From 0cd3e411f42d6db8a11ad88c6a480e16a27e4595 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Thu, 24 May 2018 16:38:56 +0200 Subject: [PATCH] src/apps/wallet/sign_tx: implement cashaddr --- src/apps/wallet/sign_tx/addresses.py | 24 +++++++++++++++++++++--- src/apps/wallet/sign_tx/signing.py | 15 +++++++++++++-- src/trezor/crypto/cashaddr.py | 2 ++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/apps/wallet/sign_tx/addresses.py b/src/apps/wallet/sign_tx/addresses.py index acfd17fd0..724ac487b 100644 --- a/src/apps/wallet/sign_tx/addresses.py +++ b/src/apps/wallet/sign_tx/addresses.py @@ -1,7 +1,7 @@ from micropython import const from trezor.crypto.hashlib import sha256, ripemd160 -from trezor.crypto import base58, bech32 +from trezor.crypto import base58, bech32, cashaddr from trezor.utils import ensure from trezor.messages import FailureType @@ -34,13 +34,19 @@ def get_address(script_type: InputScriptType, coin: CoinInfo, node, multisig=Non 'Multisig not enabled on this coin') pubkeys = multisig_get_pubkeys(multisig) - return address_multisig_p2sh(pubkeys, multisig.m, coin.address_type_p2sh) + address = address_multisig_p2sh(pubkeys, multisig.m, coin.address_type_p2sh) + if coin.cashaddr_prefix is not None: + address = address_to_cashaddr(address, coin) + return address if script_type == InputScriptType.SPENDMULTISIG: raise AddressError(FailureType.ProcessError, 'Multisig details required') # p2pkh - return node.address(coin.address_type) + address = node.address(coin.address_type) + if coin.cashaddr_prefix is not None: + address = address_to_cashaddr(address, coin) + return address elif script_type == InputScriptType.SPENDWITNESS: # native p2wpkh or native p2wsh if not coin.segwit or not coin.bech32_prefix: @@ -146,6 +152,18 @@ def decode_bech32_address(prefix: str, address: str) -> bytes: return bytes(raw) +def address_to_cashaddr(address: str, coin: CoinInfo) -> str: + raw = base58.decode_check(address) + version, data = raw[0], raw[1:] + if version == coin.address_type: + version = cashaddr.ADDRESS_TYPE_P2KH + elif version == coin.address_type_p2sh: + version = cashaddr.ADDRESS_TYPE_P2SH + else: + raise ValueError('Unknown cashaddr address type') + return cashaddr.encode(coin.cashaddr_prefix, version, data) + + def ecdsa_hash_pubkey(pubkey: bytes) -> bytes: if pubkey[0] == 0x04: ensure(len(pubkey) == 65) # uncompressed format diff --git a/src/apps/wallet/sign_tx/signing.py b/src/apps/wallet/sign_tx/signing.py index bf41e65a8..f129331de 100644 --- a/src/apps/wallet/sign_tx/signing.py +++ b/src/apps/wallet/sign_tx/signing.py @@ -1,6 +1,6 @@ from micropython import const -from trezor.crypto import base58, bip32, der +from trezor.crypto import base58, bip32, der, cashaddr from trezor.crypto.curve import secp256k1 from trezor.crypto.hashlib import sha256 from trezor.utils import HashWriter @@ -465,7 +465,18 @@ def output_derive_script(o: TxOutputType, coin: CoinInfo, root: bip32.HDNode) -> witprog = decode_bech32_address(coin.bech32_prefix, o.address) return output_script_native_p2wpkh_or_p2wsh(witprog) - raw_address = base58.decode_check(o.address) + if coin.cashaddr_prefix is not None and o.address.startswith(coin.cashaddr_prefix + ':'): + prefix, addr = o.address.split(':') + version, data = cashaddr.decode(prefix, addr) + if version == cashaddr.ADDRESS_TYPE_P2KH: + version = coin.address_type + elif version == cashaddr.ADDRESS_TYPE_P2SH: + version = coin.address_type_p2sh + else: + raise ValueError('Unknown cashaddr address type') + raw_address = bytes([version]) + data + else: + raw_address = base58.decode_check(o.address) if address_type.check(coin.address_type, raw_address): # p2pkh diff --git a/src/trezor/crypto/cashaddr.py b/src/trezor/crypto/cashaddr.py index b7a7c4879..ffaede67b 100644 --- a/src/trezor/crypto/cashaddr.py +++ b/src/trezor/crypto/cashaddr.py @@ -21,6 +21,8 @@ # THE SOFTWARE. CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l' +ADDRESS_TYPE_P2KH = 0 +ADDRESS_TYPE_P2SH = 8 def cashaddr_polymod(values):