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