Skip to main content

reth_provider/providers/
blockchain_provider.rs

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