reth_provider/providers/
blockchain_provider.rs

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