Skip to main content

reth_chain_state/
preserved_sparse_trie.rs

1//! Preserved sparse trie for reuse across payload validations.
2
3use alloy_primitives::B256;
4use reth_trie_sparse::SparseStateTrie;
5use tracing::debug;
6
7/// Type alias for the sparse trie type used in preservation.
8pub type SparseTrie = SparseStateTrie;
9
10/// Guard that holds the lock on the preserved trie.
11/// While held, the next trie take will block. Call `store()` to save the trie before dropping.
12#[derive(Debug)]
13pub struct PreservedTrieGuard<'a>(parking_lot::MutexGuard<'a, Option<PreservedSparseTrie>>);
14
15impl<'a> PreservedTrieGuard<'a> {
16    /// Creates a new guard from the preserved trie lock.
17    pub(crate) const fn new(
18        guard: parking_lot::MutexGuard<'a, Option<PreservedSparseTrie>>,
19    ) -> Self {
20        PreservedTrieGuard(guard)
21    }
22
23    /// Stores a preserved trie for later reuse.
24    pub fn store(&mut self, trie: PreservedSparseTrie) {
25        self.0.replace(trie);
26    }
27}
28
29/// A preserved sparse trie that can be reused across payload validations.
30///
31/// The trie exists in one of two states:
32/// - **Anchored**: Has a computed state root and can be reused for payloads whose parent state root
33///   matches the anchor.
34/// - **Cleared**: Trie data has been cleared but allocations are preserved for reuse.
35#[derive(Debug)]
36pub enum PreservedSparseTrie {
37    /// Trie with a computed state root that can be reused for continuation payloads.
38    Anchored {
39        /// The sparse state trie anchored to the computed state root.
40        trie: SparseTrie,
41        /// The state root this trie represents (computed from the previous block).
42        /// Used to verify continuity: new payload's `parent_state_root` must match this.
43        state_root: B256,
44    },
45    /// Cleared trie with preserved allocations, ready for fresh use.
46    Cleared {
47        /// The sparse state trie with cleared data but preserved allocations.
48        trie: SparseTrie,
49    },
50}
51
52impl PreservedSparseTrie {
53    /// Creates a new anchored preserved trie.
54    ///
55    /// The `state_root` is the computed state root from the trie, which becomes the
56    /// anchor for determining if subsequent payloads can reuse this trie.
57    pub const fn anchored(trie: SparseTrie, state_root: B256) -> Self {
58        Self::Anchored { trie, state_root }
59    }
60
61    /// Creates a cleared preserved trie (allocations preserved, data cleared).
62    pub const fn cleared(trie: SparseTrie) -> Self {
63        Self::Cleared { trie }
64    }
65
66    /// Consumes self and returns the trie for reuse.
67    ///
68    /// If the preserved trie is anchored and the parent state root matches, the preserved
69    /// trie structure is reused directly. Otherwise, the trie is cleared but allocations
70    /// are preserved to reduce memory overhead.
71    pub fn into_trie_for(self, parent_state_root: B256) -> SparseTrie {
72        match self {
73            Self::Anchored { trie, state_root } if state_root == parent_state_root => {
74                debug!(
75                    target: "engine::tree::payload_processor",
76                    %state_root,
77                    "Reusing anchored sparse trie for continuation payload"
78                );
79                trie
80            }
81            Self::Anchored { mut trie, state_root } => {
82                debug!(
83                    target: "engine::tree::payload_processor",
84                    anchor_root = %state_root,
85                    %parent_state_root,
86                    "Clearing anchored sparse trie - parent state root mismatch"
87                );
88                trie.clear();
89                trie
90            }
91            Self::Cleared { trie } => {
92                debug!(
93                    target: "engine::tree::payload_processor",
94                    %parent_state_root,
95                    "Using cleared sparse trie with preserved allocations"
96                );
97                trie
98            }
99        }
100    }
101}