Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions crates/trie/common/src/prefix_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ impl PrefixSetMut {
self.keys.is_empty()
}

/// Clears the inner vec for reuse, setting `all` to `false`.
pub fn clear(&mut self) {
self.all = false;
self.keys.clear();
}

/// Returns a `PrefixSet` with the same elements as this set.
///
/// If not yet sorted, the elements will be sorted and deduplicated.
Expand Down
54 changes: 54 additions & 0 deletions crates/trie/sparse/src/trie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,22 @@ pub enum LeafLookup {
}

impl<P: BlindedProvider> RevealedSparseTrie<P> {
/// This clears all data structures in the sparse trie, keeping the backing data structures
/// allocated.
///
/// This is useful for reusing the trie without needing to reallocate memory.
pub fn clear(&mut self) {
self.nodes.clear();
self.branch_node_tree_masks.clear();
self.branch_node_hash_masks.clear();
self.values.clear();
self.prefix_set.clear();
if let Some(updates) = self.updates.as_mut() {
updates.clear()
}
self.rlp_buf.clear();
}

/// Attempts to find a leaf node at the specified path.
///
/// This method traverses the trie from the root down to the given path, checking
Expand Down Expand Up @@ -2019,6 +2035,15 @@ impl SparseTrieUpdates {
pub fn wiped() -> Self {
Self { wiped: true, ..Default::default() }
}

/// Clears the updates for use later, but keeps the backing data structures allocated.
///
/// Sets `wiped` to `false`.
pub fn clear(&mut self) {
self.updated_nodes.clear();
self.removed_nodes.clear();
self.wiped = false;
}
}

#[cfg(test)]
Expand Down Expand Up @@ -3616,6 +3641,35 @@ mod tests {
assert_eq!(sparse.root(), EMPTY_ROOT_HASH);
}

#[test]
fn sparse_trie_clear() {
// tests that if we fill a sparse trie with some nodes and then clear it, it has the same
// contents as an empty sparse trie
let mut sparse = RevealedSparseTrie::default();
let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec();
sparse
.update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone())
.unwrap();
sparse
.update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone())
.unwrap();
sparse
.update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone())
.unwrap();
sparse.update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value).unwrap();

sparse.clear();

// we have to update the root hash to be an empty one, because the `Default` impl of
// `RevealedSparseTrie` sets the root hash to `EMPTY_ROOT_HASH` in the constructor.
//
// The default impl is only used in tests.
sparse.nodes.insert(Nibbles::default(), SparseNode::Empty);

let empty_trie = RevealedSparseTrie::default();
assert_eq!(empty_trie, sparse);
}

#[test]
fn sparse_trie_display() {
let mut sparse = RevealedSparseTrie::default();
Expand Down
Loading