From dd7ed61939277b8e17c7b4fcc4b2d5306ff35b3e Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Sat, 16 Oct 2021 10:07:19 +0200 Subject: [PATCH] feat(core): Implement GetAddress for taproot. --- core/.changelog.d/1656.added.4 | 1 + core/src/apps/bitcoin/addresses.py | 16 ++++++++++++++++ core/src/apps/bitcoin/get_address.py | 5 ++++- 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 core/.changelog.d/1656.added.4 diff --git a/core/.changelog.d/1656.added.4 b/core/.changelog.d/1656.added.4 new file mode 100644 index 0000000000..b54695a7d9 --- /dev/null +++ b/core/.changelog.d/1656.added.4 @@ -0,0 +1 @@ +Support GetAddress for Taproot addresses. diff --git a/core/src/apps/bitcoin/addresses.py b/core/src/apps/bitcoin/addresses.py index 9c904fc25e..4b25a10cc2 100644 --- a/core/src/apps/bitcoin/addresses.py +++ b/core/src/apps/bitcoin/addresses.py @@ -1,5 +1,6 @@ from trezor import wire from trezor.crypto import base58, cashaddr +from trezor.crypto.curve import bip340 from trezor.crypto.hashlib import sha256 from trezor.enums import InputScriptType from trezor.messages import MultisigRedeemScriptType @@ -56,6 +57,15 @@ def get_address( # native p2wpkh return address_p2wpkh(node.public_key(), coin) + elif script_type == InputScriptType.SPENDTAPROOT: # taproot + if not coin.taproot or not coin.bech32_prefix: + raise wire.ProcessError("Taproot not enabled on this coin") + + if multisig is not None: + raise wire.ProcessError("Multisig not supported for taproot") + + return address_p2tr(node.public_key(), coin) + elif ( script_type == InputScriptType.SPENDP2SHWITNESS ): # p2wpkh or p2wsh nested in p2sh @@ -130,6 +140,12 @@ def address_p2wsh(witness_script_hash: bytes, hrp: str) -> str: return encode_bech32_address(hrp, 0, witness_script_hash) +def address_p2tr(pubkey: bytes, coin: CoinInfo) -> str: + assert coin.bech32_prefix is not None + output_pubkey = bip340.tweak_public_key(pubkey[1:]) + return encode_bech32_address(coin.bech32_prefix, 1, output_pubkey) + + def address_to_cashaddr(address: str, coin: CoinInfo) -> str: assert coin.cashaddr_prefix is not None raw = base58.decode_check(address, coin.b58_hash) diff --git a/core/src/apps/bitcoin/get_address.py b/core/src/apps/bitcoin/get_address.py index 29fd56d3da..26723e5f12 100644 --- a/core/src/apps/bitcoin/get_address.py +++ b/core/src/apps/bitcoin/get_address.py @@ -52,7 +52,10 @@ async def get_address( address = addresses.get_address(msg.script_type, coin, node, msg.multisig) address_short = addresses.address_short(coin, address) - if coin.segwit and msg.script_type == InputScriptType.SPENDWITNESS: + if coin.segwit and msg.script_type in ( + InputScriptType.SPENDWITNESS, + InputScriptType.SPENDTAPROOT, + ): address_qr = address.upper() # bech32 address elif coin.cashaddr_prefix is not None: address_qr = address.upper() # cashaddr address