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