reth_storage_api/trie.rs
1use alloc::{boxed::Box, vec::Vec};
2use alloy_primitives::{Address, Bytes, B256, U256};
3use reth_primitives_traits::Account;
4use reth_storage_errors::provider::ProviderResult;
5use reth_trie_common::{
6 updates::{StorageTrieUpdatesSorted, TrieUpdates, TrieUpdatesSorted},
7 AccountProof, DecodedMultiProofV2, ExecutionWitnessMode, HashedPostState, HashedStorage,
8 MultiProof, MultiProofTargets, MultiProofTargetsV2, StorageMultiProof, StorageProof, TrieInput,
9};
10
11/// A type that can compute the state root of a given post state.
12#[auto_impl::auto_impl(&, Box, Arc)]
13pub trait StateRootProvider {
14 /// Returns the state root of the execution state on top of the current state.
15 ///
16 /// # Note
17 ///
18 /// It is recommended to provide a different implementation from
19 /// `state_root_with_updates` since it affects the memory usage during state root
20 /// computation.
21 fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult<B256>;
22
23 /// Returns the state root of the `HashedPostState` on top of the current state but reuses the
24 /// intermediate nodes to speed up the computation. It's up to the caller to construct the
25 /// prefix sets and inform the provider of the trie paths that have changes.
26 fn state_root_from_nodes(&self, input: TrieInput) -> ProviderResult<B256>;
27
28 /// Returns the state root of the `HashedPostState` on top of the current state with trie
29 /// updates to be committed to the database.
30 fn state_root_with_updates(
31 &self,
32 hashed_state: HashedPostState,
33 ) -> ProviderResult<(B256, TrieUpdates)>;
34
35 /// Returns state root and trie updates.
36 /// See [`StateRootProvider::state_root_from_nodes`] for more info.
37 fn state_root_from_nodes_with_updates(
38 &self,
39 input: TrieInput,
40 ) -> ProviderResult<(B256, TrieUpdates)>;
41}
42
43/// A type that can compute the storage root for a given account.
44#[auto_impl::auto_impl(&, Box, Arc)]
45pub trait StorageRootProvider {
46 /// Returns the storage root of the `HashedStorage` for target address on top of the current
47 /// state.
48 fn storage_root(&self, address: Address, hashed_storage: HashedStorage)
49 -> ProviderResult<B256>;
50
51 /// Returns the storage proof of the `HashedStorage` for target slot on top of the current
52 /// state.
53 fn storage_proof(
54 &self,
55 address: Address,
56 slot: B256,
57 hashed_storage: HashedStorage,
58 ) -> ProviderResult<StorageProof>;
59
60 /// Returns the storage multiproof for target slots.
61 fn storage_multiproof(
62 &self,
63 address: Address,
64 slots: &[B256],
65 hashed_storage: HashedStorage,
66 ) -> ProviderResult<StorageMultiProof>;
67}
68
69/// A type that can iterate over consecutive hashed accounts and storage slots, and generate
70/// boundary proofs for them, for serving `snap/2` (EIP-8189) `GetAccountRange`/`GetStorageRanges`
71/// requests. Hash-native throughout, unlike [`StorageRootProvider`].
72#[auto_impl::auto_impl(&, Box, Arc)]
73pub trait StateRangeProvider {
74 /// Returns accounts (hash, account) in `[start, limit]`, bounded by `response_bytes`.
75 fn account_range(
76 &self,
77 start: B256,
78 limit: B256,
79 response_bytes: usize,
80 ) -> RangeResult<(B256, Account)>;
81
82 /// Returns the storage root for `hashed_address` without needing its address preimage.
83 fn storage_root_by_hash(&self, hashed_address: B256) -> ProviderResult<B256>;
84
85 /// Same as [`Self::account_range`], but for the storage slots of `hashed_address`.
86 ///
87 /// Returns `None` if `hashed_address` isn't present in the account trie at the pinned state
88 /// root, distinct from an account that is present but has no storage.
89 fn storage_range(
90 &self,
91 hashed_address: B256,
92 start: B256,
93 limit: B256,
94 response_bytes: usize,
95 ) -> StorageRangeResult;
96
97 /// Returns an account-trie boundary proof for the already-hashed `keys`.
98 fn account_range_proof(&self, keys: &[B256]) -> ProviderResult<Vec<Bytes>>;
99
100 /// Same as [`Self::account_range_proof`], but for the storage trie of `hashed_address`.
101 fn storage_range_proof(
102 &self,
103 hashed_address: B256,
104 keys: &[B256],
105 ) -> ProviderResult<Vec<Bytes>>;
106}
107
108/// A type that resolves retained state roots into reusable state range views.
109#[auto_impl::auto_impl(&, Arc)]
110pub trait StateRangeProviderFactory {
111 /// Returns a view pinned to `state_root`, or `None` if that root is not retained.
112 fn state_range_provider(&self, state_root: B256) -> ProviderResult<Option<StateRangeView>>;
113}
114
115/// A range query's items and why the range ended where it did.
116#[derive(Debug, Clone, PartialEq, Eq)]
117pub struct RangeResponse<T> {
118 /// The items found within the requested range, in ascending key order.
119 pub items: Vec<T>,
120 /// Why `items` doesn't necessarily continue past its last entry.
121 pub end: RangeEnd,
122}
123
124/// Why a range query stopped before the caller-requested `limit`.
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126pub enum RangeEnd {
127 /// The cursor ran out of entries: `items` covers everything from `start` onward.
128 Exhausted,
129 /// The last returned item's key reached or passed the requested `limit`.
130 HashLimit,
131 /// `response_bytes` was exceeded before `limit` was reached.
132 ByteLimit,
133}
134
135/// Result of a [`StateRangeProvider`] range query.
136pub type RangeResult<T> = ProviderResult<RangeResponse<T>>;
137
138/// Result of a [`StateRangeProvider::storage_range`] query: `None` if the account itself isn't
139/// present in the trie at the pinned state root.
140pub type StorageRangeResult = ProviderResult<Option<RangeResponse<(B256, U256)>>>;
141
142/// A reusable state range view resolved for a specific state root.
143pub type StateRangeView = Box<dyn StateRangeProvider + Send + 'static>;
144
145/// A type that can generate state proof on top of a given post state.
146#[auto_impl::auto_impl(&, Box, Arc)]
147pub trait StateProofProvider {
148 /// Get account and storage proofs of target keys in the `HashedPostState`
149 /// on top of the current state.
150 fn proof(
151 &self,
152 input: TrieInput,
153 address: Address,
154 slots: &[B256],
155 ) -> ProviderResult<AccountProof>;
156
157 /// Generate [`MultiProof`] for target hashed account and corresponding
158 /// hashed storage slot keys.
159 fn multiproof(
160 &self,
161 input: TrieInput,
162 targets: MultiProofTargets,
163 ) -> ProviderResult<MultiProof>;
164
165 /// Generate a V2 decoded multiproof for target hashed accounts and storage slots against the
166 /// provider's state.
167 ///
168 /// A storage address with no slot targets requests its storage root node. Empty targets return
169 /// an empty proof.
170 ///
171 /// Set `requires_masks` when the hash and tree masks of returned branch nodes must match the
172 /// stored trie, as required to produce trie updates from them. Otherwise node hashes are still
173 /// exact, but masks are not guaranteed to match.
174 fn multiproof_v2(
175 &self,
176 targets: MultiProofTargetsV2,
177 requires_masks: bool,
178 ) -> ProviderResult<DecodedMultiProofV2>;
179
180 /// Get trie witness for provided state using the given witness generation mode.
181 fn witness(
182 &self,
183 input: TrieInput,
184 target: HashedPostState,
185 mode: ExecutionWitnessMode,
186 ) -> ProviderResult<Vec<Bytes>>;
187}
188
189/// Trie Writer
190#[auto_impl::auto_impl(&, Arc, Box)]
191pub trait TrieWriter: Send {
192 /// Writes trie updates to the database.
193 ///
194 /// Returns the number of entries modified.
195 fn write_trie_updates(&self, trie_updates: TrieUpdates) -> ProviderResult<usize> {
196 self.write_trie_updates_sorted(&trie_updates.into_sorted())
197 }
198
199 /// Writes trie updates to the database with already sorted updates.
200 ///
201 /// Returns the number of entries modified.
202 fn write_trie_updates_sorted(&self, trie_updates: &TrieUpdatesSorted) -> ProviderResult<usize>;
203}
204
205/// Storage Trie Writer
206#[auto_impl::auto_impl(&, Arc, Box)]
207pub trait StorageTrieWriter: Send {
208 /// Writes storage trie updates from the given storage trie map with already sorted updates.
209 ///
210 /// Expects the storage trie updates to already be sorted by the hashed address key.
211 ///
212 /// Returns the number of entries modified.
213 fn write_storage_trie_updates_sorted<'a>(
214 &self,
215 storage_tries: impl Iterator<Item = (&'a B256, &'a StorageTrieUpdatesSorted)>,
216 ) -> ProviderResult<usize>;
217}