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 set_canonical_head(&self, header: SealedHeader<Self::Header>) {
648        self.canonical_in_memory_state.set_canonical_head(header);
649    }
650
651    fn set_safe(&self, header: SealedHeader<Self::Header>) {
652        self.canonical_in_memory_state.set_safe(header);
653    }
654
655    fn set_finalized(&self, header: SealedHeader<Self::Header>) {
656        self.canonical_in_memory_state.set_finalized(header);
657    }
658}
659
660impl<N: ProviderNodeTypes> BlockReaderIdExt for BlockchainProvider<N>
661where
662    Self: ReceiptProviderIdExt,
663{
664    fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>> {
665        self.consistent_provider()?.block_by_id(id)
666    }
667
668    fn header_by_number_or_tag(
669        &self,
670        id: BlockNumberOrTag,
671    ) -> ProviderResult<Option<Self::Header>> {
672        self.consistent_provider()?.header_by_number_or_tag(id)
673    }
674
675    fn sealed_header_by_number_or_tag(
676        &self,
677        id: BlockNumberOrTag,
678    ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
679        self.consistent_provider()?.sealed_header_by_number_or_tag(id)
680    }
681
682    fn sealed_header_by_id(
683        &self,
684        id: BlockId,
685    ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
686        self.consistent_provider()?.sealed_header_by_id(id)
687    }
688
689    fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>> {
690        self.consistent_provider()?.header_by_id(id)
691    }
692
693    fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<Self::Header>>> {
694        self.consistent_provider()?.ommers_by_id(id)
695    }
696}
697
698impl<N: ProviderNodeTypes> CanonStateSubscriptions for BlockchainProvider<N> {
699    fn subscribe_to_canonical_state(&self) -> CanonStateNotifications<Self::Primitives> {
700        self.canonical_in_memory_state.subscribe_canon_state()
701    }
702}
703
704impl<N: ProviderNodeTypes> ForkChoiceSubscriptions for BlockchainProvider<N> {
705    type Header = HeaderTy<N>;
706
707    fn subscribe_safe_block(&self) -> ForkChoiceNotifications<Self::Header> {
708        let receiver = self.canonical_in_memory_state.subscribe_safe_block();
709        ForkChoiceNotifications(receiver)
710    }
711
712    fn subscribe_finalized_block(&self) -> ForkChoiceNotifications<Self::Header> {
713        let receiver = self.canonical_in_memory_state.subscribe_finalized_block();
714        ForkChoiceNotifications(receiver)
715    }
716}
717
718impl<N: ProviderNodeTypes> StorageChangeSetReader for BlockchainProvider<N> {
719    fn storage_changeset(
720        &self,
721        block_number: BlockNumber,
722    ) -> ProviderResult<Vec<(BlockNumberAddress, StorageEntry)>> {
723        self.consistent_provider()?.storage_changeset(block_number)
724    }
725}
726
727impl<N: ProviderNodeTypes> ChangeSetReader for BlockchainProvider<N> {
728    fn account_block_changeset(
729        &self,
730        block_number: BlockNumber,
731    ) -> ProviderResult<Vec<AccountBeforeTx>> {
732        self.consistent_provider()?.account_block_changeset(block_number)
733    }
734}
735
736impl<N: ProviderNodeTypes> AccountReader for BlockchainProvider<N> {
737    /// Get basic account information.
738    fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
739        self.consistent_provider()?.basic_account(address)
740    }
741}
742
743impl<N: ProviderNodeTypes> StateReader for BlockchainProvider<N> {
744    type Receipt = ReceiptTy<N>;
745
746    /// Re-constructs the [`ExecutionOutcome`] from in-memory and database state, if necessary.
747    ///
748    /// If data for the block does not exist, this will return [`None`].
749    ///
750    /// NOTE: This cannot be called safely in a loop outside of the blockchain tree thread. This is
751    /// because the [`CanonicalInMemoryState`] could change during a reorg, causing results to be
752    /// inconsistent. Currently this can safely be called within the blockchain tree thread,
753    /// because the tree thread is responsible for modifying the [`CanonicalInMemoryState`] in the
754    /// first place.
755    fn get_state(
756        &self,
757        block: BlockNumber,
758    ) -> ProviderResult<Option<ExecutionOutcome<Self::Receipt>>> {
759        StateReader::get_state(&self.consistent_provider()?, block)
760    }
761}
762
763#[cfg(test)]
764mod tests {
765    use crate::{
766        providers::BlockchainProvider,
767        test_utils::{
768            create_test_provider_factory, create_test_provider_factory_with_chain_spec,
769            MockNodeTypesWithDB,
770        },
771        writer::UnifiedStorageWriter,
772        BlockWriter, CanonChainTracker, ProviderFactory, StaticFileProviderFactory,
773        StaticFileWriter,
774    };
775    use alloy_eips::{eip4895::Withdrawals, BlockHashOrNumber, BlockNumHash, BlockNumberOrTag};
776    use alloy_primitives::{BlockNumber, TxNumber, B256};
777    use itertools::Itertools;
778    use rand::Rng;
779    use reth_chain_state::{
780        test_utils::TestBlockBuilder, CanonStateNotification, CanonStateSubscriptions,
781        CanonicalInMemoryState, ExecutedBlock, ExecutedBlockWithTrieUpdates, NewCanonicalChain,
782    };
783    use reth_chainspec::{
784        ChainSpec, ChainSpecBuilder, ChainSpecProvider, EthereumHardfork, MAINNET,
785    };
786    use reth_db_api::{
787        cursor::DbCursorRO,
788        models::{AccountBeforeTx, StoredBlockBodyIndices},
789        tables,
790        transaction::DbTx,
791    };
792    use reth_errors::ProviderError;
793    use reth_ethereum_primitives::{Block, EthPrimitives, Receipt};
794    use reth_execution_types::{Chain, ExecutionOutcome};
795    use reth_primitives_traits::{
796        BlockBody, RecoveredBlock, SealedBlock, SignedTransaction, SignerRecoverable,
797    };
798    use reth_static_file_types::StaticFileSegment;
799    use reth_storage_api::{
800        BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader,
801        BlockReaderIdExt, BlockSource, ChangeSetReader, DatabaseProviderFactory, HeaderProvider,
802        OmmersProvider, ReceiptProvider, ReceiptProviderIdExt, StateProviderFactory,
803        TransactionVariant, TransactionsProvider, WithdrawalsProvider,
804    };
805    use reth_testing_utils::generators::{
806        self, random_block, random_block_range, random_changeset_range, random_eoa_accounts,
807        random_receipt, BlockParams, BlockRangeParams,
808    };
809    use revm_database::BundleState;
810    use std::{
811        ops::{Bound, Deref, Range, RangeBounds},
812        sync::Arc,
813        time::Instant,
814    };
815
816    const TEST_BLOCKS_COUNT: usize = 5;
817
818    const TEST_TRANSACTIONS_COUNT: u8 = 4;
819
820    fn random_blocks(
821        rng: &mut impl Rng,
822        database_blocks: usize,
823        in_memory_blocks: usize,
824        requests_count: Option<Range<u8>>,
825        withdrawals_count: Option<Range<u8>>,
826        tx_count: impl RangeBounds<u8>,
827    ) -> (Vec<SealedBlock<Block>>, Vec<SealedBlock<Block>>) {
828        let block_range = (database_blocks + in_memory_blocks - 1) as u64;
829
830        let tx_start = match tx_count.start_bound() {
831            Bound::Included(&n) | Bound::Excluded(&n) => n,
832            Bound::Unbounded => u8::MIN,
833        };
834        let tx_end = match tx_count.end_bound() {
835            Bound::Included(&n) | Bound::Excluded(&n) => n + 1,
836            Bound::Unbounded => u8::MAX,
837        };
838
839        let blocks = random_block_range(
840            rng,
841            0..=block_range,
842            BlockRangeParams {
843                parent: Some(B256::ZERO),
844                tx_count: tx_start..tx_end,
845                requests_count,
846                withdrawals_count,
847            },
848        );
849        let (database_blocks, in_memory_blocks) = blocks.split_at(database_blocks);
850        (database_blocks.to_vec(), in_memory_blocks.to_vec())
851    }
852
853    #[expect(clippy::type_complexity)]
854    fn provider_with_chain_spec_and_random_blocks(
855        rng: &mut impl Rng,
856        chain_spec: Arc<ChainSpec>,
857        database_blocks: usize,
858        in_memory_blocks: usize,
859        block_range_params: BlockRangeParams,
860    ) -> eyre::Result<(
861        BlockchainProvider<MockNodeTypesWithDB>,
862        Vec<SealedBlock<Block>>,
863        Vec<SealedBlock<Block>>,
864        Vec<Vec<Receipt>>,
865    )> {
866        let (database_blocks, in_memory_blocks) = random_blocks(
867            rng,
868            database_blocks,
869            in_memory_blocks,
870            block_range_params.requests_count,
871            block_range_params.withdrawals_count,
872            block_range_params.tx_count,
873        );
874
875        let receipts: Vec<Vec<_>> = database_blocks
876            .iter()
877            .chain(in_memory_blocks.iter())
878            .map(|block| block.body().transactions.iter())
879            .map(|tx| tx.map(|tx| random_receipt(rng, tx, Some(2))).collect())
880            .collect();
881
882        let factory = create_test_provider_factory_with_chain_spec(chain_spec);
883        let provider_rw = factory.database_provider_rw()?;
884        let static_file_provider = factory.static_file_provider();
885
886        // Write transactions to static files with the right `tx_num``
887        let mut tx_num = provider_rw
888            .block_body_indices(database_blocks.first().as_ref().unwrap().number.saturating_sub(1))?
889            .map(|indices| indices.next_tx_num())
890            .unwrap_or_default();
891
892        // Insert blocks into the database
893        for (block, receipts) in database_blocks.iter().zip(&receipts) {
894            // TODO: this should be moved inside `insert_historical_block`: <https://github.com/paradigmxyz/reth/issues/11524>
895            let mut transactions_writer =
896                static_file_provider.latest_writer(StaticFileSegment::Transactions)?;
897            let mut receipts_writer =
898                static_file_provider.latest_writer(StaticFileSegment::Receipts)?;
899            transactions_writer.increment_block(block.number)?;
900            receipts_writer.increment_block(block.number)?;
901
902            for (tx, receipt) in block.body().transactions().zip(receipts) {
903                transactions_writer.append_transaction(tx_num, tx)?;
904                receipts_writer.append_receipt(tx_num, receipt)?;
905                tx_num += 1;
906            }
907
908            provider_rw.insert_historical_block(
909                block.clone().try_recover().expect("failed to seal block with senders"),
910            )?;
911        }
912
913        // Commit to both storages: database and static files
914        UnifiedStorageWriter::commit(provider_rw)?;
915
916        let provider = BlockchainProvider::new(factory)?;
917
918        // Insert the rest of the blocks and receipts into the in-memory state
919        let chain = NewCanonicalChain::Commit {
920            new: in_memory_blocks
921                .iter()
922                .map(|block| {
923                    let senders = block.senders().expect("failed to recover senders");
924                    let block_receipts = receipts.get(block.number as usize).unwrap().clone();
925                    let execution_outcome =
926                        ExecutionOutcome { receipts: vec![block_receipts], ..Default::default() };
927
928                    ExecutedBlockWithTrieUpdates::new(
929                        Arc::new(RecoveredBlock::new_sealed(block.clone(), senders)),
930                        execution_outcome.into(),
931                        Default::default(),
932                        Default::default(),
933                    )
934                })
935                .collect(),
936        };
937        provider.canonical_in_memory_state.update_chain(chain);
938
939        // Get canonical, safe, and finalized blocks
940        let blocks = database_blocks.iter().chain(in_memory_blocks.iter()).collect::<Vec<_>>();
941        let block_count = blocks.len();
942        let canonical_block = blocks.get(block_count - 1).unwrap();
943        let safe_block = blocks.get(block_count - 2).unwrap();
944        let finalized_block = blocks.get(block_count - 3).unwrap();
945
946        // Set the canonical head, safe, and finalized blocks
947        provider.set_canonical_head(canonical_block.clone_sealed_header());
948        provider.set_safe(safe_block.clone_sealed_header());
949        provider.set_finalized(finalized_block.clone_sealed_header());
950
951        Ok((provider, database_blocks.clone(), in_memory_blocks.clone(), receipts))
952    }
953
954    #[expect(clippy::type_complexity)]
955    fn provider_with_random_blocks(
956        rng: &mut impl Rng,
957        database_blocks: usize,
958        in_memory_blocks: usize,
959        block_range_params: BlockRangeParams,
960    ) -> eyre::Result<(
961        BlockchainProvider<MockNodeTypesWithDB>,
962        Vec<SealedBlock<Block>>,
963        Vec<SealedBlock<Block>>,
964        Vec<Vec<Receipt>>,
965    )> {
966        provider_with_chain_spec_and_random_blocks(
967            rng,
968            MAINNET.clone(),
969            database_blocks,
970            in_memory_blocks,
971            block_range_params,
972        )
973    }
974
975    /// This will persist the last block in-memory and delete it from
976    /// `canonical_in_memory_state` right after a database read transaction is created.
977    ///
978    /// This simulates a RPC method having a different view than when its database transaction was
979    /// created.
980    fn persist_block_after_db_tx_creation(
981        provider: BlockchainProvider<MockNodeTypesWithDB>,
982        block_number: BlockNumber,
983    ) {
984        let hook_provider = provider.clone();
985        provider.database.db_ref().set_post_transaction_hook(Box::new(move || {
986            if let Some(state) = hook_provider.canonical_in_memory_state.head_state() {
987                if state.anchor().number + 1 == block_number {
988                    let mut lowest_memory_block =
989                        state.parent_state_chain().last().expect("qed").block();
990                    let num_hash = lowest_memory_block.recovered_block().num_hash();
991
992                    let mut execution_output = (*lowest_memory_block.execution_output).clone();
993                    execution_output.first_block = lowest_memory_block.recovered_block().number;
994                    lowest_memory_block.execution_output = Arc::new(execution_output);
995
996                    // Push to disk
997                    let provider_rw = hook_provider.database_provider_rw().unwrap();
998                    UnifiedStorageWriter::from(&provider_rw, &hook_provider.static_file_provider())
999                        .save_blocks(vec![lowest_memory_block])
1000                        .unwrap();
1001                    UnifiedStorageWriter::commit(provider_rw).unwrap();
1002
1003                    // Remove from memory
1004                    hook_provider.canonical_in_memory_state.remove_persisted_blocks(num_hash);
1005                }
1006            }
1007        }));
1008    }
1009
1010    #[test]
1011    fn test_block_reader_find_block_by_hash() -> eyre::Result<()> {
1012        // Initialize random number generator and provider factory
1013        let mut rng = generators::rng();
1014        let factory = create_test_provider_factory();
1015
1016        // Generate 10 random blocks and split into database and in-memory blocks
1017        let blocks = random_block_range(
1018            &mut rng,
1019            0..=10,
1020            BlockRangeParams { parent: Some(B256::ZERO), tx_count: 0..1, ..Default::default() },
1021        );
1022        let (database_blocks, in_memory_blocks) = blocks.split_at(5);
1023
1024        // Insert first 5 blocks into the database
1025        let provider_rw = factory.provider_rw()?;
1026        for block in database_blocks {
1027            provider_rw.insert_historical_block(
1028                block.clone().try_recover().expect("failed to seal block with senders"),
1029            )?;
1030        }
1031        provider_rw.commit()?;
1032
1033        // Create a new provider
1034        let provider = BlockchainProvider::new(factory)?;
1035
1036        // Useful blocks
1037        let first_db_block = database_blocks.first().unwrap();
1038        let first_in_mem_block = in_memory_blocks.first().unwrap();
1039        let last_in_mem_block = in_memory_blocks.last().unwrap();
1040
1041        // No block in memory before setting in memory state
1042        assert_eq!(provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Any)?, None);
1043        assert_eq!(
1044            provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Canonical)?,
1045            None
1046        );
1047        // No pending block in memory
1048        assert_eq!(
1049            provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Pending)?,
1050            None
1051        );
1052
1053        // Insert first block into the in-memory state
1054        let in_memory_block_senders =
1055            first_in_mem_block.senders().expect("failed to recover senders");
1056        let chain = NewCanonicalChain::Commit {
1057            new: vec![ExecutedBlockWithTrieUpdates::new(
1058                Arc::new(RecoveredBlock::new_sealed(
1059                    first_in_mem_block.clone(),
1060                    in_memory_block_senders,
1061                )),
1062                Default::default(),
1063                Default::default(),
1064                Default::default(),
1065            )],
1066        };
1067        provider.canonical_in_memory_state.update_chain(chain);
1068
1069        // Now the block should be found in memory
1070        assert_eq!(
1071            provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Any)?,
1072            Some(first_in_mem_block.clone().into_block())
1073        );
1074        assert_eq!(
1075            provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Canonical)?,
1076            Some(first_in_mem_block.clone().into_block())
1077        );
1078
1079        // Find the first block in database by hash
1080        assert_eq!(
1081            provider.find_block_by_hash(first_db_block.hash(), BlockSource::Any)?,
1082            Some(first_db_block.clone().into_block())
1083        );
1084        assert_eq!(
1085            provider.find_block_by_hash(first_db_block.hash(), BlockSource::Canonical)?,
1086            Some(first_db_block.clone().into_block())
1087        );
1088
1089        // No pending block in database
1090        assert_eq!(provider.find_block_by_hash(first_db_block.hash(), BlockSource::Pending)?, None);
1091
1092        // Insert the last block into the pending state
1093        provider.canonical_in_memory_state.set_pending_block(ExecutedBlockWithTrieUpdates {
1094            block: ExecutedBlock {
1095                recovered_block: Arc::new(RecoveredBlock::new_sealed(
1096                    last_in_mem_block.clone(),
1097                    Default::default(),
1098                )),
1099                execution_output: Default::default(),
1100                hashed_state: Default::default(),
1101            },
1102            trie: Default::default(),
1103        });
1104
1105        // Now the last block should be found in memory
1106        assert_eq!(
1107            provider.find_block_by_hash(last_in_mem_block.hash(), BlockSource::Pending)?,
1108            Some(last_in_mem_block.clone().into_block())
1109        );
1110
1111        Ok(())
1112    }
1113
1114    #[test]
1115    fn test_block_reader_block() -> eyre::Result<()> {
1116        // Initialize random number generator and provider factory
1117        let mut rng = generators::rng();
1118        let factory = create_test_provider_factory();
1119
1120        // Generate 10 random blocks and split into database and in-memory blocks
1121        let blocks = random_block_range(
1122            &mut rng,
1123            0..=10,
1124            BlockRangeParams { parent: Some(B256::ZERO), tx_count: 0..1, ..Default::default() },
1125        );
1126        let (database_blocks, in_memory_blocks) = blocks.split_at(5);
1127
1128        // Insert first 5 blocks into the database
1129        let provider_rw = factory.provider_rw()?;
1130        for block in database_blocks {
1131            provider_rw.insert_historical_block(
1132                block.clone().try_recover().expect("failed to seal block with senders"),
1133            )?;
1134        }
1135        provider_rw.commit()?;
1136
1137        // Create a new provider
1138        let provider = BlockchainProvider::new(factory)?;
1139
1140        // First in memory block
1141        let first_in_mem_block = in_memory_blocks.first().unwrap();
1142        // First database block
1143        let first_db_block = database_blocks.first().unwrap();
1144
1145        // First in memory block should not be found yet as not integrated to the in-memory state
1146        assert_eq!(provider.block(BlockHashOrNumber::Hash(first_in_mem_block.hash()))?, None);
1147        assert_eq!(provider.block(BlockHashOrNumber::Number(first_in_mem_block.number))?, None);
1148
1149        // Insert first block into the in-memory state
1150        let in_memory_block_senders =
1151            first_in_mem_block.senders().expect("failed to recover senders");
1152        let chain = NewCanonicalChain::Commit {
1153            new: vec![ExecutedBlockWithTrieUpdates::new(
1154                Arc::new(RecoveredBlock::new_sealed(
1155                    first_in_mem_block.clone(),
1156                    in_memory_block_senders,
1157                )),
1158                Default::default(),
1159                Default::default(),
1160                Default::default(),
1161            )],
1162        };
1163        provider.canonical_in_memory_state.update_chain(chain);
1164
1165        // First in memory block should be found
1166        assert_eq!(
1167            provider.block(BlockHashOrNumber::Hash(first_in_mem_block.hash()))?,
1168            Some(first_in_mem_block.clone().into_block())
1169        );
1170        assert_eq!(
1171            provider.block(BlockHashOrNumber::Number(first_in_mem_block.number))?,
1172            Some(first_in_mem_block.clone().into_block())
1173        );
1174
1175        // First database block should be found
1176        assert_eq!(
1177            provider.block(BlockHashOrNumber::Hash(first_db_block.hash()))?,
1178            Some(first_db_block.clone().into_block())
1179        );
1180        assert_eq!(
1181            provider.block(BlockHashOrNumber::Number(first_db_block.number))?,
1182            Some(first_db_block.clone().into_block())
1183        );
1184
1185        Ok(())
1186    }
1187
1188    #[test]
1189    fn test_block_reader_pending_block() -> eyre::Result<()> {
1190        let mut rng = generators::rng();
1191        let (provider, _, _, _) = provider_with_random_blocks(
1192            &mut rng,
1193            TEST_BLOCKS_COUNT,
1194            TEST_BLOCKS_COUNT,
1195            BlockRangeParams::default(),
1196        )?;
1197
1198        // Generate a random block
1199        let mut rng = generators::rng();
1200        let block = random_block(
1201            &mut rng,
1202            0,
1203            BlockParams { parent: Some(B256::ZERO), ..Default::default() },
1204        );
1205
1206        // Set the block as pending
1207        provider.canonical_in_memory_state.set_pending_block(ExecutedBlockWithTrieUpdates {
1208            block: ExecutedBlock {
1209                recovered_block: Arc::new(RecoveredBlock::new_sealed(
1210                    block.clone(),
1211                    block.senders().unwrap(),
1212                )),
1213                execution_output: Default::default(),
1214                hashed_state: Default::default(),
1215            },
1216            trie: Default::default(),
1217        });
1218
1219        // Assertions related to the pending block
1220        assert_eq!(provider.pending_block()?, Some(block.clone()));
1221
1222        assert_eq!(
1223            provider.pending_block_with_senders()?,
1224            Some(RecoveredBlock::new_sealed(block.clone(), block.senders().unwrap()))
1225        );
1226
1227        assert_eq!(provider.pending_block_and_receipts()?, Some((block, vec![])));
1228
1229        Ok(())
1230    }
1231
1232    #[test]
1233    fn test_block_reader_ommers() -> eyre::Result<()> {
1234        // Create a new provider
1235        let mut rng = generators::rng();
1236        let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
1237            &mut rng,
1238            TEST_BLOCKS_COUNT,
1239            TEST_BLOCKS_COUNT,
1240            BlockRangeParams::default(),
1241        )?;
1242
1243        let first_in_mem_block = in_memory_blocks.first().unwrap();
1244
1245        // If the block is after the Merge, we should have an empty ommers list
1246        assert_eq!(
1247            provider.ommers(
1248                (provider.chain_spec().paris_block_and_final_difficulty.unwrap().0 + 2).into()
1249            )?,
1250            Some(vec![])
1251        );
1252
1253        // First in memory block ommers should be found
1254        assert_eq!(
1255            provider.ommers(first_in_mem_block.number.into())?,
1256            Some(first_in_mem_block.body().ommers.clone())
1257        );
1258        assert_eq!(
1259            provider.ommers(first_in_mem_block.hash().into())?,
1260            Some(first_in_mem_block.body().ommers.clone())
1261        );
1262
1263        // A random hash should return None as the block number is not found
1264        assert_eq!(provider.ommers(B256::random().into())?, None);
1265
1266        Ok(())
1267    }
1268
1269    #[test]
1270    fn test_block_body_indices() -> eyre::Result<()> {
1271        // Create a new provider
1272        let mut rng = generators::rng();
1273        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1274            &mut rng,
1275            TEST_BLOCKS_COUNT,
1276            TEST_BLOCKS_COUNT,
1277            BlockRangeParams {
1278                tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
1279                ..Default::default()
1280            },
1281        )?;
1282
1283        let first_in_mem_block = in_memory_blocks.first().unwrap();
1284
1285        // Insert the first block into the in-memory state
1286        let in_memory_block_senders =
1287            first_in_mem_block.senders().expect("failed to recover senders");
1288        let chain = NewCanonicalChain::Commit {
1289            new: vec![ExecutedBlockWithTrieUpdates::new(
1290                Arc::new(RecoveredBlock::new_sealed(
1291                    first_in_mem_block.clone(),
1292                    in_memory_block_senders,
1293                )),
1294                Default::default(),
1295                Default::default(),
1296                Default::default(),
1297            )],
1298        };
1299        provider.canonical_in_memory_state.update_chain(chain);
1300
1301        let first_db_block = database_blocks.first().unwrap().clone();
1302        let first_in_mem_block = in_memory_blocks.first().unwrap().clone();
1303
1304        // First database block body indices should be found
1305        assert_eq!(
1306            provider.block_body_indices(first_db_block.number)?.unwrap(),
1307            StoredBlockBodyIndices { first_tx_num: 0, tx_count: 4 }
1308        );
1309
1310        // First in-memory block body indices should be found with the first tx after the database
1311        // blocks
1312        assert_eq!(
1313            provider.block_body_indices(first_in_mem_block.number)?.unwrap(),
1314            StoredBlockBodyIndices { first_tx_num: 20, tx_count: 4 }
1315        );
1316
1317        // A random block number should return None as the block is not found
1318        let mut rng = rand::rng();
1319        let random_block_number: u64 = rng.random();
1320        assert_eq!(provider.block_body_indices(random_block_number)?, None);
1321
1322        Ok(())
1323    }
1324
1325    #[test]
1326    fn test_block_hash_reader() -> eyre::Result<()> {
1327        let mut rng = generators::rng();
1328        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1329            &mut rng,
1330            TEST_BLOCKS_COUNT,
1331            TEST_BLOCKS_COUNT,
1332            BlockRangeParams::default(),
1333        )?;
1334
1335        let database_block = database_blocks.first().unwrap().clone();
1336        let in_memory_block = in_memory_blocks.last().unwrap().clone();
1337
1338        assert_eq!(provider.block_hash(database_block.number)?, Some(database_block.hash()));
1339        assert_eq!(provider.block_hash(in_memory_block.number)?, Some(in_memory_block.hash()));
1340
1341        assert_eq!(
1342            provider.canonical_hashes_range(0, 10)?,
1343            [database_blocks, in_memory_blocks]
1344                .concat()
1345                .iter()
1346                .map(|block| block.hash())
1347                .collect::<Vec<_>>()
1348        );
1349
1350        Ok(())
1351    }
1352
1353    #[test]
1354    fn test_header_provider() -> eyre::Result<()> {
1355        let mut rng = generators::rng();
1356        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1357            &mut rng,
1358            TEST_BLOCKS_COUNT,
1359            TEST_BLOCKS_COUNT,
1360            BlockRangeParams::default(),
1361        )?;
1362
1363        let database_block = database_blocks.first().unwrap().clone();
1364        let in_memory_block = in_memory_blocks.last().unwrap().clone();
1365        // make sure that the finalized block is on db
1366        let finalized_block = database_blocks.get(database_blocks.len() - 3).unwrap();
1367        provider.set_finalized(finalized_block.clone_sealed_header());
1368
1369        let blocks = [database_blocks, in_memory_blocks].concat();
1370
1371        assert_eq!(
1372            provider.header_td_by_number(database_block.number)?,
1373            Some(database_block.difficulty)
1374        );
1375
1376        assert_eq!(
1377            provider.header_td_by_number(in_memory_block.number)?,
1378            Some(in_memory_block.difficulty)
1379        );
1380
1381        assert_eq!(
1382            provider.sealed_headers_while(0..=10, |header| header.number <= 8)?,
1383            blocks
1384                .iter()
1385                .take_while(|header| header.number <= 8)
1386                .map(|b| b.clone_sealed_header())
1387                .collect::<Vec<_>>()
1388        );
1389
1390        Ok(())
1391    }
1392
1393    #[tokio::test]
1394    async fn test_canon_state_subscriptions() -> eyre::Result<()> {
1395        let factory = create_test_provider_factory();
1396
1397        // Generate a random block to initialise the blockchain provider.
1398        let mut test_block_builder = TestBlockBuilder::eth();
1399        let block_1 = test_block_builder.generate_random_block(0, B256::ZERO);
1400        let block_hash_1 = block_1.hash();
1401
1402        // Insert and commit the block.
1403        let provider_rw = factory.provider_rw()?;
1404        provider_rw.insert_historical_block(block_1)?;
1405        provider_rw.commit()?;
1406
1407        let provider = BlockchainProvider::new(factory)?;
1408
1409        // Subscribe twice for canonical state updates.
1410        let in_memory_state = provider.canonical_in_memory_state();
1411        let mut rx_1 = provider.subscribe_to_canonical_state();
1412        let mut rx_2 = provider.subscribe_to_canonical_state();
1413
1414        // Send and receive commit notifications.
1415        let block_2 = test_block_builder.generate_random_block(1, block_hash_1);
1416        let chain = Chain::new(vec![block_2], ExecutionOutcome::default(), None);
1417        let commit = CanonStateNotification::Commit { new: Arc::new(chain.clone()) };
1418        in_memory_state.notify_canon_state(commit.clone());
1419        let (notification_1, notification_2) = tokio::join!(rx_1.recv(), rx_2.recv());
1420        assert_eq!(notification_1, Ok(commit.clone()));
1421        assert_eq!(notification_2, Ok(commit.clone()));
1422
1423        // Send and receive re-org notifications.
1424        let block_3 = test_block_builder.generate_random_block(1, block_hash_1);
1425        let block_4 = test_block_builder.generate_random_block(2, block_3.hash());
1426        let new_chain = Chain::new(vec![block_3, block_4], ExecutionOutcome::default(), None);
1427        let re_org =
1428            CanonStateNotification::Reorg { old: Arc::new(chain), new: Arc::new(new_chain) };
1429        in_memory_state.notify_canon_state(re_org.clone());
1430        let (notification_1, notification_2) = tokio::join!(rx_1.recv(), rx_2.recv());
1431        assert_eq!(notification_1, Ok(re_org.clone()));
1432        assert_eq!(notification_2, Ok(re_org.clone()));
1433
1434        Ok(())
1435    }
1436
1437    #[test]
1438    fn test_withdrawals_provider() -> eyre::Result<()> {
1439        let mut rng = generators::rng();
1440        let chain_spec = Arc::new(ChainSpecBuilder::mainnet().shanghai_activated().build());
1441        let (provider, database_blocks, in_memory_blocks, _) =
1442            provider_with_chain_spec_and_random_blocks(
1443                &mut rng,
1444                chain_spec.clone(),
1445                TEST_BLOCKS_COUNT,
1446                TEST_BLOCKS_COUNT,
1447                BlockRangeParams { withdrawals_count: Some(1..3), ..Default::default() },
1448            )?;
1449        let blocks = [database_blocks, in_memory_blocks].concat();
1450
1451        let shainghai_timestamp =
1452            chain_spec.hardforks.fork(EthereumHardfork::Shanghai).as_timestamp().unwrap();
1453
1454        assert_eq!(
1455            provider
1456                .withdrawals_by_block(
1457                    alloy_eips::BlockHashOrNumber::Number(15),
1458                    shainghai_timestamp
1459                )
1460                .expect("could not call withdrawals by block"),
1461            Some(Withdrawals::new(vec![])),
1462            "Expected withdrawals_by_block to return empty list if block does not exist"
1463        );
1464
1465        for block in blocks {
1466            assert_eq!(
1467                provider
1468                    .withdrawals_by_block(
1469                        alloy_eips::BlockHashOrNumber::Number(block.number),
1470                        shainghai_timestamp
1471                    )?
1472                    .unwrap(),
1473                block.body().withdrawals.clone().unwrap(),
1474                "Expected withdrawals_by_block to return correct withdrawals"
1475            );
1476        }
1477
1478        Ok(())
1479    }
1480
1481    #[test]
1482    fn test_block_num_reader() -> eyre::Result<()> {
1483        let mut rng = generators::rng();
1484        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1485            &mut rng,
1486            TEST_BLOCKS_COUNT,
1487            TEST_BLOCKS_COUNT,
1488            BlockRangeParams::default(),
1489        )?;
1490
1491        assert_eq!(provider.best_block_number()?, in_memory_blocks.last().unwrap().number);
1492        assert_eq!(provider.last_block_number()?, database_blocks.last().unwrap().number);
1493
1494        let database_block = database_blocks.first().unwrap().clone();
1495        let in_memory_block = in_memory_blocks.first().unwrap().clone();
1496        assert_eq!(provider.block_number(database_block.hash())?, Some(database_block.number));
1497        assert_eq!(provider.block_number(in_memory_block.hash())?, Some(in_memory_block.number));
1498
1499        Ok(())
1500    }
1501
1502    #[test]
1503    fn test_block_reader_id_ext_block_by_id() -> eyre::Result<()> {
1504        let mut rng = generators::rng();
1505        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1506            &mut rng,
1507            TEST_BLOCKS_COUNT,
1508            TEST_BLOCKS_COUNT,
1509            BlockRangeParams::default(),
1510        )?;
1511
1512        let database_block = database_blocks.first().unwrap().clone();
1513        let in_memory_block = in_memory_blocks.last().unwrap().clone();
1514
1515        let block_number = database_block.number;
1516        let block_hash = database_block.hash();
1517
1518        assert_eq!(
1519            provider.block_by_id(block_number.into()).unwrap(),
1520            Some(database_block.clone().into_block())
1521        );
1522        assert_eq!(
1523            provider.block_by_id(block_hash.into()).unwrap(),
1524            Some(database_block.into_block())
1525        );
1526
1527        let block_number = in_memory_block.number;
1528        let block_hash = in_memory_block.hash();
1529        assert_eq!(
1530            provider.block_by_id(block_number.into()).unwrap(),
1531            Some(in_memory_block.clone().into_block())
1532        );
1533        assert_eq!(
1534            provider.block_by_id(block_hash.into()).unwrap(),
1535            Some(in_memory_block.into_block())
1536        );
1537
1538        Ok(())
1539    }
1540
1541    #[test]
1542    fn test_block_reader_id_ext_header_by_number_or_tag() -> eyre::Result<()> {
1543        let mut rng = generators::rng();
1544        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1545            &mut rng,
1546            TEST_BLOCKS_COUNT,
1547            TEST_BLOCKS_COUNT,
1548            BlockRangeParams::default(),
1549        )?;
1550
1551        let database_block = database_blocks.first().unwrap().clone();
1552
1553        let in_memory_block_count = in_memory_blocks.len();
1554        let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
1555        let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
1556        let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();
1557
1558        let block_number = database_block.number;
1559        assert_eq!(
1560            provider.header_by_number_or_tag(block_number.into()).unwrap(),
1561            Some(database_block.header().clone())
1562        );
1563        assert_eq!(
1564            provider.sealed_header_by_number_or_tag(block_number.into())?,
1565            Some(database_block.clone_sealed_header())
1566        );
1567
1568        assert_eq!(
1569            provider.header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
1570            Some(canonical_block.header().clone())
1571        );
1572        assert_eq!(
1573            provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
1574            Some(canonical_block.clone_sealed_header())
1575        );
1576
1577        assert_eq!(
1578            provider.header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
1579            Some(safe_block.header().clone())
1580        );
1581        assert_eq!(
1582            provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
1583            Some(safe_block.clone_sealed_header())
1584        );
1585
1586        assert_eq!(
1587            provider.header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
1588            Some(finalized_block.header().clone())
1589        );
1590        assert_eq!(
1591            provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
1592            Some(finalized_block.clone_sealed_header())
1593        );
1594
1595        Ok(())
1596    }
1597
1598    #[test]
1599    fn test_block_reader_id_ext_header_by_id() -> eyre::Result<()> {
1600        let mut rng = generators::rng();
1601        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1602            &mut rng,
1603            TEST_BLOCKS_COUNT,
1604            TEST_BLOCKS_COUNT,
1605            BlockRangeParams::default(),
1606        )?;
1607
1608        let database_block = database_blocks.first().unwrap().clone();
1609        let in_memory_block = in_memory_blocks.last().unwrap().clone();
1610
1611        let block_number = database_block.number;
1612        let block_hash = database_block.hash();
1613
1614        assert_eq!(
1615            provider.header_by_id(block_number.into()).unwrap(),
1616            Some(database_block.header().clone())
1617        );
1618        assert_eq!(
1619            provider.sealed_header_by_id(block_number.into()).unwrap(),
1620            Some(database_block.clone_sealed_header())
1621        );
1622
1623        assert_eq!(
1624            provider.header_by_id(block_hash.into()).unwrap(),
1625            Some(database_block.header().clone())
1626        );
1627        assert_eq!(
1628            provider.sealed_header_by_id(block_hash.into()).unwrap(),
1629            Some(database_block.clone_sealed_header())
1630        );
1631
1632        let block_number = in_memory_block.number;
1633        let block_hash = in_memory_block.hash();
1634
1635        assert_eq!(
1636            provider.header_by_id(block_number.into()).unwrap(),
1637            Some(in_memory_block.header().clone())
1638        );
1639        assert_eq!(
1640            provider.sealed_header_by_id(block_number.into()).unwrap(),
1641            Some(in_memory_block.clone_sealed_header())
1642        );
1643
1644        assert_eq!(
1645            provider.header_by_id(block_hash.into()).unwrap(),
1646            Some(in_memory_block.header().clone())
1647        );
1648        assert_eq!(
1649            provider.sealed_header_by_id(block_hash.into()).unwrap(),
1650            Some(in_memory_block.clone_sealed_header())
1651        );
1652
1653        Ok(())
1654    }
1655
1656    #[test]
1657    fn test_block_reader_id_ext_ommers_by_id() -> eyre::Result<()> {
1658        let mut rng = generators::rng();
1659        let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1660            &mut rng,
1661            TEST_BLOCKS_COUNT,
1662            TEST_BLOCKS_COUNT,
1663            BlockRangeParams::default(),
1664        )?;
1665
1666        let database_block = database_blocks.first().unwrap().clone();
1667        let in_memory_block = in_memory_blocks.last().unwrap().clone();
1668
1669        let block_number = database_block.number;
1670        let block_hash = database_block.hash();
1671
1672        assert_eq!(
1673            provider.ommers_by_id(block_number.into()).unwrap().unwrap_or_default(),
1674            database_block.body().ommers
1675        );
1676        assert_eq!(
1677            provider.ommers_by_id(block_hash.into()).unwrap().unwrap_or_default(),
1678            database_block.body().ommers
1679        );
1680
1681        let block_number = in_memory_block.number;
1682        let block_hash = in_memory_block.hash();
1683
1684        assert_eq!(
1685            provider.ommers_by_id(block_number.into()).unwrap().unwrap_or_default(),
1686            in_memory_block.body().ommers
1687        );
1688        assert_eq!(
1689            provider.ommers_by_id(block_hash.into()).unwrap().unwrap_or_default(),
1690            in_memory_block.body().ommers
1691        );
1692
1693        Ok(())
1694    }
1695
1696    #[test]
1697    fn test_receipt_provider_id_ext_receipts_by_block_id() -> eyre::Result<()> {
1698        let mut rng = generators::rng();
1699        let (provider, database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
1700            &mut rng,
1701            TEST_BLOCKS_COUNT,
1702            TEST_BLOCKS_COUNT,
1703            BlockRangeParams { tx_count: 1..3, ..Default::default() },
1704        )?;
1705
1706        let database_block = database_blocks.first().unwrap().clone();
1707        let in_memory_block = in_memory_blocks.last().unwrap().clone();
1708
1709        let block_number = database_block.number;
1710        let block_hash = database_block.hash();
1711
1712        assert!(!receipts.get(database_block.number as usize).unwrap().is_empty());
1713        assert!(!provider
1714            .receipts_by_number_or_tag(database_block.number.into())?
1715            .unwrap()
1716            .is_empty());
1717
1718        assert_eq!(
1719            provider.receipts_by_block_id(block_number.into())?.unwrap(),
1720            receipts.get(block_number as usize).unwrap().clone()
1721        );
1722        assert_eq!(
1723            provider.receipts_by_block_id(block_hash.into())?.unwrap(),
1724            receipts.get(block_number as usize).unwrap().clone()
1725        );
1726
1727        let block_number = in_memory_block.number;
1728        let block_hash = in_memory_block.hash();
1729
1730        assert_eq!(
1731            provider.receipts_by_block_id(block_number.into())?.unwrap(),
1732            receipts.get(block_number as usize).unwrap().clone()
1733        );
1734        assert_eq!(
1735            provider.receipts_by_block_id(block_hash.into())?.unwrap(),
1736            receipts.get(block_number as usize).unwrap().clone()
1737        );
1738
1739        Ok(())
1740    }
1741
1742    #[test]
1743    fn test_receipt_provider_id_ext_receipts_by_block_number_or_tag() -> eyre::Result<()> {
1744        let mut rng = generators::rng();
1745        let (provider, database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
1746            &mut rng,
1747            TEST_BLOCKS_COUNT,
1748            TEST_BLOCKS_COUNT,
1749            BlockRangeParams { tx_count: 1..3, ..Default::default() },
1750        )?;
1751
1752        let database_block = database_blocks.first().unwrap().clone();
1753
1754        let in_memory_block_count = in_memory_blocks.len();
1755        let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
1756        let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
1757        let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();
1758
1759        assert!(!receipts.get(database_block.number as usize).unwrap().is_empty());
1760        assert!(!provider
1761            .receipts_by_number_or_tag(database_block.number.into())?
1762            .unwrap()
1763            .is_empty());
1764
1765        assert_eq!(
1766            provider.receipts_by_number_or_tag(database_block.number.into())?.unwrap(),
1767            receipts.get(database_block.number as usize).unwrap().clone()
1768        );
1769        assert_eq!(
1770            provider.receipts_by_number_or_tag(BlockNumberOrTag::Latest)?.unwrap(),
1771            receipts.get(canonical_block.number as usize).unwrap().clone()
1772        );
1773        assert_eq!(
1774            provider.receipts_by_number_or_tag(BlockNumberOrTag::Safe)?.unwrap(),
1775            receipts.get(safe_block.number as usize).unwrap().clone()
1776        );
1777        assert_eq!(
1778            provider.receipts_by_number_or_tag(BlockNumberOrTag::Finalized)?.unwrap(),
1779            receipts.get(finalized_block.number as usize).unwrap().clone()
1780        );
1781
1782        Ok(())
1783    }
1784
1785    #[test]
1786    fn test_changeset_reader() -> eyre::Result<()> {
1787        let mut rng = generators::rng();
1788
1789        let (database_blocks, in_memory_blocks) =
1790            random_blocks(&mut rng, TEST_BLOCKS_COUNT, 1, None, None, 0..1);
1791
1792        let first_database_block = database_blocks.first().map(|block| block.number).unwrap();
1793        let last_database_block = database_blocks.last().map(|block| block.number).unwrap();
1794        let first_in_memory_block = in_memory_blocks.first().map(|block| block.number).unwrap();
1795
1796        let accounts = random_eoa_accounts(&mut rng, 2);
1797
1798        let (database_changesets, database_state) = random_changeset_range(
1799            &mut rng,
1800            &database_blocks,
1801            accounts.into_iter().map(|(address, account)| (address, (account, Vec::new()))),
1802            0..0,
1803            0..0,
1804        );
1805        let (in_memory_changesets, in_memory_state) = random_changeset_range(
1806            &mut rng,
1807            &in_memory_blocks,
1808            database_state
1809                .iter()
1810                .map(|(address, (account, storage))| (*address, (*account, storage.clone()))),
1811            0..0,
1812            0..0,
1813        );
1814
1815        let factory = create_test_provider_factory();
1816
1817        let provider_rw = factory.provider_rw()?;
1818        provider_rw.append_blocks_with_state(
1819            database_blocks
1820                .into_iter()
1821                .map(|b| b.try_recover().expect("failed to seal block with senders"))
1822                .collect(),
1823            &ExecutionOutcome {
1824                bundle: BundleState::new(
1825                    database_state.into_iter().map(|(address, (account, _))| {
1826                        (address, None, Some(account.into()), Default::default())
1827                    }),
1828                    database_changesets
1829                        .iter()
1830                        .map(|block_changesets| {
1831                            block_changesets.iter().map(|(address, account, _)| {
1832                                (*address, Some(Some((*account).into())), [])
1833                            })
1834                        })
1835                        .collect::<Vec<_>>(),
1836                    Vec::new(),
1837                ),
1838                first_block: first_database_block,
1839                ..Default::default()
1840            },
1841            Default::default(),
1842            Default::default(),
1843        )?;
1844        provider_rw.commit()?;
1845
1846        let provider = BlockchainProvider::new(factory)?;
1847
1848        let in_memory_changesets = in_memory_changesets.into_iter().next().unwrap();
1849        let chain = NewCanonicalChain::Commit {
1850            new: vec![in_memory_blocks
1851                .first()
1852                .map(|block| {
1853                    let senders = block.senders().expect("failed to recover senders");
1854                    ExecutedBlockWithTrieUpdates::new(
1855                        Arc::new(RecoveredBlock::new_sealed(block.clone(), senders)),
1856                        Arc::new(ExecutionOutcome {
1857                            bundle: BundleState::new(
1858                                in_memory_state.into_iter().map(|(address, (account, _))| {
1859                                    (address, None, Some(account.into()), Default::default())
1860                                }),
1861                                [in_memory_changesets.iter().map(|(address, account, _)| {
1862                                    (*address, Some(Some((*account).into())), Vec::new())
1863                                })],
1864                                [],
1865                            ),
1866                            first_block: first_in_memory_block,
1867                            ..Default::default()
1868                        }),
1869                        Default::default(),
1870                        Default::default(),
1871                    )
1872                })
1873                .unwrap()],
1874        };
1875        provider.canonical_in_memory_state.update_chain(chain);
1876
1877        assert_eq!(
1878            provider.account_block_changeset(last_database_block).unwrap(),
1879            database_changesets
1880                .into_iter()
1881                .next_back()
1882                .unwrap()
1883                .into_iter()
1884                .sorted_by_key(|(address, _, _)| *address)
1885                .map(|(address, account, _)| AccountBeforeTx { address, info: Some(account) })
1886                .collect::<Vec<_>>()
1887        );
1888        assert_eq!(
1889            provider.account_block_changeset(first_in_memory_block).unwrap(),
1890            in_memory_changesets
1891                .into_iter()
1892                .sorted_by_key(|(address, _, _)| *address)
1893                .map(|(address, account, _)| AccountBeforeTx { address, info: Some(account) })
1894                .collect::<Vec<_>>()
1895        );
1896
1897        Ok(())
1898    }
1899
1900    #[test]
1901    fn test_state_provider_factory() -> eyre::Result<()> {
1902        let mut rng = generators::rng();
1903
1904        // test in-memory state use-cases
1905        let (in_memory_provider, _, in_memory_blocks, _) = provider_with_random_blocks(
1906            &mut rng,
1907            TEST_BLOCKS_COUNT,
1908            TEST_BLOCKS_COUNT,
1909            BlockRangeParams::default(),
1910        )?;
1911
1912        // test database state use-cases
1913        let (only_database_provider, database_blocks, _, _) = provider_with_random_blocks(
1914            &mut rng,
1915            TEST_BLOCKS_COUNT,
1916            0,
1917            BlockRangeParams::default(),
1918        )?;
1919
1920        let blocks = [database_blocks.clone(), in_memory_blocks.clone()].concat();
1921        let first_in_memory_block = in_memory_blocks.first().unwrap();
1922        let first_db_block = database_blocks.first().unwrap();
1923
1924        // test latest state
1925        assert_eq!(
1926            first_in_memory_block.hash(),
1927            in_memory_provider.latest().unwrap().block_hash(first_in_memory_block.number)?.unwrap()
1928        );
1929        // test latest falls back to database state when there's no in-memory block
1930        assert_eq!(
1931            first_db_block.hash(),
1932            only_database_provider.latest().unwrap().block_hash(first_db_block.number)?.unwrap()
1933        );
1934
1935        // test history by block number
1936        assert_eq!(
1937            first_in_memory_block.hash(),
1938            in_memory_provider
1939                .history_by_block_number(first_in_memory_block.number)?
1940                .block_hash(first_in_memory_block.number)?
1941                .unwrap()
1942        );
1943        assert_eq!(
1944            first_db_block.hash(),
1945            only_database_provider
1946                .history_by_block_number(first_db_block.number)?
1947                .block_hash(first_db_block.number)?
1948                .unwrap()
1949        );
1950        assert_eq!(
1951            first_in_memory_block.hash(),
1952            in_memory_provider
1953                .history_by_block_hash(first_in_memory_block.hash())?
1954                .block_hash(first_in_memory_block.number)?
1955                .unwrap()
1956        );
1957        assert!(only_database_provider.history_by_block_hash(B256::random()).is_err());
1958
1959        // test state by block hash
1960        assert_eq!(
1961            first_in_memory_block.hash(),
1962            in_memory_provider
1963                .state_by_block_hash(first_in_memory_block.hash())?
1964                .block_hash(first_in_memory_block.number)?
1965                .unwrap()
1966        );
1967        assert_eq!(
1968            first_db_block.hash(),
1969            only_database_provider
1970                .state_by_block_hash(first_db_block.hash())?
1971                .block_hash(first_db_block.number)?
1972                .unwrap()
1973        );
1974        assert!(only_database_provider.state_by_block_hash(B256::random()).is_err());
1975
1976        // test pending without pending state- falls back to latest
1977        assert_eq!(
1978            first_in_memory_block.hash(),
1979            in_memory_provider
1980                .pending()
1981                .unwrap()
1982                .block_hash(first_in_memory_block.number)
1983                .unwrap()
1984                .unwrap()
1985        );
1986
1987        // adding a pending block to state can test pending() and  pending_state_by_hash() function
1988        let pending_block = database_blocks[database_blocks.len() - 1].clone();
1989        only_database_provider.canonical_in_memory_state.set_pending_block(
1990            ExecutedBlockWithTrieUpdates {
1991                block: ExecutedBlock {
1992                    recovered_block: Arc::new(RecoveredBlock::new_sealed(
1993                        pending_block.clone(),
1994                        Default::default(),
1995                    )),
1996                    execution_output: Default::default(),
1997                    hashed_state: Default::default(),
1998                },
1999                trie: Default::default(),
2000            },
2001        );
2002
2003        assert_eq!(
2004            pending_block.hash(),
2005            only_database_provider
2006                .pending()
2007                .unwrap()
2008                .block_hash(pending_block.number)
2009                .unwrap()
2010                .unwrap()
2011        );
2012
2013        assert_eq!(
2014            pending_block.hash(),
2015            only_database_provider
2016                .pending_state_by_hash(pending_block.hash())?
2017                .unwrap()
2018                .block_hash(pending_block.number)?
2019                .unwrap()
2020        );
2021
2022        // test state by block number or tag
2023        assert_eq!(
2024            first_in_memory_block.hash(),
2025            in_memory_provider
2026                .state_by_block_number_or_tag(BlockNumberOrTag::Number(
2027                    first_in_memory_block.number
2028                ))?
2029                .block_hash(first_in_memory_block.number)?
2030                .unwrap()
2031        );
2032        assert_eq!(
2033            first_in_memory_block.hash(),
2034            in_memory_provider
2035                .state_by_block_number_or_tag(BlockNumberOrTag::Latest)?
2036                .block_hash(first_in_memory_block.number)?
2037                .unwrap()
2038        );
2039        // test state by block tag for safe block
2040        let safe_block = in_memory_blocks[in_memory_blocks.len() - 2].clone();
2041        in_memory_provider.canonical_in_memory_state.set_safe(safe_block.clone_sealed_header());
2042        assert_eq!(
2043            safe_block.hash(),
2044            in_memory_provider
2045                .state_by_block_number_or_tag(BlockNumberOrTag::Safe)?
2046                .block_hash(safe_block.number)?
2047                .unwrap()
2048        );
2049        // test state by block tag for finalized block
2050        let finalized_block = in_memory_blocks[in_memory_blocks.len() - 3].clone();
2051        in_memory_provider
2052            .canonical_in_memory_state
2053            .set_finalized(finalized_block.clone_sealed_header());
2054        assert_eq!(
2055            finalized_block.hash(),
2056            in_memory_provider
2057                .state_by_block_number_or_tag(BlockNumberOrTag::Finalized)?
2058                .block_hash(finalized_block.number)?
2059                .unwrap()
2060        );
2061        // test state by block tag for earliest block
2062        let earliest_block = blocks.first().unwrap().clone();
2063        assert_eq!(
2064            earliest_block.hash(),
2065            only_database_provider
2066                .state_by_block_number_or_tag(BlockNumberOrTag::Earliest)?
2067                .block_hash(earliest_block.number)?
2068                .unwrap()
2069        );
2070
2071        Ok(())
2072    }
2073
2074    #[test]
2075    fn test_block_id_reader() -> eyre::Result<()> {
2076        // Create a new provider
2077        let mut rng = generators::rng();
2078        let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
2079            &mut rng,
2080            TEST_BLOCKS_COUNT,
2081            TEST_BLOCKS_COUNT,
2082            BlockRangeParams::default(),
2083        )?;
2084
2085        // Set the pending block in memory
2086        let pending_block = in_memory_blocks.last().unwrap();
2087        provider.canonical_in_memory_state.set_pending_block(ExecutedBlockWithTrieUpdates {
2088            block: ExecutedBlock {
2089                recovered_block: Arc::new(RecoveredBlock::new_sealed(
2090                    pending_block.clone(),
2091                    Default::default(),
2092                )),
2093                execution_output: Default::default(),
2094                hashed_state: Default::default(),
2095            },
2096            trie: Default::default(),
2097        });
2098
2099        // Set the safe block in memory
2100        let safe_block = in_memory_blocks[in_memory_blocks.len() - 2].clone();
2101        provider.canonical_in_memory_state.set_safe(safe_block.clone_sealed_header());
2102
2103        // Set the finalized block in memory
2104        let finalized_block = in_memory_blocks[in_memory_blocks.len() - 3].clone();
2105        provider.canonical_in_memory_state.set_finalized(finalized_block.clone_sealed_header());
2106
2107        // Verify the pending block number and hash
2108        assert_eq!(
2109            provider.pending_block_num_hash()?,
2110            Some(BlockNumHash { number: pending_block.number, hash: pending_block.hash() })
2111        );
2112
2113        // Verify the safe block number and hash
2114        assert_eq!(
2115            provider.safe_block_num_hash()?,
2116            Some(BlockNumHash { number: safe_block.number, hash: safe_block.hash() })
2117        );
2118
2119        // Verify the finalized block number and hash
2120        assert_eq!(
2121            provider.finalized_block_num_hash()?,
2122            Some(BlockNumHash { number: finalized_block.number, hash: finalized_block.hash() })
2123        );
2124
2125        Ok(())
2126    }
2127
2128    macro_rules! test_by_tx_range {
2129        ([$(($method:ident, $data_extractor:expr)),* $(,)?]) => {{
2130
2131            // Get the number methods being tested.
2132            // Since each method tested will move a block from memory to storage, this ensures we have enough.
2133            let extra_blocks = [$(stringify!($method)),*].len();
2134
2135            let mut rng = generators::rng();
2136            let (provider, mut database_blocks, mut in_memory_blocks, receipts) = provider_with_random_blocks(
2137                &mut rng,
2138                TEST_BLOCKS_COUNT,
2139                TEST_BLOCKS_COUNT + extra_blocks,
2140                BlockRangeParams {
2141                    tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2142                    ..Default::default()
2143                },
2144            )?;
2145
2146            $(
2147                // Since data moves for each tried method, need to recalculate everything
2148                let db_tx_count =
2149                    database_blocks.iter().map(|b| b.transaction_count()).sum::<usize>() as u64;
2150                let in_mem_tx_count =
2151                    in_memory_blocks.iter().map(|b| b.transaction_count()).sum::<usize>() as u64;
2152
2153                let db_range = 0..=(db_tx_count - 1);
2154                let in_mem_range = db_tx_count..=(in_mem_tx_count + db_range.end());
2155
2156                // Retrieve the expected database data
2157                let database_data =
2158                    database_blocks.iter().flat_map(|b| $data_extractor(b, &receipts)).collect::<Vec<_>>();
2159                assert_eq!(provider.$method(db_range.clone())?, database_data, "full db data");
2160
2161                // Retrieve the expected in-memory data
2162                let in_memory_data =
2163                    in_memory_blocks.iter().flat_map(|b| $data_extractor(b, &receipts)).collect::<Vec<_>>();
2164                assert_eq!(provider.$method(in_mem_range.clone())?, in_memory_data, "full mem data");
2165
2166                // Test partial in-memory range
2167                assert_eq!(
2168                    &provider.$method(in_mem_range.start() + 1..=in_mem_range.end() - 1)?,
2169                    &in_memory_data[1..in_memory_data.len() - 1],
2170                    "partial mem data"
2171                );
2172
2173                // Test range in in-memory to unbounded end
2174                assert_eq!(provider.$method(in_mem_range.start() + 1..)?, &in_memory_data[1..], "unbounded mem data");
2175
2176                // Test last element in-memory
2177                assert_eq!(provider.$method(in_mem_range.end()..)?, &in_memory_data[in_memory_data.len() -1 ..], "last mem data");
2178
2179                // Test range that spans database and in-memory with unbounded end
2180                assert_eq!(
2181                    provider.$method(in_mem_range.start() - 2..)?,
2182                    database_data[database_data.len() - 2..]
2183                        .iter()
2184                        .chain(&in_memory_data[..])
2185                        .cloned()
2186                        .collect::<Vec<_>>(),
2187                    "unbounded span data"
2188                );
2189
2190                // Test range that spans database and in-memory
2191                {
2192                    // 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.
2193                    persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2194
2195                    assert_eq!(
2196                        provider.$method(in_mem_range.start() - 2..=in_mem_range.end() - 1)?,
2197                        database_data[database_data.len() - 2..]
2198                            .iter()
2199                            .chain(&in_memory_data[..in_memory_data.len() - 1])
2200                            .cloned()
2201                            .collect::<Vec<_>>(),
2202                        "span data"
2203                    );
2204
2205                    // Adjust our blocks accordingly
2206                    database_blocks.push(in_memory_blocks.remove(0));
2207                }
2208
2209                // Test invalid range
2210                let start_tx_num = u64::MAX;
2211                let end_tx_num = u64::MAX;
2212                let result = provider.$method(start_tx_num..end_tx_num)?;
2213                assert!(result.is_empty(), "No data should be found for an invalid transaction range");
2214
2215                // Test empty range
2216                let result = provider.$method(in_mem_range.end()+10..in_mem_range.end()+20)?;
2217                assert!(result.is_empty(), "No data should be found for an empty transaction range");
2218            )*
2219        }};
2220    }
2221
2222    #[test]
2223    fn test_methods_by_tx_range() -> eyre::Result<()> {
2224        test_by_tx_range!([
2225            (senders_by_tx_range, |block: &SealedBlock<Block>, _: &Vec<Vec<Receipt>>| block
2226                .senders()
2227                .unwrap()),
2228            (transactions_by_tx_range, |block: &SealedBlock<Block>, _: &Vec<Vec<Receipt>>| block
2229                .body()
2230                .transactions
2231                .clone()),
2232            (receipts_by_tx_range, |block: &SealedBlock<Block>, receipts: &Vec<Vec<Receipt>>| {
2233                receipts[block.number as usize].clone()
2234            })
2235        ]);
2236
2237        Ok(())
2238    }
2239
2240    macro_rules! test_by_block_range {
2241        ([$(($method:ident, $data_extractor:expr)),* $(,)?]) => {{
2242            // Get the number methods being tested.
2243            // Since each method tested will move a block from memory to storage, this ensures we have enough.
2244            let extra_blocks = [$(stringify!($method)),*].len();
2245
2246            let mut rng = generators::rng();
2247            let (provider, mut database_blocks, mut in_memory_blocks, _) = provider_with_random_blocks(
2248                &mut rng,
2249                TEST_BLOCKS_COUNT,
2250                TEST_BLOCKS_COUNT + extra_blocks,
2251                BlockRangeParams {
2252                    tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2253                    ..Default::default()
2254                },
2255            )?;
2256
2257            $(
2258                // Since data moves for each tried method, need to recalculate everything
2259                let db_block_count = database_blocks.len() as u64;
2260                let in_mem_block_count = in_memory_blocks.len() as u64;
2261
2262                let db_range = 0..=db_block_count - 1;
2263                let in_mem_range = db_block_count..=(in_mem_block_count + db_range.end());
2264
2265                // Retrieve the expected database data
2266                let database_data =
2267                    database_blocks.iter().map(|b| $data_extractor(b)).collect::<Vec<_>>();
2268                assert_eq!(provider.$method(db_range.clone())?, database_data);
2269
2270                // Retrieve the expected in-memory data
2271                let in_memory_data =
2272                    in_memory_blocks.iter().map(|b| $data_extractor(b)).collect::<Vec<_>>();
2273                assert_eq!(provider.$method(in_mem_range.clone())?, in_memory_data);
2274
2275                // Test partial in-memory range
2276                assert_eq!(
2277                    &provider.$method(in_mem_range.start() + 1..=in_mem_range.end() - 1)?,
2278                    &in_memory_data[1..in_memory_data.len() - 1]
2279                );
2280
2281                // Test range that spans database and in-memory
2282                {
2283
2284                    // 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.
2285                    persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2286
2287                    assert_eq!(
2288                        provider.$method(in_mem_range.start() - 2..=in_mem_range.end() - 1)?,
2289                        database_data[database_data.len() - 2..]
2290                            .iter()
2291                            .chain(&in_memory_data[..in_memory_data.len() - 1])
2292                            .cloned()
2293                            .collect::<Vec<_>>()
2294                    );
2295
2296                    // Adjust our blocks accordingly
2297                    database_blocks.push(in_memory_blocks.remove(0));
2298                }
2299
2300                // Test invalid range
2301                let start_block_num = u64::MAX;
2302                let end_block_num = u64::MAX;
2303                let result = provider.$method(start_block_num..=end_block_num-1)?;
2304                assert!(result.is_empty(), "No data should be found for an invalid block range");
2305
2306                // Test valid range with empty results
2307                let result = provider.$method(in_mem_range.end() + 10..=in_mem_range.end() + 20)?;
2308                assert!(result.is_empty(), "No data should be found for an empty block range");
2309            )*
2310        }};
2311    }
2312
2313    #[test]
2314    fn test_methods_by_block_range() -> eyre::Result<()> {
2315        // todo(joshie) add canonical_hashes_range below after changing its interface into range
2316        // instead start end
2317        test_by_block_range!([
2318            (headers_range, |block: &SealedBlock<Block>| block.header().clone()),
2319            (sealed_headers_range, |block: &SealedBlock<Block>| block.clone_sealed_header()),
2320            (block_range, |block: &SealedBlock<Block>| block.clone().into_block()),
2321            (block_with_senders_range, |block: &SealedBlock<Block>| block
2322                .clone()
2323                .try_recover()
2324                .unwrap()),
2325            (recovered_block_range, |block: &SealedBlock<Block>| block
2326                .clone()
2327                .try_recover()
2328                .unwrap()),
2329            (transactions_by_block_range, |block: &SealedBlock<Block>| block
2330                .body()
2331                .transactions
2332                .clone()),
2333        ]);
2334
2335        Ok(())
2336    }
2337
2338    /// Helper macro to call a provider method based on argument count and check its result
2339    macro_rules! call_method {
2340        ($provider:expr, $method:ident, ($($args:expr),*), $expected_item:expr) => {{
2341            let result = $provider.$method($($args),*)?;
2342            assert_eq!(
2343                result,
2344                $expected_item,
2345                "{}: item does not match the expected item for arguments {:?}",
2346                stringify!($method),
2347                ($($args),*)
2348            );
2349        }};
2350
2351        // Handle valid or invalid arguments for one argument
2352        (ONE, $provider:expr, $method:ident, $item_extractor:expr, $txnum:expr, $txhash:expr, $block:expr, $receipts:expr) => {{
2353            let (arg, expected_item) = $item_extractor($block, $txnum($block), $txhash($block), $receipts);
2354            call_method!($provider, $method, (arg), expected_item);
2355        }};
2356
2357        // Handle valid or invalid arguments for two arguments
2358        (TWO, $provider:expr, $method:ident, $item_extractor:expr, $txnum:expr, $txhash:expr, $block:expr, $receipts:expr) => {{
2359            let ((arg1, arg2), expected_item) = $item_extractor($block, $txnum($block), $txhash($block), $receipts);
2360            call_method!($provider, $method, (arg1, arg2), expected_item);
2361        }};
2362    }
2363
2364    /// Macro to test non-range methods.
2365    ///
2366    /// ( `NUMBER_ARGUMENTS`, METHOD, FN -> ((`METHOD_ARGUMENT(s)`,...), `EXPECTED_RESULT`),
2367    /// `INVALID_ARGUMENTS`)
2368    macro_rules! test_non_range {
2369    ([$(($arg_count:ident, $method:ident, $item_extractor:expr, $invalid_args:expr)),* $(,)?]) => {{
2370
2371        // Get the number methods being tested.
2372        // Since each method tested will move a block from memory to storage, this ensures we have enough.
2373        let extra_blocks = [$(stringify!($arg_count)),*].len();
2374
2375        let mut rng = generators::rng();
2376        let (provider, mut database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
2377            &mut rng,
2378            TEST_BLOCKS_COUNT,
2379            TEST_BLOCKS_COUNT + extra_blocks,
2380            BlockRangeParams {
2381                tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2382                ..Default::default()
2383            },
2384        )?;
2385
2386        let mut in_memory_blocks: std::collections::VecDeque<_> = in_memory_blocks.into();
2387
2388        $(
2389            let tx_hash = |block: &SealedBlock<Block>| *block.body().transactions[0].tx_hash();
2390            let tx_num = |block: &SealedBlock<Block>| {
2391                database_blocks
2392                    .iter()
2393                    .chain(in_memory_blocks.iter())
2394                    .take_while(|b| b.number < block.number)
2395                    .map(|b| b.transaction_count())
2396                    .sum::<usize>() as u64
2397            };
2398
2399            // Ensure that the first generated in-memory block exists
2400            {
2401                // 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.
2402                persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2403
2404                call_method!($arg_count, provider, $method, $item_extractor, tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2405
2406                // Move the block as well in our own structures
2407                database_blocks.push(in_memory_blocks.pop_front().unwrap());
2408            }
2409
2410            // database_blocks is changed above
2411            let tx_num = |block: &SealedBlock<Block>| {
2412                database_blocks
2413                    .iter()
2414                    .chain(in_memory_blocks.iter())
2415                    .take_while(|b| b.number < block.number)
2416                    .map(|b| b.transaction_count())
2417                    .sum::<usize>() as u64
2418            };
2419
2420            // Invalid/Non-existent argument should return `None`
2421            {
2422                call_method!($arg_count, provider, $method, |_,_,_,_| ( ($invalid_args, None)), tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2423            }
2424
2425            // Check that the item is only in memory and not in database
2426            {
2427                let last_mem_block = &in_memory_blocks[in_memory_blocks.len() - 1];
2428
2429                let (args, expected_item) = $item_extractor(last_mem_block, tx_num(last_mem_block), tx_hash(last_mem_block), &receipts);
2430                call_method!($arg_count, provider, $method, |_,_,_,_| (args.clone(), expected_item), tx_num, tx_hash, last_mem_block, &receipts);
2431
2432                // Ensure the item is not in storage
2433                call_method!($arg_count, provider.database, $method, |_,_,_,_| ( (args, None)), tx_num, tx_hash, last_mem_block, &receipts);
2434            }
2435        )*
2436    }};
2437}
2438
2439    #[test]
2440    fn test_non_range_methods() -> eyre::Result<()> {
2441        let test_tx_index = 0;
2442
2443        test_non_range!([
2444            // TODO: header should use B256 like others instead of &B256
2445            // (
2446            //     ONE,
2447            //     header,
2448            //     |block: &SealedBlock, tx_num: TxNumber, tx_hash: B256, receipts: &Vec<Vec<Receipt>>| (&block.hash(), Some(block.header.header().clone())),
2449            //     (&B256::random())
2450            // ),
2451            (
2452                ONE,
2453                header_by_number,
2454                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2455                    block.number,
2456                    Some(block.header().clone())
2457                ),
2458                u64::MAX
2459            ),
2460            (
2461                ONE,
2462                sealed_header,
2463                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2464                    block.number,
2465                    Some(block.clone_sealed_header())
2466                ),
2467                u64::MAX
2468            ),
2469            (
2470                ONE,
2471                block_hash,
2472                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2473                    block.number,
2474                    Some(block.hash())
2475                ),
2476                u64::MAX
2477            ),
2478            (
2479                ONE,
2480                block_number,
2481                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2482                    block.hash(),
2483                    Some(block.number)
2484                ),
2485                B256::random()
2486            ),
2487            (
2488                ONE,
2489                block,
2490                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2491                    BlockHashOrNumber::Hash(block.hash()),
2492                    Some(block.clone().into_block())
2493                ),
2494                BlockHashOrNumber::Hash(B256::random())
2495            ),
2496            (
2497                ONE,
2498                block,
2499                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2500                    BlockHashOrNumber::Number(block.number),
2501                    Some(block.clone().into_block())
2502                ),
2503                BlockHashOrNumber::Number(u64::MAX)
2504            ),
2505            (
2506                ONE,
2507                block_body_indices,
2508                |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2509                    block.number,
2510                    Some(StoredBlockBodyIndices {
2511                        first_tx_num: tx_num,
2512                        tx_count: block.transaction_count() as u64
2513                    })
2514                ),
2515                u64::MAX
2516            ),
2517            (
2518                TWO,
2519                recovered_block,
2520                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2521                    (BlockHashOrNumber::Number(block.number), TransactionVariant::WithHash),
2522                    block.clone().try_recover().ok()
2523                ),
2524                (BlockHashOrNumber::Number(u64::MAX), TransactionVariant::WithHash)
2525            ),
2526            (
2527                TWO,
2528                recovered_block,
2529                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2530                    (BlockHashOrNumber::Hash(block.hash()), TransactionVariant::WithHash),
2531                    block.clone().try_recover().ok()
2532                ),
2533                (BlockHashOrNumber::Hash(B256::random()), TransactionVariant::WithHash)
2534            ),
2535            (
2536                TWO,
2537                sealed_block_with_senders,
2538                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2539                    (BlockHashOrNumber::Number(block.number), TransactionVariant::WithHash),
2540                    block.clone().try_recover().ok()
2541                ),
2542                (BlockHashOrNumber::Number(u64::MAX), TransactionVariant::WithHash)
2543            ),
2544            (
2545                TWO,
2546                sealed_block_with_senders,
2547                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2548                    (BlockHashOrNumber::Hash(block.hash()), TransactionVariant::WithHash),
2549                    block.clone().try_recover().ok()
2550                ),
2551                (BlockHashOrNumber::Hash(B256::random()), TransactionVariant::WithHash)
2552            ),
2553            (
2554                ONE,
2555                transaction_id,
2556                |_: &SealedBlock<Block>, tx_num: TxNumber, tx_hash: B256, _: &Vec<Vec<Receipt>>| (
2557                    tx_hash,
2558                    Some(tx_num)
2559                ),
2560                B256::random()
2561            ),
2562            (
2563                ONE,
2564                transaction_by_id,
2565                |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2566                    tx_num,
2567                    Some(block.body().transactions[test_tx_index].clone())
2568                ),
2569                u64::MAX
2570            ),
2571            (
2572                ONE,
2573                transaction_by_id_unhashed,
2574                |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2575                    tx_num,
2576                    Some(block.body().transactions[test_tx_index].clone())
2577                ),
2578                u64::MAX
2579            ),
2580            (
2581                ONE,
2582                transaction_by_hash,
2583                |block: &SealedBlock<Block>, _: TxNumber, tx_hash: B256, _: &Vec<Vec<Receipt>>| (
2584                    tx_hash,
2585                    Some(block.body().transactions[test_tx_index].clone())
2586                ),
2587                B256::random()
2588            ),
2589            (
2590                ONE,
2591                transaction_block,
2592                |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2593                    tx_num,
2594                    Some(block.number)
2595                ),
2596                u64::MAX
2597            ),
2598            (
2599                ONE,
2600                transactions_by_block,
2601                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2602                    BlockHashOrNumber::Number(block.number),
2603                    Some(block.body().transactions.clone())
2604                ),
2605                BlockHashOrNumber::Number(u64::MAX)
2606            ),
2607            (
2608                ONE,
2609                transactions_by_block,
2610                |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2611                    BlockHashOrNumber::Hash(block.hash()),
2612                    Some(block.body().transactions.clone())
2613                ),
2614                BlockHashOrNumber::Number(u64::MAX)
2615            ),
2616            (
2617                ONE,
2618                transaction_sender,
2619                |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2620                    tx_num,
2621                    block.body().transactions[test_tx_index].recover_signer().ok()
2622                ),
2623                u64::MAX
2624            ),
2625            (
2626                ONE,
2627                receipt,
2628                |block: &SealedBlock<Block>,
2629                 tx_num: TxNumber,
2630                 _: B256,
2631                 receipts: &Vec<Vec<Receipt>>| (
2632                    tx_num,
2633                    Some(receipts[block.number as usize][test_tx_index].clone())
2634                ),
2635                u64::MAX
2636            ),
2637            (
2638                ONE,
2639                receipt_by_hash,
2640                |block: &SealedBlock<Block>,
2641                 _: TxNumber,
2642                 tx_hash: B256,
2643                 receipts: &Vec<Vec<Receipt>>| (
2644                    tx_hash,
2645                    Some(receipts[block.number as usize][test_tx_index].clone())
2646                ),
2647                B256::random()
2648            ),
2649            (
2650                ONE,
2651                receipts_by_block,
2652                |block: &SealedBlock<Block>, _: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2653                    BlockHashOrNumber::Number(block.number),
2654                    Some(receipts[block.number as usize].clone())
2655                ),
2656                BlockHashOrNumber::Number(u64::MAX)
2657            ),
2658            (
2659                ONE,
2660                receipts_by_block,
2661                |block: &SealedBlock<Block>, _: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2662                    BlockHashOrNumber::Hash(block.hash()),
2663                    Some(receipts[block.number as usize].clone())
2664                ),
2665                BlockHashOrNumber::Hash(B256::random())
2666            ),
2667            // TODO: withdrawals, requests, ommers
2668        ]);
2669
2670        Ok(())
2671    }
2672
2673    #[test]
2674    fn test_race() -> eyre::Result<()> {
2675        let mut rng = generators::rng();
2676        let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
2677            &mut rng,
2678            TEST_BLOCKS_COUNT - 1,
2679            TEST_BLOCKS_COUNT + 1,
2680            BlockRangeParams {
2681                tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2682                ..Default::default()
2683            },
2684        )?;
2685
2686        // Old implementation was querying the database first. This is problematic, if there are
2687        // changes AFTER the database transaction is created.
2688        let old_transaction_hash_fn =
2689            |hash: B256,
2690             canonical_in_memory_state: CanonicalInMemoryState,
2691             factory: ProviderFactory<MockNodeTypesWithDB>| {
2692                assert!(factory.transaction_by_hash(hash)?.is_none(), "should not be in database");
2693                Ok::<_, ProviderError>(canonical_in_memory_state.transaction_by_hash(hash))
2694            };
2695
2696        // Correct implementation queries in-memory first
2697        let correct_transaction_hash_fn =
2698            |hash: B256,
2699             canonical_in_memory_state: CanonicalInMemoryState,
2700             _factory: ProviderFactory<MockNodeTypesWithDB>| {
2701                if let Some(tx) = canonical_in_memory_state.transaction_by_hash(hash) {
2702                    return Ok::<_, ProviderError>(Some(tx));
2703                }
2704                panic!("should not be in database");
2705                // _factory.transaction_by_hash(hash)
2706            };
2707
2708        // OLD BEHAVIOUR
2709        {
2710            // This will persist block 1 AFTER a database is created. Moving it from memory to
2711            // storage.
2712            persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2713            let to_be_persisted_tx = in_memory_blocks[0].body().transactions[0].clone();
2714
2715            // Even though the block exists, given the order of provider queries done in the method
2716            // above, we do not see it.
2717            assert!(matches!(
2718                old_transaction_hash_fn(
2719                    *to_be_persisted_tx.tx_hash(),
2720                    provider.canonical_in_memory_state(),
2721                    provider.database.clone()
2722                ),
2723                Ok(None)
2724            ));
2725        }
2726
2727        // CORRECT BEHAVIOUR
2728        {
2729            // This will persist block 1 AFTER a database is created. Moving it from memory to
2730            // storage.
2731            persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[1].number);
2732            let to_be_persisted_tx = in_memory_blocks[1].body().transactions[0].clone();
2733
2734            assert!(matches!(
2735                correct_transaction_hash_fn(
2736                    *to_be_persisted_tx.tx_hash(),
2737                    provider.canonical_in_memory_state(),
2738                    provider.database
2739                ),
2740                Ok(Some(to_be_persisted_tx))
2741            ));
2742        }
2743
2744        Ok(())
2745    }
2746}