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

Added support for cashaddr.

This commit is contained in:
Jochen Hoenicke 2018-01-04 20:18:34 +01:00 committed by Pavol Rusnak
parent e1ad1512d0
commit cb6022ce04
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
4 changed files with 51 additions and 1 deletions

View File

@ -58,6 +58,7 @@ OBJS += ../vendor/trezor-crypto/pbkdf2.o
OBJS += ../vendor/trezor-crypto/base32.o OBJS += ../vendor/trezor-crypto/base32.o
OBJS += ../vendor/trezor-crypto/base58.o OBJS += ../vendor/trezor-crypto/base58.o
OBJS += ../vendor/trezor-crypto/segwit_addr.o OBJS += ../vendor/trezor-crypto/segwit_addr.o
OBJS += ../vendor/trezor-crypto/cash_addr.o
OBJS += ../vendor/trezor-crypto/ripemd160.o OBJS += ../vendor/trezor-crypto/ripemd160.o
OBJS += ../vendor/trezor-crypto/sha2.o OBJS += ../vendor/trezor-crypto/sha2.o

View File

@ -91,6 +91,7 @@ def coin_to_struct(coin):
("xprv_magic", format_hex(coin["xprv_magic"])), ("xprv_magic", format_hex(coin["xprv_magic"])),
("forkid", format_number(coin["forkid"])), ("forkid", format_number(coin["forkid"])),
("bech32_prefix", format_string(coin["bech32_prefix"])), ("bech32_prefix", format_string(coin["bech32_prefix"])),
("cashaddr_prefix", format_string(coin["cashaddr_prefix"])),
("coin_type", "({} | 0x80000000)".format(format_number(coin["bip44"]))), # noqa: E501 ("coin_type", "({} | 0x80000000)".format(format_number(coin["bip44"]))), # noqa: E501
("curve_name", "{}_NAME".format(coin["curve_name"].upper())), # noqa: E501 ("curve_name", "{}_NAME".format(coin["curve_name"].upper())), # noqa: E501
("curve", "&{}_info".format(coin["curve_name"])), ("curve", "&{}_info".format(coin["curve_name"])),

View File

