#36352 psbt: clear Taproot and MuSig2 signatures when joining
| Reviewability | Reviews | Agreement | Size | ||||
|---|---|---|---|---|---|---|---|
| #36352 psbt: clear Taproot and MuSig2 signatures when joining | Ready | 1 | Strong | 4 + 26 tests | |||
|
|
|
|
| |||
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:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| fametrano (contributor) | suggestion, correctness | Add 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 failure | accepted · fix pushed · reviewer confirmed the test changes in 4efa6b7d70 pass and fail when any clear line is removed | answered | yes | 2026-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
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