Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add P2SH-P2WPKH support #528

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion apps/btc_family/btc_pub_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,16 @@ static size_t btc_get_address(const uint8_t *seed,
case NON_SEGWIT:
hdnode_get_address(&node, g_btc_app->p2pkh_addr_ver, addr, 35);
break;
// TODO: add support for taproot and segwit
case PURPOSE_SEGWIT:
ecdsa_get_address_segwit_p2sh(node.public_key,
g_btc_app->p2sh_addr_ver,
node.curve->hasher_pubkey,
node.curve->hasher_base58,
addr,
36);
break;

// TODO: add support for taproot
default:
break;
}
Expand Down
16 changes: 14 additions & 2 deletions apps/btc_family/btc_script.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,25 @@ bool btc_check_script_address(const uint8_t *script,

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

hasher_Raw(HASHER_SHA2_RIPEMD, public_key, BTC_SHORT_PUB_KEY_SIZE, digest);

if (SCRIPT_TYPE_P2SH == type) {
// Compute redeemscript(P2WPKH). scriptpub of nested-segwit is hash160 of
// redeemscript
uint8_t buf[22] = {0};
buf[0] = 0; // version byte
buf[1] = 20; // push 20 bytes
memcpy(buf + 2, digest, 20);
hasher_Raw(HASHER_SHA2_RIPEMD, buf, 22, digest);
}

return (memcmp(digest, &script[offset], RIPEMD160_DIGEST_LENGTH) == 0);
}

Expand Down
21 changes: 19 additions & 2 deletions apps/btc_family/btc_txn.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,8 @@ static bool fetch_valid_input(btc_query_t *query) {
return false;
}

if ((SCRIPT_TYPE_P2PKH != type && SCRIPT_TYPE_P2WPKH != type) ||
if ((SCRIPT_TYPE_P2PKH != type && SCRIPT_TYPE_P2WPKH != type &&
SCRIPT_TYPE_P2SH != type) ||
0 != status) {
// input validation failed, terminate immediately
btc_send_error(ERROR_COMMON_ERROR_CORRUPT_DATA_TAG,
Expand Down Expand Up @@ -648,11 +649,27 @@ static bool sign_input(scrip_sig_t *signatures) {
status = true;
for (int idx = 0; idx < btc_txn_context->metadata.input_count; idx++) {
// generate the input digest and respective private key
status = btc_digest_input(btc_txn_context, idx, buffer);
memcpy(&t_node, &node, sizeof(HDNode));
hdnode_private_ckd(&t_node, btc_txn_context->inputs[idx].change_index);
hdnode_private_ckd(&t_node, btc_txn_context->inputs[idx].address_index);
hdnode_fill_public_key(&t_node);

// detect input type
btc_sign_txn_input_script_pub_key_t *script =
&btc_txn_context->inputs[idx].script_pub_key;
btc_script_type_e type = btc_get_script_type(script->bytes, script->size);
if (SCRIPT_TYPE_P2SH == type) {
// replace BIP16 scriptpubkey with redeemscript(P2WPKH)
uint8_t buf[22] = {0};
buf[0] = 0; // version byte
buf[1] = 20; // push 20 bytes
ecdsa_get_pubkeyhash(
t_node.public_key, t_node.curve->hasher_pubkey, buf + 2);
memcpy(btc_txn_context->inputs[idx].script_pub_key.bytes, buf, 22);
btc_txn_context->inputs[idx].script_pub_key.size = 22;
}

status = btc_digest_input(btc_txn_context, idx, buffer);
ParnikaGupta9 marked this conversation as resolved.
Show resolved Hide resolved
ecdsa_sign_digest(
curve, t_node.private_key, buffer, signatures[idx].bytes, NULL, NULL);
signatures[idx].size = btc_sig_to_script_sig(
Expand Down
1 change: 0 additions & 1 deletion apps/btc_family/btc_txn_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,6 @@ bool btc_digest_input(const btc_txn_context_t *context,
btc_sign_txn_input_script_pub_key_t *script =
&context->inputs[index].script_pub_key;
btc_script_type_e type = btc_get_script_type(script->bytes, script->size);

if (SCRIPT_TYPE_P2WPKH == type) {
// segwit digest calculation; could fail if segwit_cache not filled
status = calculate_p2wpkh_digest(context, index, digest);
Expand Down
Loading
Loading