reth_trie_sparse/
trie.rs

1use crate::blinded::{BlindedProvider, DefaultBlindedProvider};
2use alloy_primitives::{
3    hex, keccak256,
4    map::{Entry, HashMap, HashSet},
5    B256,
6};
7use alloy_rlp::Decodable;
8use reth_execution_errors::{SparseTrieError, SparseTrieErrorKind, SparseTrieResult};
9use reth_tracing::tracing::trace;
10use reth_trie_common::{
11    prefix_set::{PrefixSet, PrefixSetMut},
12    BranchNodeCompact, BranchNodeRef, ExtensionNodeRef, LeafNodeRef, Nibbles, RlpNode, TrieMask,
13    TrieNode, CHILD_INDEX_RANGE, EMPTY_ROOT_HASH,
14};
15use smallvec::SmallVec;
16use std::{borrow::Cow, fmt};
17
18/// Inner representation of the sparse trie.
19/// Sparse trie is blind by default until nodes are revealed.
20#[derive(PartialEq, Eq)]
21pub enum SparseTrie<P = DefaultBlindedProvider> {
22    /// None of the trie nodes are known.
23    Blind,
24    /// The trie nodes have been revealed.
25    Revealed(Box<RevealedSparseTrie<P>>),
26}
27
28impl<P> fmt::Debug for SparseTrie<P> {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        match self {
31            Self::Blind => write!(f, "Blind"),
32            Self::Revealed(revealed) => write!(f, "Revealed({revealed:?})"),
33        }
34    }
35}
36
37impl<P> Default for SparseTrie<P> {
38    fn default() -> Self {
39        Self::Blind
40    }
41}
42
43impl SparseTrie {
44    /// Creates new blind trie.
45    pub const fn blind() -> Self {
46        Self::Blind
47    }
48
49    /// Creates new revealed empty trie.
50    pub fn revealed_empty() -> Self {
51        Self::Revealed(Box::default())
52    }
53
54    /// Reveals the root node if the trie is blinded.
55    ///
56    /// # Returns
57    ///
58    /// Mutable reference to [`RevealedSparseTrie`].
59    pub fn reveal_root(
60        &mut self,
61        root: TrieNode,
62        hash_mask: Option<TrieMask>,
63        retain_updates: bool,
64    ) -> SparseTrieResult<&mut RevealedSparseTrie> {
65        self.reveal_root_with_provider(Default::default(), root, hash_mask, retain_updates)
66    }
67}
68
69impl<P> SparseTrie<P> {
70    /// Returns `true` if the sparse trie has no revealed nodes.
71    pub const fn is_blind(&self) -> bool {
72        matches!(self, Self::Blind)
73    }
74
75    /// Returns mutable reference to revealed sparse trie if the trie is not blind.
76    pub fn as_revealed_mut(&mut self) -> Option<&mut RevealedSparseTrie<P>> {
77        if let Self::Revealed(revealed) = self {
78            Some(revealed)
79        } else {
80            None
81        }
82    }
83
84    /// Reveals the root node if the trie is blinded.
85    ///
86    /// # Returns
87    ///
88    /// Mutable reference to [`RevealedSparseTrie`].
89    pub fn reveal_root_with_provider(
90        &mut self,
91        provider: P,
92        root: TrieNode,
93        hash_mask: Option<TrieMask>,
94        retain_updates: bool,
95    ) -> SparseTrieResult<&mut RevealedSparseTrie<P>> {
96        if self.is_blind() {
97            *self = Self::Revealed(Box::new(RevealedSparseTrie::from_provider_and_root(
98                provider,
99                root,
100                hash_mask,
101                retain_updates,
102            )?))
103        }
104        Ok(self.as_revealed_mut().unwrap())
105    }
106
107    /// Wipe the trie, removing all values and nodes, and replacing the root with an empty node.
108    pub fn wipe(&mut self) -> SparseTrieResult<()> {
109        let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
110        revealed.wipe();
111        Ok(())
112    }
113
114    /// Calculates and returns the trie root if the trie has been revealed.
115    pub fn root(&mut self) -> Option<B256> {
116        Some(self.as_revealed_mut()?.root())
117    }
118
119    /// Calculates the hashes of the nodes below the provided level.
120    pub fn calculate_below_level(&mut self, level: usize) {
121        self.as_revealed_mut().unwrap().update_rlp_node_level(level);
122    }
123}
124
125impl<P> SparseTrie<P>
126where
127    P: BlindedProvider,
128    SparseTrieError: From<P::Error>,
129{
130    /// Update the leaf node.
131    pub fn update_leaf(&mut self, path: Nibbles, value: Vec<u8>) -> SparseTrieResult<()> {
132        let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
133        revealed.update_leaf(path, value)?;
134        Ok(())
135    }
136
137    /// Remove the leaf node.
138    pub fn remove_leaf(&mut self, path: &Nibbles) -> SparseTrieResult<()> {
139        let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
140        revealed.remove_leaf(path)?;
141        Ok(())
142    }
143}
144
145/// The representation of revealed sparse trie.
146///
147/// ## Invariants
148///
149/// - The root node is always present in `nodes` collection.
150/// - Each leaf entry in `nodes` collection must have a corresponding entry in `values` collection.
151///   The opposite is also true.
152/// - All keys in `values` collection are full leaf paths.
153#[derive(Clone, PartialEq, Eq)]
154pub struct RevealedSparseTrie<P = DefaultBlindedProvider> {
155    /// Blinded node provider.
156    provider: P,
157    /// All trie nodes.
158    nodes: HashMap<Nibbles, SparseNode>,
159    /// All branch node hash masks.
160    branch_node_hash_masks: HashMap<Nibbles, TrieMask>,
161    /// All leaf values.
162    values: HashMap<Nibbles, Vec<u8>>,
163    /// Prefix set.
164    prefix_set: PrefixSetMut,
165    /// Retained trie updates.
166    updates: Option<SparseTrieUpdates>,
167    /// Reusable buffer for RLP encoding of nodes.
168    rlp_buf: Vec<u8>,
169}
170
171impl<P> fmt::Debug for RevealedSparseTrie<P> {
172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173        f.debug_struct("RevealedSparseTrie")
174            .field("nodes", &self.nodes)
175            .field("branch_hash_masks", &self.branch_node_hash_masks)
176            .field("values", &self.values)
177            .field("prefix_set", &self.prefix_set)
178            .field("updates", &self.updates)
179            .field("rlp_buf", &hex::encode(&self.rlp_buf))
180            .finish_non_exhaustive()
181    }
182}
183
184impl Default for RevealedSparseTrie {
185    fn default() -> Self {
186        Self {
187            provider: Default::default(),
188            nodes: HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]),
189            branch_node_hash_masks: HashMap::default(),
190            values: HashMap::default(),
191            prefix_set: PrefixSetMut::default(),
192            updates: None,
193            rlp_buf: Vec::new(),
194        }
195    }
196}
197
198impl RevealedSparseTrie {
199    /// Create new revealed sparse trie from the given root node.
200    pub fn from_root(
201        node: TrieNode,
202        hash_mask: Option<TrieMask>,
203        retain_updates: bool,
204    ) -> SparseTrieResult<Self> {
205        let mut this = Self {
206            provider: Default::default(),
207            nodes: HashMap::default(),
208            branch_node_hash_masks: HashMap::default(),
209            values: HashMap::default(),
210            prefix_set: PrefixSetMut::default(),
211            rlp_buf: Vec::new(),
212            updates: None,
213        }
214        .with_updates(retain_updates);
215        this.reveal_node(Nibbles::default(), node, hash_mask)?;
216        Ok(this)
217    }
218}
219
220impl<P> RevealedSparseTrie<P> {
221    /// Create new revealed sparse trie from the given root node.
222    pub fn from_provider_and_root(
223        provider: P,
224        node: TrieNode,
225        hash_mask: Option<TrieMask>,
226        retain_updates: bool,
227    ) -> SparseTrieResult<Self> {
228        let mut this = Self {
229            provider,
230            nodes: HashMap::default(),
231            branch_node_hash_masks: HashMap::default(),
232            values: HashMap::default(),
233            prefix_set: PrefixSetMut::default(),
234            rlp_buf: Vec::new(),
235            updates: None,
236        }
237        .with_updates(retain_updates);
238        this.reveal_node(Nibbles::default(), node, hash_mask)?;
239        Ok(this)
240    }
241
242    /// Set new blinded node provider on sparse trie.
243    pub fn with_provider<BP>(self, provider: BP) -> RevealedSparseTrie<BP> {
244        RevealedSparseTrie {
245            provider,
246            nodes: self.nodes,
247            branch_node_hash_masks: self.branch_node_hash_masks,
248            values: self.values,
249            prefix_set: self.prefix_set,
250            updates: self.updates,
251            rlp_buf: self.rlp_buf,
252        }
253    }
254
255    /// Set the retention of branch node updates and deletions.
256    pub fn with_updates(mut self, retain_updates: bool) -> Self {
257        if retain_updates {
258            self.updates = Some(SparseTrieUpdates::default());
259        }
260        self
261    }
262
263    /// Returns a reference to the retained sparse node updates without taking them.
264    pub fn updates_ref(&self) -> Cow<'_, SparseTrieUpdates> {
265        self.updates.as_ref().map_or(Cow::Owned(SparseTrieUpdates::default()), Cow::Borrowed)
266    }
267
268    /// Returns a reference to the leaf value if present.
269    pub fn get_leaf_value(&self, path: &Nibbles) -> Option<&Vec<u8>> {
270        self.values.get(path)
271    }
272
273    /// Takes and returns the retained sparse node updates
274    pub fn take_updates(&mut self) -> SparseTrieUpdates {
275        self.updates.take().unwrap_or_default()
276    }
277
278    /// Reveal the trie node only if it was not known already.
279    pub fn reveal_node(
280        &mut self,
281        path: Nibbles,
282        node: TrieNode,
283        hash_mask: Option<TrieMask>,
284    ) -> SparseTrieResult<()> {
285        if let Some(hash_mask) = hash_mask {
286            self.branch_node_hash_masks.insert(path.clone(), hash_mask);
287        }
288
289        match node {
290            TrieNode::EmptyRoot => {
291                debug_assert!(path.is_empty());
292                self.nodes.insert(path, SparseNode::Empty);
293            }
294            TrieNode::Branch(branch) => {
295                let mut stack_ptr = branch.as_ref().first_child_index();
296                for idx in CHILD_INDEX_RANGE {
297                    if branch.state_mask.is_bit_set(idx) {
298                        let mut child_path = path.clone();
299                        child_path.push_unchecked(idx);
300                        self.reveal_node_or_hash(child_path, &branch.stack[stack_ptr])?;
301                        stack_ptr += 1;
302                    }
303                }
304
305                match self.nodes.entry(path) {
306                    Entry::Occupied(mut entry) => match entry.get() {
307                        // Blinded nodes can be replaced.
308                        SparseNode::Hash(_) => {
309                            entry.insert(SparseNode::new_branch(branch.state_mask));
310                        }
311                        // Branch node already exists, or an extension node was placed where a
312                        // branch node was before.
313                        SparseNode::Branch { .. } | SparseNode::Extension { .. } => {}
314                        // All other node types can't be handled.
315                        node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
316                            return Err(SparseTrieErrorKind::Reveal {
317                                path: entry.key().clone(),
318                                node: Box::new(node.clone()),
319                            }
320                            .into())
321                        }
322                    },
323                    Entry::Vacant(entry) => {
324                        entry.insert(SparseNode::new_branch(branch.state_mask));
325                    }
326                }
327            }
328            TrieNode::Extension(ext) => match self.nodes.entry(path) {
329                Entry::Occupied(mut entry) => match entry.get() {
330                    SparseNode::Hash(_) => {
331                        let mut child_path = entry.key().clone();
332                        child_path.extend_from_slice_unchecked(&ext.key);
333                        entry.insert(SparseNode::new_ext(ext.key));
334                        self.reveal_node_or_hash(child_path, &ext.child)?;
335                    }
336                    // Extension node already exists, or an extension node was placed where a branch
337                    // node was before.
338                    SparseNode::Extension { .. } | SparseNode::Branch { .. } => {}
339                    // All other node types can't be handled.
340                    node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
341                        return Err(SparseTrieErrorKind::Reveal {
342                            path: entry.key().clone(),
343                            node: Box::new(node.clone()),
344                        }
345                        .into())
346                    }
347                },
348                Entry::Vacant(entry) => {
349                    let mut child_path = entry.key().clone();
350                    child_path.extend_from_slice_unchecked(&ext.key);
351                    entry.insert(SparseNode::new_ext(ext.key));
352                    self.reveal_node_or_hash(child_path, &ext.child)?;
353                }
354            },
355            TrieNode::Leaf(leaf) => match self.nodes.entry(path) {
356                Entry::Occupied(mut entry) => match entry.get() {
357                    SparseNode::Hash(_) => {
358                        let mut full = entry.key().clone();
359                        full.extend_from_slice_unchecked(&leaf.key);
360                        entry.insert(SparseNode::new_leaf(leaf.key));
361                        self.values.insert(full, leaf.value);
362                    }
363                    // Left node already exists.
364                    SparseNode::Leaf { .. } => {}
365                    // All other node types can't be handled.
366                    node @ (SparseNode::Empty |
367                    SparseNode::Extension { .. } |
368                    SparseNode::Branch { .. }) => {
369                        return Err(SparseTrieErrorKind::Reveal {
370                            path: entry.key().clone(),
371                            node: Box::new(node.clone()),
372                        }
373                        .into())
374                    }
375                },
376                Entry::Vacant(entry) => {
377                    let mut full = entry.key().clone();
378                    full.extend_from_slice_unchecked(&leaf.key);
379                    entry.insert(SparseNode::new_leaf(leaf.key));
380                    self.values.insert(full, leaf.value);
381                }
382            },
383        }
384
385        Ok(())
386    }
387
388    fn reveal_node_or_hash(&mut self, path: Nibbles, child: &[u8]) -> SparseTrieResult<()> {
389        if child.len() == B256::len_bytes() + 1 {
390            let hash = B256::from_slice(&child[1..]);
391            match self.nodes.entry(path) {
392                Entry::Occupied(entry) => match entry.get() {
393                    // Hash node with a different hash can't be handled.
394                    SparseNode::Hash(previous_hash) if previous_hash != &hash => {
395                        return Err(SparseTrieErrorKind::Reveal {
396                            path: entry.key().clone(),
397                            node: Box::new(SparseNode::Hash(hash)),
398                        }
399                        .into())
400                    }
401                    _ => {}
402                },
403                Entry::Vacant(entry) => {
404                    entry.insert(SparseNode::Hash(hash));
405                }
406            }
407            return Ok(())
408        }
409
410        self.reveal_node(path, TrieNode::decode(&mut &child[..])?, None)
411    }
412
413    /// Traverse trie nodes down to the leaf node and collect all nodes along the path.
414    fn take_nodes_for_path(&mut self, path: &Nibbles) -> SparseTrieResult<Vec<RemovedSparseNode>> {
415        let mut current = Nibbles::default(); // Start traversal from the root
416        let mut nodes = Vec::new(); // Collect traversed nodes
417
418        while let Some(node) = self.nodes.remove(&current) {
419            match &node {
420                SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
421                &SparseNode::Hash(hash) => {
422                    return Err(SparseTrieErrorKind::BlindedNode { path: current, hash }.into())
423                }
424                SparseNode::Leaf { key: _key, .. } => {
425                    // Leaf node is always the one that we're deleting, and no other leaf nodes can
426                    // be found during traversal.
427
428                    #[cfg(debug_assertions)]
429                    {
430                        let mut current = current.clone();
431                        current.extend_from_slice_unchecked(_key);
432                        assert_eq!(&current, path);
433                    }
434
435                    nodes.push(RemovedSparseNode {
436                        path: current.clone(),
437                        node,
438                        unset_branch_nibble: None,
439                    });
440                    break
441                }
442                SparseNode::Extension { key, .. } => {
443                    #[cfg(debug_assertions)]
444                    {
445                        let mut current = current.clone();
446                        current.extend_from_slice_unchecked(key);
447                        assert!(
448                            path.starts_with(&current),
449                            "path: {:?}, current: {:?}, key: {:?}",
450                            path,
451                            current,
452                            key
453                        );
454                    }
455
456                    let path = current.clone();
457                    current.extend_from_slice_unchecked(key);
458                    nodes.push(RemovedSparseNode { path, node, unset_branch_nibble: None });
459                }
460                SparseNode::Branch { state_mask, .. } => {
461                    let nibble = path[current.len()];
462                    debug_assert!(
463                        state_mask.is_bit_set(nibble),
464                        "current: {:?}, path: {:?}, nibble: {:?}, state_mask: {:?}",
465                        current,
466                        path,
467                        nibble,
468                        state_mask
469                    );
470
471                    // If the branch node has a child that is a leaf node that we're removing,
472                    // we need to unset this nibble.
473                    // Any other branch nodes will not require unsetting the nibble, because
474                    // deleting one leaf node can not remove the whole path
475                    // where the branch node is located.
476                    let mut child_path =
477                        Nibbles::from_nibbles([current.as_slice(), &[nibble]].concat());
478                    let unset_branch_nibble = self
479                        .nodes
480                        .get(&child_path)
481                        .is_some_and(move |node| match node {
482                            SparseNode::Leaf { key, .. } => {
483                                // Get full path of the leaf node
484                                child_path.extend_from_slice_unchecked(key);
485                                &child_path == path
486                            }
487                            _ => false,
488                        })
489                        .then_some(nibble);
490
491                    nodes.push(RemovedSparseNode {
492                        path: current.clone(),
493                        node,
494                        unset_branch_nibble,
495                    });
496
497                    current.push_unchecked(nibble);
498                }
499            }
500        }
501
502        Ok(nodes)
503    }
504
505    /// Wipe the trie, removing all values and nodes, and replacing the root with an empty node.
506    pub fn wipe(&mut self) {
507        self.nodes = HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]);
508        self.values = HashMap::default();
509        self.prefix_set = PrefixSetMut::all();
510        self.updates = self.updates.is_some().then(SparseTrieUpdates::wiped);
511    }
512
513    /// Return the root of the sparse trie.
514    /// Updates all remaining dirty nodes before calculating the root.
515    pub fn root(&mut self) -> B256 {
516        // take the current prefix set.
517        let mut prefix_set = std::mem::take(&mut self.prefix_set).freeze();
518        let rlp_node = self.rlp_node_allocate(Nibbles::default(), &mut prefix_set);
519        if let Some(root_hash) = rlp_node.as_hash() {
520            root_hash
521        } else {
522            keccak256(rlp_node)
523        }
524    }
525
526    /// Update hashes of the nodes that are located at a level deeper than or equal to the provided
527    /// depth. Root node has a level of 0.
528    pub fn update_rlp_node_level(&mut self, depth: usize) {
529        let mut prefix_set = self.prefix_set.clone().freeze();
530        let mut buffers = RlpNodeBuffers::default();
531
532        let targets = self.get_changed_nodes_at_depth(&mut prefix_set, depth);
533        for target in targets {
534            buffers.path_stack.push((target, Some(true)));
535            self.rlp_node(&mut prefix_set, &mut buffers);
536        }
537    }
538
539    /// Returns a list of paths to the nodes that were changed according to the prefix set and are
540    /// located at the provided depth when counting from the root node. If there's a leaf at a
541    /// depth less than the provided depth, it will be included in the result.
542    fn get_changed_nodes_at_depth(&self, prefix_set: &mut PrefixSet, depth: usize) -> Vec<Nibbles> {
543        let mut paths = Vec::from([(Nibbles::default(), 0)]);
544        let mut targets = Vec::new();
545
546        while let Some((mut path, level)) = paths.pop() {
547            match self.nodes.get(&path).unwrap() {
548                SparseNode::Empty | SparseNode::Hash(_) => {}
549                SparseNode::Leaf { hash, .. } => {
550                    if hash.is_some() && !prefix_set.contains(&path) {
551                        continue
552                    }
553
554                    targets.push(path);
555                }
556                SparseNode::Extension { key, hash } => {
557                    if hash.is_some() && !prefix_set.contains(&path) {
558                        continue
559                    }
560
561                    if level >= depth {
562                        targets.push(path);
563                    } else {
564                        path.extend_from_slice_unchecked(key);
565                        paths.push((path, level + 1));
566                    }
567                }
568                SparseNode::Branch { state_mask, hash, .. } => {
569                    if hash.is_some() && !prefix_set.contains(&path) {
570                        continue
571                    }
572
573                    if level >= depth {
574                        targets.push(path);
575                    } else {
576                        for bit in CHILD_INDEX_RANGE.rev() {
577                            if state_mask.is_bit_set(bit) {
578                                let mut child_path = path.clone();
579                                child_path.push_unchecked(bit);
580                                paths.push((child_path, level + 1));
581                            }
582                        }
583                    }
584                }
585            }
586        }
587
588        targets
589    }
590
591    fn rlp_node_allocate(&mut self, path: Nibbles, prefix_set: &mut PrefixSet) -> RlpNode {
592        let mut buffers = RlpNodeBuffers::new_with_path(path);
593        self.rlp_node(prefix_set, &mut buffers)
594    }
595
596    fn rlp_node(&mut self, prefix_set: &mut PrefixSet, buffers: &mut RlpNodeBuffers) -> RlpNode {
597        'main: while let Some((path, mut is_in_prefix_set)) = buffers.path_stack.pop() {
598            // Check if the path is in the prefix set.
599            // First, check the cached value. If it's `None`, then check the prefix set, and update
600            // the cached value.
601            let mut prefix_set_contains =
602                |path: &Nibbles| *is_in_prefix_set.get_or_insert_with(|| prefix_set.contains(path));
603
604            let (rlp_node, calculated, node_type) = match self.nodes.get_mut(&path).unwrap() {
605                SparseNode::Empty => {
606                    (RlpNode::word_rlp(&EMPTY_ROOT_HASH), false, SparseNodeType::Empty)
607                }
608                SparseNode::Hash(hash) => (RlpNode::word_rlp(hash), false, SparseNodeType::Hash),
609                SparseNode::Leaf { key, hash } => {
610                    let mut path = path.clone();
611                    path.extend_from_slice_unchecked(key);
612                    if let Some(hash) = hash.filter(|_| !prefix_set_contains(&path)) {
613                        (RlpNode::word_rlp(&hash), false, SparseNodeType::Leaf)
614                    } else {
615                        let value = self.values.get(&path).unwrap();
616                        self.rlp_buf.clear();
617                        let rlp_node = LeafNodeRef { key, value }.rlp(&mut self.rlp_buf);
618                        *hash = rlp_node.as_hash();
619                        (rlp_node, true, SparseNodeType::Leaf)
620                    }
621                }
622                SparseNode::Extension { key, hash } => {
623                    let mut child_path = path.clone();
624                    child_path.extend_from_slice_unchecked(key);
625                    if let Some(hash) = hash.filter(|_| !prefix_set_contains(&path)) {
626                        (
627                            RlpNode::word_rlp(&hash),
628                            false,
629                            SparseNodeType::Extension { store_in_db_trie: true },
630                        )
631                    } else if buffers.rlp_node_stack.last().is_some_and(|e| e.0 == child_path) {
632                        let (_, child, _, node_type) = buffers.rlp_node_stack.pop().unwrap();
633                        self.rlp_buf.clear();
634                        let rlp_node = ExtensionNodeRef::new(key, &child).rlp(&mut self.rlp_buf);
635                        *hash = rlp_node.as_hash();
636
637                        (
638                            rlp_node,
639                            true,
640                            SparseNodeType::Extension {
641                                // Inherit the `store_in_db_trie` flag from the child node, which is
642                                // always the branch node
643                                store_in_db_trie: node_type.store_in_db_trie(),
644                            },
645                        )
646                    } else {
647                        // need to get rlp node for child first
648                        buffers.path_stack.extend([(path, is_in_prefix_set), (child_path, None)]);
649                        continue
650                    }
651                }
652                SparseNode::Branch { state_mask, hash, store_in_db_trie } => {
653                    if let Some((hash, store_in_db_trie)) =
654                        hash.zip(*store_in_db_trie).filter(|_| !prefix_set_contains(&path))
655                    {
656                        buffers.rlp_node_stack.push((
657                            path,
658                            RlpNode::word_rlp(&hash),
659                            false,
660                            SparseNodeType::Branch { store_in_db_trie },
661                        ));
662                        continue
663                    }
664                    let retain_updates = self.updates.is_some() && prefix_set_contains(&path);
665
666                    buffers.branch_child_buf.clear();
667                    // Walk children in a reverse order from `f` to `0`, so we pop the `0` first
668                    // from the stack and keep walking in the sorted order.
669                    for bit in CHILD_INDEX_RANGE.rev() {
670                        if state_mask.is_bit_set(bit) {
671                            let mut child = path.clone();
672                            child.push_unchecked(bit);
673                            buffers.branch_child_buf.push(child);
674                        }
675                    }
676
677                    buffers
678                        .branch_value_stack_buf
679                        .resize(buffers.branch_child_buf.len(), Default::default());
680                    let mut added_children = false;
681
682                    // TODO(alexey): set the `TrieMask` bits directly
683                    let mut tree_mask_values = Vec::new();
684                    let mut hash_mask_values = Vec::new();
685                    let mut hashes = Vec::new();
686                    for (i, child_path) in buffers.branch_child_buf.iter().enumerate() {
687                        if buffers.rlp_node_stack.last().is_some_and(|e| &e.0 == child_path) {
688                            let (_, child, calculated, node_type) =
689                                buffers.rlp_node_stack.pop().unwrap();
690
691                            // Update the masks only if we need to retain trie updates
692                            if retain_updates {
693                                // Set the trie mask
694                                let tree_mask_value = if node_type.store_in_db_trie() {
695                                    // A branch or an extension node explicitly set the
696                                    // `store_in_db_trie` flag
697                                    true
698                                } else {
699                                    // Set the flag according to whether a child node was
700                                    // pre-calculated (`calculated = false`), meaning that it wasn't
701                                    // in the database
702                                    !calculated
703                                };
704                                tree_mask_values.push(tree_mask_value);
705
706                                // Set the hash mask. If a child node is a revealed branch node OR
707                                // is a blinded node that has its hash mask bit set according to the
708                                // database, set the hash mask bit and save the hash.
709                                let hash = child.as_hash().filter(|_| {
710                                    node_type.is_branch() ||
711                                        (node_type.is_hash() &&
712                                            self.branch_node_hash_masks
713                                                .get(&path)
714                                                .is_some_and(|mask| {
715                                                    mask.is_bit_set(child_path.last().unwrap())
716                                                }))
717                                });
718                                let hash_mask_value = hash.is_some();
719                                hash_mask_values.push(hash_mask_value);
720                                if let Some(hash) = hash {
721                                    hashes.push(hash);
722                                }
723
724                                trace!(
725                                    target: "trie::sparse",
726                                    ?path,
727                                    ?child_path,
728                                    ?tree_mask_value,
729                                    ?hash_mask_value,
730                                    "Updating branch node child masks"
731                                );
732                            }
733
734                            // Insert children in the resulting buffer in a normal order,
735                            // because initially we iterated in reverse.
736                            buffers.branch_value_stack_buf
737                                [buffers.branch_child_buf.len() - i - 1] = child;
738                            added_children = true;
739                        } else {
740                            debug_assert!(!added_children);
741                            buffers.path_stack.push((path, is_in_prefix_set));
742                            buffers
743                                .path_stack
744                                .extend(buffers.branch_child_buf.drain(..).map(|p| (p, None)));
745                            continue 'main
746                        }
747                    }
748
749                    self.rlp_buf.clear();
750                    let branch_node_ref =
751                        BranchNodeRef::new(&buffers.branch_value_stack_buf, *state_mask);
752                    let rlp_node = branch_node_ref.rlp(&mut self.rlp_buf);
753                    *hash = rlp_node.as_hash();
754
755                    // Save a branch node update only if it's not a root node, and we need to
756                    // persist updates.
757                    let store_in_db_trie_value = if let Some(updates) =
758                        self.updates.as_mut().filter(|_| retain_updates && !path.is_empty())
759                    {
760                        let mut tree_mask_values = tree_mask_values.into_iter().rev();
761                        let mut hash_mask_values = hash_mask_values.into_iter().rev();
762                        let mut tree_mask = TrieMask::default();
763                        let mut hash_mask = TrieMask::default();
764                        for (i, child) in branch_node_ref.children() {
765                            if child.is_some() {
766                                if hash_mask_values.next().unwrap() {
767                                    hash_mask.set_bit(i);
768                                }
769                                if tree_mask_values.next().unwrap() {
770                                    tree_mask.set_bit(i);
771                                }
772                            }
773                        }
774
775                        // Store in DB trie if there are either any children that are stored in the
776                        // DB trie, or any children represent hashed values
777                        let store_in_db_trie = !tree_mask.is_empty() || !hash_mask.is_empty();
778                        if store_in_db_trie {
779                            hashes.reverse();
780                            let branch_node = BranchNodeCompact::new(
781                                *state_mask,
782                                tree_mask,
783                                hash_mask,
784                                hashes,
785                                hash.filter(|_| path.len() == 0),
786                            );
787                            updates.updated_nodes.insert(path.clone(), branch_node);
788                        }
789
790                        store_in_db_trie
791                    } else {
792                        false
793                    };
794                    *store_in_db_trie = Some(store_in_db_trie_value);
795
796                    (
797                        rlp_node,
798                        true,
799                        SparseNodeType::Branch { store_in_db_trie: store_in_db_trie_value },
800                    )
801                }
802            };
803            buffers.rlp_node_stack.push((path, rlp_node, calculated, node_type));
804        }
805
806        debug_assert_eq!(buffers.rlp_node_stack.len(), 1);
807        buffers.rlp_node_stack.pop().unwrap().1
808    }
809}
810
811impl<P> RevealedSparseTrie<P>
812where
813    P: BlindedProvider,
814    SparseTrieError: From<P::Error>,
815{
816    /// Update the leaf node with provided value.
817    pub fn update_leaf(&mut self, path: Nibbles, value: Vec<u8>) -> SparseTrieResult<()> {
818        self.prefix_set.insert(path.clone());
819        let existing = self.values.insert(path.clone(), value);
820        if existing.is_some() {
821            // trie structure unchanged, return immediately
822            return Ok(())
823        }
824
825        let mut current = Nibbles::default();
826        while let Some(node) = self.nodes.get_mut(&current) {
827            match node {
828                SparseNode::Empty => {
829                    *node = SparseNode::new_leaf(path);
830                    break
831                }
832                &mut SparseNode::Hash(hash) => {
833                    return Err(SparseTrieErrorKind::BlindedNode { path: current, hash }.into())
834                }
835                SparseNode::Leaf { key: current_key, .. } => {
836                    current.extend_from_slice_unchecked(current_key);
837
838                    // this leaf is being updated
839                    if current == path {
840                        unreachable!("we already checked leaf presence in the beginning");
841                    }
842
843                    // find the common prefix
844                    let common = current.common_prefix_length(&path);
845
846                    // update existing node
847                    let new_ext_key = current.slice(current.len() - current_key.len()..common);
848                    *node = SparseNode::new_ext(new_ext_key);
849
850                    // create a branch node and corresponding leaves
851                    self.nodes.reserve(3);
852                    self.nodes.insert(
853                        current.slice(..common),
854                        SparseNode::new_split_branch(current[common], path[common]),
855                    );
856                    self.nodes.insert(
857                        path.slice(..=common),
858                        SparseNode::new_leaf(path.slice(common + 1..)),
859                    );
860                    self.nodes.insert(
861                        current.slice(..=common),
862                        SparseNode::new_leaf(current.slice(common + 1..)),
863                    );
864
865                    break;
866                }
867                SparseNode::Extension { key, .. } => {
868                    current.extend_from_slice(key);
869
870                    if !path.starts_with(&current) {
871                        // find the common prefix
872                        let common = current.common_prefix_length(&path);
873                        *key = current.slice(current.len() - key.len()..common);
874
875                        // If branch node updates retention is enabled, we need to query the
876                        // extension node child to later set the hash mask for a parent branch node
877                        // correctly.
878                        if self.updates.is_some() {
879                            // Check if the extension node child is a hash that needs to be revealed
880                            if self.nodes.get(&current).unwrap().is_hash() {
881                                if let Some(node) = self.provider.blinded_node(&current)? {
882                                    let decoded = TrieNode::decode(&mut &node[..])?;
883                                    trace!(target: "trie::sparse", ?current, ?decoded, "Revealing extension node child");
884                                    // We'll never have to update the revealed child node, only
885                                    // remove or do nothing, so
886                                    // we can safely ignore the hash mask here and
887                                    // pass `None`.
888                                    self.reveal_node(current.clone(), decoded, None)?;
889                                }
890                            }
891                        }
892
893                        // create state mask for new branch node
894                        // NOTE: this might overwrite the current extension node
895                        self.nodes.reserve(3);
896                        let branch = SparseNode::new_split_branch(current[common], path[common]);
897                        self.nodes.insert(current.slice(..common), branch);
898
899                        // create new leaf
900                        let new_leaf = SparseNode::new_leaf(path.slice(common + 1..));
901                        self.nodes.insert(path.slice(..=common), new_leaf);
902
903                        // recreate extension to previous child if needed
904                        let key = current.slice(common + 1..);
905                        if !key.is_empty() {
906                            self.nodes.insert(current.slice(..=common), SparseNode::new_ext(key));
907                        }
908
909                        break;
910                    }
911                }
912                SparseNode::Branch { state_mask, .. } => {
913                    let nibble = path[current.len()];
914                    current.push_unchecked(nibble);
915                    if !state_mask.is_bit_set(nibble) {
916                        state_mask.set_bit(nibble);
917                        let new_leaf = SparseNode::new_leaf(path.slice(current.len()..));
918                        self.nodes.insert(current, new_leaf);
919                        break;
920                    }
921                }
922            };
923        }
924
925        Ok(())
926    }
927
928    /// Remove leaf node from the trie.
929    pub fn remove_leaf(&mut self, path: &Nibbles) -> SparseTrieResult<()> {
930        if self.values.remove(path).is_none() {
931            if let Some(&SparseNode::Hash(hash)) = self.nodes.get(path) {
932                // Leaf is present in the trie, but it's blinded.
933                return Err(SparseTrieErrorKind::BlindedNode { path: path.clone(), hash }.into())
934            }
935
936            // Leaf is not present in the trie.
937            return Ok(())
938        }
939        self.prefix_set.insert(path.clone());
940
941        // If the path wasn't present in `values`, we still need to walk the trie and ensure that
942        // there is no node at the path. When a leaf node is a blinded `Hash`, it will have an entry
943        // in `nodes`, but not in the `values`.
944
945        let mut removed_nodes = self.take_nodes_for_path(path)?;
946        trace!(target: "trie::sparse", ?path, ?removed_nodes, "Removed nodes for path");
947        // Pop the first node from the stack which is the leaf node we want to remove.
948        let mut child = removed_nodes.pop().expect("leaf exists");
949        #[cfg(debug_assertions)]
950        {
951            let mut child_path = child.path.clone();
952            let SparseNode::Leaf { key, .. } = &child.node else { panic!("expected leaf node") };
953            child_path.extend_from_slice_unchecked(key);
954            assert_eq!(&child_path, path);
955        }
956
957        // If we don't have any other removed nodes, insert an empty node at the root.
958        if removed_nodes.is_empty() {
959            debug_assert!(self.nodes.is_empty());
960            self.nodes.insert(Nibbles::default(), SparseNode::Empty);
961
962            return Ok(())
963        }
964
965        // Walk the stack of removed nodes from the back and re-insert them back into the trie,
966        // adjusting the node type as needed.
967        while let Some(removed_node) = removed_nodes.pop() {
968            let removed_path = removed_node.path;
969
970            let new_node = match &removed_node.node {
971                SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
972                &SparseNode::Hash(hash) => {
973                    return Err(SparseTrieErrorKind::BlindedNode { path: removed_path, hash }.into())
974                }
975                SparseNode::Leaf { .. } => {
976                    unreachable!("we already popped the leaf node")
977                }
978                SparseNode::Extension { key, .. } => {
979                    // If the node is an extension node, we need to look at its child to see if we
980                    // need to merge them.
981                    match &child.node {
982                        SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
983                        &SparseNode::Hash(hash) => {
984                            return Err(
985                                SparseTrieErrorKind::BlindedNode { path: child.path, hash }.into()
986                            )
987                        }
988                        // For a leaf node, we collapse the extension node into a leaf node,
989                        // extending the key. While it's impossible to encounter an extension node
990                        // followed by a leaf node in a complete trie, it's possible here because we
991                        // could have downgraded the extension node's child into a leaf node from
992                        // another node type.
993                        SparseNode::Leaf { key: leaf_key, .. } => {
994                            self.nodes.remove(&child.path);
995
996                            let mut new_key = key.clone();
997                            new_key.extend_from_slice_unchecked(leaf_key);
998                            SparseNode::new_leaf(new_key)
999                        }
1000                        // For an extension node, we collapse them into one extension node,
1001                        // extending the key
1002                        SparseNode::Extension { key: extension_key, .. } => {
1003                            self.nodes.remove(&child.path);
1004
1005                            let mut new_key = key.clone();
1006                            new_key.extend_from_slice_unchecked(extension_key);
1007                            SparseNode::new_ext(new_key)
1008                        }
1009                        // For a branch node, we just leave the extension node as-is.
1010                        SparseNode::Branch { .. } => removed_node.node,
1011                    }
1012                }
1013                SparseNode::Branch { mut state_mask, hash: _, store_in_db_trie: _ } => {
1014                    // If the node is a branch node, we need to check the number of children left
1015                    // after deleting the child at the given nibble.
1016
1017                    if let Some(removed_nibble) = removed_node.unset_branch_nibble {
1018                        state_mask.unset_bit(removed_nibble);
1019                    }
1020
1021                    // If only one child is left set in the branch node, we need to collapse it.
1022                    if state_mask.count_bits() == 1 {
1023                        let child_nibble =
1024                            state_mask.first_set_bit_index().expect("state mask is not empty");
1025
1026                        // Get full path of the only child node left.
1027                        let mut child_path = removed_path.clone();
1028                        child_path.push_unchecked(child_nibble);
1029
1030                        trace!(target: "trie::sparse", ?removed_path, ?child_path, ?child, "Branch node has only one child");
1031
1032                        if self.nodes.get(&child_path).unwrap().is_hash() {
1033                            trace!(target: "trie::sparse", ?child_path, "Retrieving remaining blinded branch child");
1034                            if let Some(node) = self.provider.blinded_node(&child_path)? {
1035                                let decoded = TrieNode::decode(&mut &node[..])?;
1036                                trace!(target: "trie::sparse", ?child_path, ?decoded, "Revealing remaining blinded branch child");
1037                                // We'll never have to update the revealed branch node, only remove
1038                                // or do nothing, so we can safely ignore the hash mask here and
1039                                // pass `None`.
1040                                self.reveal_node(child_path.clone(), decoded, None)?;
1041                            }
1042                        }
1043
1044                        // Get the only child node.
1045                        let child = self.nodes.get(&child_path).unwrap();
1046
1047                        let mut delete_child = false;
1048                        let new_node = match child {
1049                            SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
1050                            &SparseNode::Hash(hash) => {
1051                                return Err(SparseTrieErrorKind::BlindedNode {
1052                                    path: child_path,
1053                                    hash,
1054                                }
1055                                .into())
1056                            }
1057                            // If the only child is a leaf node, we downgrade the branch node into a
1058                            // leaf node, prepending the nibble to the key, and delete the old
1059                            // child.
1060                            SparseNode::Leaf { key, .. } => {
1061                                delete_child = true;
1062
1063                                let mut new_key = Nibbles::from_nibbles_unchecked([child_nibble]);
1064                                new_key.extend_from_slice_unchecked(key);
1065                                SparseNode::new_leaf(new_key)
1066                            }
1067                            // If the only child node is an extension node, we downgrade the branch
1068                            // node into an even longer extension node, prepending the nibble to the
1069                            // key, and delete the old child.
1070                            SparseNode::Extension { key, .. } => {
1071                                delete_child = true;
1072
1073                                let mut new_key = Nibbles::from_nibbles_unchecked([child_nibble]);
1074                                new_key.extend_from_slice_unchecked(key);
1075                                SparseNode::new_ext(new_key)
1076                            }
1077                            // If the only child is a branch node, we downgrade the current branch
1078                            // node into a one-nibble extension node.
1079                            SparseNode::Branch { .. } => {
1080                                SparseNode::new_ext(Nibbles::from_nibbles_unchecked([child_nibble]))
1081                            }
1082                        };
1083
1084                        if delete_child {
1085                            self.nodes.remove(&child_path);
1086                        }
1087
1088                        if let Some(updates) = self.updates.as_mut() {
1089                            updates.removed_nodes.insert(removed_path.clone());
1090                        }
1091
1092                        new_node
1093                    }
1094                    // If more than one child is left set in the branch, we just re-insert it
1095                    // as-is.
1096                    else {
1097                        SparseNode::new_branch(state_mask)
1098                    }
1099                }
1100            };
1101
1102            child = RemovedSparseNode {
1103                path: removed_path.clone(),
1104                node: new_node.clone(),
1105                unset_branch_nibble: None,
1106            };
1107            trace!(target: "trie::sparse", ?removed_path, ?new_node, "Re-inserting the node");
1108            self.nodes.insert(removed_path, new_node);
1109        }
1110
1111        Ok(())
1112    }
1113}
1114
1115/// Enum representing sparse trie node type.
1116#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1117enum SparseNodeType {
1118    /// Empty trie node.
1119    Empty,
1120    /// The hash of the node that was not revealed.
1121    Hash,
1122    /// Sparse leaf node.
1123    Leaf,
1124    /// Sparse extension node.
1125    Extension {
1126        /// A flag indicating whether the extension node should be stored in the database.
1127        store_in_db_trie: bool,
1128    },
1129    /// Sparse branch node.
1130    Branch {
1131        /// A flag indicating whether the branch node should be stored in the database.
1132        store_in_db_trie: bool,
1133    },
1134}
1135
1136impl SparseNodeType {
1137    const fn is_hash(&self) -> bool {
1138        matches!(self, Self::Hash)
1139    }
1140
1141    const fn is_branch(&self) -> bool {
1142        matches!(self, Self::Branch { .. })
1143    }
1144
1145    const fn store_in_db_trie(&self) -> bool {
1146        match *self {
1147            Self::Extension { store_in_db_trie } | Self::Branch { store_in_db_trie } => {
1148                store_in_db_trie
1149            }
1150            _ => false,
1151        }
1152    }
1153}
1154
1155/// Enum representing trie nodes in sparse trie.
1156#[derive(Debug, Clone, PartialEq, Eq)]
1157pub enum SparseNode {
1158    /// Empty trie node.
1159    Empty,
1160    /// The hash of the node that was not revealed.
1161    Hash(B256),
1162    /// Sparse leaf node with remaining key suffix.
1163    Leaf {
1164        /// Remaining key suffix for the leaf node.
1165        key: Nibbles,
1166        /// Pre-computed hash of the sparse node.
1167        /// Can be reused unless this trie path has been updated.
1168        hash: Option<B256>,
1169    },
1170    /// Sparse extension node with key.
1171    Extension {
1172        /// The key slice stored by this extension node.
1173        key: Nibbles,
1174        /// Pre-computed hash of the sparse node.
1175        /// Can be reused unless this trie path has been updated.
1176        hash: Option<B256>,
1177    },
1178    /// Sparse branch node with state mask.
1179    Branch {
1180        /// The bitmask representing children present in the branch node.
1181        state_mask: TrieMask,
1182        /// Pre-computed hash of the sparse node.
1183        /// Can be reused unless this trie path has been updated.
1184        hash: Option<B256>,
1185        /// Pre-computed flag indicating whether the trie node should be stored in the database.
1186        /// Can be reused unless this trie path has been updated.
1187        store_in_db_trie: Option<bool>,
1188    },
1189}
1190
1191impl SparseNode {
1192    /// Create new sparse node from [`TrieNode`].
1193    pub fn from_node(node: TrieNode) -> Self {
1194        match node {
1195            TrieNode::EmptyRoot => Self::Empty,
1196            TrieNode::Leaf(leaf) => Self::new_leaf(leaf.key),
1197            TrieNode::Extension(ext) => Self::new_ext(ext.key),
1198            TrieNode::Branch(branch) => Self::new_branch(branch.state_mask),
1199        }
1200    }
1201
1202    /// Create new [`SparseNode::Branch`] from state mask.
1203    pub const fn new_branch(state_mask: TrieMask) -> Self {
1204        Self::Branch { state_mask, hash: None, store_in_db_trie: None }
1205    }
1206
1207    /// Create new [`SparseNode::Branch`] with two bits set.
1208    pub const fn new_split_branch(bit_a: u8, bit_b: u8) -> Self {
1209        let state_mask = TrieMask::new(
1210            // set bits for both children
1211            (1u16 << bit_a) | (1u16 << bit_b),
1212        );
1213        Self::Branch { state_mask, hash: None, store_in_db_trie: None }
1214    }
1215
1216    /// Create new [`SparseNode::Extension`] from the key slice.
1217    pub const fn new_ext(key: Nibbles) -> Self {
1218        Self::Extension { key, hash: None }
1219    }
1220
1221    /// Create new [`SparseNode::Leaf`] from leaf key and value.
1222    pub const fn new_leaf(key: Nibbles) -> Self {
1223        Self::Leaf { key, hash: None }
1224    }
1225
1226    /// Returns `true` if the node is a hash node.
1227    pub const fn is_hash(&self) -> bool {
1228        matches!(self, Self::Hash(_))
1229    }
1230}
1231
1232#[derive(Debug)]
1233struct RemovedSparseNode {
1234    path: Nibbles,
1235    node: SparseNode,
1236    unset_branch_nibble: Option<u8>,
1237}
1238
1239/// Collection of reusable buffers for [`RevealedSparseTrie::rlp_node`].
1240#[derive(Debug, Default)]
1241struct RlpNodeBuffers {
1242    /// Stack of paths we need rlp nodes for and whether the path is in the prefix set.
1243    path_stack: Vec<(Nibbles, Option<bool>)>,
1244    /// Stack of rlp nodes
1245    rlp_node_stack: Vec<(Nibbles, RlpNode, bool, SparseNodeType)>,
1246    /// Reusable branch child path
1247    branch_child_buf: SmallVec<[Nibbles; 16]>,
1248    /// Reusable branch value stack
1249    branch_value_stack_buf: SmallVec<[RlpNode; 16]>,
1250}
1251
1252impl RlpNodeBuffers {
1253    /// Creates a new instance of buffers with the given path on the stack.
1254    fn new_with_path(path: Nibbles) -> Self {
1255        Self {
1256            path_stack: vec![(path, None)],
1257            rlp_node_stack: Vec::new(),
1258            branch_child_buf: SmallVec::<[Nibbles; 16]>::new_const(),
1259            branch_value_stack_buf: SmallVec::<[RlpNode; 16]>::new_const(),
1260        }
1261    }
1262}
1263
1264/// The aggregation of sparse trie updates.
1265#[derive(Debug, Clone, Default, PartialEq, Eq)]
1266pub struct SparseTrieUpdates {
1267    pub(crate) updated_nodes: HashMap<Nibbles, BranchNodeCompact>,
1268    pub(crate) removed_nodes: HashSet<Nibbles>,
1269    pub(crate) wiped: bool,
1270}
1271
1272impl SparseTrieUpdates {
1273    /// Create new wiped sparse trie updates.
1274    pub fn wiped() -> Self {
1275        Self { wiped: true, ..Default::default() }
1276    }
1277}
1278
1279#[cfg(test)]
1280mod tests {
1281    use super::*;
1282    use alloy_primitives::{
1283        map::{B256HashSet, HashSet},
1284        U256,
1285    };
1286    use alloy_rlp::Encodable;
1287    use assert_matches::assert_matches;
1288    use itertools::Itertools;
1289    use prop::sample::SizeRange;
1290    use proptest::prelude::*;
1291    use proptest_arbitrary_interop::arb;
1292    use rand::seq::IteratorRandom;
1293    use reth_primitives_traits::Account;
1294    use reth_trie::{
1295        hashed_cursor::{noop::NoopHashedAccountCursor, HashedPostStateAccountCursor},
1296        node_iter::{TrieElement, TrieNodeIter},
1297        trie_cursor::noop::NoopAccountTrieCursor,
1298        updates::TrieUpdates,
1299        walker::TrieWalker,
1300        BranchNode, ExtensionNode, HashedPostState, LeafNode, TrieAccount,
1301    };
1302    use reth_trie_common::{
1303        proof::{ProofNodes, ProofRetainer},
1304        HashBuilder,
1305    };
1306    use std::collections::BTreeMap;
1307
1308    /// Pad nibbles to the length of a B256 hash with zeros on the left.
1309    fn pad_nibbles_left(nibbles: Nibbles) -> Nibbles {
1310        let mut base =
1311            Nibbles::from_nibbles_unchecked(vec![0; B256::len_bytes() * 2 - nibbles.len()]);
1312        base.extend_from_slice_unchecked(&nibbles);
1313        base
1314    }
1315
1316    /// Pad nibbles to the length of a B256 hash with zeros on the right.
1317    fn pad_nibbles_right(mut nibbles: Nibbles) -> Nibbles {
1318        nibbles.extend_from_slice_unchecked(&vec![0; B256::len_bytes() * 2 - nibbles.len()]);
1319        nibbles
1320    }
1321
1322    /// Calculate the state root by feeding the provided state to the hash builder and retaining the
1323    /// proofs for the provided targets.
1324    ///
1325    /// Returns the state root and the retained proof nodes.
1326    fn run_hash_builder(
1327        state: impl IntoIterator<Item = (Nibbles, Account)> + Clone,
1328        destroyed_accounts: B256HashSet,
1329        proof_targets: impl IntoIterator<Item = Nibbles>,
1330    ) -> (B256, TrieUpdates, ProofNodes, HashMap<Nibbles, TrieMask>) {
1331        let mut account_rlp = Vec::new();
1332
1333        let mut hash_builder = HashBuilder::default()
1334            .with_updates(true)
1335            .with_proof_retainer(ProofRetainer::from_iter(proof_targets));
1336
1337        let mut prefix_set = PrefixSetMut::default();
1338        prefix_set.extend_keys(state.clone().into_iter().map(|(nibbles, _)| nibbles));
1339        let walker = TrieWalker::new(NoopAccountTrieCursor::default(), prefix_set.freeze())
1340            .with_deletions_retained(true);
1341        let hashed_post_state = HashedPostState::default()
1342            .with_accounts(state.into_iter().map(|(nibbles, account)| {
1343                (nibbles.pack().into_inner().unwrap().into(), Some(account))
1344            }))
1345            .into_sorted();
1346        let mut node_iter = TrieNodeIter::new(
1347            walker,
1348            HashedPostStateAccountCursor::new(
1349                NoopHashedAccountCursor::default(),
1350                hashed_post_state.accounts(),
1351            ),
1352        );
1353
1354        while let Some(node) = node_iter.try_next().unwrap() {
1355            match node {
1356                TrieElement::Branch(branch) => {
1357                    hash_builder.add_branch(branch.key, branch.value, branch.children_are_in_trie);
1358                }
1359                TrieElement::Leaf(key, account) => {
1360                    let account = TrieAccount::from((account, EMPTY_ROOT_HASH));
1361                    account.encode(&mut account_rlp);
1362
1363                    hash_builder.add_leaf(Nibbles::unpack(key), &account_rlp);
1364                    account_rlp.clear();
1365                }
1366            }
1367        }
1368        let root = hash_builder.root();
1369        let proof_nodes = hash_builder.take_proof_nodes();
1370        let branch_node_hash_masks = hash_builder
1371            .updated_branch_nodes
1372            .clone()
1373            .unwrap_or_default()
1374            .iter()
1375            .map(|(path, node)| (path.clone(), node.hash_mask))
1376            .collect();
1377
1378        let mut trie_updates = TrieUpdates::default();
1379        let removed_keys = node_iter.walker.take_removed_keys();
1380        trie_updates.finalize(hash_builder, removed_keys, destroyed_accounts);
1381
1382        (root, trie_updates, proof_nodes, branch_node_hash_masks)
1383    }
1384
1385    /// Assert that the sparse trie nodes and the proof nodes from the hash builder are equal.
1386    fn assert_eq_sparse_trie_proof_nodes(
1387        sparse_trie: &RevealedSparseTrie,
1388        proof_nodes: ProofNodes,
1389    ) {
1390        let proof_nodes = proof_nodes
1391            .into_nodes_sorted()
1392            .into_iter()
1393            .map(|(path, node)| (path, TrieNode::decode(&mut node.as_ref()).unwrap()));
1394
1395        let sparse_nodes = sparse_trie.nodes.iter().sorted_by_key(|(path, _)| *path);
1396
1397        for ((proof_node_path, proof_node), (sparse_node_path, sparse_node)) in
1398            proof_nodes.zip(sparse_nodes)
1399        {
1400            assert_eq!(&proof_node_path, sparse_node_path);
1401
1402            let equals = match (&proof_node, &sparse_node) {
1403                // Both nodes are empty
1404                (TrieNode::EmptyRoot, SparseNode::Empty) => true,
1405                // Both nodes are branches and have the same state mask
1406                (
1407                    TrieNode::Branch(BranchNode { state_mask: proof_state_mask, .. }),
1408                    SparseNode::Branch { state_mask: sparse_state_mask, .. },
1409                ) => proof_state_mask == sparse_state_mask,
1410                // Both nodes are extensions and have the same key
1411                (
1412                    TrieNode::Extension(ExtensionNode { key: proof_key, .. }),
1413                    SparseNode::Extension { key: sparse_key, .. },
1414                ) |
1415                // Both nodes are leaves and have the same key
1416                (
1417                    TrieNode::Leaf(LeafNode { key: proof_key, .. }),
1418                    SparseNode::Leaf { key: sparse_key, .. },
1419                ) => proof_key == sparse_key,
1420                // Empty and hash nodes are specific to the sparse trie, skip them
1421                (_, SparseNode::Empty | SparseNode::Hash(_)) => continue,
1422                _ => false,
1423            };
1424            assert!(equals, "proof node: {:?}, sparse node: {:?}", proof_node, sparse_node);
1425        }
1426    }
1427
1428    #[test]
1429    fn sparse_trie_is_blind() {
1430        assert!(SparseTrie::blind().is_blind());
1431        assert!(!SparseTrie::revealed_empty().is_blind());
1432    }
1433
1434    #[test]
1435    fn sparse_trie_empty_update_one() {
1436        let key = Nibbles::unpack(B256::with_last_byte(42));
1437        let value = || Account::default();
1438        let value_encoded = || {
1439            let mut account_rlp = Vec::new();
1440            TrieAccount::from((value(), EMPTY_ROOT_HASH)).encode(&mut account_rlp);
1441            account_rlp
1442        };
1443
1444        let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _) =
1445            run_hash_builder([(key.clone(), value())], Default::default(), [key.clone()]);
1446
1447        let mut sparse = RevealedSparseTrie::default().with_updates(true);
1448        sparse.update_leaf(key, value_encoded()).unwrap();
1449        let sparse_root = sparse.root();
1450        let sparse_updates = sparse.take_updates();
1451
1452        assert_eq!(sparse_root, hash_builder_root);
1453        assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
1454        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
1455    }
1456
1457    #[test]
1458    fn sparse_trie_empty_update_multiple_lower_nibbles() {
1459        reth_tracing::init_test_tracing();
1460
1461        let paths = (0..=16).map(|b| Nibbles::unpack(B256::with_last_byte(b))).collect::<Vec<_>>();
1462        let value = || Account::default();
1463        let value_encoded = || {
1464            let mut account_rlp = Vec::new();
1465            TrieAccount::from((value(), EMPTY_ROOT_HASH)).encode(&mut account_rlp);
1466            account_rlp
1467        };
1468
1469        let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _) =
1470            run_hash_builder(
1471                paths.iter().cloned().zip(std::iter::repeat_with(value)),
1472                Default::default(),
1473                paths.clone(),
1474            );
1475
1476        let mut sparse = RevealedSparseTrie::default().with_updates(true);
1477        for path in &paths {
1478            sparse.update_leaf(path.clone(), value_encoded()).unwrap();
1479        }
1480        let sparse_root = sparse.root();
1481        let sparse_updates = sparse.take_updates();
1482
1483        assert_eq!(sparse_root, hash_builder_root);
1484        assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
1485        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
1486    }
1487
1488    #[test]
1489    fn sparse_trie_empty_update_multiple_upper_nibbles() {
1490        let paths = (239..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
1491        let value = || Account::default();
1492        let value_encoded = || {
1493            let mut account_rlp = Vec::new();
1494            TrieAccount::from((value(), EMPTY_ROOT_HASH)).encode(&mut account_rlp);
1495            account_rlp
1496        };
1497
1498        let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _) =
1499            run_hash_builder(
1500                paths.iter().cloned().zip(std::iter::repeat_with(value)),
1501                Default::default(),
1502                paths.clone(),
1503            );
1504
1505        let mut sparse = RevealedSparseTrie::default().with_updates(true);
1506        for path in &paths {
1507            sparse.update_leaf(path.clone(), value_encoded()).unwrap();
1508        }
1509        let sparse_root = sparse.root();
1510        let sparse_updates = sparse.take_updates();
1511
1512        assert_eq!(sparse_root, hash_builder_root);
1513        assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
1514        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
1515    }
1516
1517    #[test]
1518    fn sparse_trie_empty_update_multiple() {
1519        let paths = (0..=255)
1520            .map(|b| {
1521                Nibbles::unpack(if b % 2 == 0 {
1522                    B256::repeat_byte(b)
1523                } else {
1524                    B256::with_last_byte(b)
1525                })
1526            })
1527            .collect::<Vec<_>>();
1528        let value = || Account::default();
1529        let value_encoded = || {
1530            let mut account_rlp = Vec::new();
1531            TrieAccount::from((value(), EMPTY_ROOT_HASH)).encode(&mut account_rlp);
1532            account_rlp
1533        };
1534
1535        let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _) =
1536            run_hash_builder(
1537                paths.iter().sorted_unstable().cloned().zip(std::iter::repeat_with(value)),
1538                Default::default(),
1539                paths.clone(),
1540            );
1541
1542        let mut sparse = RevealedSparseTrie::default().with_updates(true);
1543        for path in &paths {
1544            sparse.update_leaf(path.clone(), value_encoded()).unwrap();
1545        }
1546        let sparse_root = sparse.root();
1547        let sparse_updates = sparse.take_updates();
1548
1549        assert_eq!(sparse_root, hash_builder_root);
1550        pretty_assertions::assert_eq!(
1551            BTreeMap::from_iter(sparse_updates.updated_nodes),
1552            BTreeMap::from_iter(hash_builder_updates.account_nodes)
1553        );
1554        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
1555    }
1556
1557    #[test]
1558    fn sparse_trie_empty_update_repeated() {
1559        let paths = (0..=255).map(|b| Nibbles::unpack(B256::repeat_byte(b))).collect::<Vec<_>>();
1560        let old_value = Account { nonce: 1, ..Default::default() };
1561        let old_value_encoded = {
1562            let mut account_rlp = Vec::new();
1563            TrieAccount::from((old_value, EMPTY_ROOT_HASH)).encode(&mut account_rlp);
1564            account_rlp
1565        };
1566        let new_value = Account { nonce: 2, ..Default::default() };
1567        let new_value_encoded = {
1568            let mut account_rlp = Vec::new();
1569            TrieAccount::from((new_value, EMPTY_ROOT_HASH)).encode(&mut account_rlp);
1570            account_rlp
1571        };
1572
1573        let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _) =
1574            run_hash_builder(
1575                paths.iter().cloned().zip(std::iter::repeat_with(|| old_value)),
1576                Default::default(),
1577                paths.clone(),
1578            );
1579
1580        let mut sparse = RevealedSparseTrie::default().with_updates(true);
1581        for path in &paths {
1582            sparse.update_leaf(path.clone(), old_value_encoded.clone()).unwrap();
1583        }
1584        let sparse_root = sparse.root();
1585        let sparse_updates = sparse.updates_ref();
1586
1587        assert_eq!(sparse_root, hash_builder_root);
1588        assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
1589        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
1590
1591        let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _) =
1592            run_hash_builder(
1593                paths.iter().cloned().zip(std::iter::repeat_with(|| new_value)),
1594                Default::default(),
1595                paths.clone(),
1596            );
1597
1598        for path in &paths {
1599            sparse.update_leaf(path.clone(), new_value_encoded.clone()).unwrap();
1600        }
1601        let sparse_root = sparse.root();
1602        let sparse_updates = sparse.take_updates();
1603
1604        assert_eq!(sparse_root, hash_builder_root);
1605        assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
1606        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
1607    }
1608
1609    #[test]
1610    fn sparse_trie_remove_leaf() {
1611        reth_tracing::init_test_tracing();
1612
1613        let mut sparse = RevealedSparseTrie::default();
1614
1615        let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
1616
1617        sparse
1618            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone())
1619            .unwrap();
1620        sparse
1621            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone())
1622            .unwrap();
1623        sparse
1624            .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone())
1625            .unwrap();
1626        sparse
1627            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone())
1628            .unwrap();
1629        sparse
1630            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone())
1631            .unwrap();
1632        sparse.update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value).unwrap();
1633
1634        // Extension (Key = 5)
1635        // └── Branch (Mask = 1011)
1636        //     ├── 0 -> Extension (Key = 23)
1637        //     │        └── Branch (Mask = 0101)
1638        //     │              ├── 1 -> Leaf (Key = 1, Path = 50231)
1639        //     │              └── 3 -> Leaf (Key = 3, Path = 50233)
1640        //     ├── 2 -> Leaf (Key = 013, Path = 52013)
1641        //     └── 3 -> Branch (Mask = 0101)
1642        //                ├── 1 -> Leaf (Key = 3102, Path = 53102)
1643        //                └── 3 -> Branch (Mask = 1010)
1644        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302)
1645        //                       └── 2 -> Leaf (Key = 3320, Path = 53320)
1646        pretty_assertions::assert_eq!(
1647            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
1648            BTreeMap::from_iter([
1649                (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
1650                (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1101.into())),
1651                (
1652                    Nibbles::from_nibbles([0x5, 0x0]),
1653                    SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
1654                ),
1655                (
1656                    Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
1657                    SparseNode::new_branch(0b1010.into())
1658                ),
1659                (
1660                    Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
1661                    SparseNode::new_leaf(Nibbles::default())
1662                ),
1663                (
1664                    Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
1665                    SparseNode::new_leaf(Nibbles::default())
1666                ),
1667                (
1668                    Nibbles::from_nibbles([0x5, 0x2]),
1669                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x1, 0x3]))
1670                ),
1671                (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
1672                (
1673                    Nibbles::from_nibbles([0x5, 0x3, 0x1]),
1674                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
1675                ),
1676                (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
1677                (
1678                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
1679                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
1680                ),
1681                (
1682                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
1683                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
1684                )
1685            ])
1686        );
1687
1688        sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3])).unwrap();
1689
1690        // Extension (Key = 5)
1691        // └── Branch (Mask = 1001)
1692        //     ├── 0 -> Extension (Key = 23)
1693        //     │        └── Branch (Mask = 0101)
1694        //     │              ├── 1 -> Leaf (Key = 0231, Path = 50231)
1695        //     │              └── 3 -> Leaf (Key = 0233, Path = 50233)
1696        //     └── 3 -> Branch (Mask = 0101)
1697        //                ├── 1 -> Leaf (Key = 3102, Path = 53102)
1698        //                └── 3 -> Branch (Mask = 1010)
1699        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302)
1700        //                       └── 2 -> Leaf (Key = 3320, Path = 53320)
1701        pretty_assertions::assert_eq!(
1702            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
1703            BTreeMap::from_iter([
1704                (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
1705                (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
1706                (
1707                    Nibbles::from_nibbles([0x5, 0x0]),
1708                    SparseNode::new_ext(Nibbles::from_nibbles([0x2, 0x3]))
1709                ),
1710                (
1711                    Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3]),
1712                    SparseNode::new_branch(0b1010.into())
1713                ),
1714                (
1715                    Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]),
1716                    SparseNode::new_leaf(Nibbles::default())
1717                ),
1718                (
1719                    Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]),
1720                    SparseNode::new_leaf(Nibbles::default())
1721                ),
1722                (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
1723                (
1724                    Nibbles::from_nibbles([0x5, 0x3, 0x1]),
1725                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
1726                ),
1727                (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
1728                (
1729                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
1730                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
1731                ),
1732                (
1733                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
1734                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
1735                )
1736            ])
1737        );
1738
1739        sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1])).unwrap();
1740
1741        // Extension (Key = 5)
1742        // └── Branch (Mask = 1001)
1743        //     ├── 0 -> Leaf (Key = 0233, Path = 50233)
1744        //     └── 3 -> Branch (Mask = 0101)
1745        //                ├── 1 -> Leaf (Key = 3102, Path = 53102)
1746        //                └── 3 -> Branch (Mask = 1010)
1747        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302)
1748        //                       └── 2 -> Leaf (Key = 3320, Path = 53320)
1749        pretty_assertions::assert_eq!(
1750            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
1751            BTreeMap::from_iter([
1752                (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
1753                (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
1754                (
1755                    Nibbles::from_nibbles([0x5, 0x0]),
1756                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
1757                ),
1758                (Nibbles::from_nibbles([0x5, 0x3]), SparseNode::new_branch(0b1010.into())),
1759                (
1760                    Nibbles::from_nibbles([0x5, 0x3, 0x1]),
1761                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0, 0x2]))
1762                ),
1763                (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
1764                (
1765                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
1766                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
1767                ),
1768                (
1769                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
1770                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
1771                )
1772            ])
1773        );
1774
1775        sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2])).unwrap();
1776
1777        // Extension (Key = 5)
1778        // └── Branch (Mask = 1001)
1779        //     ├── 0 -> Leaf (Key = 0233, Path = 50233)
1780        //     └── 3 -> Branch (Mask = 1010)
1781        //                ├── 0 -> Leaf (Key = 3302, Path = 53302)
1782        //                └── 2 -> Leaf (Key = 3320, Path = 53320)
1783        pretty_assertions::assert_eq!(
1784            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
1785            BTreeMap::from_iter([
1786                (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
1787                (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
1788                (
1789                    Nibbles::from_nibbles([0x5, 0x0]),
1790                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
1791                ),
1792                (
1793                    Nibbles::from_nibbles([0x5, 0x3]),
1794                    SparseNode::new_ext(Nibbles::from_nibbles([0x3]))
1795                ),
1796                (Nibbles::from_nibbles([0x5, 0x3, 0x3]), SparseNode::new_branch(0b0101.into())),
1797                (
1798                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0]),
1799                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2]))
1800                ),
1801                (
1802                    Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2]),
1803                    SparseNode::new_leaf(Nibbles::from_nibbles([0x0]))
1804                )
1805            ])
1806        );
1807
1808        sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0])).unwrap();
1809
1810        // Extension (Key = 5)
1811        // └── Branch (Mask = 1001)
1812        //     ├── 0 -> Leaf (Key = 0233, Path = 50233)
1813        //     └── 3 -> Leaf (Key = 3302, Path = 53302)
1814        pretty_assertions::assert_eq!(
1815            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
1816            BTreeMap::from_iter([
1817                (Nibbles::default(), SparseNode::new_ext(Nibbles::from_nibbles([0x5]))),
1818                (Nibbles::from_nibbles([0x5]), SparseNode::new_branch(0b1001.into())),
1819                (
1820                    Nibbles::from_nibbles([0x5, 0x0]),
1821                    SparseNode::new_leaf(Nibbles::from_nibbles([0x2, 0x3, 0x3]))
1822                ),
1823                (
1824                    Nibbles::from_nibbles([0x5, 0x3]),
1825                    SparseNode::new_leaf(Nibbles::from_nibbles([0x3, 0x0, 0x2]))
1826                ),
1827            ])
1828        );
1829
1830        sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3])).unwrap();
1831
1832        // Leaf (Key = 53302)
1833        pretty_assertions::assert_eq!(
1834            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
1835            BTreeMap::from_iter([(
1836                Nibbles::default(),
1837                SparseNode::new_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]))
1838            ),])
1839        );
1840
1841        sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2])).unwrap();
1842
1843        // Empty
1844        pretty_assertions::assert_eq!(
1845            sparse.nodes.clone().into_iter().collect::<BTreeMap<_, _>>(),
1846            BTreeMap::from_iter([(Nibbles::default(), SparseNode::Empty)])
1847        );
1848    }
1849
1850    #[test]
1851    fn sparse_trie_remove_leaf_blinded() {
1852        let leaf = LeafNode::new(
1853            Nibbles::default(),
1854            alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
1855        );
1856        let branch = TrieNode::Branch(BranchNode::new(
1857            vec![
1858                RlpNode::word_rlp(&B256::repeat_byte(1)),
1859                RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
1860            ],
1861            TrieMask::new(0b11),
1862        ));
1863
1864        let mut sparse =
1865            RevealedSparseTrie::from_root(branch.clone(), Some(TrieMask::new(0b01)), false)
1866                .unwrap();
1867
1868        // Reveal a branch node and one of its children
1869        //
1870        // Branch (Mask = 11)
1871        // ├── 0 -> Hash (Path = 0)
1872        // └── 1 -> Leaf (Path = 1)
1873        sparse.reveal_node(Nibbles::default(), branch, Some(TrieMask::new(0b01))).unwrap();
1874        sparse.reveal_node(Nibbles::from_nibbles([0x1]), TrieNode::Leaf(leaf), None).unwrap();
1875
1876        // Removing a blinded leaf should result in an error
1877        assert_matches!(
1878            sparse.remove_leaf(&Nibbles::from_nibbles([0x0])).map_err(|e| e.into_kind()),
1879            Err(SparseTrieErrorKind::BlindedNode { path, hash }) if path == Nibbles::from_nibbles([0x0]) && hash == B256::repeat_byte(1)
1880        );
1881    }
1882
1883    #[test]
1884    fn sparse_trie_remove_leaf_non_existent() {
1885        let leaf = LeafNode::new(
1886            Nibbles::default(),
1887            alloy_rlp::encode_fixed_size(&U256::from(1)).to_vec(),
1888        );
1889        let branch = TrieNode::Branch(BranchNode::new(
1890            vec![
1891                RlpNode::word_rlp(&B256::repeat_byte(1)),
1892                RlpNode::from_raw_rlp(&alloy_rlp::encode(leaf.clone())).unwrap(),
1893            ],
1894            TrieMask::new(0b11),
1895        ));
1896
1897        let mut sparse =
1898            RevealedSparseTrie::from_root(branch.clone(), Some(TrieMask::new(0b01)), false)
1899                .unwrap();
1900
1901        // Reveal a branch node and one of its children
1902        //
1903        // Branch (Mask = 11)
1904        // ├── 0 -> Hash (Path = 0)
1905        // └── 1 -> Leaf (Path = 1)
1906        sparse.reveal_node(Nibbles::default(), branch, Some(TrieMask::new(0b01))).unwrap();
1907        sparse.reveal_node(Nibbles::from_nibbles([0x1]), TrieNode::Leaf(leaf), None).unwrap();
1908
1909        // Removing a non-existent leaf should be a noop
1910        let sparse_old = sparse.clone();
1911        assert_matches!(sparse.remove_leaf(&Nibbles::from_nibbles([0x2])), Ok(()));
1912        assert_eq!(sparse, sparse_old);
1913    }
1914
1915    #[allow(clippy::type_complexity)]
1916    #[test]
1917    fn sparse_trie_fuzz() {
1918        // Having only the first 3 nibbles set, we narrow down the range of keys
1919        // to 4096 different hashes. It allows us to generate collisions more likely
1920        // to test the sparse trie updates.
1921        const KEY_NIBBLES_LEN: usize = 3;
1922
1923        fn test(updates: Vec<(HashMap<Nibbles, Account>, HashSet<Nibbles>)>) {
1924            {
1925                let mut state = BTreeMap::default();
1926                let mut sparse = RevealedSparseTrie::default().with_updates(true);
1927
1928                for (update, keys_to_delete) in updates {
1929                    // Insert state updates into the sparse trie and calculate the root
1930                    for (key, account) in update.clone() {
1931                        let account = TrieAccount::from((account, EMPTY_ROOT_HASH));
1932                        let mut account_rlp = Vec::new();
1933                        account.encode(&mut account_rlp);
1934                        sparse.update_leaf(key, account_rlp).unwrap();
1935                    }
1936                    // We need to clone the sparse trie, so that all updated branch nodes are
1937                    // preserved, and not only those that were changed after the last call to
1938                    // `root()`.
1939                    let mut updated_sparse = sparse.clone();
1940                    let sparse_root = updated_sparse.root();
1941                    let sparse_updates = updated_sparse.take_updates();
1942
1943                    // Insert state updates into the hash builder and calculate the root
1944                    state.extend(update);
1945                    let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _) =
1946                        run_hash_builder(
1947                            state.clone(),
1948                            Default::default(),
1949                            state.keys().cloned().collect::<Vec<_>>(),
1950                        );
1951
1952                    // Assert that the sparse trie root matches the hash builder root
1953                    assert_eq!(sparse_root, hash_builder_root);
1954                    // Assert that the sparse trie updates match the hash builder updates
1955                    pretty_assertions::assert_eq!(
1956                        sparse_updates.updated_nodes,
1957                        hash_builder_updates.account_nodes
1958                    );
1959                    // Assert that the sparse trie nodes match the hash builder proof nodes
1960                    assert_eq_sparse_trie_proof_nodes(&updated_sparse, hash_builder_proof_nodes);
1961
1962                    // Delete some keys from both the hash builder and the sparse trie and check
1963                    // that the sparse trie root still matches the hash builder root
1964                    for key in keys_to_delete {
1965                        state.remove(&key).unwrap();
1966                        sparse.remove_leaf(&key).unwrap();
1967                    }
1968
1969                    // We need to clone the sparse trie, so that all updated branch nodes are
1970                    // preserved, and not only those that were changed after the last call to
1971                    // `root()`.
1972                    let mut updated_sparse = sparse.clone();
1973                    let sparse_root = updated_sparse.root();
1974                    let sparse_updates = updated_sparse.take_updates();
1975
1976                    let (hash_builder_root, hash_builder_updates, hash_builder_proof_nodes, _) =
1977                        run_hash_builder(
1978                            state.clone(),
1979                            Default::default(),
1980                            state.keys().cloned().collect::<Vec<_>>(),
1981                        );
1982
1983                    // Assert that the sparse trie root matches the hash builder root
1984                    assert_eq!(sparse_root, hash_builder_root);
1985                    // Assert that the sparse trie updates match the hash builder updates
1986                    pretty_assertions::assert_eq!(
1987                        sparse_updates.updated_nodes,
1988                        hash_builder_updates.account_nodes
1989                    );
1990                    // Assert that the sparse trie nodes match the hash builder proof nodes
1991                    assert_eq_sparse_trie_proof_nodes(&updated_sparse, hash_builder_proof_nodes);
1992                }
1993            }
1994        }
1995
1996        fn transform_updates(
1997            updates: Vec<HashMap<Nibbles, Account>>,
1998            mut rng: impl Rng,
1999        ) -> Vec<(HashMap<Nibbles, Account>, HashSet<Nibbles>)> {
2000            let mut keys = HashSet::new();
2001            updates
2002                .into_iter()
2003                .map(|update| {
2004                    keys.extend(update.keys().cloned());
2005
2006                    let keys_to_delete_len = update.len() / 2;
2007                    let keys_to_delete = (0..keys_to_delete_len)
2008                        .map(|_| {
2009                            let key = keys.iter().choose(&mut rng).unwrap().clone();
2010                            keys.take(&key).unwrap()
2011                        })
2012                        .collect();
2013
2014                    (update, keys_to_delete)
2015                })
2016                .collect::<Vec<_>>()
2017        }
2018
2019        proptest!(ProptestConfig::with_cases(10), |(
2020            updates in proptest::collection::vec(
2021                proptest::collection::hash_map(
2022                    any_with::<Nibbles>(SizeRange::new(KEY_NIBBLES_LEN..=KEY_NIBBLES_LEN)).prop_map(pad_nibbles_right),
2023                    arb::<Account>(),
2024                    1..100,
2025                ).prop_map(HashMap::from_iter),
2026                1..100,
2027            ).prop_perturb(transform_updates)
2028        )| {
2029            test(updates)
2030        });
2031    }
2032
2033    /// We have three leaves that share the same prefix: 0x00, 0x01 and 0x02. Hash builder trie has
2034    /// only nodes 0x00 and 0x01, and we have proofs for them. Node B is new and inserted in the
2035    /// sparse trie first.
2036    ///
2037    /// 1. Reveal the hash builder proof to leaf 0x00 in the sparse trie.
2038    /// 2. Insert leaf 0x01 into the sparse trie.
2039    /// 3. Reveal the hash builder proof to leaf 0x02 in the sparse trie.
2040    ///
2041    /// The hash builder proof to the leaf 0x02 didn't have the leaf 0x01 at the corresponding
2042    /// nibble of the branch node, so we need to adjust the branch node instead of fully
2043    /// replacing it.
2044    #[test]
2045    fn sparse_trie_reveal_node_1() {
2046        let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00]));
2047        let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01]));
2048        let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x02]));
2049        let value = || Account::default();
2050        let value_encoded = || {
2051            let mut account_rlp = Vec::new();
2052            TrieAccount::from((value(), EMPTY_ROOT_HASH)).encode(&mut account_rlp);
2053            account_rlp
2054        };
2055
2056        // Generate the proof for the root node and initialize the sparse trie with it
2057        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks) = run_hash_builder(
2058            [(key1(), value()), (key3(), value())],
2059            Default::default(),
2060            [Nibbles::default()],
2061        );
2062        let mut sparse = RevealedSparseTrie::from_root(
2063            TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
2064            branch_node_hash_masks.get(&Nibbles::default()).copied(),
2065            false,
2066        )
2067        .unwrap();
2068
2069        // Generate the proof for the first key and reveal it in the sparse trie
2070        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks) =
2071            run_hash_builder([(key1(), value()), (key3(), value())], Default::default(), [key1()]);
2072        for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
2073            let hash_mask = branch_node_hash_masks.get(&path).copied();
2074            sparse.reveal_node(path, TrieNode::decode(&mut &node[..]).unwrap(), hash_mask).unwrap();
2075        }
2076
2077        // Check that the branch node exists with only two nibbles set
2078        assert_eq!(
2079            sparse.nodes.get(&Nibbles::default()),
2080            Some(&SparseNode::new_branch(0b101.into()))
2081        );
2082
2083        // Insert the leaf for the second key
2084        sparse.update_leaf(key2(), value_encoded()).unwrap();
2085
2086        // Check that the branch node was updated and another nibble was set
2087        assert_eq!(
2088            sparse.nodes.get(&Nibbles::default()),
2089            Some(&SparseNode::new_branch(0b111.into()))
2090        );
2091
2092        // Generate the proof for the third key and reveal it in the sparse trie
2093        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks) =
2094            run_hash_builder([(key1(), value()), (key3(), value())], Default::default(), [key3()]);
2095        for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
2096            let hash_mask = branch_node_hash_masks.get(&path).copied();
2097            sparse.reveal_node(path, TrieNode::decode(&mut &node[..]).unwrap(), hash_mask).unwrap();
2098        }
2099
2100        // Check that nothing changed in the branch node
2101        assert_eq!(
2102            sparse.nodes.get(&Nibbles::default()),
2103            Some(&SparseNode::new_branch(0b111.into()))
2104        );
2105
2106        // Generate the nodes for the full trie with all three key using the hash builder, and
2107        // compare them to the sparse trie
2108        let (_, _, hash_builder_proof_nodes, _) = run_hash_builder(
2109            [(key1(), value()), (key2(), value()), (key3(), value())],
2110            Default::default(),
2111            [key1(), key2(), key3()],
2112        );
2113
2114        assert_eq_sparse_trie_proof_nodes(&sparse, hash_builder_proof_nodes);
2115    }
2116
2117    /// We have three leaves: 0x0000, 0x0101, and 0x0102. Hash builder trie has all nodes, and we
2118    /// have proofs for them.
2119    ///
2120    /// 1. Reveal the hash builder proof to leaf 0x00 in the sparse trie.
2121    /// 2. Remove leaf 0x00 from the sparse trie (that will remove the branch node and create an
2122    ///    extension node with the key 0x0000).
2123    /// 3. Reveal the hash builder proof to leaf 0x0101 in the sparse trie.
2124    ///
2125    /// The hash builder proof to the leaf 0x0101 had a branch node in the path, but we turned it
2126    /// into an extension node, so it should ignore this node.
2127    #[test]
2128    fn sparse_trie_reveal_node_2() {
2129        let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x00]));
2130        let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x01]));
2131        let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x02]));
2132        let value = || Account::default();
2133
2134        // Generate the proof for the root node and initialize the sparse trie with it
2135        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks) = run_hash_builder(
2136            [(key1(), value()), (key2(), value()), (key3(), value())],
2137            Default::default(),
2138            [Nibbles::default()],
2139        );
2140        let mut sparse = RevealedSparseTrie::from_root(
2141            TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
2142            branch_node_hash_masks.get(&Nibbles::default()).copied(),
2143            false,
2144        )
2145        .unwrap();
2146
2147        // Generate the proof for the children of the root branch node and reveal it in the sparse
2148        // trie
2149        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks) = run_hash_builder(
2150            [(key1(), value()), (key2(), value()), (key3(), value())],
2151            Default::default(),
2152            [key1(), Nibbles::from_nibbles_unchecked([0x01])],
2153        );
2154        for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
2155            let hash_mask = branch_node_hash_masks.get(&path).copied();
2156            sparse.reveal_node(path, TrieNode::decode(&mut &node[..]).unwrap(), hash_mask).unwrap();
2157        }
2158
2159        // Check that the branch node exists
2160        assert_eq!(
2161            sparse.nodes.get(&Nibbles::default()),
2162            Some(&SparseNode::new_branch(0b11.into()))
2163        );
2164
2165        // Remove the leaf for the first key
2166        sparse.remove_leaf(&key1()).unwrap();
2167
2168        // Check that the branch node was turned into an extension node
2169        assert_eq!(
2170            sparse.nodes.get(&Nibbles::default()),
2171            Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
2172        );
2173
2174        // Generate the proof for the third key and reveal it in the sparse trie
2175        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks) = run_hash_builder(
2176            [(key1(), value()), (key2(), value()), (key3(), value())],
2177            Default::default(),
2178            [key2()],
2179        );
2180        for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
2181            let hash_mask = branch_node_hash_masks.get(&path).copied();
2182            sparse.reveal_node(path, TrieNode::decode(&mut &node[..]).unwrap(), hash_mask).unwrap();
2183        }
2184
2185        // Check that nothing changed in the extension node
2186        assert_eq!(
2187            sparse.nodes.get(&Nibbles::default()),
2188            Some(&SparseNode::new_ext(Nibbles::from_nibbles_unchecked([0x01])))
2189        );
2190    }
2191
2192    /// We have two leaves that share the same prefix: 0x0001 and 0x0002, and a leaf with a
2193    /// different prefix: 0x0100. Hash builder trie has only the first two leaves, and we have
2194    /// proofs for them.
2195    ///
2196    /// 1. Insert the leaf 0x0100 into the sparse trie, and check that the root extensino node was
2197    ///    turned into a branch node.
2198    /// 2. Reveal the leaf 0x0001 in the sparse trie, and check that the root branch node wasn't
2199    ///    overwritten with the extension node from the proof.
2200    #[test]
2201    fn sparse_trie_reveal_node_3() {
2202        let key1 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x01]));
2203        let key2 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x00, 0x02]));
2204        let key3 = || pad_nibbles_right(Nibbles::from_nibbles_unchecked([0x01, 0x00]));
2205        let value = || Account::default();
2206        let value_encoded = || {
2207            let mut account_rlp = Vec::new();
2208            TrieAccount::from((value(), EMPTY_ROOT_HASH)).encode(&mut account_rlp);
2209            account_rlp
2210        };
2211
2212        // Generate the proof for the root node and initialize the sparse trie with it
2213        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks) = run_hash_builder(
2214            [(key1(), value()), (key2(), value())],
2215            Default::default(),
2216            [Nibbles::default()],
2217        );
2218        let mut sparse = RevealedSparseTrie::from_root(
2219            TrieNode::decode(&mut &hash_builder_proof_nodes.nodes_sorted()[0].1[..]).unwrap(),
2220            branch_node_hash_masks.get(&Nibbles::default()).copied(),
2221            false,
2222        )
2223        .unwrap();
2224
2225        // Check that the root extension node exists
2226        assert_matches!(
2227            sparse.nodes.get(&Nibbles::default()),
2228            Some(SparseNode::Extension { key, hash: None }) if *key == Nibbles::from_nibbles([0x00])
2229        );
2230
2231        // Insert the leaf with a different prefix
2232        sparse.update_leaf(key3(), value_encoded()).unwrap();
2233
2234        // Check that the extension node was turned into a branch node
2235        assert_matches!(
2236            sparse.nodes.get(&Nibbles::default()),
2237            Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
2238        );
2239
2240        // Generate the proof for the first key and reveal it in the sparse trie
2241        let (_, _, hash_builder_proof_nodes, branch_node_hash_masks) =
2242            run_hash_builder([(key1(), value()), (key2(), value())], Default::default(), [key1()]);
2243        for (path, node) in hash_builder_proof_nodes.nodes_sorted() {
2244            let hash_mask = branch_node_hash_masks.get(&path).copied();
2245            sparse.reveal_node(path, TrieNode::decode(&mut &node[..]).unwrap(), hash_mask).unwrap();
2246        }
2247
2248        // Check that the branch node wasn't overwritten by the extension node in the proof
2249        assert_matches!(
2250            sparse.nodes.get(&Nibbles::default()),
2251            Some(SparseNode::Branch { state_mask, hash: None, store_in_db_trie: None }) if *state_mask == TrieMask::new(0b11)
2252        );
2253    }
2254
2255    #[test]
2256    fn sparse_trie_get_changed_nodes_at_depth() {
2257        let mut sparse = RevealedSparseTrie::default();
2258
2259        let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
2260
2261        // Extension (Key = 5) – Level 0
2262        // └── Branch (Mask = 1011) – Level 1
2263        //     ├── 0 -> Extension (Key = 23) – Level 2
2264        //     │        └── Branch (Mask = 0101) – Level 3
2265        //     │              ├── 1 -> Leaf (Key = 1, Path = 50231) – Level 4
2266        //     │              └── 3 -> Leaf (Key = 3, Path = 50233) – Level 4
2267        //     ├── 2 -> Leaf (Key = 013, Path = 52013) – Level 2
2268        //     └── 3 -> Branch (Mask = 0101) – Level 2
2269        //                ├── 1 -> Leaf (Key = 3102, Path = 53102) – Level 3
2270        //                └── 3 -> Branch (Mask = 1010) – Level 3
2271        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302) – Level 4
2272        //                       └── 2 -> Leaf (Key = 3320, Path = 53320) – Level 4
2273        sparse
2274            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone())
2275            .unwrap();
2276        sparse
2277            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone())
2278            .unwrap();
2279        sparse
2280            .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone())
2281            .unwrap();
2282        sparse
2283            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone())
2284            .unwrap();
2285        sparse
2286            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone())
2287            .unwrap();
2288        sparse.update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value).unwrap();
2289
2290        assert_eq!(
2291            sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 0),
2292            vec![Nibbles::default()]
2293        );
2294        assert_eq!(
2295            sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 1),
2296            vec![Nibbles::from_nibbles_unchecked([0x5])]
2297        );
2298        assert_eq!(
2299            sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 2),
2300            vec![
2301                Nibbles::from_nibbles_unchecked([0x5, 0x0]),
2302                Nibbles::from_nibbles_unchecked([0x5, 0x2]),
2303                Nibbles::from_nibbles_unchecked([0x5, 0x3])
2304            ]
2305        );
2306        assert_eq!(
2307            sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 3),
2308            vec![
2309                Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3]),
2310                Nibbles::from_nibbles_unchecked([0x5, 0x2]),
2311                Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x1]),
2312                Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3])
2313            ]
2314        );
2315        assert_eq!(
2316            sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 4),
2317            vec![
2318                Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3, 0x1]),
2319                Nibbles::from_nibbles_unchecked([0x5, 0x0, 0x2, 0x3, 0x3]),
2320                Nibbles::from_nibbles_unchecked([0x5, 0x2]),
2321                Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x1]),
2322                Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3, 0x0]),
2323                Nibbles::from_nibbles_unchecked([0x5, 0x3, 0x3, 0x2])
2324            ]
2325        );
2326    }
2327
2328    #[test]
2329    fn hash_builder_branch_hash_mask() {
2330        let key1 = || pad_nibbles_left(Nibbles::from_nibbles_unchecked([0x00]));
2331        let key2 = || pad_nibbles_left(Nibbles::from_nibbles_unchecked([0x01]));
2332        let value = || Account { bytecode_hash: Some(B256::repeat_byte(1)), ..Default::default() };
2333        let value_encoded = || {
2334            let mut account_rlp = Vec::new();
2335            TrieAccount::from((value(), EMPTY_ROOT_HASH)).encode(&mut account_rlp);
2336            account_rlp
2337        };
2338
2339        let (hash_builder_root, hash_builder_updates, _, _) = run_hash_builder(
2340            [(key1(), value()), (key2(), value())],
2341            Default::default(),
2342            [Nibbles::default()],
2343        );
2344        let mut sparse = RevealedSparseTrie::default();
2345        sparse.update_leaf(key1(), value_encoded()).unwrap();
2346        sparse.update_leaf(key2(), value_encoded()).unwrap();
2347        let sparse_root = sparse.root();
2348        let sparse_updates = sparse.take_updates();
2349
2350        assert_eq!(sparse_root, hash_builder_root);
2351        assert_eq!(sparse_updates.updated_nodes, hash_builder_updates.account_nodes);
2352    }
2353
2354    #[test]
2355    fn sparse_trie_wipe() {
2356        let mut sparse = RevealedSparseTrie::default().with_updates(true);
2357
2358        let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
2359
2360        // Extension (Key = 5) – Level 0
2361        // └── Branch (Mask = 1011) – Level 1
2362        //     ├── 0 -> Extension (Key = 23) – Level 2
2363        //     │        └── Branch (Mask = 0101) – Level 3
2364        //     │              ├── 1 -> Leaf (Key = 1, Path = 50231) – Level 4
2365        //     │              └── 3 -> Leaf (Key = 3, Path = 50233) – Level 4
2366        //     ├── 2 -> Leaf (Key = 013, Path = 52013) – Level 2
2367        //     └── 3 -> Branch (Mask = 0101) – Level 2
2368        //                ├── 1 -> Leaf (Key = 3102, Path = 53102) – Level 3
2369        //                └── 3 -> Branch (Mask = 1010) – Level 3
2370        //                       ├── 0 -> Leaf (Key = 3302, Path = 53302) – Level 4
2371        //                       └── 2 -> Leaf (Key = 3320, Path = 53320) – Level 4
2372        sparse
2373            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone())
2374            .unwrap();
2375        sparse
2376            .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone())
2377            .unwrap();
2378        sparse
2379            .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone())
2380            .unwrap();
2381        sparse
2382            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone())
2383            .unwrap();
2384        sparse
2385            .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone())
2386            .unwrap();
2387        sparse.update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value).unwrap();
2388
2389        sparse.wipe();
2390
2391        assert_eq!(sparse.root(), EMPTY_ROOT_HASH);
2392    }
2393}