psbt: verify final scripts in FinalizePSBT #36343

pull Bruce039 wants to merge 1 commits into bitcoin:master from Bruce039:fix-finalizepsbt-verify-final changing 2 files +31 −1
  1. Bruce039 commented at 9:55 AM on September 26, 2026: none

    finalizepsbt can return complete: true and a hex for a PSBT whose PSBT_IN_FINAL_SCRIPTWITNESS (or final scriptSig) is invalid.

    FinalizePSBT counts an input as complete when SignPSBTInput succeeds. If the input already has final fields, PSBTInput::FillSignatureData marks the sigdata complete and ProduceSignature returns true early (sign.cpp:752), before the script is verified. So the existing final fields are trusted as-is.

    To reproduce, take a signed P2WPKH v0 PSBT that has a non_witness_utxo and flip one bit of the signature inside the final witness:

    • finalizepsbt returns complete: true and a hex
    • analyzepsbt says the input is not final, next: finalizer
    • testmempoolaccept on the hex fails with mempool-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation)

    Inputs that only have a witness_utxo already come out incomplete because of the require_witness_sig check, so this affects inputs with a non_witness_utxo.

    #30357 fixed the same problem in FillPSBT by checking PSBTInputSignedAndVerified, and #33014 did it for descriptorprocesspsbt. This does the same in FinalizePSBT. Taproot verification needs every spent output. If one is missing, that input already fails in SignPSBTInput with MISSING_INPUTS and makes the PSBT incomplete, so the extra check doesn't change the result in that case.

    The new test in rpc_psbt.py builds that PSBT and checks that finalizepsbt returns complete: false with no hex. It fails on master and passes with the fix. wallet_musig.py and the psbt_wallet_tests / script_tests unit tests still pass.

    One behaviour change: a final script that is valid by consensus but non-standard now gives complete: false. FillPSBT and descriptorprocesspsbt already behave that way, since they check with the same standard flags.

  2. DrahtBot added the label PSBT on Sep 26, 2026
  3. DrahtBot commented at 9:55 AM on September 26, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/36343.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process. A summary of reviews will appear here.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  4. psbt: verify final scripts in FinalizePSBT
    FinalizePSBT counts an input as complete whenever SignPSBTInput succeeds.
    For an input that already has final_script_sig/final_script_witness,
    FillSignatureData marks the signature data complete and ProduceSignature
    returns true before running its script check, so the existing final
    fields are never verified. finalizepsbt then returns complete=true and a
    hex that is rejected by the mempool, while analyzepsbt reports the same
    input as not final.
    
    #30357 fixed this for FillPSBT by using PSBTInputSignedAndVerified. Do
    the same in FinalizePSBT.
    417a548cf2
  5. Bruce039 force-pushed on Sep 26, 2026
  6. DrahtBot added the label CI failed on Sep 26, 2026
  7. DrahtBot removed the label CI failed on Sep 26, 2026

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-09-28 10:51 UTC

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