]> Untitled Git - bdk/commitdiff
[bdk_chain_redesign] Make default anchor for `TxGraph` as `()`
author志宇 <hello@evanlinjin.me>
Thu, 30 Mar 2023 10:14:44 +0000 (18:14 +0800)
committer志宇 <hello@evanlinjin.me>
Thu, 30 Mar 2023 10:14:44 +0000 (18:14 +0800)
This allows us to use the old API with minimal changes. `TxGraph`
methods have also been rearranged to allow for it.

crates/bdk/src/wallet/mod.rs
crates/chain/src/chain_graph.rs
crates/chain/src/tx_graph.rs

index 6e4adf74b46ef93d2fe5b4e6152f01be778be750..84040d5fd19898e33e50e1d5cb497784e71848ce 100644 (file)
@@ -524,7 +524,7 @@ impl<D> Wallet<D> {
     /// unconfirmed transactions last.
     pub fn transactions(
         &self,
-    ) -> impl DoubleEndedIterator<Item = (ConfirmationTime, TxInGraph<'_, Transaction, BlockId>)> + '_
+    ) -> impl DoubleEndedIterator<Item = (ConfirmationTime, TxInGraph<'_, Transaction, ()>)> + '_
     {
         self.keychain_tracker
             .chain_graph()
index 3c841965afd820b8e7cb6852e8073a2500f4c2cb..85a4c956e8ab3a839fcb3867af6ebf86f1ada1c5 100644 (file)
@@ -27,7 +27,7 @@ use core::fmt::Debug;
 #[derive(Clone, Debug, PartialEq)]
 pub struct ChainGraph<P = TxHeight> {
     chain: SparseChain<P>,
-    graph: TxGraph<BlockId>,
+    graph: TxGraph,
 }
 
 impl<P> Default for ChainGraph<P> {
@@ -45,8 +45,8 @@ impl<P> AsRef<SparseChain<P>> for ChainGraph<P> {
     }
 }
 
-impl<P> AsRef<TxGraph<BlockId>> for ChainGraph<P> {
-    fn as_ref(&self) -> &TxGraph<BlockId> {
+impl<P> AsRef<TxGraph> for ChainGraph<P> {
+    fn as_ref(&self) -> &TxGraph {
         &self.graph
     }
 }
@@ -64,7 +64,7 @@ impl<P> ChainGraph<P> {
     }
 
     /// Returns a reference to the internal [`TxGraph`].
-    pub fn graph(&self) -> &TxGraph<BlockId> {
+    pub fn graph(&self) -> &TxGraph {
         &self.graph
     }
 }
@@ -81,7 +81,7 @@ where
     /// transaction in `graph`.
     /// 2. The `chain` has two transactions that are allegedly in it, but they conflict in the `graph`
     /// (so could not possibly be in the same chain).
-    pub fn new(chain: SparseChain<P>, graph: TxGraph<BlockId>) -> Result<Self, NewError<P>> {
+    pub fn new(chain: SparseChain<P>, graph: TxGraph) -> Result<Self, NewError<P>> {
         let mut missing = HashSet::default();
         for (pos, txid) in chain.txids() {
             if let Some(graphed_tx) = graph.get_tx(*txid) {
@@ -212,7 +212,7 @@ where
     ///
     /// This does not necessarily mean that it is *confirmed* in the blockchain; it might just be in
     /// the unconfirmed transaction list within the [`SparseChain`].
-    pub fn get_tx_in_chain(&self, txid: Txid) -> Option<(&P, TxInGraph<'_, Transaction, BlockId>)> {
+    pub fn get_tx_in_chain(&self, txid: Txid) -> Option<(&P, TxInGraph<'_, Transaction, ()>)> {
         let position = self.chain.tx_position(txid)?;
         let graphed_tx = self.graph.get_tx(txid).expect("must exist");
         Some((position, graphed_tx))
@@ -430,7 +430,7 @@ where
     /// in ascending order.
     pub fn transactions_in_chain(
         &self,
-    ) -> impl DoubleEndedIterator<Item = (&P, TxInGraph<'_, Transaction, BlockId>)> {
+    ) -> impl DoubleEndedIterator<Item = (&P, TxInGraph<'_, Transaction, ()>)> {
         self.chain
             .txids()
             .map(move |(pos, txid)| (pos, self.graph.get_tx(*txid).expect("must exist")))
@@ -469,7 +469,7 @@ where
 #[must_use]
 pub struct ChangeSet<P> {
     pub chain: sparse_chain::ChangeSet<P>,
-    pub graph: tx_graph::Additions<BlockId>,
+    pub graph: tx_graph::Additions<()>,
 }
 
 impl<P> ChangeSet<P> {
index ddeb5e13ee633ede9f1489336cd57a9eb9057022..2236822b270d6ce99588ed807cbd31728ea28789 100644 (file)
@@ -55,7 +55,7 @@
 //! assert!(additions.is_empty());
 //! ```
 
-use crate::{collections::*, BlockAnchor, BlockId, ChainOracle, ForEachTxOut, ObservedIn};
+use crate::{collections::*, BlockAnchor, ChainOracle, ForEachTxOut, ObservedIn};
 use alloc::vec::Vec;
 use bitcoin::{OutPoint, Transaction, TxOut, Txid};
 use core::{
@@ -69,7 +69,7 @@ use core::{
 ///
 /// [module-level documentation]: crate::tx_graph
 #[derive(Clone, Debug, PartialEq)]
-pub struct TxGraph<A = BlockId> {
+pub struct TxGraph<A = ()> {
     // all transactions that the graph is aware of in format: `(tx_node, tx_anchors, tx_last_seen)`
     txs: HashMap<Txid, (TxNode, BTreeSet<A>, u64)>,
     spends: BTreeMap<OutPoint, HashSet<Txid>>,
@@ -244,9 +244,111 @@ impl<A> TxGraph<A> {
 
         Some(inputs_sum - outputs_sum)
     }
+
+    /// The transactions spending from this output.
+    ///
+    /// `TxGraph` allows conflicting transactions within the graph. Obviously the transactions in
+    /// the returned set will never be in the same active-chain.
+    pub fn outspends(&self, outpoint: OutPoint) -> &HashSet<Txid> {
+        self.spends.get(&outpoint).unwrap_or(&self.empty_outspends)
+    }
+
+    /// Iterates over the transactions spending from `txid`.
+    ///
+    /// The iterator item is a union of `(vout, txid-set)` where:
+    ///
+    /// - `vout` is the provided `txid`'s outpoint that is being spent
+    /// - `txid-set` is the set of txids spending the `vout`.
+    pub fn tx_outspends(
+        &self,
+        txid: Txid,
+    ) -> impl DoubleEndedIterator<Item = (u32, &HashSet<Txid>)> + '_ {
+        let start = OutPoint { txid, vout: 0 };
+        let end = OutPoint {
+            txid,
+            vout: u32::MAX,
+        };
+        self.spends
+            .range(start..=end)
+            .map(|(outpoint, spends)| (outpoint.vout, spends))
+    }
+
+    /// Iterate over all partial transactions (outputs only) in the graph.
+    pub fn partial_transactions(
+        &self,
+    ) -> impl Iterator<Item = TxInGraph<'_, BTreeMap<u32, TxOut>, A>> {
+        self.txs
+            .iter()
+            .filter_map(|(&txid, (tx, anchors, last_seen))| match tx {
+                TxNode::Whole(_) => None,
+                TxNode::Partial(partial) => Some(TxInGraph {
+                    txid,
+                    tx: partial,
+                    anchors,
+                    last_seen: *last_seen,
+                }),
+            })
+    }
+
+    /// Creates an iterator that filters and maps descendants from the starting `txid`.
+    ///
+    /// The supplied closure takes in two inputs `(depth, descendant_txid)`:
+    ///
+    /// * `depth` is the distance between the starting `txid` and the `descendant_txid`. I.e., if the
+    ///     descendant is spending an output of the starting `txid`; the `depth` will be 1.
+    /// * `descendant_txid` is the descendant's txid which we are considering to walk.
+    ///
+    /// The supplied closure returns an `Option<T>`, allowing the caller to map each node it vists
+    /// and decide whether to visit descendants.
+    pub fn walk_descendants<'g, F, O>(&'g self, txid: Txid, walk_map: F) -> TxDescendants<A, F>
+    where
+        F: FnMut(usize, Txid) -> Option<O> + 'g,
+    {
+        TxDescendants::new_exclude_root(self, txid, walk_map)
+    }
+
+    /// Creates an iterator that both filters and maps conflicting transactions (this includes
+    /// descendants of directly-conflicting transactions, which are also considered conflicts).
+    ///
+    /// Refer to [`Self::walk_descendants`] for `walk_map` usage.
+    pub fn walk_conflicts<'g, F, O>(
+        &'g self,
+        tx: &'g Transaction,
+        walk_map: F,
+    ) -> TxDescendants<A, F>
+    where
+        F: FnMut(usize, Txid) -> Option<O> + 'g,
+    {
+        let txids = self.direct_conflicts_of_tx(tx).map(|(_, txid)| txid);
+        TxDescendants::from_multiple_include_root(self, txids, walk_map)
+    }
+
+    /// Given a transaction, return an iterator of txids that directly conflict with the given
+    /// transaction's inputs (spends). The conflicting txids are returned with the given
+    /// transaction's vin (in which it conflicts).
+    ///
+    /// Note that this only returns directly conflicting txids and does not include descendants of
+    /// those txids (which are technically also conflicting).
+    pub fn direct_conflicts_of_tx<'g>(
+        &'g self,
+        tx: &'g Transaction,
+    ) -> impl Iterator<Item = (usize, Txid)> + '_ {
+        let txid = tx.txid();
+        tx.input
+            .iter()
+            .enumerate()
+            .filter_map(move |(vin, txin)| self.spends.get(&txin.previous_output).zip(Some(vin)))
+            .flat_map(|(spends, vin)| core::iter::repeat(vin).zip(spends.iter().cloned()))
+            .filter(move |(_, conflicting_txid)| *conflicting_txid != txid)
+    }
+
+    /// Whether the graph has any transactions or outputs in it.
+    pub fn is_empty(&self) -> bool {
+        self.txs.is_empty()
+    }
 }
 
-impl<A: BlockAnchor> TxGraph<A> {
+impl<A: Clone + Ord> TxGraph<A> {
     /// Construct a new [`TxGraph`] from a list of transactions.
     pub fn new(txs: impl IntoIterator<Item = Transaction>) -> Self {
         let mut new = Self::default();
@@ -256,6 +358,24 @@ impl<A: BlockAnchor> TxGraph<A> {
         new
     }
 
+    /// Returns the resultant [`Additions`] if the given `txout` is inserted at `outpoint`. Does not
+    /// mutate `self`.
+    ///
+    /// The [`Additions`] result will be empty if the `outpoint` (or a full transaction containing
+    /// the `outpoint`) already existed in `self`.
+    pub fn insert_txout_preview(&self, outpoint: OutPoint, txout: TxOut) -> Additions<A> {
+        let mut update = Self::default();
+        update.txs.insert(
+            outpoint.txid,
+            (
+                TxNode::Partial([(outpoint.vout, txout)].into()),
+                BTreeSet::new(),
+                0,
+            ),
+        );
+        self.determine_additions(&update)
+    }
+
     /// Inserts the given [`TxOut`] at [`OutPoint`].
     ///
     /// Note this will ignore the action if we already have the full transaction that the txout is
@@ -266,6 +386,18 @@ impl<A: BlockAnchor> TxGraph<A> {
         additions
     }
 
+    /// Returns the resultant [`Additions`] if the given transaction is inserted. Does not actually
+    /// mutate [`Self`].
+    ///
+    /// The [`Additions`] result will be empty if `tx` already exists in `self`.
+    pub fn insert_tx_preview(&self, tx: Transaction) -> Additions<A> {
+        let mut update = Self::default();
+        update
+            .txs
+            .insert(tx.txid(), (TxNode::Whole(tx), BTreeSet::new(), 0));
+        self.determine_additions(&update)
+    }
+
     /// Inserts the given transaction into [`TxGraph`].
     ///
     /// The [`Additions`] returned will be empty if `tx` already exists.
@@ -275,6 +407,13 @@ impl<A: BlockAnchor> TxGraph<A> {
         additions
     }
 
+    /// Returns the resultant [`Additions`] if the `txid` is set in `anchor`.
+    pub fn insert_anchor_preview(&self, txid: Txid, anchor: A) -> Additions<A> {
+        let mut update = Self::default();
+        update.anchors.insert((anchor, txid));
+        self.determine_additions(&update)
+    }
+
     /// Inserts the given `anchor` into [`TxGraph`].
     ///
     /// This is equivalent to calling [`insert_anchor_preview`] and [`apply_additions`] in sequence.
@@ -289,6 +428,16 @@ impl<A: BlockAnchor> TxGraph<A> {
         additions
     }
 
+    /// Returns the resultant [`Additions`] if the `txid` is set to `seen_at`.
+    ///
+    /// Note that [`TxGraph`] only keeps track of the lastest `seen_at`.
+    pub fn insert_seen_at_preview(&self, txid: Txid, seen_at: u64) -> Additions<A> {
+        let mut update = Self::default();
+        let (_, _, update_last_seen) = update.txs.entry(txid).or_default();
+        *update_last_seen = seen_at;
+        self.determine_additions(&update)
+    }
+
     /// Inserts the given `seen_at` into [`TxGraph`].
     ///
     /// This is equivalent to calling [`insert_seen_at_preview`] and [`apply_additions`] in
@@ -421,54 +570,9 @@ impl<A: BlockAnchor> TxGraph<A> {
 
         additions
     }
+}
 
-    /// Returns the resultant [`Additions`] if the given transaction is inserted. Does not actually
-    /// mutate [`Self`].
-    ///
-    /// The [`Additions`] result will be empty if `tx` already exists in `self`.
-    pub fn insert_tx_preview(&self, tx: Transaction) -> Additions<A> {
-        let mut update = Self::default();
-        update
-            .txs
-            .insert(tx.txid(), (TxNode::Whole(tx), BTreeSet::new(), 0));
-        self.determine_additions(&update)
-    }
-
-    /// Returns the resultant [`Additions`] if the given `txout` is inserted at `outpoint`. Does not
-    /// mutate `self`.
-    ///
-    /// The [`Additions`] result will be empty if the `outpoint` (or a full transaction containing
-    /// the `outpoint`) already existed in `self`.
-    pub fn insert_txout_preview(&self, outpoint: OutPoint, txout: TxOut) -> Additions<A> {
-        let mut update = Self::default();
-        update.txs.insert(
-            outpoint.txid,
-            (
-                TxNode::Partial([(outpoint.vout, txout)].into()),
-                BTreeSet::new(),
-                0,
-            ),
-        );
-        self.determine_additions(&update)
-    }
-
-    /// Returns the resultant [`Additions`] if the `txid` is set in `anchor`.
-    pub fn insert_anchor_preview(&self, txid: Txid, anchor: A) -> Additions<A> {
-        let mut update = Self::default();
-        update.anchors.insert((anchor, txid));
-        self.determine_additions(&update)
-    }
-
-    /// Returns the resultant [`Additions`] if the `txid` is set to `seen_at`.
-    ///
-    /// Note that [`TxGraph`] only keeps track of the lastest `seen_at`.
-    pub fn insert_seen_at_preview(&self, txid: Txid, seen_at: u64) -> Additions<A> {
-        let mut update = Self::default();
-        let (_, _, update_last_seen) = update.txs.entry(txid).or_default();
-        *update_last_seen = seen_at;
-        self.determine_additions(&update)
-    }
-
+impl<A: BlockAnchor> TxGraph<A> {
     /// Get all heights that are relevant to the graph.
     pub fn relevant_heights(&self) -> BTreeSet<u32> {
         self.anchors
@@ -573,110 +677,6 @@ impl<A: BlockAnchor> TxGraph<A> {
     }
 }
 
-impl<A> TxGraph<A> {
-    /// The transactions spending from this output.
-    ///
-    /// `TxGraph` allows conflicting transactions within the graph. Obviously the transactions in
-    /// the returned set will never be in the same active-chain.
-    pub fn outspends(&self, outpoint: OutPoint) -> &HashSet<Txid> {
-        self.spends.get(&outpoint).unwrap_or(&self.empty_outspends)
-    }
-
-    /// Iterates over the transactions spending from `txid`.
-    ///
-    /// The iterator item is a union of `(vout, txid-set)` where:
-    ///
-    /// - `vout` is the provided `txid`'s outpoint that is being spent
-    /// - `txid-set` is the set of txids spending the `vout`.
-    pub fn tx_outspends(
-        &self,
-        txid: Txid,
-    ) -> impl DoubleEndedIterator<Item = (u32, &HashSet<Txid>)> + '_ {
-        let start = OutPoint { txid, vout: 0 };
-        let end = OutPoint {
-            txid,
-            vout: u32::MAX,
-        };
-        self.spends
-            .range(start..=end)
-            .map(|(outpoint, spends)| (outpoint.vout, spends))
-    }
-
-    /// Iterate over all partial transactions (outputs only) in the graph.
-    pub fn partial_transactions(
-        &self,
-    ) -> impl Iterator<Item = TxInGraph<'_, BTreeMap<u32, TxOut>, A>> {
-        self.txs
-            .iter()
-            .filter_map(|(&txid, (tx, anchors, last_seen))| match tx {
-                TxNode::Whole(_) => None,
-                TxNode::Partial(partial) => Some(TxInGraph {
-                    txid,
-                    tx: partial,
-                    anchors,
-                    last_seen: *last_seen,
-                }),
-            })
-    }
-
-    /// Creates an iterator that filters and maps descendants from the starting `txid`.
-    ///
-    /// The supplied closure takes in two inputs `(depth, descendant_txid)`:
-    ///
-    /// * `depth` is the distance between the starting `txid` and the `descendant_txid`. I.e., if the
-    ///     descendant is spending an output of the starting `txid`; the `depth` will be 1.
-    /// * `descendant_txid` is the descendant's txid which we are considering to walk.
-    ///
-    /// The supplied closure returns an `Option<T>`, allowing the caller to map each node it vists
-    /// and decide whether to visit descendants.
-    pub fn walk_descendants<'g, F, O>(&'g self, txid: Txid, walk_map: F) -> TxDescendants<A, F>
-    where
-        F: FnMut(usize, Txid) -> Option<O> + 'g,
-    {
-        TxDescendants::new_exclude_root(self, txid, walk_map)
-    }
-
-    /// Creates an iterator that both filters and maps conflicting transactions (this includes
-    /// descendants of directly-conflicting transactions, which are also considered conflicts).
-    ///
-    /// Refer to [`Self::walk_descendants`] for `walk_map` usage.
-    pub fn walk_conflicts<'g, F, O>(
-        &'g self,
-        tx: &'g Transaction,
-        walk_map: F,
-    ) -> TxDescendants<A, F>
-    where
-        F: FnMut(usize, Txid) -> Option<O> + 'g,
-    {
-        let txids = self.direct_conflicts_of_tx(tx).map(|(_, txid)| txid);
-        TxDescendants::from_multiple_include_root(self, txids, walk_map)
-    }
-
-    /// Given a transaction, return an iterator of txids that directly conflict with the given
-    /// transaction's inputs (spends). The conflicting txids are returned with the given
-    /// transaction's vin (in which it conflicts).
-    ///
-    /// Note that this only returns directly conflicting txids and does not include descendants of
-    /// those txids (which are technically also conflicting).
-    pub fn direct_conflicts_of_tx<'g>(
-        &'g self,
-        tx: &'g Transaction,
-    ) -> impl Iterator<Item = (usize, Txid)> + '_ {
-        let txid = tx.txid();
-        tx.input
-            .iter()
-            .enumerate()
-            .filter_map(move |(vin, txin)| self.spends.get(&txin.previous_output).zip(Some(vin)))
-            .flat_map(|(spends, vin)| core::iter::repeat(vin).zip(spends.iter().cloned()))
-            .filter(move |(_, conflicting_txid)| *conflicting_txid != txid)
-    }
-
-    /// Whether the graph has any transactions or outputs in it.
-    pub fn is_empty(&self) -> bool {
-        self.txs.is_empty()
-    }
-}
-
 /// A structure that represents changes to a [`TxGraph`].
 ///
 /// It is named "additions" because [`TxGraph`] is monotone, so transactions can only be added and
@@ -698,7 +698,7 @@ impl<A> TxGraph<A> {
     )
 )]
 #[must_use]
-pub struct Additions<A = BlockId> {
+pub struct Additions<A> {
     pub tx: BTreeSet<Transaction>,
     pub txout: BTreeMap<OutPoint, TxOut>,
     pub anchors: BTreeSet<(A, Txid)>,