]> Untitled Git - bdk/commitdiff
refactor(chain)!: update KeychainTxOutIndex methods to use owned ScriptBuf
authorSteve Myers <steve@notmandatory.org>
Tue, 9 Jul 2024 21:51:12 +0000 (16:51 -0500)
committerSteve Myers <steve@notmandatory.org>
Mon, 22 Jul 2024 01:28:01 +0000 (20:28 -0500)
crates/chain/src/indexer/keychain_txout.rs
crates/chain/src/indexer/spk_txout.rs
crates/chain/src/tx_graph.rs
crates/chain/tests/common/tx_template.rs
crates/chain/tests/test_indexed_tx_graph.rs
crates/chain/tests/test_tx_graph_conflicts.rs
crates/wallet/src/wallet/mod.rs
crates/wallet/tests/wallet.rs
example-crates/example_cli/src/lib.rs

index 9b22cc556b9befb6f76fd8e0938e78839838130e..c4a13fbe1d0f95a8f993ba472808795bbfb84b85 100644 (file)
@@ -9,7 +9,7 @@ use crate::{
     DescriptorExt, DescriptorId, Indexed, Indexer, KeychainIndexed, SpkIterator,
 };
 use alloc::{borrow::ToOwned, vec::Vec};
-use bitcoin::{Amount, OutPoint, Script, ScriptBuf, SignedAmount, Transaction, TxOut, Txid};
+use bitcoin::{Amount, OutPoint, ScriptBuf, SignedAmount, Transaction, TxOut, Txid};
 use core::{
     fmt::Debug,
     ops::{Bound, RangeBounds},
@@ -251,14 +251,14 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
     /// Return the script that exists under the given `keychain`'s `index`.
     ///
     /// This calls [`SpkTxOutIndex::spk_at_index`] internally.
-    pub fn spk_at_index(&self, keychain: K, index: u32) -> Option<&Script> {
+    pub fn spk_at_index(&self, keychain: K, index: u32) -> Option<ScriptBuf> {
         self.inner.spk_at_index(&(keychain.clone(), index))
     }
 
     /// Returns the keychain and keychain index associated with the spk.
     ///
     /// This calls [`SpkTxOutIndex::index_of_spk`] internally.
-    pub fn index_of_spk(&self, script: &Script) -> Option<&(K, u32)> {
+    pub fn index_of_spk(&self, script: ScriptBuf) -> Option<&(K, u32)> {
         self.inner.index_of_spk(script)
     }
 
@@ -489,7 +489,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
     pub fn revealed_spks(
         &self,
         range: impl RangeBounds<K>,
-    ) -> impl Iterator<Item = KeychainIndexed<K, &Script>> {
+    ) -> impl Iterator<Item = KeychainIndexed<K, ScriptBuf>> + '_ {
         let start = range.start_bound();
         let end = range.end_bound();
         let mut iter_last_revealed = self
@@ -516,7 +516,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
             let (current_keychain, last_revealed) = current_keychain?;
 
             if current_keychain == keychain && Some(*index) <= last_revealed {
-                break Some(((keychain.clone(), *index), spk.as_script()));
+                break Some(((keychain.clone(), *index), spk.clone()));
             }
         })
     }
@@ -528,7 +528,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
     pub fn revealed_keychain_spks(
         &self,
         keychain: K,
-    ) -> impl DoubleEndedIterator<Item = Indexed<&Script>> {
+    ) -> impl DoubleEndedIterator<Item = Indexed<ScriptBuf>> + '_ {
         let end = self
             .last_revealed_index(keychain.clone())
             .map(|v| v + 1)
@@ -536,16 +536,16 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
         self.inner
             .all_spks()
             .range((keychain.clone(), 0)..(keychain.clone(), end))
-            .map(|((_, index), spk)| (*index, spk.as_script()))
+            .map(|((_, index), spk)| (*index, spk.clone()))
     }
 
     /// Iterate over revealed, but unused, spks of all keychains.
     pub fn unused_spks(
         &self,
-    ) -> impl DoubleEndedIterator<Item = KeychainIndexed<K, &Script>> + Clone {
+    ) -> impl DoubleEndedIterator<Item = KeychainIndexed<K, ScriptBuf>> + Clone + '_ {
         self.keychain_to_descriptor_id.keys().flat_map(|keychain| {
             self.unused_keychain_spks(keychain.clone())
-                .map(|(i, spk)| ((keychain.clone(), i), spk))
+                .map(|(i, spk)| ((keychain.clone(), i), spk.clone()))
         })
     }
 
