feat(wasm-utxo): implement MuSig2 with BitGo-specific p2tr variant#6
Merged
Conversation
BTC-2652 Co-authored-by: llm-git <llm-git@ttll.de>
Added serde, serde_json, and hex crates to dev-dependencies to enhance test capabilities in the wasm-utxo package. Co-authored-by: llm-git <llm-git@ttll.de> Issue: BTC-2652
Re-export bitcoin from miniscript to support transition to a more general bitcoin package. This provides easier access to the bitcoin module. Issue: BTC-2652 Co-authored-by: llm-git <llm-git@ttll.de>
eb1bfa5 to
4f8dbde
Compare
Add the BIP-327 reference implementation for MuSig2 multi-signature protocol including Python code and test vectors. Issue: BTC-2652 1: https://github.com/bitcoin/bips/blob/ab9d5b8/bip-0327/reference.py Co-authored-by: llm-git <llm-git@ttll.de>
This adds a modified version of BIP-0327 reference implementation to support BitGo's legacy p2tr aggregation method. The implementation adds: 1. Support for x-only pubkeys in key aggregation 2. Legacy p2tr aggregation function that converts to x-only format before sorting 3. Enhanced sign and verify functions to handle both pubkey formats 4. Comprehensive test cases to verify both standard MuSig2 (p2trMusig2) and legacy p2tr behavior Issue: BTC-2652 Co-authored-by: llm-git <llm-git@ttll.de>
Add implementation of BitGo's non-standard variant of MuSig2 key aggregation that uses x-only (32-byte) pubkeys in the hash computation. This differs from the standard BIP327 implementation and is required for compatibility with existing BitGo wallets. BTC-2652 Co-authored-by: llm-git <llm-git@ttll.de>
4f8dbde to
663d0d9
Compare
ppongbitgo
previously approved these changes
Oct 22, 2025
To satisfy the config of the `infra/` repo mostly. It's not a great name. Co-authored-by: llm-git <llm-git@ttll.de>
c79e8b3 to
1abb959
Compare
lcovar
approved these changes
Oct 22, 2025
4 tasks
OttoAllmendinger
added a commit
that referenced
this pull request
Jun 29, 2026
Add a pure-JS prevTx-inclusion policy to @bitgo/wasm-utxo so all
callers share one source of truth for whether a PSBT input needs
non_witness_utxo (full prevTx) or can be signed from witness_utxo-only.
requiresPrevTx(coinName, txFormat, chain) returns false when
witness_utxo-only is sufficient:
- psbt-lite never includes non_witness_utxo;
- segwit/taproot inputs (non-p2sh chains) always use witness_utxo;
- value-committing coins commit the input amount into the sighash, so
prevTx is pointless for signing p2sh inputs even when txFormat is
"psbt":
* Zcash (zec/tzec): ZIP-243 transparent sighash commits the amount.
Including prevTx also crashes wasm-utxo, whose consensus::deserialize
rejects Zcash overwintered transactions.
* BCH family (bch/bcha/eCash, bsv, btg + testnets): replay-protected
BIP-143 sighash (SIGHASH_FORKID, the default for the whole family)
commits the 8-byte value as preimage item #6.
isValueCommittingCoin is backed by a mainnet Set {zec, bch, bcha, bsv,
btg} normalized via getMainnet (covers testnets). isZcashCoin is kept
(selects ZcashBitGoPsbt). isNonSegwitChain checks chain === 0 || 1
literally so the module does not trigger WASM initialization — the
predicate is cheap to evaluate without loading wasm-utxo.
Exported both namespaced (fixedScriptWallet.*) and as top-level named
exports (alongside CoinName/getMainnet).
Refs: T1-3654
OttoAllmendinger
added a commit
that referenced
this pull request
Jun 29, 2026
Add a pure-JS prevTx-inclusion policy to @bitgo/wasm-utxo so all
callers share one source of truth for whether a PSBT input needs
non_witness_utxo (full prevTx) or can be signed from witness_utxo-only.
requiresPrevTx(coinName, txFormat, chain) returns false when
witness_utxo-only is sufficient:
- psbt-lite never includes non_witness_utxo;
- segwit/taproot inputs (non-p2sh chains) always use witness_utxo;
- value-committing coins commit the input amount into the sighash, so
prevTx is pointless for signing p2sh inputs even when txFormat is
"psbt":
* Zcash (zec/tzec): ZIP-243 transparent sighash commits the amount.
Including prevTx also crashes wasm-utxo, whose consensus::deserialize
rejects Zcash overwintered transactions.
* BCH family (bch/bcha/eCash, bsv, btg + testnets): replay-protected
BIP-143 sighash (SIGHASH_FORKID, the default for the whole family)
commits the 8-byte value as preimage item #6.
isValueCommittingCoin is backed by a mainnet Set {zec, bch, bcha, bsv,
btg} normalized via getMainnet (covers testnets). isZcashCoin is kept
(selects ZcashBitGoPsbt). isNonSegwitChain checks chain === 0 || 1
literally so the module does not trigger WASM initialization — the
predicate is cheap to evaluate without loading wasm-utxo.
Exported both namespaced (fixedScriptWallet.*) and as top-level named
exports (alongside CoinName/getMainnet).
Refs: T1-3654
OttoAllmendinger
added a commit
that referenced
this pull request
Jun 29, 2026
Add a pure-JS prevTx-inclusion policy to @bitgo/wasm-utxo so all callers share one source of truth for whether a p2sh PSBT input needs non_witness_utxo (full prevTx) or can be signed from witness_utxo-only. requiresPrevTxForP2sh(coinName) answers only the coin-level question for an input the caller has already determined is p2sh (via isNonSegwitChain) and whose tx format includes prevTx (e.g. "psbt", not "psbt-lite"). It returns false for value-committing coins whose sighash commits the input amount, making prevTx cryptographically pointless for signing p2sh inputs: - Zcash (zec/tzec): ZIP-243 transparent sighash commits the amount. Including prevTx also crashes wasm-utxo, whose consensus::deserialize rejects Zcash overwintered transactions. - BCH family (bch/bcha/eCash, bsv, btg + testnets): replay-protected BIP-143 sighash (SIGHASH_FORKID, the default for the whole family) commits the 8-byte value as preimage item #6. isValueCommittingCoin is backed by a mainnet Set {zec, bch, bcha, bsv, btg} normalized via getMainnet (covers testnets). isNonSegwitChain checks chain === 0 || 1 literally so the module does not trigger WASM initialization — the predicates are cheap to evaluate without loading wasm-utxo. Exported both namespaced (fixedScriptWallet.*) and as top-level named exports (alongside CoinName/getMainnet). Refs: T1-3654
OttoAllmendinger
added a commit
that referenced
this pull request
Jun 29, 2026
Add a pure-JS prevTx-inclusion predicate to @bitgo/wasm-utxo so all callers share one source of truth for whether a p2sh PSBT input needs non_witness_utxo (full prevTx) or can be signed from witness_utxo-only. requiresPrevTxForP2sh(coinName) answers only the coin-level question for an input the caller has already determined is p2sh (non-segwit) and whose tx format includes prevTx (e.g. "psbt", not "psbt-lite"). It returns false for value-committing coins whose sighash commits the input amount, making prevTx cryptographically pointless for signing p2sh inputs: - Zcash (zec/tzec): ZIP-243 transparent sighash commits the amount. Including prevTx also crashes wasm-utxo, whose consensus::deserialize rejects Zcash overwintered transactions. - BCH family (bch/bcha/eCash, bsv, btg + testnets): replay-protected BIP-143 sighash (SIGHASH_FORKID, the default for the whole family) commits the 8-byte value as preimage item #6. The value-committing mainnet set {zec, bch, bcha, bsv, btg} is normalized via getMainnet (covers testnets). The module is pure JS — no WASM initialization — so the predicate is cheap to evaluate without loading wasm-utxo. Exported both namespaced (fixedScriptWallet.requiresPrevTxForP2sh) and as a top-level named export (alongside CoinName/getMainnet). Refs: T1-3654
OttoAllmendinger
added a commit
that referenced
this pull request
Jun 30, 2026
Add a pure-JS prevTx-inclusion predicate to @bitgo/wasm-utxo so all callers share one source of truth for whether a p2sh PSBT input needs non_witness_utxo (full prevTx) or can be signed from witness_utxo-only. requiresPrevTxForP2sh(coinName) answers only the coin-level question for an input the caller has already determined is p2sh (non-segwit) and whose tx format includes prevTx (e.g. "psbt", not "psbt-lite"). It returns false for value-committing coins whose sighash commits the input amount, making prevTx cryptographically pointless for signing p2sh inputs: - Zcash (zec/tzec): ZIP-243 transparent sighash commits the amount. Including prevTx also crashes wasm-utxo, whose consensus::deserialize rejects Zcash overwintered transactions. - BCH family (bch/bcha/eCash, bsv, btg + testnets): replay-protected BIP-143 sighash (SIGHASH_FORKID, the default for the whole family) commits the 8-byte value as preimage item #6. The value-committing mainnets {zec, bch, bcha, bsv, btg} are matched via a switch on getMainnet(coinName), so testnets are covered. The module is pure JS — no WASM initialization — so the predicate is cheap to evaluate without loading wasm-utxo. Exported both namespaced (fixedScriptWallet.requiresPrevTxForP2sh) and as a top-level named export (alongside CoinName/getMainnet). Refs: T1-3654
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.
This PR adds part of the MuSig2 multi-signature protocol implementation with support
for BitGo's legacy p2tr aggregation method.
This enables the generation of the legacy
p2trandp2trMusig2script types in subsequent steps.The implementation includes:
Additional improvements:
Note that this does not include any signing code yet.
Issue: BTC-2652