reth_provider/providers/
blockchain_provider.rs

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