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