reth_provider/providers/
blockchain_provider.rs

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