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