@@ -554,7 +554,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
     pub fn unused_keychain_spks(
         &self,
         keychain: K,
-    ) -> impl DoubleEndedIterator<Item = Indexed<&Script>> + Clone {
+    ) -> impl DoubleEndedIterator<Item = Indexed<ScriptBuf>> + Clone + '_ {
         let end = match self.keychain_to_descriptor_id.get(&keychain) {
             Some(did) => self.last_revealed.get(did).map(|v| *v + 1).unwrap_or(0),
             None => 0,
@@ -681,8 +681,8 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
     ///  1. The descriptor has no wildcard and already has one script revealed.
     ///  2. The descriptor has already revealed scripts up to the numeric bound.
     ///  3. There is no descriptor associated with the given keychain.
-    pub fn reveal_next_spk(&mut self, keychain: &K) -> Option<(Indexed<ScriptBuf>, ChangeSet)> {
-        let (next_index, new) = self.next_index(keychain)?;
+    pub fn reveal_next_spk(&mut self, keychain: K) -> Option<(Indexed<ScriptBuf>, ChangeSet)> {
+        let (next_index, new) = self.next_index(keychain.clone())?;
         let mut changeset = ChangeSet::default();
 
         if new {
@@ -695,7 +695,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
             .inner
             .spk_at_index(&(keychain.clone(), next_index))
             .expect("we just inserted it");
-        Some(((next_index, script.into()), changeset))
+        Some(((next_index, script), changeset))
     }
 
     /// Gets the next unused script pubkey in the keychain. I.e., the script pubkey with the lowest
index b3cd923eeeba42bb45983f3a4058153dc063ddb0..b55bd72a1ee6dc6391e9345e466a2e787662808c 100644 (file)
@@ -6,7 +6,7 @@ use crate::{
     collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap},
     Indexer,
 };
-use bitcoin::{Amount, OutPoint, Script, ScriptBuf, SignedAmount, Transaction, TxOut, Txid};
+use bitcoin::{Amount, OutPoint, ScriptBuf, SignedAmount, Transaction, TxOut, Txid};
 
 /// An index storing [`TxOut`]s that have a script pubkey that matches those in a list.
 ///
@@ -176,8 +176,8 @@ impl<I: Clone + Ord + core::fmt::Debug> SpkTxOutIndex<I> {
     /// Returns the script that has been inserted at the `index`.
     ///
     /// If that index hasn't been inserted yet, it will return `None`.
-    pub fn spk_at_index(&self, index: &I) -> Option<&Script> {
-        self.spks.get(index).map(|s| s.as_script())
+    pub fn spk_at_index(&self, index: &I) -> Option<ScriptBuf> {
+        self.spks.get(index).cloned()
     }
 
     /// The script pubkeys that are being tracked by the index.
@@ -217,7 +217,10 @@ impl<I: Clone + Ord + core::fmt::Debug> SpkTxOutIndex<I> {
     /// let unused_change_spks =
     ///     txout_index.unused_spks((change_index, u32::MIN)..(change_index, u32::MAX));
     /// ```
-    pub fn unused_spks<R>(&self, range: R) -> impl DoubleEndedIterator<Item = (&I, &Script)> + Clone
+    pub fn unused_spks<R>(
+        &self,
+        range: R,
+    ) -> impl DoubleEndedIterator<Item = (&I, ScriptBuf)> + Clone + '_
     where
         R: RangeBounds<I>,
     {
@@ -268,8 +271,8 @@ impl<I: Clone + Ord + core::fmt::Debug> SpkTxOutIndex<I> {
     }
 
     /// Returns the index associated with the script pubkey.
-    pub fn index_of_spk(&self, script: &Script) -> Option<&I> {
-        self.spk_indices.get(script)
+    pub fn index_of_spk(&self, script: ScriptBuf) -> Option<&I> {
+        self.spk_indices.get(script.as_script())
     }
 
     /// Computes the total value transfer effect `tx` has on the script pubkeys in `range`. Value is
@@ -293,7 +296,7 @@ impl<I: Clone + Ord + core::fmt::Debug> SpkTxOutIndex<I> {
             }
         }
         for txout in &tx.output {
-            if let Some(index) = self.index_of_spk(&txout.script_pubkey) {
+            if let Some(index) = self.index_of_spk(txout.script_pubkey.clone()) {
                 if range.contains(index) {
                     received += txout.value;
                 }
index 8c11e737a41a03dee8738194fee8cd681875db2c..192b122e2ff5f97091fb3106055fb9da913ff0cb 100644 (file)
@@ -94,7 +94,7 @@ use crate::{
 use alloc::collections::vec_deque::VecDeque;
 use alloc::sync::Arc;
 use alloc::vec::Vec;
-use bitcoin::{Amount, OutPoint, Script, SignedAmount, Transaction, TxOut, Txid};
+use bitcoin::{Amount, OutPoint, ScriptBuf, SignedAmount, Transaction, TxOut, Txid};
 use core::fmt::{self, Formatter};
 use core::{
     convert::Infallible,
@@ -1163,7 +1163,7 @@ impl<A: Anchor> TxGraph<A> {
         chain: &C,
         chain_tip: BlockId,
         outpoints: impl IntoIterator<Item = (OI, OutPoint)>,
-        mut trust_predicate: impl FnMut(&OI, &Script) -> bool,
+        mut trust_predicate: impl FnMut(&OI, ScriptBuf) -> bool,
     ) -> Result<Balance, C::Error> {
         let mut immature = Amount::ZERO;
         let mut trusted_pending = Amount::ZERO;
@@ -1182,7 +1182,7 @@ impl<A: Anchor> TxGraph<A> {
                     }
                 }
                 ChainPosition::Unconfirmed(_) => {
-                    if trust_predicate(&spk_i, &txout.txout.script_pubkey) {
+                    if trust_predicate(&spk_i, txout.txout.script_pubkey) {
                         trusted_pending += txout.txout.value;
                     } else {
                         untrusted_pending += txout.txout.value;
@@ -1209,7 +1209,7 @@ impl<A: Anchor> TxGraph<A> {
         chain: &C,
         chain_tip: BlockId,
         outpoints: impl IntoIterator<Item = (OI, OutPoint)>,
-        trust_predicate: impl FnMut(&OI, &Script) -> bool,
+        trust_predicate: impl FnMut(&OI, ScriptBuf) -> bool,
     ) -> Balance {
         self.try_balance(chain, chain_tip, outpoints, trust_predicate)
             .expect("oracle is infallible")
index 6445fb63cafef5540481e49994141a49f7dfb697..c7ce392e584c8b310e88d035b775b6a84b630d10 100644 (file)
@@ -119,7 +119,7 @@ pub fn init_graph<'a, A: Anchor + Clone + 'a>(
                     },
                     Some(index) => TxOut {
                         value: Amount::from_sat(output.value),
-                        script_pubkey: spk_index.spk_at_index(index).unwrap().to_owned(),
+                        script_pubkey: spk_index.spk_at_index(index).unwrap(),
                     },
                 })
                 .collect(),
index abbf7e6c2552872e1641bf5a23d13a85b1b4d456..361e5ab5c30c82aba194e5725f58978dddbb50e3 100644 (file)
@@ -12,9 +12,7 @@ use bdk_chain::{
     local_chain::LocalChain,
     tx_graph, Balance, ChainPosition, ConfirmationBlockTime, DescriptorExt,
 };
-use bitcoin::{
-    secp256k1::Secp256k1, Amount, OutPoint, Script, ScriptBuf, Transaction, TxIn, TxOut,
-};
+use bitcoin::{secp256k1::Secp256k1, Amount, OutPoint, ScriptBuf, Transaction, TxIn, TxOut};
 use miniscript::Descriptor;
 
 /// Ensure [`IndexedTxGraph::insert_relevant_txs`] can successfully index transactions NOT presented
@@ -284,7 +282,7 @@ fn test_list_owned_txouts() {
                 &local_chain,
                 chain_tip,
                 graph.index.outpoints().iter().cloned(),
-                |_, spk: &Script| trusted_spks.contains(&spk.to_owned()),
+                |_, spk: ScriptBuf| trusted_spks.contains(&spk),
             );
 
             let confirmed_txouts_txid = txouts
index 802ba5c7e4a06bd37e6265c4347633586b9a7078..45370b676370cfc0d01f331cbcb75bae7cbf3275 100644 (file)
@@ -6,7 +6,7 @@ mod common;
 use std::collections::{BTreeSet, HashSet};
 
 use bdk_chain::{Balance, BlockId};
-use bitcoin::{Amount, OutPoint, Script};
+use bitcoin::{Amount, OutPoint, ScriptBuf};
 use common::*;
 
 #[allow(dead_code)]
@@ -659,7 +659,7 @@ fn test_tx_conflict_handling() {
             &local_chain,
             chain_tip,
             spk_index.outpoints().iter().cloned(),
-            |_, spk: &Script| spk_index.index_of_spk(spk).is_some(),
+            |_, spk: ScriptBuf| spk_index.index_of_spk(spk).is_some(),
         );
         assert_eq!(
             balance, scenario.exp_balance,
index d971790a046b6d829911b3a9a60bc9e12025e7bf..df22c8a6413ca6b0530d599c3bbf46efb9feec82 100644 (file)
@@ -36,8 +36,8 @@ use bdk_chain::{
 };
 use bitcoin::sighash::{EcdsaSighashType, TapSighashType};
 use bitcoin::{
-    absolute, psbt, Address, Block, FeeRate, Network, OutPoint, Script, ScriptBuf, Sequence,
-    Transaction, TxOut, Txid, Witness,
+    absolute, psbt, Address, Block, FeeRate, Network, OutPoint, ScriptBuf, Sequence, Transaction,
+    TxOut, Txid, Witness,
 };
 use bitcoin::{consensus::encode::serialize, transaction, BlockHash, Psbt};
 use bitcoin::{constants::genesis_block, Amount};
@@ -363,8 +363,8 @@ impl Wallet {
         ));
         let index = create_indexer(descriptor, change_descriptor, params.lookahead)?;
 
-        let descriptor = index.get_descriptor(&KeychainKind::External).cloned();
-        let change_descriptor = index.get_descriptor(&KeychainKind::Internal).cloned();
+        let descriptor = index.get_descriptor(KeychainKind::External).cloned();
+        let change_descriptor = index.get_descriptor(KeychainKind::Internal).cloned();
         let indexed_graph = IndexedTxGraph::new(index);
         let indexed_graph_changeset = indexed_graph.initial_changeset();
 
@@ -705,20 +705,21 @@ impl Wallet {
             .unused_keychain_spks(keychain)
             .map(move |(index, spk)| AddressInfo {
                 index,
-                address: Address::from_script(spk, self.network).expect("must have address form"),
+                address: Address::from_script(spk.as_script(), self.network)
+                    .expect("must have address form"),
                 keychain,
             })
     }
 
     /// Return whether or not a `script` is part of this wallet (either internal or external)
-    pub fn is_mine(&self, script: &Script) -> bool {
+    pub fn is_mine(&self, script: ScriptBuf) -> bool {
         self.indexed_graph.index.index_of_spk(script).is_some()
     }
 
     /// Finds how the wallet derived the script pubkey `spk`.
     ///
     /// Will only return `Some(_)` if the wallet has given out the spk.
-    pub fn derivation_of_spk(&self, spk: &Script) -> Option<(KeychainKind, u32)> {
+    pub fn derivation_of_spk(&self, spk: ScriptBuf) -> Option<(KeychainKind, u32)> {
         self.indexed_graph.index.index_of_spk(spk).cloned()
     }
 
@@ -1060,7 +1061,7 @@ impl Wallet {
         let descriptor = self
             .indexed_graph
             .index
-            .get_descriptor(&keychain)
+            .get_descriptor(keychain)
             .expect("keychain must exist");
         *wallet_signers = SignersContainer::build(keymap, descriptor, &self.secp);
     }
@@ -1327,7 +1328,7 @@ impl Wallet {
                 return Err(CreateTxError::OutputBelowDustLimit(index));
             }
 
-            if self.is_mine(script_pubkey) {
+            if self.is_mine(script_pubkey.clone()) {
                 received += Amount::from_sat(value);
             }
 
@@ -1434,7 +1435,7 @@ impl Wallet {
                 remaining_amount, ..
             } => fee_amount += remaining_amount,
             Change { amount, fee } => {
-                if self.is_mine(&drain_script) {
+                if self.is_mine(drain_script.clone()) {
                     received += Amount::from_sat(*amount);
                 }
                 fee_amount += fee;
@@ -1555,7 +1556,7 @@ impl Wallet {
                     .cloned()
                     .into();
 
-                let weighted_utxo = match txout_index.index_of_spk(&txout.script_pubkey) {
+                let weighted_utxo = match txout_index.index_of_spk(txout.script_pubkey.clone()) {
                     Some(&(keychain, derivation_index)) => {
                         let satisfaction_weight = self
                             .public_descriptor(keychain)
@@ -1600,7 +1601,7 @@ impl Wallet {
             let mut change_index = None;
             for (index, txout) in tx.output.iter().enumerate() {
                 let change_keychain = KeychainKind::Internal;
-                match txout_index.index_of_spk(&txout.script_pubkey) {
+                match txout_index.index_of_spk(txout.script_pubkey.clone()) {
                     Some((keychain, _)) if *keychain == change_keychain => {
                         change_index = Some(index)
                     }
@@ -1862,7 +1863,7 @@ impl Wallet {
     pub fn cancel_tx(&mut self, tx: &Transaction) {
         let txout_index = &mut self.indexed_graph.index;
         for txout in &tx.output {
-            if let Some((keychain, index)) = txout_index.index_of_spk(&txout.script_pubkey) {
+            if let Some((keychain, index)) = txout_index.index_of_spk(txout.script_pubkey.clone()) {
                 // NOTE: unmark_used will **not** make something unused if it has actually been used
                 // by a tx in the tracker. It only removes the superficial marking.
                 txout_index.unmark_used(*keychain, *index);
@@ -1874,7 +1875,7 @@ impl Wallet {
         let &(keychain, child) = self
             .indexed_graph
             .index
-            .index_of_spk(&txout.script_pubkey)?;
+            .index_of_spk(txout.script_pubkey.clone())?;
         let descriptor = self.public_descriptor(keychain);
         descriptor.at_derivation_index(child).ok()
     }
@@ -2089,7 +2090,7 @@ impl Wallet {
         let &(keychain, child) = self
             .indexed_graph
             .index
-            .index_of_spk(&utxo.txout.script_pubkey)
+            .index_of_spk(utxo.txout.script_pubkey)
             .ok_or(CreateTxError::UnknownUtxo)?;
 
         let mut psbt_input = psbt::Input {
@@ -2135,7 +2136,7 @@ impl Wallet {
         // Try to figure out the keychain and derivation for every input and output
         for (is_input, index, out) in utxos.into_iter() {
             if let Some(&(keychain, child)) =
-                self.indexed_graph.index.index_of_spk(&out.script_pubkey)
+                self.indexed_graph.index.index_of_spk(out.script_pubkey)
             {
                 let desc = self.public_descriptor(keychain);
                 let desc = desc
index 0c4fde7990f2a0a9310585f01b5be2a052b8c438..a4433bc19a0c21b1300aa756bbbaafa5b0328400 100644 (file)
@@ -4023,7 +4023,7 @@ fn test_tx_cancellation() {
         .unsigned_tx
         .output
         .iter()
-        .find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
+        .find_map(|txout| wallet.derivation_of_spk(txout.script_pubkey.clone()))
         .unwrap();
     assert_eq!(change_derivation_1, (KeychainKind::Internal, 0));
 
@@ -4033,7 +4033,7 @@ fn test_tx_cancellation() {
         .unsigned_tx
         .output
         .iter()
-        .find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
+        .find_map(|txout| wallet.derivation_of_spk(txout.script_pubkey.clone()))
         .unwrap();
     assert_eq!(change_derivation_2, (KeychainKind::Internal, 1));
 
@@ -4044,7 +4044,7 @@ fn test_tx_cancellation() {
         .unsigned_tx
         .output
         .iter()
-        .find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
+        .find_map(|txout| wallet.derivation_of_spk(txout.script_pubkey.clone()))
         .unwrap();
     assert_eq!(change_derivation_3, (KeychainKind::Internal, 0));
 
@@ -4053,7 +4053,7 @@ fn test_tx_cancellation() {
         .unsigned_tx
         .output
         .iter()
-        .find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
+        .find_map(|txout| wallet.derivation_of_spk(txout.script_pubkey.clone()))
         .unwrap();
     assert_eq!(change_derivation_3, (KeychainKind::Internal, 2));
 
@@ -4064,7 +4064,7 @@ fn test_tx_cancellation() {
         .unsigned_tx
         .output
         .iter()
-        .find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
+        .find_map(|txout| wallet.derivation_of_spk(txout.script_pubkey.clone()))
         .unwrap();
     assert_eq!(change_derivation_4, (KeychainKind::Internal, 2));
 }
index c7a882ccb2fccb2fc5196a28c40a8f6bccaa07a8..568123d922d6168c361b9fa840bdd0ed02c71e08 100644 (file)
@@ -502,7 +502,7 @@ where
                         false => Keychain::External,
                     };
                     for (spk_i, spk) in index.revealed_keychain_spks(target_keychain) {
-                        let address = Address::from_script(spk, network)
+                        let address = Address::from_script(spk.as_script(), network)
                             .expect("should always be able to derive address");
                         println!(
                             "{:?} {} used:{}",