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;
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                return Some(Err(err))
122            }
123        }
124    }
125}
126
127#[cfg(test)]
128mod tests {
129    use super::*;
130    use crate::trie_cursor::{mock::MockTrieCursorFactory, TrieCursorFactory};
131    use alloy_trie::TrieMask;
132    use std::{collections::BTreeMap, sync::Arc};
133
134    fn create_test_node(state_nibbles: &[u8], tree_nibbles: &[u8]) -> BranchNodeCompact {
135        let mut state_mask = TrieMask::default();
136        for &nibble in state_nibbles {
137            state_mask.set_bit(nibble);
138        }
139
140        let mut tree_mask = TrieMask::default();
141        for &nibble in tree_nibbles {
142            tree_mask.set_bit(nibble);
143        }
144
145        BranchNodeCompact {
146            state_mask,
147            tree_mask,
148            hash_mask: TrieMask::default(),
149            hashes: Arc::new(vec![]),
150            root_hash: None,
151        }
152    }
153
154    #[test]
155    fn test_depth_first_cmp() {
156        // Test case 1: Child comes before parent
157        let child = Nibbles::from_nibbles([0x1, 0x1]);
158        let parent = Nibbles::from_nibbles([0x1]);
159        assert_eq!(cmp(&child, &parent), Ordering::Less);
160        assert_eq!(cmp(&parent, &child), Ordering::Greater);
161
162        // Test case 2: Deeper descendant comes before ancestor
163        let deep = Nibbles::from_nibbles([0x1, 0x2, 0x3, 0x4]);
164        let ancestor = Nibbles::from_nibbles([0x1, 0x2]);
165        assert_eq!(cmp(&deep, &ancestor), Ordering::Less);
166        assert_eq!(cmp(&ancestor, &deep), Ordering::Greater);
167
168        // Test case 3: Siblings use lexicographical ordering
169        let sibling1 = Nibbles::from_nibbles([0x1, 0x2]);
170        let sibling2 = Nibbles::from_nibbles([0x1, 0x3]);
171        assert_eq!(cmp(&sibling1, &sibling2), Ordering::Less);
172        assert_eq!(cmp(&sibling2, &sibling1), Ordering::Greater);
173
174        // Test case 4: Different branches use lexicographical ordering
175        let branch1 = Nibbles::from_nibbles([0x1]);
176        let branch2 = Nibbles::from_nibbles([0x2]);
177        assert_eq!(cmp(&branch1, &branch2), Ordering::Less);
178        assert_eq!(cmp(&branch2, &branch1), Ordering::Greater);
179
180        // Test case 5: Empty path comes after everything
181        let empty = Nibbles::new();
182        let non_empty = Nibbles::from_nibbles([0x0]);
183        assert_eq!(cmp(&non_empty, &empty), Ordering::Less);
184        assert_eq!(cmp(&empty, &non_empty), Ordering::Greater);
185
186        // Test case 6: Same paths are equal
187        let same1 = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
188        let same2 = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
189        assert_eq!(cmp(&same1, &same2), Ordering::Equal);
190    }
191
192    #[test]
193    fn test_depth_first_ordering_complex() {
194        // Test the example from the conversation: 0x11, 0x12, 0x1, 0x2
195        let mut paths = [
196            Nibbles::from_nibbles([0x1]),      // 0x1
197            Nibbles::from_nibbles([0x2]),      // 0x2
198            Nibbles::from_nibbles([0x1, 0x1]), // 0x11
199            Nibbles::from_nibbles([0x1, 0x2]), // 0x12
200        ];
201
202        // Shuffle to ensure sorting works regardless of input order
203        paths.reverse();
204
205        // Sort using depth-first ordering
206        paths.sort_by(cmp);
207
208        // Expected order: 0x11, 0x12, 0x1, 0x2
209        assert_eq!(paths[0], Nibbles::from_nibbles([0x1, 0x1])); // 0x11
210        assert_eq!(paths[1], Nibbles::from_nibbles([0x1, 0x2])); // 0x12
211        assert_eq!(paths[2], Nibbles::from_nibbles([0x1])); // 0x1
212        assert_eq!(paths[3], Nibbles::from_nibbles([0x2])); // 0x2
213    }
214
215    #[test]
216    fn test_depth_first_ordering_tree() {
217        // Test a more complex tree structure
218        let mut paths = vec![
219            Nibbles::new(),                         // root (empty)
220            Nibbles::from_nibbles([0x1]),           // 0x1
221            Nibbles::from_nibbles([0x1, 0x1]),      // 0x11
222            Nibbles::from_nibbles([0x1, 0x1, 0x1]), // 0x111
223            Nibbles::from_nibbles([0x1, 0x1, 0x2]), // 0x112
224            Nibbles::from_nibbles([0x1, 0x2]),      // 0x12
225            Nibbles::from_nibbles([0x2]),           // 0x2
226            Nibbles::from_nibbles([0x2, 0x1]),      // 0x21
227        ];
228
229        // Shuffle
230        paths.reverse();
231
232        // Sort using depth-first ordering
233        paths.sort_by(cmp);
234
235        // Expected depth-first order:
236        // All descendants come before ancestors
237        // Within the same level, lexicographical order
238        assert_eq!(paths[0], Nibbles::from_nibbles([0x1, 0x1, 0x1])); // 0x111 (deepest in 0x1 branch)
239        assert_eq!(paths[1], Nibbles::from_nibbles([0x1, 0x1, 0x2])); // 0x112 (sibling of 0x111)
240        assert_eq!(paths[2], Nibbles::from_nibbles([0x1, 0x1])); // 0x11 (parent of 0x111, 0x112)
241        assert_eq!(paths[3], Nibbles::from_nibbles([0x1, 0x2])); // 0x12 (sibling of 0x11)
242        assert_eq!(paths[4], Nibbles::from_nibbles([0x1])); // 0x1 (parent of 0x11, 0x12)
243        assert_eq!(paths[5], Nibbles::from_nibbles([0x2, 0x1])); // 0x21 (child of 0x2)
244        assert_eq!(paths[6], Nibbles::from_nibbles([0x2])); // 0x2 (parent of 0x21)
245        assert_eq!(paths[7], Nibbles::new()); // root (empty, parent of all)
246    }
247
248    #[test]
249    fn test_empty_trie() {
250        let factory = MockTrieCursorFactory::new(BTreeMap::new(), Default::default());
251        let cursor = factory.account_trie_cursor().unwrap();
252        let mut iter = DepthFirstTrieIterator::new(cursor);
253        assert!(iter.next().is_none());
254    }
255
256    #[test]
257    fn test_single_node() {
258        let path = Nibbles::from_nibbles([0x1, 0x2, 0x3]);
259        let node = create_test_node(&[0x4], &[0x5]);
260
261        let mut nodes = BTreeMap::new();
262        nodes.insert(path, node.clone());
263        let factory = MockTrieCursorFactory::new(nodes, Default::default());
264        let cursor = factory.account_trie_cursor().unwrap();
265        let mut iter = DepthFirstTrieIterator::new(cursor);
266
267        let result = iter.next().unwrap().unwrap();
268        assert_eq!(result.0, path);
269        assert_eq!(result.1, node);
270        assert!(iter.next().is_none());
271    }
272
273    #[test]
274    fn test_depth_first_order() {
275        // Create a simple trie structure:
276        // root
277        // ├── 0x1 (has children 0x2 and 0x3)
278        // │   ├── 0x12
279        // │   └── 0x13
280        // └── 0x2 (has child 0x4)
281        //     └── 0x24
282
283        let nodes = vec![
284            // Root node with children at nibbles 1 and 2
285            (Nibbles::default(), create_test_node(&[], &[0x1, 0x2])),
286            // Node at path 0x1 with children at nibbles 2 and 3
287            (Nibbles::from_nibbles([0x1]), create_test_node(&[], &[0x2, 0x3])),
288            // Leaf nodes
289            (Nibbles::from_nibbles([0x1, 0x2]), create_test_node(&[0xF], &[])),
290            (Nibbles::from_nibbles([0x1, 0x3]), create_test_node(&[0xF], &[])),
291            // Node at path 0x2 with child at nibble 4
292            (Nibbles::from_nibbles([0x2]), create_test_node(&[], &[0x4])),
293            // Leaf node
294            (Nibbles::from_nibbles([0x2, 0x4]), create_test_node(&[0xF], &[])),
295        ];
296
297        let nodes_map: BTreeMap<_, _> = nodes.into_iter().collect();
298        let factory = MockTrieCursorFactory::new(nodes_map, Default::default());
299        let cursor = factory.account_trie_cursor().unwrap();
300        let iter = DepthFirstTrieIterator::new(cursor);
301
302        // Expected post-order (depth-first with children before parents):
303        // 1. 0x12 (leaf, child of 0x1)
304        // 2. 0x13 (leaf, child of 0x1)
305        // 3. 0x1 (parent of 0x12 and 0x13)
306        // 4. 0x24 (leaf, child of 0x2)
307        // 5. 0x2 (parent of 0x24)
308        // 6. Root (parent of 0x1 and 0x2)
309
310        let expected_order = vec![
311            Nibbles::from_nibbles([0x1, 0x2]),
312            Nibbles::from_nibbles([0x1, 0x3]),
313            Nibbles::from_nibbles([0x1]),
314            Nibbles::from_nibbles([0x2, 0x4]),
315            Nibbles::from_nibbles([0x2]),
316            Nibbles::default(),
317        ];
318
319        let mut actual_order = Vec::new();
320        for result in iter {
321            let (path, _) = result.unwrap();
322            actual_order.push(path);
323        }
324
325        assert_eq!(actual_order, expected_order);
326    }
327
328    #[test]
329    fn test_complex_tree() {
330        // Create a more complex tree structure with multiple levels
331        let nodes = vec![
332            // Root with multiple children
333            (Nibbles::default(), create_test_node(&[], &[0x0, 0x5, 0xA, 0xF])),
334            // Branch at 0x0 with children
335            (Nibbles::from_nibbles([0x0]), create_test_node(&[], &[0x1, 0x2])),
336            (Nibbles::from_nibbles([0x0, 0x1]), create_test_node(&[0x3], &[])),
337            (Nibbles::from_nibbles([0x0, 0x2]), create_test_node(&[0x4], &[])),
338            // Branch at 0x5 with no children (leaf)
339            (Nibbles::from_nibbles([0x5]), create_test_node(&[0xB], &[])),
340            // Branch at 0xA with deep nesting
341            (Nibbles::from_nibbles([0xA]), create_test_node(&[], &[0xB])),
342            (Nibbles::from_nibbles([0xA, 0xB]), create_test_node(&[], &[0xC])),
343            (Nibbles::from_nibbles([0xA, 0xB, 0xC]), create_test_node(&[0xD], &[])),
344            // Branch at 0xF (leaf)
345            (Nibbles::from_nibbles([0xF]), create_test_node(&[0xE], &[])),
346        ];
347
348        let nodes_map: BTreeMap<_, _> = nodes.into_iter().collect();
349        let factory = MockTrieCursorFactory::new(nodes_map, Default::default());
350        let cursor = factory.account_trie_cursor().unwrap();
351        let iter = DepthFirstTrieIterator::new(cursor);
352
353        // Verify post-order traversal (children before parents)
354        let expected_order = vec![
355            Nibbles::from_nibbles([0x0, 0x1]),      // leaf child of 0x0
356            Nibbles::from_nibbles([0x0, 0x2]),      // leaf child of 0x0
357            Nibbles::from_nibbles([0x0]),           // parent of 0x01 and 0x02
358            Nibbles::from_nibbles([0x5]),           // leaf
359            Nibbles::from_nibbles([0xA, 0xB, 0xC]), // deepest leaf
360            Nibbles::from_nibbles([0xA, 0xB]),      // parent of 0xABC
361            Nibbles::from_nibbles([0xA]),           // parent of 0xAB
362            Nibbles::from_nibbles([0xF]),           // leaf
363            Nibbles::default(),                     // root (last)
364        ];
365
366        let mut actual_order = Vec::new();
367        for result in iter {
368            let (path, _node) = result.unwrap();
369            actual_order.push(path);
370        }
371
372        assert_eq!(actual_order, expected_order);
373    }
374}