Skip to content

Handle p2tr key-spend weights in payjoin-cli - #1970

Merged
benalleng merged 2 commits into
payjoin:masterfrom
benalleng:handle-p2tr-weights
Oct 14, 2026
Merged

benalleng merged 2 commits into
payjoin:masterfrom
benalleng:handle-p2tr-weights

Conversation

@benalleng

@benalleng benalleng commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

This handles a bug that prevented taproot coins from being properly handled by the payjoin-cli. Previously attempted in #1600

Namely this prevents the panic when list_unspent reaches a taprrot coin. Taproot script-path spends remain unsupported.

This is a breaking change but it does not affect the db so I'm not sure if this should be treated as something we should wait on or ok to include in a minor version bump.

This is related to #1959 in that this similarly handles Taproot inputs via InputPair::new_p2tr_keyspend but this obviously only touches the cli and does not add any additional logic for the other script types.

Assigning @chavic since you have just touched all these typed methods for the ffi

Coded with GLM-5.3

Pull Request Checklist

Please confirm the following before requesting review:

@benalleng benalleng changed the title Handle p2tr key-spend weights Handle p2tr key-spend weights in payjoin-cli Oct 12, 2026
@coveralls

coveralls commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 38309675529

Coverage decreased (-0.02%) to 87.475%

Details

  • Coverage decreased (-0.02%) from the base build.
  • Patch coverage: 5 uncovered changes across 1 file (20 of 25 lines covered, 80.0%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
payjoin-cli/src/app/wallet.rs 25 20 80.0%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 17860
Covered Lines: 15623
Line Coverage: 87.47%
Coverage Strength: 319.52 hits per line

💛 - Coveralls

This handles a bug that prevented taproot coins from being properly
handled by the payjoin-cli.

Namely this prevents the panic when `list_unspent` reaches a taprrot
coin. Taproot script-path spends remain unsupported.
@benalleng
benalleng force-pushed the handle-p2tr-weights branch from e96f17f to 03f1ddb Compare October 12, 2026 18:44
@ValeraFinebits

Copy link
Copy Markdown
Contributor

@benalleng One follow-up question about mixed UTXO sets: native P2WSH coins still reach InputPair::new(txin, psbtin, None) without a witness or an explicit input weight. It looks like one such coin would make list_unspent() fail even when usable P2WPKH/P2TR candidates are available.

Is failing the whole candidate list the intended behavior, or would it make sense to track skipping known unsupported receiver UTXOs in a separate issue?

@benalleng

benalleng commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

Thats a good point. I only thought of p2tr for this as one of my regtest wallets has a taproot coin that kept causing failures when trying to do payjoins but we should probably add a fix for these. I will look and perhaps this is actually the appropriate place for that after all rather than a separate issue.

@benalleng

Copy link
Copy Markdown
Collaborator Author

@ValeraFinebits Take a look at 8c81e1e I think this is the most minimal commit that still allows for us to simply add support for the typed InputPair methods in the future essentially pulling them into the "supported" list one at a time.

Currently P2WSH and P2SH or some custom script is not able to be
properly measured by `InputPair` and as a result `list_unspent` will
fail blocking the whole wallet instead of the unsupported coins.

By filtering those coins out of the available list we can still
optimistically proceed and avoid any unsupported coins moving on to ones
that we can use for a payjoin.
@benalleng
benalleng force-pushed the handle-p2tr-weights branch from 8c81e1e to 3989c82 Compare October 12, 2026 21:17

@codaMW codaMW left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tACK 3989c828

Reviewed against master and verified the fix end-to-end on regtest.

The bug: on master, input_pair_from_corepc builds every input via InputPair::new(txin, psbtin, None).expect("Input pair should be valid"). For a P2TR input, expected_input_weight() returns Err(NotSupported) (taproot weight can't be predicted from the witness_utxo alone), and with no weight hint InputPair::new returns that Err, so the .expect panics. Any wallet holding a taproot UTXO crashes the receiver when it builds candidate inputs.

The fix routes is_p2tr() inputs to InputPair::new_p2tr_keyspend, which supplies P2TR_KEY_DEFAULT_SIGHASH as the predicted weight: the canonical rust-bitcoin value for a key-path spend (64-byte sig, no annex). Non-predictable non-p2tr scripts (P2WSH, legacy, bare) now return Err and are skipped with a warning instead of panicking, and redeem_script is populated from the UTXO for P2SH-wrapped inputs. The CHANGELOG entry is present and accurate.

Verified locally (nightly-2026-09-28):

  • End-to-end: patched send_receive_payjoin_v1 to fund the receiver with AddressType::Bech32m (taproot) and ran it on this branch. Result: test e2e::send_receive_payjoin_v1 ... ok. The receiver contributes its taproot input and the v1 payjoin completes (real TXID). On master the same taproot-funded receiver crashes in input_pair_from_corepc, hanging the harness rather than failing cleanly, consistent with the root cause above.
  • cargo test -p payjoin --all-features p2tr -> 2 passed (the new_p2tr_keyspend API the fix relies on).
  • cargo build -p payjoin-cli --all-features -> clean.

One non-blocking question: with the skip-on-error behavior, a wallet whose UTXOs are all unsupported now yields an empty candidate-input list instead of panicking. That's better than a crash, but does the caller surface a clear "no usable inputs" message, or could it fail opaquely later? Just checking the degraded path stays legible.


Review drafted with AI assistance; I ran the e2e repro and tests myself and verified the root cause against the source.

@ValeraFinebits

Copy link
Copy Markdown
Contributor

@ValeraFinebits Take a look at 8c81e1e I think this is the most minimal commit that still allows for us to simply add support for the typed methods in the future essentially pulling them into the "supported" list one at a time.InputPair

Thanks, this covers the mixed-UTXO case I meant.

@DanGould DanGould left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 3989c82

@chavic chavic left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tACK

@benalleng
benalleng merged commit a0f7598 into payjoin:master Oct 14, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants