1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-26 17:38:39 +00:00

wallet/signing: extract addresses.py

This commit is contained in:
Jan Pochyla 2017-11-23 17:30:43 +01:00
parent 65481308e6
commit 7de6a082d3
4 changed files with 90 additions and 75 deletions

View File

@ -20,6 +20,8 @@ async def sign_tx(ctx, msg):
req = signer.send(res)
except signing.SigningError as e:
raise wire.FailureError(*e.args)
except signing.AddressError as e:
raise wire.FailureError(*e.args)
if req.__qualname__ == 'TxRequest':
if req.request_type == TXFINISHED:
break

View 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

View File

@ -1,4 +1,3 @@
from trezor.messages.CoinType import CoinType
from trezor.messages.TxOutputType import TxOutputType
from trezor.messages.TxOutputBinType import TxOutputBinType

View File

@ -1,9 +1,8 @@
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 import base58, der, bech32
from trezor.utils import ensure
from trezor.crypto import base58, der
from trezor.messages.TxRequestSerializedType import TxRequestSerializedType
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 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.segwit_bip143 import *
from apps.wallet.sign_tx.scripts import *
from apps.wallet.sign_tx.writers import *
@ -345,64 +345,6 @@ def get_p2wpkh_witness(signature: bytes, pubkey: bytes):
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
# ===
@ -505,18 +447,6 @@ def node_derive(root, address_n: list):
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:
sig = secp256k1.sign(node.private_key(), digest)
sigder = der.encode_seq((sig[1:33], sig[33:65]))