]> Untitled Git - bdk/commitdiff
fix(chain): TxDescendants performs a BFS
authorDaniela Brozzoni <danielabrozzoni@protonmail.com>
Fri, 29 Sep 2023 16:42:49 +0000 (18:42 +0200)
committerDaniela Brozzoni <danielabrozzoni@protonmail.com>
Tue, 3 Oct 2023 13:11:04 +0000 (15:11 +0200)
This commit also changes test_descendants_no_repeat to check
the order of the transactions returned

crates/chain/src/tx_graph.rs
crates/chain/tests/test_tx_graph.rs

index 95797f28568c1745866b640d65f39004c83f3446..73d602df4bae6c970b8a9bddd8669be6a33dcbdf 100644 (file)
@@ -1145,7 +1145,7 @@ impl<A> AsRef<TxGraph<A>> for TxGraph<A> {
 pub struct TxDescendants<'g, A, F> {
     graph: &'g TxGraph<A>,
     visited: HashSet<Txid>,
-    stack: Vec<(usize, Txid)>,
+    queue: VecDeque<(usize, Txid)>,
     filter_map: F,
 }
 
@@ -1156,7 +1156,7 @@ impl<'g, A, F> TxDescendants<'g, A, F> {
         Self {
             graph,
             visited: Default::default(),
-            stack: [(0, txid)].into(),
+            queue: [(0, txid)].into(),
             filter_map,
         }
     }
@@ -1166,10 +1166,10 @@ impl<'g, A, F> TxDescendants<'g, A, F> {
         let mut descendants = Self {
             graph,
             visited: Default::default(),
-            stack: Default::default(),
+            queue: Default::default(),
             filter_map,
         };
-        descendants.populate_stack(1, txid);
+        descendants.populate_queue(1, txid);
         descendants
     }
 
@@ -1186,7 +1186,7 @@ impl<'g, A, F> TxDescendants<'g, A, F> {
         Self {
             graph,
             visited: Default::default(),
-            stack: txids.into_iter().map(|txid| (0, txid)).collect(),
+            queue: txids.into_iter().map(|txid| (0, txid)).collect(),
             filter_map,
         }
     }
@@ -1205,25 +1205,25 @@ impl<'g, A, F> TxDescendants<'g, A, F> {
         let mut descendants = Self {
             graph,
             visited: Default::default(),
-            stack: Default::default(),
+            queue: Default::default(),
             filter_map,
         };
         for txid in txids {
-            descendants.populate_stack(1, txid);
+            descendants.populate_queue(1, txid);
         }
         descendants
     }
 }
 
 impl<'g, A, F> TxDescendants<'g, A, F> {
-    fn populate_stack(&mut self, depth: usize, txid: Txid) {
+    fn populate_queue(&mut self, depth: usize, txid: Txid) {
         let spend_paths = self
             .graph
             .spends
             .range(tx_outpoint_range(txid))
             .flat_map(|(_, spends)| spends)
             .map(|&txid| (depth, txid));
-        self.stack.extend(spend_paths);
+        self.queue.extend(spend_paths);
     }
 }
 
@@ -1235,8 +1235,8 @@ where
 
     fn next(&mut self) -> Option<Self::Item> {
         let (op_spends, txid, item) = loop {
-            // we have exhausted all paths when stack is empty
-            let (op_spends, txid) = self.stack.pop()?;
+            // we have exhausted all paths when queue is empty
+            let (op_spends, txid) = self.queue.pop_front()?;
             // we do not want to visit the same transaction twice
             if self.visited.insert(txid) {
                 // ignore paths when user filters them out
@@ -1246,7 +1246,7 @@ where
             }
         };
 
-        self.populate_stack(op_spends + 1, txid);
+        self.populate_queue(op_spends + 1, txid);
         Some(item)
     }
 }
index 4c68f510821ae257feda8b17616a489af6dbcc96..36a27a589d2b4a14ebd442f81b68627e9d5b4df9 100644 (file)
@@ -610,7 +610,7 @@ fn test_descendants_no_repeat() {
         .collect::<Vec<_>>();
 
     let mut graph = TxGraph::<()>::default();
-    let mut expected_txids = BTreeSet::new();
+    let mut expected_txids = Vec::new();
 
     // these are NOT descendants of `tx_a`
     for tx in txs_not_connected {
@@ -625,19 +625,14 @@ fn test_descendants_no_repeat() {
         .chain(core::iter::once(&tx_e))
     {
         let _ = graph.insert_tx(tx.clone());
-        assert!(expected_txids.insert(tx.txid()));
+        expected_txids.push(tx.txid());
     }
 
     let descendants = graph
         .walk_descendants(tx_a.txid(), |_, txid| Some(txid))
         .collect::<Vec<_>>();
 
-    assert_eq!(descendants.len(), expected_txids.len());
-
-    for txid in descendants {
-        assert!(expected_txids.remove(&txid));
-    }
-    assert!(expected_txids.is_empty());
+    assert_eq!(descendants, expected_txids);
 }
 
 #[test]