Skip to main content

reth_trie/trie_cursor/
depth_first.rs

1use super::TrieCursor;
2use crate::{BranchNodeCompact, Nibbles};
3use reth_storage_errors::db::DatabaseError;
4use std::{cmp::Ordering, iter::FusedIterator};
5use tracing::trace;
6
7/// Compares two Nibbles in depth-first order.
8///
9/// See [`reth_trie_common::depth_first_cmp`] for details.
10pub fn cmp(a: &Nibbles, b: &Nibbles) -> Ordering {
11    reth_trie_common::depth_first_cmp(a, b)
12}
13
14/// An iterator that traverses trie nodes in depth-first post-order.
15///
16/// This iterator yields nodes in post-order traversal (children before parents),
17/// which matches the `cmp` comparison function where descendants
18/// come before their ancestors.
19#[derive(Debug)]
20pub struct DepthFirstTrieIterator<C: TrieCursor> {
21    /// The underlying trie cursor.
22    cursor: C,
23    /// Set to true once the trie cursor has done its initial seek to the root node.
24    initialized: bool,
25    /// Stack of nodes which have been fetched. Each node's path is a prefix of the next's.
26    stack: Vec<(Nibbles, BranchNodeCompact)>,
27    /// Nodes which are ready to be yielded from `next`.
28    next: Vec<(Nibbles, BranchNodeCompact)>,
29    /// Set to true once the cursor has been exhausted.
30    complete: bool,
31}
32
33impl<C: TrieCursor> DepthFirstTrieIterator<C> {
34    /// Create a new depth-first iterator from a trie cursor.
35    pub fn new(cursor: C) -> Self {
36        Self {
37            cursor,
38            initialized: false,
39            stack: Default::default(),
40            next: Default::default(),
41            complete: false,
42        }
43    }
44
45    fn push(&mut self, path: Nibbles, node: BranchNodeCompact) {
46        loop {
47            match self.stack.last() {
48                None => {
49                    // If the stack is empty then we push this node onto it, as it may have child
50                    // nodes which need to be yielded first.
51                    self.stack.push((path, node));
52                    break
53                }
54                Some((top_path, _)) if path.starts_with(top_path) => {
55                    // If the top of the stack is a prefix of this node, it means this node is a
56                    // child of the top of the stack (and all other nodes on the stack). Push this
57                    // node onto the stack, as future nodes may be children of it.
58                    self.stack.push((path, node));
59                    break
60                }
61                Some((_, _)) => {
62                    // The top of the stack is not a prefix of this node, therefore it is not a
63                    // parent of this node. Yield the top of the stack, and loop back to see if this
64                    // node is a child of the new top-of-stack.
65                    self.next.push(self.stack.pop().expect("stack is not empty"));
66                }
67            }
68        }
69
70        // We will have popped off the top of the stack in the order we want to yield nodes, but
71        // `next` is itself popped off so it needs to be reversed.
72        self.next.reverse();
73    }
74
75    fn fill_next(&mut self) -> Result<(), DatabaseError> {
76        debug_assert!(self.next.is_empty());
77
78        loop {
79            let Some((path, node)) = (if self.initialized {
80                self.cursor.next()?
81            } else {
82                self.initialized = true;
83                self.cursor.seek(Nibbles::new())?
84            }) else {
85                // Record that the cursor is empty and yield the stack. The stack is in reverse
86                // order of what we want to yield, but `next` is popped from, so we don't have to
87                // reverse it.
88                self.complete = true;
89                self.next = core::mem::take(&mut self.stack);
90                return Ok(())
91            };
92
93            trace!(
94                target: "trie::trie_cursor::depth_first",
95                ?path,
96                "Iterated from cursor",
97            );
98
99            self.push(path, node);
100            if !self.next.is_empty() {
101                return Ok(())
102            }
103        }
104    }
105}
106
107impl<C: TrieCursor> Iterator for DepthFirstTrieIterator<C> {
108    type Item = Result<(Nibbles, BranchNodeCompact), DatabaseError>;
109
110    fn next(&mut self) -> Option<Self::Item> {
111        loop {
112            if let Some(next) = self.next.pop() {
113                return Some(Ok(next))
114            }
115
116            if self.complete {
117                return None
118            }
119
120            if let Err(err) = self.fill_next() {
121                self.complete = true;
122                return Some(Err(err))
123            }
124        }
125    }
126}
127
128impl<C: TrieCursor> FusedIterator for DepthFirstTrieIterator<C> {}
129
130#[cfg(test)]
131mod tests {
132    use super::*;
133    use crate::trie_cursor::{mock::MockTrieCursorFactory, TrieCursorFactory};
134    use alloy_trie::TrieMask;
135    use std::{collections::BTreeMap, sync::Arc};
136
137    /// A trie cursor that always returns an error on seek/next.
138    struct FailingTrieCursor;
139
140    impl TrieCursor for FailingTrieCursor {
141        fn seek_exact(
142            &mut self,
143            _key: Nibbles,
144        ) -> Result<Option<(Nibbles, BranchNodeCompact)>, DatabaseError> {
145            Err(DatabaseError::Other("test error".to_string()))
146        }
147
148        fn seek(
149            &mut self,
150            _key: Nibbles,
151        ) -> Result<Option<(Nibbles, BranchNodeCompact)>, DatabaseError> {
152            Err(DatabaseError::Other("test error".to_string()))
153        }
154
155        fn next(&mut self) -> Result<Option<(Nibbles, BranchNodeCompact)>, DatabaseError> {
156            Err(DatabaseError::Other("test error".to_string()))
157        }
158
159        fn current(&mut self) -> Result<Option<Nibbles>, DatabaseError> {
160            Err(DatabaseError::Other("test error".to_string()))
161        }
162
163        fn reset(&mut self) {}
164    }
165
166    fn create_test_node(state_nibbles: &[u8], tree_nibbles: &[u8]) -> BranchNodeCompact {
167        let mut state_mask = TrieMask::default();
168        for &nibble in state_nibbles {
169            state_mask.set_bit(nibble);
170        }
171
172        let mut tree_mask = TrieMask::default();
173        for &nibble in tree_nibbles {
174            tree_mask.set_bit(nibble);
175        }
176
177        BranchNodeCompact {
178            state_mask,
179            tree_mask,
180            hash_mask: TrieMask::default(),
181            hashes: Arc::new(vec![]),
182            root_hash: None,
183        }
184    }
185
186    #[test]
187    fn test_depth_first_cmp() {
188        // Test case 1: Child comes before parent
189        let child = Nibbles::from_nibbles([0x1, 0x1]);
190        let parent = Nibbles::from_nibbles([0x1]);
191        assert_eq!(cmp(&child, &parent), Ordering::Less);
192        assert_eq!(cmp(&parent, &child), Ordering::Greater);
193
194        // Test case 2: Deeper descendant comes before ancestor
195        let deep = Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]);
196        let ancestor = Nibbles::from_nibbles([0x1, 0x2]);
197        assert_eq!(cmp(&deep, &ancestor), Ordering::Less);
198        assert_eq!(cmp(&ancestor, &deep), Ordering::Greater);
199
200        // Test case 3: Siblings use lexicographical ordering
201        let sibling1 = Nibbles::from_nibbles([0x1, 0x2]);
202        let sibling2 = Nibbles::from_nibbles([0x1, 0x3]);
203        assert_eq!(cmp(&sibling1, &sibling2), Ordering::Less);
204        assert_eq!(cmp(&sibling2, &sibling1), Ordering::Greater);
205
206        // Test case 4: Different branches use lexicographical ordering
207        let branch1 = Nibbles::from_nibbles([0x1]);
208        let branch2 = Nibbles::from_nibbles([0x2]);
209        assert_eq!(cmp(&branch1, &branch2), Ordering::Less);
210        assert_eq!(cmp(&branch2, &branch1), Ordering::Greater);
211
212        // Test case 5: Empty path comes after everything
213        let empty = Nibbles::new();
214        let non_empty = Nibbles::from_nibbles([0x0]);
215        assert_eq!(cmp(&non_empty, &empty), Ordering::Less);
216        assert_eq!(cmp(&empty, &non_empty), Ordering::Greater);
217
218        // Test case 6: Same paths are equal
219        let same1 = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
220        let same2 = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
221        assert_eq!(cmp(&same1, &same2), Ordering::Equal);
222    }
223
224    #[test]
225    fn test_depth_first_ordering_complex() {
226        // Test the example from the conversation: 0x11, 0x12, 0x1, 0x2
227        let mut paths = [
228            Nibbles::from_nibbles([0x1]),      // 0x1
229            Nibbles::from_nibbles([0x2]),      // 0x2
230            Nibbles::from_nibbles([0x1, 0x1]), // 0x11
231            Nibbles::from_nibbles([0x1, 0x2]), // 0x12
232        ];
233
234        // Shuffle to ensure sorting works regardless of input order
235        paths.reverse();
236
237        // Sort using depth-first ordering
238        paths.sort_by(cmp);
239
240        // Expected order: 0x11, 0x12, 0x1, 0x2
241        assert_eq!(paths[0], Nibbles::from_nibbles([0x1, 0x1])); // 0x11
242        assert_eq!(paths[1], Nibbles::from_nibbles([0x1, 0x2])); // 0x12
243        assert_eq!(paths[2], Nibbles::from_nibbles([0x1])); // 0x1
244        assert_eq!(paths[3], Nibbles::from_nibbles([0x2])); // 0x2
245    }
246
247    #[test]
248    fn test_depth_first_ordering_tree() {
249        // Test a more complex tree structure
250        let mut paths = vec![
251            Nibbles::new(),                         // root (empty)
252            Nibbles::from_nibbles([0x1]),           // 0x1
253            Nibbles::from_nibbles([0x1, 0x1]),      // 0x11
254            Nibbles::from_nibbles([0x1, 0x1, 0x1]), // 0x111
255            Nibbles::from_nibbles([0x1, 0x1, 0x2]), // 0x112
256            Nibbles::from_nibbles([0x1, 0x2]),      // 0x12
257            Nibbles::from_nibbles([0x2]),           // 0x2
258            Nibbles::from_nibbles([0x2, 0x1]),      // 0x21
259        ];
260
261        // Shuffle
262        paths.reverse();
263
264        // Sort using depth-first ordering
265        paths.sort_by(cmp);
266
267        // Expected depth-first order:
268        // All descendants come before ancestors
269        // Within the same level, lexicographical order
270        assert_eq!(paths[0], Nibbles::from_nibbles([0x1, 0x1, 0x1])); // 0x111 (deepest in 0x1 branch)
271        assert_eq!(paths[1], Nibbles::from_nibbles([0x1, 0x1, 0x2])); // 0x112 (sibling of 0x111)
272        assert_eq!(paths[2], Nibbles::from_nibbles([0x1, 0x1])); // 0x11 (parent of 0x111, 0x112)
273        assert_eq!(paths[3], Nibbles::from_nibbles([0x1, 0x2])); // 0x12 (sibling of 0x11)
274        assert_eq!(paths[4], Nibbles::from_nibbles([0x1])); // 0x1 (parent of 0x11, 0x12)
275        assert_eq!(paths[5], Nibbles::from_nibbles([0x2, 0x1])); // 0x21 (child of 0x2)
276        assert_eq!(paths[6], Nibbles::from_nibbles([0x2])); // 0x2 (parent of 0x21)
277        assert_eq!(paths[7], Nibbles::new()); // root (empty, parent of all)
278    }
279
280    #[test]
281    fn test_empty_trie() {
282        let factory = MockTrieCursorFactory::new(BTreeMap::new(), Default::default());
283        let cursor = factory.account_trie_cursor().unwrap();
284        let mut iter = DepthFirstTrieIterator::new(cursor);
285        assert!(iter.next().is_none());
286    }
287
288    #[test]
289    fn test_single_node() {
290        let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
291        let node = create_test_node(&[0x4], &[0x5]);
292
293        let mut nodes = BTreeMap::new();
294        nodes.insert(path, node.clone());
295        let factory = MockTrieCursorFactory::new(nodes, Default::default());
296        let cursor = factory.account_trie_cursor().unwrap();
297        let mut iter = DepthFirstTrieIterator::new(cursor);
298
299        let result = iter.next().unwrap().unwrap();
300        assert_eq!(result.0, path);
301        assert_eq!(result.1, node);
302        assert!(iter.next().is_none());
303    }
304
305    #[test]
306    fn test_depth_first_order() {
307        // Create a simple trie structure:
308        // root
309        // ├── 0x1 (has children 0x2 and 0x3)
310        // │   ├── 0x12
311        // │   └── 0x13
312        // └── 0x2 (has child 0x4)
313        //     └── 0x24
314
315        let nodes = vec![
316            // Root node with children at nibbles 1 and 2
317            (Nibbles::default(), create_test_node(&[], &[0x1, 0x2])),
318            // Node at path 0x1 with children at nibbles 2 and 3
319            (Nibbles::from_nibbles([0x1]), create_test_node(&[], &[0x2, 0x3])),
320            // Leaf nodes
321            (Nibbles::from_nibbles([0x1, 0x2]), create_test_node(&[0xF], &[])),
322            (Nibbles::from_nibbles([0x1, 0x3]), create_test_node(&[0xF], &[])),
323            // Node at path 0x2 with child at nibble 4
324            (Nibbles::from_nibbles([0x2]), create_test_node(&[], &[0x4])),
325            // Leaf node
326            (Nibbles::from_nibbles([0x2, 0x4]), create_test_node(&[0xF], &[])),
327        ];
328
329        let nodes_map: BTreeMap<_, _> = nodes.into_iter().collect();
330        let factory = MockTrieCursorFactory::new(nodes_map, Default::default());
331        let cursor = factory.account_trie_cursor().unwrap();
332        let iter = DepthFirstTrieIterator::new(cursor);
333
334        // Expected post-order (depth-first with children before parents):
335        // 1. 0x12 (leaf, child of 0x1)
336        // 2. 0x13 (leaf, child of 0x1)
337        // 3. 0x1 (parent of 0x12 and 0x13)
338        // 4. 0x24 (leaf, child of 0x2)
339        // 5. 0x2 (parent of 0x24)
340        // 6. Root (parent of 0x1 and 0x2)
341
342        let expected_order = vec![
343            Nibbles::from_nibbles([0x1, 0x2]),
344            Nibbles::from_nibbles([0x1, 0x3]),
345            Nibbles::from_nibbles([0x1]),
346            Nibbles::from_nibbles([0x2, 0x4]),
347            Nibbles::from_nibbles([0x2]),
348            Nibbles::default(),
349        ];
350
351        let mut actual_order = Vec::new();
352        for result in iter {
353            let (path, _) = result.unwrap();
354            actual_order.push(path);
355        }
356
357        assert_eq!(actual_order, expected_order);
358    }
359
360    #[test]
361    fn test_complex_tree() {
362        // Create a more complex tree structure with multiple levels
363        let nodes = vec![
364            // Root with multiple children
365            (Nibbles::default(), create_test_node(&[], &[0x0, 0x5, 0xA, 0xF])),
366            // Branch at 0x0 with children
367            (Nibbles::from_nibbles([0x0]), create_test_node(&[], &[0x1, 0x2])),
368            (Nibbles::from_nibbles([0x0, 0x1]), create_test_node(&[0x3], &[])),
369            (Nibbles::from_nibbles([0x0, 0x2]), create_test_node(&[0x4], &[])),
370            // Branch at 0x5 with no children (leaf)
371            (Nibbles::from_nibbles([0x5]), create_test_node(&[0xB], &[])),
372            // Branch at 0xA with deep nesting
373            (Nibbles::from_nibbles([0xA]), create_test_node(&[], &[0xB])),
374            (Nibbles::from_nibbles([0xA, 0xB]), create_test_node(&[], &[0xC])),
375            (Nibbles::from_nibbles([0xA, 0xB, 0xC]), create_test_node(&[0xD], &[])),
376            // Branch at 0xF (leaf)
377            (Nibbles::from_nibbles([0xF]), create_test_node(&[0xE], &[])),
378        ];
379
380        let nodes_map: BTreeMap<_, _> = nodes.into_iter().collect();
381        let factory = MockTrieCursorFactory::new(nodes_map, Default::default());
382        let cursor = factory.account_trie_cursor().unwrap();
383        let iter = DepthFirstTrieIterator::new(cursor);
384
385        // Verify post-order traversal (children before parents)
386        let expected_order = vec![
387            Nibbles::from_nibbles([0x0, 0x1]),      // leaf child of 0x0
388            Nibbles::from_nibbles([0x0, 0x2]),      // leaf child of 0x0
389            Nibbles::from_nibbles([0x0]),           // parent of 0x01 and 0x02
390            Nibbles::from_nibbles([0x5]),           // leaf
391            Nibbles::from_nibbles([0xA, 0xB, 0xC]), // deepest leaf
392            Nibbles::from_nibbles([0xA, 0xB]),      // parent of 0xABC
393            Nibbles::from_nibbles([0xA]),           // parent of 0xAB
394            Nibbles::from_nibbles([0xF]),           // leaf
395            Nibbles::default(),                     // root (last)
396        ];
397
398        let mut actual_order = Vec::new();
399        for result in iter {
400            let (path, _node) = result.unwrap();
401            actual_order.push(path);
402        }
403
404        assert_eq!(actual_order, expected_order);
405    }
406
407    #[test]
408    fn test_iterator_terminates_on_error() {
409        let mut iter = DepthFirstTrieIterator::new(FailingTrieCursor);
410
411        // First call should return the error.
412        assert!(iter.next().unwrap().is_err());
413        // Iterator must be fused after the error — no infinite error loop.
414        assert!(iter.next().is_none());
415    }
416}