]> Untitled Git - bdk/commitdiff
refactor(chain)!: revamp `KeychainTxOutIndex` API
author志宇 <hello@evanlinjin.me>
Sat, 13 Jan 2024 12:04:49 +0000 (20:04 +0800)
committer志宇 <hello@evanlinjin.me>
Wed, 17 Jan 2024 03:17:25 +0000 (11:17 +0800)
Previously `SpkTxOutIndex` methods can be called from
`KeychainTxOutIndex` due to the `DeRef` implementation. However, the
internal `SpkTxOut` will also contain lookahead spks resulting in an
error-prone API.

`SpkTxOutIndex` methods are now not directly callable from
`KeychainTxOutIndex`. Methods of `KeychainTxOutIndex` are renamed for
clarity. I.e. methods that return an unbounded spk iter are prefixed
with `unbounded`.

crates/bdk/src/wallet/mod.rs
crates/chain/src/keychain/txout_index.rs
crates/chain/tests/test_keychain_txout_index.rs
crates/electrum/src/electrum_ext.rs
example-crates/example_cli/src/lib.rs
example-crates/example_electrum/src/main.rs
example-crates/example_esplora/src/main.rs
example-crates/wallet_electrum/src/main.rs
example-crates/wallet_esplora_async/src/main.rs
example-crates/wallet_esplora_blocking/src/main.rs

