1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-23 23:08:14 +00:00

feat(legacy): Implement GetAddress for taproot.

This commit is contained in:
Andrew Kozlik 2021-11-10 13:15:20 +01:00 committed by Andrew Kozlik
parent 34e8284331
commit 6c9c727359
4 changed files with 53 additions and 31 deletions

View File

@ -0,0 +1 @@
Support GetAddress for Taproot addresses.

View File

@ -233,7 +233,8 @@ void fsm_msgGetAddress(const GetAddress *msg) {
}
bool is_cashaddr = coin->cashaddr_prefix != NULL;
bool is_bech32 = msg->script_type == InputScriptType_SPENDWITNESS;
bool is_bech32 = msg->script_type == InputScriptType_SPENDWITNESS ||
msg->script_type == InputScriptType_SPENDTAPROOT;
if (!fsm_layoutAddress(address, desc, is_cashaddr || is_bech32,
is_cashaddr ? strlen(coin->cashaddr_prefix) + 1 : 0,
msg->address_n, msg->address_n_count, false,

View File

@ -33,8 +33,10 @@
#include "ripemd160.h"
#include "segwit_addr.h"
#include "util.h"
#include "zkp_bip340.h"
#define SEGWIT_VERSION_0 0
#define SEGWIT_VERSION_1 1
#define CASHADDR_P2KH (0)
#define CASHADDR_P2SH (8)
@ -143,21 +145,27 @@ bool compute_address(const CoinInfo *coin, InputScriptType script_type,
address, MAX_ADDR_SIZE)) {
return 0;
}
} else if (coin->cashaddr_prefix) {
raw[0] = CASHADDR_P2SH | CASHADDR_160;
ripemd160(digest, 32, raw + 1);
if (!cash_addr_encode(address, coin->cashaddr_prefix, raw, 21)) {
return 0;
} else if (script_type == InputScriptType_SPENDADDRESS ||
script_type == InputScriptType_SPENDMULTISIG) {
if (coin->cashaddr_prefix) {
raw[0] = CASHADDR_P2SH | CASHADDR_160;
ripemd160(digest, 32, raw + 1);
if (!cash_addr_encode(address, coin->cashaddr_prefix, raw, 21)) {
return 0;
}
} else {
// non-segwit p2sh multisig
prelen = address_prefix_bytes_len(coin->address_type_p2sh);
address_write_prefix_bytes(coin->address_type_p2sh, raw);
ripemd160(digest, 32, raw + prelen);
if (!base58_encode_check(raw, prelen + 20, coin->curve->hasher_base58,
address, MAX_ADDR_SIZE)) {
return 0;
}
}
} else {
// non-segwit p2sh multisig
prelen = address_prefix_bytes_len(coin->address_type_p2sh);
address_write_prefix_bytes(coin->address_type_p2sh, raw);
ripemd160(digest, 32, raw + prelen);
if (!base58_encode_check(raw, prelen + 20, coin->curve->hasher_base58,
address, MAX_ADDR_SIZE)) {
return 0;
}
// unsupported script type
return 0;
}
} else if (script_type == InputScriptType_SPENDWITNESS) {
// segwit p2wpkh: pubkey hash is ripemd160 of sha256
@ -169,6 +177,17 @@ bool compute_address(const CoinInfo *coin, InputScriptType script_type,
digest, 20)) {
return 0;
}
} else if (script_type == InputScriptType_SPENDTAPROOT) {
// taproot
if (!coin->has_taproot || !coin->has_segwit || !coin->bech32_prefix) {
return 0;
}
uint8_t tweaked_pubkey[32];
zkp_bip340_tweak_public_key(node->public_key + 1, NULL, tweaked_pubkey);
if (!segwit_addr_encode(address, coin->bech32_prefix, SEGWIT_VERSION_1,
tweaked_pubkey, 32)) {
return 0;
}
} else if (script_type == InputScriptType_SPENDP2SHWITNESS) {
// segwit p2wpkh embedded in p2sh
if (!coin->has_segwit) {
@ -177,16 +196,22 @@ bool compute_address(const CoinInfo *coin, InputScriptType script_type,
ecdsa_get_address_segwit_p2sh(
node->public_key, coin->address_type_p2sh, coin->curve->hasher_pubkey,
coin->curve->hasher_base58, address, MAX_ADDR_SIZE);
} else if (coin->cashaddr_prefix) {
ecdsa_get_address_raw(node->public_key, CASHADDR_P2KH | CASHADDR_160,
coin->curve->hasher_pubkey, raw);
if (!cash_addr_encode(address, coin->cashaddr_prefix, raw, 21)) {
return 0;
} else if (script_type == InputScriptType_SPENDADDRESS ||
script_type == InputScriptType_SPENDMULTISIG) {
if (coin->cashaddr_prefix) {
ecdsa_get_address_raw(node->public_key, CASHADDR_P2KH | CASHADDR_160,
coin->curve->hasher_pubkey, raw);
if (!cash_addr_encode(address, coin->cashaddr_prefix, raw, 21)) {
return 0;
}
} else {
ecdsa_get_address(node->public_key, coin->address_type,
coin->curve->hasher_pubkey, coin->curve->hasher_base58,
address, MAX_ADDR_SIZE);
}
} else {
ecdsa_get_address(node->public_key, coin->address_type,
coin->curve->hasher_pubkey, coin->curve->hasher_base58,
address, MAX_ADDR_SIZE);
// unsupported script type
return 0;
}
return 1;
}

View File

@ -45,33 +45,29 @@ VECTORS = ( # coin, path, script_type, address
proto.InputScriptType.SPENDWITNESS,
"bc1qktmhrsmsenepnnfst8x6j27l0uqv7ggrg8x38q",
),
pytest.param(
(
"Testnet",
"86'/1'/0'/0/0",
proto.InputScriptType.SPENDTAPROOT,
"tb1pswrqtykue8r89t9u4rprjs0gt4qzkdfuursfnvqaa3f2yql07zmq8s8a5u",
marks=pytest.mark.skip_t1,
),
pytest.param(
(
"Testnet",
"86'/1'/0'/1/0",
proto.InputScriptType.SPENDTAPROOT,
"tb1pn2d0yjeedavnkd8z8lhm566p0f2utm3lgvxrsdehnl94y34txmts5s7t4c",
marks=pytest.mark.skip_t1,
),
pytest.param(
(
"Bitcoin",
"86'/0'/0'/0/0",
proto.InputScriptType.SPENDTAPROOT,
"bc1ptxs597p3fnpd8gwut5p467ulsydae3rp9z75hd99w8k3ljr9g9rqx6ynaw",
marks=pytest.mark.skip_t1,
),
pytest.param(
(
"Bitcoin",
"86'/0'/0'/1/0",
proto.InputScriptType.SPENDTAPROOT,
"bc1pgypgja2hmcx2l6s2ssq75k6ev68ved6nujcspt47dgvkp8euc70s6uegk6",
marks=pytest.mark.skip_t1,
),
pytest.param(
"Groestlcoin",
@ -114,7 +110,6 @@ def test_show_segwit(client, show_display, coin, path, script_type, address):
# Tests https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#test-vectors
@pytest.mark.skip_t1
@pytest.mark.setup_client(
mnemonic="abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
)