Skip to content

Commit b7581b3

Browse files
OttoAllmendingerllm-git
andcommitted
feat(wasm-utxo): add multi-stage PSBT fixture loading helpers
Introduces PsbtStages and PsbtInputStages types to simplify testing across different signing stages (unsigned, halfsigned, fullsigned). Refactors test helpers to use these new types for more structured testing. Issue: BTC-2652 Co-authored-by: llm-git <[email protected]>
1 parent 62cb38d commit b7581b3

File tree

3 files changed

+114
-30
lines changed

3 files changed

+114
-30
lines changed

packages/wasm-utxo/src/bitgo_psbt/mod.rs

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,6 @@ mod tests {
238238
use crate::fixed_script_wallet::{RootWalletKeys, WalletScripts};
239239
use crate::test_utils::fixtures;
240240
use base64::engine::{general_purpose::STANDARD as BASE64_STANDARD, Engine};
241-
use miniscript::bitcoin::bip32::Xpub;
242241
use miniscript::bitcoin::consensus::Decodable;
243242
use miniscript::bitcoin::Transaction;
244243

@@ -386,7 +385,7 @@ mod tests {
386385
output.script_pubkey.to_hex_string()
387386
}
388387

389-
fn assert_matches_wallet_scripts(
388+
fn assert_full_signed_matches_wallet_scripts(
390389
network: Network,
391390
tx_format: fixtures::TxFormat,
392391
fixture: &fixtures::PsbtFixture,
@@ -497,50 +496,35 @@ mod tests {
497496
network: Network,
498497
tx_format: fixtures::TxFormat,
499498
) -> Result<(), String> {
500-
let fixture = fixtures::load_psbt_fixture_with_format(
501-
network.to_utxolib_name(),
502-
fixtures::SignatureState::Fullsigned,
503-
tx_format,
504-
)
505-
.expect("Failed to load fixture");
506-
let wallet_keys =
507-
fixtures::parse_wallet_keys(&fixture).expect("Failed to parse wallet keys");
508-
let secp = crate::bitcoin::secp256k1::Secp256k1::new();
509-
let wallet_keys = RootWalletKeys::new(
510-
wallet_keys
511-
.iter()
512-
.map(|x| Xpub::from_priv(&secp, x))
513-
.collect::<Vec<_>>()
514-
.try_into()
515-
.expect("Failed to convert to XpubTriple"),
516-
);
499+
let psbt_stages = fixtures::PsbtStages::load(network, tx_format)?;
500+
let psbt_input_stages =
501+
fixtures::PsbtInputStages::from_psbt_stages(&psbt_stages, script_type);
517502

518503
// Check if the script type is supported by the network
519504
let output_script_support = network.output_script_support();
520-
let input_fixture = fixture.find_input_with_script_type(script_type);
521505
if !script_type.is_supported_by(&output_script_support) {
522506
// Script type not supported by network - skip test (no fixture expected)
523507
assert!(
524-
input_fixture.is_err(),
508+
psbt_input_stages.is_err(),
525509
"Expected error for unsupported script type"
526510
);
527511
return Ok(());
528512
}
529513

530-
let (input_index, input_fixture) = input_fixture.unwrap();
514+
let psbt_input_stages = psbt_input_stages.unwrap();
531515

532-
assert_matches_wallet_scripts(
516+
assert_full_signed_matches_wallet_scripts(
533517
network,
534518
tx_format,
535-
&fixture,
536-
&wallet_keys,
537-
input_index,
538-
input_fixture,
519+
&psbt_stages.fullsigned,
520+
&psbt_input_stages.wallet_keys,
521+
psbt_input_stages.input_index,
522+
&psbt_input_stages.input_fixture_fullsigned,
539523
)?;
540524

541525
assert_finalize_input(
542-
fixture.to_bitgo_psbt(network).unwrap(),
543-
input_index,
526+
psbt_stages.fullsigned.to_bitgo_psbt(network).unwrap(),
527+
psbt_input_stages.input_index,
544528
network,
545529
tx_format,
546530
)?;

packages/wasm-utxo/src/fixed_script_wallet/test_utils/fixtures.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,106 @@ pub struct PsbtFixture {
480480
pub extracted_transaction: Option<String>,
481481
}
482482

483+
// Test helper types for multi-stage PSBT testing
484+
485+
pub struct PsbtStages {
486+
pub network: Network,
487+
pub tx_format: TxFormat,
488+
pub wallet_keys: crate::fixed_script_wallet::RootWalletKeys,
489+
pub unsigned: PsbtFixture,
490+
pub halfsigned: PsbtFixture,
491+
pub fullsigned: PsbtFixture,
492+
}
493+
494+
impl PsbtStages {
495+
pub fn load(network: Network, tx_format: TxFormat) -> Result<Self, String> {
496+
let unsigned = load_psbt_fixture_with_format(
497+
network.to_utxolib_name(),
498+
SignatureState::Unsigned,
499+
tx_format,
500+
)
501+
.expect("Failed to load unsigned fixture");
502+
let halfsigned = load_psbt_fixture_with_format(
503+
network.to_utxolib_name(),
504+
SignatureState::Halfsigned,
505+
tx_format,
506+
)
507+
.expect("Failed to load halfsigned fixture");
508+
let fullsigned = load_psbt_fixture_with_format(
509+
network.to_utxolib_name(),
510+
SignatureState::Fullsigned,
511+
tx_format,
512+
)
513+
.expect("Failed to load fullsigned fixture");
514+
let wallet_keys_unsigned =
515+
parse_wallet_keys(&unsigned).expect("Failed to parse wallet keys");
516+
let wallet_keys_halfsigned =
517+
parse_wallet_keys(&halfsigned).expect("Failed to parse wallet keys");
518+
let wallet_keys_fullsigned =
519+
parse_wallet_keys(&fullsigned).expect("Failed to parse wallet keys");
520+
assert_eq!(wallet_keys_unsigned, wallet_keys_halfsigned);
521+
assert_eq!(wallet_keys_unsigned, wallet_keys_fullsigned);
522+
let secp = crate::bitcoin::secp256k1::Secp256k1::new();
523+
let wallet_keys = crate::fixed_script_wallet::RootWalletKeys::new(
524+
wallet_keys_unsigned
525+
.iter()
526+
.map(|x| crate::bitcoin::bip32::Xpub::from_priv(&secp, x))
527+
.collect::<Vec<_>>()
528+
.try_into()
529+
.expect("Failed to convert to XpubTriple"),
530+
);
531+
532+
Ok(Self {
533+
network,
534+
tx_format,
535+
wallet_keys,
536+
unsigned,
537+
halfsigned,
538+
fullsigned,
539+
})
540+
}
541+
}
542+
543+
pub struct PsbtInputStages {
544+
pub network: Network,
545+
pub tx_format: TxFormat,
546+
pub wallet_keys: crate::fixed_script_wallet::RootWalletKeys,
547+
pub wallet_script_type: ScriptType,
548+
pub input_index: usize,
549+
pub input_fixture_unsigned: PsbtInputFixture,
550+
pub input_fixture_halfsigned: PsbtInputFixture,
551+
pub input_fixture_fullsigned: PsbtInputFixture,
552+
}
553+
554+
impl PsbtInputStages {
555+
pub fn from_psbt_stages(
556+
psbt_stages: &PsbtStages,
557+
wallet_script_type: ScriptType,
558+
) -> Result<Self, String> {
559+
let input_fixture_unsigned = psbt_stages
560+
.unsigned
561+
.find_input_with_script_type(wallet_script_type)?;
562+
let input_fixture_halfsigned = psbt_stages
563+
.halfsigned
564+
.find_input_with_script_type(wallet_script_type)?;
565+
let input_fixture_fullsigned = psbt_stages
566+
.fullsigned
567+
.find_input_with_script_type(wallet_script_type)?;
568+
assert_eq!(input_fixture_unsigned.0, input_fixture_halfsigned.0);
569+
assert_eq!(input_fixture_unsigned.0, input_fixture_fullsigned.0);
570+
Ok(Self {
571+
network: psbt_stages.network,
572+
tx_format: psbt_stages.tx_format,
573+
wallet_keys: psbt_stages.wallet_keys.clone(),
574+
wallet_script_type,
575+
input_index: input_fixture_unsigned.0,
576+
input_fixture_unsigned: input_fixture_unsigned.1.clone(),
577+
input_fixture_halfsigned: input_fixture_halfsigned.1.clone(),
578+
input_fixture_fullsigned: input_fixture_fullsigned.1.clone(),
579+
})
580+
}
581+
}
582+
483583
/// Helper function to find a unique input matching a predicate
484584
fn find_unique_input<'a, T, I, F>(
485585
iter: I,

packages/wasm-utxo/src/fixed_script_wallet/wallet_keys.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub fn to_pub_triple(xpubs: &XpubTriple) -> PubTriple {
3232
.expect("could not convert vec to array")
3333
}
3434

35-
#[derive(Debug)]
35+
#[derive(Debug, Clone)]
3636
pub struct RootWalletKeys {
3737
xpubs: XpubTriple,
3838
derivation_prefixes: [DerivationPath; 3],

0 commit comments

Comments
 (0)