From 42945f4a96eab3f73211e2704faaa0823b81e97f Mon Sep 17 00:00:00 2001 From: Otto Allmendinger Date: Wed, 17 Dec 2025 11:07:08 +0100 Subject: [PATCH 1/4] docs(wasm-utxo): update feature matrix in README.md Mark FixedScript Wallet Transaction Support for Bitcoin and Litecoin as complete in the feature status table. Issue: BTC-2656 Co-authored-by: llm-git --- packages/wasm-utxo/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wasm-utxo/README.md b/packages/wasm-utxo/README.md index 249196f..f4997ba 100644 --- a/packages/wasm-utxo/README.md +++ b/packages/wasm-utxo/README.md @@ -20,7 +20,7 @@ This project is under active development. | Descriptor Wallet: Address Support | βœ… Complete | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | | Descriptor Wallet: Transaction Support | βœ… Complete | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | | FixedScript Wallet: Address Generation | βœ… Complete | βœ… Complete | βœ… Complete | βœ… Complete | βœ… Complete | βœ… Complete | βœ… Complete | -| FixedScript Wallet: Transaction Support | ⏳ TODO | ⏳ TODO | ⏳ TODO | ⏳ TODO | ⏳ TODO | ⏳ TODO | ⏳ TODO | +| FixedScript Wallet: Transaction Support | βœ… Complete | ⏳ TODO | ⏳ TODO | ⏳ TODO | ⏳ TODO | βœ… Complete | ⏳ TODO | ## Building From 059165850ccc709434600ca1124db5beed2598ed Mon Sep 17 00:00:00 2001 From: Otto Allmendinger Date: Wed, 17 Dec 2025 11:06:08 +0100 Subject: [PATCH 2/4] feat(wasm-utxo): add BCH fork ID support for BCH, XEC, BSV, BTG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement fork ID support for Bitcoin Cash-style networks to enable proper signing and verification. This includes: - Use fork ID-aware signing for BCH (0), BTG (79), XEC (0), and BSV (0) - Update miniscript dependency to use forkid-compatible version - Modify PSBT functions to use the appropriate sighash algorithm - Ensure replay protection inputs use correct sighash calculation - Add tests to verify signβ†’verify roundtrip works correctly Issue: BTC-2656 Co-authored-by: llm-git --- packages/wasm-utxo/Cargo.lock | 5 +- packages/wasm-utxo/Cargo.toml | 2 +- packages/wasm-utxo/cli/Cargo.toml | 2 +- .../src/fixed_script_wallet/bitgo_psbt/mod.rs | 236 ++++++++++++++---- .../bitgo_psbt/psbt_wallet_input.rs | 19 +- 5 files changed, 206 insertions(+), 58 deletions(-) diff --git a/packages/wasm-utxo/Cargo.lock b/packages/wasm-utxo/Cargo.lock index 2f38a12..0957a53 100644 --- a/packages/wasm-utxo/Cargo.lock +++ b/packages/wasm-utxo/Cargo.lock @@ -157,8 +157,7 @@ checksum = "32637268377fc7b10a8c6d51de3e7fba1ce5dd371a96e342b34e6078db558e7f" [[package]] name = "bitcoin" version = "0.32.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e499f9fc0407f50fe98af744ab44fa67d409f76b6772e1689ec8485eb0c0f66" +source = "git+https://github.com/BitGo/rust-bitcoin?tag=bitcoin-0.32.8-forkid#e1eb843a5f5f28ed7a229bcca59cff44719bbcc1" dependencies = [ "base58ck", "bech32", @@ -779,7 +778,7 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniscript" version = "13.0.0" -source = "git+https://github.com/BitGo/rust-miniscript?tag=miniscript-13.0.0-opdrop#970feb88f5ceae6b1bf4253b77dbeaf0f2e2d7ce" +source = "git+https://github.com/BitGo/rust-miniscript?tag=miniscript-13.0.0-opdrop-forkid#13eccd8bdb83af1a9b63118ceac962aed49906a5" dependencies = [ "bech32", "bitcoin", diff --git a/packages/wasm-utxo/Cargo.toml b/packages/wasm-utxo/Cargo.toml index 703fd6f..ba37948 100644 --- a/packages/wasm-utxo/Cargo.toml +++ b/packages/wasm-utxo/Cargo.toml @@ -16,7 +16,7 @@ all = "warn" [dependencies] wasm-bindgen = "0.2" js-sys = "0.3" -miniscript = { git = "https://github.com/BitGo/rust-miniscript", tag = "miniscript-13.0.0-opdrop" } +miniscript = { git = "https://github.com/BitGo/rust-miniscript", tag = "miniscript-13.0.0-opdrop-forkid" } bech32 = "0.11" musig2 = { version = "0.3.1", default-features = false, features = ["k256"] } getrandom = { version = "0.2", features = ["js"] } diff --git a/packages/wasm-utxo/cli/Cargo.toml b/packages/wasm-utxo/cli/Cargo.toml index 08b6e43..0b95766 100644 --- a/packages/wasm-utxo/cli/Cargo.toml +++ b/packages/wasm-utxo/cli/Cargo.toml @@ -16,6 +16,6 @@ base64 = "0.21" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" num-bigint = "0.4" -bitcoin = "0.32" +bitcoin = { git = "https://github.com/BitGo/rust-bitcoin", tag = "bitcoin-0.32.8-forkid" } colored = "2.1" ptree = "0.5" diff --git a/packages/wasm-utxo/src/fixed_script_wallet/bitgo_psbt/mod.rs b/packages/wasm-utxo/src/fixed_script_wallet/bitgo_psbt/mod.rs index 95f8895..e2baf68 100644 --- a/packages/wasm-utxo/src/fixed_script_wallet/bitgo_psbt/mod.rs +++ b/packages/wasm-utxo/src/fixed_script_wallet/bitgo_psbt/mod.rs @@ -314,7 +314,7 @@ impl BitGoPsbt { use miniscript::psbt::PsbtExt; match self { - BitGoPsbt::BitcoinLike(ref mut psbt, _network) => { + BitGoPsbt::BitcoinLike(ref mut psbt, network) => { // Use custom bitgo p2trMusig2 input finalization for MuSig2 inputs if p2tr_musig2_input::Musig2Input::is_musig2_input(&psbt.inputs[input_index]) { let mut ctx = p2tr_musig2_input::Musig2Context::new(psbt, input_index) @@ -322,8 +322,16 @@ impl BitGoPsbt { ctx.finalize_input(secp).map_err(|e| e.to_string())?; return Ok(()); } - // other inputs can be finalized using the standard miniscript::psbt::finalize_input - psbt.finalize_inp_mut(secp, input_index) + + // Check if this network uses SIGHASH_FORKID (BCH, BTG, XEC, BSV) + let fork_id = match network.mainnet() { + Network::BitcoinCash | Network::Ecash | Network::BitcoinSV => Some(0u32), + Network::BitcoinGold => Some(79u32), + _ => None, + }; + + // Finalize with fork_id support for FORKID networks + psbt.finalize_inp_mut_with_fork_id(secp, input_index, fork_id) .map_err(|e| e.to_string())?; Ok(()) } @@ -589,19 +597,56 @@ impl BitGoPsbt { ); } - // Sign the replay protection input with legacy P2SH sighash - let sighash_type = miniscript::bitcoin::sighash::EcdsaSighashType::All; - let cache = SighashCache::new(&psbt.unsigned_tx); - let sighash = cache - .legacy_signature_hash(input_index, redeem_script, sighash_type.to_u32()) - .map_err(|e| format!("Failed to compute sighash: {}", e))?; + // Check if this network uses SIGHASH_FORKID (BCH-style networks) + let fork_id = match network.mainnet() { + Network::BitcoinCash | Network::Ecash | Network::BitcoinSV => Some(0u32), + Network::BitcoinGold => Some(79u32), + _ => None, + }; + + // Get input value for BIP143-style sighash (required for FORKID) + let input = &psbt.inputs[input_index]; + let prevout = psbt.unsigned_tx.input[input_index].previous_output; + let value = psbt_wallet_input::get_output_script_and_value(input, prevout) + .map(|(_, v)| v) + .unwrap_or(miniscript::bitcoin::Amount::ZERO); + + // Compute sighash based on network type + let mut cache = SighashCache::new(&psbt.unsigned_tx); + let (message, sighash_type_u32) = if let Some(fork_id) = fork_id { + // BCH-style BIP143 sighash with FORKID + // SIGHASH_ALL | SIGHASH_FORKID = 0x01 | 0x40 = 0x41 + let sighash_type = 0x41u32; + let sighash = cache + .p2wsh_signature_hash_forkid( + input_index, + redeem_script, + value, + sighash_type, + Some(fork_id), + ) + .map_err(|e| format!("Failed to compute FORKID sighash: {}", e))?; + ( + secp256k1::Message::from_digest(sighash.to_byte_array()), + sighash_type, + ) + } else { + // Legacy P2SH sighash for standard Bitcoin + let sighash_type = miniscript::bitcoin::sighash::EcdsaSighashType::All; + let sighash = cache + .legacy_signature_hash(input_index, redeem_script, sighash_type.to_u32()) + .map_err(|e| format!("Failed to compute sighash: {}", e))?; + ( + secp256k1::Message::from_digest(sighash.to_byte_array()), + sighash_type.to_u32(), + ) + }; // Create ECDSA signature - let message = secp256k1::Message::from_digest(sighash.to_byte_array()); let signature = secp.sign_ecdsa(&message, privkey); let ecdsa_sig = EcdsaSignature { signature, - sighash_type, + sighash_type: sighash_type_u32, }; // Add signature to partial_sigs @@ -688,7 +733,18 @@ impl BitGoPsbt { K: miniscript::bitcoin::psbt::GetKey, { match self { - BitGoPsbt::BitcoinLike(ref mut psbt, _network) => psbt.sign(k, secp), + BitGoPsbt::BitcoinLike(ref mut psbt, network) => { + // Check if this network uses SIGHASH_FORKID + // BCH, XEC, BSV: fork_id = 0 + // BTG: fork_id = 79 + match network.mainnet() { + Network::BitcoinCash | Network::Ecash | Network::BitcoinSV => { + psbt.sign_forkid(k, secp, 0) + } + Network::BitcoinGold => psbt.sign_forkid(k, secp, 79), + _ => psbt.sign(k, secp), + } + } BitGoPsbt::Zcash(_zcash_psbt, _network) => { // Return an error indicating Zcash signing is not implemented Err(( @@ -911,6 +967,7 @@ impl BitGoPsbt { use miniscript::bitcoin::{hashes::Hash, sighash::SighashCache}; let psbt = self.psbt(); + let network = self.network(); // Check input index bounds if input_index >= psbt.inputs.len() { @@ -920,10 +977,9 @@ impl BitGoPsbt { let input = &psbt.inputs[input_index]; let prevout = psbt.unsigned_tx.input[input_index].previous_output; - // Get output script from input - let (output_script, _value) = - psbt_wallet_input::get_output_script_and_value(input, prevout) - .map_err(|e| format!("Failed to get output script: {}", e))?; + // Get output script and value from input + let (output_script, value) = psbt_wallet_input::get_output_script_and_value(input, prevout) + .map_err(|e| format!("Failed to get output script: {}", e))?; // Verify this is a replay protection input if !replay_protection.is_replay_protection_input(output_script) { @@ -951,14 +1007,37 @@ impl BitGoPsbt { return Ok(false); }; - // Compute legacy P2SH sighash - let cache = SighashCache::new(&psbt.unsigned_tx); - let sighash = cache - .legacy_signature_hash(input_index, redeem_script, ecdsa_sig.sighash_type.to_u32()) - .map_err(|e| format!("Failed to compute sighash: {}", e))?; + // Check if this network uses SIGHASH_FORKID + let fork_id = match network.mainnet() { + Network::BitcoinCash | Network::Ecash | Network::BitcoinSV => Some(0u32), + Network::BitcoinGold => Some(79u32), + _ => None, + }; + + // Compute sighash based on network type + let mut cache = SighashCache::new(&psbt.unsigned_tx); + let message = if let Some(fork_id) = fork_id { + // BCH-style BIP143 sighash with FORKID + // Use p2wsh_signature_hash_forkid which handles the forkid encoding + let sighash = cache + .p2wsh_signature_hash_forkid( + input_index, + redeem_script, + value, + ecdsa_sig.sighash_type as u32, + Some(fork_id), + ) + .map_err(|e| format!("Failed to compute FORKID sighash: {}", e))?; + secp256k1::Message::from_digest(sighash.to_byte_array()) + } else { + // Legacy P2SH sighash for standard Bitcoin + let sighash = cache + .legacy_signature_hash(input_index, redeem_script, ecdsa_sig.sighash_type) + .map_err(|e| format!("Failed to compute sighash: {}", e))?; + secp256k1::Message::from_digest(sighash.to_byte_array()) + }; - // Verify the signature using the bitcoin crate's built-in verification - let message = secp256k1::Message::from_digest(sighash.to_byte_array()); + // Verify the signature match secp.verify_ecdsa(&message, &ecdsa_sig.signature, &public_key.inner) { Ok(()) => Ok(true), Err(_) => Ok(false), @@ -986,6 +1065,7 @@ impl BitGoPsbt { public_key: CompressedPublicKey, ) -> Result { let psbt = self.psbt(); + let network = self.network(); let input = &psbt.inputs[input_index]; @@ -999,8 +1079,15 @@ impl BitGoPsbt { ); } + // Determine fork_id based on network + let fork_id = match network.mainnet() { + Network::BitcoinCash | Network::Ecash | Network::BitcoinSV => Some(0u32), + Network::BitcoinGold => Some(79u32), + _ => None, + }; + // Fall back to ECDSA signature verification for legacy/SegWit inputs - psbt_wallet_input::verify_ecdsa_signature(secp, psbt, input_index, public_key) + psbt_wallet_input::verify_ecdsa_signature(secp, psbt, input_index, public_key, fork_id) } /// Verify if a valid signature exists for a given extended public key at the specified input index @@ -1584,6 +1671,62 @@ mod tests { Ok(()) } + /// Test that sign_with_privkey β†’ verify_replay_protection_signature roundtrip works. + /// + /// This test guards against sighash algorithm mismatches between signing and verification. + /// Specifically, it catches the bug where sign_with_privkey used legacy_signature_hash + /// for all networks, but verify_replay_protection_signature used p2wsh_signature_hash_forkid + /// for BCH-like networks (BitcoinCash, BitcoinGold, Ecash). + fn assert_p2shp2pk_sign_verify_roundtrip( + unsigned_fixture: &fixtures::PsbtFixture, + wallet_keys: &fixtures::XprvTriple, + input_index: usize, + network: Network, + ) -> Result<(), String> { + // Get the xpriv for signing (user key) + let xpriv = wallet_keys.user_key(); + let privkey = xpriv.private_key; + + // Deserialize the unsigned PSBT + let original_bytes = BASE64_STANDARD + .decode(&unsigned_fixture.psbt_base64) + .map_err(|e| format!("Failed to decode base64: {}", e))?; + let mut psbt = BitGoPsbt::deserialize(&original_bytes, network) + .map_err(|e| format!("Failed to deserialize PSBT: {:?}", e))?; + + // Sign the p2shP2pk input + psbt.sign_with_privkey(input_index, &privkey) + .map_err(|e| format!("Failed to sign p2shP2pk input: {}", e))?; + + // Get the output script for replay protection verification + let psbt_ref = psbt.psbt(); + let input = &psbt_ref.inputs[input_index]; + let prevout = psbt_ref.unsigned_tx.input[input_index].previous_output; + let (output_script, _value) = + psbt_wallet_input::get_output_script_and_value(input, prevout) + .map_err(|e| format!("Failed to get output script: {}", e))?; + + let replay_protection = + crate::fixed_script_wallet::ReplayProtection::new(vec![output_script.clone()]); + + // Verify the signature + let secp = secp256k1::Secp256k1::new(); + let has_valid_signature = psbt + .verify_replay_protection_signature(&secp, input_index, &replay_protection) + .map_err(|e| format!("Failed to verify signature: {}", e))?; + + if !has_valid_signature { + return Err(format!( + "p2shP2pk signβ†’verify roundtrip failed for {:?}. \ + This indicates a sighash mismatch between sign_with_privkey and \ + verify_replay_protection_signature (e.g., SIGHASH_FORKID handling).", + network + )); + } + + Ok(()) + } + fn assert_signature_count( bitgo_psbt: &BitGoPsbt, wallet_keys: &RootWalletKeys, @@ -1685,6 +1828,17 @@ mod tests { &psbt_input_stages.wallet_keys, psbt_input_stages.input_index, )?; + + // Test signβ†’verify roundtrip from unsigned state. + // This verifies that sign_with_privkey uses the correct sighash algorithm: + // - BCH-like networks (BitcoinCash, BitcoinGold, Ecash): SIGHASH_FORKID | SIGHASH_ALL + // - Standard networks: SIGHASH_ALL (legacy) + assert_p2shp2pk_sign_verify_roundtrip( + &psbt_stages.unsigned, + &psbt_input_stages.wallet_keys, + psbt_input_stages.input_index, + network, + )?; } else { assert_full_signed_matches_wallet_scripts( network, @@ -1722,8 +1876,6 @@ mod tests { crate::test_psbt_fixtures!(test_p2sh_p2pk_suite, network, format, { test_wallet_script_type(fixtures::ScriptType::P2shP2pk, network, format).unwrap(); }, ignore: [ - // TODO: sighash support - BitcoinCash, Ecash, BitcoinGold, // TODO: zec support Zcash, ]); @@ -1731,33 +1883,17 @@ mod tests { crate::test_psbt_fixtures!(test_p2sh_suite, network, format, { test_wallet_script_type(fixtures::ScriptType::P2sh, network, format).unwrap(); }, ignore: [ - // TODO: sighash support - BitcoinCash, Ecash, BitcoinGold, // TODO: zec support Zcash, ]); - crate::test_psbt_fixtures!( - test_p2sh_p2wsh_suite, - network, - format, - { - test_wallet_script_type(fixtures::ScriptType::P2shP2wsh, network, format).unwrap(); - }, - // TODO: sighash support - ignore: [BitcoinGold] - ); + crate::test_psbt_fixtures!(test_p2sh_p2wsh_suite, network, format, { + test_wallet_script_type(fixtures::ScriptType::P2shP2wsh, network, format).unwrap(); + }); - crate::test_psbt_fixtures!( - test_p2wsh_suite, - network, - format, - { - test_wallet_script_type(fixtures::ScriptType::P2wsh, network, format).unwrap(); - }, - // TODO: sighash support - ignore: [BitcoinGold] - ); + crate::test_psbt_fixtures!(test_p2wsh_suite, network, format, { + test_wallet_script_type(fixtures::ScriptType::P2wsh, network, format).unwrap(); + }); crate::test_psbt_fixtures!( test_p2tr_legacy_script_path_suite, @@ -1822,7 +1958,7 @@ mod tests { extracted_transaction_hex, fixture_extracted_transaction, "Extracted transaction should match" ); - }, ignore: [BitcoinGold, BitcoinCash, Ecash, Zcash]); + }, ignore: [Zcash]); #[test] fn test_add_paygo_attestation() { @@ -2116,7 +2252,7 @@ mod tests { parsed.spend_amount > 0, "Spend amount should be greater than 0 when there are external outputs" ); - }, ignore: [BitcoinGold, BitcoinCash, Ecash, Zcash]); + }, ignore: [Zcash]); #[test] fn test_serialize_bitcoin_psbt() { diff --git a/packages/wasm-utxo/src/fixed_script_wallet/bitgo_psbt/psbt_wallet_input.rs b/packages/wasm-utxo/src/fixed_script_wallet/bitgo_psbt/psbt_wallet_input.rs index 3312087..a4aaeb3 100644 --- a/packages/wasm-utxo/src/fixed_script_wallet/bitgo_psbt/psbt_wallet_input.rs +++ b/packages/wasm-utxo/src/fixed_script_wallet/bitgo_psbt/psbt_wallet_input.rs @@ -211,6 +211,7 @@ pub fn verify_taproot_script_signature( /// - `psbt`: The PSBT containing the transaction and inputs /// - `input_index`: The index of the input to verify /// - `public_key`: The compressed public key to verify the signature for +/// - `fork_id`: Optional fork ID for BCH/BTG/XEC networks (0 for BCH/XEC, 79 for BTG) /// /// # Returns /// - `Ok(true)` if a valid ECDSA signature exists for the public key @@ -221,6 +222,7 @@ pub fn verify_ecdsa_signature( psbt: &miniscript::bitcoin::psbt::Psbt, input_index: usize, public_key: miniscript::bitcoin::CompressedPublicKey, + fork_id: Option, ) -> Result { use miniscript::bitcoin::{sighash::SighashCache, PublicKey}; @@ -234,9 +236,20 @@ pub fn verify_ecdsa_signature( if let Some(signature) = input.partial_sigs.get(&public_key_inner) { // Create sighash cache and compute sighash for this input let mut cache = SighashCache::new(&psbt.unsigned_tx); - let (sighash_msg, _sighash_type) = match psbt.sighash_ecdsa(input_index, &mut cache) { - Ok(result) => result, - Err(e) => return Err(format!("Failed to compute sighash: {}", e)), + + // Use appropriate sighash computation based on fork_id + let sighash_msg = if let Some(fid) = fork_id { + // BCH/BTG/XEC: use sighash_forkid + let (msg, _) = psbt + .sighash_forkid(input_index, &mut cache, fid) + .map_err(|e| format!("Failed to compute FORKID sighash: {}", e))?; + msg + } else { + // Standard Bitcoin: use sighash_ecdsa + let (msg, _) = psbt + .sighash_ecdsa(input_index, &mut cache) + .map_err(|e| format!("Failed to compute sighash: {}", e))?; + msg }; // Verify the signature From ef0552750f59b4390161f88c6a8f3b2c4124ca40 Mon Sep 17 00:00:00 2001 From: Otto Allmendinger Date: Wed, 17 Dec 2025 11:07:46 +0100 Subject: [PATCH 3/4] feat(wasm-utxo): mark BCH and BTG transaction support as complete Updates the feature status in README to reflect that Bitcoin Cash and Bitcoin Gold now have complete transaction support in the FixedScript wallet. Issue: BTC-2656 Co-authored-by: llm-git --- packages/wasm-utxo/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wasm-utxo/README.md b/packages/wasm-utxo/README.md index f4997ba..d3fc2b3 100644 --- a/packages/wasm-utxo/README.md +++ b/packages/wasm-utxo/README.md @@ -20,7 +20,7 @@ This project is under active development. | Descriptor Wallet: Address Support | βœ… Complete | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | | Descriptor Wallet: Transaction Support | βœ… Complete | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | | FixedScript Wallet: Address Generation | βœ… Complete | βœ… Complete | βœ… Complete | βœ… Complete | βœ… Complete | βœ… Complete | βœ… Complete | -| FixedScript Wallet: Transaction Support | βœ… Complete | ⏳ TODO | ⏳ TODO | ⏳ TODO | ⏳ TODO | βœ… Complete | ⏳ TODO | +| FixedScript Wallet: Transaction Support | βœ… Complete | βœ… Complete | βœ… Complete | ⏳ TODO | ⏳ TODO | βœ… Complete | ⏳ TODO | ## Building From 9cfedc8b19392834a181d75e6888deb1b1dfc172 Mon Sep 17 00:00:00 2001 From: Otto Allmendinger Date: Wed, 17 Dec 2025 11:12:59 +0100 Subject: [PATCH 4/4] feat(wasm-utxo): add network support utilities for fixtures Extract fixture network filtering into a utility function. This improves code organization and reduces duplication across test files. Now includes bitcoincash and bitcoingold in fixture networks. Issue: BTC-2656 Co-authored-by: llm-git --- .../test/fixedScript/finalizeExtract.ts | 14 ++------------ .../test/fixedScript/networkSupport.util.ts | 17 +++++++++++++++++ .../parseTransactionWithWalletKeys.ts | 14 ++------------ .../test/fixedScript/signAndVerifySignature.ts | 14 ++------------ 4 files changed, 23 insertions(+), 36 deletions(-) create mode 100644 packages/wasm-utxo/test/fixedScript/networkSupport.util.ts diff --git a/packages/wasm-utxo/test/fixedScript/finalizeExtract.ts b/packages/wasm-utxo/test/fixedScript/finalizeExtract.ts index bb70403..47199ad 100644 --- a/packages/wasm-utxo/test/fixedScript/finalizeExtract.ts +++ b/packages/wasm-utxo/test/fixedScript/finalizeExtract.ts @@ -7,20 +7,10 @@ import { getExtractedTransactionHex, type Fixture, } from "./fixtureUtil.js"; +import { getFixtureNetworks } from "./networkSupport.util.js"; describe("finalize and extract transaction", function () { - const supportedNetworks = utxolib.getNetworkList().filter((network) => { - return ( - utxolib.isMainnet(network) && - network !== utxolib.networks.bitcoincash && - network !== utxolib.networks.bitcoingold && - network !== utxolib.networks.bitcoinsv && - network !== utxolib.networks.ecash && - network !== utxolib.networks.zcash - ); - }); - - supportedNetworks.forEach((network) => { + getFixtureNetworks().forEach((network) => { const networkName = utxolib.getNetworkName(network); describe(`network: ${networkName}`, function () { diff --git a/packages/wasm-utxo/test/fixedScript/networkSupport.util.ts b/packages/wasm-utxo/test/fixedScript/networkSupport.util.ts new file mode 100644 index 0000000..275e049 --- /dev/null +++ b/packages/wasm-utxo/test/fixedScript/networkSupport.util.ts @@ -0,0 +1,17 @@ +import * as utxolib from "@bitgo/utxo-lib"; + +/** + * Get networks that have psbt fixtures + */ +export function getFixtureNetworks(): utxolib.Network[] { + return utxolib.getNetworkList().filter((network) => { + return ( + // we only have fixtures for mainnet networks + utxolib.isMainnet(network) && + // we don't have fixtures for bitcoinsv since it is not really supported any longer + network !== utxolib.networks.bitcoinsv && + // we do have zcash fixtures but it is not fully implemented yet + network !== utxolib.networks.zcash + ); + }); +} diff --git a/packages/wasm-utxo/test/fixedScript/parseTransactionWithWalletKeys.ts b/packages/wasm-utxo/test/fixedScript/parseTransactionWithWalletKeys.ts index 2533a9f..6531fc6 100644 --- a/packages/wasm-utxo/test/fixedScript/parseTransactionWithWalletKeys.ts +++ b/packages/wasm-utxo/test/fixedScript/parseTransactionWithWalletKeys.ts @@ -11,6 +11,7 @@ import { loadReplayProtectionKeyFromFixture, type Fixture, } from "./fixtureUtil.js"; +import { getFixtureNetworks } from "./networkSupport.util.js"; function getExpectedInputScriptType(fixtureScriptType: string): InputScriptType { // Map fixture types to InputScriptType values @@ -38,18 +39,7 @@ function getOtherWalletKeys(): utxolib.bitgo.RootWalletKeys { } describe("parseTransactionWithWalletKeys", function () { - const supportedNetworks = utxolib.getNetworkList().filter((network) => { - return ( - utxolib.isMainnet(network) && - network !== utxolib.networks.bitcoincash && - network !== utxolib.networks.bitcoingold && - network !== utxolib.networks.bitcoinsv && - network !== utxolib.networks.ecash && - network !== utxolib.networks.zcash - ); - }); - - supportedNetworks.forEach((network) => { + getFixtureNetworks().forEach((network) => { const networkName = utxolib.getNetworkName(network); describe(`network: ${networkName}`, function () { diff --git a/packages/wasm-utxo/test/fixedScript/signAndVerifySignature.ts b/packages/wasm-utxo/test/fixedScript/signAndVerifySignature.ts index 394c457..cd95a0a 100644 --- a/packages/wasm-utxo/test/fixedScript/signAndVerifySignature.ts +++ b/packages/wasm-utxo/test/fixedScript/signAndVerifySignature.ts @@ -14,6 +14,7 @@ import { type Fixture, loadReplayProtectionKeyFromFixture, } from "./fixtureUtil.js"; +import { getFixtureNetworks } from "./networkSupport.util.js"; type SignatureStage = "unsigned" | "halfsigned" | "fullsigned"; @@ -279,18 +280,7 @@ function runTestsForFixture( } describe("verifySignature", function () { - const supportedNetworks = utxolib.getNetworkList().filter((network) => { - return ( - utxolib.isMainnet(network) && - network !== utxolib.networks.bitcoincash && - network !== utxolib.networks.bitcoingold && - network !== utxolib.networks.bitcoinsv && - network !== utxolib.networks.ecash && - network !== utxolib.networks.zcash - ); - }); - - supportedNetworks.forEach((network) => { + getFixtureNetworks().forEach((network) => { const networkName = utxolib.getNetworkName(network); describe(`network: ${networkName}`, function () {