bitceptron_retriever/
path_pairs.rs

1use std::str::FromStr;
2
3use bitcoin::{
4    bip32::DerivationPath, key::Secp256k1, secp256k1::SecretKey, Amount, BlockHash, ScriptBuf, Txid,
5};
6use bitcoincore_rpc::json::{ScanTxOutRequest, ScanTxOutResult, Utxo};
7use miniscript::{bitcoin::secp256k1::PublicKey, Descriptor};
8use tracing::info;
9use zeroize::{Zeroize, ZeroizeOnDrop};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct PathScriptPubKeyBytesPair(DerivationPath, Vec<u8>);
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct PathDescriptorPair(pub(crate) DerivationPath, pub(crate) Descriptor<PublicKey>);
16
17impl PathDescriptorPair {
18    pub fn new(path: DerivationPath, descriptor: Descriptor<PublicKey>) -> Self {
19        PathDescriptorPair(path, descriptor)
20    }
21
22    pub fn to_path_scan_request_descriptor_trio(&self) -> PathScanRequestDescriptorTrio {
23        let scan_request = ScanTxOutRequest::Single(self.1.to_string());
24        PathScanRequestDescriptorTrio(self.0.clone(), scan_request, self.1.clone())
25    }
26}
27
28impl Zeroize for PathDescriptorPair {
29    fn zeroize(&mut self) {
30        let paths = vec!["0".to_string(); self.0.len()].join::<&str>("/");
31        self.0 = DerivationPath::from_str(format!("m/{}", paths).as_str()).unwrap();
32        self.1 = Descriptor::new_pkh(
33            SecretKey::from_slice(&[0u8; 32])
34                .unwrap()
35                .public_key(&Secp256k1::new()),
36        )
37        .unwrap();
38    }
39}
40
41impl ZeroizeOnDrop for PathDescriptorPair {}
42
43#[derive(Debug, Clone, PartialEq, Eq)]
44pub struct PathScanRequestDescriptorTrio(
45    pub(crate) DerivationPath,
46    pub(crate) ScanTxOutRequest,
47    pub(crate) Descriptor<PublicKey>,
48);
49
50impl PathScanRequestDescriptorTrio {
51    pub fn new(
52        path: DerivationPath,
53        scan_request: ScanTxOutRequest,
54        descriptor: Descriptor<PublicKey>,
55    ) -> Self {
56        PathScanRequestDescriptorTrio(path, scan_request, descriptor)
57    }
58
59    pub fn from_path_descriptor_pair(path_descriptor_pair: PathDescriptorPair) -> Self {
60        let scan_request = ScanTxOutRequest::Single(path_descriptor_pair.1.to_string());
61        PathScanRequestDescriptorTrio(path_descriptor_pair.0, scan_request, path_descriptor_pair.1)
62    }
63}
64
65impl Zeroize for PathScanRequestDescriptorTrio {
66    fn zeroize(&mut self) {
67        let paths = vec!["0".to_string(); self.0.len()].join::<&str>("/");
68        self.0 = DerivationPath::from_str(format!("m/{}", paths).as_str()).unwrap();
69        self.1 = ScanTxOutRequest::Single("00000000000000000".to_string());
70    }
71}
72
73impl ZeroizeOnDrop for PathScanRequestDescriptorTrio {}
74
75#[derive(Debug, Clone, PartialEq, Eq)]
76pub struct PathScanResultDescriptorTrio(
77    pub DerivationPath,
78    pub ScanTxOutResult,
79    pub Descriptor<PublicKey>,
80);
81
82impl PathScanResultDescriptorTrio {
83    pub fn new(
84        path: DerivationPath,
85        scan_result: ScanTxOutResult,
86        descriptor: Descriptor<PublicKey>,
87    ) -> Self {
88        PathScanResultDescriptorTrio(path, scan_result, descriptor)
89    }
90
91    pub fn get_derivation_path(&self) -> DerivationPath {
92        self.0.clone()
93    }
94
95    pub fn get_scan_result(&self) -> ScanTxOutResult {
96        self.1.clone()
97    }
98
99    pub fn get_descriptor(&self) -> Descriptor<PublicKey> {
100        self.2.clone()
101    }
102}
103
104impl Zeroize for PathScanResultDescriptorTrio {
105    fn zeroize(&mut self) {
106        info!("Zeroizing path-scan result pairs initialized.");
107        let paths = vec!["0".to_string(); self.0.len()].join::<&str>("/");
108        self.0 = DerivationPath::from_str(format!("m/{}", paths).as_str()).unwrap();
109        self.1 = ScanTxOutResult {
110            success: Some(false),
111            tx_outs: Some(42),
112            height: Some(5326),
113            best_block_hash: Some(
114                BlockHash::from_str(
115                    "00000000000000000002ac885fab3cd598f5ae4092fc92b3d4c7096ef0f0caae",
116                )
117                .unwrap(),
118            ),
119            unspents: vec![Utxo {
120                txid: Txid::from_str(
121                    "f3aa99937337582a105c90e0595847177d8ab99d50201e318634a5d2db4f9d85",
122                )
123                .unwrap(),
124                vout: 21,
125                script_pub_key: ScriptBuf::from_hex(
126                    "a91442402a28dd61f2718a4b27ae72a4791d5bbdade787",
127                )
128                .unwrap(),
129                descriptor: "none".to_string(),
130                amount: Amount::from_sat(2100000000000000),
131                height: 42,
132            }],
133            total_amount: Amount::from_sat(2100000000000000),
134        };
135        info!("Zeroizing path-scan result pairs finished.");
136    }
137}
138
139impl ZeroizeOnDrop for PathScanResultDescriptorTrio {}