1use super::ExecutedBlock;
2use alloy_consensus::BlockHeader;
3use alloy_primitives::{
4 keccak256, map::B256HashMap, Address, BlockNumber, Bytes, StorageKey, B256,
5};
6use reth_errors::ProviderResult;
7use reth_primitives::{Account, Bytecode, NodePrimitives};
8use reth_storage_api::{
9 AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider,
10 StateRootProvider, StorageRootProvider,
11};
12use reth_trie::{
13 updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
14 MultiProofTargets, StorageMultiProof, TrieInput,
15};
16use revm::{db::BundleState, primitives::FlaggedStorage};
17use std::sync::OnceLock;
18
19#[allow(missing_debug_implementations)]
22pub struct MemoryOverlayStateProviderRef<'a, N: NodePrimitives = reth_primitives::EthPrimitives> {
23 pub(crate) historical: Box<dyn StateProvider + 'a>,
25 pub(crate) in_memory: Vec<ExecutedBlock<N>>,
27 pub(crate) trie_state: OnceLock<MemoryOverlayTrieState>,
29}
30
31#[allow(missing_debug_implementations)]
34pub struct MemoryOverlayStateProvider<N: NodePrimitives = reth_primitives::EthPrimitives> {
35 pub(crate) historical: Box<dyn StateProvider>,
37 pub(crate) in_memory: Vec<ExecutedBlock<N>>,
39 pub(crate) trie_state: OnceLock<MemoryOverlayTrieState>,
41}
42
43macro_rules! impl_state_provider {
44 ([$($tokens:tt)*],$type:ty, $historical_type:ty) => {
45 impl $($tokens)* $type {
46 pub fn new(historical: $historical_type, in_memory: Vec<ExecutedBlock<N>>) -> Self {
54 Self { historical, in_memory, trie_state: OnceLock::new() }
55 }
56
57 pub fn boxed(self) -> $historical_type {
59 Box::new(self)
60 }
61
62 fn trie_state(&self) -> &MemoryOverlayTrieState {
64 self.trie_state.get_or_init(|| {
65 let mut trie_state = MemoryOverlayTrieState::default();
66 for block in self.in_memory.iter().rev() {
67 trie_state.state.extend_ref(block.hashed_state.as_ref());
68 trie_state.nodes.extend_ref(block.trie.as_ref());
69 }
70 trie_state
71 })
72 }
73 }
74
75 impl $($tokens)* BlockHashReader for $type {
76 fn block_hash(&self, number: BlockNumber) -> ProviderResult<Option<B256>> {
77 for block in &self.in_memory {
78 if block.block.number() == number {
79 return Ok(Some(block.block.hash()))
80 }
81 }
82
83 self.historical.block_hash(number)
84 }
85
86 fn canonical_hashes_range(
87 &self,
88 start: BlockNumber,
89 end: BlockNumber,
90 ) -> ProviderResult<Vec<B256>> {
91 let range = start..end;
92 let mut earliest_block_number = None;
93 let mut in_memory_hashes = Vec::new();
94 for block in &self.in_memory {
95 if range.contains(&block.block.number()) {
96 in_memory_hashes.insert(0, block.block.hash());
97 earliest_block_number = Some(block.block.number());
98 }
99 }
100
101 let mut hashes =
102 self.historical.canonical_hashes_range(start, earliest_block_number.unwrap_or(end))?;
103 hashes.append(&mut in_memory_hashes);
104 Ok(hashes)
105 }
106 }
107
108 impl $($tokens)* AccountReader for $type {
109 fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
110 for block in &self.in_memory {
111 if let Some(account) = block.execution_output.account(&address) {
112 return Ok(account)
113 }
114 }
115
116 self.historical.basic_account(address)
117 }
118 }
119
120 impl $($tokens)* StateRootProvider for $type {
121 fn state_root(&self, state: HashedPostState) -> ProviderResult<B256> {
122 self.state_root_from_nodes(TrieInput::from_state(state))
123 }
124
125 fn state_root_from_nodes(&self, mut input: TrieInput) -> ProviderResult<B256> {
126 let MemoryOverlayTrieState { nodes, state } = self.trie_state().clone();
127 input.prepend_cached(nodes, state);
128 self.historical.state_root_from_nodes(input)
129 }
130
131 fn state_root_with_updates(
132 &self,
133 state: HashedPostState,
134 ) -> ProviderResult<(B256, TrieUpdates)> {
135 self.state_root_from_nodes_with_updates(TrieInput::from_state(state))
136 }
137
138 fn state_root_from_nodes_with_updates(
139 &self,
140 mut input: TrieInput,
141 ) -> ProviderResult<(B256, TrieUpdates)> {
142 let MemoryOverlayTrieState { nodes, state } = self.trie_state().clone();
143 input.prepend_cached(nodes, state);
144 self.historical.state_root_from_nodes_with_updates(input)
145 }
146 }
147
148 impl $($tokens)* StorageRootProvider for $type {
149 fn storage_root(&self, address: Address, storage: HashedStorage) -> ProviderResult<B256> {
151 let state = &self.trie_state().state;
152 let mut hashed_storage =
153 state.storages.get(&keccak256(address)).cloned().unwrap_or_default();
154 hashed_storage.extend(&storage);
155 self.historical.storage_root(address, hashed_storage)
156 }
157
158 fn storage_proof(
160 &self,
161 address: Address,
162 slot: B256,
163 storage: HashedStorage,
164 ) -> ProviderResult<reth_trie::StorageProof> {
165 let state = &self.trie_state().state;
166 let mut hashed_storage =
167 state.storages.get(&keccak256(address)).cloned().unwrap_or_default();
168 hashed_storage.extend(&storage);
169 self.historical.storage_proof(address, slot, hashed_storage)
170 }
171
172 fn storage_multiproof(
174 &self,
175 address: Address,
176 slots: &[B256],
177 storage: HashedStorage,
178 ) -> ProviderResult<StorageMultiProof> {
179 let state = &self.trie_state().state;
180 let mut hashed_storage =
181 state.storages.get(&keccak256(address)).cloned().unwrap_or_default();
182 hashed_storage.extend(&storage);
183 self.historical.storage_multiproof(address, slots, hashed_storage)
184 }
185 }
186
187 impl $($tokens)* StateProofProvider for $type {
188 fn proof(
189 &self,
190 mut input: TrieInput,
191 address: Address,
192 slots: &[B256],
193 ) -> ProviderResult<AccountProof> {
194 let MemoryOverlayTrieState { nodes, state } = self.trie_state().clone();
195 input.prepend_cached(nodes, state);
196 self.historical.proof(input, address, slots)
197 }
198
199 fn multiproof(
200 &self,
201 mut input: TrieInput,
202 targets: MultiProofTargets,
203 ) -> ProviderResult<MultiProof> {
204 let MemoryOverlayTrieState { nodes, state } = self.trie_state().clone();
205 input.prepend_cached(nodes, state);
206 self.historical.multiproof(input, targets)
207 }
208
209 fn witness(
210 &self,
211 mut input: TrieInput,
212 target: HashedPostState,
213 ) -> ProviderResult<B256HashMap<Bytes>> {
214 let MemoryOverlayTrieState { nodes, state } = self.trie_state().clone();
215 input.prepend_cached(nodes, state);
216 self.historical.witness(input, target)
217 }
218 }
219
220 impl $($tokens)* HashedPostStateProvider for $type {
221 fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState {
222 self.historical.hashed_post_state(bundle_state)
223 }
224 }
225
226 impl $($tokens)* StateProvider for $type {
227 fn storage(
228 &self,
229 address: Address,
230 storage_key: StorageKey,
231 ) -> ProviderResult<Option<FlaggedStorage>> {
232 for block in &self.in_memory {
233 if let Some(value) = block.execution_output.storage(&address, storage_key.into()) {
234 return Ok(Some(value))
235 }
236 }
237
238 self.historical.storage(address, storage_key)
239 }
240
241 fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>> {
242 for block in &self.in_memory {
243 if let Some(contract) = block.execution_output.bytecode(&code_hash) {
244 return Ok(Some(contract))
245 }
246 }
247
248 self.historical.bytecode_by_hash(code_hash)
249 }
250 }
251 };
252}
253
254impl_state_provider!([<N: NodePrimitives>], MemoryOverlayStateProvider<N>, Box<dyn StateProvider>);
255impl_state_provider!([<'a, N: NodePrimitives>], MemoryOverlayStateProviderRef<'a, N>, Box<dyn StateProvider + 'a>);
256
257#[derive(Clone, Default, Debug)]
259pub(crate) struct MemoryOverlayTrieState {
260 pub(crate) nodes: TrieUpdates,
262 pub(crate) state: HashedPostState,
264}