@ -44,6 +44,7 @@ typedef struct _CoinInfo {
uint32_t xprv_magic; uint32_t xprv_magic;
uint32_t forkid; uint32_t forkid;
const char *bech32_prefix; const char *bech32_prefix;
const char *cashaddr_prefix;
uint32_t coin_type; uint32_t coin_type;
const char *curve_name; const char *curve_name;
const curve_info *curve; const curve_info *curve;

View File

@ -32,9 +32,14 @@
#include "messages.pb.h" #include "messages.pb.h"
#include "types.pb.h" #include "types.pb.h"
#include "segwit_addr.h" #include "segwit_addr.h"
#include "cash_addr.h"
#define SEGWIT_VERSION_0 0 #define SEGWIT_VERSION_0 0
#define CASHADDR_P2KH (0)
#define CASHADDR_P2SH (8)
#define CASHADDR_160 (0)
/* transaction input size (without script): 32 prevhash, 4 idx, 4 sequence */ /* transaction input size (without script): 32 prevhash, 4 idx, 4 sequence */
#define TXSIZE_INPUT 40 #define TXSIZE_INPUT 40
/* transaction output size (without script): 8 amount */ /* transaction output size (without script): 8 amount */
@ -138,6 +143,12 @@ bool compute_address(const CoinInfo *coin,
if (!base58_encode_check(raw, prelen + 20, coin->curve->hasher_base58, address, MAX_ADDR_SIZE)) { if (!base58_encode_check(raw, prelen + 20, coin->curve->hasher_base58, address, MAX_ADDR_SIZE)) {
return 0; 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 { } else {
// non-segwit p2sh multisig // non-segwit p2sh multisig
prelen = address_prefix_bytes_len(coin->address_type_p2sh); prelen = address_prefix_bytes_len(coin->address_type_p2sh);
@ -165,6 +176,11 @@ bool compute_address(const CoinInfo *coin,
return 0; return 0;
} }
ecdsa_get_address_segwit_p2sh(node->public_key, coin->address_type_p2sh, coin->curve->hasher_pubkey, coin->curve->hasher_base58, address, MAX_ADDR_SIZE); 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_type, raw);
if (!cash_addr_encode(address, coin->cashaddr_prefix, raw, 21)) {
return 0;
}
} else { } else {
ecdsa_get_address(node->public_key, coin->address_type, coin->curve->hasher_pubkey, coin->curve->hasher_base58, address, MAX_ADDR_SIZE); ecdsa_get_address(node->public_key, coin->address_type, coin->curve->hasher_pubkey, coin->curve->hasher_base58, address, MAX_ADDR_SIZE);
} }
@ -252,6 +268,28 @@ int compile_output(const CoinInfo *coin, const HDNode *root, TxOutputType *in, T
memcpy(out->script_pubkey.bytes + 2, addr_raw + prefix_len, 20); memcpy(out->script_pubkey.bytes + 2, addr_raw + prefix_len, 20);
out->script_pubkey.bytes[22] = 0x87; // OP_EQUAL out->script_pubkey.bytes[22] = 0x87; // OP_EQUAL
out->script_pubkey.size = 23; out->script_pubkey.size = 23;
} else if (coin->cashaddr_prefix
&& cash_addr_decode(addr_raw, &addr_raw_len, coin->cashaddr_prefix, in->address)) {
if (addr_raw_len == 21
&& addr_raw[0] == (CASHADDR_P2KH | CASHADDR_160)) {
out->script_pubkey.bytes[0] = 0x76; // OP_DUP
out->script_pubkey.bytes[1] = 0xA9; // OP_HASH_160
out->script_pubkey.bytes[2] = 0x14; // pushing 20 bytes
memcpy(out->script_pubkey.bytes + 3, addr_raw + 1, 20);
out->script_pubkey.bytes[23] = 0x88; // OP_EQUALVERIFY
out->script_pubkey.bytes[24] = 0xAC; // OP_CHECKSIG
out->script_pubkey.size = 25;
} else if (addr_raw_len == 21
&& addr_raw[0] == (CASHADDR_P2SH | CASHADDR_160)) {
out->script_pubkey.bytes[0] = 0xA9; // OP_HASH_160
out->script_pubkey.bytes[1] = 0x14; // pushing 20 bytes
memcpy(out->script_pubkey.bytes + 2, addr_raw + 1, 20);
out->script_pubkey.bytes[22] = 0x87; // OP_EQUAL
out->script_pubkey.size = 23;
} else {
return 0;
}
} else if (coin->bech32_prefix) { } else if (coin->bech32_prefix) {
int witver; int witver;
if (!segwit_addr_decode(&witver, addr_raw, &addr_raw_len, coin->bech32_prefix, in->address)) { if (!segwit_addr_decode(&witver, addr_raw, &addr_raw_len, coin->bech32_prefix, in->address)) {
@ -736,7 +774,16 @@ uint32_t tx_output_weight(const CoinInfo *coin, const TxOutputType *txoutput) {
uint8_t addr_raw[MAX_ADDR_RAW_SIZE]; uint8_t addr_raw[MAX_ADDR_RAW_SIZE];
int witver; int witver;
size_t addr_raw_len; size_t addr_raw_len;
if (coin->bech32_prefix if (coin->cashaddr_prefix
&& cash_addr_decode(addr_raw, &addr_raw_len, coin->cashaddr_prefix, txoutput->address)) {
if (addr_raw_len == 21
&& addr_raw[0] == (CASHADDR_P2KH | CASHADDR_160)) {
output_script_size = TXSIZE_P2PKHASH;
} else if (addr_raw_len == 21
&& addr_raw[0] == (CASHADDR_P2SH | CASHADDR_160)) {
output_script_size = TXSIZE_P2SCRIPT;
}
} else if (coin->bech32_prefix
&& segwit_addr_decode(&witver, addr_raw, &addr_raw_len, coin->bech32_prefix, txoutput->address)) { && segwit_addr_decode(&witver, addr_raw, &addr_raw_len, coin->bech32_prefix, txoutput->address)) {
output_script_size = 2 + addr_raw_len; output_script_size = 2 + addr_raw_len;
} else { } else {