1use crate::{
2 hashed_cursor::{HashedCursor, HashedCursorFactory, HashedStorageCursor},
3 node_iter::{TrieElement, TrieNodeIter},
4 prefix_set::{PrefixSet, TriePrefixSets},
5 progress::{
6 IntermediateRootState, IntermediateStateRootState, IntermediateStorageRootState,
7 StateRootProgress, StorageRootProgress,
8 },
9 stats::TrieTracker,
10 trie_cursor::{TrieCursor, TrieCursorFactory, TrieCursorIter, TrieStorageCursor},
11 updates::{StorageTrieUpdates, TrieUpdates},
12 walker::TrieWalker,
13 HashBuilder, Nibbles, TRIE_ACCOUNT_RLP_MAX_SIZE,
14};
15use alloy_consensus::EMPTY_ROOT_HASH;
16use alloy_primitives::{keccak256, map::B256Map, Address, B256, U256};
17use alloy_rlp::{BufMut, Encodable};
18use alloy_trie::proof::AddedRemovedKeys;
19use reth_execution_errors::{StateRootError, StorageRootError};
20use reth_primitives_traits::Account;
21use tracing::{debug, instrument, trace, Span};
22
23pub(crate) const DEFAULT_INTERMEDIATE_THRESHOLD: u64 = 100_000;
26
27#[cfg(feature = "metrics")]
28use crate::metrics::{StateRootMetrics, TrieRootMetrics};
29
30#[derive(Debug)]
32pub struct StateRoot<T, H> {
33 pub trie_cursor_factory: T,
35 pub hashed_cursor_factory: H,
37 pub prefix_sets: TriePrefixSets,
39 walk_all_changed_branch_children: bool,
41 previous_state: Option<IntermediateStateRootState>,
43 threshold: u64,
45 #[cfg(feature = "metrics")]
46 metrics: StateRootMetrics,
48}
49
50impl<T, H> StateRoot<T, H> {
51 pub fn new(trie_cursor_factory: T, hashed_cursor_factory: H) -> Self {
57 Self {
58 trie_cursor_factory,
59 hashed_cursor_factory,
60 prefix_sets: TriePrefixSets::default(),
61 walk_all_changed_branch_children: false,
62 previous_state: None,
63 threshold: DEFAULT_INTERMEDIATE_THRESHOLD,
64 #[cfg(feature = "metrics")]
65 metrics: StateRootMetrics::default(),
66 }
67 }
68
69 pub fn with_prefix_sets(mut self, prefix_sets: TriePrefixSets) -> Self {
71 self.prefix_sets = prefix_sets;
72 self
73 }
74
75 pub const fn with_walk_all_changed_branch_children(mut self, enabled: bool) -> Self {
80 self.walk_all_changed_branch_children = enabled;
81 self
82 }
83
84 pub const fn with_threshold(mut self, threshold: u64) -> Self {
86 self.threshold = threshold;
87 self
88 }
89
90 pub const fn with_no_threshold(mut self) -> Self {
92 self.threshold = u64::MAX;
93 self
94 }
95
96 pub fn with_intermediate_state(mut self, state: Option<IntermediateStateRootState>) -> Self {
98 self.previous_state = state;
99 self
100 }
101
102 pub fn with_hashed_cursor_factory<HF>(self, hashed_cursor_factory: HF) -> StateRoot<T, HF> {
104 StateRoot {
105 trie_cursor_factory: self.trie_cursor_factory,
106 hashed_cursor_factory,
107 prefix_sets: self.prefix_sets,
108 walk_all_changed_branch_children: self.walk_all_changed_branch_children,
109 threshold: self.threshold,
110 previous_state: self.previous_state,
111 #[cfg(feature = "metrics")]
112 metrics: self.metrics,
113 }
114 }
115
116 pub fn with_trie_cursor_factory<TF>(self, trie_cursor_factory: TF) -> StateRoot<TF, H> {
118 StateRoot {
119 trie_cursor_factory,
120 hashed_cursor_factory: self.hashed_cursor_factory,
121 prefix_sets: self.prefix_sets,
122 walk_all_changed_branch_children: self.walk_all_changed_branch_children,
123 threshold: self.threshold,
124 previous_state: self.previous_state,
125 #[cfg(feature = "metrics")]
126 metrics: self.metrics,
127 }
128 }
129}
130
131impl<T, H> StateRoot<T, H>
132where
133 T: TrieCursorFactory,
134 H: HashedCursorFactory,
135{
136 pub fn root_with_updates(self) -> Result<(B256, TrieUpdates), StateRootError> {
145 match self.with_no_threshold().calculate(true)? {
146 StateRootProgress::Complete(root, _, updates) => Ok((root, updates)),
147 StateRootProgress::Progress(..) => unreachable!(), }
149 }
150
151 pub fn root(self) -> Result<B256, StateRootError> {
158 match self.calculate(false)? {
159 StateRootProgress::Complete(root, _, _) => Ok(root),
160 StateRootProgress::Progress(..) => unreachable!(), }
162 }
163
164 pub fn root_with_progress(self) -> Result<StateRootProgress, StateRootError> {
171 self.calculate(true)
172 }
173
174 fn calculate(self, retain_updates: bool) -> Result<StateRootProgress, StateRootError> {
175 trace!(target: "trie::state_root", "calculating state root");
176 let mut tracker = TrieTracker::default();
177
178 let trie_cursor = self.trie_cursor_factory.account_trie_cursor()?;
179 let hashed_account_cursor = self.hashed_cursor_factory.hashed_account_cursor()?;
180
181 let mut hashed_storage_cursor: Option<H::StorageCursor<'_>> = None;
184 let mut storage_trie_cursor: Option<T::StorageTrieCursor<'_>> = None;
185
186 let mut storage_ctx = StateRootContext::new();
188
189 let (mut hash_builder, mut account_node_iter) = if let Some(state) = self.previous_state {
191 let IntermediateStateRootState { account_root_state, storage_root_state } = state;
192
193 let mut hash_builder = account_root_state.hash_builder.with_updates(retain_updates);
195 let walker = TrieWalker::<_>::state_trie_from_stack(
196 trie_cursor,
197 account_root_state.walker_stack,
198 self.prefix_sets.account_prefix_set,
199 )
200 .with_walk_all_changed_branch_children(self.walk_all_changed_branch_children)
201 .with_deletions_retained(retain_updates);
202 let account_node_iter = TrieNodeIter::state_trie(walker, hashed_account_cursor)
203 .with_last_hashed_key(account_root_state.last_hashed_key);
204
205 if let Some(storage_state) = storage_root_state {
207 let hashed_address = account_root_state.last_hashed_key;
208 let account = storage_state.account;
209
210 debug!(
211 target: "trie::state_root",
212 account_nonce = account.nonce,
213 account_balance = ?account.balance,
214 last_hashed_key = ?account_root_state.last_hashed_key,
215 "Resuming storage root calculation"
216 );
217
218 let remaining_threshold = self.threshold.saturating_sub(
219 storage_ctx.total_updates_len(&account_node_iter, &hash_builder),
220 );
221
222 if hashed_storage_cursor.is_none() {
223 hashed_storage_cursor =
224 Some(self.hashed_cursor_factory.hashed_storage_cursor(hashed_address)?);
225 }
226 if storage_trie_cursor.is_none() {
227 storage_trie_cursor =
228 Some(self.trie_cursor_factory.storage_trie_cursor(hashed_address)?);
229 }
230
231 let storage_result = StorageRootCalculation {
232 hashed_address,
233 prefix_set: self
234 .prefix_sets
235 .storage_prefix_sets
236 .get(&hashed_address)
237 .cloned()
238 .unwrap_or_default(),
239 previous_state: Some(storage_state.state),
240 walk_all_changed_branch_children: self.walk_all_changed_branch_children,
241 threshold: remaining_threshold,
242 retain_updates,
243 }
244 .calculate(
245 storage_trie_cursor.as_mut().expect("storage trie cursor is initialized"),
246 hashed_storage_cursor.as_mut().expect("hashed storage cursor is initialized"),
247 #[cfg(feature = "metrics")]
248 &self.metrics.storage_trie,
249 )?;
250 if let Some(storage_state) = storage_ctx.process_storage_root_result(
251 storage_result,
252 hashed_address,
253 account,
254 &mut hash_builder,
255 retain_updates,
256 )? {
257 return Ok(storage_ctx.create_progress_state(
259 account_node_iter,
260 hash_builder,
261 account_root_state.last_hashed_key,
262 Some(storage_state),
263 ))
264 }
265 }
266
267 (hash_builder, account_node_iter)
268 } else {
269 let hash_builder = HashBuilder::default().with_updates(retain_updates);
272 let walker = TrieWalker::state_trie(trie_cursor, self.prefix_sets.account_prefix_set)?
273 .with_walk_all_changed_branch_children(self.walk_all_changed_branch_children)
274 .with_deletions_retained(retain_updates);
275 let node_iter = TrieNodeIter::state_trie(walker, hashed_account_cursor);
276 (hash_builder, node_iter)
277 };
278
279 while let Some(node) = account_node_iter.try_next()? {
280 match node {
281 TrieElement::Branch(node) => {
282 tracker.inc_branch();
283 hash_builder.add_branch(node.key, node.value, node.children_are_in_trie);
284 }
285 TrieElement::Leaf(hashed_address, account) => {
286 tracker.inc_leaf();
287 storage_ctx.hashed_entries_walked += 1;
288
289 let remaining_threshold = self.threshold.saturating_sub(
292 storage_ctx.total_updates_len(&account_node_iter, &hash_builder),
293 );
294
295 if hashed_storage_cursor.is_none() {
296 hashed_storage_cursor =
297 Some(self.hashed_cursor_factory.hashed_storage_cursor(hashed_address)?);
298 }
299 if storage_trie_cursor.is_none() {
300 storage_trie_cursor =
301 Some(self.trie_cursor_factory.storage_trie_cursor(hashed_address)?);
302 }
303
304 let storage_result = StorageRootCalculation {
305 hashed_address,
306 prefix_set: self
307 .prefix_sets
308 .storage_prefix_sets
309 .get(&hashed_address)
310 .cloned()
311 .unwrap_or_default(),
312 previous_state: None,
313 walk_all_changed_branch_children: self.walk_all_changed_branch_children,
314 threshold: remaining_threshold,
315 retain_updates,
316 }
317 .calculate(
318 storage_trie_cursor.as_mut().expect("storage trie cursor is initialized"),
319 hashed_storage_cursor
320 .as_mut()
321 .expect("hashed storage cursor is initialized"),
322 #[cfg(feature = "metrics")]
323 &self.metrics.storage_trie,
324 )?;
325 if let Some(storage_state) = storage_ctx.process_storage_root_result(
326 storage_result,
327 hashed_address,
328 account,
329 &mut hash_builder,
330 retain_updates,
331 )? {
332 return Ok(storage_ctx.create_progress_state(
334 account_node_iter,
335 hash_builder,
336 hashed_address,
337 Some(storage_state),
338 ))
339 }
340
341 let total_updates_len =
343 storage_ctx.total_updates_len(&account_node_iter, &hash_builder);
344 if retain_updates && total_updates_len >= self.threshold {
345 return Ok(storage_ctx.create_progress_state(
346 account_node_iter,
347 hash_builder,
348 hashed_address,
349 None,
350 ))
351 }
352 }
353 }
354 }
355
356 let root = hash_builder.root();
357
358 let mut destroyed_storage_trie_nodes = B256Map::default();
359 if retain_updates && !self.prefix_sets.destroyed_accounts.is_empty() {
360 let mut storage_trie_cursor = match storage_trie_cursor {
361 Some(cursor) => cursor,
362 None => self.trie_cursor_factory.storage_trie_cursor(B256::ZERO)?,
363 };
364
365 for hashed_address in &self.prefix_sets.destroyed_accounts {
366 storage_trie_cursor.set_hashed_address(*hashed_address);
367 let nodes = TrieCursorIter::new(&mut storage_trie_cursor)
368 .map(|node| node.map(|(path, _)| path))
369 .collect::<Result<Vec<_>, _>>()?;
370
371 if !nodes.is_empty() {
372 destroyed_storage_trie_nodes.insert(*hashed_address, nodes);
373 }
374 }
375 }
376
377 let removed_keys = account_node_iter.walker.take_removed_keys();
378 let StateRootContext { mut trie_updates, hashed_entries_walked, .. } = storage_ctx;
379 trie_updates.finalize(hash_builder, removed_keys, destroyed_storage_trie_nodes);
380
381 let stats = tracker.finish();
382
383 #[cfg(feature = "metrics")]
384 self.metrics.state_trie.record(stats);
385
386 trace!(
387 target: "trie::state_root",
388 %root,
389 duration = ?stats.duration(),
390 branches_added = stats.branches_added(),
391 leaves_added = stats.leaves_added(),
392 "calculated state root"
393 );
394
395 Ok(StateRootProgress::Complete(root, hashed_entries_walked, trie_updates))
396 }
397}
398
399#[derive(Debug)]
401pub(crate) struct StateRootContext {
402 account_rlp: Vec<u8>,
404 trie_updates: TrieUpdates,
406 hashed_entries_walked: usize,
408 updated_storage_nodes: usize,
410}
411
412impl StateRootContext {
413 fn new() -> Self {
415 Self {
416 account_rlp: Vec::with_capacity(TRIE_ACCOUNT_RLP_MAX_SIZE),
417 trie_updates: TrieUpdates::default(),
418 hashed_entries_walked: 0,
419 updated_storage_nodes: 0,
420 }
421 }
422
423 fn create_progress_state<C, H, K>(
426 mut self,
427 account_node_iter: TrieNodeIter<C, H, K>,
428 hash_builder: HashBuilder,
429 last_hashed_key: B256,
430 storage_state: Option<IntermediateStorageRootState>,
431 ) -> StateRootProgress
432 where
433 C: TrieCursor,
434 H: HashedCursor,
435 K: AsRef<AddedRemovedKeys>,
436 {
437 let (walker_stack, walker_deleted_keys) = account_node_iter.walker.split();
438 self.trie_updates.removed_nodes.extend(walker_deleted_keys);
439 let (hash_builder, hash_builder_updates) = hash_builder.split();
440 self.trie_updates.account_nodes.extend(hash_builder_updates);
441
442 let account_state = IntermediateRootState { hash_builder, walker_stack, last_hashed_key };
443
444 let state = IntermediateStateRootState {
445 account_root_state: account_state,
446 storage_root_state: storage_state,
447 };
448
449 StateRootProgress::Progress(Box::new(state), self.hashed_entries_walked, self.trie_updates)
450 }
451
452 fn total_updates_len<C, H, K>(
454 &self,
455 account_node_iter: &TrieNodeIter<C, H, K>,
456 hash_builder: &HashBuilder,
457 ) -> u64
458 where
459 C: TrieCursor,
460 H: HashedCursor,
461 K: AsRef<AddedRemovedKeys>,
462 {
463 (self.updated_storage_nodes +
464 account_node_iter.walker.removed_keys_len() +
465 hash_builder.updates_len()) as u64
466 }
467
468 fn process_storage_root_result(
478 &mut self,
479 storage_result: StorageRootProgress,
480 hashed_address: B256,
481 account: Account,
482 hash_builder: &mut HashBuilder,
483 retain_updates: bool,
484 ) -> Result<Option<IntermediateStorageRootState>, StateRootError> {
485 match storage_result {
486 StorageRootProgress::Complete(storage_root, storage_slots_walked, updates) => {
487 self.hashed_entries_walked += storage_slots_walked;
489 if retain_updates {
490 self.updated_storage_nodes += updates.len();
491 self.trie_updates.insert_storage_updates(hashed_address, updates);
492 }
493
494 self.account_rlp.clear();
496 let trie_account = account.into_trie_account(storage_root);
497 trie_account.encode(&mut self.account_rlp as &mut dyn BufMut);
498 hash_builder.add_leaf(Nibbles::unpack(hashed_address), &self.account_rlp);
499 Ok(None)
500 }
501 StorageRootProgress::Progress(state, storage_slots_walked, updates) => {
502 debug!(
504 target: "trie::state_root",
505 ?hashed_address,
506 storage_slots_walked,
507 last_storage_key = ?state.last_hashed_key,
508 ?account,
509 "Pausing storage root calculation"
510 );
511
512 self.hashed_entries_walked += storage_slots_walked;
513 if retain_updates {
514 self.trie_updates.insert_storage_updates(hashed_address, updates);
515 }
516
517 Ok(Some(IntermediateStorageRootState { state: *state, account }))
518 }
519 }
520 }
521}
522
523#[derive(Debug)]
525pub struct StorageRoot<T, H> {
526 pub trie_cursor_factory: T,
528 pub hashed_cursor_factory: H,
530 pub hashed_address: B256,
532 pub prefix_set: PrefixSet,
534 walk_all_changed_branch_children: bool,
536 previous_state: Option<IntermediateRootState>,
538 threshold: u64,
540 #[cfg(feature = "metrics")]
542 metrics: TrieRootMetrics,
543}
544
545impl<T, H> StorageRoot<T, H> {
546 pub fn new(
548 trie_cursor_factory: T,
549 hashed_cursor_factory: H,
550 address: Address,
551 prefix_set: PrefixSet,
552 #[cfg(feature = "metrics")] metrics: TrieRootMetrics,
553 ) -> Self {
554 Self::new_hashed(
555 trie_cursor_factory,
556 hashed_cursor_factory,
557 keccak256(address),
558 prefix_set,
559 #[cfg(feature = "metrics")]
560 metrics,
561 )
562 }
563
564 pub const fn new_hashed(
566 trie_cursor_factory: T,
567 hashed_cursor_factory: H,
568 hashed_address: B256,
569 prefix_set: PrefixSet,
570 #[cfg(feature = "metrics")] metrics: TrieRootMetrics,
571 ) -> Self {
572 Self {
573 trie_cursor_factory,
574 hashed_cursor_factory,
575 hashed_address,
576 prefix_set,
577 walk_all_changed_branch_children: false,
578 previous_state: None,
579 threshold: DEFAULT_INTERMEDIATE_THRESHOLD,
580 #[cfg(feature = "metrics")]
581 metrics,
582 }
583 }
584
585 pub fn with_prefix_set(mut self, prefix_set: PrefixSet) -> Self {
587 self.prefix_set = prefix_set;
588 self
589 }
590
591 pub const fn with_walk_all_changed_branch_children(mut self, enabled: bool) -> Self {
596 self.walk_all_changed_branch_children = enabled;
597 self
598 }
599
600 pub const fn with_threshold(mut self, threshold: u64) -> Self {
602 self.threshold = threshold;
603 self
604 }
605
606 pub const fn with_no_threshold(mut self) -> Self {
608 self.threshold = u64::MAX;
609 self
610 }
611
612 pub fn with_intermediate_state(mut self, state: Option<IntermediateRootState>) -> Self {
614 self.previous_state = state;
615 self
616 }
617
618 pub fn with_hashed_cursor_factory<HF>(self, hashed_cursor_factory: HF) -> StorageRoot<T, HF> {
620 StorageRoot {
621 trie_cursor_factory: self.trie_cursor_factory,
622 hashed_cursor_factory,
623 hashed_address: self.hashed_address,
624 prefix_set: self.prefix_set,
625 walk_all_changed_branch_children: self.walk_all_changed_branch_children,
626 previous_state: self.previous_state,
627 threshold: self.threshold,
628 #[cfg(feature = "metrics")]
629 metrics: self.metrics,
630 }
631 }
632
633 pub fn with_trie_cursor_factory<TF>(self, trie_cursor_factory: TF) -> StorageRoot<TF, H> {
635 StorageRoot {
636 trie_cursor_factory,
637 hashed_cursor_factory: self.hashed_cursor_factory,
638 hashed_address: self.hashed_address,
639 prefix_set: self.prefix_set,
640 walk_all_changed_branch_children: self.walk_all_changed_branch_children,
641 previous_state: self.previous_state,
642 threshold: self.threshold,
643 #[cfg(feature = "metrics")]
644 metrics: self.metrics,
645 }
646 }
647}
648
649impl<T, H> StorageRoot<T, H>
650where
651 T: TrieCursorFactory,
652 H: HashedCursorFactory,
653{
654 pub fn root_with_progress(self) -> Result<StorageRootProgress, StorageRootError> {
661 self.calculate(true)
662 }
663
664 pub fn root_with_updates(self) -> Result<(B256, usize, StorageTrieUpdates), StorageRootError> {
670 match self.with_no_threshold().calculate(true)? {
671 StorageRootProgress::Complete(root, walked, updates) => Ok((root, walked, updates)),
672 StorageRootProgress::Progress(..) => unreachable!(), }
674 }
675
676 pub fn root(self) -> Result<B256, StorageRootError> {
682 match self.calculate(false)? {
683 StorageRootProgress::Complete(root, _, _) => Ok(root),
684 StorageRootProgress::Progress(..) => unreachable!(), }
686 }
687
688 #[instrument(skip_all, level = "trace", target = "trie::storage_root", name = "storage_trie", fields(addr = %self.hashed_address, storage_root))]
695 pub fn calculate(self, retain_updates: bool) -> Result<StorageRootProgress, StorageRootError> {
696 trace!(target: "trie::storage_root", "calculating storage root");
697
698 let Self {
699 trie_cursor_factory,
700 hashed_cursor_factory,
701 hashed_address,
702 prefix_set,
703 walk_all_changed_branch_children,
704 previous_state,
705 threshold,
706 #[cfg(feature = "metrics")]
707 metrics,
708 } = self;
709
710 let mut hashed_storage_cursor =
711 hashed_cursor_factory.hashed_storage_cursor(hashed_address)?;
712 let mut storage_trie_cursor = trie_cursor_factory.storage_trie_cursor(hashed_address)?;
713
714 StorageRootCalculation {
715 hashed_address,
716 prefix_set,
717 previous_state,
718 walk_all_changed_branch_children,
719 threshold,
720 retain_updates,
721 }
722 .calculate(
723 &mut storage_trie_cursor,
724 &mut hashed_storage_cursor,
725 #[cfg(feature = "metrics")]
726 &metrics,
727 )
728 }
729
730 #[instrument(skip_all, level = "trace", target = "trie::storage_root", name = "storage_trie_with_cursor", fields(addr = %self.hashed_address, storage_root))]
736 pub fn calculate_with_cursor(
737 self,
738 hashed_storage_cursor: &mut H::StorageCursor<'_>,
739 retain_updates: bool,
740 ) -> Result<StorageRootProgress, StorageRootError> {
741 trace!(target: "trie::storage_root", "calculating storage root with cursor");
742
743 let Self {
744 trie_cursor_factory,
745 hashed_address,
746 prefix_set,
747 walk_all_changed_branch_children,
748 previous_state,
749 threshold,
750 #[cfg(feature = "metrics")]
751 metrics,
752 ..
753 } = self;
754
755 let mut storage_trie_cursor = trie_cursor_factory.storage_trie_cursor(hashed_address)?;
756
757 StorageRootCalculation {
758 hashed_address,
759 prefix_set,
760 previous_state,
761 walk_all_changed_branch_children,
762 threshold,
763 retain_updates,
764 }
765 .calculate(
766 &mut storage_trie_cursor,
767 hashed_storage_cursor,
768 #[cfg(feature = "metrics")]
769 &metrics,
770 )
771 }
772}
773
774pub(crate) struct StorageRootCalculation {
776 pub(crate) hashed_address: B256,
777 pub(crate) prefix_set: PrefixSet,
778 pub(crate) previous_state: Option<IntermediateRootState>,
779 pub(crate) walk_all_changed_branch_children: bool,
780 pub(crate) threshold: u64,
781 pub(crate) retain_updates: bool,
782}
783
784impl StorageRootCalculation {
785 pub(crate) fn calculate<TC, HC>(
788 self,
789 trie_cursor: &mut TC,
790 hashed_storage_cursor: &mut HC,
791 #[cfg(feature = "metrics")] metrics: &TrieRootMetrics,
792 ) -> Result<StorageRootProgress, StorageRootError>
793 where
794 TC: TrieStorageCursor,
795 HC: HashedStorageCursor<Value = U256>,
796 {
797 let Self {
798 hashed_address,
799 prefix_set,
800 previous_state,
801 walk_all_changed_branch_children,
802 threshold,
803 retain_updates,
804 } = self;
805 hashed_storage_cursor.set_hashed_address(hashed_address);
806
807 if previous_state.is_none() &&
809 (!retain_updates || prefix_set.is_empty()) &&
810 hashed_storage_cursor.is_storage_empty()?
811 {
812 Span::current().record("storage_root", tracing::field::debug(EMPTY_ROOT_HASH));
813 return Ok(StorageRootProgress::Complete(
814 EMPTY_ROOT_HASH,
815 0,
816 StorageTrieUpdates::default(),
817 ))
818 }
819
820 trie_cursor.set_hashed_address(hashed_address);
821
822 let mut tracker = TrieTracker::default();
823 let mut trie_updates = StorageTrieUpdates::default();
824
825 let (mut hash_builder, mut storage_node_iter) = match previous_state {
826 Some(state) => {
827 let hash_builder = state.hash_builder.with_updates(retain_updates);
828 let walker = TrieWalker::<_>::storage_trie_from_stack(
829 trie_cursor,
830 state.walker_stack,
831 prefix_set,
832 )
833 .with_walk_all_changed_branch_children(walk_all_changed_branch_children)
834 .with_deletions_retained(retain_updates);
835 let node_iter = TrieNodeIter::storage_trie(walker, hashed_storage_cursor)
836 .with_last_hashed_key(state.last_hashed_key);
837 (hash_builder, node_iter)
838 }
839 None => {
840 let hash_builder = HashBuilder::default().with_updates(retain_updates);
841 let walker = TrieWalker::storage_trie(trie_cursor, prefix_set)?
842 .with_walk_all_changed_branch_children(walk_all_changed_branch_children)
843 .with_deletions_retained(retain_updates);
844 let node_iter = TrieNodeIter::storage_trie(walker, hashed_storage_cursor);
845 (hash_builder, node_iter)
846 }
847 };
848
849 let mut hashed_entries_walked = 0;
850 while let Some(node) = storage_node_iter.try_next()? {
851 match node {
852 TrieElement::Branch(node) => {
853 tracker.inc_branch();
854 hash_builder.add_branch(node.key, node.value, node.children_are_in_trie);
855 }
856 TrieElement::Leaf(hashed_slot, value) => {
857 tracker.inc_leaf();
858 hashed_entries_walked += 1;
859 hash_builder.add_leaf(
860 Nibbles::unpack(hashed_slot),
861 alloy_rlp::encode_fixed_size(&value).as_ref(),
862 );
863
864 let total_updates_len =
866 storage_node_iter.walker.removed_keys_len() + hash_builder.updates_len();
867 if retain_updates && total_updates_len as u64 >= threshold {
868 let (walker_stack, walker_deleted_keys) = storage_node_iter.walker.split();
869 trie_updates.removed_nodes.extend(walker_deleted_keys);
870 let (hash_builder, hash_builder_updates) = hash_builder.split();
871 trie_updates.storage_nodes.extend(hash_builder_updates);
872
873 let state = IntermediateRootState {
874 hash_builder,
875 walker_stack,
876 last_hashed_key: hashed_slot,
877 };
878
879 return Ok(StorageRootProgress::Progress(
880 Box::new(state),
881 hashed_entries_walked,
882 trie_updates,
883 ))
884 }
885 }
886 }
887 }
888
889 let root = hash_builder.root();
890 Span::current().record("storage_root", tracing::field::debug(root));
891
892 let removed_keys = storage_node_iter.walker.take_removed_keys();
893 trie_updates.finalize(hash_builder, removed_keys);
894
895 let stats = tracker.finish();
896
897 #[cfg(feature = "metrics")]
898 metrics.record(stats);
899
900 trace!(
901 target: "trie::storage_root",
902 %root,
903 %hashed_address,
904 duration = ?stats.duration(),
905 branches_added = stats.branches_added(),
906 leaves_added = stats.leaves_added(),
907 "calculated storage root"
908 );
909
910 let storage_slots_walked = stats.leaves_added() as usize;
911 Ok(StorageRootProgress::Complete(root, storage_slots_walked, trie_updates))
912 }
913}
914
915#[derive(Clone, Copy, Debug)]
917pub enum TrieType {
918 State,
920 Storage,
922 Custom(&'static str),
924}
925
926impl TrieType {
927 #[cfg(feature = "metrics")]
928 pub(crate) const fn as_str(&self) -> &'static str {
929 match self {
930 Self::State => "state",
931 Self::Storage => "storage",
932 Self::Custom(s) => s,
933 }
934 }
935}