Skip to content

Commit 77620b4

Browse files
committed
feat (app): Add nested-segwit support
test nested-segwit digest for 1 inputs and 2 output transactions test nested-segwit digest for 2 inputs and 2 output transactions
1 parent 7ad67f2 commit 77620b4

File tree

6 files changed

+418
-12
lines changed

6 files changed

+418
-12
lines changed

apps/btc_family/btc_pub_key.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,16 @@ static size_t btc_get_address(const uint8_t *seed,
204204
case NON_SEGWIT:
205205
hdnode_get_address(&node, g_btc_app->p2pkh_addr_ver, addr, 35);
206206
break;
207-
// TODO: add support for taproot and segwit
207+
case PURPOSE_SEGWIT:
208+
ecdsa_get_address_segwit_p2sh(node.public_key,
209+
g_btc_app->p2sh_addr_ver,
210+
node.curve->hasher_pubkey,
211+
node.curve->hasher_base58,
212+
addr,
213+
36);
214+
break;
215+
216+
// TODO: add support for taproot
208217
default:
209218
break;
210219
}

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
@@ -478,7 +478,8 @@ static bool fetch_valid_input(btc_query_t *query) {
478478
return false;
479479
}
480480

481-
if ((SCRIPT_TYPE_P2PKH != type && SCRIPT_TYPE_P2WPKH != type) ||
481+
if ((SCRIPT_TYPE_P2PKH != type && SCRIPT_TYPE_P2WPKH != type &&
482+
SCRIPT_TYPE_P2SH != type) ||
482483
0 != status) {
483484
// input validation failed, terminate immediately
484485
btc_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG,
@@ -648,11 +649,27 @@ static bool sign_input(scrip_sig_t *signatures) {
648649
status = true;
649650
for (int idx = 0; idx < btc_txn_context->metadata.input_count; idx++) {
650651
// generate the input digest and respective private key
651-
status = btc_digest_input(btc_txn_context, idx, buffer);
652652
memcpy(&t_node, &node, sizeof(HDNode));
653653
hdnode_private_ckd(&t_node, btc_txn_context->inputs[idx].change_index);
654654
hdnode_private_ckd(&t_node, btc_txn_context->inputs[idx].address_index);
655655
hdnode_fill_public_key(&t_node);
656+
657+
// detect input type
658+
btc_sign_txn_input_script_pub_key_t *script =
659+
&btc_txn_context->inputs[idx].script_pub_key;
660+
btc_script_type_e type = btc_get_script_type(script->bytes, script->size);
661+
if (SCRIPT_TYPE_P2SH == type) {
662+
// replace BIP16 scriptpubkey with redeemscript(P2WPKH)
663+
uint8_t buf[22] = {0};
664+
buf[0] = 0; // version byte
665+
buf[1] = 20; // push 20 bytes
666+
ecdsa_get_pubkeyhash(
667+
t_node.public_key, t_node.curve->hasher_pubkey, buf + 2);
668+
memcpy(btc_txn_context->inputs[idx].script_pub_key.bytes, buf, 22);
669+
btc_txn_context->inputs[idx].script_pub_key.size = 22;
670+
}
671+
672+
status = btc_digest_input(btc_txn_context, idx, buffer);
656673
ecdsa_sign_digest(
657674
curve, t_node.private_key, buffer, signatures[idx].bytes, NULL, NULL);
658675
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
@@ -670,7 +670,6 @@ bool btc_digest_input(const btc_txn_context_t *context,
670670
btc_sign_txn_input_script_pub_key_t *script =
671671
&context->inputs[index].script_pub_key;
672672
btc_script_type_e type = btc_get_script_type(script->bytes, script->size);
673-
674673
if (SCRIPT_TYPE_P2WPKH == type) {
675674
// segwit digest calculation; could fail if segwit_cache not filled
676675
status = calculate_p2wpkh_digest(context, index, digest);

0 commit comments

Comments
 (0)