diff --git a/src/apps/common/coininfo.py b/src/apps/common/coininfo.py index 5bfad8e4e3..a608193378 100644 --- a/src/apps/common/coininfo.py +++ b/src/apps/common/coininfo.py @@ -1,6 +1,6 @@ # generated from coininfo.py.mako # do not edit manually! -from trezor.crypto.base58 import groestl512d_32, sha256d_32 +from trezor.crypto.base58 import blake256_32, groestl512d_32, sha256d_32 class CoinInfo: @@ -48,6 +48,9 @@ class CoinInfo: if curve_name == "secp256k1-groestl": self.b58_hash = groestl512d_32 self.sign_hash_double = False + elif curve_name == "secp256k1-decred": + self.b58_hash = blake256_32 + self.sign_hash_double = False else: self.b58_hash = sha256d_32 self.sign_hash_double = True diff --git a/src/apps/common/coininfo.py.mako b/src/apps/common/coininfo.py.mako index ca15c932b7..75f4e3276f 100644 --- a/src/apps/common/coininfo.py.mako +++ b/src/apps/common/coininfo.py.mako @@ -1,6 +1,6 @@ # generated from coininfo.py.mako # do not edit manually! -from trezor.crypto.base58 import groestl512d_32, sha256d_32 +from trezor.crypto.base58 import blake256_32, groestl512d_32, sha256d_32 class CoinInfo: @@ -48,6 +48,9 @@ class CoinInfo: if curve_name == "secp256k1-groestl": self.b58_hash = groestl512d_32 self.sign_hash_double = False + elif curve_name == "secp256k1-decred": + self.b58_hash = blake256_32 + self.sign_hash_double = False else: self.b58_hash = sha256d_32 self.sign_hash_double = True diff --git a/src/apps/common/signverify.py b/src/apps/common/signverify.py index baa88c1de7..d5a48f9e08 100644 --- a/src/apps/common/signverify.py +++ b/src/apps/common/signverify.py @@ -1,13 +1,16 @@ from ubinascii import hexlify -from trezor.crypto.hashlib import sha256 +from trezor.crypto.hashlib import blake256, sha256 from trezor.utils import HashWriter from apps.wallet.sign_tx.signing import write_varint def message_digest(coin, message): - h = HashWriter(sha256) + if coin.decred: + h = HashWriter(blake256) + else: + h = HashWriter(sha256) write_varint(h, len(coin.signed_message_header)) h.extend(coin.signed_message_header) write_varint(h, len(message)) diff --git a/src/apps/common/writers.py b/src/apps/common/writers.py index 8d7215ec3e..868e5e4ac4 100644 --- a/src/apps/common/writers.py +++ b/src/apps/common/writers.py @@ -14,6 +14,13 @@ def write_uint8(w: bytearray, n: int) -> int: return 1 +def write_uint16_le(w: bytearray, n: int) -> int: + assert 0 <= n <= 0xFFFF + w.append(n & 0xFF) + w.append((n >> 8) & 0xFF) + return 2 + + def write_uint32_le(w: bytearray, n: int) -> int: assert 0 <= n <= 0xFFFFFFFF w.append(n & 0xFF) diff --git a/src/apps/wallet/sign_tx/addresses.py b/src/apps/wallet/sign_tx/addresses.py index 0c62a39703..bb6eb6b697 100644 --- a/src/apps/wallet/sign_tx/addresses.py +++ b/src/apps/wallet/sign_tx/addresses.py @@ -9,6 +9,7 @@ from apps.common import address_type from apps.common.coininfo import CoinInfo from apps.wallet.sign_tx.multisig import multisig_get_pubkeys, multisig_pubkey_index from apps.wallet.sign_tx.scripts import ( + blake256_ripemd160_digest, output_script_multisig, output_script_native_p2wpkh_or_p2wsh, sha256_ripemd160_digest, @@ -65,7 +66,7 @@ def get_address( return address_multisig_p2wsh(pubkeys, multisig.m, coin.bech32_prefix) # native p2wpkh - return address_p2wpkh(node.public_key(), coin.bech32_prefix) + return address_p2wpkh(node.public_key(), coin) elif ( script_type == InputScriptType.SPENDP2SHWITNESS @@ -92,7 +93,10 @@ def address_multisig_p2sh(pubkeys: bytes, m: int, coin: CoinInfo): FailureType.ProcessError, "Multisig not enabled on this coin" ) redeem_script = output_script_multisig(pubkeys, m) - redeem_script_hash = sha256_ripemd160_digest(redeem_script) + if coin.decred: + redeem_script_hash = blake256_ripemd160_digest(redeem_script) + else: + redeem_script_hash = sha256_ripemd160_digest(redeem_script) return address_p2sh(redeem_script_hash, coin) @@ -127,7 +131,7 @@ def address_p2sh(redeem_script_hash: bytes, coin: CoinInfo) -> str: def address_p2wpkh_in_p2sh(pubkey: bytes, coin: CoinInfo) -> str: - pubkey_hash = ecdsa_hash_pubkey(pubkey) + pubkey_hash = ecdsa_hash_pubkey(pubkey, coin) redeem_script = output_script_native_p2wpkh_or_p2wsh(pubkey_hash) redeem_script_hash = sha256_ripemd160_digest(redeem_script) return address_p2sh(redeem_script_hash, coin) @@ -139,9 +143,9 @@ def address_p2wsh_in_p2sh(witness_script_hash: bytes, coin: CoinInfo) -> str: return address_p2sh(redeem_script_hash, coin) -def address_p2wpkh(pubkey: bytes, hrp: str) -> str: - pubkeyhash = ecdsa_hash_pubkey(pubkey) - address = bech32.encode(hrp, _BECH32_WITVER, pubkeyhash) +def address_p2wpkh(pubkey: bytes, coin: CoinInfo) -> str: + pubkeyhash = ecdsa_hash_pubkey(pubkey, coin) + address = bech32.encode(coin.bech32_prefix, _BECH32_WITVER, pubkeyhash) if address is None: raise AddressError(FailureType.ProcessError, "Invalid address") return address @@ -173,13 +177,17 @@ def address_to_cashaddr(address: str, coin: CoinInfo) -> str: return cashaddr.encode(coin.cashaddr_prefix, version, data) -def ecdsa_hash_pubkey(pubkey: bytes) -> bytes: +def ecdsa_hash_pubkey(pubkey: bytes, coin: CoinInfo) -> 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 + + if coin.decred: + return blake256_ripemd160_digest(pubkey) + h = sha256(pubkey).digest() h = ripemd160(h).digest() return h diff --git a/src/apps/wallet/sign_tx/decred_prefix_hasher.py b/src/apps/wallet/sign_tx/decred_prefix_hasher.py new file mode 100644 index 0000000000..c818a54212 --- /dev/null +++ b/src/apps/wallet/sign_tx/decred_prefix_hasher.py @@ -0,0 +1,65 @@ +from micropython import const + +from trezor.crypto.hashlib import blake256 +from trezor.messages.SignTx import SignTx +from trezor.messages.TxInputType import TxInputType +from trezor.messages.TxOutputBinType import TxOutputBinType +from trezor.utils import HashWriter + +from apps.wallet.sign_tx.writers import ( + write_tx_input_decred, + write_tx_output, + write_uint32, + write_varint, +) + +DECRED_SERIALIZE_FULL = const(0 << 16) +DECRED_SERIALIZE_NO_WITNESS = const(1 << 16) +DECRED_SERIALIZE_WITNESS_SIGNING = const(3 << 16) + +DECRED_SIGHASHALL = const(1) + + +class DecredPrefixHasher: + """ + While Decred does not have the exact same implementation as bip143/zip143, + the semantics for using the prefix hash of transactions are close enough + that a pseudo-bip143 class can be used to store the prefix hash during the + check_fee stage of transaction signature to then reuse it at the sign_tx + stage without having to request the inputs again. + """ + + def __init__(self, tx: SignTx): + self.h_prefix = HashWriter(blake256) + self.last_output_bytes = None + write_uint32(self.h_prefix, tx.version | DECRED_SERIALIZE_NO_WITNESS) + write_varint(self.h_prefix, tx.inputs_count) + + def add_prevouts(self, txi: TxInputType): + write_tx_input_decred(self.h_prefix, txi) + + def add_sequence(self, txi: TxInputType): + pass + + def add_output_count(self, tx: SignTx): + write_varint(self.h_prefix, tx.outputs_count) + + def add_output(self, txo_bin: TxOutputBinType): + write_tx_output(self.h_prefix, txo_bin) + + def set_last_output_bytes(self, w_txo_bin: bytearray): + """ + This is required because the last serialized output obtained in + `check_fee` will only be sent to the client in `sign_tx` + """ + self.last_output_bytes = w_txo_bin + + def get_last_output_bytes(self): + return self.last_output_bytes + + def add_locktime_expiry(self, tx: SignTx): + write_uint32(self.h_prefix, tx.lock_time) + write_uint32(self.h_prefix, tx.expiry) + + def prefix_hash(self) -> bytes: + return self.h_prefix.get_digest() diff --git a/src/apps/wallet/sign_tx/scripts.py b/src/apps/wallet/sign_tx/scripts.py index 22f347b64a..0384e77ec4 100644 --- a/src/apps/wallet/sign_tx/scripts.py +++ b/src/apps/wallet/sign_tx/scripts.py @@ -1,6 +1,7 @@ -from trezor.crypto.hashlib import ripemd160, sha256 +from trezor.crypto.hashlib import blake256, ripemd160, sha256 from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType +from apps.common.coininfo import CoinInfo from apps.common.writers import empty_bytearray from apps.wallet.sign_tx.multisig import multisig_get_pubkeys from apps.wallet.sign_tx.writers import ( @@ -192,6 +193,7 @@ def input_script_multisig( signature: bytes, signature_index: int, sighash: int, + coin: CoinInfo, ): signatures = multisig.signatures # other signatures if len(signatures[signature_index]) > 0: @@ -199,10 +201,12 @@ def input_script_multisig( signatures[signature_index] = signature # our signature w = bytearray() - # Starts with OP_FALSE because of an old OP_CHECKMULTISIG bug, which - # consumes one additional item on the stack: - # https://bitcoin.org/en/developer-guide#standard-transactions - w.append(0x00) + + if not coin.decred: + # Starts with OP_FALSE because of an old OP_CHECKMULTISIG bug, which + # consumes one additional item on the stack: + # https://bitcoin.org/en/developer-guide#standard-transactions + w.append(0x00) for s in signatures: if len(s): @@ -267,3 +271,9 @@ def sha256_ripemd160_digest(b: bytes) -> bytes: h = sha256(b).digest() h = ripemd160(h).digest() return h + + +def blake256_ripemd160_digest(b: bytes) -> bytes: + h = blake256(b).digest() + h = ripemd160(h).digest() + return h diff --git a/src/apps/wallet/sign_tx/signing.py b/src/apps/wallet/sign_tx/signing.py index dda4bc58ef..5d56a6a7ec 100644 --- a/src/apps/wallet/sign_tx/signing.py +++ b/src/apps/wallet/sign_tx/signing.py @@ -2,7 +2,7 @@ from micropython import const from trezor.crypto import base58, bip32, cashaddr, der from trezor.crypto.curve import secp256k1 -from trezor.crypto.hashlib import sha256 +from trezor.crypto.hashlib import blake256, sha256 from trezor.messages import OutputScriptType from trezor.messages.TxRequestDetailsType import TxRequestDetailsType from trezor.messages.TxRequestSerializedType import TxRequestSerializedType @@ -13,6 +13,12 @@ from apps.common.coininfo import CoinInfo from apps.common.writers import empty_bytearray from apps.wallet.sign_tx import progress from apps.wallet.sign_tx.addresses import * +from apps.wallet.sign_tx.decred_prefix_hasher import ( + DECRED_SERIALIZE_NO_WITNESS, + DECRED_SERIALIZE_WITNESS_SIGNING, + DECRED_SIGHASHALL, + DecredPrefixHasher, +) from apps.wallet.sign_tx.helpers import * from apps.wallet.sign_tx.multisig import * from apps.wallet.sign_tx.overwinter_zip143 import ( # noqa:F401 @@ -59,7 +65,10 @@ async def check_tx_fee(tx: SignTx, root: bip32.HDNode): # tx, as the SignTx info is streamed only once h_first = HashWriter(sha256) # not a real tx hash - if tx.overwintered: + if coin.decred: + hash143 = DecredPrefixHasher(tx) # pseudo bip143 prefix hashing + tx_ser = TxRequestSerializedType() + elif tx.overwintered: hash143 = Zip143() # zip143 transaction hashing else: hash143 = Bip143() # bip143 transaction hashing @@ -130,6 +139,17 @@ async def check_tx_fee(tx: SignTx, root: bip32.HDNode): else: raise SigningError(FailureType.DataError, "Wrong input script type") + if coin.decred: + w_txi = empty_bytearray(8 if i == 0 else 0 + 9 + len(txi.prev_hash)) + if i == 0: # serializing first input => prepend headers + write_bytes(w_txi, get_tx_header(coin, tx)) + write_tx_input_decred(w_txi, txi) + tx_ser.serialized_tx = w_txi + tx_req.serialized = tx_ser + + if coin.decred: + hash143.add_output_count(tx) + for o in range(tx.outputs_count): # STAGE_REQUEST_3_OUTPUT txo = await request_tx_output(tx_req, o) @@ -143,6 +163,22 @@ async def check_tx_fee(tx: SignTx, root: bip32.HDNode): elif not await confirm_output(txo, coin): raise SigningError(FailureType.ActionCancelled, "Output cancelled") + if coin.decred: + if txo.decred_script_version is not None and txo.decred_script_version != 0: + raise SigningError( + FailureType.ActionCancelled, + "Cannot send to output with script version != 0", + ) + txo_bin.decred_script_version = txo.decred_script_version + + w_txo_bin = empty_bytearray(4 + 8 + 2 + 4 + len(txo_bin.script_pubkey)) + if o == 0: # serializing first output => prepend outputs count + write_varint(w_txo_bin, tx.outputs_count) + write_tx_output(w_txo_bin, txo_bin) + tx_ser.serialized_tx = w_txo_bin + tx_req.serialized = tx_ser + hash143.set_last_output_bytes(w_txo_bin) + write_tx_output(h_first, txo_bin) hash143.add_output(txo_bin) total_out += txo_bin.amount @@ -159,6 +195,9 @@ async def check_tx_fee(tx: SignTx, root: bip32.HDNode): if not await confirm_total(total_in - change_out, fee, coin): raise SigningError(FailureType.ActionCancelled, "Total cancelled") + if coin.decred: + hash143.add_locktime_expiry(tx) + return h_first, hash143, segwit, total_in, wallet_path @@ -183,6 +222,9 @@ async def sign_tx(tx: SignTx, root: bip32.HDNode): tx_req.details = TxRequestDetailsType() tx_req.serialized = None + if coin.decred: + prefix_hash = hash143.prefix_hash() + for i_sign in range(tx.inputs_count): progress.advance() txi_sign = None @@ -234,7 +276,11 @@ async def sign_tx(tx: SignTx, root: bip32.HDNode): key_sign = node_derive(root, txi_sign.address_n) key_sign_pub = key_sign.public_key() hash143_hash = hash143.preimage_hash( - coin, tx, txi_sign, ecdsa_hash_pubkey(key_sign_pub), get_hash_type(coin) + coin, + tx, + txi_sign, + ecdsa_hash_pubkey(key_sign_pub, coin), + get_hash_type(coin), ) # if multisig, check if singing with a key that is included in multisig @@ -259,6 +305,70 @@ async def sign_tx(tx: SignTx, root: bip32.HDNode): tx_req.serialized = tx_ser + elif coin.decred: + txi_sign = await request_tx_input(tx_req, i_sign) + + input_check_wallet_path(txi_sign, wallet_path) + + key_sign = node_derive(root, txi_sign.address_n) + key_sign_pub = key_sign.public_key() + + if txi_sign.script_type == InputScriptType.SPENDMULTISIG: + prev_pkscript = output_script_multisig( + multisig_get_pubkeys(txi_sign.multisig), txi_sign.multisig.m + ) + elif txi_sign.script_type == InputScriptType.SPENDADDRESS: + prev_pkscript = output_script_p2pkh( + ecdsa_hash_pubkey(key_sign_pub, coin) + ) + else: + raise ValueError("Unknown input script type") + + h_witness = HashWriter(blake256) + write_uint32(h_witness, tx.version | DECRED_SERIALIZE_WITNESS_SIGNING) + write_varint(h_witness, tx.inputs_count) + + for ii in range(tx.inputs_count): + if ii == i_sign: + write_varint(h_witness, len(prev_pkscript)) + write_bytes(h_witness, prev_pkscript) + else: + write_varint(h_witness, 0) + + witness_hash = get_tx_hash( + h_witness, double=coin.sign_hash_double, reverse=False + ) + + h_sign = HashWriter(blake256) + write_uint32(h_sign, DECRED_SIGHASHALL) + write_bytes(h_sign, prefix_hash) + write_bytes(h_sign, witness_hash) + + sig_hash = get_tx_hash(h_sign, double=coin.sign_hash_double) + signature = ecdsa_sign(key_sign, sig_hash) + tx_ser.signature_index = i_sign + tx_ser.signature = signature + + # serialize input with correct signature + txi_sign.script_sig = input_derive_script( + coin, txi_sign, key_sign_pub, signature + ) + w_txi_sign = empty_bytearray( + 8 + 4 + len(hash143.get_last_output_bytes()) + if i_sign == 0 + else 0 + 16 + 4 + len(txi_sign.script_sig) + ) + + if i_sign == 0: + write_bytes(w_txi_sign, hash143.get_last_output_bytes()) + write_uint32(w_txi_sign, tx.lock_time) + write_uint32(w_txi_sign, tx.expiry) + write_varint(w_txi_sign, tx.inputs_count) + + write_tx_input_decred_witness(w_txi_sign, txi_sign) + tx_ser.serialized_tx = w_txi_sign + tx_req.serialized = tx_ser + else: # hash of what we are signing with this input h_sign = HashWriter(sha256) @@ -292,7 +402,7 @@ async def sign_tx(tx: SignTx, root: bip32.HDNode): ) elif txi_sign.script_type == InputScriptType.SPENDADDRESS: txi_sign.script_sig = output_script_p2pkh( - ecdsa_hash_pubkey(key_sign_pub) + ecdsa_hash_pubkey(key_sign_pub, coin) ) if coin.bip115: txi_sign.script_sig += script_replay_protection_bip115( @@ -355,6 +465,9 @@ async def sign_tx(tx: SignTx, root: bip32.HDNode): tx_req.serialized = tx_ser + if coin.decred: + return await request_tx_finish(tx_req) + for o in range(tx.outputs_count): progress.advance() # STAGE_REQUEST_5_OUTPUT @@ -396,7 +509,11 @@ async def sign_tx(tx: SignTx, root: bip32.HDNode): key_sign = node_derive(root, txi.address_n) key_sign_pub = key_sign.public_key() hash143_hash = hash143.preimage_hash( - coin, tx, txi, ecdsa_hash_pubkey(key_sign_pub), get_hash_type(coin) + coin, + tx, + txi, + ecdsa_hash_pubkey(key_sign_pub, coin), + get_hash_type(coin), ) signature = ecdsa_sign(key_sign, hash143_hash) @@ -420,6 +537,7 @@ async def sign_tx(tx: SignTx, root: bip32.HDNode): tx_req.serialized = tx_ser write_uint32(tx_ser.serialized_tx, tx.lock_time) + if tx.overwintered: write_uint32(tx_ser.serialized_tx, tx.expiry) # expiryHeight write_varint(tx_ser.serialized_tx, 0) # nJoinSplit @@ -435,11 +553,16 @@ async def get_prevtx_output_value( # STAGE_REQUEST_2_PREV_META tx = await request_tx_meta(tx_req, prev_hash) - txh = HashWriter(sha256) + if coin.decred: + txh = HashWriter(blake256) + else: + txh = HashWriter(sha256) if tx.overwintered: write_uint32(txh, tx.version | OVERWINTERED) # nVersion | fOverwintered write_uint32(txh, coin.version_group_id) # nVersionGroupId + elif coin.decred: + write_uint32(txh, tx.version | DECRED_SERIALIZE_NO_WITNESS) else: write_uint32(txh, tx.version) # nVersion @@ -448,7 +571,10 @@ async def get_prevtx_output_value( for i in range(tx.inputs_cnt): # STAGE_REQUEST_2_PREV_INPUT txi = await request_tx_input(tx_req, i, prev_hash) - write_tx_input(txh, txi) + if coin.decred: + write_tx_input_decred(txh, txi) + else: + write_tx_input(txh, txi) write_varint(txh, tx.outputs_cnt) @@ -458,10 +584,19 @@ async def get_prevtx_output_value( write_tx_output(txh, txo_bin) if o == prev_index: total_out += txo_bin.amount + if ( + coin.decred + and txo_bin.decred_script_version is not None + and txo_bin.decred_script_version != 0 + ): + raise SigningError( + FailureType.ProcessError, + "Cannot use utxo that has script_version != 0", + ) write_uint32(txh, tx.lock_time) - if tx.overwintered: + if tx.overwintered or coin.decred: write_uint32(txh, tx.expiry) ofs = 0 @@ -626,7 +761,7 @@ def input_derive_script( return input_script_p2wsh_in_p2sh(witness_script_hash) # p2wpkh in p2sh - return input_script_p2wpkh_in_p2sh(ecdsa_hash_pubkey(pubkey)) + return input_script_p2wpkh_in_p2sh(ecdsa_hash_pubkey(pubkey, coin)) elif i.script_type == InputScriptType.SPENDWITNESS: # native p2wpkh or p2wsh @@ -636,7 +771,7 @@ def input_derive_script( # p2sh multisig signature_index = multisig_pubkey_index(i.multisig, pubkey) return input_script_multisig( - i.multisig, signature, signature_index, get_hash_type(coin) + i.multisig, signature, signature_index, get_hash_type(coin), coin ) else: diff --git a/src/apps/wallet/sign_tx/writers.py b/src/apps/wallet/sign_tx/writers.py index 7c56a0b045..99541b84c2 100644 --- a/src/apps/wallet/sign_tx/writers.py +++ b/src/apps/wallet/sign_tx/writers.py @@ -5,10 +5,13 @@ from trezor.messages.TxOutputBinType import TxOutputBinType from apps.common.writers import ( write_bytes, write_bytes_reversed, + write_uint8, + write_uint16_le, write_uint32_le, write_uint64_le, ) +write_uint16 = write_uint16_le write_uint32 = write_uint32_le write_uint64 = write_uint64_le @@ -32,8 +35,25 @@ def write_tx_input_check(w, i: TxInputType): write_uint32(w, i.amount or 0) +def write_tx_input_decred(w, i: TxInputType): + write_bytes_reversed(w, i.prev_hash) + write_uint32(w, i.prev_index or 0) + write_uint8(w, i.decred_tree or 0) + write_uint32(w, i.sequence) + + +def write_tx_input_decred_witness(w, i: TxInputType): + write_uint64(w, i.amount or 0) + write_uint32(w, 0) # block height fraud proof + write_uint32(w, 0xFFFFFFFF) # block index fraud proof + write_varint(w, len(i.script_sig)) + write_bytes(w, i.script_sig) + + def write_tx_output(w, o: TxOutputBinType): write_uint64(w, o.amount) + if o.decred_script_version is not None: + write_uint16(w, o.decred_script_version) write_varint(w, len(o.script_pubkey)) write_bytes(w, o.script_pubkey) diff --git a/src/apps/wallet/verify_message.py b/src/apps/wallet/verify_message.py index ee0d11a5e6..b06fb33088 100644 --- a/src/apps/wallet/verify_message.py +++ b/src/apps/wallet/verify_message.py @@ -51,7 +51,7 @@ async def verify_message(ctx, msg): elif script_type == SPENDP2SHWITNESS: addr = address_p2wpkh_in_p2sh(pubkey, coin) elif script_type == SPENDWITNESS: - addr = address_p2wpkh(pubkey, coin.bech32_prefix) + addr = address_p2wpkh(pubkey, coin) else: raise wire.ProcessError("Invalid signature") diff --git a/src/trezor/crypto/base58.py b/src/trezor/crypto/base58.py index 10bc0147f3..a9b560aa53 100644 --- a/src/trezor/crypto/base58.py +++ b/src/trezor/crypto/base58.py @@ -71,6 +71,12 @@ def groestl512d_32(data: bytes) -> bytes: return groestl512(groestl512(data).digest()).digest()[:4] +def blake256_32(data: bytes) -> bytes: + from .hashlib import blake256 + + return blake256(blake256(data).digest()).digest()[:4] + + def encode_check(data: bytes, digestfunc=sha256d_32) -> str: """ Convert bytes to base58 encoded string, append checksum. diff --git a/tests/test_apps.wallet.address.py b/tests/test_apps.wallet.address.py index 978ee2aa69..aace29ba4d 100644 --- a/tests/test_apps.wallet.address.py +++ b/tests/test_apps.wallet.address.py @@ -41,7 +41,7 @@ class TestAddress(unittest.TestCase): coin = coins.by_name('Testnet') address = address_p2wpkh( unhexlify('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), - coin.bech32_prefix + coin ) self.assertEqual(address, 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx') diff --git a/tests/test_apps.wallet.address_grs.py b/tests/test_apps.wallet.address_grs.py index f2d70bbb44..404ddff04b 100644 --- a/tests/test_apps.wallet.address_grs.py +++ b/tests/test_apps.wallet.address_grs.py @@ -60,15 +60,15 @@ class TestAddressGRS(unittest.TestCase): root = bip32.from_seed(seed, coin.curve_name) node = node_derive(root, [84 | 0x80000000, 17 | 0x80000000, 0 | 0x80000000, 1, 0]) - address = address_p2wpkh(node.public_key(), coin.bech32_prefix) + address = address_p2wpkh(node.public_key(), coin) self.assertEqual(address, 'grs1qzfpwn55tvkxcw0xwfa0g8k2gtlzlgkcq3z000e') node = node_derive(root, [84 | 0x80000000, 17 | 0x80000000, 0 | 0x80000000, 1, 1]) - address = address_p2wpkh(node.public_key(), coin.bech32_prefix) + address = address_p2wpkh(node.public_key(), coin) self.assertEqual(address, 'grs1qxsgwl66tx7tsuwfm4kk5c5dh6tlfpr4qjqg6gg') node = node_derive(root, [84 | 0x80000000, 17 | 0x80000000, 0 | 0x80000000, 0, 0]) - address = address_p2wpkh(node.public_key(), coin.bech32_prefix) + address = address_p2wpkh(node.public_key(), coin) self.assertEqual(address, 'grs1qw4teyraux2s77nhjdwh9ar8rl9dt7zww8r6lne')