]> Untitled Git - bdk/commitdiff
feat(graph): add convenience function for inserting relevant `evicted_at`s
authorWei Chen <wzc110@gmail.com>
Fri, 25 Apr 2025 07:29:36 +0000 (07:29 +0000)
committerWei Chen <wzc110@gmail.com>
Thu, 1 May 2025 14:41:55 +0000 (14:41 +0000)
crates/bitcoind_rpc/src/lib.rs
crates/bitcoind_rpc/tests/test_emitter.rs
crates/chain/src/indexed_tx_graph.rs
crates/chain/src/tx_graph.rs
examples/example_bitcoind_rpc_polling/src/main.rs

index 7e363560ba1d469a6351d9719a1767c8a74de849..dc21997d0415da3c38d4e98c3488475b4bf8d6b9 100644 (file)
@@ -236,6 +236,14 @@ pub struct MempoolEvent {
     pub latest_update_time: u64,
 }
 
+impl MempoolEvent {
+    /// Returns an iterator of `(txid, evicted_at)` pairs for all evicted transactions.
+    pub fn evicted_ats(&self) -> impl ExactSizeIterator<Item = (Txid, u64)> + '_ {
+        let time = self.latest_update_time;
+        self.evicted_txids.iter().map(move |&txid| (txid, time))
+    }
+}
+
 /// A newly emitted block from [`Emitter`].
 #[derive(Debug)]
 pub struct BlockEvent<B> {
index 0c30f5a803b9c85587c1ab9f1cf7e41f199d8e12..360a1f435eab87ddc8b39ad4ec1b2a1d3457dfe2 100644 (file)
@@ -847,11 +847,7 @@ fn test_expect_tx_evicted() -> anyhow::Result<()> {
     assert!(mempool_event.evicted_txids.contains(&txid_1));
 
     // Update graph with evicted tx.
-    for txid in mempool_event.evicted_txids {
-        if graph.graph().get_tx_node(txid).is_some() {
-            let _ = graph.insert_evicted_at(txid, mempool_event.latest_update_time);
-        }
-    }
+    let _ = graph.batch_insert_relevant_evicted_at(mempool_event.evicted_ats());
 
     let canonical_txids = graph
         .graph()
index bcd6ac3fc6b052eb8bf55ed3ec1b42ca3245b6ec..89e79432660556d6787d68db73cf3d7a6b355561 100644 (file)
@@ -145,6 +145,22 @@ where
         }
     }
 
+    /// Batch inserts `(txid, evicted_at)` pairs for `txid`s that the graph is tracking.
+    ///
+    /// The `evicted_at` timestamp represents the last known time when the transaction was observed
+    /// to be missing from the mempool. If `txid` was previously recorded with an earlier
+    /// `evicted_at` value, it is updated only if the new value is greater.
+    pub fn batch_insert_relevant_evicted_at(
+        &mut self,
+        evicted_ats: impl IntoIterator<Item = (Txid, u64)>,
+    ) -> ChangeSet<A, I::ChangeSet> {
+        let tx_graph = self.graph.batch_insert_relevant_evicted_at(evicted_ats);
+        ChangeSet {
+            tx_graph,
+            ..Default::default()
+        }
+    }
+
     /// Batch insert transactions, filtering out those that are irrelevant.
     ///
     /// Relevancy is determined by the [`Indexer::is_tx_relevant`] implementation of `I`. Irrelevant
index 2358b188561e384e4a9e4ac5b58757638511a267..a10f3e7578937319c3082bfda0abcf405706df67 100644 (file)
@@ -835,6 +835,26 @@ impl<A: Anchor> TxGraph<A> {
         changeset
     }
 
+    /// Batch inserts `(txid, evicted_at)` pairs into [`TxGraph`] for `txid`s that the graph is
+    /// tracking.
+    ///
+    /// The `evicted_at` timestamp represents the last known time when the transaction was observed
+    /// to be missing from the mempool. If `txid` was previously recorded with an earlier
+    /// `evicted_at` value, it is updated only if the new value is greater.
+    pub fn batch_insert_relevant_evicted_at(
+        &mut self,
+        evicted_ats: impl IntoIterator<Item = (Txid, u64)>,
+    ) -> ChangeSet<A> {
+        let mut changeset = ChangeSet::default();
+        for (txid, evicted_at) in evicted_ats {
+            // Only record evictions for transactions the graph is tracking.
+            if self.txs.contains_key(&txid) {
+                changeset.merge(self.insert_evicted_at(txid, evicted_at));
+            }
+        }
+        changeset
+    }
+
     /// Extends this graph with the given `update`.
     ///
     /// The returned [`ChangeSet`] is the set difference between `update` and `self` (transactions that
index 3684edbfcbcf3f762cb0865b8b65497d95d82be1..8cbe1939d6651bba54eb5b7f8c333de2943d0091 100644 (file)
@@ -289,11 +289,9 @@ fn main() -> anyhow::Result<()> {
                     Emission::Mempool(mempool_txs) => {
                         let mut graph_changeset =
                             graph.batch_insert_relevant_unconfirmed(mempool_txs.new_txs.clone());
-                        for txid in mempool_txs.evicted_txids {
-                            graph_changeset.merge(
-                                graph.insert_evicted_at(txid, mempool_txs.latest_update_time),
-                            );
-                        }
+                        graph_changeset.merge(
+                            graph.batch_insert_relevant_evicted_at(mempool_txs.evicted_ats()),
+                        );
                         (local_chain::ChangeSet::default(), graph_changeset)
                     }
                     Emission::Tip(h) => {