wallet: Fix FillPSBT failing to sign owned inputs when UTXOs disagree #35747

pull nervana21 wants to merge 2 commits into bitcoin:master from nervana21:fix-fillpsbt changing 4 files +93 −7
  1. nervana21 commented at 4:45 PM on July 19, 2026: contributor

    tl;dr

    Previously, the wallet could fail to sign an intended spend when an input's non_witness_utxo and witness_utxo disagreed. This PR fixes FillPSBT by routing its UTXO-selection logic through GetUTXO.

    Problem

    A PSBT input can carry both a non_witness_utxo and a witness_utxo. GetUTXO prefers a verified non_witness_utxo and does not fall back to witness_utxo when the non_witness_utxo is present but unusable.

    Previously, FillPSBT selected the SigningProvider from the witness_utxo whenever it was set. When the two disagreed, FillPSBT loaded keys for the witness_utxo script while SignPSBTInput signed the non_witness_utxo spend. This could lead to an incomplete input even though the wallet owns the appropriate non_witness_utxo script.

    Fix

    Route FillPSBT through GetUTXO so it shares SignPSBTInput's prefer/reject rule.

    Behavior change

    FillPSBT now uses GetUTXO for script selection, so an input whose non_witness_utxo is present but unusable (out-of-range or txid-mismatched) returns MISSING_INPUTS instead of first selecting a script from witness_utxo.

    SignPSBTInput rejects the same input with MISSING_INPUTS, and FillPSBT already propagates any non-INCOMPLETE error for the remaining ScriptPubKeyMans and inputs. The change is that the failure is detected at script selection rather than after a mistaken key lookup.

    Well-formed PSBTs are unaffected, since witness_utxo and non_witness_utxo resolve to the same script. Txid handling is also tightened in the selection path. A txid-mismatched non_witness_utxo is now rejected by GetUTXO rather than used for script selection when no witness_utxo is present.

    Testing

    fillpsbt_signs_despite_conflicting_witness_utxo covers the regression. psbt2_getutxo pins the GetUTXO prefer/reject rules the fix relies on.

    Follow-up

    SignPSBTInput, PSBTInputSignedAndVerified, and decodepsbt fee totaling still reimplement GetUTXO's logic and risk the same divergence. Refactoring them is left for a follow-up.

  2. test, doc: Pin PSBTInput::GetUTXO prefer rules
    Document and test prefer-non_witness, reject OOB/txid mismatch, and no
    witness fallthrough when fields disagree, before migrating callers.
    a5c3fd0993
  3. DrahtBot added the label Wallet on Jul 19, 2026
  4. DrahtBot commented at 4:45 PM on July 19, 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/35747.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

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

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #32784 (wallet: derivehdkey RPC to get xpub at arbitrary path by Sjors)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  5. DrahtBot added the label CI failed on Jul 19, 2026
  6. DrahtBot commented at 5:45 PM on July 19, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task tidy: https://github.com/bitcoin/bitcoin/actions/runs/29695490423/job/88215409202</sub> <sub>LLM reason (✨ experimental): CI failed because clang-tidy reported a bugprone-argument-comment error (commented argument name mismatch in wallet/test/psbt_wallet_tests.cpp), treated as warnings-as-errors.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  7. wallet: Select FillPSBT SigningProvider via GetUTXO
    Match SignPSBTInput by preferring a verified non_witness_utxo and
    rejecting a bad non_witness_utxo instead of falling back to a
    witness_utxo.
    
    Add a regression test.
    0a13744b73
  8. nervana21 force-pushed on Jul 20, 2026
  9. DrahtBot removed the label CI failed on Jul 20, 2026
Contributors
Labels

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-07-22 09:50 UTC

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