]> Untitled Git - bdk/commitdiff
[bdk_chain_redesign] Rm unnecessary code and premature optimisation
author志宇 <hello@evanlinjin.me>
Thu, 20 Apr 2023 10:07:26 +0000 (18:07 +0800)
committer志宇 <hello@evanlinjin.me>
Thu, 20 Apr 2023 10:07:26 +0000 (18:07 +0800)
* Remove `chain_oracle::CacheBackend` for now as it is not used.
* `SparseChain` does not need to implement `ChainOracle`.
* Remove filter predicate for `list..` methods of `TxGraph` and
  `IndexedTxGraph` as this is premature optimisation.
* `Append` can be implemented for all `BTreeMap`s and `BTreeSet`s,
  instead of only `local_chain::ChangeSet`.

crates/chain/src/chain_oracle.rs
crates/chain/src/indexed_tx_graph.rs
crates/chain/src/local_chain.rs
crates/chain/src/sparse_chain.rs
crates/chain/src/tx_data_traits.rs
crates/chain/src/tx_graph.rs

index 7e975ad2345d41c013bcc2c456ceefb462887ead..2b4ad36fe2305ffe4ddb6c3c5bb46ef8c9e9cb49 100644 (file)
@@ -1,9 +1,3 @@
-use crate::collections::HashSet;
-use core::marker::PhantomData;
-
-use alloc::{collections::VecDeque, vec::Vec};
-use bitcoin::BlockHash;
-
 use crate::BlockId;
 
 /// Represents a service that tracks the blockchain.
@@ -25,53 +19,3 @@ pub trait ChainOracle {
         static_block: BlockId,
     ) -> Result<Option<bool>, Self::Error>;
 }
-
-/// A cache structure increases the performance of getting chain data.
-///
-/// A simple FIFO cache replacement policy is used. Something more efficient and advanced can be
-/// implemented later.
-#[derive(Debug, Default)]
-pub struct CacheBackend<C> {
-    cache: HashSet<(BlockHash, BlockHash)>,
-    fifo: VecDeque<(BlockHash, BlockHash)>,
-    marker: PhantomData<C>,
-}
-
-impl<C> CacheBackend<C> {
-    /// Get the number of elements in the cache.
-    pub fn cache_size(&self) -> usize {
-        self.cache.len()
-    }
-
-    /// Prunes the cache to reach the `max_size` target.
-    ///
-    /// Returns pruned elements.
-    pub fn prune(&mut self, max_size: usize) -> Vec<(BlockHash, BlockHash)> {
-        let prune_count = self.cache.len().saturating_sub(max_size);
-        (0..prune_count)
-            .filter_map(|_| self.fifo.pop_front())
-            .filter(|k| self.cache.remove(k))
-            .collect()
-    }
-
-    pub fn contains(&self, static_block: BlockId, block: BlockId) -> bool {
-        if static_block.height < block.height
-            || static_block.height == block.height && static_block.hash != block.hash
-        {
-            return false;
-        }
-
-        self.cache.contains(&(static_block.hash, block.hash))
-    }
-
-    pub fn insert(&mut self, static_block: BlockId, block: BlockId) -> bool {
-        let cache_key = (static_block.hash, block.hash);
-
-        if self.cache.insert(cache_key) {
-            self.fifo.push_back(cache_key);
-            true
-        } else {
-            false
-        }
-    }
-}
index fd5aa6d974a9759c06d9536e7d48562a2523c7f4..5ce53111d7336277d555b2165f90fec4baf0d91a 100644 (file)
@@ -120,15 +120,12 @@ where
     ///
     /// `anchors` can be provided to anchor the transactions to blocks. `seen_at` is a unix
     /// timestamp of when the transactions are last seen.
