Skip to content

Commit 102f799

Browse files
Merge branch 'develop' into feat/evm/txn-calldata
2 parents 2275d7c + cfc0f3e commit 102f799

File tree

8 files changed

+455
-7
lines changed

8 files changed

+455
-7
lines changed

apps/btc_family/btc_pub_key.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,16 @@ static size_t btc_get_address(const uint8_t *seed,
221221
case NON_SEGWIT:
222222
hdnode_get_address(&node, g_btc_app->p2pkh_addr_ver, addr, 35);
223223
break;
224-
// TODO: add support for taproot and segwit
224+
case PURPOSE_SEGWIT:
225+
ecdsa_get_address_segwit_p2sh(node.public_key,
226+
g_btc_app->p2sh_addr_ver,
227+
node.curve->hasher_pubkey,
228+
node.curve->hasher_base58,
229+
addr,
230+
36);
231+
break;
232+
233+
// TODO: add support for taproot
225234
default:
226235
break;
227236
}

apps/btc_family/btc_script.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,25 @@ bool btc_check_script_address(const uint8_t *script,
239239

240240
uint8_t digest[HASHER_DIGEST_LENGTH] = {0};
241241
btc_script_type_e type = btc_get_script_type(script, script_len);
242-
if (SCRIPT_TYPE_P2PKH != type && SCRIPT_TYPE_P2WPKH != type) {
243-
// allow only p2pkh and p2wpkh for change output
242+
if (SCRIPT_TYPE_P2PKH != type && SCRIPT_TYPE_P2WPKH != type &&
243+
SCRIPT_TYPE_P2SH != type) {
244+
// allow only p2pkh and p2wpkh and p2sh-p2wpkh for change output
244245
return false;
245246
}
246247
uint8_t offset = (SCRIPT_TYPE_P2PKH == type) ? 3 : 2;
247248

248249
hasher_Raw(HASHER_SHA2_RIPEMD, public_key, BTC_SHORT_PUB_KEY_SIZE, digest);
250+
251+
if (SCRIPT_TYPE_P2SH == type) {
252+
// Compute redeemscript(P2WPKH). scriptpub of nested-segwit is hash160 of
253+
// redeemscript
254+
uint8_t buf[22] = {0};
255+
buf[0] = 0; // version byte
256+
buf[1] = 20; // push 20 bytes
257+
memcpy(buf + 2, digest, 20);
258+
hasher_Raw(HASHER_SHA2_RIPEMD, buf, 22, digest);
259+
}
260+
249261
return (memcmp(digest, &script[offset], RIPEMD160_DIGEST_LENGTH) == 0);
250262
}
251263

apps/btc_family/btc_txn.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,8 @@ static bool fetch_valid_input(btc_query_t *query) {
502502
payload = NULL;
503503
hoisted_query = NULL;
504504

505-
if ((SCRIPT_TYPE_P2PKH != type && SCRIPT_TYPE_P2WPKH != type) ||
505+
if ((SCRIPT_TYPE_P2PKH != type && SCRIPT_TYPE_P2WPKH != type &&
506+
SCRIPT_TYPE_P2SH != type) ||
506507
validation_result != BTC_VALIDATE_SUCCESS) {
507508
// input validation failed, terminate immediately
508509
btc_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG,
@@ -680,11 +681,27 @@ static bool sign_input(scrip_sig_t *signatures) {
680681
status = true;
681682
for (int idx = 0; idx < btc_txn_context->metadata.input_count; idx++) {
682683
// generate the input digest and respective private key
683-
status = btc_digest_input(btc_txn_context, idx, buffer);
684684
memcpy(&t_node, &node, sizeof(HDNode));
685685
hdnode_private_ckd(&t_node, btc_txn_context->inputs[idx].change_index);
686686
hdnode_private_ckd(&t_node, btc_txn_context->inputs[idx].address_index);
687687
hdnode_fill_public_key(&t_node);
688+
689+
// detect input type
690+
btc_sign_txn_input_script_pub_key_t *script =
691+
&btc_txn_context->inputs[idx].script_pub_key;
692+
btc_script_type_e type = btc_get_script_type(script->bytes, script->size);
693+
if (SCRIPT_TYPE_P2SH == type) {
694+
// replace BIP16 scriptpubkey with redeemscript(P2WPKH)
695+
uint8_t buf[22] = {0};
696+
buf[0] = 0; // version byte
697+
buf[1] = 20; // push 20 bytes
698+
ecdsa_get_pubkeyhash(
699+
t_node.public_key, t_node.curve->hasher_pubkey, buf + 2);
700+
memcpy(btc_txn_context->inputs[idx].script_pub_key.bytes, buf, 22);
701+
btc_txn_context->inputs[idx].script_pub_key.size = 22;
702+
}
703+
704+
status = btc_digest_input(btc_txn_context, idx, buffer);
688705
ecdsa_sign_digest(
689706
curve, t_node.private_key, buffer, signatures[idx].bytes, NULL, NULL);
690707
signatures[idx].size = btc_sig_to_script_sig(

apps/btc_family/btc_txn_helpers.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,6 @@ bool btc_digest_input(const btc_txn_context_t *context,
406406
btc_sign_txn_input_script_pub_key_t *script =
407407
&context->inputs[index].script_pub_key;
408408
btc_script_type_e type = btc_get_script_type(script->bytes, script->size);
409-
410409
if (SCRIPT_TYPE_P2WPKH == type) {
411410
// segwit digest calculation; could fail if segwit_cache not filled
412411
status = calculate_p2wpkh_digest(context, index, digest);

tests/apps/btc_app/btc_inputs_validator.c

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,193 @@ TEST(btc_inputs_validator_tests, btc_txn_helper_verify_input_p2wpkh_fail) {
454454
TEST_ASSERT_EQUAL(BTC_VALIDATE_ERR_INVALID_TX_HASH, status);
455455
}
456456

457+
TEST(btc_inputs_validator_tests, btc_txn_helper_verify_input_p2wpkh_in_p2sh) {
458+
/* Test data source: Bip143
459+
* https://blockstream.info/testnet/tx/b095225e60df2896a4e03fcc4fb2ba9622ee513f34b3e8de45c25a4793a244a2?expand
460+
*/
461+
uint8_t raw_txn[2000] = {0};
462+
hex_string_to_byte_array(
463+
"0200000000010258afb1ece76f01c24f4935f453d210518163cb1d0383eaec331b202ebe"
464+
"b5e389"
465+
"0000000017160014a76cad25cb569bb47305513ebedd6011dc419deeffffffff2b3682b3"
466+
"592588"
467+
"5001f0e321df28d4ac675a9cbbccef2a69533bea7c5e5ad2c40000000017160014a76cad"
468+
"25cb56"
469+
"9bb47305513ebedd6011dc419deeffffffff02941100000000000017a914bd7aabdeeef2"
470+
"11b1bd"
471+
"ad7218e14fea6c032101c087f22f00000000000017a914eaf97514c5ac1e41e413502e97"
472+
"ae42eb"
473+
"f27ace3a870247304402206e038f4712541d699697ed55efc41219df4f244fc72caa5edd"
474+
"653837"
475+
"f6555f6f02201cd8ea15b65fda17992abafaed86e066c3271ac16b9c46c54c2192438843"
476+
"dd0401"
477+
"21029f75e1ef6b04e004a308b1f59215a8a3a5b7958bbcf184cc24ba7ab6574448780248"
478+
"304502"
479+
"2100d15ce61648edc28b8b5a3531b80a1e8fc3b3eebe7d3fc4ca962cb04afc770dda0220"
480+
"7c7eaf8"
481+
"82d7fac45d2752f20e48d2f896715cbc5a3b0f5de3e19fea0da99beac0121029f75e1ef6"
482+
"b04e004"
483+
"a308b1f59215a8a3a5b7958bbcf184cc24ba7ab65744487800000000",
484+
838,
485+
raw_txn);
486+
// only fill necessary values
487+
btc_sign_txn_input_t input[] = {{
488+
.value = 4500,
489+
.prev_output_index = 0x00000000,
490+
.script_pub_key = {.size = 23},
491+
},
492+
{
493+
.value = 12274,
494+
.prev_output_index = 0x00000001,
495+
.script_pub_key = {.size = 23},
496+
}};
497+
498+
hex_string_to_byte_array(
499+
"b095225e60df2896a4e03fcc4fb2ba9622ee513f34b3e8de45c25a4793a244a2",
500+
64,
501+
input[0].prev_txn_hash);
502+
// Reverse order of txn-id:
503+
// A244A293475AC245DEE8B3343F51EE2296BAB24FCC3FE0A49628DF605E2295B0
504+
cy_reverse_byte_array(input[0].prev_txn_hash, sizeof(input[0].prev_txn_hash));
505+
506+
hex_string_to_byte_array(
507+
"b095225e60df2896a4e03fcc4fb2ba9622ee513f34b3e8de45c25a4793a244a2",
508+
64,
509+
input[1].prev_txn_hash);
510+
// Reverse order of txn-id:
511+
// A244A293475AC245DEE8B3343F51EE2296BAB24FCC3FE0A49628DF605E2295B0
512+
cy_reverse_byte_array(input[1].prev_txn_hash, sizeof(input[1].prev_txn_hash));
513+
514+
hex_string_to_byte_array("a914bd7aabdeeef211b1bdad7218e14fea6c032101c087",
515+
46,
516+
input[0].script_pub_key.bytes);
517+
hex_string_to_byte_array("a914eaf97514c5ac1e41e413502e97ae42ebf27ace3a87",
518+
46,
519+
input[1].script_pub_key.bytes);
520+
521+
data_ptr = raw_txn;
522+
data_total_size = 838 / 2;
523+
524+
byte_stream_t stream = {
525+
.stream_pointer = raw_txn,
526+
.writer = generic_writer,
527+
.offset = 0,
528+
.capacity = 100,
529+
};
530+
531+
btc_validation_error_e status = btc_validate_inputs(&stream, input);
532+
533+
TEST_ASSERT_EQUAL(BTC_VALIDATE_SUCCESS, status);
534+
535+
data_ptr = raw_txn;
536+
data_total_size = 838 / 2;
537+
global_offset = 0;
538+
539+
stream.stream_pointer = raw_txn;
540+
stream.offset = 0;
541+
stream.capacity = 100;
542+
543+
status = btc_validate_inputs(&stream, input + 1);
544+
545+
TEST_ASSERT_EQUAL(BTC_VALIDATE_SUCCESS, status);
546+
}
547+
548+
TEST(btc_inputs_validator_tests,
549+
btc_txn_helper_verify_input_p2wpkh_in_p2sh_fail) {
550+
/* Test data source: Bip143
551+
* https://blockstream.info/testnet/tx/b095225e60df2896a4e03fcc4fb2ba9622ee513f34b3e8de45c25a4793a244a2?expand
552+
*/
553+
uint8_t raw_txn[2000] = {0};
554+
hex_string_to_byte_array(
555+
"0200000000010258afb1ece76f01c24f4935f453d210518163cb1d0383eaec331b202ebe"
556+
"b5e389"
557+
"0000000017160014a76cad25cb569bb47305513ebedd6011dc419deeffffffff2b3682b3"
558+
"592588"
559+
"5001f0e321df28d4ac675a9cbbccef2a69533bea7c5e5ad2c40000000017160014a76cad"
560+
"25cb56"
561+
"9bb47305513ebedd6011dc419deeffffffff02941100000000000017a914bd7aabdeeef2"
562+
"11b1bd"
563+
"ad7218e14fea6c032101c087f22f00000000000017a914eaf97514c5ac1e41e413502e97"
564+
"ae42eb"
565+
"f27ace3a870247304402206e038f4712541d699697ed55efc41219df4f244fc72caa5edd"
566+
"653837"
567+
"f6555f6f02201cd8ea15b65fda17992abafaed86e066c3271ac16b9c46c54c2192438843"
568+
"dd0401"
569+
"21029f75e1ef6b04e004a308b1f59215a8a3a5b7958bbcf184cc24ba7ab6574448780248"
570+
"304502"
571+
"2100d15ce61648edc28b8b5a3531b80a1e8fc3b3eebe7d3fc4ca962cb04afc770dda0220"
572+
"7c7eaf8"
573+
"82d7fac45d2752f20e48d2f896715cbc5a3b0f5de3e19fea0da99beac0121029f75e1ef6"
574+
"b04e004"
575+
"a308b1f59215a8a3a5b7958bbcf184cc24ba7ab65744487800000000",
576+
838,
577+
raw_txn);
578+
// only fill necessary values
579+
btc_sign_txn_input_t input[] = {{
580+
.value = 4500,
581+
.prev_output_index = 0x00000000,
582+
.script_pub_key = {.size = 23},
583+
},
584+
{
585+
.value = 12274,
586+
.prev_output_index = 0x00000001,
587+
.script_pub_key = {.size = 23},
588+
}};
589+
590+
hex_string_to_byte_array(
591+
// invalid txn hash test. valid txn hash/id:
592+
// b095225e60df2896a4e03fcc4fb2ba9622ee513f34b3e8de45c25a4793a244a2
593+
"b095225e60df2896a4e03fcc4fb2ba9622ee513f34b3e8de45c25a4793a244a3",
594+
64,
595+
input[0].prev_txn_hash);
596+
// Reverse order of txn-id:
597+
// A344A293475AC245DEE8B3343F51EE2296BAB24FCC3FE0A49628DF605E2295B0
598+
cy_reverse_byte_array(input[0].prev_txn_hash, sizeof(input[0].prev_txn_hash));
599+
600+
hex_string_to_byte_array(
601+
// invalid txn hash test. valid txn hash/id:
602+
// b095225e60df2896a4e03fcc4fb2ba9622ee513f34b3e8de45c25a4793a244a2
603+
"b095225e60df2896a4e03fcc4fb2ba9622ee513f34b3e8de45c25a4793a244a3",
604+
64,
605+
input[1].prev_txn_hash);
606+
// Reverse order of txn-id:
607+
// A344A293475AC245DEE8B3343F51EE2296BAB24FCC3FE0A49628DF605E2295B0
608+
cy_reverse_byte_array(input[1].prev_txn_hash, sizeof(input[1].prev_txn_hash));
609+
610+
hex_string_to_byte_array("a914bd7aabdeeef211b1bdad7218e14fea6c032101c087",
611+
46,
612+
input[0].script_pub_key.bytes);
613+
hex_string_to_byte_array("a914eaf97514c5ac1e41e413502e97ae42ebf27ace3a87",
614+
46,
615+
input[1].script_pub_key.bytes);
616+
617+
data_ptr = raw_txn;
618+
data_total_size = 838 / 2;
619+
620+
byte_stream_t stream = {
621+
.stream_pointer = raw_txn,
622+
.writer = generic_writer,
623+
.offset = 0,
624+
.capacity = 500,
625+
};
626+
627+
btc_validation_error_e status = btc_validate_inputs(&stream, input);
628+
629+
TEST_ASSERT_EQUAL(BTC_VALIDATE_ERR_INVALID_TX_HASH, status);
630+
631+
data_ptr = raw_txn;
632+
data_total_size = 838 / 2;
633+
global_offset = 0;
634+
635+
stream.stream_pointer = raw_txn;
636+
stream.offset = 0;
637+
stream.capacity = 100;
638+
639+
status = btc_validate_inputs(&stream, input + 1);
640+
641+
TEST_ASSERT_EQUAL(BTC_VALIDATE_ERR_INVALID_TX_HASH, status);
642+
}
643+
457644
TEST(btc_inputs_validator_tests,
458645
btc_validate_inputs_for_a_transaction_with_witness_data) {
459646
/* Test data source: rawTxn -

tests/apps/btc_app/btc_script_tests.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858

5959
#include "btc_helpers.h"
6060
#include "btc_priv.h"
61+
#include "btc_script.h"
6162
#include "curves.h"
6263
#include "flash_config.h"
6364
#include "ltc_app.h"

0 commit comments

Comments
 (0)