|
16 | 16 | //! .expect("Failed to decode PSBT"); |
17 | 17 | //! |
18 | 18 | //! // Parse wallet keys (xprv) |
19 | | -//! let xprvs = parse_wallet_keys(&fixture) |
| 19 | +//! let xprvs = fixture.get_wallet_xprvs() |
20 | 20 | //! .expect("Failed to parse wallet keys"); |
21 | 21 | //! |
22 | 22 | //! // Access fixture data |
|
38 | 38 | //! } |
39 | 39 | //! ``` |
40 | 40 |
|
| 41 | +use std::str::FromStr; |
| 42 | + |
| 43 | +use crate::{bitcoin::bip32::Xpriv, fixed_script_wallet::RootWalletKeys}; |
| 44 | +use miniscript::bitcoin::bip32::Xpub; |
41 | 45 | use serde::{Deserialize, Serialize}; |
42 | 46 |
|
43 | 47 | use crate::Network; |
44 | 48 |
|
| 49 | +#[derive(Debug, Clone, PartialEq, Eq)] |
| 50 | +pub struct XprvTriple([Xpriv; 3]); |
| 51 | + |
| 52 | +impl XprvTriple { |
| 53 | + pub fn new(xprvs: [Xpriv; 3]) -> Self { |
| 54 | + Self(xprvs) |
| 55 | + } |
| 56 | + |
| 57 | + pub fn from_strings(strings: Vec<String>) -> Result<Self, Box<dyn std::error::Error>> { |
| 58 | + let xprvs = strings |
| 59 | + .iter() |
| 60 | + .map(|s| Xpriv::from_str(s).map_err(|e| Box::new(e) as Box<dyn std::error::Error>)) |
| 61 | + .collect::<Result<Vec<_>, _>>()?; |
| 62 | + Ok(Self::new( |
| 63 | + xprvs.try_into().expect("Expected exactly 3 xprvs"), |
| 64 | + )) |
| 65 | + } |
| 66 | + |
| 67 | + pub fn user_key(&self) -> &Xpriv { |
| 68 | + &self.0[0] |
| 69 | + } |
| 70 | + |
| 71 | + pub fn backup_key(&self) -> &Xpriv { |
| 72 | + &self.0[1] |
| 73 | + } |
| 74 | + |
| 75 | + pub fn bitgo_key(&self) -> &Xpriv { |
| 76 | + &self.0[2] |
| 77 | + } |
| 78 | + |
| 79 | + pub fn to_root_wallet_keys(&self) -> RootWalletKeys { |
| 80 | + let secp = crate::bitcoin::secp256k1::Secp256k1::new(); |
| 81 | + RootWalletKeys::new(self.0.map(|x| Xpub::from_priv(&secp, &x))) |
| 82 | + } |
| 83 | +} |
| 84 | + |
45 | 85 | // Basic helper types (no dependencies on other types in this file) |
46 | 86 |
|
47 | 87 | #[derive(Debug, Clone, Deserialize, Serialize)] |
@@ -511,23 +551,18 @@ impl PsbtStages { |
511 | 551 | tx_format, |
512 | 552 | ) |
513 | 553 | .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"); |
| 554 | + let wallet_keys_unsigned = unsigned |
| 555 | + .get_wallet_xprvs() |
| 556 | + .expect("Failed to parse wallet keys"); |
| 557 | + let wallet_keys_halfsigned = halfsigned |
| 558 | + .get_wallet_xprvs() |
| 559 | + .expect("Failed to parse wallet keys"); |
| 560 | + let wallet_keys_fullsigned = fullsigned |
| 561 | + .get_wallet_xprvs() |
| 562 | + .expect("Failed to parse wallet keys"); |
520 | 563 | assert_eq!(wallet_keys_unsigned, wallet_keys_halfsigned); |
521 | 564 | 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 | | - ); |
| 565 | + let wallet_keys = wallet_keys_unsigned.to_root_wallet_keys(); |
531 | 566 |
|
532 | 567 | Ok(Self { |
533 | 568 | network, |
@@ -614,6 +649,11 @@ impl PsbtFixture { |
614 | 649 | Ok(psbt) |
615 | 650 | } |
616 | 651 |
|
| 652 | + /// Parse wallet keys from fixture (xprv strings) |
| 653 | + pub fn get_wallet_xprvs(&self) -> Result<XprvTriple, Box<dyn std::error::Error>> { |
| 654 | + XprvTriple::from_strings(self.wallet_keys.clone()) |
| 655 | + } |
| 656 | + |
617 | 657 | pub fn find_input_with_script_type( |
618 | 658 | &self, |
619 | 659 | script_type: ScriptType, |
@@ -807,19 +847,6 @@ pub fn decode_psbt_from_fixture( |
807 | 847 | Ok(psbt) |
808 | 848 | } |
809 | 849 |
|
810 | | -/// Parse wallet keys from fixture (xprv strings) |
811 | | -pub fn parse_wallet_keys( |
812 | | - fixture: &PsbtFixture, |
813 | | -) -> Result<Vec<crate::bitcoin::bip32::Xpriv>, Box<dyn std::error::Error>> { |
814 | | - use std::str::FromStr; |
815 | | - |
816 | | - fixture |
817 | | - .wallet_keys |
818 | | - .iter() |
819 | | - .map(|key_str| crate::bitcoin::bip32::Xpriv::from_str(key_str).map_err(|e| e.into())) |
820 | | - .collect() |
821 | | -} |
822 | | - |
823 | 850 | // Helper functions for validation |
824 | 851 |
|
825 | 852 | /// Compares a generated hex string with an expected hex string |
@@ -1382,10 +1409,6 @@ mod tests { |
1382 | 1409 | let psbt = decode_psbt_from_fixture(&fixture).expect("Failed to decode PSBT"); |
1383 | 1410 | assert_eq!(psbt.inputs.len(), 7); |
1384 | 1411 | assert_eq!(psbt.outputs.len(), 5); |
1385 | | - |
1386 | | - // Parse wallet keys |
1387 | | - let xprvs = parse_wallet_keys(&fixture).expect("Failed to parse wallet keys"); |
1388 | | - assert_eq!(xprvs.len(), 3); |
1389 | 1412 | } |
1390 | 1413 |
|
1391 | 1414 | #[test] |
|
0 commit comments