Skip to main content

reth_storage_overlay/
provider.rs

1use crate::{database_state_frontiers, ExecutionOverlay, OverlayBuilder, StateTrieOverlay};
2use alloy_primitives::{Address, BlockHash, BlockNumber, B256, U256};
3use metrics::{Counter, Histogram};
4use reth_db_api::{cursor::DbDupCursorRO, tables, transaction::DbTx, DatabaseError};
5use reth_errors::{ProviderError, ProviderResult};
6use reth_ethereum_primitives::EthPrimitives;
7use reth_metrics::Metrics;
8use reth_primitives_traits::{
9    dashmap::{self, DashMap},
10    Account, NodePrimitives,
11};
12use reth_prune_types::PruneSegment;
13use reth_storage_api::{
14    AccountReader, BlockHashReader, BlockNumReader, BytecodeReader, ChangeSetReader, DBProvider,
15    DatabaseProviderFactory, DatabaseProviderROFactory, DbTxProvider, HashedPostStateProvider,
16    HistoryInfo, HistoryReader, PruneCheckpointReader, StageCheckpointReader, StateProofProvider,
17    StateProvider, StateRootProvider, StorageChangeSetReader, StorageRootProvider,
18    StorageSettingsCache,
19};
20use reth_trie::{
21    hashed_cursor::{
22        zero_destroyed_account_storage, HashedCursorFactory, HashedPostStateCursorFactory,
23    },
24    proof::{Proof, StorageProof as TrieStorageProof},
25    trie_cursor::{
26        InMemoryTrieCursor, InMemoryTrieCursorFactory, TrieCursor, TrieCursorFactory,
27        TrieStorageCursor,
28    },
29    updates::TrieUpdates,
30    witness::TrieWitness,
31    AccountProof, DecodedMultiProofV2, ExecutionWitnessMode, HashedPostState,
32    HashedPostStateSorted, HashedStorage, KeccakKeyHasher, MultiProof, MultiProofTargets,
33    MultiProofTargetsV2, StateRoot, StorageMultiProof, StorageProof, StorageRoot, TrieInput,
34    TrieInputSorted,
35};
36use reth_trie_db::{
37    DatabaseAccountTrieCursor, DatabaseHashedCursorFactory, DatabaseProof, DatabaseStateRoot,
38    DatabaseStorageProof, DatabaseStorageRoot, DatabaseStorageTrieCursor,
39    DatabaseTrieCursorFactory, LegacyKeyAdapter, PackedAccountsTrie, PackedKeyAdapter,
40    PackedStoragesTrie,
41};
42use std::{cell::OnceCell, fmt, ops::Deref, sync::Arc, time::Instant};
43use tracing::instrument;
44
45/// Factory for creating overlay state providers with optional reverts and overlays.
46///
47/// This factory allows building an `OverlayStateProvider` whose DB state has been reverted to a
48/// particular block, and/or with additional overlay information added on top.
49#[derive(Debug, Clone)]
50pub struct OverlayStateProviderFactory<F, N: NodePrimitives = EthPrimitives> {
51    /// The underlying database provider factory
52    factory: F,
53    /// Overlay builder containing the configuration and overlay calculation logic.
54    overlay_builder: OverlayBuilder<N>,
55    /// A cache mapping `(state_trie_tip, finish_tip)` to [`StateTrieOverlay`].
56    ///
57    /// Under partial persistence the overlay depends on both durable frontiers, so both hashes are
58    /// part of the cache key.
59    state_trie_overlay_cache: StateTrieOverlayCache,
60    /// Metrics for provider factory operations.
61    metrics: OverlayStateProviderFactoryMetrics,
62}
63
64impl<F, N: NodePrimitives> OverlayStateProviderFactory<F, N> {
65    /// Create a new overlay state provider factory.
66    pub fn new(factory: F, overlay_builder: OverlayBuilder<N>) -> Self {
67        Self {
68            factory,
69            overlay_builder,
70            state_trie_overlay_cache: Default::default(),
71            metrics: Default::default(),
72        }
73    }
74
75    /// Skips managed overlay construction when this factory is used by a task that reused a sparse
76    /// trie covering both durable frontiers through the parent.
77    pub fn with_skip_overlay_for_reused_sparse_trie(mut self, anchor_hash: B256) -> Self {
78        self.overlay_builder =
79            self.overlay_builder.with_skip_overlay_for_reused_sparse_trie(anchor_hash);
80        self.state_trie_overlay_cache = Default::default();
81        self
82    }
83}
84
85impl<F, N> DatabaseProviderROFactory for OverlayStateProviderFactory<F, N>
86where
87    N: NodePrimitives,
88    F: DatabaseProviderFactory,
89    F::Provider: StageCheckpointReader
90        + PruneCheckpointReader
91        + BlockNumReader
92        + ChangeSetReader
93        + StorageChangeSetReader
94        + StorageSettingsCache,
95{
96    type Provider = OverlayStateProvider<OwnedProvider<F::Provider>, N>;
97
98    /// Create a read-only [`OverlayStateProvider`].
99    #[instrument(level = "debug", target = "providers::state::overlay", skip_all)]
100    fn database_provider_ro(
101        &self,
102    ) -> ProviderResult<OverlayStateProvider<OwnedProvider<F::Provider>, N>> {
103        let overall_start = Instant::now();
104
105        // Get a read-only provider
106        let provider = {
107            let start = Instant::now();
108            let res = self.factory.database_provider_ro()?;
109            self.metrics.create_provider_duration.record(start.elapsed());
110            res
111        };
112
113        let is_v2 = provider.cached_storage_settings().is_v2();
114        self.metrics.database_provider_ro_duration.record(overall_start.elapsed());
115        Ok(OverlayStateProvider::new_with_caches(
116            provider,
117            self.overlay_builder.clone(),
118            Arc::clone(&self.state_trie_overlay_cache),
119            self.metrics.clone(),
120            is_v2,
121        ))
122    }
123}
124
125/// State provider with lazily resolved state trie and execution overlays.
126pub struct OverlayStateProvider<Provider, N: NodePrimitives = EthPrimitives> {
127    provider: Provider,
128    overlay_builder: Option<OverlayBuilder<N>>,
129    state_trie_overlay_cache: StateTrieOverlayCache,
130    metrics: OverlayStateProviderFactoryMetrics,
131    state_trie_overlay: OnceCell<StateTrieOverlay>,
132    execution_overlay: OnceCell<CachedExecutionOverlay>,
133    is_v2: bool,
134}
135
136impl<Provider, N: NodePrimitives> OverlayStateProvider<OwnedProvider<Provider>, N> {
137    /// Creates an overlay state provider over an already-open database provider.
138    pub fn new(provider: Provider, overlay_builder: OverlayBuilder<N>) -> Self
139    where
140        Provider: StorageSettingsCache,
141    {
142        let is_v2 = provider.cached_storage_settings().is_v2();
143        Self::new_with_caches(
144            provider,
145            overlay_builder,
146            Default::default(),
147            Default::default(),
148            is_v2,
149        )
150    }
151
152    const fn new_with_caches(
153        provider: Provider,
154        overlay_builder: OverlayBuilder<N>,
155        state_trie_overlay_cache: StateTrieOverlayCache,
156        metrics: OverlayStateProviderFactoryMetrics,
157        is_v2: bool,
158    ) -> Self {
159        Self {
160            provider: OwnedProvider(provider),
161            overlay_builder: Some(overlay_builder),
162            state_trie_overlay_cache,
163            metrics,
164            state_trie_overlay: OnceCell::new(),
165            execution_overlay: OnceCell::new(),
166            is_v2,
167        }
168    }
169
170    #[cfg(test)]
171    fn new_with_execution(
172        provider: Provider,
173        execution_overlay: Arc<ExecutionOverlay>,
174        is_v2: bool,
175    ) -> Self {
176        Self {
177            provider: OwnedProvider(provider),
178            overlay_builder: None,
179            state_trie_overlay_cache: Default::default(),
180            metrics: Default::default(),
181            state_trie_overlay: OnceCell::new(),
182            execution_overlay: OnceCell::from(CachedExecutionOverlay {
183                overlay: execution_overlay,
184                historical_fallback: None,
185            }),
186            is_v2,
187        }
188    }
189}
190
191impl<'a, Provider, N: NodePrimitives> OverlayStateProvider<&'a Provider, N> {
192    /// Creates an overlay state provider over a borrowed database provider.
193    pub fn new_ref(provider: &'a Provider, overlay_builder: OverlayBuilder<N>) -> Self
194    where
195        Provider: StorageSettingsCache,
196    {
197        let is_v2 = provider.cached_storage_settings().is_v2();
198        Self {
199            provider,
200            overlay_builder: Some(overlay_builder),
201            state_trie_overlay_cache: Default::default(),
202            metrics: Default::default(),
203            state_trie_overlay: OnceCell::new(),
204            execution_overlay: OnceCell::new(),
205            is_v2,
206        }
207    }
208
209    pub(crate) fn new_with_state_trie(
210        provider: &'a Provider,
211        state_trie_overlay: StateTrieOverlay,
212        is_v2: bool,
213    ) -> Self {
214        Self {
215            provider,
216            overlay_builder: None,
217            state_trie_overlay_cache: Default::default(),
218            metrics: Default::default(),
219            state_trie_overlay: OnceCell::from(state_trie_overlay),
220            execution_overlay: OnceCell::new(),
221            is_v2,
222        }
223    }
224}
225
226impl<Provider, N: NodePrimitives> OverlayStateProvider<Provider, N>
227where
228    Provider: Deref,
229    Provider::Target: Sized,
230{
231    fn provider(&self) -> &Provider::Target {
232        &self.provider
233    }
234
235    fn state_trie_overlay(&self) -> ProviderResult<&StateTrieOverlay>
236    where
237        Provider::Target: StageCheckpointReader
238            + PruneCheckpointReader
239            + ChangeSetReader
240            + StorageChangeSetReader
241            + DBProvider
242            + BlockNumReader
243            + StorageSettingsCache,
244    {
245        if let Some(overlay) = self.state_trie_overlay.get() {
246            return Ok(overlay)
247        }
248
249        let (state_trie_tip_block, finish_tip_block) = database_state_frontiers(self.provider())?;
250        let overlay = match self
251            .state_trie_overlay_cache
252            .entry((state_trie_tip_block.hash, finish_tip_block.hash))
253        {
254            dashmap::Entry::Occupied(entry) => entry.get().clone(),
255            dashmap::Entry::Vacant(entry) => {
256                self.metrics.state_trie_overlay_cache_misses.increment(1);
257                let overlay = self
258                    .overlay_builder
259                    .as_ref()
260                    .expect("state trie overlay must be initialized or lazily resolvable")
261                    .build_state_trie_overlay_at_frontiers(
262                        self.provider(),
263                        state_trie_tip_block,
264                        finish_tip_block,
265                    )?;
266                if !overlay.skipped_for_reused_sparse_trie() {
267                    entry.insert(overlay.clone());
268                }
269                overlay
270            }
271        };
272        let _ = self.state_trie_overlay.set(overlay);
273        Ok(self.state_trie_overlay.get().expect("state trie overlay was just initialized"))
274    }
275
276    fn build_overlay(&self, input: TrieInputSorted) -> ProviderResult<TrieInputSorted>
277    where
278        Provider::Target: StageCheckpointReader
279            + PruneCheckpointReader
280            + ChangeSetReader
281            + StorageChangeSetReader
282            + DBProvider
283            + BlockNumReader
284            + StorageSettingsCache,
285    {
286        let overlay = self.state_trie_overlay()?;
287        if overlay.skipped_for_reused_sparse_trie() {
288            return Err(ProviderError::UnsupportedProvider)
289        }
290        let TrieInputSorted { nodes: input_nodes, state: input_state, prefix_sets } = input;
291        let mut nodes = Arc::clone(&overlay.trie_updates);
292        let mut state = Arc::clone(&overlay.hashed_post_state);
293
294        if !input_nodes.is_empty() {
295            Arc::make_mut(&mut nodes).extend_ref_and_sort(&input_nodes);
296        }
297        if !input_state.is_empty() {
298            Arc::make_mut(&mut state).extend_ref_and_sort(&input_state);
299        }
300
301        Ok(TrieInputSorted::new(nodes, state, prefix_sets))
302    }
303
304    fn execution_overlay(
305        &self,
306    ) -> ProviderResult<(&Arc<ExecutionOverlay>, Option<&HistoricalFallback>)>
307    where
308        Provider::Target: StageCheckpointReader
309            + PruneCheckpointReader
310            + ChangeSetReader
311            + StorageChangeSetReader
312            + DBProvider
313            + BlockNumReader,
314    {
315        if let Some(overlay) = self.execution_overlay.get() {
316            return Ok((&overlay.overlay, overlay.historical_fallback.as_ref()))
317        }
318
319        let (state_trie_tip_block, finish_tip_block) = database_state_frontiers(self.provider())?;
320        let (overlay, fallback_block_number) = self
321            .overlay_builder
322            .as_ref()
323            .expect("execution overlay must be initialized or lazily resolvable")
324            .execution_overlay_at_frontiers(
325                self.provider(),
326                state_trie_tip_block,
327                finish_tip_block,
328            )?;
329        let historical_fallback = fallback_block_number
330            .map(|block_number| {
331                let account_history_block_number = self
332                    .provider()
333                    .get_prune_checkpoint(PruneSegment::AccountHistory)?
334                    .and_then(|checkpoint| checkpoint.block_number)
335                    .map(|block_number| block_number + 1);
336                if account_history_block_number.is_some_and(|lowest| block_number < lowest) {
337                    return Err(ProviderError::StateAtBlockPruned(block_number))
338                }
339
340                let storage_history_block_number = self
341                    .provider()
342                    .get_prune_checkpoint(PruneSegment::StorageHistory)?
343                    .and_then(|checkpoint| checkpoint.block_number)
344                    .map(|block_number| block_number + 1);
345                if storage_history_block_number.is_some_and(|lowest| block_number < lowest) {
346                    return Err(ProviderError::StateAtBlockPruned(block_number))
347                }
348
349                Ok(HistoricalFallback {
350                    block_number,
351                    account_history_block_number,
352                    storage_history_block_number,
353                })
354            })
355            .transpose()?;
356        let overlay = CachedExecutionOverlay { overlay, historical_fallback };
357        let _ = self.execution_overlay.set(overlay);
358        let overlay = self.execution_overlay.get().expect("execution overlay was just initialized");
359        Ok((&overlay.overlay, overlay.historical_fallback.as_ref()))
360    }
361}
362
363impl<Provider, N: NodePrimitives> fmt::Debug for OverlayStateProvider<Provider, N>
364where
365    Provider: Deref,
366    Provider::Target: fmt::Debug + Sized,
367{
368    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369        f.debug_struct("OverlayStateProvider")
370            .field("provider", self.provider())
371            .field("state_trie_overlay", &self.state_trie_overlay.get())
372            .field("execution_overlay", &self.execution_overlay.get())
373            .field("is_v2", &self.is_v2)
374            .finish()
375    }
376}
377
378impl<Provider, N: NodePrimitives> AccountReader for OverlayStateProvider<Provider, N>
379where
380    Provider: Deref,
381    Provider::Target: DBProvider
382        + HistoryReader
383        + StorageSettingsCache
384        + StageCheckpointReader
385        + PruneCheckpointReader
386        + ChangeSetReader
387        + StorageChangeSetReader
388        + BlockNumReader,
389{
390    fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
391        let (overlay, historical_fallback) = self.execution_overlay()?;
392        if let Some(account) = overlay.accounts().get(address) {
393            return Ok(account.as_ref().map(Account::from))
394        }
395        if let Some(historical_fallback) = historical_fallback {
396            return match self.provider().account_history_info(
397                *address,
398                historical_fallback.block_number,
399                historical_fallback.account_history_block_number,
400            )? {
401                HistoryInfo::NotYetWritten => Ok(None),
402                HistoryInfo::InChangeset(changeset_block_number) => self
403                    .provider()
404                    .get_account_before_block(changeset_block_number, *address)?
405                    .ok_or(ProviderError::AccountChangesetNotFound {
406                        block_number: changeset_block_number,
407                        address: *address,
408                    })
409                    .map(|account_before| account_before.info),
410                HistoryInfo::InPlainState | HistoryInfo::MaybeInPlainState => {
411                    self.basic_account_from_db(address)
412                }
413            }
414        }
415        self.basic_account_from_db(address)
416    }
417}
418
419impl<Provider, N: NodePrimitives> OverlayStateProvider<Provider, N>
420where
421    Provider: Deref,
422    Provider::Target: DBProvider + StorageSettingsCache,
423{
424    fn basic_account_from_db(&self, address: &Address) -> ProviderResult<Option<Account>> {
425        if self.provider().cached_storage_settings().use_hashed_state() {
426            let hashed_address = alloy_primitives::keccak256(address);
427            self.provider()
428                .tx()
429                .get_by_encoded_key::<tables::HashedAccounts>(&hashed_address)
430                .map_err(Into::into)
431        } else {
432            self.provider()
433                .tx()
434                .get_by_encoded_key::<tables::PlainAccountState>(address)
435                .map_err(Into::into)
436        }
437    }
438}
439
440impl<Provider, N: NodePrimitives> BlockHashReader for OverlayStateProvider<Provider, N>
441where
442    Provider: Deref,
443    Provider::Target: BlockHashReader
444        + DBProvider
445        + Sized
446        + StageCheckpointReader
447        + PruneCheckpointReader
448        + ChangeSetReader
449        + StorageChangeSetReader
450        + BlockNumReader,
451{
452    fn block_hash(&self, number: BlockNumber) -> ProviderResult<Option<B256>> {
453        let (overlay, _) = self.execution_overlay()?;
454        if let Some(block) = overlay.block_hashes().iter().find(|block| block.number == number) {
455            return Ok(Some(block.hash))
456        }
457        self.provider().block_hash(number)
458    }
459
460    fn canonical_hashes_range(
461        &self,
462        start: BlockNumber,
463        end: BlockNumber,
464    ) -> ProviderResult<Vec<B256>> {
465        let (overlay, _) = self.execution_overlay()?;
466        let mut block_hashes =
467            overlay.block_hashes().iter().filter(|block| (start..end).contains(&block.number));
468        let Some(first_block) = block_hashes.next() else {
469            return self.provider().canonical_hashes_range(start, end)
470        };
471
472        let mut hashes = self.provider().canonical_hashes_range(start, first_block.number)?;
473        hashes.push(first_block.hash);
474        hashes.extend(block_hashes.map(|block| block.hash));
475        Ok(hashes)
476    }
477}
478
479impl<Provider, N: NodePrimitives> BytecodeReader for OverlayStateProvider<Provider, N>
480where
481    Provider: Deref,
482    Provider::Target: DBProvider
483        + StageCheckpointReader
484        + PruneCheckpointReader
485        + ChangeSetReader
486        + StorageChangeSetReader
487        + BlockNumReader,
488{
489    fn bytecode_by_hash(
490        &self,
491        code_hash: &B256,
492    ) -> ProviderResult<Option<reth_primitives_traits::Bytecode>> {
493        let (overlay, _) = self.execution_overlay()?;
494        if let Some(bytecode) = overlay.code_hashes().get(code_hash) {
495            return Ok(Some(reth_primitives_traits::Bytecode(bytecode.clone())));
496        }
497        self.provider().tx().get_by_encoded_key::<tables::Bytecodes>(code_hash).map_err(Into::into)
498    }
499}
500
501impl<Provider, N: NodePrimitives> StateRootProvider for OverlayStateProvider<Provider, N>
502where
503    Provider: Deref,
504    Provider::Target: DBProvider
505        + StageCheckpointReader
506        + PruneCheckpointReader
507        + ChangeSetReader
508        + StorageChangeSetReader
509        + BlockNumReader
510        + StorageSettingsCache,
511{
512    fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult<B256> {
513        reth_trie_db::with_adapter!(self.provider(), |A| {
514            let input = self.build_overlay(TrieInputSorted::from_unsorted(
515                TrieInput::from_state(hashed_state),
516            ))?;
517            Ok(<DbStateRoot<'_, _, A>>::overlay_root_from_nodes(self.provider().tx(), input)?)
518        })
519    }
520
521    fn state_root_from_nodes(&self, input: TrieInput) -> ProviderResult<B256> {
522        reth_trie_db::with_adapter!(self.provider(), |A| {
523            let input = self.build_overlay(TrieInputSorted::from_unsorted(input))?;
524            Ok(<DbStateRoot<'_, _, A> as DatabaseStateRoot<_>>::overlay_root_from_nodes(
525                self.provider().tx(),
526                input,
527            )?)
528        })
529    }
530
531    fn state_root_with_updates(
532        &self,
533        hashed_state: HashedPostState,
534    ) -> ProviderResult<(B256, TrieUpdates)> {
535        reth_trie_db::with_adapter!(self.provider(), |A| {
536            let input = self.build_overlay(TrieInputSorted::from_unsorted(
537                TrieInput::from_state(hashed_state),
538            ))?;
539            Ok(<DbStateRoot<'_, _, A>>::overlay_root_from_nodes_with_updates(
540                self.provider().tx(),
541                input,
542            )?)
543        })
544    }
545
546    fn state_root_from_nodes_with_updates(
547        &self,
548        input: TrieInput,
549    ) -> ProviderResult<(B256, TrieUpdates)> {
550        reth_trie_db::with_adapter!(self.provider(), |A| {
551            let input = self.build_overlay(TrieInputSorted::from_unsorted(input))?;
552            Ok(
553                <DbStateRoot<'_, _, A> as DatabaseStateRoot<_>>::overlay_root_from_nodes_with_updates(
554                    self.provider().tx(),
555                    input,
556                )?,
557            )
558        })
559    }
560}
561
562impl<Provider, N: NodePrimitives> StorageRootProvider for OverlayStateProvider<Provider, N>
563where
564    Provider: Deref,
565    Provider::Target: DBProvider
566        + StageCheckpointReader
567        + PruneCheckpointReader
568        + ChangeSetReader
569        + StorageChangeSetReader
570        + BlockNumReader
571        + StorageSettingsCache,
572{
573    fn storage_root(
574        &self,
575        address: Address,
576        hashed_storage: HashedStorage,
577    ) -> ProviderResult<B256> {
578        reth_trie_db::with_adapter!(self.provider(), |A| {
579            let input = self.build_overlay(TrieInputSorted::from_unsorted(
580                TrieInput::from_state(HashedPostState::from_hashed_storage(
581                    alloy_primitives::keccak256(address),
582                    hashed_storage,
583                )),
584            ))?;
585            let hashed_storage = input
586                .state
587                .account_storages()
588                .get(&alloy_primitives::keccak256(address))
589                .cloned()
590                .unwrap_or_default()
591                .into();
592            <DbStorageRoot<'_, _, A>>::overlay_root(self.provider().tx(), address, hashed_storage)
593                .map_err(|err| ProviderError::Database(err.into()))
594        })
595    }
596
597    fn storage_proof(
598        &self,
599        address: Address,
600        slot: B256,
601        hashed_storage: HashedStorage,
602    ) -> ProviderResult<StorageProof> {
603        reth_trie_db::with_adapter!(self.provider(), |A| {
604            let input = self.build_overlay(TrieInputSorted::from_unsorted(
605                TrieInput::from_state(HashedPostState::from_hashed_storage(
606                    alloy_primitives::keccak256(address),
607                    hashed_storage,
608                )),
609            ))?;
610            let hashed_storage = input
611                .state
612                .account_storages()
613                .get(&alloy_primitives::keccak256(address))
614                .cloned()
615                .unwrap_or_default()
616                .into();
617            <DbStorageProof<'_, _, A>>::overlay_storage_proof(
618                self.provider().tx(),
619                address,
620                slot,
621                hashed_storage,
622            )
623            .map_err(ProviderError::from)
624        })
625    }
626
627    fn storage_multiproof(
628        &self,
629        address: Address,
630        slots: &[B256],
631        hashed_storage: HashedStorage,
632    ) -> ProviderResult<StorageMultiProof> {
633        reth_trie_db::with_adapter!(self.provider(), |A| {
634            let input = self.build_overlay(TrieInputSorted::from_unsorted(
635                TrieInput::from_state(HashedPostState::from_hashed_storage(
636                    alloy_primitives::keccak256(address),
637                    hashed_storage,
638                )),
639            ))?;
640            let hashed_storage = input
641                .state
642                .account_storages()
643                .get(&alloy_primitives::keccak256(address))
644                .cloned()
645                .unwrap_or_default()
646                .into();
647            <DbStorageProof<'_, _, A>>::overlay_storage_multiproof(
648                self.provider().tx(),
649                address,
650                slots,
651                hashed_storage,
652            )
653            .map_err(ProviderError::from)
654        })
655    }
656}
657
658impl<Provider, N: NodePrimitives> StateProofProvider for OverlayStateProvider<Provider, N>
659where
660    Provider: Deref,
661    Provider::Target: DBProvider
662        + StageCheckpointReader
663        + PruneCheckpointReader
664        + ChangeSetReader
665        + StorageChangeSetReader
666        + BlockNumReader
667        + StorageSettingsCache,
668{
669    fn proof(
670        &self,
671        input: TrieInput,
672        address: Address,
673        slots: &[B256],
674    ) -> ProviderResult<AccountProof> {
675        reth_trie_db::with_adapter!(self.provider(), |A| {
676            let TrieInputSorted { nodes, state, prefix_sets } =
677                self.build_overlay(TrieInputSorted::from_unsorted(input))?;
678            let input = TrieInput::new(
679                Arc::unwrap_or_clone(nodes).into(),
680                Arc::unwrap_or_clone(state).into(),
681                prefix_sets,
682            );
683            let proof = <DbProof<'_, _, A> as DatabaseProof>::from_tx(self.provider().tx());
684            proof.overlay_account_proof(input, address, slots).map_err(ProviderError::from)
685        })
686    }
687
688    fn multiproof(
689        &self,
690        input: TrieInput,
691        targets: MultiProofTargets,
692    ) -> ProviderResult<MultiProof> {
693        reth_trie_db::with_adapter!(self.provider(), |A| {
694            let TrieInputSorted { nodes, state, prefix_sets } =
695                self.build_overlay(TrieInputSorted::from_unsorted(input))?;
696            let input = TrieInput::new(
697                Arc::unwrap_or_clone(nodes).into(),
698                Arc::unwrap_or_clone(state).into(),
699                prefix_sets,
700            );
701            let proof = <DbProof<'_, _, A> as DatabaseProof>::from_tx(self.provider().tx());
702            proof.overlay_multiproof(input, targets).map_err(ProviderError::from)
703        })
704    }
705
706    fn multiproof_v2(
707        &self,
708        input: TrieInput,
709        targets: MultiProofTargetsV2,
710    ) -> ProviderResult<DecodedMultiProofV2> {
711        reth_trie_db::with_adapter!(self.provider(), |A| {
712            let TrieInputSorted { nodes, state, prefix_sets } =
713                self.build_overlay(TrieInputSorted::from_unsorted(input))?;
714            let input = TrieInput::new(
715                Arc::unwrap_or_clone(nodes).into(),
716                Arc::unwrap_or_clone(state).into(),
717                prefix_sets,
718            );
719            let proof = <DbProof<'_, _, A> as DatabaseProof>::from_tx(self.provider().tx());
720            proof.overlay_multiproof_v2(input, targets).map_err(ProviderError::from)
721        })
722    }
723
724    fn witness(
725        &self,
726        input: TrieInput,
727        target: HashedPostState,
728        mode: ExecutionWitnessMode,
729    ) -> ProviderResult<Vec<alloy_primitives::Bytes>> {
730        reth_trie_db::with_adapter!(self.provider(), |A| {
731            let TrieInputSorted { nodes, state, prefix_sets } =
732                self.build_overlay(TrieInputSorted::from_unsorted(input))?;
733            let witness = TrieWitness::new(
734                InMemoryTrieCursorFactory::new(
735                    DatabaseTrieCursorFactory::<_, A>::new(self.provider().tx()),
736                    nodes.as_ref(),
737                ),
738                HashedPostStateCursorFactory::new(
739                    DatabaseHashedCursorFactory::new(self.provider().tx()),
740                    state.as_ref(),
741                ),
742            )
743            .with_prefix_sets_mut(prefix_sets)
744            .with_execution_witness_mode(mode);
745            let witness =
746                if mode.is_canonical() { witness } else { witness.always_include_root_node() };
747            let mut values: Vec<_> = witness.compute(target)?.into_values().collect();
748            if mode.is_canonical() {
749                values.sort_unstable();
750            }
751            Ok(values)
752        })
753    }
754}
755
756impl<Provider, N: NodePrimitives> HashedPostStateProvider for OverlayStateProvider<Provider, N>
757where
758    Provider: Deref,
759    Provider::Target: DBProvider
760        + StageCheckpointReader
761        + PruneCheckpointReader
762        + ChangeSetReader
763        + StorageChangeSetReader
764        + BlockNumReader
765        + StorageSettingsCache,
766{
767    fn hashed_post_state(
768        &self,
769        bundle_state: &revm::database::BundleState,
770    ) -> ProviderResult<HashedPostState> {
771        let mut hashed_state =
772            HashedPostState::from_bundle_state::<KeccakKeyHasher>(bundle_state.state());
773        if !bundle_state
774            .state()
775            .values()
776            .any(|account| account.was_destroyed() && account.original_info.is_some())
777        {
778            return Ok(hashed_state)
779        }
780
781        let overlay_state = self.build_overlay(TrieInputSorted::default())?.state;
782        zero_destroyed_account_storage(
783            &HashedPostStateCursorFactory::new(
784                DatabaseHashedCursorFactory::new(self.provider().tx()),
785                overlay_state.as_ref(),
786            ),
787            bundle_state.state(),
788            &mut hashed_state,
789        )?;
790        Ok(hashed_state)
791    }
792}
793
794impl<Provider, N: NodePrimitives> StateProvider for OverlayStateProvider<Provider, N>
795where
796    Provider: Deref,
797    Provider::Target: DBProvider
798        + HistoryReader
799        + BlockHashReader
800        + StorageSettingsCache
801        + StageCheckpointReader
802        + PruneCheckpointReader
803        + ChangeSetReader
804        + StorageChangeSetReader
805        + BlockNumReader,
806{
807    fn storage(
808        &self,
809        address: Address,
810        storage_key: alloy_primitives::StorageKey,
811    ) -> ProviderResult<Option<alloy_primitives::StorageValue>> {
812        let (overlay, historical_fallback) = self.execution_overlay()?;
813        if let Some(value) = overlay.storage_value(address, U256::from_be_bytes(storage_key.0)) {
814            return Ok(Some(value));
815        }
816        if let Some(historical_fallback) = historical_fallback {
817            return match self.provider().storage_history_info(
818                address,
819                storage_key,
820                historical_fallback.block_number,
821                historical_fallback.storage_history_block_number,
822            )? {
823                HistoryInfo::NotYetWritten => Ok(None),
824                HistoryInfo::InChangeset(changeset_block_number) => self
825                    .provider()
826                    .get_storage_before_block(changeset_block_number, address, storage_key)?
827                    .ok_or_else(|| ProviderError::StorageChangesetNotFound {
828                        block_number: changeset_block_number,
829                        address,
830                        storage_key: Box::new(storage_key),
831                    })
832                    .map(|entry| Some(entry.value)),
833                HistoryInfo::InPlainState | HistoryInfo::MaybeInPlainState => {
834                    self.storage_from_db(address, storage_key, true)
835                }
836            }
837        }
838        self.storage_from_db(address, storage_key, false)
839    }
840}
841
842impl<Provider, N: NodePrimitives> OverlayStateProvider<Provider, N>
843where
844    Provider: Deref,
845    Provider::Target: DBProvider + StorageSettingsCache,
846{
847    fn storage_from_db(
848        &self,
849        address: Address,
850        storage_key: alloy_primitives::StorageKey,
851        zero_if_missing: bool,
852    ) -> ProviderResult<Option<alloy_primitives::StorageValue>> {
853        if self.provider().cached_storage_settings().use_hashed_state() {
854            let hashed_address = alloy_primitives::keccak256(address);
855            let hashed_slot = alloy_primitives::keccak256(storage_key);
856            let mut cursor = self.provider().tx().cursor_dup_read::<tables::HashedStorages>()?;
857            let value = cursor
858                .seek_by_key_subkey(hashed_address, hashed_slot)?
859                .filter(|entry| entry.key == hashed_slot)
860                .map(|entry| entry.value);
861            Ok(value.or_else(|| zero_if_missing.then_some(U256::ZERO)))
862        } else {
863            let mut cursor = self.provider().tx().cursor_dup_read::<tables::PlainStorageState>()?;
864            if let Some(entry) = cursor.seek_by_key_subkey(address, storage_key)? &&
865                entry.key == storage_key
866            {
867                return Ok(Some(entry.value))
868            }
869            Ok(zero_if_missing.then_some(U256::ZERO))
870        }
871    }
872}
873
874impl<Provider, N: NodePrimitives> TrieCursorFactory for OverlayStateProvider<Provider, N>
875where
876    Provider: Deref,
877    Provider::Target: DBProvider
878        + StageCheckpointReader
879        + PruneCheckpointReader
880        + ChangeSetReader
881        + StorageChangeSetReader
882        + BlockNumReader
883        + StorageSettingsCache,
884{
885    type AccountTrieCursor<'a>
886        = InMemoryTrieCursor<'a, Box<dyn TrieCursor + Send + 'a>>
887    where
888        Self: 'a;
889
890    type StorageTrieCursor<'a>
891        = InMemoryTrieCursor<'a, Box<dyn TrieStorageCursor + Send + 'a>>
892    where
893        Self: 'a;
894
895    fn account_trie_cursor(&self) -> Result<Self::AccountTrieCursor<'_>, DatabaseError> {
896        let overlay = self.state_trie_overlay().map_err(into_database_error)?;
897        let cursor: Box<dyn TrieCursor + Send> = if self.is_v2 {
898            Box::new(DatabaseAccountTrieCursor::<_, PackedKeyAdapter>::new(
899                self.provider().tx().cursor_read::<PackedAccountsTrie>()?,
900            ))
901        } else {
902            Box::new(DatabaseAccountTrieCursor::<_, LegacyKeyAdapter>::new(
903                self.provider().tx().cursor_read::<tables::AccountsTrie>()?,
904            ))
905        };
906        Ok(InMemoryTrieCursor::new_account(cursor, &overlay.trie_updates))
907    }
908
909    fn storage_trie_cursor(
910        &self,
911        hashed_address: B256,
912    ) -> Result<Self::StorageTrieCursor<'_>, DatabaseError> {
913        let overlay = self.state_trie_overlay().map_err(into_database_error)?;
914        let cursor: Box<dyn TrieStorageCursor + Send> = if self.is_v2 {
915            Box::new(DatabaseStorageTrieCursor::<_, PackedKeyAdapter>::new(
916                self.provider().tx().cursor_dup_read::<PackedStoragesTrie>()?,
917                hashed_address,
918            ))
919        } else {
920            Box::new(DatabaseStorageTrieCursor::<_, LegacyKeyAdapter>::new(
921                self.provider().tx().cursor_dup_read::<tables::StoragesTrie>()?,
922                hashed_address,
923            ))
924        };
925        Ok(InMemoryTrieCursor::new_storage(cursor, &overlay.trie_updates, hashed_address))
926    }
927}
928
929impl<Provider, N: NodePrimitives> HashedCursorFactory for OverlayStateProvider<Provider, N>
930where
931    Provider: Deref,
932    Provider::Target: DBProvider
933        + StageCheckpointReader
934        + PruneCheckpointReader
935        + ChangeSetReader
936        + StorageChangeSetReader
937        + BlockNumReader
938        + StorageSettingsCache,
939{
940    type AccountCursor<'a>
941        = <HashedPostStateCursorFactory<
942        DatabaseHashedCursorFactory<&'a <Provider::Target as DbTxProvider>::Tx>,
943        &'a Arc<HashedPostStateSorted>,
944    > as HashedCursorFactory>::AccountCursor<'a>
945    where
946        Self: 'a;
947
948    type StorageCursor<'a>
949        = <HashedPostStateCursorFactory<
950        DatabaseHashedCursorFactory<&'a <Provider::Target as DbTxProvider>::Tx>,
951        &'a Arc<HashedPostStateSorted>,
952    > as HashedCursorFactory>::StorageCursor<'a>
953    where
954        Self: 'a;
955
956    fn hashed_account_cursor(&self) -> Result<Self::AccountCursor<'_>, DatabaseError> {
957        let overlay = self.state_trie_overlay().map_err(into_database_error)?;
958        HashedPostStateCursorFactory::new(
959            DatabaseHashedCursorFactory::new(self.provider().tx()),
960            &overlay.hashed_post_state,
961        )
962        .hashed_account_cursor()
963    }
964
965    fn hashed_storage_cursor(
966        &self,
967        hashed_address: B256,
968    ) -> Result<Self::StorageCursor<'_>, DatabaseError> {
969        let overlay = self.state_trie_overlay().map_err(into_database_error)?;
970        HashedPostStateCursorFactory::new(
971            DatabaseHashedCursorFactory::new(self.provider().tx()),
972            &overlay.hashed_post_state,
973        )
974        .hashed_storage_cursor(hashed_address)
975    }
976}
977
978/// Metrics for overlay state provider factory operations.
979#[derive(Clone, Metrics)]
980#[metrics(scope = "storage.providers.overlay")]
981pub(crate) struct OverlayStateProviderFactoryMetrics {
982    /// Duration of creating the database provider transaction.
983    create_provider_duration: Histogram,
984    /// Overall duration of the [`OverlayStateProviderFactory::database_provider_ro`] call.
985    database_provider_ro_duration: Histogram,
986    /// Number of cache misses when fetching state trie overlays.
987    state_trie_overlay_cache_misses: Counter,
988}
989
990type StateTrieOverlayCache = Arc<DashMap<(BlockHash, BlockHash), StateTrieOverlay>>;
991
992#[derive(Clone, Debug)]
993struct CachedExecutionOverlay {
994    overlay: Arc<ExecutionOverlay>,
995    historical_fallback: Option<HistoricalFallback>,
996}
997
998#[derive(Clone, Copy, Debug)]
999struct HistoricalFallback {
1000    block_number: BlockNumber,
1001    account_history_block_number: Option<BlockNumber>,
1002    storage_history_block_number: Option<BlockNumber>,
1003}
1004
1005type DbStateRoot<'a, TX, A> =
1006    StateRoot<DatabaseTrieCursorFactory<&'a TX, A>, DatabaseHashedCursorFactory<&'a TX>>;
1007type DbStorageRoot<'a, TX, A> =
1008    StorageRoot<DatabaseTrieCursorFactory<&'a TX, A>, DatabaseHashedCursorFactory<&'a TX>>;
1009type DbStorageProof<'a, TX, A> = TrieStorageProof<
1010    'static,
1011    DatabaseTrieCursorFactory<&'a TX, A>,
1012    DatabaseHashedCursorFactory<&'a TX>,
1013>;
1014type DbProof<'a, TX, A> =
1015    Proof<DatabaseTrieCursorFactory<&'a TX, A>, DatabaseHashedCursorFactory<&'a TX>>;
1016
1017#[doc(hidden)]
1018#[derive(Debug)]
1019pub struct OwnedProvider<Provider>(Provider);
1020
1021impl<Provider> Deref for OwnedProvider<Provider> {
1022    type Target = Provider;
1023
1024    fn deref(&self) -> &Self::Target {
1025        &self.0
1026    }
1027}
1028
1029fn into_database_error(error: ProviderError) -> DatabaseError {
1030    match error {
1031        ProviderError::Database(error) => error,
1032        error => DatabaseError::Other(error.to_string()),
1033    }
1034}
1035
1036#[cfg(test)]
1037mod tests {
1038    use super::*;
1039    use crate::{ExecutionOverlay, OverlayManager};
1040    use alloy_eips::BlockNumHash;
1041    use alloy_primitives::{Address, U256};
1042    use reth_chain_state::{test_utils::TestBlockBuilder, ExecutedBlock};
1043    use reth_db_api::{
1044        models::{
1045            storage_sharded_key::StorageShardedKey, AccountBeforeTx, BlockNumberAddress, ShardedKey,
1046        },
1047        tables,
1048        transaction::DbTxMut,
1049        BlockNumberList,
1050    };
1051    use reth_primitives_traits::Account;
1052    use reth_provider::{
1053        test_utils::{create_test_provider_factory, MockNodeTypesWithDB},
1054        BlockWriter, ProviderFactory,
1055    };
1056    use reth_stages_types::{FinishCheckpoint, StageCheckpoint, StageId};
1057    use reth_storage_api::StageCheckpointWriter;
1058    use reth_trie::{
1059        updates::TrieUpdatesSorted, BranchNodeCompact, ComputedTrieData, HashedPostState,
1060        HashedStorage, Nibbles,
1061    };
1062    use revm::{bytecode::Bytecode as RevmBytecode, state::AccountInfo};
1063
1064    fn with_unique_trie_data(
1065        block: &ExecutedBlock<EthPrimitives>,
1066        id: u8,
1067    ) -> ExecutedBlock<EthPrimitives> {
1068        let hashed_address = B256::with_last_byte(id);
1069        let hashed_slot = B256::with_last_byte(id.saturating_add(32));
1070        let hashed_state = HashedPostState::default()
1071            .with_accounts([(hashed_address, Some(Account::default()))])
1072            .with_storages([(
1073                hashed_address,
1074                HashedStorage::from_iter([(hashed_slot, U256::from(id))]),
1075            )])
1076            .into_sorted();
1077        let trie_updates = TrieUpdatesSorted::new(
1078            vec![(
1079                Nibbles::from_nibbles([id]),
1080                Some(BranchNodeCompact::new(0, 0, 0, vec![], None)),
1081            )],
1082            Default::default(),
1083        );
1084
1085        ExecutedBlock::new(
1086            Arc::clone(&block.recovered_block),
1087            Arc::clone(&block.execution_output),
1088            ComputedTrieData::new(Arc::new(hashed_state), Arc::new(trie_updates)),
1089        )
1090    }
1091
1092    fn test_blocks() -> Vec<ExecutedBlock<EthPrimitives>> {
1093        TestBlockBuilder::eth()
1094            .get_executed_blocks(0..5)
1095            .enumerate()
1096            .map(|(index, block)| with_unique_trie_data(&block, index as u8 + 1))
1097            .collect()
1098    }
1099
1100    fn setup_frontiers(
1101        state_trie_tip_index: usize,
1102        finish_tip_index: usize,
1103    ) -> (ProviderFactory<MockNodeTypesWithDB>, Vec<ExecutedBlock<EthPrimitives>>) {
1104        let factory = create_test_provider_factory();
1105        let blocks = test_blocks();
1106        let provider_rw = factory.provider_rw().unwrap();
1107        for block in &blocks[..=finish_tip_index] {
1108            provider_rw.insert_block(block.recovered_block()).unwrap();
1109        }
1110        provider_rw
1111            .save_stage_checkpoint(
1112                StageId::Finish,
1113                StageCheckpoint::new(blocks[finish_tip_index].block_number())
1114                    .with_finish_stage_checkpoint(FinishCheckpoint {
1115                        partial_state_trie: Some(blocks[state_trie_tip_index].block_number()),
1116                    }),
1117            )
1118            .unwrap();
1119        provider_rw.commit().unwrap();
1120
1121        (factory, blocks)
1122    }
1123
1124    fn account_keys(overlay: &StateTrieOverlay) -> Vec<B256> {
1125        overlay.hashed_post_state.accounts.iter().map(|(key, _)| *key).collect()
1126    }
1127
1128    fn account_node_paths(overlay: &StateTrieOverlay) -> Vec<Nibbles> {
1129        overlay.trie_updates.account_nodes_ref().iter().map(|(path, _)| *path).collect()
1130    }
1131
1132    #[test]
1133    fn overlay_cache_is_keyed_by_both_durable_frontiers() {
1134        let (factory, blocks) = setup_frontiers(1, 3);
1135        let manager = OverlayManager::default();
1136        for block in &blocks[2..=3] {
1137            manager.insert_block(block.clone());
1138        }
1139        let state_provider_factory = OverlayStateProviderFactory::new(
1140            factory.clone(),
1141            manager.overlay_builder(blocks[3].recovered_block().hash()),
1142        );
1143
1144        let provider = state_provider_factory.database_provider_ro().unwrap();
1145        let first = provider.state_trie_overlay().unwrap().clone();
1146        assert_eq!(account_keys(&first), vec![B256::with_last_byte(3), B256::with_last_byte(4)]);
1147        drop(provider);
1148
1149        let provider_rw = factory.provider_rw().unwrap();
1150        provider_rw
1151            .save_stage_checkpoint(
1152                StageId::Finish,
1153                StageCheckpoint::new(blocks[3].block_number()).with_finish_stage_checkpoint(
1154                    FinishCheckpoint { partial_state_trie: Some(blocks[2].block_number()) },
1155                ),
1156            )
1157            .unwrap();
1158        provider_rw.commit().unwrap();
1159
1160        let provider = state_provider_factory.database_provider_ro().unwrap();
1161        let second = provider.state_trie_overlay().unwrap().clone();
1162        assert_eq!(account_keys(&second), vec![B256::with_last_byte(4)]);
1163        assert_eq!(account_node_paths(&second), vec![Nibbles::from_nibbles([4])]);
1164        assert_eq!(state_provider_factory.state_trie_overlay_cache.len(), 2);
1165    }
1166
1167    #[test]
1168    fn overlays_are_computed_lazily() {
1169        let (factory, blocks) = setup_frontiers(1, 3);
1170        let manager = OverlayManager::default();
1171        for block in &blocks[2..=3] {
1172            manager.insert_block(block.clone());
1173        }
1174        let state_provider_factory = OverlayStateProviderFactory::new(
1175            factory,
1176            manager.overlay_builder(blocks[3].recovered_block().hash()),
1177        );
1178
1179        let provider = state_provider_factory.database_provider_ro().unwrap();
1180
1181        assert!(provider.state_trie_overlay.get().is_none());
1182        assert!(provider.execution_overlay.get().is_none());
1183        assert!(state_provider_factory.state_trie_overlay_cache.is_empty());
1184
1185        provider.basic_account(&Address::ZERO).unwrap();
1186        assert!(provider.state_trie_overlay.get().is_none());
1187        assert!(provider.execution_overlay.get().is_some());
1188        assert!(state_provider_factory.state_trie_overlay_cache.is_empty());
1189
1190        provider.account_trie_cursor().unwrap();
1191        assert_eq!(state_provider_factory.state_trie_overlay_cache.len(), 1);
1192    }
1193
1194    #[test]
1195    fn lazy_overlays_survive_manager_block_removal() {
1196        let (factory, blocks) = setup_frontiers(1, 1);
1197        let manager = OverlayManager::default();
1198        for block in &blocks[2..=3] {
1199            manager.insert_block(block.clone());
1200        }
1201        let state_provider_factory = OverlayStateProviderFactory::new(
1202            factory,
1203            manager.overlay_builder(blocks[3].recovered_block().hash()),
1204        );
1205        let provider = state_provider_factory.database_provider_ro().unwrap();
1206
1207        manager.remove_blocks(blocks[2..=3].iter().map(|block| block.recovered_block().hash()));
1208
1209        let (execution_overlay, _) = provider.execution_overlay().unwrap();
1210        assert_eq!(
1211            execution_overlay.block_hashes(),
1212            [blocks[2].recovered_block().num_hash(), blocks[3].recovered_block().num_hash()]
1213        );
1214        assert_eq!(
1215            account_keys(provider.state_trie_overlay().unwrap()),
1216            vec![B256::with_last_byte(3), B256::with_last_byte(4)]
1217        );
1218    }
1219
1220    #[test]
1221    fn skipped_state_trie_overlay_is_not_cached_or_used_for_state_roots() {
1222        let (factory, blocks) = setup_frontiers(3, 3);
1223        let manager = OverlayManager::default();
1224        manager.insert_block(blocks[4].clone());
1225        let state_provider_factory = OverlayStateProviderFactory::new(
1226            factory,
1227            manager
1228                .overlay_builder(blocks[4].recovered_block().hash())
1229                .with_skip_overlay_for_reused_sparse_trie(blocks[3].recovered_block().hash()),
1230        );
1231
1232        let provider = state_provider_factory.database_provider_ro().unwrap();
1233        assert!(provider.state_trie_overlay().unwrap().skipped_for_reused_sparse_trie());
1234        assert!(state_provider_factory.state_trie_overlay_cache.is_empty());
1235        assert!(matches!(
1236            provider.state_root(HashedPostState::default()),
1237            Err(ProviderError::UnsupportedProvider)
1238        ));
1239        assert!(state_provider_factory.state_trie_overlay_cache.is_empty());
1240    }
1241
1242    #[test]
1243    fn execution_overlay_readers_use_overlay_first() {
1244        let (factory, _) = setup_frontiers(1, 3);
1245        let address = Address::with_last_byte(1);
1246        let account_info = AccountInfo { nonce: 1, balance: U256::from(2), ..Default::default() };
1247        let block_hash = B256::with_last_byte(3);
1248        let storage_key = B256::with_last_byte(4);
1249        let storage_value = U256::from(5);
1250        let code_hash = B256::with_last_byte(6);
1251        let bytecode = RevmBytecode::new_raw([0x60, 0x01].into());
1252        let mut execution_overlay = ExecutionOverlay::default();
1253        execution_overlay.accounts_mut().insert(address, Some(account_info.clone()));
1254        execution_overlay.block_hashes_mut().push(BlockNumHash::new(1, block_hash));
1255        execution_overlay
1256            .storage_mut()
1257            .entry(address)
1258            .or_default()
1259            .insert(U256::from_be_bytes(storage_key.0), storage_value);
1260        execution_overlay.code_hashes_mut().insert(code_hash, bytecode.clone());
1261        let provider = OverlayStateProvider::<_, EthPrimitives>::new_with_execution(
1262            factory.provider().unwrap(),
1263            Arc::new(execution_overlay),
1264            false,
1265        );
1266
1267        assert_eq!(provider.basic_account(&address).unwrap(), Some(Account::from(account_info)));
1268        assert!(provider.basic_account(&Address::with_last_byte(2)).unwrap().is_none());
1269        assert_eq!(provider.block_hash(1).unwrap(), Some(block_hash));
1270        assert_eq!(provider.canonical_hashes_range(1, 2).unwrap(), vec![block_hash]);
1271        assert_eq!(provider.storage(address, storage_key).unwrap(), Some(storage_value));
1272        assert_eq!(
1273            provider.bytecode_by_hash(&code_hash).unwrap(),
1274            Some(reth_primitives_traits::Bytecode(bytecode))
1275        );
1276    }
1277
1278    #[test]
1279    fn historical_execution_reads_use_history_indexes() {
1280        let (factory, blocks) = setup_frontiers(1, 3);
1281        let address = Address::with_last_byte(1);
1282        let storage_key = B256::with_last_byte(2);
1283        let account = Account { balance: U256::from(10), ..Default::default() };
1284        let storage = U256::from(10);
1285        let provider_rw = factory.provider_rw().unwrap();
1286
1287        provider_rw
1288            .tx_ref()
1289            .put::<tables::AccountsHistory>(
1290                ShardedKey { key: address, highest_block_number: u64::MAX },
1291                BlockNumberList::new([2]).unwrap(),
1292            )
1293            .unwrap();
1294        provider_rw
1295            .tx_ref()
1296            .put::<tables::AccountChangeSets>(2, AccountBeforeTx { address, info: Some(account) })
1297            .unwrap();
1298        provider_rw
1299            .tx_ref()
1300            .put::<tables::PlainAccountState>(
1301                address,
1302                Account { balance: U256::from(20), ..Default::default() },
1303            )
1304            .unwrap();
1305        provider_rw
1306            .tx_ref()
1307            .put::<tables::StoragesHistory>(
1308                StorageShardedKey {
1309                    address,
1310                    sharded_key: ShardedKey { key: storage_key, highest_block_number: u64::MAX },
1311                },
1312                BlockNumberList::new([2]).unwrap(),
1313            )
1314            .unwrap();
1315        provider_rw
1316            .tx_ref()
1317            .put::<tables::StorageChangeSets>(
1318                BlockNumberAddress((2, address)),
1319                reth_primitives_traits::StorageEntry { key: storage_key, value: storage },
1320            )
1321            .unwrap();
1322        provider_rw
1323            .tx_ref()
1324            .put::<tables::PlainStorageState>(
1325                address,
1326                reth_primitives_traits::StorageEntry { key: storage_key, value: U256::from(20) },
1327            )
1328            .unwrap();
1329        provider_rw.commit().unwrap();
1330
1331        let state_provider_factory = OverlayStateProviderFactory::<_, EthPrimitives>::new(
1332            factory,
1333            OverlayManager::default().overlay_builder(blocks[1].recovered_block().hash()),
1334        );
1335        let provider = state_provider_factory.database_provider_ro().unwrap();
1336
1337        assert_eq!(provider.basic_account(&address).unwrap(), Some(account));
1338        assert_eq!(provider.storage(address, storage_key).unwrap(), Some(storage));
1339    }
1340}