index ce152cb5ede509a12ddf496cc5ba4b4d43ecd7fd..366a1d20718231dd04d98a1a43dc29eb3eea4532 100644 (file)
@@ -712,7 +712,7 @@ impl<D> Wallet<D> {
             }
             AddressIndex::Peek(index) => {
                 let (index, spk) = txout_index
-                    .spks_of_keychain(&keychain)
+                    .unbounded_spk_iter(&keychain)
                     .take(index as usize + 1)
                     .last()
                     .unwrap();
@@ -745,7 +745,7 @@ impl<D> Wallet<D> {
     ///
     /// Will only return `Some(_)` if the wallet has given out the spk.
     pub fn derivation_of_spk(&self, spk: &Script) -> Option<(KeychainKind, u32)> {
-        self.indexed_graph.index.index_of_spk(spk).copied()
+        self.indexed_graph.index.index_of_spk(spk)
     }
 
     /// Return the list of unspent outputs of this wallet
@@ -784,7 +784,8 @@ impl<D> Wallet<D> {
         self.chain.tip()
     }
 
-    /// Returns a iterators of all the script pubkeys for the `Internal` and External` variants in `KeychainKind`.
+    /// Returns a iterators of all the script pubkeys for the `Internal` and `External` variants in
+    /// `KeychainKind`.
     ///
     /// This is intended to be used when doing a full scan of your addresses (e.g. after restoring
     /// from seed words). You pass the `BTreeMap` of iterators to a blockchain data source (e.g.
@@ -792,36 +793,36 @@ impl<D> Wallet<D> {
     ///
     /// Note carefully that iterators go over **all** script pubkeys on the keychains (not what
     /// script pubkeys the wallet is storing internally).
-    pub fn spks_of_all_keychains(
+    pub fn all_unbounded_spk_iters(
         &self,
     ) -> BTreeMap<KeychainKind, impl Iterator<Item = (u32, ScriptBuf)> + Clone> {
-        self.indexed_graph.index.spks_of_all_keychains()
+        self.indexed_graph.index.all_unbounded_spk_iters()
     }
 
     /// Gets an iterator over all the script pubkeys in a single keychain.
     ///
-    /// See [`spks_of_all_keychains`] for more documentation
+    /// See [`all_unbounded_spk_iters`] for more documentation
     ///
-    /// [`spks_of_all_keychains`]: Self::spks_of_all_keychains
-    pub fn spks_of_keychain(
+    /// [`all_unbounded_spk_iters`]: Self::all_unbounded_spk_iters
+    pub fn unbounded_spk_iter(
         &self,
         keychain: KeychainKind,
     ) -> impl Iterator<Item = (u32, ScriptBuf)> + Clone {
-        self.indexed_graph.index.spks_of_keychain(&keychain)
+        self.indexed_graph.index.unbounded_spk_iter(&keychain)
     }
 
     /// Returns the utxo owned by this wallet corresponding to `outpoint` if it exists in the
     /// wallet's database.
     pub fn get_utxo(&self, op: OutPoint) -> Option<LocalOutput> {
-        let (&spk_i, _) = self.indexed_graph.index.txout(op)?;
+        let (keychain, index, _) = self.indexed_graph.index.txout(op)?;
         self.indexed_graph
             .graph()
             .filter_chain_unspents(
                 &self.chain,
                 self.chain.tip().block_id(),
-                core::iter::once((spk_i, op)),
+                core::iter::once(((), op)),
             )
-            .map(|((k, i), full_txo)| new_local_utxo(k, i, full_txo))
+            .map(|(_, full_txo)| new_local_utxo(keychain, index, full_txo))
             .next()
     }
 
@@ -1459,7 +1460,7 @@ impl<D> Wallet<D> {
                 let ((index, spk), index_changeset) =
                     self.indexed_graph.index.next_unused_spk(&change_keychain);
                 let spk = spk.into();
-                self.indexed_graph.index.mark_used(&change_keychain, index);
+                self.indexed_graph.index.mark_used(change_keychain, index);
                 self.persist
                     .stage(ChangeSet::from(indexed_tx_graph::ChangeSet::from(
                         index_changeset,
@@ -1640,7 +1641,7 @@ impl<D> Wallet<D> {
                     .into();
 
                 let weighted_utxo = match txout_index.index_of_spk(&txout.script_pubkey) {
-                    Some(&(keychain, derivation_index)) => {
+                    Some((keychain, derivation_index)) => {
                         #[allow(deprecated)]
                         let satisfaction_weight = self
                             .get_descriptor_for_keychain(keychain)
@@ -1684,7 +1685,7 @@ impl<D> Wallet<D> {
             for (index, txout) in tx.output.iter().enumerate() {
                 let change_type = self.map_keychain(KeychainKind::Internal);
                 match txout_index.index_of_spk(&txout.script_pubkey) {
-                    Some(&(keychain, _)) if keychain == change_type => change_index = Some(index),
+                    Some((keychain, _)) if keychain == change_type => change_index = Some(index),
                     _ => {}
                 }
             }
@@ -1939,10 +1940,10 @@ impl<D> Wallet<D> {
     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) {
                 // 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);
+                txout_index.unmark_used(keychain, index);
             }
         }
     }
@@ -1958,7 +1959,7 @@ impl<D> Wallet<D> {
     }
 
     fn get_descriptor_for_txout(&self, txout: &TxOut) -> Option<DerivedDescriptor> {
-        let &(keychain, child) = self
+        let (keychain, child) = self
             .indexed_graph
             .index
             .index_of_spk(&txout.script_pubkey)?;
@@ -2172,7 +2173,7 @@ impl<D> Wallet<D> {
     {
         // Try to find the prev_script in our db to figure out if this is internal or external,
         // and the derivation index
-        let &(keychain, child) = self
+        let (keychain, child) = self
             .indexed_graph
             .index
             .index_of_spk(&utxo.txout.script_pubkey)
@@ -2226,7 +2227,7 @@ impl<D> Wallet<D> {
 
         // 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)) =
+            if let Some((keychain, child)) =
                 self.indexed_graph.index.index_of_spk(&out.script_pubkey)
             {
                 let desc = self.get_descriptor_for_keychain(keychain);
index a8955b8a981d3dacc182956e183da6d40282a354..d6ee80dfd363ac52f4ede2ee78dd3197a553e7a2 100644 (file)
@@ -5,8 +5,8 @@ use crate::{
     spk_iter::BIP32_MAX_INDEX,
     SpkIterator, SpkTxOutIndex,
 };
-use bitcoin::{OutPoint, Script, TxOut};
-use core::{fmt::Debug, ops::Deref};
+use bitcoin::{OutPoint, Script, Transaction, TxOut};
+use core::fmt::Debug;
 
 use crate::Append;
 
@@ -75,14 +75,6 @@ impl<K> Default for KeychainTxOutIndex<K> {
     }
 }
 
-impl<K> Deref for KeychainTxOutIndex<K> {
-    type Target = SpkTxOutIndex<(K, u32)>;
-
-    fn deref(&self) -> &Self::Target {
-        &self.inner
-    }
-}
-
 impl<K: Clone + Ord + Debug> Indexer for KeychainTxOutIndex<K> {
     type ChangeSet = super::ChangeSet<K>;
 
@@ -110,7 +102,7 @@ impl<K: Clone + Ord + Debug> Indexer for KeychainTxOutIndex<K> {
     }
 
     fn is_tx_relevant(&self, tx: &bitcoin::Transaction) -> bool {
-        self.is_relevant(tx)
+        self.inner.is_relevant(tx)
     }
 }
 
@@ -133,8 +125,11 @@ impl<K> KeychainTxOutIndex<K> {
     }
 }
 
+/// Methods that are *re-exposed* from the internal [`SpkTxOutIndex`].
 impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
     /// Return a reference to the internal [`SpkTxOutIndex`].
+    ///
+    /// **WARNING:** The internal index will contain lookahead spks.
     pub fn inner(&self) -> &SpkTxOutIndex<(K, u32)> {
         &self.inner
     }
@@ -144,7 +139,97 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
         self.inner.outpoints()
     }
 
-    /// Return a reference to the internal map of the keychain to descriptors.
+    /// Return the [`TxOut`] of `outpoint` if it has been indexed.
+    ///
+    /// The associated keychain and keychain index of the txout's spk is also returned.
+    ///
+    /// This calls [`SpkTxOutIndex::txout`] internally.
+    pub fn txout(&self, outpoint: OutPoint) -> Option<(K, u32, &TxOut)> {
+        self.inner
+            .txout(outpoint)
+            .map(|((k, i), txo)| (k.clone(), *i, txo))
+    }
+
+    /// 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> {
+        self.inner.spk_at_index(&(keychain, 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)> {
+        self.inner.index_of_spk(script).cloned()
+    }
+
+    /// Returns whether the spk under the `keychain`'s `index` has been used.
+    ///
+    /// Here, "unused" means that after the script pubkey was stored in the index, the index has
+    /// never scanned a transaction output with it.
+    ///
+    /// This calls [`SpkTxOutIndex::is_used`] internally.
+    pub fn is_used(&self, keychain: K, index: u32) -> bool {
+        self.inner.is_used(&(keychain, index))
+    }
+
+    /// Marks the script pubkey at `index` as used even though the tracker hasn't seen an output
+    /// with it.
+    ///
+    /// This only has an effect when the `index` had been added to `self` already and was unused.
+    ///
+    /// Returns whether the `index` was initially present as `unused`.
+    ///
+    /// This is useful when you want to reserve a script pubkey for something but don't want to add
+    /// the transaction output using it to the index yet. Other callers will consider `index` on
+    /// `keychain` used until you call [`unmark_used`].
+    ///
+    /// This calls [`SpkTxOutIndex::mark_used`] internally.
+    ///
+    /// [`unmark_used`]: Self::unmark_used
+    pub fn mark_used(&mut self, keychain: K, index: u32) -> bool {
+        self.inner.mark_used(&(keychain, index))
+    }
+
+    /// Undoes the effect of [`mark_used`]. Returns whether the `index` is inserted back into
+    /// `unused`.
+    ///
+    /// Note that if `self` has scanned an output with this script pubkey, then this will have no
+    /// effect.
+    ///
+    /// This calls [`SpkTxOutIndex::unmark_used`] internally.
+    ///
+    /// [`mark_used`]: Self::mark_used
+    pub fn unmark_used(&mut self, keychain: K, index: u32) -> bool {
+        self.inner.unmark_used(&(keychain, index))
+    }
+
+    /// Computes total input value going from script pubkeys in the index (sent) and the total output
+    /// value going to script pubkeys in the index (received) in `tx`. For the `sent` to be computed
+    /// correctly, the output being spent must have already been scanned by the index. Calculating
+    /// received just uses the [`Transaction`] outputs directly, so it will be correct even if it has
+    /// not been scanned.
+    ///
+    /// This calls [`SpkTxOutIndex::sent_and_received`] internally.
+    pub fn sent_and_received(&self, tx: &Transaction) -> (u64, u64) {
+        self.inner.sent_and_received(tx)
+    }
+
+    /// Computes the net value that this transaction gives to the script pubkeys in the index and
+    /// *takes* from the transaction outputs in the index. Shorthand for calling
+    /// [`sent_and_received`] and subtracting sent from received.
+    ///
+    /// This calls [`SpkTxOutIndex::net_value`] internally.
+    ///
+    /// [`sent_and_received`]: Self::sent_and_received
+    pub fn net_value(&self, tx: &Transaction) -> i64 {
+        self.inner.net_value(tx)
+    }
+}
+
+impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
+    /// Return a reference to the internal map of keychain to descriptors.
     pub fn keychains(&self) -> &BTreeMap<K, Descriptor<DescriptorPublicKey>> {
         &self.keychains
     }
@@ -213,59 +298,67 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
             .map_or(0, |((_, index), _)| *index + 1)
     }
 
-    /// Generates script pubkey iterators for every `keychain`. The iterators iterate over all
-    /// derivable script pubkeys.
-    pub fn spks_of_all_keychains(
+    /// Get an unbounded spk iterator over a given `keychain`.
+    ///
+    /// # Panics
+    ///
+    /// This will panic if the given `keychain`'s descriptor does not exist.
+    pub fn unbounded_spk_iter(&self, keychain: &K) -> SpkIterator<Descriptor<DescriptorPublicKey>> {
+        SpkIterator::new(
+            self.keychains
+                .get(keychain)
+                .expect("keychain does not exist")
+                .clone(),
+        )
+    }
+
+    /// Get unbounded spk iterators for all keychains.
+    pub fn all_unbounded_spk_iters(
         &self,
     ) -> BTreeMap<K, SpkIterator<Descriptor<DescriptorPublicKey>>> {
         self.keychains
             .iter()
-            .map(|(keychain, descriptor)| {
-                (
-                    keychain.clone(),
-                    SpkIterator::new_with_range(descriptor.clone(), 0..),
-                )
-            })
+            .map(|(k, descriptor)| (k.clone(), SpkIterator::new(descriptor.clone())))
             .collect()
     }
 
-    /// Generates a script pubkey iterator for the given `keychain`'s descriptor (if it exists). The
-    /// iterator iterates over all derivable scripts of the keychain's descriptor.
-    ///
-    /// # Panics
-    ///
-    /// This will panic if the `keychain` does not exist.
-    pub fn spks_of_keychain(&self, keychain: &K) -> SpkIterator<Descriptor<DescriptorPublicKey>> {
-        let descriptor = self
-            .keychains
-            .get(keychain)
-            .expect("keychain must exist")
-            .clone();
-        SpkIterator::new_with_range(descriptor, 0..)
+    /// Iterate over revealed spks of all keychains.
+    pub fn revealed_spks(&self) -> impl DoubleEndedIterator<Item = (K, u32, &Script)> + Clone {
+        self.keychains.keys().flat_map(|keychain| {
+            self.revealed_keychain_spks(keychain)
+                .map(|(i, spk)| (keychain.clone(), i, spk))
+        })
     }
 
-    /// Convenience method to get [`revealed_spks_of_keychain`] of all keychains.
-    ///
-    /// [`revealed_spks_of_keychain`]: Self::revealed_spks_of_keychain
-    pub fn revealed_spks_of_all_keychains(
+    /// Iterate over revealed spks of the given `keychain`.
+    pub fn revealed_keychain_spks(
         &self,
-    ) -> BTreeMap<K, impl Iterator<Item = (u32, &Script)> + Clone> {
-        self.keychains
-            .keys()
-            .map(|keychain| (keychain.clone(), self.revealed_spks_of_keychain(keychain)))
-            .collect()
+        keychain: &K,
+    ) -> impl DoubleEndedIterator<Item = (u32, &Script)> + Clone {
+        let next_i = self.last_revealed.get(keychain).map_or(0, |&i| i + 1);
+        self.inner
+            .all_spks()
+            .range((keychain.clone(), u32::MIN)..(keychain.clone(), next_i))
+            .map(|((_, i), spk)| (*i, spk.as_script()))
     }
 
-    /// Iterates over the script pubkeys revealed by this index under `keychain`.
-    pub fn revealed_spks_of_keychain(
+    /// Iterate over revealed, but unused, spks of all keychains.
+    pub fn unused_spks(&self) -> impl DoubleEndedIterator<Item = (K, u32, &Script)> + Clone {
+        self.keychains.keys().flat_map(|keychain| {
+            self.unused_keychain_spks(keychain)
+                .map(|(i, spk)| (keychain.clone(), i, spk))
+        })
+    }
+
+    /// Iterate over revealed, but unused, spks of the given `keychain`.
+    pub fn unused_keychain_spks(
         &self,
         keychain: &K,
     ) -> impl DoubleEndedIterator<Item = (u32, &Script)> + Clone {
-        let next_index = self.last_revealed.get(keychain).map_or(0, |v| *v + 1);
+        let next_i = self.last_revealed.get(keychain).map_or(0, |&i| i + 1);
         self.inner
-            .all_spks()
-            .range((keychain.clone(), u32::MIN)..(keychain.clone(), next_index))
-            .map(|((_, derivation_index), spk)| (*derivation_index, spk.as_script()))
+            .unused_spks((keychain.clone(), u32::MIN)..(keychain.clone(), next_i))
+            .map(|((_, i), spk)| (*i, spk))
     }
 
     /// Get the next derivation index for `keychain`. The next index is the index after the last revealed
@@ -442,13 +535,13 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
     ///
     /// Panics if `keychain` has never been added to the index
     pub fn next_unused_spk(&mut self, keychain: &K) -> ((u32, &Script), super::ChangeSet<K>) {
-        let need_new = self.unused_spks_of_keychain(keychain).next().is_none();
+        let need_new = self.unused_keychain_spks(keychain).next().is_none();
         // this rather strange branch is needed because of some lifetime issues
         if need_new {
             self.reveal_next_spk(keychain)
         } else {
             (
-                self.unused_spks_of_keychain(keychain)
+                self.unused_keychain_spks(keychain)
                     .next()
                     .expect("we already know next exists"),
                 super::ChangeSet::default(),
@@ -456,46 +549,9 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
         }
     }
 
-    /// Marks the script pubkey at `index` as used even though the tracker hasn't seen an output with it.
-    /// This only has an effect when the `index` had been added to `self` already and was unused.
-    ///
-    /// Returns whether the `index` was initially present as `unused`.
-    ///
-    /// This is useful when you want to reserve a script pubkey for something but don't want to add
-    /// the transaction output using it to the index yet. Other callers will consider `index` on
-    /// `keychain` used until you call [`unmark_used`].
-    ///
-    /// [`unmark_used`]: Self::unmark_used
-    pub fn mark_used(&mut self, keychain: &K, index: u32) -> bool {
-        self.inner.mark_used(&(keychain.clone(), index))
-    }
-
-    /// Undoes the effect of [`mark_used`]. Returns whether the `index` is inserted back into
-    /// `unused`.
-    ///
-    /// Note that if `self` has scanned an output with this script pubkey, then this will have no
-    /// effect.
-    ///
-    /// [`mark_used`]: Self::mark_used
-    pub fn unmark_used(&mut self, keychain: &K, index: u32) -> bool {
-        self.inner.unmark_used(&(keychain.clone(), index))
-    }
-
-    /// Iterates over all unused script pubkeys for a `keychain` stored in the index.
-    pub fn unused_spks_of_keychain(
-        &self,
-        keychain: &K,
-    ) -> impl DoubleEndedIterator<Item = (u32, &Script)> {
-        let next_index = self.last_revealed.get(keychain).map_or(0, |&v| v + 1);
-        let range = (keychain.clone(), u32::MIN)..(keychain.clone(), next_index);
-        self.inner
-            .unused_spks(range)
-            .map(|((_, i), script)| (*i, script))
-    }
-
     /// Iterates over all the [`OutPoint`] that have a `TxOut` with a script pubkey derived from
     /// `keychain`.
-    pub fn txouts_of_keychain(
+    pub fn keychain_outpoints(
         &self,
         keychain: &K,
     ) -> impl DoubleEndedIterator<Item = (u32, OutPoint)> + '_ {
@@ -507,7 +563,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
     /// Returns the highest derivation index of the `keychain` where [`KeychainTxOutIndex`] has
     /// found a [`TxOut`] with it's script pubkey.
     pub fn last_used_index(&self, keychain: &K) -> Option<u32> {
-        self.txouts_of_keychain(keychain).last().map(|(i, _)| i)
+        self.keychain_outpoints(keychain).last().map(|(i, _)| i)
     }
 
     /// Returns the highest derivation index of each keychain that [`KeychainTxOutIndex`] has found
index e1f55dc31f306b5210ecbe9941801d8eb5e205e8..0bbc37393c461d04214194b24188a8c8492e4b7c 100644 (file)
@@ -95,25 +95,25 @@ fn test_lookahead() {
         );
         assert_eq!(
             txout_index
-                .revealed_spks_of_keychain(&TestKeychain::External)
+                .revealed_keychain_spks(&TestKeychain::External)
                 .count(),
             index as usize + 1,
         );
         assert_eq!(
             txout_index
-                .revealed_spks_of_keychain(&TestKeychain::Internal)
+                .revealed_keychain_spks(&TestKeychain::Internal)
                 .count(),
             0,
         );
         assert_eq!(
             txout_index
-                .unused_spks_of_keychain(&TestKeychain::External)
+                .unused_keychain_spks(&TestKeychain::External)
                 .count(),
             index as usize + 1,
         );
         assert_eq!(
             txout_index
-                .unused_spks_of_keychain(&TestKeychain::Internal)
+                .unused_keychain_spks(&TestKeychain::Internal)
                 .count(),
             0,
         );
@@ -147,7 +147,7 @@ fn test_lookahead() {
     );
     assert_eq!(
         txout_index
-            .revealed_spks_of_keychain(&TestKeychain::Internal)
+            .revealed_keychain_spks(&TestKeychain::Internal)
             .count(),
         25,
     );
@@ -199,13 +199,13 @@ fn test_lookahead() {
         );
         assert_eq!(
             txout_index
-                .revealed_spks_of_keychain(&TestKeychain::External)
+                .revealed_keychain_spks(&TestKeychain::External)
                 .count(),
             last_external_index as usize + 1,
         );
         assert_eq!(
             txout_index
-                .revealed_spks_of_keychain(&TestKeychain::Internal)
+                .revealed_keychain_spks(&TestKeychain::Internal)
                 .count(),
             last_internal_index as usize + 1,
         );
@@ -305,7 +305,7 @@ fn test_wildcard_derivations() {
 
     (0..=15)
         .chain([17, 20, 23])
-        .for_each(|index| assert!(txout_index.mark_used(&TestKeychain::External, index)));
+        .for_each(|index| assert!(txout_index.mark_used(TestKeychain::External, index)));
 
     assert_eq!(txout_index.next_index(&TestKeychain::External), (26, true));
 
@@ -321,7 +321,7 @@ fn test_wildcard_derivations() {
     // - Use all the derived till 26.
     // - next_unused() = ((27, <spk>), keychain::ChangeSet)
     (0..=26).for_each(|index| {
-        txout_index.mark_used(&TestKeychain::External, index);
+        txout_index.mark_used(TestKeychain::External, index);
     });
 
     let (spk, changeset) = txout_index.next_unused_spk(&TestKeychain::External);
@@ -364,7 +364,7 @@ fn test_non_wildcard_derivations() {
     // - derive new and next unused should return the old script
     // - store_up_to should not panic and return empty changeset
     assert_eq!(txout_index.next_index(&TestKeychain::External), (0, false));
-    txout_index.mark_used(&TestKeychain::External, 0);
+    txout_index.mark_used(TestKeychain::External, 0);
 
     let (spk, changeset) = txout_index.reveal_next_spk(&TestKeychain::External);
     assert_eq!(spk, (0, external_spk.as_script()));
@@ -381,7 +381,7 @@ fn test_non_wildcard_derivations() {
     // we check that spks_of_keychain returns a SpkIterator with just one element
     assert_eq!(
         txout_index
-            .spks_of_keychain(&TestKeychain::External)
+            .revealed_keychain_spks(&TestKeychain::External)
             .count(),
         1,
     );
index 1c9ce9890ddec11638d9d6400a6195e3023befaa..1f41aaf9cee64439d362a76495b458424b54d684 100644 (file)
@@ -187,7 +187,7 @@ impl ElectrumExt for Client {
     ) -> Result<(ElectrumUpdate, BTreeMap<K, u32>), Error> {
         let mut request_spks = keychain_spks
             .into_iter()
-            .map(|(k, s)| (k, s.into_iter()))
+            .map(|(k, s)| (k.clone(), s.into_iter()))
             .collect::<BTreeMap<K, _>>();
         let mut scanned_spks = BTreeMap::<(K, u32), (ScriptBuf, bool)>::new();
 
index 39b4f312e91028e83ca2e887a032af9895068305..46231946f0552e6923e80e6811a44f3c5509f4ab 100644 (file)
@@ -478,14 +478,14 @@ where
                         true => Keychain::Internal,
                         false => Keychain::External,
                     };
-                    for (spk_i, spk) in index.revealed_spks_of_keychain(&target_keychain) {
+                    for (spk_i, spk) in index.revealed_keychain_spks(&target_keychain) {
                         let address = Address::from_script(spk, network)
                             .expect("should always be able to derive address");
                         println!(
                             "{:?} {} used:{}",
                             spk_i,
                             address,
-                            index.is_used(&(target_keychain, spk_i))
+                            index.is_used(target_keychain, spk_i)
                         );
                     }
                     Ok(())
@@ -611,7 +611,7 @@ where
                     // We don't want other callers/threads to use this address while we're using it
                     // but we also don't want to scan the tx we just created because it's not
                     // technically in the blockchain yet.
-                    graph.index.mark_used(&change_keychain, index);
+                    graph.index.mark_used(change_keychain, index);
                     (tx, Some((change_keychain, index)))
                 } else {
                     (tx, None)
@@ -636,7 +636,7 @@ where
                 Err(e) => {
                     if let Some((keychain, index)) = change_index {
                         // We failed to broadcast, so allow our change address to be used in the future
-                        graph.lock().unwrap().index.unmark_used(&keychain, index);
+                        graph.lock().unwrap().index.unmark_used(keychain, index);
                     }
                     Err(e)
                 }
index 8d82fded449187741addf35d2f0999271d5fbd05..e7545f057099d477908347687c6d2cc035829fe3 100644 (file)
@@ -5,7 +5,7 @@ use std::{
 };
 
 use bdk_chain::{
-    bitcoin::{constants::genesis_block, Address, Network, OutPoint, ScriptBuf, Txid},
+    bitcoin::{constants::genesis_block, Address, Network, OutPoint, Txid},
     indexed_tx_graph::{self, IndexedTxGraph},
     keychain,
     local_chain::{self, LocalChain},
@@ -155,7 +155,7 @@ fn main() -> anyhow::Result<()> {
 
                 let keychain_spks = graph
                     .index
-                    .spks_of_all_keychains()
+                    .all_unbounded_spk_iters()
                     .into_iter()
                     .map(|(keychain, iter)| {
                         let mut first = true;
@@ -206,29 +206,28 @@ fn main() -> anyhow::Result<()> {
             if all_spks {
                 let all_spks = graph
                     .index
-                    .all_spks()
-                    .iter()
-                    .map(|(k, v)| (*k, v.clone()))
+                    .revealed_spks()
+                    .map(|(k, i, spk)| (k, i, spk.to_owned()))
                     .collect::<Vec<_>>();
-                spks = Box::new(spks.chain(all_spks.into_iter().map(|(index, script)| {
-                    eprintln!("scanning {:?}", index);
-                    script
+                spks = Box::new(spks.chain(all_spks.into_iter().map(|(k, i, spk)| {
+                    eprintln!("scanning {}:{}", k, i);
+                    spk
                 })));
             }
             if unused_spks {
                 let unused_spks = graph
                     .index
-                    .unused_spks(..)
-                    .map(|(k, v)| (*k, ScriptBuf::from(v)))
+                    .unused_spks()
+                    .map(|(k, i, spk)| (k, i, spk.to_owned()))
                     .collect::<Vec<_>>();
-                spks = Box::new(spks.chain(unused_spks.into_iter().map(|(index, script)| {
+                spks = Box::new(spks.chain(unused_spks.into_iter().map(|(k, i, spk)| {
                     eprintln!(
-                        "Checking if address {} {:?} has been used",
-                        Address::from_script(&script, args.network).unwrap(),
-                        index
+                        "Checking if address {} {}:{} has been used",
+                        Address::from_script(&spk, args.network).unwrap(),
+                        k,
+                        i,
                     );
-
-                    script
+                    spk
                 })));
             }
 
index 101fd58ba20f428cc322dda66861d9d12634a115..298532cb6dbf728dd3bf06813e415878ebae05fd 100644 (file)
@@ -165,7 +165,7 @@ fn main() -> anyhow::Result<()> {
                 .lock()
                 .expect("mutex must not be poisoned")
                 .index
-                .spks_of_all_keychains()
+                .all_unbounded_spk_iters()
                 .into_iter()
                 // This `map` is purely for logging.
                 .map(|(keychain, iter)| {
@@ -235,32 +235,32 @@ fn main() -> anyhow::Result<()> {
                 if *all_spks {
                     let all_spks = graph
                         .index
-                        .all_spks()
-                        .iter()
-                        .map(|(k, v)| (*k, v.clone()))
+                        .revealed_spks()
+                        .map(|(k, i, spk)| (k, i, spk.to_owned()))
                         .collect::<Vec<_>>();
-                    spks = Box::new(spks.chain(all_spks.into_iter().map(|(index, script)| {
-                        eprintln!("scanning {:?}", index);
+                    spks = Box::new(spks.chain(all_spks.into_iter().map(|(k, i, spk)| {
+                        eprintln!("scanning {}:{}", k, i);
                         // Flush early to ensure we print at every iteration.
                         let _ = io::stderr().flush();
-                        script
+                        spk
                     })));
                 }
                 if unused_spks {
                     let unused_spks = graph
                         .index
-                        .unused_spks(..)
-                        .map(|(k, v)| (*k, v.to_owned()))
+                        .unused_spks()
+                        .map(|(k, i, spk)| (k, i, spk.to_owned()))
                         .collect::<Vec<_>>();
-                    spks = Box::new(spks.chain(unused_spks.into_iter().map(|(index, script)| {
+                    spks = Box::new(spks.chain(unused_spks.into_iter().map(|(k, i, spk)| {
                         eprintln!(
-                            "Checking if address {} {:?} has been used",
-                            Address::from_script(&script, args.network).unwrap(),
-                            index
+                            "Checking if address {} {}:{} has been used",
+                            Address::from_script(&spk, args.network).unwrap(),
+                            k,
+                            i,
                         );
                         // Flush early to ensure we print at every iteration.
                         let _ = io::stderr().flush();
-                        script
+                        spk
                     })));
                 }
                 if utxos {
index e5c6b146627a00d305eeccaec2952edff34bc34c..4f8aba9fd3aa71a58a5a83cde5a3e369c64c8451 100644 (file)
@@ -40,7 +40,7 @@ fn main() -> Result<(), anyhow::Error> {
 
     let prev_tip = wallet.latest_checkpoint();
     let keychain_spks = wallet
-        .spks_of_all_keychains()
+        .all_unbounded_spk_iters()
         .into_iter()
         .map(|(k, k_spks)| {
             let mut once = Some(());
index 755b39007b1e8a1d5fab7b6bcb40f373b43ed9b3..690cd87e24f740e2c6f8b2890863bd8d24204c18 100644 (file)
@@ -39,7 +39,7 @@ async fn main() -> Result<(), anyhow::Error> {
 
     let prev_tip = wallet.latest_checkpoint();
     let keychain_spks = wallet
-        .spks_of_all_keychains()
+        .all_unbounded_spk_iters()
         .into_iter()
         .map(|(k, k_spks)| {
             let mut once = Some(());
index d0f35bea8e7dda9d5908e9ed767f4ac047c29fc8..73bfdd5598a3eec086133a446e8434d00dd04dc1 100644 (file)
@@ -38,7 +38,7 @@ fn main() -> Result<(), anyhow::Error> {
 
     let prev_tip = wallet.latest_checkpoint();
     let keychain_spks = wallet
-        .spks_of_all_keychains()
+        .all_unbounded_spk_iters()
         .into_iter()
         .map(|(k, k_spks)| {
             let mut once = Some(());