#36352 psbt: clear Taproot and MuSig2 signatures when joining

ReviewabilityReviewsAgreementSize
#36352 FlashWayne psbt: clear Taproot and MuSig2 signatures when joiningReady1Strong4 + 26 tests
  • Ensure joined PSBTs can be signed and finalized when using Taproot inputs
  • Avoid broken transactions and manual PSBT editing after running joinpsbts
  • Ready to review
  • Strong support with testing verifying stale Taproot and MuSig2 data is dropped on join (fametrano)
  • Confirmed the functional test fails if any of the clearing steps are removed (fametrano)
  • 4 lines added or modified outside tests
  • 26 lines added or modified in tests
  • 0 lines removed in total
  • 2 files, 1 commits
Wallet#18 of 92
P2 · bug fix
  • P2 because it fixes broken Taproot transaction signing and finalization after joining PSBTs
  • Users combining Taproot PSBTs will no longer get incomplete transactions requiring manual PSBT edits
  • Ranking pass: Moved up: grouped with the other PSBT signing/finalization correctness fixes.
Reviewability: ReadyStalePaused
Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets
Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs.
Size: lines added or modified outside tests, then in tests; greener = smaller.

Goal

Clears Taproot and MuSig2 signatures and nonces when joining PSBTs via PartiallySignedTransaction::AddInput. Previously, adding inputs to a joined v0 PSBT dropped legacy and Segwit v0 signatures but left Taproot key-path signatures, script-path signatures, and MuSig2 fields intact. Clearing these fields ensures stale signatures are stripped so subsequent signing steps can generate valid signatures for the new transaction.

Problem: When combining PSBTs with joinpsbts, previous signatures are invalidated because the transaction inputs and outputs change. For Taproot inputs, stale key-path signatures were left in place; because SignTaproot skips signing when a key-path signature is already present, walletprocesspsbt and finalizepsbt fail to complete the joined transaction, requiring manual PSBT editing to recover.

Evidence of importance:

  • PR description: 'a bech32m (P2TR) input: taproot_key_path_sig is still there after the join, and walletprocesspsbt / finalizepsbt return complete: false... the only way out is editing the PSBT by hand.'
  • rpc_psbt.py functional test reproduces the failure on master and verifies that joined Taproot inputs can be successfully signed and completed after the fix.

Risk of a mistake: low (rpc_api, wallet). A mistake could discard valid input fields or fail to properly clear stale signatures during joinpsbts, affecting users combining partially signed transactions.

Changed since the previous assessment: The code and test logic are unchanged across patch versions; the update is an administrative rebase.

Reviewability

Ready

Nothing known that would invalidate a review now.

Waiting on (from the thread read):

  • nothing: no pending items; reviewer accepted fix and reACKed 2026-10-03

Agreement

Strong

substantive support, no open objection (fametrano, fametrano)

Thread notes: fametrano reACKed after confirming the updated test in 4efa6b7d70 passes and properly catches missing clear calls, marking the suggestion accepted.

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
fametrano (contributor)suggestion, correctnessAdd script path signatures, MuSig2 pubnonces, and MuSig2 partial sigs to the test input before joining and assert all four are dropped, so deleting any clear line causes a test failureaccepted · fix pushed · reviewer confirmed the test changes in 4efa6b7d70 pass and fail when any clear line is removedansweredyes2026-10-02: 'The test only checks taproot_key_path_sig, though: it still passes if any one of the other three new clear() lines is deleted. Adding the other three fields to tr_psbt1 before the join ... and checkin'
Status from: 2026-10-03: fametrano: 'Thanks for taking the test. `rpc_psbt.py` passes here.'

Support:

  • fametrano (contributor) (Tested ACK, 2026-10-02) [tested: rpc_psbt.py]: built and ran rpc_psbt.py (passes on branch, fails on master), and verified with joinpsbts directly that all four fields are dropped on the branch and kept on master
  • fametrano (contributor) (Tested ACK, 2026-10-03) [tested: rpc_psbt.py]: rpc_psbt.py passes, and fails without the fix or when any of the four clear() lines is removed

Participants:

  • fametrano (contributor, support, 2 statements 2026-10-02 to 2026-10-03): tested ACK; confirmed test updates in 4efa6b7d70

Files

26 lines under test/bench/ci.

  • test/functional/rpc_psbt.py +26/-0
  • src/psbt.cpp +4/-0

Card

The short text the ranking pass compares across PRs.

Clears Taproot signatures and MuSig2 nonces and partial signatures when joining PSBTs in PartiallySignedTransaction::AddInput. Because joinpsbts constructs a new transaction, pre-existing signatures are invalidated, but stale Taproot signatures were previously retained, causing SignTaproot to skip signing and leaving joined P2TR PSBTs unable to be signed or finalized without manual edits. The PR adds missing field clears for v0 PSBTs and includes functional test coverage verifying that joined Taproot PSBTs can be completed.

Data

dossier JSON · extract JSON · model ledger, generated 2026-10-04T01:18, confidence high, input hash f459e0fe5377668d
thread read through 2026-10-03 (3 statements), head 4efa6b7d70
labels: PSBT

Categories

Wallet

P2 · bug fix (ranking pass: Moved up: grouped with the other PSBT signing/finalization correctness fixes.)

Fixes a bug where joining PSBTs with Taproot inputs leaves stale signatures, causing walletprocesspsbt and finalizepsbt to fail to complete the transaction without manual PSBT editing.

Membership: Modifies PSBT input handling in src/psbt.cpp to fix signing breakage in walletprocesspsbt and finalizepsbt.

Factors: security/stability 0, bug 2, performance 0, user value 2, leverage 0