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 = self.build_overlay(
537                TrieInputSorted::from_unsorted(TrieInput::from_state(hashed_state)),
538                false,
539            )?;
540            Ok(<DbStateRoot<'_, _, A>>::overlay_root_from_nodes(self.provider().tx(), input)?)
541        })
542    }
543
544    fn state_root_from_nodes(&self, input: TrieInput) -> ProviderResult<B256> {
545        reth_trie_db::with_adapter!(self.provider(), |A| {
546            let input = self.build_overlay(TrieInputSorted::from_unsorted(input), false)?;
547            Ok(<DbStateRoot<'_, _, A> as DatabaseStateRoot<_>>::overlay_root_from_nodes(
548                self.provider().tx(),
549                input,
550            )?)
551        })
552    }
553
554    fn state_root_with_updates(
555        &self,
556        hashed_state: HashedPostState,
557    ) -> ProviderResult<(B256, TrieUpdates)> {
558        reth_trie_db::with_adapter!(self.provider(), |A| {
559            let input = self.build_overlay(
560                TrieInputSorted::from_unsorted(TrieInput::from_state(hashed_state)),
561                true,
562            )?;
563            Ok(<DbStateRoot<'_, _, A>>::overlay_root_from_nodes_with_updates(
564                self.provider().tx(),
565                input,
566            )?)
567        })
568    }
569
570    fn state_root_from_nodes_with_updates(
571        &self,
572        input: TrieInput,
573    ) -> ProviderResult<(B256, TrieUpdates)> {
574        reth_trie_db::with_adapter!(self.provider(), |A| {
575            let input = self.build_overlay(TrieInputSorted::from_unsorted(input), true)?;
576            Ok(
577                <DbStateRoot<'_, _, A> as DatabaseStateRoot<_>>::overlay_root_from_nodes_with_updates(
578                    self.provider().tx(),
579                    input,
580                )?,
581            )
582        })
583    }
584}
585
586impl<Provider, N: NodePrimitives> StorageRootProvider for OverlayStateProvider<Provider, N>
587where
588    Provider: Deref,
589    Provider::Target: DBProvider
590        + StageCheckpointReader
591        + PruneCheckpointReader
592        + ChangeSetReader
593        + StorageChangeSetReader
594        + BlockNumReader
595        + StorageSettingsCache,
596{
597    fn storage_root(
598        &self,
599        address: Address,
600        hashed_storage: HashedStorage,
601    ) -> ProviderResult<B256> {
602        reth_trie_db::with_adapter!(self.provider(), |A| {
603            let input = self.build_overlay(
604                TrieInputSorted::from_unsorted(TrieInput::from_state(
605                    HashedPostState::from_hashed_storage(
606                        alloy_primitives::keccak256(address),
607                        hashed_storage,
608                    ),
609                )),
610                false,
611            )?;
612            let hashed_storage = input
613                .state
614                .account_storages()
615                .get(&alloy_primitives::keccak256(address))
616                .cloned()
617                .unwrap_or_default()
618                .into();
619            <DbStorageRoot<'_, _, A>>::overlay_root(self.provider().tx(), address, hashed_storage)
620                .map_err(|err| ProviderError::Database(err.into()))
621        })
622    }
623
624    fn storage_proof(
625        &self,
626        address: Address,
627        slot: B256,
628        hashed_storage: HashedStorage,
629    ) -> ProviderResult<StorageProof> {
630        reth_trie_db::with_adapter!(self.provider(), |A| {
631            let input = self.build_overlay(
632                TrieInputSorted::from_unsorted(TrieInput::from_state(
633                    HashedPostState::from_hashed_storage(
634                        alloy_primitives::keccak256(address),
635                        hashed_storage,
636                    ),
637                )),
638                false,
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_proof(
648                self.provider().tx(),
649                address,
650                slot,
651                hashed_storage,
652            )
653            .map_err(ProviderError::from)
654        })
655    }
656
657    fn storage_multiproof(
658        &self,
659        address: Address,
660        slots: &[B256],
661        hashed_storage: HashedStorage,
662    ) -> ProviderResult<StorageMultiProof> {
663        reth_trie_db::with_adapter!(self.provider(), |A| {
664            let input = self.build_overlay(
665                TrieInputSorted::from_unsorted(TrieInput::from_state(
666                    HashedPostState::from_hashed_storage(
667                        alloy_primitives::keccak256(address),
668                        hashed_storage,
669                    ),
670                )),
671                false,
672            )?;
673            let hashed_storage = input
674                .state
675                .account_storages()
676                .get(&alloy_primitives::keccak256(address))
677                .cloned()
678                .unwrap_or_default()
679                .into();
680            <DbStorageProof<'_, _, A>>::overlay_storage_multiproof(
681                self.provider().tx(),
682                address,
683                slots,
684                hashed_storage,
685            )
686            .map_err(ProviderError::from)
687        })
688    }
689}
690
691impl<Provider, N: NodePrimitives> StateProofProvider for OverlayStateProvider<Provider, N>
692where
693    Provider: Deref,
694    Provider::Target: DBProvider
695        + StageCheckpointReader
696        + PruneCheckpointReader
697        + ChangeSetReader
698        + StorageChangeSetReader
699        + BlockNumReader
700        + StorageSettingsCache,
701{
702    fn proof(
703        &self,
704        input: TrieInput,
705        address: Address,
706        slots: &[B256],
707    ) -> ProviderResult<AccountProof> {
708        reth_trie_db::with_adapter!(self.provider(), |A| {
709            let TrieInputSorted { nodes, state, prefix_sets } =
710                self.build_overlay(TrieInputSorted::from_unsorted(input), false)?;
711            let input = TrieInput::new(
712                Arc::unwrap_or_clone(nodes).into(),
713                Arc::unwrap_or_clone(state).into(),
714                prefix_sets,
715            );
716            let proof = <DbProof<'_, _, A> as DatabaseProof>::from_tx(self.provider().tx());
717            proof.overlay_account_proof(input, address, slots).map_err(ProviderError::from)
718        })
719    }
720
721    fn multiproof(
722        &self,
723        input: TrieInput,
724        targets: MultiProofTargets,
725    ) -> ProviderResult<MultiProof> {
726        reth_trie_db::with_adapter!(self.provider(), |A| {
727            let TrieInputSorted { nodes, state, prefix_sets } =
728                self.build_overlay(TrieInputSorted::from_unsorted(input), false)?;
729            let input = TrieInput::new(
730                Arc::unwrap_or_clone(nodes).into(),
731                Arc::unwrap_or_clone(state).into(),
732                prefix_sets,
733            );
734            let proof = <DbProof<'_, _, A> as DatabaseProof>::from_tx(self.provider().tx());
735            proof.overlay_multiproof(input, targets).map_err(ProviderError::from)
736        })
737    }
738
739    fn multiproof_v2(
740        &self,
741        input: TrieInput,
742        targets: MultiProofTargetsV2,
743    ) -> ProviderResult<DecodedMultiProofV2> {
744        reth_trie_db::with_adapter!(self.provider(), |A| {
745            let TrieInputSorted { nodes, state, prefix_sets } =
746                self.build_overlay(TrieInputSorted::from_unsorted(input), false)?;
747            let input = TrieInput::new(
748                Arc::unwrap_or_clone(nodes).into(),
749                Arc::unwrap_or_clone(state).into(),
750                prefix_sets,
751            );
752            let proof = <DbProof<'_, _, A> as DatabaseProof>::from_tx(self.provider().tx());
753            proof.overlay_multiproof_v2(input, targets).map_err(ProviderError::from)
754        })
755    }
756
757    fn witness(
758        &self,
759        input: TrieInput,
760        target: HashedPostState,
761        mode: ExecutionWitnessMode,
762    ) -> ProviderResult<Vec<alloy_primitives::Bytes>> {
763        reth_trie_db::with_adapter!(self.provider(), |A| {
764            let TrieInputSorted { nodes, state, prefix_sets } =
765                self.build_overlay(TrieInputSorted::from_unsorted(input), false)?;
766            let witness = TrieWitness::new(
767                InMemoryTrieCursorFactory::new(
768                    DatabaseTrieCursorFactory::<_, A>::new(self.provider().tx()),
769                    nodes.as_ref(),
770                ),
771                HashedPostStateCursorFactory::new(
772                    DatabaseHashedCursorFactory::new(self.provider().tx()),
773                    state.as_ref(),
774                ),
775            )
776            .with_prefix_sets_mut(prefix_sets)
777            .with_execution_witness_mode(mode);
778            let witness =
779                if mode.is_canonical() { witness } else { witness.always_include_root_node() };
780            let mut values: Vec<_> = witness.compute(target)?.into_values().collect();
781            if mode.is_canonical() {
782                values.sort_unstable();
783            }
784            Ok(values)
785        })
786    }
787}
788
789impl<Provider, N: NodePrimitives> HashedPostStateProvider for OverlayStateProvider<Provider, N>
790where
791    Provider: Deref,
792    Provider::Target: DBProvider
793        + StageCheckpointReader
794        + PruneCheckpointReader
795        + ChangeSetReader
796        + StorageChangeSetReader
797        + BlockNumReader
798        + StorageSettingsCache,
799{
800    fn hashed_post_state(
801        &self,
802        bundle_state: &revm::database::BundleState,
803    ) -> ProviderResult<HashedPostState> {
804        let mut hashed_state =
805            HashedPostState::from_bundle_state::<KeccakKeyHasher>(bundle_state.state());
806        if !bundle_state
807            .state()
808            .values()
809            .any(|account| account.was_destroyed() && account.original_info.is_some())
810        {
811            return Ok(hashed_state)
812        }
813
814        let overlay_state = self.build_overlay(TrieInputSorted::default(), false)?.state;
815        zero_destroyed_account_storage(
816            &HashedPostStateCursorFactory::new(
817                DatabaseHashedCursorFactory::new(self.provider().tx()),
818                overlay_state.as_ref(),
819            ),
820            bundle_state.state(),
821            &mut hashed_state,
822        )?;
823        Ok(hashed_state)
824    }
825}
826
827impl<Provider, N: NodePrimitives> StateProvider for OverlayStateProvider<Provider, N>
828where
829    Provider: Deref,
830    Provider::Target: DBProvider
831        + HistoryReader
832        + BlockHashReader
833        + StorageSettingsCache
834        + StageCheckpointReader
835        + PruneCheckpointReader
836        + ChangeSetReader
837        + StorageChangeSetReader
838        + BlockNumReader,
839{
840    fn storage(
841        &self,
842        address: Address,
843        storage_key: alloy_primitives::StorageKey,
844    ) -> ProviderResult<Option<alloy_primitives::StorageValue>> {
845        let (overlay, historical_fallback) = self.execution_overlay()?;
846        if let Some(value) = overlay.storage_value(address, U256::from_be_bytes(storage_key.0)) {
847            return Ok(Some(value));
848        }
849        if let Some(historical_fallback) = historical_fallback {
850            return match self.provider().storage_history_info(
851                address,
852                storage_key,
853                historical_fallback.block_number,
854                historical_fallback.storage_history_block_number,
855            )? {
856                HistoryInfo::NotYetWritten => Ok(None),
857                HistoryInfo::InChangeset(changeset_block_number) => self
858                    .provider()
859                    .get_storage_before_block(changeset_block_number, address, storage_key)?
860                    .ok_or_else(|| ProviderError::StorageChangesetNotFound {
861                        block_number: changeset_block_number,
862                        address,
863                        storage_key: Box::new(storage_key),
864                    })
865                    .map(|entry| Some(entry.value)),
866                HistoryInfo::InPlainState | HistoryInfo::MaybeInPlainState => {
867                    self.storage_from_db(address, storage_key, true)
868                }
869            }
870        }
871        self.storage_from_db(address, storage_key, false)
872    }
873}
874
875impl<Provider, N: NodePrimitives> OverlayStateProvider<Provider, N>
876where
877    Provider: Deref,
878    Provider::Target: DBProvider + StorageSettingsCache,
879{
880    fn storage_from_db(
881        &self,
882        address: Address,
883        storage_key: alloy_primitives::StorageKey,
884        zero_if_missing: bool,
885    ) -> ProviderResult<Option<alloy_primitives::StorageValue>> {
886        if self.provider().cached_storage_settings().use_hashed_state() {
887            let hashed_address = alloy_primitives::keccak256(address);
888            let hashed_slot = alloy_primitives::keccak256(storage_key);
889            let mut cursor = self.provider().tx().cursor_dup_read::<tables::HashedStorages>()?;
890            let value = cursor
891                .seek_by_key_subkey(hashed_address, hashed_slot)?
892                .filter(|entry| entry.key == hashed_slot)
893                .map(|entry| entry.value);
894            Ok(value.or_else(|| zero_if_missing.then_some(U256::ZERO)))
895        } else {
896            let mut cursor = self.provider().tx().cursor_dup_read::<tables::PlainStorageState>()?;
897            if let Some(entry) = cursor.seek_by_key_subkey(address, storage_key)? &&
898                entry.key == storage_key
899            {
900                return Ok(Some(entry.value))
901            }
902            Ok(zero_if_missing.then_some(U256::ZERO))
903        }
904    }
905}
906
907impl<Provider, N: NodePrimitives> TrieCursorFactory for OverlayStateProvider<Provider, N>
908where
909    Provider: Deref,
910    Provider::Target: DBProvider
911        + StageCheckpointReader
912        + PruneCheckpointReader
913        + ChangeSetReader
914        + StorageChangeSetReader
915        + BlockNumReader
916        + StorageSettingsCache,
917{
918    type AccountTrieCursor<'a>
919        = InMemoryTrieCursor<'a, Box<dyn TrieCursor + Send + 'a>>
920    where
921        Self: 'a;
922
923    type StorageTrieCursor<'a>
924        = InMemoryTrieCursor<'a, Box<dyn TrieStorageCursor + Send + 'a>>
925    where
926        Self: 'a;
927
928    fn account_trie_cursor(&self) -> Result<Self::AccountTrieCursor<'_>, DatabaseError> {
929        let overlay = self.state_trie_overlay(true).map_err(into_database_error)?;
930        let cursor: Box<dyn TrieCursor + Send> = if self.is_v2 {
931            Box::new(DatabaseAccountTrieCursor::<_, PackedKeyAdapter>::new(
932                self.provider().tx().cursor_read::<PackedAccountsTrie>()?,
933            ))
934        } else {
935            Box::new(DatabaseAccountTrieCursor::<_, LegacyKeyAdapter>::new(
936                self.provider().tx().cursor_read::<tables::AccountsTrie>()?,
937            ))
938        };
939        Ok(InMemoryTrieCursor::new_account(cursor, &overlay.input().nodes))
940    }
941
942    fn storage_trie_cursor(
943        &self,
944        hashed_address: B256,
945    ) -> Result<Self::StorageTrieCursor<'_>, DatabaseError> {
946        let overlay = self.state_trie_overlay(true).map_err(into_database_error)?;
947        let cursor: Box<dyn TrieStorageCursor + Send> = if self.is_v2 {
948            Box::new(DatabaseStorageTrieCursor::<_, PackedKeyAdapter>::new(
949                self.provider().tx().cursor_dup_read::<PackedStoragesTrie>()?,
950                hashed_address,
951            ))
952        } else {
953            Box::new(DatabaseStorageTrieCursor::<_, LegacyKeyAdapter>::new(
954                self.provider().tx().cursor_dup_read::<tables::StoragesTrie>()?,
955                hashed_address,
956            ))
957        };
958        Ok(InMemoryTrieCursor::new_storage(cursor, &overlay.input().nodes, hashed_address))
959    }
960}
961
962impl<Provider, N: NodePrimitives> HashedCursorFactory for OverlayStateProvider<Provider, N>
963where
964    Provider: Deref,
965    Provider::Target: DBProvider
966        + StageCheckpointReader
967        + PruneCheckpointReader
968        + ChangeSetReader
969        + StorageChangeSetReader
970        + BlockNumReader
971        + StorageSettingsCache,
972{
973    type AccountCursor<'a>
974        = <HashedPostStateCursorFactory<
975        DatabaseHashedCursorFactory<&'a <Provider::Target as DbTxProvider>::Tx>,
976        &'a Arc<HashedPostStateSorted>,
977    > as HashedCursorFactory>::AccountCursor<'a>
978    where
979        Self: 'a;
980
981    type StorageCursor<'a>
982        = <HashedPostStateCursorFactory<
983        DatabaseHashedCursorFactory<&'a <Provider::Target as DbTxProvider>::Tx>,
984        &'a Arc<HashedPostStateSorted>,
985    > as HashedCursorFactory>::StorageCursor<'a>
986    where
987        Self: 'a;
988
989    fn hashed_account_cursor(&self) -> Result<Self::AccountCursor<'_>, DatabaseError> {
990        let overlay = self.state_trie_overlay(true).map_err(into_database_error)?;
991        HashedPostStateCursorFactory::new(
992            DatabaseHashedCursorFactory::new(self.provider().tx()),
993            &overlay.input().state,
994        )
995        .hashed_account_cursor()
996    }
997
998    fn hashed_storage_cursor(
999        &self,
1000        hashed_address: B256,
1001    ) -> Result<Self::StorageCursor<'_>, DatabaseError> {
1002        let overlay = self.state_trie_overlay(true).map_err(into_database_error)?;
1003        HashedPostStateCursorFactory::new(
1004            DatabaseHashedCursorFactory::new(self.provider().tx()),
1005            &overlay.input().state,
1006        )
1007        .hashed_storage_cursor(hashed_address)
1008    }
1009}
1010
1011/// Metrics for overlay state provider factory operations.
1012#[derive(Clone, Metrics)]
1013#[metrics(scope = "storage.providers.overlay")]
1014pub(crate) struct OverlayStateProviderFactoryMetrics {
1015    /// Duration of creating the database provider transaction.
1016    create_provider_duration: Histogram,
1017    /// Overall duration of the [`OverlayStateProviderFactory::database_provider_ro`] call.
1018    database_provider_ro_duration: Histogram,
1019    /// Number of cache misses when fetching state trie overlays.
1020    state_trie_overlay_cache_misses: Counter,
1021}
1022
1023type StateTrieOverlayCache = Arc<DashMap<(BlockHash, BlockHash, bool), StateTrieOverlay>>;
1024
1025#[derive(Clone, Debug)]
1026struct CachedExecutionOverlay {
1027    overlay: Arc<ExecutionOverlay>,
1028    historical_fallback: Option<HistoricalFallback>,
1029}
1030
1031#[derive(Clone, Copy, Debug)]
1032struct HistoricalFallback {
1033    block_number: BlockNumber,
1034    account_history_block_number: Option<BlockNumber>,
1035    storage_history_block_number: Option<BlockNumber>,
1036}
1037
1038type DbStateRoot<'a, TX, A> =
1039    StateRoot<DatabaseTrieCursorFactory<&'a TX, A>, DatabaseHashedCursorFactory<&'a TX>>;
1040type DbStorageRoot<'a, TX, A> =
1041    StorageRoot<DatabaseTrieCursorFactory<&'a TX, A>, DatabaseHashedCursorFactory<&'a TX>>;
1042type DbStorageProof<'a, TX, A> = TrieStorageProof<
1043    'static,
1044    DatabaseTrieCursorFactory<&'a TX, A>,
1045    DatabaseHashedCursorFactory<&'a TX>,
1046>;
1047type DbProof<'a, TX, A> =
1048    Proof<DatabaseTrieCursorFactory<&'a TX, A>, DatabaseHashedCursorFactory<&'a TX>>;
1049
1050#[doc(hidden)]
1051#[derive(Debug)]
1052pub struct OwnedProvider<Provider>(Provider);
1053
1054impl<Provider> Deref for OwnedProvider<Provider> {
1055    type Target = Provider;
1056
1057    fn deref(&self) -> &Self::Target {
1058        &self.0
1059    }
1060}
1061
1062fn into_database_error(error: ProviderError) -> DatabaseError {
1063    match error {
1064        ProviderError::Database(error) => error,
1065        error => DatabaseError::Other(error.to_string()),
1066    }
1067}
1068
1069#[cfg(test)]
1070mod tests {
1071    use super::*;
1072    use crate::{ExecutionOverlay, OverlayManager};
1073    use alloy_eips::BlockNumHash;
1074    use alloy_primitives::{Address, U256};
1075    use reth_chain_state::{test_utils::TestBlockBuilder, ExecutedBlock};
1076    use reth_db_api::{
1077        models::{
1078            storage_sharded_key::StorageShardedKey, AccountBeforeTx, BlockNumberAddress, ShardedKey,
1079        },
1080        tables,
1081        transaction::DbTxMut,
1082        BlockNumberList,
1083    };
1084    use reth_primitives_traits::Account;
1085    use reth_provider::{
1086        test_utils::{create_test_provider_factory, MockNodeTypesWithDB},
1087        BlockWriter, ProviderFactory,
1088    };
1089    use reth_stages_types::{FinishCheckpoint, StageCheckpoint, StageId};
1090    use reth_storage_api::StageCheckpointWriter;
1091    use reth_trie::{
1092        updates::TrieUpdatesSorted, BranchNodeCompact, ComputedTrieData, HashedPostState,
1093        HashedStorage, Nibbles,
1094    };
1095    use revm::{bytecode::Bytecode as RevmBytecode, state::AccountInfo};
1096
1097    fn with_unique_trie_data(
1098        block: &ExecutedBlock<EthPrimitives>,
1099        id: u8,
1100    ) -> ExecutedBlock<EthPrimitives> {
1101        let hashed_address = B256::with_last_byte(id);
1102        let hashed_slot = B256::with_last_byte(id.saturating_add(32));
1103        let hashed_state = HashedPostState::default()
1104            .with_accounts([(hashed_address, Some(Account::default()))])
1105            .with_storages([(
1106                hashed_address,
1107                HashedStorage::from_iter([(hashed_slot, U256::from(id))]),
1108            )])
1109            .into_sorted();
1110        let trie_updates = TrieUpdatesSorted::new(
1111            vec![(
1112                Nibbles::from_nibbles([id]),
1113                Some(BranchNodeCompact::new(0, 0, 0, vec![], None)),
1114            )],
1115            Default::default(),
1116        );
1117
1118        ExecutedBlock::new(
1119            Arc::clone(&block.recovered_block),
1120            Arc::clone(&block.execution_output),
1121            ComputedTrieData::new(Arc::new(hashed_state), Arc::new(trie_updates)),
1122        )
1123    }
1124
1125    fn test_blocks() -> Vec<ExecutedBlock<EthPrimitives>> {
1126        TestBlockBuilder::eth()
1127            .get_executed_blocks(0..5)
1128            .enumerate()
1129            .map(|(index, block)| with_unique_trie_data(&block, index as u8 + 1))
1130            .collect()
1131    }
1132
1133    fn setup_frontiers(
1134        state_trie_tip_index: usize,
1135        finish_tip_index: usize,
1136    ) -> (ProviderFactory<MockNodeTypesWithDB>, Vec<ExecutedBlock<EthPrimitives>>) {
1137        let factory = create_test_provider_factory();
1138        let blocks = test_blocks();
1139        let provider_rw = factory.provider_rw().unwrap();
1140        for block in &blocks[..=finish_tip_index] {
1141            provider_rw.insert_block(block.recovered_block()).unwrap();
1142        }
1143        provider_rw
1144            .save_stage_checkpoint(
1145                StageId::Finish,
1146                StageCheckpoint::new(blocks[finish_tip_index].block_number())
1147                    .with_finish_stage_checkpoint(FinishCheckpoint {
1148                        partial_state_trie: Some(blocks[state_trie_tip_index].block_number()),
1149                    }),
1150            )
1151            .unwrap();
1152        provider_rw.commit().unwrap();
1153
1154        (factory, blocks)
1155    }
1156
1157    fn account_keys(overlay: &StateTrieOverlay) -> Vec<B256> {
1158        overlay.input().state.accounts.iter().map(|(key, _)| *key).collect()
1159    }
1160
1161    fn account_node_paths(overlay: &StateTrieOverlay) -> Vec<Nibbles> {
1162        overlay.input().nodes.account_nodes_ref().iter().map(|(path, _)| *path).collect()
1163    }
1164
1165    #[test]
1166    fn overlay_cache_is_keyed_by_both_durable_frontiers() {
1167        let (factory, blocks) = setup_frontiers(1, 3);
1168        let manager = OverlayManager::default();
1169        for block in &blocks[2..=3] {
1170            manager.insert_block(block.clone());
1171        }
1172        let state_provider_factory = OverlayStateProviderFactory::new(
1173            factory.clone(),
1174            manager.overlay_builder(blocks[3].recovered_block().hash()),
1175        );
1176
1177        let provider = state_provider_factory.database_provider_ro().unwrap();
1178        let first = provider.state_trie_overlay(false).unwrap().clone();
1179        assert_eq!(account_keys(&first), vec![B256::with_last_byte(3), B256::with_last_byte(4)]);
1180        drop(provider);
1181
1182        let provider_rw = factory.provider_rw().unwrap();
1183        provider_rw
1184            .save_stage_checkpoint(
1185                StageId::Finish,
1186                StageCheckpoint::new(blocks[3].block_number()).with_finish_stage_checkpoint(
1187                    FinishCheckpoint { partial_state_trie: Some(blocks[2].block_number()) },
1188                ),
1189            )
1190            .unwrap();
1191        provider_rw.commit().unwrap();
1192
1193        let provider = state_provider_factory.database_provider_ro().unwrap();
1194        let second = provider.state_trie_overlay(false).unwrap().clone();
1195        assert_eq!(account_keys(&second), vec![B256::with_last_byte(4)]);
1196        assert_eq!(account_node_paths(&second), vec![Nibbles::from_nibbles([4])]);
1197        assert_eq!(state_provider_factory.state_trie_overlay_cache.len(), 2);
1198    }
1199
1200    #[test]
1201    fn overlays_are_computed_lazily() {
1202        let (factory, blocks) = setup_frontiers(1, 3);
1203        let manager = OverlayManager::default();
1204        for block in &blocks[2..=3] {
1205            manager.insert_block(block.clone());
1206        }
1207        let state_provider_factory = OverlayStateProviderFactory::new(
1208            factory,
1209            manager.overlay_builder(blocks[3].recovered_block().hash()),
1210        );
1211
1212        let provider = state_provider_factory.database_provider_ro().unwrap();
1213
1214        assert!(provider.state_trie_overlay.get().is_none());
1215        assert!(provider.execution_overlay.get().is_none());
1216        assert!(state_provider_factory.state_trie_overlay_cache.is_empty());
1217
1218        provider.basic_account(&Address::ZERO).unwrap();
1219        assert!(provider.state_trie_overlay.get().is_none());
1220        assert!(provider.execution_overlay.get().is_some());
1221        assert!(state_provider_factory.state_trie_overlay_cache.is_empty());
1222
1223        provider.account_trie_cursor().unwrap();
1224        assert_eq!(state_provider_factory.state_trie_overlay_cache.len(), 1);
1225    }
1226
1227    #[test]
1228    fn state_trie_overlay_cache_is_keyed_by_trie_changesets() {
1229        let (factory, blocks) = setup_frontiers(1, 3);
1230        let manager = OverlayManager::default();
1231        for block in &blocks[2..=3] {
1232            manager.insert_block(block.clone());
1233        }
1234        let state_provider_factory = OverlayStateProviderFactory::new(
1235            factory,
1236            manager.overlay_builder(blocks[3].recovered_block().hash()),
1237        );
1238        let provider = state_provider_factory.database_provider_ro().unwrap();
1239
1240        provider.state_trie_overlay(false).unwrap();
1241        provider.state_trie_overlay(true).unwrap();
1242
1243        assert_eq!(state_provider_factory.state_trie_overlay_cache.len(), 2);
1244    }
1245
1246    #[test]
1247    fn supplied_state_trie_overlay_is_available_in_both_modes() {
1248        let (factory, _) = setup_frontiers(1, 1);
1249        let provider = factory.provider().unwrap();
1250        let provider = OverlayStateProvider::<&_, EthPrimitives>::new_with_state_trie(
1251            &provider,
1252            StateTrieOverlay::new(TrieInputSorted::default()),
1253            false,
1254        );
1255
1256        assert!(provider.state_trie_overlay(false).is_ok());
1257        assert!(provider.state_trie_overlay(true).is_ok());
1258    }
1259
1260    #[test]
1261    fn lazy_overlays_survive_manager_block_removal() {
1262        let (factory, blocks) = setup_frontiers(1, 1);
1263        let manager = OverlayManager::default();
1264        for block in &blocks[2..=3] {
1265            manager.insert_block(block.clone());
1266        }
1267        let state_provider_factory = OverlayStateProviderFactory::new(
1268            factory,
1269            manager.overlay_builder(blocks[3].recovered_block().hash()),
1270        );
1271        let provider = state_provider_factory.database_provider_ro().unwrap();
1272
1273        manager.remove_blocks(blocks[2..=3].iter().map(|block| block.recovered_block().hash()));
1274
1275        let (execution_overlay, _) = provider.execution_overlay().unwrap();
1276        assert_eq!(
1277            execution_overlay.block_hashes(),
1278            [blocks[2].recovered_block().num_hash(), blocks[3].recovered_block().num_hash()]
1279        );
1280        assert_eq!(
1281            account_keys(provider.state_trie_overlay(false).unwrap()),
1282            vec![B256::with_last_byte(3), B256::with_last_byte(4)]
1283        );
1284    }
1285
1286    #[test]
1287    fn skipped_state_trie_overlay_is_not_cached_or_used_for_state_roots() {
1288        let (factory, blocks) = setup_frontiers(3, 3);
1289        let manager = OverlayManager::default();
1290        manager.insert_block(blocks[4].clone());
1291        let state_provider_factory = OverlayStateProviderFactory::new(
1292            factory,
1293            manager
1294                .overlay_builder(blocks[4].recovered_block().hash())
1295                .with_skip_overlay_for_reused_sparse_trie(blocks[3].recovered_block().hash()),
1296        );
1297
1298        let provider = state_provider_factory.database_provider_ro().unwrap();
1299        assert!(provider.state_trie_overlay(false).unwrap().skipped_for_reused_sparse_trie());
1300        assert!(state_provider_factory.state_trie_overlay_cache.is_empty());
1301        assert!(matches!(
1302            provider.state_root(HashedPostState::default()),
1303            Err(ProviderError::UnsupportedProvider)
1304        ));
1305        assert!(state_provider_factory.state_trie_overlay_cache.is_empty());
1306    }
1307
1308    #[test]
1309    fn execution_overlay_readers_use_overlay_first() {
1310        let (factory, _) = setup_frontiers(1, 3);
1311        let address = Address::with_last_byte(1);
1312        let account_info = AccountInfo { nonce: 1, balance: U256::from(2), ..Default::default() };
1313        let block_hash = B256::with_last_byte(3);
1314        let storage_key = B256::with_last_byte(4);
1315        let storage_value = U256::from(5);
1316        let code_hash = B256::with_last_byte(6);
1317        let bytecode = RevmBytecode::new_raw([0x60, 0x01].into());
1318        let mut execution_overlay = ExecutionOverlay::default();
1319        execution_overlay.accounts_mut().insert(address, Some(account_info.clone()));
1320        execution_overlay.block_hashes_mut().push(BlockNumHash::new(1, block_hash));
1321        execution_overlay
1322            .storage_mut()
1323            .entry(address)
1324            .or_default()
1325            .insert(U256::from_be_bytes(storage_key.0), storage_value);
1326        execution_overlay.code_hashes_mut().insert(code_hash, bytecode.clone());
1327        let provider = OverlayStateProvider::<_, EthPrimitives>::new_with_execution(
1328            factory.provider().unwrap(),
1329            Arc::new(execution_overlay),
1330            false,
1331        );
1332
1333        assert_eq!(provider.basic_account(&address).unwrap(), Some(Account::from(account_info)));
1334        assert!(provider.basic_account(&Address::with_last_byte(2)).unwrap().is_none());
1335        assert_eq!(provider.block_hash(1).unwrap(), Some(block_hash));
1336        assert_eq!(provider.canonical_hashes_range(1, 2).unwrap(), vec![block_hash]);
1337        assert_eq!(provider.storage(address, storage_key).unwrap(), Some(storage_value));
1338        assert_eq!(
1339            provider.bytecode_by_hash(&code_hash).unwrap(),
1340            Some(reth_primitives_traits::Bytecode(bytecode))
1341        );
1342    }
1343
1344    #[test]
1345    fn historical_execution_reads_use_history_indexes() {
1346        let (factory, blocks) = setup_frontiers(1, 3);
1347        let address = Address::with_last_byte(1);
1348        let storage_key = B256::with_last_byte(2);
1349        let account = Account { balance: U256::from(10), ..Default::default() };
1350        let storage = U256::from(10);
1351        let provider_rw = factory.provider_rw().unwrap();
1352
1353        provider_rw
1354            .tx_ref()
1355            .put::<tables::AccountsHistory>(
1356                ShardedKey { key: address, highest_block_number: u64::MAX },
1357                BlockNumberList::new([2]).unwrap(),
1358            )
1359            .unwrap();
1360        provider_rw
1361            .tx_ref()
1362            .put::<tables::AccountChangeSets>(2, AccountBeforeTx { address, info: Some(account) })
1363            .unwrap();
1364        provider_rw
1365            .tx_ref()
1366            .put::<tables::PlainAccountState>(
1367                address,
1368                Account { balance: U256::from(20), ..Default::default() },
1369            )
1370            .unwrap();
1371        provider_rw
1372            .tx_ref()
1373            .put::<tables::StoragesHistory>(
1374                StorageShardedKey {
1375                    address,
1376                    sharded_key: ShardedKey { key: storage_key, highest_block_number: u64::MAX },
1377                },
1378                BlockNumberList::new([2]).unwrap(),
1379            )
1380            .unwrap();
1381        provider_rw
1382            .tx_ref()
1383            .put::<tables::StorageChangeSets>(
1384                BlockNumberAddress((2, address)),
1385                reth_primitives_traits::StorageEntry { key: storage_key, value: storage },
1386            )
1387            .unwrap();
1388        provider_rw
1389            .tx_ref()
1390            .put::<tables::PlainStorageState>(
1391                address,
1392                reth_primitives_traits::StorageEntry { key: storage_key, value: U256::from(20) },
1393            )
1394            .unwrap();
1395        provider_rw.commit().unwrap();
1396
1397        let state_provider_factory = OverlayStateProviderFactory::<_, EthPrimitives>::new(
1398            factory,
1399            OverlayManager::default().overlay_builder(blocks[1].recovered_block().hash()),
1400        );
1401        let provider = state_provider_factory.database_provider_ro().unwrap();
1402
1403        assert_eq!(provider.basic_account(&address).unwrap(), Some(account));
1404        assert_eq!(provider.storage(address, storage_key).unwrap(), Some(storage));
1405    }
1406}