reth_provider/providers/
blockchain_provider.rs

1#![allow(unused)]
2use crate::{
3    providers::{ConsistentProvider, ProviderNodeTypes, StaticFileProvider},
4    AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
5    BlockSource, CanonChainTracker, CanonStateNotifications, CanonStateSubscriptions,
6    ChainSpecProvider, ChainStateBlockReader, ChangeSetReader, DatabaseProvider,
7    DatabaseProviderFactory, FullProvider, HashedPostStateProvider, HeaderProvider, ProviderError,
8    ProviderFactory, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt,
9    StageCheckpointReader, StateProviderBox, StateProviderFactory, StateReader,
10    StaticFileProviderFactory, TransactionVariant, TransactionsProvider,
11};
12use alloy_consensus::{transaction::TransactionMeta, Header};
13use alloy_eips::{
14    eip4895::{Withdrawal, Withdrawals},
15    BlockHashOrNumber, BlockId, BlockNumHash, BlockNumberOrTag,
16};
17use alloy_primitives::{Address, BlockHash, BlockNumber, Sealable, TxHash, TxNumber, B256, U256};
18use alloy_rpc_types_engine::ForkchoiceState;
19use reth_chain_state::{
20    BlockState, CanonicalInMemoryState, ForkChoiceNotifications, ForkChoiceSubscriptions,
21    MemoryOverlayStateProvider,
22};
23use reth_chainspec::{ChainInfo, EthereumHardforks};
24use reth_db_api::{
25    models::{AccountBeforeTx, BlockNumberAddress, StoredBlockBodyIndices},
26    transaction::DbTx,
27    Database,
28};
29use reth_ethereum_primitives::{Block, EthPrimitives, Receipt, TransactionSigned};
30use reth_evm::{ConfigureEvm, EvmEnv};
31use reth_execution_types::ExecutionOutcome;
32use reth_node_types::{BlockTy, HeaderTy, NodeTypesWithDB, ReceiptTy, TxTy};
33use reth_primitives_traits::{
34    Account, BlockBody, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader, StorageEntry,
35};
36use reth_prune_types::{PruneCheckpoint, PruneSegment};
37use reth_stages_types::{StageCheckpoint, StageId};
38use reth_storage_api::{
39    BlockBodyIndicesProvider, DBProvider, NodePrimitivesProvider, StorageChangeSetReader,
40};
41use reth_storage_errors::provider::ProviderResult;
42use reth_trie::{HashedPostState, KeccakKeyHasher};
43use revm_database::BundleState;
44use std::{
45    ops::{Add, RangeBounds, RangeInclusive, Sub},
46    sync::Arc,
47    time::Instant,
48};
49use tracing::trace;
50
51/// The main type for interacting with the blockchain.
52///
53/// This type serves as the main entry point for interacting with the blockchain and provides data
54/// from database storage and from the blockchain tree (pending state etc.) It is a simple wrapper
55/// type that holds an instance of the database and the blockchain tree.
56#[derive(Debug)]
57pub struct BlockchainProvider<N: NodeTypesWithDB> {
58    /// Provider factory used to access the database.
59    pub(crate) database: ProviderFactory<N>,
60    /// Tracks the chain info wrt forkchoice updates and in memory canonical
61    /// state.
62    pub(crate) canonical_in_memory_state: CanonicalInMemoryState<N::Primitives>,
63}
64
65impl<N: NodeTypesWithDB> Clone for BlockchainProvider<N> {
66    fn clone(&self) -> Self {
67        Self {
68            database: self.database.clone(),
69            canonical_in_memory_state: self.canonical_in_memory_state.clone(),
70        }
71    }
72}
73
74impl<N: ProviderNodeTypes> BlockchainProvider<N> {
75    /// Create a new [`BlockchainProvider`] using only the storage, fetching the latest
76    /// header from the database to initialize the provider.
77    pub fn new(storage: ProviderFactory<N>) -> ProviderResult<Self> {
78        let provider = storage.provider()?;
79        let best = provider.chain_info()?;
80        match provider.header_by_number(best.best_number)? {
81            Some(header) => {
82                drop(provider);
83                Ok(Self::with_latest(storage, SealedHeader::new(header, best.best_hash))?)
84            }
85            None => Err(ProviderError::HeaderNotFound(best.best_number.into())),
86        }
87    }
88
89    /// Create new provider instance that wraps the database and the blockchain tree, using the
90    /// provided latest header to initialize the chain info tracker.
91    ///
92    /// This returns a `ProviderResult` since it tries the retrieve the last finalized header from
93    /// `database`.
94    pub fn with_latest(
95        storage: ProviderFactory<N>,
96        latest: SealedHeader<HeaderTy<N>>,
97    ) -> ProviderResult<Self> {
98        let provider = storage.provider()?;
99        let finalized_header = provider
100            .last_finalized_block_number()?
101            .map(|num| provider.sealed_header(num))
102            .transpose()?
103            .flatten();
104        let safe_header = provider
105            .last_safe_block_number()?
106            .or_else(|| {
107                // for the purpose of this we can also use the finalized block if we don't have the
108                // safe block
109                provider.last_finalized_block_number().ok().flatten()
110            })
111            .map(|num| provider.sealed_header(num))
112            .transpose()?
113            .flatten();
114        Ok(Self {
115            database: storage,
116            canonical_in_memory_state: CanonicalInMemoryState::with_head(
117                latest,
118                finalized_header,
119                safe_header,
120            ),
121        })
122    }
123
124    /// Gets a clone of `canonical_in_memory_state`.
125    pub fn canonical_in_memory_state(&self) -> CanonicalInMemoryState<N::Primitives> {
126        self.canonical_in_memory_state.clone()
127    }
128
129    /// Returns a provider with a created `DbTx` inside, which allows fetching data from the
130    /// database using different types of providers. Example: [`HeaderProvider`]
131    /// [`BlockHashReader`]. This may fail if the inner read database transaction fails to open.
132    #[track_caller]
133    pub fn consistent_provider(&self) -> ProviderResult<ConsistentProvider<N>> {
134        ConsistentProvider::new(self.database.clone(), self.canonical_in_memory_state())
135    }
136
137    /// This uses a given [`BlockState`] to initialize a state provider for that block.
138    fn block_state_provider(
139        &self,
140        state: &BlockState<N::Primitives>,
141    ) -> ProviderResult<MemoryOverlayStateProvider<N::Primitives>> {
142        let anchor_hash = state.anchor().hash;
143        let latest_historical = self.database.history_by_block_hash(anchor_hash)?;
144        Ok(state.state_provider(latest_historical))
145    }
146
147    /// Return the last N blocks of state, recreating the [`ExecutionOutcome`].
148    ///
149    /// If the range is empty, or there are no blocks for the given range, then this returns `None`.
150    pub fn get_state(
151        &self,
152        range: RangeInclusive<BlockNumber>,
153    ) -> ProviderResult<Option<ExecutionOutcome<ReceiptTy<N>>>> {
154        self.consistent_provider()?.get_state(range)
155    }
156}
157
158impl<N: NodeTypesWithDB> NodePrimitivesProvider for BlockchainProvider<N> {
159    type Primitives = N::Primitives;
160}
161
162impl<N: ProviderNodeTypes> DatabaseProviderFactory for BlockchainProvider<N> {
163    type DB = N::DB;
164    type Provider = <ProviderFactory<N> as DatabaseProviderFactory>::Provider;
165    type ProviderRW = <ProviderFactory<N> as DatabaseProviderFactory>::ProviderRW;
166
167    fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
168        self.database.database_provider_ro()
169    }
170
171    fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
172        self.database.database_provider_rw()
173    }
174}
175
176impl<N: ProviderNodeTypes> StaticFileProviderFactory for BlockchainProvider<N> {
177    fn static_file_provider(&self) -> StaticFileProvider<Self::Primitives> {
178        self.database.static_file_provider()
179    }
180}
181
182impl<N: ProviderNodeTypes> HeaderProvider for BlockchainProvider<N> {
183    type Header = HeaderTy<N>;
184
185    fn header(&self, block_hash: BlockHash) -> ProviderResult<Option<Self::Header>> {
186        self.consistent_provider()?.header(block_hash)
187    }
188
189    fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Self::Header>> {
190        self.consistent_provider()?.header_by_number(num)
191    }
192
193    fn header_td(&self, hash: BlockHash) -> ProviderResult<Option<U256>> {
194        self.consistent_provider()?.header_td(hash)
195    }
196
197    fn header_td_by_number(&self, number: BlockNumber) -> ProviderResult<Option<U256>> {
198        self.consistent_provider()?.header_td_by_number(number)
199    }
200
201    fn headers_range(
202        &self,
203        range: impl RangeBounds<BlockNumber>,
204    ) -> ProviderResult<Vec<Self::Header>> {
205        self.consistent_provider()?.headers_range(range)
206    }
207
208    fn sealed_header(
209        &self,
210        number: BlockNumber,
211    ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
212        self.consistent_provider()?.sealed_header(number)
213    }
214
215    fn sealed_headers_range(
216        &self,
217        range: impl RangeBounds<BlockNumber>,
218    ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
219        self.consistent_provider()?.sealed_headers_range(range)
220    }
221
222    fn sealed_headers_while(
223        &self,
224        range: impl RangeBounds<BlockNumber>,
225        predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
226    ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
227        self.consistent_provider()?.sealed_headers_while(range, predicate)
228    }
229}
230
231impl<N: ProviderNodeTypes> BlockHashReader for BlockchainProvider<N> {
232    fn block_hash(&self, number: u64) -> ProviderResult<Option<B256>> {
233        self.consistent_provider()?.block_hash(number)
234    }
235
236    fn canonical_hashes_range(
237        &self,
238        start: BlockNumber,
239        end: BlockNumber,
240    ) -> ProviderResult<Vec<B256>> {
241        self.consistent_provider()?.canonical_hashes_range(start, end)
242    }
243}
244
245impl<N: ProviderNodeTypes> BlockNumReader for BlockchainProvider<N> {
246    fn chain_info(&self) -> ProviderResult<ChainInfo> {
247        Ok(self.canonical_in_memory_state.chain_info())
248    }
249
250    fn best_block_number(&self) -> ProviderResult<BlockNumber> {
251        Ok(self.canonical_in_memory_state.get_canonical_block_number())
252    }
253
254    fn last_block_number(&self) -> ProviderResult<BlockNumber> {
255        self.database.last_block_number()
256    }
257
258    fn earliest_block_number(&self) -> ProviderResult<BlockNumber> {
259        self.database.earliest_block_number()
260    }
261
262    fn block_number(&self, hash: B256) -> ProviderResult<Option<BlockNumber>> {
263        self.consistent_provider()?.block_number(hash)
264    }
265}
266
267impl<N: ProviderNodeTypes> BlockIdReader for BlockchainProvider<N> {
268    fn pending_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
269        Ok(self.canonical_in_memory_state.pending_block_num_hash())
270    }
271
272    fn safe_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
273        Ok(self.canonical_in_memory_state.get_safe_num_hash())
274    }
275
276    fn finalized_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
277        Ok(self.canonical_in_memory_state.get_finalized_num_hash())
278    }
279}
280
281impl<N: ProviderNodeTypes> BlockReader for BlockchainProvider<N> {
282    type Block = BlockTy<N>;
283
284    fn find_block_by_hash(
285        &self,
286        hash: B256,
287        source: BlockSource,
288    ) -> ProviderResult<Option<Self::Block>> {
289        self.consistent_provider()?.find_block_by_hash(hash, source)
290    }
291
292    fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
293        self.consistent_provider()?.block(id)
294    }
295
296    fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
297        Ok(self.canonical_in_memory_state.pending_recovered_block())
298    }
299
300    fn pending_block_and_receipts(
301        &self,
302    ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
303        Ok(self.canonical_in_memory_state.pending_block_and_receipts())
304    }
305
306    /// Returns the block with senders with matching number or hash from database.
307    ///
308    /// **NOTE: If [`TransactionVariant::NoHash`] is provided then the transactions have invalid
309    /// hashes, since they would need to be calculated on the spot, and we want fast querying.**
310    ///
311    /// Returns `None` if block is not found.
312    fn recovered_block(
313        &self,
314        id: BlockHashOrNumber,
315        transaction_kind: TransactionVariant,
316    ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
317        self.consistent_provider()?.recovered_block(id, transaction_kind)
318    }
319
320    fn sealed_block_with_senders(
321        &self,
322        id: BlockHashOrNumber,
323        transaction_kind: TransactionVariant,
324    ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
325        self.consistent_provider()?.sealed_block_with_senders(id, transaction_kind)
326    }
327
328    fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
329        self.consistent_provider()?.block_range(range)
330    }
331
332    fn block_with_senders_range(
333        &self,
334        range: RangeInclusive<BlockNumber>,
335    ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
336        self.consistent_provider()?.block_with_senders_range(range)
337    }
338
339    fn recovered_block_range(
340        &self,
341        range: RangeInclusive<BlockNumber>,
342    ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
343        self.consistent_provider()?.recovered_block_range(range)
344    }
345
346    fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
347        self.consistent_provider()?.block_by_transaction_id(id)
348    }
349}
350
351impl<N: ProviderNodeTypes> TransactionsProvider for BlockchainProvider<N> {
352    type Transaction = TxTy<N>;
353
354    fn transaction_id(&self, tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
355        self.consistent_provider()?.transaction_id(tx_hash)
356    }
357
358    fn transaction_by_id(&self, id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
359        self.consistent_provider()?.transaction_by_id(id)
360    }
361
362    fn transaction_by_id_unhashed(
363        &self,
364        id: TxNumber,
365    ) -> ProviderResult<Option<Self::Transaction>> {
366        self.consistent_provider()?.transaction_by_id_unhashed(id)
367    }
368
369    fn transaction_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
370        self.consistent_provider()?.transaction_by_hash(hash)
371    }
372
373    fn transaction_by_hash_with_meta(
374        &self,
375        tx_hash: TxHash,
376    ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
377        self.consistent_provider()?.transaction_by_hash_with_meta(tx_hash)
378    }
379
380    fn transaction_block(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
381        self.consistent_provider()?.transaction_block(id)
382    }
383
384    fn transactions_by_block(
385        &self,
386        id: BlockHashOrNumber,
387    ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
388        self.consistent_provider()?.transactions_by_block(id)
389    }
390
391    fn transactions_by_block_range(
392        &self,
393        range: impl RangeBounds<BlockNumber>,
394    ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
395        self.consistent_provider()?.transactions_by_block_range(range)
396    }
397
398    fn transactions_by_tx_range(
399        &self,
400        range: impl RangeBounds<TxNumber>,
401    ) -> ProviderResult<Vec<Self::Transaction>> {
402        self.consistent_provider()?.transactions_by_tx_range(range)
403    }
404
405    fn senders_by_tx_range(
406        &self,
407        range: impl RangeBounds<TxNumber>,
408    ) -> ProviderResult<Vec<Address>> {
409        self.consistent_provider()?.senders_by_tx_range(range)
410    }
411
412    fn transaction_sender(&self, id: TxNumber) -> ProviderResult<Option<Address>> {
413        self.consistent_provider()?.transaction_sender(id)
414    }
415}
416
417impl<N: ProviderNodeTypes> ReceiptProvider for BlockchainProvider<N> {
418    type Receipt = ReceiptTy<N>;
419
420    fn receipt(&self, id: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
421        self.consistent_provider()?.receipt(id)
422    }
423
424    fn receipt_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
425        self.consistent_provider()?.receipt_by_hash(hash)
426    }
427
428    fn receipts_by_block(
429        &self,
430        block: BlockHashOrNumber,
431    ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
432        self.consistent_provider()?.receipts_by_block(block)
433    }
434
435    fn receipts_by_tx_range(
436        &self,
437        range: impl RangeBounds<TxNumber>,
438    ) -> ProviderResult<Vec<Self::Receipt>> {
439        self.consistent_provider()?.receipts_by_tx_range(range)
440    }
441
442    fn receipts_by_block_range(
443        &self,
444        block_range: RangeInclusive<BlockNumber>,
445    ) -> ProviderResult<Vec<Vec<Self::Receipt>>> {
446        self.consistent_provider()?.receipts_by_block_range(block_range)
447    }
448}
449
450impl<N: ProviderNodeTypes> ReceiptProviderIdExt for BlockchainProvider<N> {
451    fn receipts_by_block_id(&self, block: BlockId) -> ProviderResult<Option<Vec<Self::Receipt>>> {
452        self.consistent_provider()?.receipts_by_block_id(block)
453    }
454}
455
456impl<N: ProviderNodeTypes> BlockBodyIndicesProvider for BlockchainProvider<N> {
457    fn block_body_indices(
458        &self,
459        number: BlockNumber,
460    ) -> ProviderResult<Option<StoredBlockBodyIndices>> {
461        self.consistent_provider()?.block_body_indices(number)
462    }
463
464    fn block_body_indices_range(
465        &self,
466        range: RangeInclusive<BlockNumber>,
467    ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
468        self.consistent_provider()?.block_body_indices_range(range)
469    }
470}
471
472impl<N: ProviderNodeTypes> StageCheckpointReader for BlockchainProvider<N> {
473    fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
474        self.consistent_provider()?.get_stage_checkpoint(id)
475    }
476
477    fn get_stage_checkpoint_progress(&self, id: StageId) -> ProviderResult<Option<Vec<u8>>> {
478        self.consistent_provider()?.get_stage_checkpoint_progress(id)
479    }
480
481    fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
482        self.consistent_provider()?.get_all_checkpoints()
483    }
484}
485
486impl<N: ProviderNodeTypes> PruneCheckpointReader for BlockchainProvider<N> {
487    fn get_prune_checkpoint(
488        &self,
489        segment: PruneSegment,
490    ) -> ProviderResult<Option<PruneCheckpoint>> {
491        self.consistent_provider()?.get_prune_checkpoint(segment)
492    }
493
494    fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
495        self.consistent_provider()?.get_prune_checkpoints()
496    }
497}
498
499impl<N: NodeTypesWithDB> ChainSpecProvider for BlockchainProvider<N> {
500    type ChainSpec = N::ChainSpec;
501
502    fn chain_spec(&self) -> Arc<N::ChainSpec> {
503        self.database.chain_spec()
504    }
505}
506
507impl<N: ProviderNodeTypes> StateProviderFactory for BlockchainProvider<N> {
508    /// Storage provider for latest block
509    fn latest(&self) -> ProviderResult<StateProviderBox> {
510        trace!(target: "providers::blockchain", "Getting latest block state provider");
511        // use latest state provider if the head state exists
512        if let Some(state) = self.canonical_in_memory_state.head_state() {
513            trace!(target: "providers::blockchain", "Using head state for latest state provider");
514            Ok(self.block_state_provider(&state)?.boxed())
515        } else {
516            trace!(target: "providers::blockchain", "Using database state for latest state provider");
517            self.database.latest()
518        }
519    }
520
521    /// Returns a [`StateProviderBox`] indexed by the given block number or tag.
522    fn state_by_block_number_or_tag(
523        &self,
524        number_or_tag: BlockNumberOrTag,
525    ) -> ProviderResult<StateProviderBox> {
526        match number_or_tag {
527            BlockNumberOrTag::Latest => self.latest(),
528            BlockNumberOrTag::Finalized => {
529                // we can only get the finalized state by hash, not by num
530                let hash =
531                    self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
532                self.state_by_block_hash(hash)
533            }
534            BlockNumberOrTag::Safe => {
535                // we can only get the safe state by hash, not by num
536                let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
537                self.state_by_block_hash(hash)
538            }
539            BlockNumberOrTag::Earliest => {
540                self.history_by_block_number(self.earliest_block_number()?)
541            }
542            BlockNumberOrTag::Pending => self.pending(),
543            BlockNumberOrTag::Number(num) => {
544                let hash = self
545                    .block_hash(num)?
546                    .ok_or_else(|| ProviderError::HeaderNotFound(num.into()))?;
547                self.state_by_block_hash(hash)
548            }
549        }
550    }
551
552    fn history_by_block_number(
553        &self,
554        block_number: BlockNumber,
555    ) -> ProviderResult<StateProviderBox> {
556        trace!(target: "providers::blockchain", ?block_number, "Getting history by block number");
557        let provider = self.consistent_provider()?;
558        provider.ensure_canonical_block(block_number)?;
559        let hash = provider
560            .block_hash(block_number)?
561            .ok_or_else(|| ProviderError::HeaderNotFound(block_number.into()))?;
562        provider.into_state_provider_at_block_hash(hash)
563    }
564
565    fn history_by_block_hash(&self, block_hash: BlockHash) -> ProviderResult<StateProviderBox> {
566        trace!(target: "providers::blockchain", ?block_hash, "Getting history by block hash");
567        self.consistent_provider()?.into_state_provider_at_block_hash(block_hash)
568    }
569
570    fn state_by_block_hash(&self, hash: BlockHash) -> ProviderResult<StateProviderBox> {
571        trace!(target: "providers::blockchain", ?hash, "Getting state by block hash");
572        if let Ok(state) = self.history_by_block_hash(hash) {
573            // This could be tracked by a historical block
574            Ok(state)
575        } else if let Ok(Some(pending)) = self.pending_state_by_hash(hash) {
576            // .. or this could be the pending state
577            Ok(pending)
578        } else {
579            // if we couldn't find it anywhere, then we should return an error
580            Err(ProviderError::StateForHashNotFound(hash))
581        }
582    }
583
584    /// Returns the state provider for pending state.
585    ///
586    /// If there's no pending block available then the latest state provider is returned:
587    /// [`Self::latest`]
588    fn pending(&self) -> ProviderResult<StateProviderBox> {
589        trace!(target: "providers::blockchain", "Getting provider for pending state");
590
591        if let Some(pending) = self.canonical_in_memory_state.pending_state() {
592            // we have a pending block
593            return Ok(Box::new(self.block_state_provider(&pending)?));
594        }
595
596        // fallback to latest state if the pending block is not available
597        self.latest()
598    }
599
600    fn pending_state_by_hash(&self, block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
601        if let Some(pending) = self.canonical_in_memory_state.pending_state() &&
602            pending.hash() == block_hash
603        {
604            return Ok(Some(Box::new(self.block_state_provider(&pending)?)));
605        }
606        Ok(None)
607    }
608
609    fn maybe_pending(&self) -> ProviderResult<Option<StateProviderBox>> {
610        if let Some(pending) = self.canonical_in_memory_state.pending_state() {
611            return Ok(Some(Box::new(self.block_state_provider(&pending)?)))
612        }
613
614        Ok(None)
615    }
616}
617
618impl<N: NodeTypesWithDB> HashedPostStateProvider for BlockchainProvider<N> {
619    fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState {
620        HashedPostState::from_bundle_state::<KeccakKeyHasher>(bundle_state.state())
621    }
622}
623
624impl<N: ProviderNodeTypes> CanonChainTracker for BlockchainProvider<N> {
625    type Header = HeaderTy<N>;
626
627    fn on_forkchoice_update_received(&self, _update: &ForkchoiceState) {
628        // update timestamp
629        self.canonical_in_memory_state.on_forkchoice_update_received();
630    }
631
632    fn last_received_update_timestamp(&self) -> Option<Instant> {
633        self.canonical_in_memory_state.last_received_update_timestamp()
634    }
635
636    fn set_canonical_head(&self, header: SealedHeader<Self::Header>) {
637        self.canonical_in_memory_state.set_canonical_head(header);
638    }
639
640    fn set_safe(&self, header: SealedHeader<Self::Header>) {
641        self.canonical_in_memory_state.set_safe(header);
642    }
643
644    fn set_finalized(&self, header: SealedHeader<Self::Header>) {
645        self.canonical_in_memory_state.set_finalized(header);
646    }
647}
648
649impl<N: ProviderNodeTypes> BlockReaderIdExt for BlockchainProvider<N>
650where
651    Self: ReceiptProviderIdExt,
652{
653    fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>> {
654        self.consistent_provider()?.block_by_id(id)
655    }
656
657    fn header_by_number_or_tag(
658        &self,
659        id: BlockNumberOrTag,
660    ) -> ProviderResult<Option<Self::Header>> {
661        self.consistent_provider()?.header_by_number_or_tag(id)
662    }
663
664    fn sealed_header_by_number_or_tag(
665        &self,
666        id: BlockNumberOrTag,
667    ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
668        self.consistent_provider()?.sealed_header_by_number_or_tag(id)
669    }
670
671    fn sealed_header_by_id(
672        &self,
673        id: BlockId,
674    ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
675        self.consistent_provider()?.sealed_header_by_id(id)
676    }
677
678    fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>> {
679        self.consistent_provider()?.header_by_id(id)
680    }
681}
682
683impl<N: ProviderNodeTypes> CanonStateSubscriptions for BlockchainProvider<N> {
684    fn subscribe_to_canonical_state(&self) -> CanonStateNotifications<Self::Primitives> {
685        self.canonical_in_memory_state.subscribe_canon_state()
686    }
687}
688
689impl<N: ProviderNodeTypes> ForkChoiceSubscriptions for BlockchainProvider<N> {
690    type Header = HeaderTy<N>;
691
692    fn subscribe_safe_block(&self) -> ForkChoiceNotifications<Self::Header> {
693        let receiver = self.canonical_in_memory_state.subscribe_safe_block();
694        ForkChoiceNotifications(receiver)
695    }
696
697    fn subscribe_finalized_block(&self) -> ForkChoiceNotifications<Self::Header> {
698        let receiver = self.canonical_in_memory_state.subscribe_finalized_block();
699        ForkChoiceNotifications(receiver)
700    }
701}
702
703impl<N: ProviderNodeTypes> StorageChangeSetReader for BlockchainProvider<N> {
704    fn storage_changeset(
705        &self,
706        block_number: BlockNumber,
707    ) -> ProviderResult<Vec<(BlockNumberAddress, StorageEntry)>> {
708        self.consistent_provider()?.storage_changeset(block_number)
709    }
710}
711
712impl<N: ProviderNodeTypes> ChangeSetReader for BlockchainProvider<N> {
713    fn account_block_changeset(
714        &self,
715        block_number: BlockNumber,
716    ) -> ProviderResult<Vec<AccountBeforeTx>> {
717        self.consistent_provider()?.account_block_changeset(block_number)
718    }
719
720    fn get_account_before_block(
721        &self,
722        block_number: BlockNumber,
723        address: Address,
724    ) -> ProviderResult<Option<AccountBeforeTx>> {
725        self.consistent_provider()?.get_account_before_block(block_number, address)
726    }
727}
728
729impl<N: ProviderNodeTypes> AccountReader for BlockchainProvider<N> {
730    /// Get basic account information.
731    fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
732        self.consistent_provider()?.basic_account(address)
733    }
734}
735
736impl<N: ProviderNodeTypes> StateReader for BlockchainProvider<N> {
737    type Receipt = ReceiptTy<N>;
738
739    /// Re-constructs the [`ExecutionOutcome`] from in-memory and database state, if necessary.
740    ///
741    /// If data for the block does not exist, this will return [`None`].
742    ///
743    /// NOTE: This cannot be called safely in a loop outside of the blockchain tree thread. This is
744    /// because the [`CanonicalInMemoryState`] could change during a reorg, causing results to be
745    /// inconsistent. Currently this can safely be called within the blockchain tree thread,
746    /// because the tree thread is responsible for modifying the [`CanonicalInMemoryState`] in the
747    /// first place.
748    fn get_state(
749        &self,
750        block: BlockNumber,
751    ) -> ProviderResult<Option<ExecutionOutcome<Self::Receipt>>> {
752        StateReader::get_state(&self.consistent_provider()?, block)
753    }
754}
755
756#[cfg(test)]
757mod tests {
758    use crate::{
759        providers::BlockchainProvider,
760        test_utils::{
761            create_test_provider_factory, create_test_provider_factory_with_chain_spec,
762            MockNodeTypesWithDB,
763        },
764        BlockWriter, CanonChainTracker, ProviderFactory, StaticFileProviderFactory,
765        StaticFileWriter,
766    };
767    use alloy_eips::{BlockHashOrNumber, BlockNumHash, BlockNumberOrTag};
768    use alloy_primitives::{BlockNumber, TxNumber, B256};
769    use itertools::Itertools;
770    use rand::Rng;
771    use reth_chain_state::{
772        test_utils::TestBlockBuilder, CanonStateNotification, CanonStateSubscriptions,
773        CanonicalInMemoryState, ExecutedBlock, ExecutedBlockWithTrieUpdates, ExecutedTrieUpdates,
774        NewCanonicalChain,
775    };
776    use reth_chainspec::{
777        ChainSpec, ChainSpecBuilder, ChainSpecProvider, EthereumHardfork, MAINNET,
778    };
779    use reth_db_api::{
780        cursor::DbCursorRO,
781        models::{AccountBeforeTx, StoredBlockBodyIndices},
782        tables,
783        transaction::DbTx,
784    };
785    use reth_errors::ProviderError;
786    use reth_ethereum_primitives::{Block, EthPrimitives, Receipt};
787    use reth_execution_types::{Chain, ExecutionOutcome};
788    use reth_primitives_traits::{
789        BlockBody, RecoveredBlock, SealedBlock, SignedTransaction, SignerRecoverable,
790    };
791    use reth_static_file_types::StaticFileSegment;
792    use reth_storage_api::{
793        BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader,
794        BlockReaderIdExt, BlockSource, ChangeSetReader, DBProvider, DatabaseProviderFactory,
795        HeaderProvider, ReceiptProvider, ReceiptProviderIdExt, StateProviderFactory, StateWriter,
796        TransactionVariant, TransactionsProvider,
797    };
798    use reth_testing_utils::generators::{
799        self, random_block, random_block_range, random_changeset_range, random_eoa_accounts,
800        random_receipt, BlockParams, BlockRangeParams,
801    };
802    use revm_database::{BundleState, OriginalValuesKnown};
803    use std::{
804        ops::{Bound, Deref, Range, RangeBounds},
805        sync::Arc,
806        time::Instant,
807    };
808
809    const TEST_BLOCKS_COUNT: usize = 5;
810
811    const TEST_TRANSACTIONS_COUNT: u8 = 4;
812
813    fn random_blocks(
814        rng: &mut impl Rng,
815        database_blocks: usize,
816        in_memory_blocks: usize,
817        requests_count: Option<Range<u8>>,
818        withdrawals_count: Option<Range<u8>>,
819        tx_count: impl RangeBounds<u8>,
820    ) -> (Vec<SealedBlock<Block>>, Vec<SealedBlock<Block>>) {
821        let block_range = (database_blocks + in_memory_blocks - 1) as u64;
822
823        let tx_start = match tx_count.start_bound() {
824            Bound::Included(&n) | Bound::Excluded(&n) => n,
825            Bound::Unbounded => u8::MIN,
826        };
827        let tx_end = match tx_count.end_bound() {
828            Bound::Included(&n) | Bound::Excluded(&n) => n + 1,
829            Bound::Unbounded => u8::MAX,
830        };
831
832        let blocks = random_block_range(
833            rng,
834            0..=block_range,
835            BlockRangeParams {
836                parent: Some(B256::ZERO),
837                tx_count: tx_start..tx_end,
838                requests_count,
839                withdrawals_count,
840            },
841        );
842        let (database_blocks, in_memory_blocks) = blocks.split_at(database_blocks);
843        (database_blocks.to_vec(), in_memory_blocks.to_vec())
844    }
845
846    #[expect(clippy::type_complexity)]
847    fn provider_with_chain_spec_and_random_blocks(
848        rng: &mut impl Rng,
849        chain_spec: Arc<ChainSpec>,
850        database_blocks: usize,
851        in_memory_blocks: usize,
852        block_range_params: BlockRangeParams,
853    ) -> eyre::Result<(
854        BlockchainProvider<MockNodeTypesWithDB>,
855        Vec<SealedBlock<Block>>,
856        Vec<SealedBlock<Block>>,
857        Vec<Vec<Receipt>>,
858    )> {
859        let (database_blocks, in_memory_blocks) = random_blocks(
860            rng,
861            database_blocks,
862            in_memory_blocks,
863            block_range_params.requests_count,
864            block_range_params.withdrawals_count,
865            block_range_params.tx_count,
866        );
867
868        let receipts: Vec<Vec<_>> = database_blocks
869            .iter()
870            .chain(in_memory_blocks.iter())
871            .map(|block| block.body().transactions.iter())
872            .map(|tx| tx.map(|tx| random_receipt(rng, tx, Some(2), None)).collect())
873            .collect();
874
875        let factory = create_test_provider_factory_with_chain_spec(chain_spec);
876        let provider_rw = factory.database_provider_rw()?;
877
878        // Insert blocks into the database
879        for block in &database_blocks {
880            provider_rw.insert_block(
881                block.clone().try_recover().expect("failed to seal block with senders"),
882            )?;
883        }
884
885        // Insert receipts into the database
886        if let Some(first_block) = database_blocks.first() {
887            provider_rw.write_state(
888                &ExecutionOutcome {
889                    first_block: first_block.number,
890                    receipts: receipts.iter().take(database_blocks.len()).cloned().collect(),
891                    ..Default::default()
892                },
893                OriginalValuesKnown::No,
894            )?;
895        }
896
897        provider_rw.commit()?;
898
899        let provider = BlockchainProvider::new(factory)?;
900
901        // Insert the rest of the blocks and receipts into the in-memory state
902        let chain = NewCanonicalChain::Commit {
903            new: in_memory_blocks
904                .iter()
905                .map(|block| {
906                    let senders = block.senders().expect("failed to recover senders");
907                    let block_receipts = receipts.get(block.number as usize).unwrap().clone();
908                    let execution_outcome =
909                        ExecutionOutcome { receipts: vec![block_receipts], ..Default::default() };
910
911                    ExecutedBlockWithTrieUpdates::new(
912                        Arc::new(RecoveredBlock::new_sealed(block.clone(), senders)),
913                        execution_outcome.into(),
914                        Default::default(),
915                        ExecutedTrieUpdates::empty(),
916                    )
917                })
918                .collect(),
919        };
920        provider.canonical_in_memory_state.update_chain(chain);
921
922        // Get canonical, safe, and finalized blocks
923        let blocks = database_blocks.iter().chain(in_memory_blocks.iter()).collect::<Vec<_>>();
924        let block_count = blocks.len();
925        let canonical_block = blocks.get(block_count - 1).unwrap();
926        let safe_block = blocks.get(block_count - 2).unwrap();
927        let finalized_block = blocks.get(block_count - 3).unwrap();
928
929        // Set the canonical head, safe, and finalized blocks
930        provider.set_canonical_head(canonical_block.clone_sealed_header());
931        provider.set_safe(safe_block.clone_sealed_header());
932        provider.set_finalized(finalized_block.clone_sealed_header());
933
934        Ok((provider, database_blocks.clone(), in_memory_blocks.clone(), receipts))
935    }
936
937    #[expect(clippy::type_complexity)]
938    fn provider_with_random_blocks(
939        rng: &mut impl Rng,
940        database_blocks: usize,
941        in_memory_blocks: usize,
942        block_range_params: BlockRangeParams,
943    ) -> eyre::Result<(
944        BlockchainProvider<MockNodeTypesWithDB>,
945        Vec<SealedBlock<Block>>,
946        Vec<SealedBlock<Block>>,
947        Vec<Vec<Receipt>>,
948    )> {
949        provider_with_chain_spec_and_random_blocks(
950            rng,
951            MAINNET.clone(),
952            database_blocks,
953            in_memory_blocks,
954            block_range_params,
955        )
956    }
957
958    /// This will persist the last block in-memory and delete it from
959    /// `canonical_in_memory_state` right after a database read transaction is created.
960    ///
961    /// This simulates a RPC method having a different view than when its database transaction was
962    /// created.
963    fn persist_block_after_db_tx_creation(
964        provider: BlockchainProvider<MockNodeTypesWithDB>,
965        block_number: BlockNumber,
966    ) {
967        let hook_provider = provider.clone();
968        provider.database.db_ref().set_post_transaction_hook(Box::new(move || {
969            if let Some(state) = hook_provider.canonical_in_memory_state.head_state() &&
970                state.anchor().number + 1 == block_number
971            {
972                let mut lowest_memory_block =
973                    state.parent_state_chain().last().expect("qed").block();
974                let num_hash = lowest_memory_block.recovered_block().num_hash();
975
976                let mut execution_output = (*lowest_memory_block.execution_output).clone();
977                execution_output.first_block = lowest_memory_block.recovered_block().number;
978                lowest_memory_block.execution_output = Arc::new(execution_output);
979
980                // Push to disk
981                let provider_rw = hook_provider.database_provider_rw().unwrap();
982                provider_rw.save_blocks(vec![lowest_memory_block]).unwrap();
983                provider_rw.commit().unwrap();
984
985                // Remove from memory
986                hook_provider.canonical_in_memory_state.remove_persisted_blocks(num_hash);
987            }
988        }));
989    }
990
991    #[test]
992    fn test_block_reader_find_block_by_hash() -> eyre::Result<()> {
993        // Initialize random number generator and provider factory
994        let mut rng = generators::rng();
995        let factory = create_test_provider_factory();
996
997        // Generate 10 random blocks and split into database and in-memory blocks
998        let blocks = random_block_range(
999            &mut rng,
1000            0..=10,
1001            BlockRangeParams { parent: Some(B256::ZERO), tx_count: 0..1, ..Default::default() },
1002        );
1003        let (database_blocks, in_memory_blocks) = blocks.split_at(5);
1004
1005        // Insert first 5 blocks into the database
1006        let provider_rw = factory.provider_rw()?;
1007        for block in database_blocks {
1008            provider_rw.insert_block(
1009                block.clone().try_recover().expect("failed to seal block with senders"),
1010            )?;
1011        }
1012        provider_rw.commit()?;
1013
1014        // Create a new provider
1015        let provider = BlockchainProvider::new(factory)?;
1016
1017        // Useful blocks
1018        let first_db_block = database_blocks.first().unwrap();
1019        let first_in_mem_block = in_memory_blocks.first().unwrap();
1020        let last_in_mem_block = in_memory_blocks.last().unwrap();
1021
1022        // No block in memory before setting in memory state
1023        assert_eq!(provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Any)?, None);
1024        assert_eq!(
1025            provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Canonical)?,
1026            None
1027        );
1028        // No pending block in memory
1029        assert_eq!(
1030            provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Pending)?,
1031            None
1032        );
1033
1034        // Insert first block into the in-memory state
1035        let in_memory_block_senders =
1036            first_in_mem_block.senders().expect("failed to recover senders");
1037        let chain = NewCanonicalChain::Commit {
1038            new: vec![ExecutedBlockWithTrieUpdates::new(
1039                Arc::new(RecoveredBlock::new_sealed(
1040                    first_in_mem_block.clone(),
1041                    in_memory_block_senders,
1042                )),
1043                Default::default(),
1044                Default::default(),
1045                ExecutedTrieUpdates::empty(),
1046            )],
1047        };
1048        provider.canonical_in_memory_state.update_chain(chain);
1049
1050        // Now the block should be found in memory
1051        assert_eq!(
1052            provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Any)?,
1053            Some(first_in_mem_block.clone().into_block())
1054        );
1055        assert_eq!(
1056            provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Canonical)?,
1057            Some(first_in_mem_block.clone().into_block())
1058        );
1059
1060        // Find the first block in database by hash
1061        assert_eq!(
1062            provider.find_block_by_hash(first_db_block.hash(), BlockSource::Any)?,
1063            Some(first_db_block.clone().into_block())
1064        );
1065        assert_eq!(
1066            provider.find_block_by_hash(first_db_block.hash(), BlockSource::Canonical)?,
1067            Some(first_db_block.clone().into_block())
1068        );
1069
1070        // No pending block in database
1071        assert_eq!(provider.find_block_by_hash(first_db_block.hash(), BlockSource::Pending)?, None);
1072
1073        // Insert the last block into the pending state
1074        provider.canonical_in_memory_state.set_pending_block(ExecutedBlockWithTrieUpdates {
1075            block: ExecutedBlock {
1076                recovered_block: Arc::new(RecoveredBlock::new_sealed(
1077                    last_in_mem_block.clone(),
1078                    Default::default(),
1079                )),
1080                execution_output: Default::default(),
1081                hashed_state: Default::default(),
1082            },
1083            trie: ExecutedTrieUpdates::empty(),
1084        });
1085
1086        // Now the last block should be found in memory
1087        assert_eq!(
1088            provider.find_block_by_hash(last_in_mem_block.hash(), BlockSource::Pending)?,
1089            Some(last_in_mem_block.clone().into_block())
1090        );
1091
1092        Ok(())
1093    }
1094
1095    #[test]
1096    fn test_block_reader_block() -> eyre::Result<()> {
1097        // Initialize random number generator and provider factory
1098        let mut rng = generators::rng();
1099        let factory = create_test_provider_factory();
1100
1101        // Generate 10 random blocks and split into database and in-memory blocks
1102        let blocks = random_block_range(
1103            &mut rng,
1104            0..=10,
1105            BlockRangeParams { parent: Some(B256::ZERO), tx_count: 0..1, ..Default::default() },
1106        );
1107        let (database_blocks, in_memory_blocks) = blocks.split_at(5);
1108
1109        // Insert first 5 blocks into the database
1110        let provider_rw = factory.provider_rw()?;
1111        for block in database_blocks {
1112            provider_rw.insert_block(
1113                block.clone().try_recover().expect("failed to seal block with senders"),
1114            )?;
1115        }
1116        provider_rw.commit()?;
1117
1118        // Create a new provider
1119        let provider = BlockchainProvider::new(factory)?;
1120
1121        // First in memory block
1122        let first_in_mem_block = in_memory_blocks.first().unwrap();
1123        // First database block
1124        let first_db_block = database_blocks.first().unwrap();
1125
1126        // First in memory block should not be found yet as not integrated to the in-memory state
1127        assert_eq!(provider.block(BlockHashOrNumber::Hash(first_in_mem_block.hash()))?, None);
1128        assert_eq!(provider.block(BlockHashOrNumber::Number(first_in_mem_block.number))?, None);
1129
1130        // Insert first block into the in-memory state
1131        let in_memory_block_senders =
1132            first_in_mem_block.senders().expect("failed to recover senders");
1133        let chain = NewCanonicalChain::Commit {
1134            new: vec![ExecutedBlockWithTrieUpdates::new(
1135                Arc::new(RecoveredBlock::new_sealed(
1136                    first_in_mem_block.clone(),
1137                    in_memory_block_senders,
1138                )),
1139                Default::default(),
1140                Default::default(),
1141                ExecutedTrieUpdates::empty(),
1142            )],
1143        };
1144        provider.canonical_in_memory_state.update_chain(chain);
1145
1146        // First in memory block should be found
1147        assert_eq!(
1148            provider.block(BlockHashOrNumber::Hash(first_in_mem_block.hash()))?,
1149            Some(first_in_mem_block.clone().into_block())
1150        );
1151        assert_eq!(
1152            provider.block(BlockHashOrNumber::Number(first_in_mem_block.number))?,
1153            Some(first_in_mem_block.clone().into_block())
1154        );
1155
1156        // First database block should be found
1157        assert_eq!(
1158            provider.block(BlockHashOrNumber::Hash(first_db_block.hash()))?,
1159            Some(first_db_block.clone().into_block())
1160        );
1161        assert_eq!(
1162            provider.block(BlockHashOrNumber::Number(first_db_block.number))?,
1163            Some(first_db_block.clone().into_block())
1164        );
1165
1166        Ok(())
1167    }
1168
1169    #[test]
1170    fn test_block_reader_pending_block() -> eyre::Result<()> {
1171        let mut rng = generators::rng();
1172        let (provider, _, _, _) = provider_with_random_blocks(
1173            &mut rng,
1174            TEST_BLOCKS_COUNT,
1175            TEST_BLOCKS_COUNT,
1176            BlockRangeParams::default(),
1177        )?;
1178
1179        // Generate a random block
1180        let mut rng = generators::rng();
1181        let block = random_block(
1182            &mut rng,
1183            0,
1184            BlockParams { parent: Some(B256::ZERO), ..Default::default() },
1185        );
1186
1187        // Set the block as pending
1188        provider.canonical_in_memory_state.set_pending_block(ExecutedBlockWithTrieUpdates {
1189            block: ExecutedBlock {
1190                recovered_block: Arc::new(RecoveredBlock::new_sealed(
1191                    block.clone(),
1192                    block.senders().unwrap(),
1193                )),
1194                execution_output: Default::default(),
1195                hashed_state: Default::default(),
1196            },
1197            trie: ExecutedTrieUpdates::empty(),
1198        });
1199
1200        // Assertions related to the pending block
1201
1202        assert_eq!(
1203            provider.pending_block()?,
1204            Some(RecoveredBlock::new_sealed(block.clone(), block.senders().unwrap()))
1205        );
1206
1207        assert_eq!(
1208            provider.pending_block_and_receipts()?,
1209            Some((RecoveredBlock::new_sealed(block.clone(), block.senders().unwrap()), vec![]))
1210        );
1211
1212        Ok(())
1213    }
1214
1215    #[test]
1216    fn test_block_body_indices() -> eyre::Result<()> {
1217        // Create a new provider
1218        let mut rng = generators::rng();
1219        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1220            &mut rng,
1221            TEST_BLOCKS_COUNT,
1222            TEST_BLOCKS_COUNT,
1223            BlockRangeParams {
1224                tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
1225                ..Default::default()
1226            },
1227        )?;
1228
1229        let first_in_mem_block = in_memory_blocks.first().unwrap();
1230
1231        // Insert the first block into the in-memory state
1232        let in_memory_block_senders =
1233            first_in_mem_block.senders().expect("failed to recover senders");
1234        let chain = NewCanonicalChain::Commit {
1235            new: vec![ExecutedBlockWithTrieUpdates::new(
1236                Arc::new(RecoveredBlock::new_sealed(
1237                    first_in_mem_block.clone(),
1238                    in_memory_block_senders,
1239                )),
1240                Default::default(),
1241                Default::default(),
1242                ExecutedTrieUpdates::empty(),
1243            )],
1244        };
1245        provider.canonical_in_memory_state.update_chain(chain);
1246
1247        let first_db_block = database_blocks.first().unwrap().clone();
1248        let first_in_mem_block = in_memory_blocks.first().unwrap().clone();
1249
1250        // First database block body indices should be found
1251        assert_eq!(
1252            provider.block_body_indices(first_db_block.number)?.unwrap(),
1253            StoredBlockBodyIndices { first_tx_num: 0, tx_count: 4 }
1254        );
1255
1256        // First in-memory block body indices should be found with the first tx after the database
1257        // blocks
1258        assert_eq!(
1259            provider.block_body_indices(first_in_mem_block.number)?.unwrap(),
1260            StoredBlockBodyIndices { first_tx_num: 20, tx_count: 4 }
1261        );
1262
1263        // A random block number should return None as the block is not found
1264        let mut rng = rand::rng();
1265        let random_block_number: u64 = rng.random();
1266        assert_eq!(provider.block_body_indices(random_block_number)?, None);
1267
1268        Ok(())
1269    }
1270
1271    #[test]
1272    fn test_block_hash_reader() -> eyre::Result<()> {
1273        let mut rng = generators::rng();
1274        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1275            &mut rng,
1276            TEST_BLOCKS_COUNT,
1277            TEST_BLOCKS_COUNT,
1278            BlockRangeParams::default(),
1279        )?;
1280
1281        let database_block = database_blocks.first().unwrap().clone();
1282        let in_memory_block = in_memory_blocks.last().unwrap().clone();
1283
1284        assert_eq!(provider.block_hash(database_block.number)?, Some(database_block.hash()));
1285        assert_eq!(provider.block_hash(in_memory_block.number)?, Some(in_memory_block.hash()));
1286
1287        assert_eq!(
1288            provider.canonical_hashes_range(0, 10)?,
1289            [database_blocks, in_memory_blocks]
1290                .concat()
1291                .iter()
1292                .map(|block| block.hash())
1293                .collect::<Vec<_>>()
1294        );
1295
1296        Ok(())
1297    }
1298
1299    #[test]
1300    fn test_header_provider() -> eyre::Result<()> {
1301        let mut rng = generators::rng();
1302        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1303            &mut rng,
1304            TEST_BLOCKS_COUNT,
1305            TEST_BLOCKS_COUNT,
1306            BlockRangeParams::default(),
1307        )?;
1308
1309        let database_block = database_blocks.first().unwrap().clone();
1310        let in_memory_block = in_memory_blocks.last().unwrap().clone();
1311        // make sure that the finalized block is on db
1312        let finalized_block = database_blocks.get(database_blocks.len() - 3).unwrap();
1313        provider.set_finalized(finalized_block.clone_sealed_header());
1314
1315        let blocks = [database_blocks, in_memory_blocks].concat();
1316
1317        assert_eq!(
1318            provider.header_td_by_number(database_block.number)?,
1319            Some(database_block.difficulty)
1320        );
1321
1322        assert_eq!(
1323            provider.header_td_by_number(in_memory_block.number)?,
1324            Some(in_memory_block.difficulty)
1325        );
1326
1327        assert_eq!(
1328            provider.sealed_headers_while(0..=10, |header| header.number <= 8)?,
1329            blocks
1330                .iter()
1331                .take_while(|header| header.number <= 8)
1332                .map(|b| b.clone_sealed_header())
1333                .collect::<Vec<_>>()
1334        );
1335
1336        Ok(())
1337    }
1338
1339    #[tokio::test]
1340    async fn test_canon_state_subscriptions() -> eyre::Result<()> {
1341        let factory = create_test_provider_factory();
1342
1343        // Generate a random block to initialize the blockchain provider.
1344        let mut test_block_builder = TestBlockBuilder::eth();
1345        let block_1 = test_block_builder.generate_random_block(0, B256::ZERO);
1346        let block_hash_1 = block_1.hash();
1347
1348        // Insert and commit the block.
1349        let provider_rw = factory.provider_rw()?;
1350        provider_rw.insert_block(block_1)?;
1351        provider_rw.commit()?;
1352
1353        let provider = BlockchainProvider::new(factory)?;
1354
1355        // Subscribe twice for canonical state updates.
1356        let in_memory_state = provider.canonical_in_memory_state();
1357        let mut rx_1 = provider.subscribe_to_canonical_state();
1358        let mut rx_2 = provider.subscribe_to_canonical_state();
1359
1360        // Send and receive commit notifications.
1361        let block_2 = test_block_builder.generate_random_block(1, block_hash_1);
1362        let chain = Chain::new(vec![block_2], ExecutionOutcome::default(), None);
1363        let commit = CanonStateNotification::Commit { new: Arc::new(chain.clone()) };
1364        in_memory_state.notify_canon_state(commit.clone());
1365        let (notification_1, notification_2) = tokio::join!(rx_1.recv(), rx_2.recv());
1366        assert_eq!(notification_1, Ok(commit.clone()));
1367        assert_eq!(notification_2, Ok(commit.clone()));
1368
1369        // Send and receive re-org notifications.
1370        let block_3 = test_block_builder.generate_random_block(1, block_hash_1);
1371        let block_4 = test_block_builder.generate_random_block(2, block_3.hash());
1372        let new_chain = Chain::new(vec![block_3, block_4], ExecutionOutcome::default(), None);
1373        let re_org =
1374            CanonStateNotification::Reorg { old: Arc::new(chain), new: Arc::new(new_chain) };
1375        in_memory_state.notify_canon_state(re_org.clone());
1376        let (notification_1, notification_2) = tokio::join!(rx_1.recv(), rx_2.recv());
1377        assert_eq!(notification_1, Ok(re_org.clone()));
1378        assert_eq!(notification_2, Ok(re_org.clone()));
1379
1380        Ok(())
1381    }
1382
1383    #[test]
1384    fn test_block_num_reader() -> eyre::Result<()> {
1385        let mut rng = generators::rng();
1386        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1387            &mut rng,
1388            TEST_BLOCKS_COUNT,
1389            TEST_BLOCKS_COUNT,
1390            BlockRangeParams::default(),
1391        )?;
1392
1393        assert_eq!(provider.best_block_number()?, in_memory_blocks.last().unwrap().number);
1394        assert_eq!(provider.last_block_number()?, database_blocks.last().unwrap().number);
1395
1396        let database_block = database_blocks.first().unwrap().clone();
1397        let in_memory_block = in_memory_blocks.first().unwrap().clone();
1398        assert_eq!(provider.block_number(database_block.hash())?, Some(database_block.number));
1399        assert_eq!(provider.block_number(in_memory_block.hash())?, Some(in_memory_block.number));
1400
1401        Ok(())
1402    }
1403
1404    #[test]
1405    fn test_block_reader_id_ext_block_by_id() -> eyre::Result<()> {
1406        let mut rng = generators::rng();
1407        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1408            &mut rng,
1409            TEST_BLOCKS_COUNT,
1410            TEST_BLOCKS_COUNT,
1411            BlockRangeParams::default(),
1412        )?;
1413
1414        let database_block = database_blocks.first().unwrap().clone();
1415        let in_memory_block = in_memory_blocks.last().unwrap().clone();
1416
1417        let block_number = database_block.number;
1418        let block_hash = database_block.hash();
1419
1420        assert_eq!(
1421            provider.block_by_id(block_number.into()).unwrap(),
1422            Some(database_block.clone().into_block())
1423        );
1424        assert_eq!(
1425            provider.block_by_id(block_hash.into()).unwrap(),
1426            Some(database_block.into_block())
1427        );
1428
1429        let block_number = in_memory_block.number;
1430        let block_hash = in_memory_block.hash();
1431        assert_eq!(
1432            provider.block_by_id(block_number.into()).unwrap(),
1433            Some(in_memory_block.clone().into_block())
1434        );
1435        assert_eq!(
1436            provider.block_by_id(block_hash.into()).unwrap(),
1437            Some(in_memory_block.into_block())
1438        );
1439
1440        Ok(())
1441    }
1442
1443    #[test]
1444    fn test_block_reader_id_ext_header_by_number_or_tag() -> eyre::Result<()> {
1445        let mut rng = generators::rng();
1446        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1447            &mut rng,
1448            TEST_BLOCKS_COUNT,
1449            TEST_BLOCKS_COUNT,
1450            BlockRangeParams::default(),
1451        )?;
1452
1453        let database_block = database_blocks.first().unwrap().clone();
1454
1455        let in_memory_block_count = in_memory_blocks.len();
1456        let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
1457        let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
1458        let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();
1459
1460        let block_number = database_block.number;
1461        assert_eq!(
1462            provider.header_by_number_or_tag(block_number.into()).unwrap(),
1463            Some(database_block.header().clone())
1464        );
1465        assert_eq!(
1466            provider.sealed_header_by_number_or_tag(block_number.into())?,
1467            Some(database_block.clone_sealed_header())
1468        );
1469
1470        assert_eq!(
1471            provider.header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
1472            Some(canonical_block.header().clone())
1473        );
1474        assert_eq!(
1475            provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
1476            Some(canonical_block.clone_sealed_header())
1477        );
1478
1479        assert_eq!(
1480            provider.header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
1481            Some(safe_block.header().clone())
1482        );
1483        assert_eq!(
1484            provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
1485            Some(safe_block.clone_sealed_header())
1486        );
1487
1488        assert_eq!(
1489            provider.header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
1490            Some(finalized_block.header().clone())
1491        );
1492        assert_eq!(
1493            provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
1494            Some(finalized_block.clone_sealed_header())
1495        );
1496
1497        Ok(())
1498    }
1499
1500    #[test]
1501    fn test_block_reader_id_ext_header_by_id() -> eyre::Result<()> {
1502        let mut rng = generators::rng();
1503        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1504            &mut rng,
1505            TEST_BLOCKS_COUNT,
1506            TEST_BLOCKS_COUNT,
1507            BlockRangeParams::default(),
1508        )?;
1509
1510        let database_block = database_blocks.first().unwrap().clone();
1511        let in_memory_block = in_memory_blocks.last().unwrap().clone();
1512
1513        let block_number = database_block.number;
1514        let block_hash = database_block.hash();
1515
1516        assert_eq!(
1517            provider.header_by_id(block_number.into()).unwrap(),
1518            Some(database_block.header().clone())
1519        );
1520        assert_eq!(
1521            provider.sealed_header_by_id(block_number.into()).unwrap(),
1522            Some(database_block.clone_sealed_header())
1523        );
1524
1525        assert_eq!(
1526            provider.header_by_id(block_hash.into()).unwrap(),
1527            Some(database_block.header().clone())
1528        );
1529        assert_eq!(
1530            provider.sealed_header_by_id(block_hash.into()).unwrap(),
1531            Some(database_block.clone_sealed_header())
1532        );
1533
1534        let block_number = in_memory_block.number;
1535        let block_hash = in_memory_block.hash();
1536
1537        assert_eq!(
1538            provider.header_by_id(block_number.into()).unwrap(),
1539            Some(in_memory_block.header().clone())
1540        );
1541        assert_eq!(
1542            provider.sealed_header_by_id(block_number.into()).unwrap(),
1543            Some(in_memory_block.clone_sealed_header())
1544        );
1545
1546        assert_eq!(
1547            provider.header_by_id(block_hash.into()).unwrap(),
1548            Some(in_memory_block.header().clone())
1549        );
1550        assert_eq!(
1551            provider.sealed_header_by_id(block_hash.into()).unwrap(),
1552            Some(in_memory_block.clone_sealed_header())
1553        );
1554
1555        Ok(())
1556    }
1557
1558    #[test]
1559    fn test_receipt_provider_id_ext_receipts_by_block_id() -> eyre::Result<()> {
1560        let mut rng = generators::rng();
1561        let (provider, database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
1562            &mut rng,
1563            TEST_BLOCKS_COUNT,
1564            TEST_BLOCKS_COUNT,
1565            BlockRangeParams { tx_count: 1..3, ..Default::default() },
1566        )?;
1567
1568        let database_block = database_blocks.first().unwrap().clone();
1569        let in_memory_block = in_memory_blocks.last().unwrap().clone();
1570
1571        let block_number = database_block.number;
1572        let block_hash = database_block.hash();
1573
1574        assert!(!receipts.get(database_block.number as usize).unwrap().is_empty());
1575        assert!(!provider
1576            .receipts_by_number_or_tag(database_block.number.into())?
1577            .unwrap()
1578            .is_empty());
1579
1580        assert_eq!(
1581            provider.receipts_by_block_id(block_number.into())?.unwrap(),
1582            receipts.get(block_number as usize).unwrap().clone()
1583        );
1584        assert_eq!(
1585            provider.receipts_by_block_id(block_hash.into())?.unwrap(),
1586            receipts.get(block_number as usize).unwrap().clone()
1587        );
1588
1589        let block_number = in_memory_block.number;
1590        let block_hash = in_memory_block.hash();
1591
1592        assert_eq!(
1593            provider.receipts_by_block_id(block_number.into())?.unwrap(),
1594            receipts.get(block_number as usize).unwrap().clone()
1595        );
1596        assert_eq!(
1597            provider.receipts_by_block_id(block_hash.into())?.unwrap(),
1598            receipts.get(block_number as usize).unwrap().clone()
1599        );
1600
1601        Ok(())
1602    }
1603
1604    #[test]
1605    fn test_receipt_provider_id_ext_receipts_by_block_number_or_tag() -> eyre::Result<()> {
1606        let mut rng = generators::rng();
1607        let (provider, database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
1608            &mut rng,
1609            TEST_BLOCKS_COUNT,
1610            TEST_BLOCKS_COUNT,
1611            BlockRangeParams { tx_count: 1..3, ..Default::default() },
1612        )?;
1613
1614        let database_block = database_blocks.first().unwrap().clone();
1615
1616        let in_memory_block_count = in_memory_blocks.len();
1617        let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
1618        let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
1619        let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();
1620
1621        assert!(!receipts.get(database_block.number as usize).unwrap().is_empty());
1622        assert!(!provider
1623            .receipts_by_number_or_tag(database_block.number.into())?
1624            .unwrap()
1625            .is_empty());
1626
1627        assert_eq!(
1628            provider.receipts_by_number_or_tag(database_block.number.into())?.unwrap(),
1629            receipts.get(database_block.number as usize).unwrap().clone()
1630        );
1631        assert_eq!(
1632            provider.receipts_by_number_or_tag(BlockNumberOrTag::Latest)?.unwrap(),
1633            receipts.get(canonical_block.number as usize).unwrap().clone()
1634        );
1635        assert_eq!(
1636            provider.receipts_by_number_or_tag(BlockNumberOrTag::Safe)?.unwrap(),
1637            receipts.get(safe_block.number as usize).unwrap().clone()
1638        );
1639        assert_eq!(
1640            provider.receipts_by_number_or_tag(BlockNumberOrTag::Finalized)?.unwrap(),
1641            receipts.get(finalized_block.number as usize).unwrap().clone()
1642        );
1643
1644        Ok(())
1645    }
1646
1647    #[test]
1648    fn test_changeset_reader() -> eyre::Result<()> {
1649        let mut rng = generators::rng();
1650
1651        let (database_blocks, in_memory_blocks) =
1652            random_blocks(&mut rng, TEST_BLOCKS_COUNT, 1, None, None, 0..1);
1653
1654        let first_database_block = database_blocks.first().map(|block| block.number).unwrap();
1655        let last_database_block = database_blocks.last().map(|block| block.number).unwrap();
1656        let first_in_memory_block = in_memory_blocks.first().map(|block| block.number).unwrap();
1657
1658        let accounts = random_eoa_accounts(&mut rng, 2);
1659
1660        let (database_changesets, database_state) = random_changeset_range(
1661            &mut rng,
1662            &database_blocks,
1663            accounts.into_iter().map(|(address, account)| (address, (account, Vec::new()))),
1664            0..0,
1665            0..0,
1666        );
1667        let (in_memory_changesets, in_memory_state) = random_changeset_range(
1668            &mut rng,
1669            &in_memory_blocks,
1670            database_state
1671                .iter()
1672                .map(|(address, (account, storage))| (*address, (*account, storage.clone()))),
1673            0..0,
1674            0..0,
1675        );
1676
1677        let factory = create_test_provider_factory();
1678
1679        let provider_rw = factory.provider_rw()?;
1680        provider_rw.append_blocks_with_state(
1681            database_blocks
1682                .into_iter()
1683                .map(|b| b.try_recover().expect("failed to seal block with senders"))
1684                .collect(),
1685            &ExecutionOutcome {
1686                bundle: BundleState::new(
1687                    database_state.into_iter().map(|(address, (account, _))| {
1688                        (address, None, Some(account.into()), Default::default())
1689                    }),
1690                    database_changesets
1691                        .iter()
1692                        .map(|block_changesets| {
1693                            block_changesets.iter().map(|(address, account, _)| {
1694                                (*address, Some(Some((*account).into())), [])
1695                            })
1696                        })
1697                        .collect::<Vec<_>>(),
1698                    Vec::new(),
1699                ),
1700                first_block: first_database_block,
1701                ..Default::default()
1702            },
1703            Default::default(),
1704        )?;
1705        provider_rw.commit()?;
1706
1707        let provider = BlockchainProvider::new(factory)?;
1708
1709        let in_memory_changesets = in_memory_changesets.into_iter().next().unwrap();
1710        let chain = NewCanonicalChain::Commit {
1711            new: vec![in_memory_blocks
1712                .first()
1713                .map(|block| {
1714                    let senders = block.senders().expect("failed to recover senders");
1715                    ExecutedBlockWithTrieUpdates::new(
1716                        Arc::new(RecoveredBlock::new_sealed(block.clone(), senders)),
1717                        Arc::new(ExecutionOutcome {
1718                            bundle: BundleState::new(
1719                                in_memory_state.into_iter().map(|(address, (account, _))| {
1720                                    (address, None, Some(account.into()), Default::default())
1721                                }),
1722                                [in_memory_changesets.iter().map(|(address, account, _)| {
1723                                    (*address, Some(Some((*account).into())), Vec::new())
1724                                })],
1725                                [],
1726                            ),
1727                            first_block: first_in_memory_block,
1728                            ..Default::default()
1729                        }),
1730                        Default::default(),
1731                        ExecutedTrieUpdates::empty(),
1732                    )
1733                })
1734                .unwrap()],
1735        };
1736        provider.canonical_in_memory_state.update_chain(chain);
1737
1738        assert_eq!(
1739            provider.account_block_changeset(last_database_block).unwrap(),
1740            database_changesets
1741                .into_iter()
1742                .next_back()
1743                .unwrap()
1744                .into_iter()
1745                .sorted_by_key(|(address, _, _)| *address)
1746                .map(|(address, account, _)| AccountBeforeTx { address, info: Some(account) })
1747                .collect::<Vec<_>>()
1748        );
1749        assert_eq!(
1750            provider.account_block_changeset(first_in_memory_block).unwrap(),
1751            in_memory_changesets
1752                .into_iter()
1753                .sorted_by_key(|(address, _, _)| *address)
1754                .map(|(address, account, _)| AccountBeforeTx { address, info: Some(account) })
1755                .collect::<Vec<_>>()
1756        );
1757
1758        Ok(())
1759    }
1760
1761    #[test]
1762    fn test_state_provider_factory() -> eyre::Result<()> {
1763        let mut rng = generators::rng();
1764
1765        // test in-memory state use-cases
1766        let (in_memory_provider, _, in_memory_blocks, _) = provider_with_random_blocks(
1767            &mut rng,
1768            TEST_BLOCKS_COUNT,
1769            TEST_BLOCKS_COUNT,
1770            BlockRangeParams::default(),
1771        )?;
1772
1773        // test database state use-cases
1774        let (only_database_provider, database_blocks, _, _) = provider_with_random_blocks(
1775            &mut rng,
1776            TEST_BLOCKS_COUNT,
1777            0,
1778            BlockRangeParams::default(),
1779        )?;
1780
1781        let blocks = [database_blocks.clone(), in_memory_blocks.clone()].concat();
1782        let first_in_memory_block = in_memory_blocks.first().unwrap();
1783        let first_db_block = database_blocks.first().unwrap();
1784
1785        // test latest state
1786        assert_eq!(
1787            first_in_memory_block.hash(),
1788            in_memory_provider.latest().unwrap().block_hash(first_in_memory_block.number)?.unwrap()
1789        );
1790        // test latest falls back to database state when there's no in-memory block
1791        assert_eq!(
1792            first_db_block.hash(),
1793            only_database_provider.latest().unwrap().block_hash(first_db_block.number)?.unwrap()
1794        );
1795
1796        // test history by block number
1797        assert_eq!(
1798            first_in_memory_block.hash(),
1799            in_memory_provider
1800                .history_by_block_number(first_in_memory_block.number)?
1801                .block_hash(first_in_memory_block.number)?
1802                .unwrap()
1803        );
1804        assert_eq!(
1805            first_db_block.hash(),
1806            only_database_provider
1807                .history_by_block_number(first_db_block.number)?
1808                .block_hash(first_db_block.number)?
1809                .unwrap()
1810        );
1811        assert_eq!(
1812            first_in_memory_block.hash(),
1813            in_memory_provider
1814                .history_by_block_hash(first_in_memory_block.hash())?
1815                .block_hash(first_in_memory_block.number)?
1816                .unwrap()
1817        );
1818        assert!(only_database_provider.history_by_block_hash(B256::random()).is_err());
1819
1820        // test state by block hash
1821        assert_eq!(
1822            first_in_memory_block.hash(),
1823            in_memory_provider
1824                .state_by_block_hash(first_in_memory_block.hash())?
1825                .block_hash(first_in_memory_block.number)?
1826                .unwrap()
1827        );
1828        assert_eq!(
1829            first_db_block.hash(),
1830            only_database_provider
1831                .state_by_block_hash(first_db_block.hash())?
1832                .block_hash(first_db_block.number)?
1833                .unwrap()
1834        );
1835        assert!(only_database_provider.state_by_block_hash(B256::random()).is_err());
1836
1837        // test pending without pending state- falls back to latest
1838        assert_eq!(
1839            first_in_memory_block.hash(),
1840            in_memory_provider
1841                .pending()
1842                .unwrap()
1843                .block_hash(first_in_memory_block.number)
1844                .unwrap()
1845                .unwrap()
1846        );
1847
1848        // adding a pending block to state can test pending() and  pending_state_by_hash() function
1849        let pending_block = database_blocks[database_blocks.len() - 1].clone();
1850        only_database_provider.canonical_in_memory_state.set_pending_block(
1851            ExecutedBlockWithTrieUpdates {
1852                block: ExecutedBlock {
1853                    recovered_block: Arc::new(RecoveredBlock::new_sealed(
1854                        pending_block.clone(),
1855                        Default::default(),
1856                    )),
1857                    execution_output: Default::default(),
1858                    hashed_state: Default::default(),
1859                },
1860                trie: ExecutedTrieUpdates::empty(),
1861            },
1862        );
1863
1864        assert_eq!(
1865            pending_block.hash(),
1866            only_database_provider
1867                .pending()
1868                .unwrap()
1869                .block_hash(pending_block.number)
1870                .unwrap()
1871                .unwrap()
1872        );
1873
1874        assert_eq!(
1875            pending_block.hash(),
1876            only_database_provider
1877                .pending_state_by_hash(pending_block.hash())?
1878                .unwrap()
1879                .block_hash(pending_block.number)?
1880                .unwrap()
1881        );
1882
1883        // test state by block number or tag
1884        assert_eq!(
1885            first_in_memory_block.hash(),
1886            in_memory_provider
1887                .state_by_block_number_or_tag(BlockNumberOrTag::Number(
1888                    first_in_memory_block.number
1889                ))?
1890                .block_hash(first_in_memory_block.number)?
1891                .unwrap()
1892        );
1893        assert_eq!(
1894            first_in_memory_block.hash(),
1895            in_memory_provider
1896                .state_by_block_number_or_tag(BlockNumberOrTag::Latest)?
1897                .block_hash(first_in_memory_block.number)?
1898                .unwrap()
1899        );
1900        // test state by block tag for safe block
1901        let safe_block = in_memory_blocks[in_memory_blocks.len() - 2].clone();
1902        in_memory_provider.canonical_in_memory_state.set_safe(safe_block.clone_sealed_header());
1903        assert_eq!(
1904            safe_block.hash(),
1905            in_memory_provider
1906                .state_by_block_number_or_tag(BlockNumberOrTag::Safe)?
1907                .block_hash(safe_block.number)?
1908                .unwrap()
1909        );
1910        // test state by block tag for finalized block
1911        let finalized_block = in_memory_blocks[in_memory_blocks.len() - 3].clone();
1912        in_memory_provider
1913            .canonical_in_memory_state
1914            .set_finalized(finalized_block.clone_sealed_header());
1915        assert_eq!(
1916            finalized_block.hash(),
1917            in_memory_provider
1918                .state_by_block_number_or_tag(BlockNumberOrTag::Finalized)?
1919                .block_hash(finalized_block.number)?
1920                .unwrap()
1921        );
1922        // test state by block tag for earliest block
1923        let earliest_block = blocks.first().unwrap().clone();
1924        assert_eq!(
1925            earliest_block.hash(),
1926            only_database_provider
1927                .state_by_block_number_or_tag(BlockNumberOrTag::Earliest)?
1928                .block_hash(earliest_block.number)?
1929                .unwrap()
1930        );
1931
1932        Ok(())
1933    }
1934
1935    #[test]
1936    fn test_block_id_reader() -> eyre::Result<()> {
1937        // Create a new provider
1938        let mut rng = generators::rng();
1939        let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
1940            &mut rng,
1941            TEST_BLOCKS_COUNT,
1942            TEST_BLOCKS_COUNT,
1943            BlockRangeParams::default(),
1944        )?;
1945
1946        // Set the pending block in memory
1947        let pending_block = in_memory_blocks.last().unwrap();
1948        provider.canonical_in_memory_state.set_pending_block(ExecutedBlockWithTrieUpdates {
1949            block: ExecutedBlock {
1950                recovered_block: Arc::new(RecoveredBlock::new_sealed(
1951                    pending_block.clone(),
1952                    Default::default(),
1953                )),
1954                execution_output: Default::default(),
1955                hashed_state: Default::default(),
1956            },
1957            trie: ExecutedTrieUpdates::empty(),
1958        });
1959
1960        // Set the safe block in memory
1961        let safe_block = in_memory_blocks[in_memory_blocks.len() - 2].clone();
1962        provider.canonical_in_memory_state.set_safe(safe_block.clone_sealed_header());
1963
1964        // Set the finalized block in memory
1965        let finalized_block = in_memory_blocks[in_memory_blocks.len() - 3].clone();
1966        provider.canonical_in_memory_state.set_finalized(finalized_block.clone_sealed_header());
1967
1968        // Verify the pending block number and hash
1969        assert_eq!(
1970            provider.pending_block_num_hash()?,
1971            Some(BlockNumHash { number: pending_block.number, hash: pending_block.hash() })
1972        );
1973
1974        // Verify the safe block number and hash
1975        assert_eq!(
1976            provider.safe_block_num_hash()?,
1977            Some(BlockNumHash { number: safe_block.number, hash: safe_block.hash() })
1978        );
1979
1980        // Verify the finalized block number and hash
1981        assert_eq!(
1982            provider.finalized_block_num_hash()?,
1983            Some(BlockNumHash { number: finalized_block.number, hash: finalized_block.hash() })
1984        );
1985
1986        Ok(())
1987    }
1988
1989    macro_rules! test_by_tx_range {
1990        ([$(($method:ident, $data_extractor:expr)),* $(,)?]) => {{
1991
1992            // Get the number methods being tested.
1993            // Since each method tested will move a block from memory to storage, this ensures we have enough.
1994            let extra_blocks = [$(stringify!($method)),*].len();
1995
1996            let mut rng = generators::rng();
1997            let (provider, mut database_blocks, mut in_memory_blocks, receipts) = provider_with_random_blocks(
1998                &mut rng,
1999                TEST_BLOCKS_COUNT,
2000                TEST_BLOCKS_COUNT + extra_blocks,
2001                BlockRangeParams {
2002                    tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2003                    ..Default::default()
2004                },
2005            )?;
2006
2007            $(
2008                // Since data moves for each tried method, need to recalculate everything
2009                let db_tx_count =
2010                    database_blocks.iter().map(|b| b.transaction_count()).sum::<usize>() as u64;
2011                let in_mem_tx_count =
2012                    in_memory_blocks.iter().map(|b| b.transaction_count()).sum::<usize>() as u64;
2013
2014                let db_range = 0..=(db_tx_count - 1);
2015                let in_mem_range = db_tx_count..=(in_mem_tx_count + db_range.end());
2016
2017                // Retrieve the expected database data
2018                let database_data =
2019                    database_blocks.iter().flat_map(|b| $data_extractor(b, &receipts)).collect::<Vec<_>>();
2020                assert_eq!(provider.$method(db_range.clone())?, database_data, "full db data");
2021
2022                // Retrieve the expected in-memory data
2023                let in_memory_data =
2024                    in_memory_blocks.iter().flat_map(|b| $data_extractor(b, &receipts)).collect::<Vec<_>>();
2025                assert_eq!(provider.$method(in_mem_range.clone())?, in_memory_data, "full mem data");
2026
2027                // Test partial in-memory range
2028                assert_eq!(
2029                    &provider.$method(in_mem_range.start() + 1..=in_mem_range.end() - 1)?,
2030                    &in_memory_data[1..in_memory_data.len() - 1],
2031                    "partial mem data"
2032                );
2033
2034                // Test range in memory to unbounded end
2035                assert_eq!(provider.$method(in_mem_range.start() + 1..)?, &in_memory_data[1..], "unbounded mem data");
2036
2037                // Test last element in-memory
2038                assert_eq!(provider.$method(in_mem_range.end()..)?, &in_memory_data[in_memory_data.len() -1 ..], "last mem data");
2039
2040                // Test range that spans database and in-memory with unbounded end
2041                assert_eq!(
2042                    provider.$method(in_mem_range.start() - 2..)?,
2043                    database_data[database_data.len() - 2..]
2044                        .iter()
2045                        .chain(&in_memory_data[..])
2046                        .cloned()
2047                        .collect::<Vec<_>>(),
2048                    "unbounded span data"
2049                );
2050
2051                // Test range that spans database and in-memory
2052                {
2053                    // This block will be persisted to disk and removed from memory AFTER the first database query. This ensures that we query the in-memory state before the database avoiding any race condition.
2054                    persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2055
2056                    assert_eq!(
2057                        provider.$method(in_mem_range.start() - 2..=in_mem_range.end() - 1)?,
2058                        database_data[database_data.len() - 2..]
2059                            .iter()
2060                            .chain(&in_memory_data[..in_memory_data.len() - 1])
2061                            .cloned()
2062                            .collect::<Vec<_>>(),
2063                        "span data"
2064                    );
2065
2066                    // Adjust our blocks accordingly
2067                    database_blocks.push(in_memory_blocks.remove(0));
2068                }
2069
2070                // Test invalid range
2071                let start_tx_num = u64::MAX;
2072                let end_tx_num = u64::MAX;
2073                let result = provider.$method(start_tx_num..end_tx_num)?;
2074                assert!(result.is_empty(), "No data should be found for an invalid transaction range");
2075
2076                // Test empty range
2077                let result = provider.$method(in_mem_range.end()+10..in_mem_range.end()+20)?;
2078                assert!(result.is_empty(), "No data should be found for an empty transaction range");
2079            )*
2080        }};
2081    }
2082
2083    #[test]
2084    fn test_methods_by_tx_range() -> eyre::Result<()> {
2085        test_by_tx_range!([
2086            (senders_by_tx_range, |block: &SealedBlock<Block>, _: &Vec<Vec<Receipt>>| block
2087                .senders()
2088                .unwrap()),
2089            (transactions_by_tx_range, |block: &SealedBlock<Block>, _: &Vec<Vec<Receipt>>| block
2090                .body()
2091                .transactions
2092                .clone()),
2093            (receipts_by_tx_range, |block: &SealedBlock<Block>, receipts: &Vec<Vec<Receipt>>| {
2094                receipts[block.number as usize].clone()
2095            })
2096        ]);
2097
2098        Ok(())
2099    }
2100
2101    macro_rules! test_by_block_range {
2102        ([$(($method:ident, $data_extractor:expr)),* $(,)?]) => {{
2103            // Get the number methods being tested.
2104            // Since each method tested will move a block from memory to storage, this ensures we have enough.
2105            let extra_blocks = [$(stringify!($method)),*].len();
2106
2107            let mut rng = generators::rng();
2108            let (provider, mut database_blocks, mut in_memory_blocks, _) = provider_with_random_blocks(
2109                &mut rng,
2110                TEST_BLOCKS_COUNT,
2111                TEST_BLOCKS_COUNT + extra_blocks,
2112                BlockRangeParams {
2113                    tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2114                    ..Default::default()
2115                },
2116            )?;
2117
2118            $(
2119                // Since data moves for each tried method, need to recalculate everything
2120                let db_block_count = database_blocks.len() as u64;
2121                let in_mem_block_count = in_memory_blocks.len() as u64;
2122
2123                let db_range = 0..=db_block_count - 1;
2124                let in_mem_range = db_block_count..=(in_mem_block_count + db_range.end());
2125
2126                // Retrieve the expected database data
2127                let database_data =
2128                    database_blocks.iter().map(|b| $data_extractor(b)).collect::<Vec<_>>();
2129                assert_eq!(provider.$method(db_range.clone())?, database_data);
2130
2131                // Retrieve the expected in-memory data
2132                let in_memory_data =
2133                    in_memory_blocks.iter().map(|b| $data_extractor(b)).collect::<Vec<_>>();
2134                assert_eq!(provider.$method(in_mem_range.clone())?, in_memory_data);
2135
2136                // Test partial in-memory range
2137                assert_eq!(
2138                    &provider.$method(in_mem_range.start() + 1..=in_mem_range.end() - 1)?,
2139                    &in_memory_data[1..in_memory_data.len() - 1]
2140                );
2141
2142                // Test range that spans database and in-memory
2143                {
2144
2145                    // This block will be persisted to disk and removed from memory AFTER the first database query. This ensures that we query the in-memory state before the database avoiding any race condition.
2146                    persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2147
2148                    assert_eq!(
2149                        provider.$method(in_mem_range.start() - 2..=in_mem_range.end() - 1)?,
2150                        database_data[database_data.len() - 2..]
2151                            .iter()
2152                            .chain(&in_memory_data[..in_memory_data.len() - 1])
2153                            .cloned()
2154                            .collect::<Vec<_>>()
2155                    );
2156
2157                    // Adjust our blocks accordingly
2158                    database_blocks.push(in_memory_blocks.remove(0));
2159                }
2160
2161                // Test invalid range
2162                let start_block_num = u64::MAX;
2163                let end_block_num = u64::MAX;
2164                let result = provider.$method(start_block_num..=end_block_num-1)?;
2165                assert!(result.is_empty(), "No data should be found for an invalid block range");
2166
2167                // Test valid range with empty results
2168                let result = provider.$method(in_mem_range.end() + 10..=in_mem_range.end() + 20)?;
2169                assert!(result.is_empty(), "No data should be found for an empty block range");
2170            )*
2171        }};
2172    }
2173
2174    #[test]
2175    fn test_methods_by_block_range() -> eyre::Result<()> {
2176        // todo(joshie) add canonical_hashes_range below after changing its interface into range
2177        // instead start end
2178        test_by_block_range!([
2179            (headers_range, |block: &SealedBlock<Block>| block.header().clone()),
2180            (sealed_headers_range, |block: &SealedBlock<Block>| block.clone_sealed_header()),
2181            (block_range, |block: &SealedBlock<Block>| block.clone().into_block()),
2182            (block_with_senders_range, |block: &SealedBlock<Block>| block
2183                .clone()
2184                .try_recover()
2185                .unwrap()),
2186            (recovered_block_range, |block: &SealedBlock<Block>| block
2187                .clone()
2188                .try_recover()
2189                .unwrap()),
2190            (transactions_by_block_range, |block: &SealedBlock<Block>| block
2191                .body()
2192                .transactions
2193                .clone()),
2194        ]);
2195
2196        Ok(())
2197    }
2198
2199    /// Helper macro to call a provider method based on argument count and check its result
2200    macro_rules! call_method {
2201        ($provider:expr, $method:ident, ($($args:expr),*), $expected_item:expr) => {{
2202            let result = $provider.$method($($args),*)?;
2203            assert_eq!(
2204                result,
2205                $expected_item,
2206                "{}: item does not match the expected item for arguments {:?}",
2207                stringify!($method),
2208                ($($args),*)
2209            );
2210        }};
2211
2212        // Handle valid or invalid arguments for one argument
2213        (ONE, $provider:expr, $method:ident, $item_extractor:expr, $txnum:expr, $txhash:expr, $block:expr, $receipts:expr) => {{
2214            let (arg, expected_item) = $item_extractor($block, $txnum($block), $txhash($block), $receipts);
2215            call_method!($provider, $method, (arg), expected_item);
2216        }};
2217
2218        // Handle valid or invalid arguments for two arguments
2219        (TWO, $provider:expr, $method:ident, $item_extractor:expr, $txnum:expr, $txhash:expr, $block:expr, $receipts:expr) => {{
2220            let ((arg1, arg2), expected_item) = $item_extractor($block, $txnum($block), $txhash($block), $receipts);
2221            call_method!($provider, $method, (arg1, arg2), expected_item);
2222        }};
2223    }
2224
2225    /// Macro to test non-range methods.
2226    ///
2227    /// ( `NUMBER_ARGUMENTS`, METHOD, FN -> ((`METHOD_ARGUMENT(s)`,...), `EXPECTED_RESULT`),
2228    /// `INVALID_ARGUMENTS`)
2229    macro_rules! test_non_range {
2230    ([$(($arg_count:ident, $method:ident, $item_extractor:expr, $invalid_args:expr)),* $(,)?]) => {{
2231
2232        // Get the number methods being tested.
2233        // Since each method tested will move a block from memory to storage, this ensures we have enough.
2234        let extra_blocks = [$(stringify!($arg_count)),*].len();
2235
2236        let mut rng = generators::rng();
2237        let (provider, mut database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
2238            &mut rng,
2239            TEST_BLOCKS_COUNT,
2240            TEST_BLOCKS_COUNT + extra_blocks,
2241            BlockRangeParams {
2242                tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2243                ..Default::default()
2244            },
2245        )?;
2246
2247        let mut in_memory_blocks: std::collections::VecDeque<_> = in_memory_blocks.into();
2248
2249        $(
2250            let tx_hash = |block: &SealedBlock<Block>| *block.body().transactions[0].tx_hash();
2251            let tx_num = |block: &SealedBlock<Block>| {
2252                database_blocks
2253                    .iter()
2254                    .chain(in_memory_blocks.iter())
2255                    .take_while(|b| b.number < block.number)
2256                    .map(|b| b.transaction_count())
2257                    .sum::<usize>() as u64
2258            };
2259
2260            // Ensure that the first generated in-memory block exists
2261            {
2262                // This block will be persisted to disk and removed from memory AFTER the first database query. This ensures that we query the in-memory state before the database avoiding any race condition.
2263                persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2264
2265                call_method!($arg_count, provider, $method, $item_extractor, tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2266
2267                // Move the block as well in our own structures
2268                database_blocks.push(in_memory_blocks.pop_front().unwrap());
2269            }
2270
2271            // database_blocks is changed above
2272            let tx_num = |block: &SealedBlock<Block>| {
2273                database_blocks
2274                    .iter()
2275                    .chain(in_memory_blocks.iter())
2276                    .take_while(|b| b.number < block.number)
2277                    .map(|b| b.transaction_count())
2278                    .sum::<usize>() as u64
2279            };
2280
2281            // Invalid/Non-existent argument should return `None`
2282            {
2283                call_method!($arg_count, provider, $method, |_,_,_,_|  ($invalid_args, None), tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2284            }
2285
2286            // Check that the item is only in memory and not in database
2287            {
2288                let last_mem_block = &in_memory_blocks[in_memory_blocks.len() - 1];
2289
2290                let (args, expected_item) = $item_extractor(last_mem_block, tx_num(last_mem_block), tx_hash(last_mem_block), &receipts);
2291                call_method!($arg_count, provider, $method, |_,_,_,_| (args.clone(), expected_item), tx_num, tx_hash, last_mem_block, &receipts);
2292
2293                // Ensure the item is not in storage
2294                call_method!($arg_count, provider.database, $method, |_,_,_,_|  (args, None), tx_num, tx_hash, last_mem_block, &receipts);
2295            }
2296        )*
2297    }};
2298}
2299
2300    #[test]
2301    fn test_non_range_methods() -> eyre::Result<()> {
2302        let test_tx_index = 0;
2303
2304        test_non_range!([
2305            (
2306                ONE,
2307                header,
2308                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2309                    block.hash(),
2310                    Some(block.header().clone())
2311                ),
2312                B256::random()
2313            ),
2314            (
2315                ONE,
2316                header_by_number,
2317                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2318                    block.number,
2319                    Some(block.header().clone())
2320                ),
2321                u64::MAX
2322            ),
2323            (
2324                ONE,
2325                sealed_header,
2326                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2327                    block.number,
2328                    Some(block.clone_sealed_header())
2329                ),
2330                u64::MAX
2331            ),
2332            (
2333                ONE,
2334                block_hash,
2335                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2336                    block.number,
2337                    Some(block.hash())
2338                ),
2339                u64::MAX
2340            ),
2341            (
2342                ONE,
2343                block_number,
2344                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2345                    block.hash(),
2346                    Some(block.number)
2347                ),
2348                B256::random()
2349            ),
2350            (
2351                ONE,
2352                block,
2353                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2354                    BlockHashOrNumber::Hash(block.hash()),
2355                    Some(block.clone().into_block())
2356                ),
2357                BlockHashOrNumber::Hash(B256::random())
2358            ),
2359            (
2360                ONE,
2361                block,
2362                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2363                    BlockHashOrNumber::Number(block.number),
2364                    Some(block.clone().into_block())
2365                ),
2366                BlockHashOrNumber::Number(u64::MAX)
2367            ),
2368            (
2369                ONE,
2370                block_body_indices,
2371                |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2372                    block.number,
2373                    Some(StoredBlockBodyIndices {
2374                        first_tx_num: tx_num,
2375                        tx_count: block.transaction_count() as u64
2376                    })
2377                ),
2378                u64::MAX
2379            ),
2380            (
2381                TWO,
2382                recovered_block,
2383                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2384                    (BlockHashOrNumber::Number(block.number), TransactionVariant::WithHash),
2385                    block.clone().try_recover().ok()
2386                ),
2387                (BlockHashOrNumber::Number(u64::MAX), TransactionVariant::WithHash)
2388            ),
2389            (
2390                TWO,
2391                recovered_block,
2392                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2393                    (BlockHashOrNumber::Hash(block.hash()), TransactionVariant::WithHash),
2394                    block.clone().try_recover().ok()
2395                ),
2396                (BlockHashOrNumber::Hash(B256::random()), TransactionVariant::WithHash)
2397            ),
2398            (
2399                TWO,
2400                sealed_block_with_senders,
2401                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2402                    (BlockHashOrNumber::Number(block.number), TransactionVariant::WithHash),
2403                    block.clone().try_recover().ok()
2404                ),
2405                (BlockHashOrNumber::Number(u64::MAX), TransactionVariant::WithHash)
2406            ),
2407            (
2408                TWO,
2409                sealed_block_with_senders,
2410                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2411                    (BlockHashOrNumber::Hash(block.hash()), TransactionVariant::WithHash),
2412                    block.clone().try_recover().ok()
2413                ),
2414                (BlockHashOrNumber::Hash(B256::random()), TransactionVariant::WithHash)
2415            ),
2416            (
2417                ONE,
2418                transaction_id,
2419                |_: &SealedBlock<Block>, tx_num: TxNumber, tx_hash: B256, _: &Vec<Vec<Receipt>>| (
2420                    tx_hash,
2421                    Some(tx_num)
2422                ),
2423                B256::random()
2424            ),
2425            (
2426                ONE,
2427                transaction_by_id,
2428                |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2429                    tx_num,
2430                    Some(block.body().transactions[test_tx_index].clone())
2431                ),
2432                u64::MAX
2433            ),
2434            (
2435                ONE,
2436                transaction_by_id_unhashed,
2437                |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2438                    tx_num,
2439                    Some(block.body().transactions[test_tx_index].clone())
2440                ),
2441                u64::MAX
2442            ),
2443            (
2444                ONE,
2445                transaction_by_hash,
2446                |block: &SealedBlock<Block>, _: TxNumber, tx_hash: B256, _: &Vec<Vec<Receipt>>| (
2447                    tx_hash,
2448                    Some(block.body().transactions[test_tx_index].clone())
2449                ),
2450                B256::random()
2451            ),
2452            (
2453                ONE,
2454                transaction_block,
2455                |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2456                    tx_num,
2457                    Some(block.number)
2458                ),
2459                u64::MAX
2460            ),
2461            (
2462                ONE,
2463                transactions_by_block,
2464                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2465                    BlockHashOrNumber::Number(block.number),
2466                    Some(block.body().transactions.clone())
2467                ),
2468                BlockHashOrNumber::Number(u64::MAX)
2469            ),
2470            (
2471                ONE,
2472                transactions_by_block,
2473                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2474                    BlockHashOrNumber::Hash(block.hash()),
2475                    Some(block.body().transactions.clone())
2476                ),
2477                BlockHashOrNumber::Number(u64::MAX)
2478            ),
2479            (
2480                ONE,
2481                transaction_sender,
2482                |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2483                    tx_num,
2484                    block.body().transactions[test_tx_index].recover_signer().ok()
2485                ),
2486                u64::MAX
2487            ),
2488            (
2489                ONE,
2490                receipt,
2491                |block: &SealedBlock<Block>,
2492                 tx_num: TxNumber,
2493                 _: B256,
2494                 receipts: &Vec<Vec<Receipt>>| (
2495                    tx_num,
2496                    Some(receipts[block.number as usize][test_tx_index].clone())
2497                ),
2498                u64::MAX
2499            ),
2500            (
2501                ONE,
2502                receipt_by_hash,
2503                |block: &SealedBlock<Block>,
2504                 _: TxNumber,
2505                 tx_hash: B256,
2506                 receipts: &Vec<Vec<Receipt>>| (
2507                    tx_hash,
2508                    Some(receipts[block.number as usize][test_tx_index].clone())
2509                ),
2510                B256::random()
2511            ),
2512            (
2513                ONE,
2514                receipts_by_block,
2515                |block: &SealedBlock<Block>, _: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2516                    BlockHashOrNumber::Number(block.number),
2517                    Some(receipts[block.number as usize].clone())
2518                ),
2519                BlockHashOrNumber::Number(u64::MAX)
2520            ),
2521            (
2522                ONE,
2523                receipts_by_block,
2524                |block: &SealedBlock<Block>, _: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2525                    BlockHashOrNumber::Hash(block.hash()),
2526                    Some(receipts[block.number as usize].clone())
2527                ),
2528                BlockHashOrNumber::Hash(B256::random())
2529            ),
2530            // TODO: withdrawals, requests, ommers
2531        ]);
2532
2533        Ok(())
2534    }
2535
2536    #[test]
2537    fn test_race() -> eyre::Result<()> {
2538        let mut rng = generators::rng();
2539        let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
2540            &mut rng,
2541            TEST_BLOCKS_COUNT - 1,
2542            TEST_BLOCKS_COUNT + 1,
2543            BlockRangeParams {
2544                tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2545                ..Default::default()
2546            },
2547        )?;
2548
2549        // Old implementation was querying the database first. This is problematic, if there are
2550        // changes AFTER the database transaction is created.
2551        let old_transaction_hash_fn =
2552            |hash: B256,
2553             canonical_in_memory_state: CanonicalInMemoryState,
2554             factory: ProviderFactory<MockNodeTypesWithDB>| {
2555                assert!(factory.transaction_by_hash(hash)?.is_none(), "should not be in database");
2556                Ok::<_, ProviderError>(canonical_in_memory_state.transaction_by_hash(hash))
2557            };
2558
2559        // Correct implementation queries in-memory first
2560        let correct_transaction_hash_fn =
2561            |hash: B256,
2562             canonical_in_memory_state: CanonicalInMemoryState,
2563             _factory: ProviderFactory<MockNodeTypesWithDB>| {
2564                if let Some(tx) = canonical_in_memory_state.transaction_by_hash(hash) {
2565                    return Ok::<_, ProviderError>(Some(tx));
2566                }
2567                panic!("should not be in database");
2568                // _factory.transaction_by_hash(hash)
2569            };
2570
2571        // OLD BEHAVIOUR
2572        {
2573            // This will persist block 1 AFTER a database is created. Moving it from memory to
2574            // storage.
2575            persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2576            let to_be_persisted_tx = in_memory_blocks[0].body().transactions[0].clone();
2577
2578            // Even though the block exists, given the order of provider queries done in the method
2579            // above, we do not see it.
2580            assert!(matches!(
2581                old_transaction_hash_fn(
2582                    *to_be_persisted_tx.tx_hash(),
2583                    provider.canonical_in_memory_state(),
2584                    provider.database.clone()
2585                ),
2586                Ok(None)
2587            ));
2588        }
2589
2590        // CORRECT BEHAVIOUR
2591        {
2592            // This will persist block 1 AFTER a database is created. Moving it from memory to
2593            // storage.
2594            persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[1].number);
2595            let to_be_persisted_tx = in_memory_blocks[1].body().transactions[0].clone();
2596
2597            assert!(matches!(
2598                correct_transaction_hash_fn(
2599                    *to_be_persisted_tx.tx_hash(),
2600                    provider.canonical_in_memory_state(),
2601                    provider.database
2602                ),
2603                Ok(Some(to_be_persisted_tx))
2604            ));
2605        }
2606
2607        Ok(())
2608    }
2609}