mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-19 20:01:11 +00:00
Allow SegWit addresses
New output scripts for segwit addresses in accordance to BIP-142 and BIP-141. This allows Trezor to pay to segwit users, but it doesn't enable segwit for Trezor itself.
This commit is contained in:
parent
71890e4edf
commit
1bd4b99f95
@ -12,7 +12,7 @@ TxInputType.address_n max_count:8
|
||||
TxInputType.prev_hash max_size:32
|
||||
TxInputType.script_sig max_size:1650
|
||||
|
||||
TxOutputType.address max_size:41
|
||||
TxOutputType.address max_size:54
|
||||
TxOutputType.address_n max_count:8
|
||||
TxOutputType.op_return_data max_size:80
|
||||
|
||||
|
@ -229,7 +229,7 @@ typedef struct {
|
||||
|
||||
typedef struct _TxOutputType {
|
||||
bool has_address;
|
||||
char address[41];
|
||||
char address[54];
|
||||
size_t address_n_count;
|
||||
uint32_t address_n[8];
|
||||
uint64_t amount;
|
||||
|
@ -61,11 +61,68 @@ int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, T
|
||||
memset(out, 0, sizeof(TxOutputBinType));
|
||||
out->amount = in->amount;
|
||||
uint8_t addr_raw[MAX_ADDR_RAW_SIZE];
|
||||
int addr_raw_len;
|
||||
|
||||
if (in->has_address) { // address provided -> regular output
|
||||
addr_raw_len = base58_decode_check(in->address, addr_raw, MAX_ADDR_RAW_SIZE);
|
||||
if (in->script_type != OutputScriptType_PAYTOADDRESS) {
|
||||
// allow for p2sh (backward compatibility only)
|
||||
if (in->script_type != OutputScriptType_PAYTOSCRIPTHASH
|
||||
|| addr_raw_len != 21
|
||||
|| addr_raw[0] != coin->address_type_p2sh) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (addr_raw_len == 21 &&
|
||||
addr_raw[0] == coin->address_type) { // p2pkh
|
||||
|
||||
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] == coin->address_type_p2sh) { // p2sh
|
||||
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 if (addr_raw_len == 23
|
||||
&& addr_raw[0] == coin->address_type_p2wpkh
|
||||
&& addr_raw[1] == 0 && addr_raw[2] == 0) { // p2wpkh v0
|
||||
out->script_pubkey.bytes[0] = 0x00; // version 0
|
||||
out->script_pubkey.bytes[1] = 0x14; // pushing 20 bytes
|
||||
memcpy(out->script_pubkey.bytes + 2, addr_raw + 3, 20);
|
||||
out->script_pubkey.size = 22;
|
||||
} else if (addr_raw_len == 35
|
||||
&& addr_raw[0] == coin->address_type_p2wsh
|
||||
&& addr_raw[1] == 0 && addr_raw[2] == 0) { // p2wsh v0
|
||||
out->script_pubkey.bytes[0] = 0x00; // version 0
|
||||
out->script_pubkey.bytes[1] = 0x20; // pushing 32 bytes
|
||||
memcpy(out->script_pubkey.bytes + 2, addr_raw + 3, 32);
|
||||
out->script_pubkey.size = 34;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (needs_confirm) {
|
||||
layoutConfirmOutput(coin, in);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return out->script_pubkey.size;
|
||||
}
|
||||
|
||||
if (in->script_type == OutputScriptType_PAYTOADDRESS) {
|
||||
|
||||
// address_n provided-> change address -> calculate from address_n
|
||||
if (in->address_n_count > 0) {
|
||||
if (in->script_type == OutputScriptType_PAYTOADDRESS &&
|
||||
in->address_n_count > 0) {
|
||||
HDNode node;
|
||||
memcpy(&node, root, sizeof(HDNode));
|
||||
if (hdnode_private_ckd_cached(&node, in->address_n, in->address_n_count) == 0) {
|
||||
@ -73,18 +130,6 @@ int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, T
|
||||
}
|
||||
layoutProgressUpdate(true);
|
||||
hdnode_get_address_raw(&node, coin->address_type, addr_raw);
|
||||
} else
|
||||
if (in->has_address) { // address provided -> regular output
|
||||
if (needs_confirm) {
|
||||
layoutConfirmOutput(coin, in);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!ecdsa_address_decode(in->address, coin->address_type, addr_raw)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else { // does not have address_n neither address -> error
|
||||
return 0;
|
||||
}
|
||||
@ -99,24 +144,6 @@ int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, T
|
||||
return 25;
|
||||
}
|
||||
|
||||
if (in->script_type == OutputScriptType_PAYTOSCRIPTHASH) {
|
||||
if (!in->has_address || !ecdsa_address_decode(in->address, coin->address_type_p2sh, addr_raw)) {
|
||||
return 0;
|
||||
}
|
||||
if (needs_confirm) {
|
||||
layoutConfirmOutput(coin, in);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
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 + address_prefix_bytes_len(coin->address_type_p2sh), 20);
|
||||
out->script_pubkey.bytes[22] = 0x87; // OP_EQUAL
|
||||
out->script_pubkey.size = 23;
|
||||
return 23;
|
||||
}
|
||||
|
||||
if (in->script_type == OutputScriptType_PAYTOMULTISIG) {
|
||||
uint8_t buf[32];
|
||||
size_t prefix_bytes = address_prefix_bytes_len(coin->address_type_p2sh);
|
||||
|
Loading…
Reference in New Issue
Block a user