bip-0375: check test vector signatures in the test runner #2317

pull fametrano wants to merge 7 commits into bitcoin:master from fametrano:bip375-check-signatures-v2 changing 7 files +636 −128
  1. fametrano commented at 8:36 PM on September 29, 2026: contributor

    BIP-375's test runner does not check the signatures in the test vectors, so master's vectors pass although only one of their 43 signatures verifies. This PR adds bip-0375/signatures.py, which the runner applies to every vector. signatures.py checks that each P2PKH, P2WPKH and P2SH-P2WPKH program commits to its input's keys, that a P2SH program commits to its redeem script, that each sighash byte matches PSBT_IN_SIGHASH_TYPE where that field is set, and that each signature verifies. A signature whose sighash cannot be computed, such as one on a segwit v2 input, counts as a failure, not a skip. An input without its spent output, or a P2SH input without its redeem script, is skipped: rejecting such a PSBT is the validator's job, which #2324 makes it do. The validator is unchanged.

    This PR depends on #2316, which fixes the vectors, and contains its three commits; the last three commits are this PR's own. With #2316's vectors the runner reports 44 passed; with master's, 39 of 44 fail. hash160 now uses a copy of bip-0352/ripemd160.py, because hashlib lacks RIPEMD-160 on some systems, as #1616 found for BIP-352. The version is the 0.1.5 that #2316 sets, and the last commit adds this PR's line to its changelog entry; 0.1.6 is #2324's, and whichever of #2316 and #2324 lands second rebases its version if needed.

    Made with my usual tools: a computer, the Internet and an LLM. The mistakes, as usual, are all mine.

  2. jonatack added the label Fixups on Oct 18, 2026
  3. fametrano force-pushed on Oct 25, 2026
  4. fametrano force-pushed on Nov 4, 2026
  5. fametrano force-pushed on Nov 5, 2026
  6. jonatack commented at 4:43 PM on November 9, 2026: member

    LGTM

    Companion PR #2316 seems to be a dependency for this one and should go in first.

  7. jonatack added the label Tests on Nov 9, 2026
  8. jonatack removed the label Fixups on Nov 9, 2026
  9. jonatack added the label Pending acceptance on Nov 9, 2026
  10. jonatack commented at 4:46 PM on November 9, 2026: member
  11. fametrano force-pushed on Nov 10, 2026
  12. bip-0375: fix P2WPKH scriptPubKeys and signatures in test vectors
    Except in the In Progress vector added in 0.1.4, the P2WPKH inputs of
    the test vectors spend a witness program equal to SHA256(pubkey)[:20]
    instead of HASH160(pubkey), so the key each input carries cannot spend
    it. None of the other vectors' ECDSA signatures verifies against the
    transaction its PSBT describes, whatever the input type. The reference
    validator does not check signatures, so no test fails.
    
    Set every P2WPKH witness program to HASH160 of the input's public key,
    in PSBT_IN_WITNESS_UTXO and in the supplementary witness_utxo and
    prevout_scriptpubkey. Re-sign the PSBT_IN_PARTIAL_SIG signatures
    deterministically (RFC 6979, low S): BIP 143 for P2WPKH and P2SH-P2WPKH,
    the legacy signature hash for P2PKH. Where an input sets
    PSBT_IN_SIGHASH_TYPE, its signature uses that type, as BIP 174
    requires.
    
    Two vectors carried a signature with no defined signature hash: one on
    a segwit v2 input, one in the vector whose output lacks PSBT_OUT_SCRIPT.
    Remove both signatures, and mark the segwit v2 input as not signed in
    the supplementary material. Both vectors still fail for their stated
    reason.
    
    Inside the PSBTs only PSBT_IN_WITNESS_UTXO and PSBT_IN_PARTIAL_SIG
    change, and the test runner's result for every vector is unchanged.
    4e1e6e5505
  13. bip-0375: drop the segwit v2 signature from the non-witness UTXO vector
    No signature hash is defined for segwit v2. The previous commit removed
    the same signature from the other segwit v2 vector. The validator still
    rejects the input for its segwit version.
    1d9b85daf3
  14. bip-0375: add 0.1.5 changelog for P2WPKH test vector fix 37c30cf98b
  15. bip-0375: check test vector signatures in the test runner
    The validator does not read PSBT_IN_PARTIAL_SIG. Nothing checks that a
    P2PKH, P2WPKH or P2SH-P2WPKH program commits to its signing key. So the
    wrong programs and signatures that the parent commit corrects pass the
    test runner.
    
    Add signatures.py. The test runner applies it to every vector. It
    checks that:
    - a single-key program commits to the keys in PSBT_IN_PARTIAL_SIG and
      PSBT_IN_BIP32_DERIVATION;
    - a P2SH program commits to PSBT_IN_REDEEM_SCRIPT;
    - a signature's sighash byte equals PSBT_IN_SIGHASH_TYPE, if set;
    - each signature verifies: BIP 143 for P2WPKH and P2SH-P2WPKH, the
      legacy sighash for P2PKH and bare scripts.
    
    A signature the check cannot verify is a failure. The validator is
    unchanged.
    
    hash160 uses the pure Python RIPEMD-160 from bip-0352. hashlib lacks
    RIPEMD-160 on some OpenSSL builds.
    58d00a2d2e
  16. bip-0375: skip inputs without spent output or redeem script in signature checks
    An input whose PSBT lacks its spent output, or a P2SH input without
    PSBT_IN_REDEEM_SCRIPT, gives no signature hash to check against. Such a
    PSBT is malformed, and rejecting it is the validator's job, so the
    signature check skips the input instead of failing the vector.
    8fd2ce1929
  17. bip-0375: add signature check to 0.1.5 changelog 80cd3ba85b
  18. fametrano force-pushed on Nov 11, 2026
  19. agammann commented at 5:48 AM on November 11, 2026: none

    check_partial_signatures is new verification logic, but this PR only exercises it against the corrected vector set. Could you add a focused negative test that flips a byte in a known-valid PSBT_IN_PARTIAL_SIG and asserts the helper reports a failure? That would make the regression fail if the runner accidentally stops validating signatures while all existing vectors continue to pass.

  20. bip-0375: test that the runner rejects a tampered signature
    The existing vectors only show that valid signatures pass. If the
    signature check stopped verifying, every vector would still pass.
    
    Flip the low bit of the last byte of s in the first PSBT_IN_PARTIAL_SIG
    of the valid vectors, keeping the DER encoding and sighash byte valid,
    and require check_partial_signatures to report a failure.
    2f0e788402
  21. fametrano commented at 11:25 PM on November 11, 2026: contributor

    Added in 2f0e788: the runner now flips one bit of s in the first valid PSBT_IN_PARTIAL_SIG and requires check_partial_signatures to report it. With verification stubbed out, that test fails while every vector still passes.

  22. agammann commented at 6:34 PM on November 12, 2026: none

    Thanks for adding the negative test. I rechecked 2f0e788: it flips a bit in the signature scalar and expects verification to fail, addressing the tampered-signature case I requested. I reviewed the diff but did not run the test locally. AI-assisted review.


github-metadata-mirror

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

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