-    pub fn insert_relevant_txs<'t, T>(
+    pub fn insert_relevant_txs<'t, T: Iterator<Item = &'t Transaction>>(
         &mut self,
         txs: T,
         anchors: impl IntoIterator<Item = A> + Clone,
         seen_at: Option<u64>,
-    ) -> IndexedAdditions<A, I::Additions>
-    where
-        T: Iterator<Item = &'t Transaction>,
-    {
+    ) -> IndexedAdditions<A, I::Additions> {
         txs.filter_map(|tx| match self.index.is_tx_relevant(tx) {
             true => Some(self.insert_tx(tx, anchors.clone(), seen_at)),
             false => None,
@@ -141,14 +138,11 @@ where
 }
 
 impl<A: Anchor, I: OwnedIndexer> IndexedTxGraph<A, I> {
-    pub fn try_list_owned_txs<'a, C>(
+    pub fn try_list_owned_txs<'a, C: ChainOracle + 'a>(
         &'a self,
         chain: &'a C,
         chain_tip: BlockId,
-    ) -> impl Iterator<Item = Result<CanonicalTx<'a, Transaction, A>, C::Error>>
-    where
-        C: ChainOracle + 'a,
-    {
+    ) -> impl Iterator<Item = Result<CanonicalTx<'a, Transaction, A>, C::Error>> {
         self.graph
             .full_txs()
             .filter(|node| tx_alters_owned_utxo_set(&self.graph, &self.index, node.txid, node.tx))
@@ -165,55 +159,55 @@ impl<A: Anchor, I: OwnedIndexer> IndexedTxGraph<A, I> {
             })
     }
 
-    pub fn list_owned_txs<'a, C>(
+    pub fn list_owned_txs<'a, C: ChainOracle<Error = Infallible> + 'a>(
         &'a self,
         chain: &'a C,
         chain_tip: BlockId,
-    ) -> impl Iterator<Item = CanonicalTx<'a, Transaction, A>>
-    where
-        C: ChainOracle<Error = Infallible> + 'a,
-    {
+    ) -> impl Iterator<Item = CanonicalTx<'a, Transaction, A>> {
         self.try_list_owned_txs(chain, chain_tip)
             .map(|r| r.expect("chain oracle is infallible"))
     }
 
-    pub fn try_list_owned_txouts<'a, C>(
+    pub fn try_list_owned_txouts<'a, C: ChainOracle + 'a>(
         &'a self,
         chain: &'a C,
         chain_tip: BlockId,
-    ) -> impl Iterator<Item = Result<FullTxOut<ObservedAs<A>>, C::Error>> + 'a
-    where
-        C: ChainOracle + 'a,
-    {
+    ) -> impl Iterator<Item = Result<FullTxOut<ObservedAs<A>>, C::Error>> + 'a {
         self.graph()
-            .try_list_chain_txouts(chain, chain_tip, |_, txout| {
-                self.index.is_spk_owned(&txout.script_pubkey)
+            .try_list_chain_txouts(chain, chain_tip)
+            .filter(|r| {
+                if let Ok(full_txout) = r {
+                    if !self.index.is_spk_owned(&full_txout.txout.script_pubkey) {
+                        return false;
+                    }
+                }
+                true
             })
     }
 
-    pub fn list_owned_txouts<'a, C>(
+    pub fn list_owned_txouts<'a, C: ChainOracle + 'a>(
         &'a self,
         chain: &'a C,
         chain_tip: BlockId,
-    ) -> impl Iterator<Item = FullTxOut<ObservedAs<A>>> + 'a
-    where
-        C: ChainOracle + 'a,
-    {
+    ) -> impl Iterator<Item = FullTxOut<ObservedAs<A>>> + 'a {
         self.try_list_owned_txouts(chain, chain_tip)
             .map(|r| r.expect("oracle is infallible"))
     }
 
-    pub fn try_list_owned_unspents<'a, C>(
+    pub fn try_list_owned_unspents<'a, C: ChainOracle + 'a>(
         &'a self,
         chain: &'a C,
         chain_tip: BlockId,
-    ) -> impl Iterator<Item = Result<FullTxOut<ObservedAs<A>>, C::Error>> + 'a
-    where
-        C: ChainOracle + 'a,
-    {
+    ) -> impl Iterator<Item = Result<FullTxOut<ObservedAs<A>>, C::Error>> + 'a {
         self.graph()
