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