mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-17 05:03:07 +00:00
wallet/signing: extract addresses.py
This commit is contained in:
parent
65481308e6
commit
7de6a082d3
@ -20,6 +20,8 @@ async def sign_tx(ctx, msg):
|
|||||||
req = signer.send(res)
|
req = signer.send(res)
|
||||||
except signing.SigningError as e:
|
except signing.SigningError as e:
|
||||||
raise wire.FailureError(*e.args)
|
raise wire.FailureError(*e.args)
|
||||||
|
except signing.AddressError as e:
|
||||||
|
raise wire.FailureError(*e.args)
|
||||||
if req.__qualname__ == 'TxRequest':
|
if req.__qualname__ == 'TxRequest':
|
||||||
if req.request_type == TXFINISHED:
|
if req.request_type == TXFINISHED:
|
||||||
break
|
break
|
||||||
|
84
src/apps/wallet/sign_tx/addresses.py
Normal file
84
src/apps/wallet/sign_tx/addresses.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
from micropython import const
|
||||||
|
|
||||||
|
from trezor.crypto.hashlib import sha256, ripemd160
|
||||||
|
from trezor.crypto import base58, bech32
|
||||||
|
from trezor.utils import ensure
|
||||||
|
|
||||||
|
from trezor.messages.CoinType import CoinType
|
||||||
|
from trezor.messages import FailureType
|
||||||
|
from trezor.messages import InputScriptType
|
||||||
|
|
||||||
|
# supported witness version for bech32 addresses
|
||||||
|
_BECH32_WITVER = const(0x00)
|
||||||
|
|
||||||
|
|
||||||
|
class AddressError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_address(script_type: InputScriptType, coin: CoinType, node) -> bytes:
|
||||||
|
|
||||||
|
if script_type == InputScriptType.SPENDADDRESS: # p2pkh
|
||||||
|
return node.address(coin.address_type)
|
||||||
|
|
||||||
|
elif script_type == InputScriptType.SPENDWITNESS: # native p2wpkh
|
||||||
|
if not coin.segwit or not coin.bech32_prefix:
|
||||||
|
raise AddressError(FailureType.ProcessError,
|
||||||
|
'Segwit not enabled on this coin')
|
||||||
|
return address_p2wpkh(node.public_key(), coin.bech32_prefix)
|
||||||
|
|
||||||
|
elif script_type == InputScriptType.SPENDP2SHWITNESS: # p2wpkh using p2sh
|
||||||
|
if not coin.segwit or not coin.address_type_p2sh:
|
||||||
|
raise AddressError(FailureType.ProcessError,
|
||||||
|
'Segwit not enabled on this coin')
|
||||||
|
return address_p2wpkh_in_p2sh(node.public_key(), coin.address_type_p2sh)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise AddressError(FailureType.ProcessError,
|
||||||
|
'Invalid script type')
|
||||||
|
|
||||||
|
|
||||||
|
def address_p2wpkh_in_p2sh(pubkey: bytes, addrtype: int) -> str:
|
||||||
|
s = bytearray(21)
|
||||||
|
s[0] = addrtype
|
||||||
|
s[1:21] = address_p2wpkh_in_p2sh_raw(pubkey)
|
||||||
|
return base58.encode_check(bytes(s))
|
||||||
|
|
||||||
|
|
||||||
|
def address_p2wpkh_in_p2sh_raw(pubkey: bytes) -> bytes:
|
||||||
|
s = bytearray(22)
|
||||||
|
s[0] = 0x00 # OP_0
|
||||||
|
s[1] = 0x14 # pushing 20 bytes
|
||||||
|
s[2:22] = ecdsa_hash_pubkey(pubkey)
|
||||||
|
h = sha256(s).digest()
|
||||||
|
h = ripemd160(h).digest()
|
||||||
|
return h
|
||||||
|
|
||||||
|
|
||||||
|
def address_p2wpkh(pubkey: bytes, hrp: str) -> str:
|
||||||
|
pubkeyhash = ecdsa_hash_pubkey(pubkey)
|
||||||
|
address = bech32.encode(hrp, _BECH32_WITVER, pubkeyhash)
|
||||||
|
if address is None:
|
||||||
|
raise AddressError(FailureType.ProcessError,
|
||||||
|
'Invalid address')
|
||||||
|
return address
|
||||||
|
|
||||||
|
|
||||||
|
def decode_bech32_address(prefix: str, address: str) -> bytes:
|
||||||
|
witver, raw = bech32.decode(prefix, address)
|
||||||
|
if witver != _BECH32_WITVER:
|
||||||
|
raise AddressError(FailureType.ProcessError,
|
||||||
|
'Invalid address witness program')
|
||||||
|
return bytes(raw)
|
||||||
|
|
||||||
|
|
||||||
|
def ecdsa_hash_pubkey(pubkey: bytes) -> bytes:
|
||||||
|
if pubkey[0] == 0x04:
|
||||||
|
ensure(len(pubkey) == 65) # uncompressed format
|
||||||
|
elif pubkey[0] == 0x00:
|
||||||
|
ensure(len(pubkey) == 1) # point at infinity
|
||||||
|
else:
|
||||||
|
ensure(len(pubkey) == 33) # compresssed format
|
||||||
|
h = sha256(pubkey).digest()
|
||||||
|
h = ripemd160(h).digest()
|
||||||
|
return h
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
from trezor.messages.CoinType import CoinType
|
from trezor.messages.CoinType import CoinType
|
||||||
from trezor.messages.TxOutputType import TxOutputType
|
from trezor.messages.TxOutputType import TxOutputType
|
||||||
from trezor.messages.TxOutputBinType import TxOutputBinType
|
from trezor.messages.TxOutputBinType import TxOutputBinType
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
from micropython import const
|
from micropython import const
|
||||||
|
|
||||||
from trezor.crypto.hashlib import sha256, ripemd160
|
from trezor.crypto.hashlib import sha256
|
||||||
from trezor.crypto.curve import secp256k1
|
from trezor.crypto.curve import secp256k1
|
||||||
from trezor.crypto import base58, der, bech32
|
from trezor.crypto import base58, der
|
||||||
from trezor.utils import ensure
|
|
||||||
|
|
||||||
from trezor.messages.TxRequestSerializedType import TxRequestSerializedType
|
from trezor.messages.TxRequestSerializedType import TxRequestSerializedType
|
||||||
from trezor.messages.TxRequestDetailsType import TxRequestDetailsType
|
from trezor.messages.TxRequestDetailsType import TxRequestDetailsType
|
||||||
@ -11,8 +10,9 @@ from trezor.messages import OutputScriptType
|
|||||||
|
|
||||||
from apps.common import address_type
|
from apps.common import address_type
|
||||||
from apps.common import coins
|
from apps.common import coins
|
||||||
from apps.wallet.sign_tx.segwit_bip143 import *
|
from apps.wallet.sign_tx.addresses import *
|
||||||
from apps.wallet.sign_tx.helpers import *
|
from apps.wallet.sign_tx.helpers import *
|
||||||
|
from apps.wallet.sign_tx.segwit_bip143 import *
|
||||||
from apps.wallet.sign_tx.scripts import *
|
from apps.wallet.sign_tx.scripts import *
|
||||||
from apps.wallet.sign_tx.writers import *
|
from apps.wallet.sign_tx.writers import *
|
||||||
|
|
||||||
@ -345,64 +345,6 @@ def get_p2wpkh_witness(signature: bytes, pubkey: bytes):
|
|||||||
return w
|
return w
|
||||||
|
|
||||||
|
|
||||||
def get_address(script_type: InputScriptType, coin: CoinType, node) -> bytes:
|
|
||||||
|
|
||||||
if script_type == InputScriptType.SPENDADDRESS: # p2pkh
|
|
||||||
return node.address(coin.address_type)
|
|
||||||
|
|
||||||
elif script_type == InputScriptType.SPENDWITNESS: # native p2wpkh
|
|
||||||
if not coin.segwit or not coin.bech32_prefix:
|
|
||||||
raise SigningError(FailureType.ProcessError,
|
|
||||||
'Segwit not enabled on this coin')
|
|
||||||
return address_p2wpkh(node.public_key(), coin.bech32_prefix)
|
|
||||||
|
|
||||||
elif script_type == InputScriptType.SPENDP2SHWITNESS: # p2wpkh using p2sh
|
|
||||||
if not coin.segwit or not coin.address_type_p2sh:
|
|
||||||
raise SigningError(FailureType.ProcessError,
|
|
||||||
'Segwit not enabled on this coin')
|
|
||||||
return address_p2wpkh_in_p2sh(node.public_key(), coin.address_type_p2sh)
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise SigningError(FailureType.ProcessError, 'Invalid script type')
|
|
||||||
|
|
||||||
|
|
||||||
def address_p2wpkh_in_p2sh(pubkey: bytes, addrtype: int) -> str:
|
|
||||||
s = bytearray(21)
|
|
||||||
s[0] = addrtype
|
|
||||||
s[1:21] = address_p2wpkh_in_p2sh_raw(pubkey)
|
|
||||||
return base58.encode_check(bytes(s))
|
|
||||||
|
|
||||||
|
|
||||||
def address_p2wpkh_in_p2sh_raw(pubkey: bytes) -> bytes:
|
|
||||||
s = bytearray(22)
|
|
||||||
s[0] = 0x00 # OP_0
|
|
||||||
s[1] = 0x14 # pushing 20 bytes
|
|
||||||
s[2:22] = ecdsa_hash_pubkey(pubkey)
|
|
||||||
h = sha256(s).digest()
|
|
||||||
h = ripemd160(h).digest()
|
|
||||||
return h
|
|
||||||
|
|
||||||
|
|
||||||
_BECH32_WITVER = const(0x00)
|
|
||||||
|
|
||||||
|
|
||||||
def address_p2wpkh(pubkey: bytes, hrp: str) -> str:
|
|
||||||
pubkeyhash = ecdsa_hash_pubkey(pubkey)
|
|
||||||
address = bech32.encode(hrp, _BECH32_WITVER, pubkeyhash)
|
|
||||||
if address is None:
|
|
||||||
raise SigningError(FailureType.ProcessError,
|
|
||||||
'Invalid address')
|
|
||||||
return address
|
|
||||||
|
|
||||||
|
|
||||||
def decode_bech32_address(prefix: str, address: str) -> bytes:
|
|
||||||
witver, raw = bech32.decode(prefix, address)
|
|
||||||
if witver != _BECH32_WITVER:
|
|
||||||
raise SigningError(FailureType.DataError,
|
|
||||||
'Invalid address witness program')
|
|
||||||
return bytes(raw)
|
|
||||||
|
|
||||||
|
|
||||||
# TX Outputs
|
# TX Outputs
|
||||||
# ===
|
# ===
|
||||||
|
|
||||||
@ -505,18 +447,6 @@ def node_derive(root, address_n: list):
|
|||||||
return node
|
return node
|
||||||
|
|
||||||
|
|
||||||
def ecdsa_hash_pubkey(pubkey: bytes) -> bytes:
|
|
||||||
if pubkey[0] == 0x04:
|
|
||||||
ensure(len(pubkey) == 65) # uncompressed format
|
|
||||||
elif pubkey[0] == 0x00:
|
|
||||||
ensure(len(pubkey) == 1) # point at infinity
|
|
||||||
else:
|
|
||||||
ensure(len(pubkey) == 33) # compresssed format
|
|
||||||
h = sha256(pubkey).digest()
|
|
||||||
h = ripemd160(h).digest()
|
|
||||||
return h
|
|
||||||
|
|
||||||
|
|
||||||
def ecdsa_sign(node, digest: bytes) -> bytes:
|
def ecdsa_sign(node, digest: bytes) -> bytes:
|
||||||
sig = secp256k1.sign(node.private_key(), digest)
|
sig = secp256k1.sign(node.private_key(), digest)
|
||||||
sigder = der.encode_seq((sig[1:33], sig[33:65]))
|
sigder = der.encode_seq((sig[1:33], sig[33:65]))
|
||||||
|
Loading…
Reference in New Issue
Block a user