]> Untitled Git - bdk/commitdiff
[bdk_chain_redesign] MOVE: `IndexedTxGraph` into submodule
author志宇 <hello@evanlinjin.me>
Mon, 27 Mar 2023 06:21:10 +0000 (14:21 +0800)
committer志宇 <hello@evanlinjin.me>
Mon, 27 Mar 2023 06:21:10 +0000 (14:21 +0800)
crates/chain/src/indexed_tx_graph.rs [new file with mode: 0644]
crates/chain/src/lib.rs
crates/chain/src/tx_graph.rs

diff --git a/crates/chain/src/indexed_tx_graph.rs b/crates/chain/src/indexed_tx_graph.rs
new file mode 100644 (file)
index 0000000..b0d547c
--- /dev/null
@@ -0,0 +1,248 @@
+use core::convert::Infallible;
+
+use alloc::collections::BTreeSet;
+use bitcoin::{OutPoint, Transaction, TxOut};
+
+use crate::{
+    sparse_chain::ChainPosition,
+    tx_graph::{Additions, TxGraph, TxInGraph},
+    BlockAnchor, ChainOracle, FullTxOut, ObservedIn, TxIndex, TxIndexAdditions,
+};
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct TxInChain<'a, T, A> {
+    pub observed_in: ObservedIn<&'a A>,
+    pub tx: TxInGraph<'a, T, A>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct TxOutInChain<'a, I, A> {
+    pub spk_index: &'a I,
+    pub txout: FullTxOut<ObservedIn<&'a A>>,
+}
+
+pub struct IndexedAdditions<A, D> {
+    pub graph_additions: Additions<A>,
+    pub index_delta: D,
+}
+
+impl<A, D: Default> Default for IndexedAdditions<A, D> {
+    fn default() -> Self {
+        Self {
+            graph_additions: Default::default(),
+            index_delta: Default::default(),
+        }
+    }
+}
+
+impl<A: BlockAnchor, D: TxIndexAdditions> TxIndexAdditions for IndexedAdditions<A, D> {
+    fn append_additions(&mut self, other: Self) {
+        let Self {
+            graph_additions,
+            index_delta,
+        } = other;
+        self.graph_additions.append(graph_additions);
+        self.index_delta.append_additions(index_delta);
+    }
+}
+
+pub struct IndexedTxGraph<A, I> {
+    graph: TxGraph<A>,
+    index: I,
+}
+
+impl<A, I: Default> Default for IndexedTxGraph<A, I> {
+    fn default() -> Self {
+        Self {
+            graph: Default::default(),
+            index: Default::default(),
+        }
+    }
+}
+
+impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
+    /// Get a reference of the internal transaction graph.
+    pub fn graph(&self) -> &TxGraph<A> {
+        &self.graph
+    }
+
+    /// Get a reference of the internal transaction index.
+    pub fn index(&self) -> &I {
+        &self.index
+    }
+
+    /// Insert a `txout` that exists in `outpoint` with the given `observation`.
+    pub fn insert_txout(
+        &mut self,
+        outpoint: OutPoint,
+        txout: &TxOut,
+        observation: ObservedIn<A>,
+    ) -> IndexedAdditions<A, I::Additions> {
+        IndexedAdditions {
+            graph_additions: {
+                let mut graph_additions = self.graph.insert_txout(outpoint, txout.clone());
+                graph_additions.append(match observation {
+                    ObservedIn::Block(anchor) => self.graph.insert_anchor(outpoint.txid, anchor),
+                    ObservedIn::Mempool(seen_at) => {
+                        self.graph.insert_seen_at(outpoint.txid, seen_at)
+                    }
+                });
+                graph_additions
+            },
+            index_delta: <I as TxIndex>::index_txout(&mut self.index, outpoint, txout),
+        }
+    }
+
+    pub fn insert_tx(
+        &mut self,
+        tx: &Transaction,
+        observation: ObservedIn<A>,
+    ) -> IndexedAdditions<A, I::Additions> {
+        let txid = tx.txid();
+        IndexedAdditions {
+            graph_additions: {
+                let mut graph_additions = self.graph.insert_tx(tx.clone());
+                graph_additions.append(match observation {
+                    ObservedIn::Block(anchor) => self.graph.insert_anchor(txid, anchor),
+                    ObservedIn::Mempool(seen_at) => self.graph.insert_seen_at(txid, seen_at),
+                });
+                graph_additions
+            },
+            index_delta: <I as TxIndex>::index_tx(&mut self.index, tx),
+        }
+    }
+
+    pub fn filter_and_insert_txs<'t, T>(
+        &mut self,
+        txs: T,
+        observation: ObservedIn<A>,
+    ) -> IndexedAdditions<A, I::Additions>
+    where
+        T: Iterator<Item = &'t Transaction>,
+    {
+        txs.filter_map(|tx| {
+            if self.index.is_tx_relevant(tx) {
+                Some(self.insert_tx(tx, observation.clone()))
+            } else {
+                None
+            }
+        })
+        .fold(IndexedAdditions::default(), |mut acc, other| {
+            acc.append_additions(other);
+            acc
+        })
+    }
+
+    pub fn relevant_heights(&self) -> BTreeSet<u32> {
+        self.graph.relevant_heights()
+    }
+
+    pub fn try_list_chain_txs<'a, C>(
+        &'a self,
+        chain: C,
+    ) -> impl Iterator<Item = Result<TxInChain<'a, Transaction, A>, C::Error>>
+    where
+        C: ChainOracle + 'a,
+    {
+        self.graph
+            .full_transactions()
+            .filter(|tx| self.index.is_tx_relevant(tx))
+            .filter_map(move |tx| {
+                self.graph
+                    .try_get_chain_position(&chain, tx.txid)
+                    .map(|v| v.map(|observed_in| TxInChain { observed_in, tx }))
+                    .transpose()
+            })
+    }
+
+    pub fn list_chain_txs<'a, C>(
+        &'a self,
+        chain: C,
+    ) -> impl Iterator<Item = TxInChain<'a, Transaction, A>>
+    where
+        C: ChainOracle<Error = Infallible> + 'a,
+    {
+        self.try_list_chain_txs(chain)
+            .map(|r| r.expect("error is infallible"))
+    }
+
+    pub fn try_list_chain_txouts<'a, C>(
+        &'a self,
+        chain: C,
+    ) -> impl Iterator<Item = Result<TxOutInChain<'a, I::SpkIndex, A>, C::Error>>
+    where
+        C: ChainOracle + 'a,
+        ObservedIn<A>: ChainPosition,
+    {
+        self.index.relevant_txouts().iter().filter_map(
+            move |(op, (spk_i, txout))| -> Option<Result<_, C::Error>> {
+                let graph_tx = self.graph.get_tx(op.txid)?;
+
+                let is_on_coinbase = graph_tx.is_coin_base();
+
+                let chain_position = match self.graph.try_get_chain_position(&chain, op.txid) {
+                    Ok(Some(observed_at)) => observed_at,
+                    Ok(None) => return None,
+                    Err(err) => return Some(Err(err)),
+                };
+
+                let spent_by = match self.graph.try_get_spend_in_chain(&chain, *op) {
+                    Ok(spent_by) => spent_by,
+                    Err(err) => return Some(Err(err)),
+                };
+
+                let full_txout = FullTxOut {
+                    outpoint: *op,
+                    txout: txout.clone(),
+                    chain_position,
+                    spent_by,
+                    is_on_coinbase,
+                };
+
+                let txout_in_chain = TxOutInChain {
+                    spk_index: spk_i,
+                    txout: full_txout,
+                };
+
+                Some(Ok(txout_in_chain))
+            },
+        )
+    }
+
+    pub fn list_chain_txouts<'a, C>(
+        &'a self,
+        chain: C,
+    ) -> impl Iterator<Item = TxOutInChain<'a, I::SpkIndex, A>>
+    where
+        C: ChainOracle<Error = Infallible> + 'a,
+        ObservedIn<A>: ChainPosition,
+    {
+        self.try_list_chain_txouts(chain)
+            .map(|r| r.expect("error in infallible"))
+    }
+
+    /// Return relevant unspents.
+    pub fn try_list_chain_utxos<'a, C>(
+        &'a self,
+        chain: C,
+    ) -> impl Iterator<Item = Result<TxOutInChain<'a, I::SpkIndex, A>, C::Error>>
+    where
+        C: ChainOracle + 'a,
+        ObservedIn<A>: ChainPosition,
+    {
+        self.try_list_chain_txouts(chain)
+            .filter(|r| !matches!(r, Ok(txo) if txo.txout.spent_by.is_none()))
+    }
+
+    pub fn list_chain_utxos<'a, C>(
+        &'a self,
+        chain: C,
+    ) -> impl Iterator<Item = TxOutInChain<'a, I::SpkIndex, A>>
+    where
+        C: ChainOracle<Error = Infallible> + 'a,
+        ObservedIn<A>: ChainPosition,
+    {
+        self.try_list_chain_utxos(chain)
+            .map(|r| r.expect("error is infallible"))
+    }
+}
index 4e49e34ed7690ce011f5052b93a9e6f99c66b560..5284409790e4279f51d1d475a53d44e5ae31965d 100644 (file)
@@ -24,6 +24,7 @@ mod spk_txout_index;
 pub use spk_txout_index::*;
 mod chain_data;
 pub use chain_data::*;
