1use alloy_primitives::{
4 B256, U256, keccak256,
5 map::{AddressMap, B256Map, HashSet, U256Map},
6};
7use alloy_rlp::Encodable;
8use alloy_trie::{
9 EMPTY_ROOT_HASH, HashBuilder, Nibbles, TrieMask,
10 nodes::{BranchNodeRef, ExtensionNodeRef, LeafNodeRef, RlpNode},
11};
12use revm::{
13 database::{AccountState, DbAccount},
14 state::{Account, AccountInfo},
15};
16use std::{array, mem};
17
18#[derive(Debug, Default)]
25pub struct StateRootCache {
26 trie: Option<IncrementalStateTrie>,
27 dirty: AddressMap<DirtyAccount>,
28 rlp_buf: Vec<u8>,
30}
31
32#[derive(Debug, Default)]
33struct DirtyAccount {
34 storage: HashSet<U256>,
35 reset_storage: bool,
36}
37
38impl StateRootCache {
39 pub fn record_changes(&mut self, changes: &AddressMap<Account>) {
41 for (address, account) in changes {
42 if !account.is_touched() {
43 continue;
44 }
45
46 let dirty = self.dirty.entry(*address).or_default();
47 dirty.reset_storage |= account.is_created() || account.is_selfdestructed();
48 dirty.storage.extend(account.changed_storage_slots().map(|(slot, _)| *slot));
49 }
50 }
51
52 pub fn record_account(&mut self, address: alloy_primitives::Address) {
54 self.dirty.entry(address).or_default();
55 }
56
57 pub fn record_storage(&mut self, address: alloy_primitives::Address, slot: U256) {
59 self.dirty.entry(address).or_default().storage.insert(slot);
60 }
61
62 pub fn invalidate(&mut self) {
64 self.trie = None;
65 self.dirty.clear();
66 }
67
68 pub fn root(&mut self, accounts: &AddressMap<DbAccount>) -> B256 {
70 let Self { trie, dirty, rlp_buf } = self;
71 if trie.is_none() {
72 *trie = Some(IncrementalStateTrie::from_accounts(accounts, rlp_buf));
73 dirty.clear();
74 return trie.as_mut().unwrap().root(rlp_buf);
75 }
76
77 let trie = trie.as_mut().unwrap();
78 for (address, dirty) in mem::take(dirty) {
79 let hashed_address = keccak256(address);
80 let Some(account) = accounts
81 .get(&address)
82 .filter(|account| account.account_state != AccountState::NotExisting)
83 else {
84 trie.accounts.remove(hashed_address);
85 trie.storage.remove(&hashed_address);
86 continue;
87 };
88
89 let storage_trie = if dirty.reset_storage {
90 trie.storage
91 .entry(hashed_address)
92 .insert_entry(IncrementalTrie::from_storage(&account.storage))
93 .into_mut()
94 } else {
95 let storage_trie = trie.storage.entry(hashed_address).or_default();
96 for slot in dirty.storage {
97 let key = keccak256(slot.to_be_bytes::<32>());
98 if let Some(value) = account.storage.get(&slot).filter(|value| !value.is_zero())
99 {
100 storage_trie.insert(key, alloy_rlp::encode(value));
101 } else {
102 storage_trie.remove(key);
103 }
104 }
105 storage_trie
106 };
107 let storage_root = storage_trie.root_with_buf(rlp_buf);
108 trie.accounts.insert(
109 hashed_address,
110 trie_account_rlp_with_storage_root(&account.info, storage_root),
111 );
112 }
113
114 trie.root(rlp_buf)
115 }
116}
117
118#[derive(Debug, Default)]
119struct IncrementalStateTrie {
120 accounts: IncrementalTrie,
121 storage: B256Map<IncrementalTrie>,
122}
123
124impl IncrementalStateTrie {
125 fn from_accounts(accounts: &AddressMap<DbAccount>, rlp_buf: &mut Vec<u8>) -> Self {
126 let mut trie = Self::default();
127 for (address, account) in accounts {
128 if account.account_state == AccountState::NotExisting {
129 continue;
130 }
131 let hashed_address = keccak256(address);
132 let mut storage_trie = IncrementalTrie::from_storage(&account.storage);
133 let storage_root = storage_trie.root_with_buf(rlp_buf);
134 trie.accounts.insert(
135 hashed_address,
136 trie_account_rlp_with_storage_root(&account.info, storage_root),
137 );
138 trie.storage.insert(hashed_address, storage_trie);
139 }
140 trie
141 }
142
143 fn root(&mut self, rlp_buf: &mut Vec<u8>) -> B256 {
144 self.accounts.root_with_buf(rlp_buf)
145 }
146}
147
148#[derive(Debug, Default)]
150struct IncrementalTrie {
151 root: TrieNode,
152}
153
154impl IncrementalTrie {
155 fn from_storage(storage: &U256Map<U256>) -> Self {
156 let mut trie = Self::default();
157 for (slot, value) in storage.iter().filter(|(_, value)| !value.is_zero()) {
158 trie.insert(keccak256(slot.to_be_bytes::<32>()), alloy_rlp::encode(value));
159 }
160 trie
161 }
162
163 fn insert(&mut self, key: B256, value: Vec<u8>) {
164 self.root.insert(Nibbles::unpack(key), value);
165 }
166
167 fn remove(&mut self, key: B256) {
168 self.root.remove(Nibbles::unpack(key));
169 }
170
171 #[cfg(test)]
172 fn root(&mut self) -> B256 {
173 self.root_with_buf(&mut Vec::new())
174 }
175
176 fn root_with_buf(&mut self, rlp_buf: &mut Vec<u8>) -> B256 {
177 let Some(root) = self.root.rlp(rlp_buf) else { return EMPTY_ROOT_HASH };
178 root.as_hash().unwrap_or_else(|| keccak256(root.as_ref()))
179 }
180}
181
182#[derive(Debug, Default)]
183struct TrieNode {
184 kind: TrieNodeKind,
185 rlp: Option<RlpNode>,
186}
187
188#[derive(Debug, Default)]
189enum TrieNodeKind {
190 #[default]
191 Empty,
192 Leaf {
193 path: Nibbles,
194 value: Vec<u8>,
195 },
196 Extension {
197 path: Nibbles,
198 child: Box<TrieNode>,
199 },
200 Branch {
201 children: [Option<Box<TrieNode>>; 16],
202 },
203}
204
205impl TrieNode {
206 const fn leaf(path: Nibbles, value: Vec<u8>) -> Self {
207 Self { kind: TrieNodeKind::Leaf { path, value }, rlp: None }
208 }
209
210 fn extension(path: Nibbles, child: Self) -> Self {
211 debug_assert!(!path.is_empty());
212 Self { kind: TrieNodeKind::Extension { path, child: Box::new(child) }, rlp: None }
213 }
214
215 const fn branch(children: [Option<Box<Self>>; 16]) -> Self {
216 Self { kind: TrieNodeKind::Branch { children }, rlp: None }
217 }
218
219 fn empty_children() -> [Option<Box<Self>>; 16] {
220 Default::default()
221 }
222
223 fn insert(&mut self, key: Nibbles, value: Vec<u8>) {
224 let kind = mem::take(&mut self.kind);
225 self.rlp = None;
226 *self = match kind {
227 TrieNodeKind::Empty => Self::leaf(key, value),
228 TrieNodeKind::Leaf { path, value: old_value } => {
229 let common = path.common_prefix_length(&key);
230 if common == path.len() {
231 debug_assert_eq!(common, key.len());
232 Self::leaf(path, value)
233 } else {
234 let mut children = Self::empty_children();
235 let old_index = path.get(common).unwrap() as usize;
236 let new_index = key.get(common).unwrap() as usize;
237 children[old_index] =
238 Some(Box::new(Self::leaf(path.slice(common + 1..), old_value)));
239 children[new_index] =
240 Some(Box::new(Self::leaf(key.slice(common + 1..), value)));
241 let branch = Self::branch(children);
242 if common == 0 { branch } else { Self::extension(path.slice(..common), branch) }
243 }
244 }
245 TrieNodeKind::Extension { path, mut child } => {
246 let common = path.common_prefix_length(&key);
247 if common == path.len() {
248 child.insert(key.slice(common..), value);
249 Self::extension(path, *child)
250 } else {
251 let mut children = Self::empty_children();
252 let old_index = path.get(common).unwrap() as usize;
253 let old_path = path.slice(common + 1..);
254 let old_child = if old_path.is_empty() {
255 *child
256 } else {
257 Self::extension(old_path, *child)
258 };
259 children[old_index] = Some(Box::new(old_child));
260
261 let new_index = key.get(common).unwrap() as usize;
262 children[new_index] =
263 Some(Box::new(Self::leaf(key.slice(common + 1..), value)));
264 let branch = Self::branch(children);
265 if common == 0 { branch } else { Self::extension(path.slice(..common), branch) }
266 }
267 }
268 TrieNodeKind::Branch { mut children } => {
269 let index = key.first().expect("trie keys have equal lengths") as usize;
270 children[index]
271 .get_or_insert_with(|| Box::new(Self::default()))
272 .insert(key.slice(1..), value);
273 Self::branch(children)
274 }
275 };
276 }
277
278 fn remove(&mut self, key: Nibbles) {
279 let kind = mem::take(&mut self.kind);
280 self.rlp = None;
281 *self = match kind {
282 TrieNodeKind::Empty => Self::default(),
283 TrieNodeKind::Leaf { path, value } => {
284 if path == key {
285 Self::default()
286 } else {
287 Self::leaf(path, value)
288 }
289 }
290 TrieNodeKind::Extension { path, mut child } => {
291 if key.starts_with(&path) {
292 child.remove(key.slice(path.len()..));
293 Self::normalize_extension(path, *child)
294 } else {
295 Self::extension(path, *child)
296 }
297 }
298 TrieNodeKind::Branch { mut children } => {
299 let index = key.first().expect("trie keys have equal lengths") as usize;
300 if let Some(child) = &mut children[index] {
301 child.remove(key.slice(1..));
302 if matches!(child.kind, TrieNodeKind::Empty) {
303 children[index] = None;
304 }
305 }
306 Self::normalize_branch(children)
307 }
308 };
309 }
310
311 fn normalize_extension(path: Nibbles, child: Self) -> Self {
312 match child.kind {
313 TrieNodeKind::Empty => Self::default(),
314 TrieNodeKind::Leaf { path: child_path, value } => {
315 Self::leaf(path.join(&child_path), value)
316 }
317 TrieNodeKind::Extension { path: child_path, child } => {
318 Self::extension(path.join(&child_path), *child)
319 }
320 TrieNodeKind::Branch { children } => Self::extension(path, Self::branch(children)),
321 }
322 }
323
324 fn normalize_branch(mut children: [Option<Box<Self>>; 16]) -> Self {
325 let mut indexes =
326 children.iter().enumerate().filter_map(|(index, child)| child.as_ref().map(|_| index));
327 let Some(index) = indexes.next() else { return Self::default() };
328 if indexes.next().is_some() {
329 return Self::branch(children);
330 }
331
332 let child = *children[index].take().unwrap();
333 let prefix = Nibbles::from_nibbles([index as u8]);
334 match child.kind {
335 TrieNodeKind::Empty => unreachable!("empty branch children are removed"),
336 TrieNodeKind::Leaf { path, value } => Self::leaf(prefix.join(&path), value),
337 TrieNodeKind::Extension { path, child } => Self::extension(prefix.join(&path), *child),
338 TrieNodeKind::Branch { children } => Self::extension(prefix, Self::branch(children)),
339 }
340 }
341
342 fn rlp(&mut self, out: &mut Vec<u8>) -> Option<RlpNode> {
343 if let Some(rlp) = &self.rlp {
344 return Some(rlp.clone());
345 }
346
347 let rlp = match &mut self.kind {
348 TrieNodeKind::Empty => return None,
349 TrieNodeKind::Leaf { path, value } => {
350 out.clear();
351 LeafNodeRef::new(path, value).rlp(out)
352 }
353 TrieNodeKind::Extension { path, child } => {
354 let child = child.rlp(out).expect("extension nodes have a child");
355 out.clear();
356 ExtensionNodeRef::new(path, child.as_ref()).rlp(out)
357 }
358 TrieNodeKind::Branch { children } => {
359 let mut stack: [RlpNode; 16] = array::from_fn(|_| RlpNode::default());
360 let mut stack_len = 0;
361 let mut state_mask = TrieMask::default();
362 for (index, child) in children.iter_mut().enumerate() {
363 if let Some(child) = child {
364 stack[stack_len] = child.rlp(out).expect("branch children are not empty");
365 stack_len += 1;
366 state_mask.set_bit(index as u8);
367 }
368 }
369 out.clear();
370 BranchNodeRef::new(&stack[..stack_len], state_mask).rlp(out)
371 }
372 };
373 self.rlp = Some(rlp.clone());
374 Some(rlp)
375 }
376}
377
378pub fn build_root(values: impl IntoIterator<Item = (Nibbles, Vec<u8>)>) -> B256 {
379 let mut builder = HashBuilder::default();
380 for (key, value) in values {
381 builder.add_leaf(key, value.as_ref());
382 }
383 builder.root()
384}
385
386pub fn state_root(accounts: &AddressMap<DbAccount>) -> B256 {
388 build_root(trie_accounts(accounts))
389}
390
391pub fn storage_root(storage: &U256Map<U256>) -> B256 {
393 build_root(trie_storage(storage))
394}
395
396pub fn trie_storage(storage: &U256Map<U256>) -> Vec<(Nibbles, Vec<u8>)> {
398 let mut storage = storage
399 .iter()
400 .filter(|(_, value)| !value.is_zero())
401 .map(|(key, value)| {
402 let data = alloy_rlp::encode(value);
403 (Nibbles::unpack(keccak256(key.to_be_bytes::<32>())), data)
404 })
405 .collect::<Vec<_>>();
406 storage.sort_by_key(|(key, _)| *key);
407
408 storage
409}
410
411pub fn trie_accounts(accounts: &AddressMap<DbAccount>) -> Vec<(Nibbles, Vec<u8>)> {
413 let mut accounts: Vec<(Nibbles, Vec<u8>)> = accounts
414 .iter()
415 .filter(|(_, account)| account.account_state != AccountState::NotExisting)
416 .map(|(address, account)| {
417 let data = trie_account_rlp(&account.info, &account.storage);
418 (Nibbles::unpack(keccak256(*address)), data)
419 })
420 .collect();
421 accounts.sort_by_key(|(key, _)| *key);
422
423 accounts
424}
425
426pub fn trie_account_rlp(info: &AccountInfo, storage: &U256Map<U256>) -> Vec<u8> {
428 trie_account_rlp_with_storage_root(info, storage_root(storage))
429}
430
431fn trie_account_rlp_with_storage_root(info: &AccountInfo, storage_root: B256) -> Vec<u8> {
433 let mut out: Vec<u8> = Vec::new();
434 let list: [&dyn Encodable; 4] = [&info.nonce, &info.balance, &storage_root, &info.code_hash];
435
436 alloy_rlp::encode_list::<_, dyn Encodable>(&list, &mut out);
437
438 out
439}
440
441#[cfg(test)]
442mod tests {
443 use super::*;
444
445 #[test]
446 fn canonical_roots_omit_zero_storage_and_non_existing_accounts() {
447 let mut storage = U256Map::default();
448 storage.insert(U256::from(1), U256::ZERO);
449 assert_eq!(storage_root(&storage), EMPTY_ROOT_HASH);
450
451 let mut accounts = AddressMap::default();
452 accounts.insert(
453 alloy_primitives::Address::with_last_byte(1),
454 DbAccount { account_state: AccountState::NotExisting, ..Default::default() },
455 );
456 assert_eq!(state_root(&accounts), EMPTY_ROOT_HASH);
457 assert_eq!(StateRootCache::default().root(&accounts), EMPTY_ROOT_HASH);
458 }
459
460 fn rebuilt_root(values: &B256Map<Vec<u8>>) -> B256 {
461 let mut leaves = values
462 .iter()
463 .map(|(key, value)| (Nibbles::unpack(*key), value.clone()))
464 .collect::<Vec<_>>();
465 leaves.sort_by_key(|(key, _)| *key);
466 build_root(leaves)
467 }
468
469 #[test]
470 fn incremental_trie_matches_full_rebuild() {
471 let mut trie = IncrementalTrie::default();
472 let mut values = B256Map::default();
473 assert_eq!(trie.root(), EMPTY_ROOT_HASH);
474
475 for index in 0..128 {
476 let key = keccak256(U256::from(index).to_be_bytes::<32>());
477 let value = alloy_rlp::encode(U256::from(index + 1));
478 trie.insert(key, value.clone());
479 values.insert(key, value);
480 assert_eq!(trie.root(), rebuilt_root(&values));
481 }
482
483 for index in (0..128).step_by(3) {
484 let key = keccak256(U256::from(index).to_be_bytes::<32>());
485 let value = alloy_rlp::encode(U256::from(index + 1_000));
486 trie.insert(key, value.clone());
487 values.insert(key, value);
488 assert_eq!(trie.root(), rebuilt_root(&values));
489 }
490
491 for index in (0..128).rev() {
492 let key = keccak256(U256::from(index).to_be_bytes::<32>());
493 trie.remove(key);
494 values.remove(&key);
495 assert_eq!(trie.root(), rebuilt_root(&values));
496 }
497 }
498}