bip352: verify redeem script and pubkey hash in GetPubKeyFromInput #36417

pull Yudis-bit wants to merge 1 commits into bitcoin:master from Yudis-bit:bip352-verify-redeem-script changing 2 files +106 −3
  1. Yudis-bit commented at 1:56 PM on October 2, 2026: none

    In GetPubKeyFromInput(), evaluating TxoutType::SCRIPTHASH (P2SH-P2WPKH) inputs runs EvalScript under SCRIPT_VERIFY_NONE and passes the resulting redeem script to Solver(redeem, solutions). Because Solver clears the passed solutions vector, the 20-byte script hash originally extracted from the UTXO's scriptPubKey is erased without checking that Hash160(redeem) matches it. Consequently, spending an arbitrary P2SH UTXO (such as a multisig or timelock) with a scriptSig that pushes a valid P2WPKH redeem script causes an unintended public key to be extracted and summed into A_sum, silently corrupting the Silent Payments input hash and derived shared secret.

    Additionally, GetPubKeyFromInput() previously accepted malleated or non-standard witness stacks and scriptSigs by grabbing stack.back() without enforcing the BIP-16 push-only requirement (!txin.scriptSig.IsPushOnly()), the BIP-141 single-element redeem script constraint (stack.size() == 1), the standard two-element P2WPKH witness stack depth (txin.scriptWitness.stack.size() == 2), or verifying that the extracted compressed public key actually hashes to the target witness program (Hash160(key) == solutions[0]).

    This change preserves the expected 20-byte script hash prior to solver invocation, enforces BIP-16 push-only and single-element constraints, verifies both redeem script and witness pubkey preimage hashes, and validates exact witness stack depths for both native P2WPKH and P2SH-P2WPKH inputs. Targeted unit test coverage in src/test/bip352_tests.cpp verifies rejection of redeem script mismatches, non-push opcodes, multi-push scriptSigs, pubkey hash mismatches, uncompressed keys, and invalid stack sizes.

  2. Yudis-bit requested review from Copilot on Oct 2, 2026
  3. Copilot commented at 1:56 PM on October 2, 2026: none

    Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

  4. DrahtBot commented at 1:56 PM on October 2, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    External sites

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    Concept ACK w0xlt

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    No conflicts as of last run.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  5. Yudis-bit force-pushed on Oct 6, 2026
  6. DrahtBot added the label Needs rebase on Oct 7, 2026
  7. Yudis-bit force-pushed on Oct 7, 2026
  8. DrahtBot removed the label Needs rebase on Oct 7, 2026
  9. bip352: verify redeem script, push-only scriptSig, and pubkey hash in GetPubKeyFromInput
    In GetPubKeyFromInput, evaluating TxoutType::SCRIPTHASH (P2SH-P2WPKH) inputs
    runs EvalScript under SCRIPT_VERIFY_NONE and passes the resulting redeem script
    to Solver(redeem, solutions). However, Solver immediately clears the solutions
    vector, discarding the original 20-byte script hash from the UTXO's scriptPubKey
    without checking that Hash160(redeem) matches it.
    
    As a result, any non-P2WPKH P2SH UTXO (such as multisig or timelock) spent by an input
    whose scriptSig pushes a valid P2WPKH redeem script is mistakenly treated as an
    eligible BIP-352 input, causing an unintended pubkey to be extracted and summed into
    A_sum, which silently corrupts the derived input_hash and shared secret.
    
    Additionally, GetPubKeyFromInput did not enforce the BIP-16 push-only constraint
    (!txin.scriptSig.IsPushOnly()), the BIP-141 single-element redeem script constraint
    (stack.size() == 1), standard two-element P2WPKH witness stack depths
    (txin.scriptWitness.stack.size() == 2), or that the extracted compressed public key
    hashes to the witness program (Hash160(key) == solutions[0]).
    
    Preserve the expected script hash before Solver runs, enforce BIP-16 push-only and
    single-element constraints, verify both redeem script and witness pubkey preimage hashes,
    and validate exact witness stack depths for both native P2WPKH and P2SH-P2WPKH inputs.
    Targeted unit tests in src/test/bip352_tests.cpp cover redeem script mismatches,
    non-push opcodes, multi-push scriptSigs, pubkey hash mismatches, uncompressed keys,
    and invalid stack sizes.
    d48b8af83a
  10. Yudis-bit force-pushed on Oct 8, 2026
  11. w0xlt commented at 5:53 PM on October 8, 2026: contributor

    Concept ACK


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-10-09 00:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me