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