rpc: Fix internal bug in descriptorprocesspsbt when encountering invalid signatures #33014

pull b-l-u-e wants to merge 1 commits into bitcoin:master from b-l-u-e:fix-32849-descriptorprocesspsbt-internal-bug changing 1 files +3 −2
  1. b-l-u-e commented at 5:15 am on July 19, 2025: none

    Summary

    Fixes #32849 - Replace CHECK_NONFATAL with proper error handling in descriptorprocesspsbt RPC to prevent internal bug assertions when encountering invalid Schnorr signatures.

    Problem

    When descriptorprocesspsbt encounters a PSBT with invalid signatures (e.g., invalid Schnorr signatures with SIGHASH_SINGLE | ANYONECANPAY flags), it triggers an internal bug assertion instead of returning a user-friendly error message.

    Solution

    Replace the CHECK_NONFATAL(FinalizeAndExtractPSBT(psbtx_copy, mtx)) call with proper error handling that throws a JSONRPCError with a clear message.

    Testing

    • Reproduced the bug with Bitcoin Core v29.0.0
    • Verified the fix returns proper error messages instead of crashing
    • Tested with the exact PSBT from the issue report

    Changes

    • src/rpc/rawtransaction.cpp: Replace CHECK_NONFATAL with if-statement and JSONRPCError
  2. DrahtBot added the label RPC/REST/ZMQ on Jul 19, 2025
  3. DrahtBot commented at 5:15 am on July 19, 2025: contributor

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

    Code Coverage & Benchmarks

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

    Reviews

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

  4. achow101 commented at 10:47 pm on July 22, 2025: member

    The CHECK_NONFATAL is correct. complete == true means that the PSBT is complete and can be finalized. The invariant here is that complete == true means FinalizeAndExtract must succeed.

    BIP 174 states that a finalizer must only construct valid scriptSigs and witnesses. We encounter this error because we assume that if a PSBT is finalized, the scriptSigs and witnesses are valid so we are not performing the extra step of verifying the script. However, in this situation, the finalizer has misbehaved and produce invalid scriptSigs or witnesses which causes the assumption to fail.

    This should be resolved by using PSBTInputSignedAndVerified instead. It may even be worth it to combine PSBTInputSigned with PSBTInputSignedAndVerified and replacing PSBTInputSigned wherever it is used. Although that may not be possible to do.

  5. b-l-u-e force-pushed on Jul 24, 2025
  6. b-l-u-e commented at 1:00 pm on July 24, 2025: none

    @achow101…You were right, my initial approach was incorrect. I now understand that CHECK_NONFATAL is correctly protecting the invariant that a PSBT marked as complete must be finalizable.

    The actual bug, as you pointed out, was that the completeness check was too lenient, only checking for the presence of a signature rather than its cryptographic validity.

    After ensuring that the logic first verifies the existing signatures before declaring the PSBT complete (the approach you suggested with PSBTInputSignedAndVerified), the system now behaves as expected. The same invalid PSBT now correctly results in { “complete”: false } instead of triggering the internal bug.

  7. maflcko commented at 1:43 pm on July 24, 2025: member
  8. rpc: Fix descriptorprocesspsbt internal bug on invalid signatures
    rpc: Fix descriptorprocesspsbt internal bug on invalid signatures
    
    Use PSBTInputSignedAndVerified instead of PSBTInputSigned to properly
    validate signatures before marking PSBT as complete.
    507501ddfa
  9. b-l-u-e force-pushed on Jul 24, 2025

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: 2025-08-02 18:13 UTC

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