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