Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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, 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