+pub mod indexed_tx_graph;
 pub mod keychain;
 pub mod sparse_chain;
 mod tx_data_traits;
index 63b7532460d6819515a2fd0b18fab28ab9f3fca2..ddeb5e13ee633ede9f1489336cd57a9eb9057022 100644 (file)
 //! assert!(additions.is_empty());
 //! ```
 
-use crate::{
-    collections::*, sparse_chain::ChainPosition, BlockAnchor, BlockId, ChainOracle, ForEachTxOut,
-    FullTxOut, ObservedIn, TxIndex, TxIndexAdditions,
-};
+use crate::{collections::*, BlockAnchor, BlockId, ChainOracle, ForEachTxOut, ObservedIn};
 use alloc::vec::Vec;
 use bitcoin::{OutPoint, Transaction, TxOut, Txid};
 use core::{
@@ -129,18 +126,6 @@ impl<'a, A> TxInGraph<'a, Transaction, A> {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub struct TxInChain<'a, T, A> {
-    pub observed_in: ObservedIn<&'a A>,
-    pub tx: TxInGraph<'a, T, A>,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub struct TxOutInChain<'a, I, A> {
-    pub spk_index: &'a I,
-    pub txout: FullTxOut<ObservedIn<&'a A>>,
-}
-
 /// Internal representation of a transaction node of a [`TxGraph`].
 ///
 /// This can either be a whole transaction, or a partial transaction (where we only have select
@@ -692,232 +677,6 @@ impl<A> TxGraph<A> {
     }
 }
 
-pub struct IndexedAdditions<A, D> {
-    pub graph_additions: Additions<A>,
-    pub index_delta: D,
-}
-
-impl<A, D: Default> Default for IndexedAdditions<A, D> {
-    fn default() -> Self {
-        Self {
-            graph_additions: Default::default(),
-            index_delta: Default::default(),
-        }
-    }
-}
-
-impl<A: BlockAnchor, D: TxIndexAdditions> TxIndexAdditions for IndexedAdditions<A, D> {
-    fn append_additions(&mut self, other: Self) {
-        let Self {
-            graph_additions,
-            index_delta,
-        } = other;
-        self.graph_additions.append(graph_additions);
-        self.index_delta.append_additions(index_delta);
-    }
-}
-
-pub struct IndexedTxGraph<A, I> {
-    graph: TxGraph<A>,
-    index: I,
-}
-
-impl<A, I: Default> Default for IndexedTxGraph<A, I> {
-    fn default() -> Self {
-        Self {
-            graph: Default::default(),
-            index: Default::default(),
-        }
-    }
-}
-
-impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
-    /// Get a reference of the internal transaction graph.
-    pub fn graph(&self) -> &TxGraph<A> {
-        &self.graph
-    }
-
-    /// Get a reference of the internal transaction index.
-    pub fn index(&self) -> &I {
-        &self.index
-    }
-
-    /// Insert a `txout` that exists in `outpoint` with the given `observation`.
-    pub fn insert_txout(
-        &mut self,
-        outpoint: OutPoint,
-        txout: &TxOut,
-        observation: ObservedIn<A>,
-    ) -> IndexedAdditions<A, I::Additions> {
-        IndexedAdditions {
-            graph_additions: {
-                let mut graph_additions = self.graph.insert_txout(outpoint, txout.clone());
-                graph_additions.append(match observation {
-                    ObservedIn::Block(anchor) => self.graph.insert_anchor(outpoint.txid, anchor),
-                    ObservedIn::Mempool(seen_at) => {
-                        self.graph.insert_seen_at(outpoint.txid, seen_at)
-                    }
-                });
-                graph_additions
-            },
-            index_delta: <I as TxIndex>::index_txout(&mut self.index, outpoint, txout),
-        }
-    }
-
-    pub fn insert_tx(
-        &mut self,
-        tx: &Transaction,
-        observation: ObservedIn<A>,
-    ) -> IndexedAdditions<A, I::Additions> {
-        let txid = tx.txid();
-        IndexedAdditions {
-            graph_additions: {
-                let mut graph_additions = self.graph.insert_tx(tx.clone());
-                graph_additions.append(match observation {
-                    ObservedIn::Block(anchor) => self.graph.insert_anchor(txid, anchor),
-                    ObservedIn::Mempool(seen_at) => self.graph.insert_seen_at(txid, seen_at),
-                });
-                graph_additions
-            },
-            index_delta: <I as TxIndex>::index_tx(&mut self.index, tx),
-        }
-    }
-
-    pub fn filter_and_insert_txs<'t, T>(
-        &mut self,
-        txs: T,
-        observation: ObservedIn<A>,
-    ) -> IndexedAdditions<A, I::Additions>
-    where
-        T: Iterator<Item = &'t Transaction>,
-    {
-        txs.filter_map(|tx| {
-            if self.index.is_tx_relevant(tx) {
-                Some(self.insert_tx(tx, observation.clone()))
-            } else {
-                None
-            }
-        })
-        .fold(IndexedAdditions::default(), |mut acc, other| {
-            acc.append_additions(other);
-            acc
-        })
-    }
-
-    pub fn relevant_heights(&self) -> BTreeSet<u32> {
-        self.graph.relevant_heights()
-    }
-
-    pub fn try_list_chain_txs<'a, C>(
-        &'a self,
-        chain: C,
-    ) -> impl Iterator<Item = Result<TxInChain<'a, Transaction, A>, C::Error>>
-    where
-        C: ChainOracle + 'a,
-    {
-        self.graph
-            .full_transactions()
-            .filter(|tx| self.index.is_tx_relevant(tx))
-            .filter_map(move |tx| {
-                self.graph
-                    .try_get_chain_position(&chain, tx.txid)
-                    .map(|v| v.map(|observed_in| TxInChain { observed_in, tx }))
-                    .transpose()
-            })
-    }
-
-    pub fn list_chain_txs<'a, C>(
-        &'a self,
-        chain: C,
-    ) -> impl Iterator<Item = TxInChain<'a, Transaction, A>>
-    where
-        C: ChainOracle<Error = Infallible> + 'a,
-    {
-        self.try_list_chain_txs(chain)
-            .map(|r| r.expect("error is infallible"))
-    }
-
-    pub fn try_list_chain_txouts<'a, C>(
-        &'a self,
-        chain: C,
-    ) -> impl Iterator<Item = Result<TxOutInChain<'a, I::SpkIndex, A>, C::Error>>
-    where
-        C: ChainOracle + 'a,
-        ObservedIn<A>: ChainPosition,
-    {
-        self.index.relevant_txouts().iter().filter_map(
-            move |(op, (spk_i, txout))| -> Option<Result<_, C::Error>> {
-                let graph_tx = self.graph.get_tx(op.txid)?;
-
-                let is_on_coinbase = graph_tx.is_coin_base();
-
-                let chain_position = match self.graph.try_get_chain_position(&chain, op.txid) {
-                    Ok(Some(observed_at)) => observed_at,
-                    Ok(None) => return None,
-                    Err(err) => return Some(Err(err)),
-                };
-
-                let spent_by = match self.graph.try_get_spend_in_chain(&chain, *op) {
-                    Ok(spent_by) => spent_by,
-                    Err(err) => return Some(Err(err)),
-                };
-
-                let full_txout = FullTxOut {
-                    outpoint: *op,
-                    txout: txout.clone(),
-                    chain_position,
-                    spent_by,
-                    is_on_coinbase,
-                };
-
-                let txout_in_chain = TxOutInChain {
-                    spk_index: spk_i,
-                    txout: full_txout,
-                };
-
-                Some(Ok(txout_in_chain))
-            },
-        )
-    }
-
-    pub fn list_chain_txouts<'a, C>(
-        &'a self,
-        chain: C,
-    ) -> impl Iterator<Item = TxOutInChain<'a, I::SpkIndex, A>>
-    where
-        C: ChainOracle<Error = Infallible> + 'a,
-        ObservedIn<A>: ChainPosition,
-    {
-        self.try_list_chain_txouts(chain)
-            .map(|r| r.expect("error in infallible"))
-    }
-
-    /// Return relevant unspents.
-    pub fn try_list_chain_utxos<'a, C>(
-        &'a self,
-        chain: C,
-    ) -> impl Iterator<Item = Result<TxOutInChain<'a, I::SpkIndex, A>, C::Error>>
-    where
-        C: ChainOracle + 'a,
-        ObservedIn<A>: ChainPosition,
-    {
-        self.try_list_chain_txouts(chain)
-            .filter(|r| !matches!(r, Ok(txo) if txo.txout.spent_by.is_none()))
-    }
-
-    pub fn list_chain_utxos<'a, C>(
-        &'a self,
-        chain: C,
-    ) -> impl Iterator<Item = TxOutInChain<'a, I::SpkIndex, A>>
-    where
-        C: ChainOracle<Error = Infallible> + 'a,
-        ObservedIn<A>: ChainPosition,
-    {
-        self.try_list_chain_utxos(chain)
-            .map(|r| r.expect("error is infallible"))
-    }
-}
-
 /// A structure that represents changes to a [`TxGraph`].
 ///
 /// It is named "additions" because [`TxGraph`] is monotone, so transactions can only be added and