]> Untitled Git - bdk/commitdiff
ref(tx_graph): Change last_seen to `HashMap<Txid, u64>`
authorvalued mammal <valuedmammal@protonmail.com>
Sun, 30 Jun 2024 14:53:35 +0000 (10:53 -0400)
committervalued mammal <valuedmammal@protonmail.com>
Sun, 30 Jun 2024 15:26:15 +0000 (11:26 -0400)
crates/chain/src/tx_graph.rs

index 199c85ea91428bfac8bb4987a2c85ca60c4298ca..b79aa434ec6109bc2e77f82dcd960af4ed914005 100644 (file)
@@ -109,10 +109,11 @@ use core::{
 /// [module-level documentation]: crate::tx_graph
 #[derive(Clone, Debug, PartialEq)]
 pub struct TxGraph<A = ()> {
-    // all transactions that the graph is aware of in format: `(tx_node, tx_anchors, tx_last_seen)`
-    txs: HashMap<Txid, (TxNodeInternal, BTreeSet<A>, Option<u64>)>,
+    // all transactions that the graph is aware of in format: `(tx_node, tx_anchors)`
+    txs: HashMap<Txid, (TxNodeInternal, BTreeSet<A>)>,
     spends: BTreeMap<OutPoint, HashSet<Txid>>,
     anchors: BTreeSet<(A, Txid)>,
+    last_seen: HashMap<Txid, u64>,
 
     // This atrocity exists so that `TxGraph::outspends()` can return a reference.
     // FIXME: This can be removed once `HashSet::new` is a const fn.
@@ -125,6 +126,7 @@ impl<A> Default for TxGraph<A> {
             txs: Default::default(),
             spends: Default::default(),
             anchors: Default::default(),
+            last_seen: Default::default(),
             empty_outspends: Default::default(),
         }
     }
@@ -210,7 +212,7 @@ impl<A> TxGraph<A> {
     ///
     /// This includes txouts of both full transactions as well as floating transactions.
     pub fn all_txouts(&self) -> impl Iterator<Item = (OutPoint, &TxOut)> {
-        self.txs.iter().flat_map(|(txid, (tx, _, _))| match tx {
+        self.txs.iter().flat_map(|(txid, (tx, _))| match tx {
             TxNodeInternal::Whole(tx) => tx
                 .as_ref()
                 .output
@@ -232,7 +234,7 @@ impl<A> TxGraph<A> {
     pub fn floating_txouts(&self) -> impl Iterator<Item = (OutPoint, &TxOut)> {
         self.txs
             .iter()
-            .filter_map(|(txid, (tx_node, _, _))| match tx_node {
+            .filter_map(|(txid, (tx_node, _))| match tx_node {
                 TxNodeInternal::Whole(_) => None,
                 TxNodeInternal::Partial(txouts) => Some(
                     txouts
@@ -247,12 +249,12 @@ impl<A> TxGraph<A> {
     pub fn full_txs(&self) -> impl Iterator<Item = TxNode<'_, Arc<Transaction>, A>> {
         self.txs
             .iter()
-            .filter_map(|(&txid, (tx, anchors, last_seen))| match tx {
+            .filter_map(|(&txid, (tx, anchors))| match tx {
                 TxNodeInternal::Whole(tx) => Some(TxNode {
                     txid,
                     tx: tx.clone(),
                     anchors,
-                    last_seen_unconfirmed: *last_seen,
+                    last_seen_unconfirmed: self.last_seen.get(&txid).copied(),
                 }),
                 TxNodeInternal::Partial(_) => None,
             })
@@ -283,11 +285,11 @@ impl<A> TxGraph<A> {
     /// Get a transaction node by txid. This only returns `Some` for full transactions.
     pub fn get_tx_node(&self, txid: Txid) -> Option<TxNode<'_, Arc<Transaction>, A>> {
         match &self.txs.get(&txid)? {
-            (TxNodeInternal::Whole(tx), anchors, last_seen) => Some(TxNode {
+            (TxNodeInternal::Whole(tx), anchors) => Some(TxNode {
                 txid,
                 tx: tx.clone(),
                 anchors,
-                last_seen_unconfirmed: *last_seen,
+                last_seen_unconfirmed: self.last_seen.get(&txid).copied(),
             }),
             _ => None,
         }
@@ -517,7 +519,6 @@ impl<A: Clone + Ord> TxGraph<A> {
             (
                 TxNodeInternal::Partial([(outpoint.vout, txout)].into()),
                 BTreeSet::new(),
-                None,
             ),
         );
         self.apply_update(update)
@@ -531,7 +532,7 @@ impl<A: Clone + Ord> TxGraph<A> {
         let mut update = Self::default();
         update.txs.insert(
             tx.compute_txid(),
-            (TxNodeInternal::Whole(tx), BTreeSet::new(), None),
+            (TxNodeInternal::Whole(tx), BTreeSet::new()),
         );
         self.apply_update(update)
     }
@@ -572,8 +573,7 @@ impl<A: Clone + Ord> TxGraph<A> {
     /// [`update_last_seen_unconfirmed`]: Self::update_last_seen_unconfirmed
     pub fn insert_seen_at(&mut self, txid: Txid, seen_at: u64) -> ChangeSet<A> {
         let mut update = Self::default();
-        let (_, _, update_last_seen) = update.txs.entry(txid).or_default();
-        *update_last_seen = Some(seen_at);
+        update.last_seen.insert(txid, seen_at);
         self.apply_update(update)
     }
 
@@ -620,7 +620,7 @@ impl<A: Clone + Ord> TxGraph<A> {
             .txs
             .iter()
             .filter_map(
-                |(&txid, (_, anchors, _))| {
+                |(&txid, (_, anchors))| {
                     if anchors.is_empty() {
                         Some(txid)
                     } else {
@@ -669,10 +669,10 @@ impl<A: Clone + Ord> TxGraph<A> {
                 });
 
             match self.txs.get_mut(&txid) {
-                Some((tx_node @ TxNodeInternal::Partial(_), _, _)) => {
+                Some((tx_node @ TxNodeInternal::Partial(_), _)) => {
                     *tx_node = TxNodeInternal::Whole(wrapped_tx.clone());
                 }
-                Some((TxNodeInternal::Whole(tx), _, _)) => {
+                Some((TxNodeInternal::Whole(tx), _)) => {
                     debug_assert_eq!(
                         tx.as_ref().compute_txid(),
                         txid,
@@ -680,10 +680,8 @@ impl<A: Clone + Ord> TxGraph<A> {
                     );
                 }
                 None => {
-                    self.txs.insert(
-                        txid,
-                        (TxNodeInternal::Whole(wrapped_tx), BTreeSet::new(), None),
-                    );
+                    self.txs
+                        .insert(txid, (TxNodeInternal::Whole(wrapped_tx), BTreeSet::new()));
                 }
             }
         }
@@ -692,9 +690,8 @@ impl<A: Clone + Ord> TxGraph<A> {
             let tx_entry = self.txs.entry(outpoint.txid).or_default();
 
             match tx_entry {
-                (TxNodeInternal::Whole(_), _, _) => { /* do nothing since we already have full tx */
-                }
-                (TxNodeInternal::Partial(txouts), _, _) => {
+                (TxNodeInternal::Whole(_), _) => { /* do nothing since we already have full tx */ }
+                (TxNodeInternal::Partial(txouts), _) => {
                     txouts.insert(outpoint.vout, txout);
                 }
             }
@@ -702,15 +699,15 @@ impl<A: Clone + Ord> TxGraph<A> {
 
         for (anchor, txid) in changeset.anchors {
             if self.anchors.insert((anchor.clone(), txid)) {
-                let (_, anchors, _) = self.txs.entry(txid).or_default();
+                let (_, anchors) = self.txs.entry(txid).or_default();
                 anchors.insert(anchor);
             }
         }
 
         for (txid, new_last_seen) in changeset.last_seen {
-            let (_, _, last_seen) = self.txs.entry(txid).or_default();
-            if Some(new_last_seen) > *last_seen {
-                *last_seen = Some(new_last_seen);
+            let last_seen = self.last_seen.entry(txid).or_default();
+            if new_last_seen > *last_seen {
+                *last_seen = new_last_seen;
             }
         }
     }
@@ -722,11 +719,10 @@ impl<A: Clone + Ord> TxGraph<A> {
     pub(crate) fn determine_changeset(&self, update: TxGraph<A>) -> ChangeSet<A> {
         let mut changeset = ChangeSet::<A>::default();
 
-        for (&txid, (update_tx_node, _, update_last_seen)) in &update.txs {
-            let prev_last_seen = match (self.txs.get(&txid), update_tx_node) {
+        for (&txid, (update_tx_node, _)) in &update.txs {
+            match (self.txs.get(&txid), update_tx_node) {
                 (None, TxNodeInternal::Whole(update_tx)) => {
                     changeset.txs.insert(update_tx.clone());
-                    None
                 }
                 (None, TxNodeInternal::Partial(update_txos)) => {
                     changeset.txouts.extend(
@@ -734,18 +730,13 @@ impl<A: Clone + Ord> TxGraph<A> {
                             .iter()
                             .map(|(&vout, txo)| (OutPoint::new(txid, vout), txo.clone())),
                     );
-                    None
                 }
-                (Some((TxNodeInternal::Whole(_), _, last_seen)), _) => *last_seen,
-                (
-                    Some((TxNodeInternal::Partial(_), _, last_seen)),
-                    TxNodeInternal::Whole(update_tx),
-                ) => {
+                (Some((TxNodeInternal::Whole(_), _)), _) => {}
+                (Some((TxNodeInternal::Partial(_), _)), TxNodeInternal::Whole(update_tx)) => {
                     changeset.txs.insert(update_tx.clone());
-                    *last_seen
                 }
                 (
-                    Some((TxNodeInternal::Partial(txos), _, last_seen)),
+                    Some((TxNodeInternal::Partial(txos), _)),
                     TxNodeInternal::Partial(update_txos),
                 ) => {
                     changeset.txouts.extend(
@@ -754,15 +745,14 @@ impl<A: Clone + Ord> TxGraph<A> {
                             .filter(|(vout, _)| !txos.contains_key(*vout))
                             .map(|(&vout, txo)| (OutPoint::new(txid, vout), txo.clone())),
                     );
-                    *last_seen
                 }
-            };
+            }
+        }
 
-            if *update_last_seen > prev_last_seen {
-                changeset.last_seen.insert(
-                    txid,
-                    update_last_seen.expect("checked is greater, so we must have a last_seen"),
-                );
+        for (txid, update_last_seen) in update.last_seen {
+            let prev_last_seen = self.last_seen.get(&txid).copied();
+            if Some(update_last_seen) > prev_last_seen {
+                changeset.last_seen.insert(txid, update_last_seen);
             }
         }
 
@@ -802,7 +792,7 @@ impl<A: Anchor> TxGraph<A> {
         chain_tip: BlockId,
         txid: Txid,
     ) -> Result<Option<ChainPosition<&A>>, C::Error> {
-        let (tx_node, anchors, last_seen) = match self.txs.get(&txid) {
+        let (tx_node, anchors) = match self.txs.get(&txid) {
             Some(v) => v,
             None => return Ok(None),
         };
@@ -816,7 +806,7 @@ impl<A: Anchor> TxGraph<A> {
 
         // If no anchors are in best chain and we don't have a last_seen, we can return
         // early because by definition the tx doesn't have a chain position.
-        let last_seen = match last_seen {
+        let last_seen = match self.last_seen.get(&txid) {
             Some(t) => *t,
             None => return Ok(None),
         };