alloy_trie/proof/added_removed_keys.rs
1use crate::{Nibbles, TrieMask};
2use alloy_primitives::{B256, map::B256Set};
3
4/// Provides added and removed keys for an account or storage trie.
5///
6/// Used by the [`crate::proof::ProofRetainer`] to determine which nodes may be ancestors of newly
7/// added or removed leaves. This information allows for generation of more complete proofs which
8/// include the nodes necessary for adding and removing leaves from the trie.
9#[derive(Debug, Default, Clone)]
10pub struct AddedRemovedKeys {
11 /// Keys which are known to be removed from the trie.
12 removed_keys: B256Set,
13 /// Keys which are known to be added to the trie.
14 added_keys: B256Set,
15 /// Assume that all keys have been added.
16 assume_added: bool,
17}
18
19impl AsRef<Self> for AddedRemovedKeys {
20 fn as_ref(&self) -> &Self {
21 self
22 }
23}
24
25impl AddedRemovedKeys {
26 /// Sets the `assume_added` flag, which can be used instead of `insert_added` if exact
27 /// additions aren't known and you want to optimistically collect all proofs which _might_ be
28 /// necessary.
29 pub fn with_assume_added(mut self, assume_added: bool) -> Self {
30 self.assume_added = assume_added;
31 self
32 }
33
34 /// Sets the key as being a removed key. This removes the key from the `added_keys` set if it
35 /// was previously inserted into it.
36 pub fn insert_removed(&mut self, key: B256) {
37 self.added_keys.remove(&key);
38 self.removed_keys.insert(key);
39 }
40
41 /// Unsets the key as being a removed key.
42 pub fn remove_removed(&mut self, key: &B256) {
43 self.removed_keys.remove(key);
44 }
45
46 /// Sets the key as being an added key. This removes the key from the `removed_keys` set if it
47 /// was previously inserted into it.
48 pub fn insert_added(&mut self, key: B256) {
49 self.removed_keys.remove(&key);
50 self.added_keys.insert(key);
51 }
52
53 /// Clears all keys which have been added via `insert_added`.
54 pub fn clear_added(&mut self) {
55 self.added_keys.clear();
56 }
57
58 /// Returns true if the given key path is marked as removed.
59 pub fn is_removed(&self, path: &B256) -> bool {
60 self.removed_keys.contains(path)
61 }
62
63 /// Returns true if the given key path is marked as added.
64 pub fn is_added(&self, path: &B256) -> bool {
65 self.assume_added || self.added_keys.contains(path)
66 }
67
68 /// Returns true if the given path prefix is the prefix of an added key.
69 pub fn is_prefix_added(&self, prefix: &Nibbles) -> bool {
70 self.assume_added
71 || self.added_keys.iter().any(|key| {
72 let key_nibbles = Nibbles::unpack(key);
73 key_nibbles.starts_with(prefix)
74 })
75 }
76
77 /// Returns a mask containing a bit set for each child of the branch which is a prefix of a
78 /// removed leaf.
79 pub fn get_removed_mask(&self, branch_path: &Nibbles) -> TrieMask {
80 let mut mask = TrieMask::default();
81 for key in &self.removed_keys {
82 let key_nibbles = Nibbles::unpack(key);
83 if key_nibbles.starts_with(branch_path) {
84 let child_bit = key_nibbles.get_unchecked(branch_path.len());
85 mask.set_bit(child_bit);
86 }
87 }
88 mask
89 }
90}