fix(wasm-utxo): infer input script type in fromPsbt with nonstandard derivations - #361
Merged
Merged
Conversation
OttoAllmendinger
force-pushed
the
otto/WCN-2155-infer-input-script-type
branch
10 times, most recently
from
August 18, 2026 10:12
cd6e72f to
f294161
Compare
…erivations Dimensions.fromPsbt classifies inputs using BIP32 derivation chain codes, falling back to P2shP2pk when no standard BitGo chain is found. PSBTs with nonstandard chain codes on valid P2WSH 2-of-3 multisig inputs cause misclassification as non-segwit P2shP2pk. This inflates vsize ~2.5x, understates feeRate, and triggers maxfeerate broadcast rejections (WCN-2155). This test asserts the current (buggy) behavior: a P2WSH PSBT built with nonstandard chain codes (0/1 instead of 20/21) via the WrapPsbt/descriptor API is classified as non-segwit P2shP2pk, producing a larger vsize than the equivalent wallet-built PSBT. Also asserts the P2shP2pk fallback for replay-protection inputs without derivations. Refs: WCN-2155
…ard derivations Dimensions.from_psbt unconditionally classified inputs lacking BIP32 derivation paths as P2shP2pk (replay protection), regardless of the actual script type. For P2WSH PSBTs with nonstandard derivation paths this inflated vsize ~2.5x, understating feeRate and triggering maxfeerate broadcast rejections (WCN-2155). Replace the entire classification path with a single call to infer_input_script_type for every input. Classification is now based solely on script metadata: witness_script (verified as 2-of-3 multisig via parse_multisig_script_2_of_3) → P2wsh/P2shP2wsh; redeem_script (P2PK via parse_p2pk_script, or 2-of-3 multisig) → P2shP2pk/P2sh; taproot metadata (tap_scripts/tap_internal_key) → P2trMusig2 variants; is_p2mr output → P2mr. Every candidate is cross-checked against the output-script shape; mismatches and bare inputs (only witness_utxo) error rather than guessing. The old BIP32 derivation-chain-code path is removed entirely — script metadata is sufficient and more authoritative. The P2shP2pk default fallback is gone; replay protection inputs are now correctly detected via their P2PK redeem_script. Refs: WCN-2155
OttoAllmendinger
force-pushed
the
otto/WCN-2155-infer-input-script-type
branch
from
August 18, 2026 10:15
f294161 to
5499ca0
Compare
OttoAllmendinger
marked this pull request as ready for review
August 18, 2026 10:30
davidkaplanbitgo
approved these changes
Aug 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Dimensions.from_psbtclassified inputs based on BIP32 derivation chain codes, falling back toP2shP2pk(replay protection) when no standard BitGo chain was found. For P2WSH PSBTs with nonstandard derivation paths this inflated vsize ~2.5x, understatingfeeRate, triggeringmaxfeeratebroadcast rejections (WCN-2155).Replace the entire classification path with a single call to
infer_input_script_typefor every input. Classification is now based solely on script metadata (witness_script, redeem_script, taproot fields, output-script shape), independent of BIP32 derivation chain codes.Changes
psbt_wallet_input.rs— Addinfer_input_script_type, which classifies from script/witness metadata: witness_script (verified as 2-of-3 multisig) → P2wsh/P2shP2wsh; redeem_script (P2PK or 2-of-3 multisig) → P2shP2pk/P2sh; taproot metadata → P2trMusig2 variants; is_p2mr output → P2mr. Every candidate is cross-checked against the output-script shape. Errors on bare inputs (only witness_utxo) or shape mismatches.dimensions.rs— Replace the entirefrom_psbtinput classification loop with a call toinfer_input_script_type. The old BIP32 derivation-chain-code path and P2shP2pk default fallback are removed.address/mod.rs— Re-exportis_p2mraspub(crate)for P2MR (BIP-360) detection.test/dimensions.ts— Red test (commit 1) reproduces the bug with nonstandard derivation paths via the WrapPsbt/descriptor API; fix commit flips assertions to green and adds a replay-protection test case.Refs: WCN-2155