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