-            .try_list_chain_unspents(chain, chain_tip, |_, txout| {
-                self.index.is_spk_owned(&txout.script_pubkey)
+            .try_list_chain_unspents(chain, chain_tip)
+            .filter(|r| {
+                if let Ok(full_txout) = r {
+                    if !self.index.is_spk_owned(&full_txout.txout.script_pubkey) {
+                        return false;
+                    }
+                }
+                true
             })
     }
 
@@ -278,35 +272,26 @@ impl<A: Anchor + ConfirmationHeight, I: OwnedIndexer> IndexedTxGraph<A, I> {
         })
     }
 
-    pub fn balance<C, F>(
-        &self,
-        chain: &C,
-        static_block: BlockId,
-        tip: u32,
-        should_trust: F,
-    ) -> Balance
+    pub fn balance<C, F>(&self, chain: &C, chain_tip: BlockId, tip: u32, should_trust: F) -> Balance
     where
         C: ChainOracle<Error = Infallible>,
         F: FnMut(&Script) -> bool,
     {
-        self.try_balance(chain, static_block, tip, should_trust)
+        self.try_balance(chain, chain_tip, tip, should_trust)
             .expect("error is infallible")
     }
 
     pub fn try_balance_at<C>(
         &self,
         chain: &C,
-        static_block: BlockId,
+        chain_tip: BlockId,
         height: u32,
     ) -> Result<u64, C::Error>
     where
         C: ChainOracle,
     {
         let mut sum = 0;
-        for txo_res in self
-            .graph()
-            .try_list_chain_txouts(chain, static_block, |_, _| true)
-        {
+        for txo_res in self.try_list_owned_unspents(chain, chain_tip) {
             let txo = txo_res?;
             if txo.is_observed_as_confirmed_and_spendable(height) {
                 sum += txo.txout.value;
@@ -315,11 +300,11 @@ impl<A: Anchor + ConfirmationHeight, I: OwnedIndexer> IndexedTxGraph<A, I> {
         Ok(sum)
     }
 
-    pub fn balance_at<C>(&self, chain: &C, static_block: BlockId, height: u32) -> u64
+    pub fn balance_at<C>(&self, chain: &C, chain_tip: BlockId, height: u32) -> u64
     where
         C: ChainOracle<Error = Infallible>,
     {
-        self.try_balance_at(chain, static_block, height)
+        self.try_balance_at(chain, chain_tip, height)
             .expect("error is infallible")
     }
 }
index 88c688fe9344658a9d7f1dffc44a9ffe298809d8..30dfe80b8a850cc9f2e09f3cc842589b176eabf9 100644 (file)
@@ -3,7 +3,7 @@ use core::convert::Infallible;
 use alloc::collections::{BTreeMap, BTreeSet};
 use bitcoin::BlockHash;
 
-use crate::{Append, BlockId, ChainOracle};
+use crate::{BlockId, ChainOracle};
 
 /// This is a local implementation of [`ChainOracle`].
 ///
@@ -180,12 +180,6 @@ impl LocalChain {
 /// [`determine_changeset`]: LocalChain::determine_changeset
 pub type ChangeSet = BTreeMap<u32, Option<BlockHash>>;
 
-impl Append for ChangeSet {
-    fn append(&mut self, mut other: Self) {
-        BTreeMap::append(self, &mut other)
-    }
-}
-
 /// Represents an update failure of [`LocalChain`] due to the update not connecting to the original
 /// chain.
 ///
index fbcdcaa5f3c66f55a089d6aabf2eeb356b8b680c..55121695dd310eb1c96e615be1ed6741b0d6d9f1 100644 (file)
 //! );
 //! ```
 use core::{
-    convert::Infallible,
     fmt::Debug,
     ops::{Bound, RangeBounds},
 };
 
-use crate::{collections::*, tx_graph::TxGraph, BlockId, ChainOracle, FullTxOut, TxHeight};
+use crate::{collections::*, tx_graph::TxGraph, BlockId, FullTxOut, TxHeight};
 use bitcoin::{hashes::Hash, BlockHash, OutPoint, Txid};
 
 /// This is a non-monotone structure that tracks relevant [`Txid`]s that are ordered by chain
@@ -457,26 +456,6 @@ impl<P: core::fmt::Debug> core::fmt::Display for UpdateError<P> {
 #[cfg(feature = "std")]
 impl<P: core::fmt::Debug> std::error::Error for UpdateError<P> {}
 
-impl<P> ChainOracle for SparseChain<P> {
-    type Error = Infallible;
-
-    fn is_block_in_chain(
-        &self,
-        block: BlockId,
-        static_block: BlockId,
-    ) -> Result<Option<bool>, Self::Error> {
-        Ok(
-            match (
-                self.checkpoint_at(block.height),
-                self.checkpoint_at(static_block.height),
-            ) {
-                (Some(b), Some(static_b)) => Some(b == block && static_b == static_block),
-                _ => None,
-            },
-        )
-    }
-}
-
 impl<P> SparseChain<P> {
     /// Creates a new chain from a list of block hashes and heights. The caller must guarantee they
     /// are in the same chain.
index 9d41c549f0b25e2298589ea48b0cfc722820296f..bd7e66acb8012266f618c5d9b3847b8d4e98e7a9 100644 (file)
@@ -1,6 +1,7 @@
-use bitcoin::{Block, BlockHash, OutPoint, Transaction, TxOut};
-
+use crate::collections::BTreeMap;
+use crate::collections::BTreeSet;
 use crate::BlockId;
+use bitcoin::{Block, BlockHash, OutPoint, Transaction, TxOut};
 
 /// Trait to do something with every txout contained in a structure.
 ///
@@ -77,3 +78,15 @@ pub trait Append {
 impl Append for () {
     fn append(&mut self, _other: Self) {}
 }
+
+impl<K: Ord, V> Append for BTreeMap<K, V> {
+    fn append(&mut self, mut other: Self) {
+        BTreeMap::append(self, &mut other)
+    }
+}
+
+impl<T: Ord> Append for BTreeSet<T> {
+    fn append(&mut self, mut other: Self) {
+        BTreeSet::append(self, &mut other)
+    }
+}
index a1ddbf875b1e6063637db532ccf2ed7aa105fda9..07e4680e987551ff5acbe8ceaa88eed6cf7cb537 100644 (file)
@@ -627,15 +627,12 @@ impl<A: Anchor> TxGraph<A> {
     /// [`ChainOracle`] is infallible, [`get_chain_position`] can be used instead.
     ///
     /// [`get_chain_position`]: Self::get_chain_position
-    pub fn try_get_chain_position<C>(
+    pub fn try_get_chain_position<C: ChainOracle>(
         &self,
         chain: &C,
         chain_tip: BlockId,
         txid: Txid,
-    ) -> Result<Option<ObservedAs<&A>>, C::Error>
-    where
-        C: ChainOracle,
-    {
+    ) -> Result<Option<ObservedAs<&A>>, C::Error> {
         let (tx_node, anchors, &last_seen) = match self.txs.get(&txid) {
             Some((tx, anchors, last_seen)) if !(anchors.is_empty() && *last_seen == 0) => {
                 (tx, anchors, last_seen)
@@ -682,15 +679,12 @@ impl<A: Anchor> TxGraph<A> {
     /// This is the infallible version of [`try_get_chain_position`].
     ///
     /// [`try_get_chain_position`]: Self::try_get_chain_position
-    pub fn get_chain_position<C>(
+    pub fn get_chain_position<C: ChainOracle<Error = Infallible>>(
         &self,
         chain: &C,
         chain_tip: BlockId,
         txid: Txid,
-    ) -> Option<ObservedAs<&A>>
-    where
-        C: ChainOracle<Error = Infallible>,
-    {
+    ) -> Option<ObservedAs<&A>> {
         self.try_get_chain_position(chain, chain_tip, txid)
             .expect("error is infallible")
     }
@@ -707,15 +701,12 @@ impl<A: Anchor> TxGraph<A> {
     /// If the [`ChainOracle`] is infallible, [`get_chain_spend`] can be used instead.
     ///
     /// [`get_chain_spend`]: Self::get_chain_spend
-    pub fn try_get_chain_spend<C>(
+    pub fn try_get_chain_spend<C: ChainOracle>(
         &self,
         chain: &C,
         chain_tip: BlockId,
         outpoint: OutPoint,
-    ) -> Result<Option<(ObservedAs<&A>, Txid)>, C::Error>
-    where
-        C: ChainOracle,
-    {
+    ) -> Result<Option<(ObservedAs<&A>, Txid)>, C::Error> {
         if self
             .try_get_chain_position(chain, chain_tip, outpoint.txid)?
             .is_none()
@@ -738,15 +729,12 @@ impl<A: Anchor> TxGraph<A> {
     /// This is the infallible version of [`try_get_chain_spend`]
     ///
     /// [`try_get_chain_spend`]: Self::try_get_chain_spend
-    pub fn get_chain_spend<C>(
+    pub fn get_chain_spend<C: ChainOracle<Error = Infallible>>(
         &self,
         chain: &C,
         static_block: BlockId,
         outpoint: OutPoint,
-    ) -> Option<(ObservedAs<&A>, Txid)>
-    where
-        C: ChainOracle<Error = Infallible>,
-    {
+    ) -> Option<(ObservedAs<&A>, Txid)> {
         self.try_get_chain_spend(chain, static_block, outpoint)
             .expect("error is infallible")
     }
@@ -764,14 +752,11 @@ impl<A: Anchor> TxGraph<A> {
     /// If the [`ChainOracle`] is infallible, [`list_chain_txs`] can be used instead.
     ///
     /// [`list_chain_txs`]: Self::list_chain_txs
-    pub fn try_list_chain_txs<'a, C>(
+    pub fn try_list_chain_txs<'a, C: ChainOracle + 'a>(
         &'a self,
         chain: &'a C,
         chain_tip: BlockId,
-    ) -> impl Iterator<Item = Result<CanonicalTx<'a, Transaction, A>, C::Error>>
-    where
-        C: ChainOracle + 'a,
-    {
+    ) -> impl Iterator<Item = Result<CanonicalTx<'a, Transaction, A>, C::Error>> {
         self.full_txs().filter_map(move |tx| {
             self.try_get_chain_position(chain, chain_tip, tx.txid)
                 .map(|v| {
@@ -789,14 +774,11 @@ impl<A: Anchor> TxGraph<A> {
     /// This is the infallible version of [`try_list_chain_txs`].
     ///
     /// [`try_list_chain_txs`]: Self::try_list_chain_txs
-    pub fn list_chain_txs<'a, C>(
+    pub fn list_chain_txs<'a, C: ChainOracle + 'a>(
         &'a self,
         chain: &'a C,
         chain_tip: BlockId,
-    ) -> impl Iterator<Item = CanonicalTx<'a, Transaction, A>>
-    where
-        C: ChainOracle + 'a,
-    {
+    ) -> impl Iterator<Item = CanonicalTx<'a, Transaction, A>> {
         self.try_list_chain_txs(chain, chain_tip)
             .map(|r| r.expect("oracle is infallible"))
     }
@@ -814,16 +796,11 @@ impl<A: Anchor> TxGraph<A> {
     /// If the [`ChainOracle`] is infallible, [`list_chain_txouts`] can be used instead.
     ///
     /// [`list_chain_txouts`]: Self::list_chain_txouts
-    pub fn try_list_chain_txouts<'a, C, P>(
+    pub fn try_list_chain_txouts<'a, C: ChainOracle + 'a>(
         &'a self,
         chain: &'a C,
         chain_tip: BlockId,
-        mut filter_predicate: P,
-    ) -> impl Iterator<Item = Result<FullTxOut<ObservedAs<A>>, C::Error>> + 'a
-    where
-        C: ChainOracle + 'a,
-        P: FnMut(OutPoint, &TxOut) -> bool + 'a,
-    {
+    ) -> impl Iterator<Item = Result<FullTxOut<ObservedAs<A>>, C::Error>> + 'a {
         self.try_list_chain_txs(chain, chain_tip)
             .flat_map(move |tx_res| match tx_res {
                 Ok(canonical_tx) => canonical_tx
@@ -831,13 +808,9 @@ impl<A: Anchor> TxGraph<A> {
                     .output
                     .iter()
                     .enumerate()
-                    .filter_map(|(vout, txout)| {
+                    .map(|(vout, txout)| {
                         let outpoint = OutPoint::new(canonical_tx.node.txid, vout as _);
-                        if filter_predicate(outpoint, txout) {
-                            Some(Ok((outpoint, txout.clone(), canonical_tx.clone())))
-                        } else {
-                            None
-                        }
+                        Ok((outpoint, txout.clone(), canonical_tx.clone()))
                     })
                     .collect::<Vec<_>>(),
                 Err(err) => vec![Err(err)],
@@ -871,17 +844,12 @@ impl<A: Anchor> TxGraph<A> {
     /// This is the infallible version of [`try_list_chain_txouts`].
     ///
     /// [`try_list_chain_txouts`]: Self::try_list_chain_txouts
-    pub fn list_chain_txouts<'a, C, P>(
+    pub fn list_chain_txouts<'a, C: ChainOracle<Error = Infallible> + 'a>(
         &'a self,
         chain: &'a C,
         chain_tip: BlockId,
-        filter_predicate: P,
-    ) -> impl Iterator<Item = FullTxOut<ObservedAs<A>>> + 'a
-    where
-        C: ChainOracle<Error = Infallible> + 'a,
-        P: FnMut(OutPoint, &TxOut) -> bool + 'a,
-    {
-        self.try_list_chain_txouts(chain, chain_tip, filter_predicate)
+    ) -> impl Iterator<Item = FullTxOut<ObservedAs<A>>> + 'a {
+        self.try_list_chain_txouts(chain, chain_tip)
             .map(|r| r.expect("error in infallible"))
     }
 
@@ -895,17 +863,12 @@ impl<A: Anchor> TxGraph<A> {
     /// infallible, [`list_chain_unspents`] can be used instead.
     ///
     /// [`list_chain_unspents`]: Self::list_chain_unspents
-    pub fn try_list_chain_unspents<'a, C, P>(
+    pub fn try_list_chain_unspents<'a, C: ChainOracle + 'a>(
         &'a self,
         chain: &'a C,
         chain_tip: BlockId,
-        filter_txout: P,
-    ) -> impl Iterator<Item = Result<FullTxOut<ObservedAs<A>>, C::Error>> + 'a
-    where
-        C: ChainOracle + 'a,
-        P: FnMut(OutPoint, &TxOut) -> bool + 'a,
-    {
-        self.try_list_chain_txouts(chain, chain_tip, filter_txout)
+    ) -> impl Iterator<Item = Result<FullTxOut<ObservedAs<A>>, C::Error>> + 'a {
+        self.try_list_chain_txouts(chain, chain_tip)
             .filter(|r| !matches!(r, Ok(txo) if txo.spent_by.is_none()))
     }
 
@@ -914,17 +877,12 @@ impl<A: Anchor> TxGraph<A> {
     /// This is the infallible version of [`try_list_chain_unspents`].
     ///
     /// [`try_list_chain_unspents`]: Self::try_list_chain_unspents
-    pub fn list_chain_unspents<'a, C, P>(
+    pub fn list_chain_unspents<'a, C: ChainOracle<Error = Infallible> + 'a>(
         &'a self,
         chain: &'a C,
         static_block: BlockId,
-        filter_txout: P,
-    ) -> impl Iterator<Item = FullTxOut<ObservedAs<A>>> + 'a
-    where
-        C: ChainOracle<Error = Infallible> + 'a,
-        P: FnMut(OutPoint, &TxOut) -> bool + 'a,
-    {
-        self.try_list_chain_unspents(chain, static_block, filter_txout)
+    ) -> impl Iterator<Item = FullTxOut<ObservedAs<A>>> + 'a {
+        self.try_list_chain_unspents(chain, static_block)
             .map(|r| r.expect("error is infallible"))
     }
 }