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_evm::{ConfigureEvm, EvmEnv};
30use reth_execution_types::ExecutionOutcome;
31use reth_node_types::{BlockTy, HeaderTy, NodeTypesWithDB, ReceiptTy, TxTy};
32use reth_primitives::{
33 Account, Block, EthPrimitives, NodePrimitives, Receipt, RecoveredBlock, SealedBlock,
34 SealedHeader, StorageEntry, TransactionSigned,
35};
36use reth_primitives_traits::BlockBody;
37use reth_prune_types::{PruneCheckpoint, PruneSegment};
38use reth_stages_types::{StageCheckpoint, StageId};
39use reth_storage_api::{
40 BlockBodyIndicesProvider, DBProvider, NodePrimitivesProvider, OmmersProvider,
41 StateCommitmentProvider, StorageChangeSetReader,
42};
43use reth_storage_errors::provider::ProviderResult;
44use reth_trie::HashedPostState;
45use reth_trie_db::StateCommitment;
46use revm_database::BundleState;
47use std::{
48 ops::{Add, RangeBounds, RangeInclusive, Sub},
49 sync::Arc,
50 time::Instant,
51};
52use tracing::trace;
53
54#[derive(Debug)]
60pub struct BlockchainProvider<N: NodeTypesWithDB> {
61 pub(crate) database: ProviderFactory<N>,
63 pub(crate) canonical_in_memory_state: CanonicalInMemoryState<N::Primitives>,
66}
67
68impl<N: NodeTypesWithDB> Clone for BlockchainProvider<N> {
69 fn clone(&self) -> Self {
70 Self {
71 database: self.database.clone(),
72 canonical_in_memory_state: self.canonical_in_memory_state.clone(),
73 }
74 }
75}
76
77impl<N: ProviderNodeTypes> BlockchainProvider<N> {
78 pub fn new(storage: ProviderFactory<N>) -> ProviderResult<Self> {
81 let provider = storage.provider()?;
82 let best = provider.chain_info()?;
83 match provider.header_by_number(best.best_number)? {
84 Some(header) => {
85 drop(provider);
86 Ok(Self::with_latest(storage, SealedHeader::new(header, best.best_hash))?)
87 }
88 None => Err(ProviderError::HeaderNotFound(best.best_number.into())),
89 }
90 }
91
92 pub fn with_latest(
98 storage: ProviderFactory<N>,
99 latest: SealedHeader<HeaderTy<N>>,
100 ) -> ProviderResult<Self> {
101 let provider = storage.provider()?;
102 let finalized_header = provider
103 .last_finalized_block_number()?
104 .map(|num| provider.sealed_header(num))
105 .transpose()?
106 .flatten();
107 let safe_header = provider
108 .last_safe_block_number()?
109 .or_else(|| {
110 provider.last_finalized_block_number().ok().flatten()
113 })
114 .map(|num| provider.sealed_header(num))
115 .transpose()?
116 .flatten();
117 Ok(Self {
118 database: storage,
119 canonical_in_memory_state: CanonicalInMemoryState::with_head(
120 latest,
121 finalized_header,
122 safe_header,
123 ),
124 })
125 }
126
127 pub fn canonical_in_memory_state(&self) -> CanonicalInMemoryState<N::Primitives> {
129 self.canonical_in_memory_state.clone()
130 }
131
132 #[track_caller]
136 pub fn consistent_provider(&self) -> ProviderResult<ConsistentProvider<N>> {
137 ConsistentProvider::new(self.database.clone(), self.canonical_in_memory_state())
138 }
139
140 fn block_state_provider(
142 &self,
143 state: &BlockState<N::Primitives>,
144 ) -> ProviderResult<MemoryOverlayStateProvider<N::Primitives>> {
145 let anchor_hash = state.anchor().hash;
146 let latest_historical = self.database.history_by_block_hash(anchor_hash)?;
147 Ok(state.state_provider(latest_historical))
148 }
149
150 pub fn get_state(
154 &self,
155 range: RangeInclusive<BlockNumber>,
156 ) -> ProviderResult<Option<ExecutionOutcome<ReceiptTy<N>>>> {
157 self.consistent_provider()?.get_state(range)
158 }
159}
160
161impl<N: NodeTypesWithDB> NodePrimitivesProvider for BlockchainProvider<N> {
162 type Primitives = N::Primitives;
163}
164
165impl<N: ProviderNodeTypes> DatabaseProviderFactory for BlockchainProvider<N> {
166 type DB = N::DB;
167 type Provider = <ProviderFactory<N> as DatabaseProviderFactory>::Provider;
168 type ProviderRW = <ProviderFactory<N> as DatabaseProviderFactory>::ProviderRW;
169
170 fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
171 self.database.database_provider_ro()
172 }
173
174 fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
175 self.database.database_provider_rw()
176 }
177}
178
179impl<N: ProviderNodeTypes> StateCommitmentProvider for BlockchainProvider<N> {
180 type StateCommitment = N::StateCommitment;
181}
182
183impl<N: ProviderNodeTypes> StaticFileProviderFactory for BlockchainProvider<N> {
184 fn static_file_provider(&self) -> StaticFileProvider<Self::Primitives> {
185 self.database.static_file_provider()
186 }
187}
188
189impl<N: ProviderNodeTypes> HeaderProvider for BlockchainProvider<N> {
190 type Header = HeaderTy<N>;
191
192 fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Self::Header>> {
193 self.consistent_provider()?.header(block_hash)
194 }
195
196 fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Self::Header>> {
197 self.consistent_provider()?.header_by_number(num)
198 }
199
200 fn header_td(&self, hash: &BlockHash) -> ProviderResult<Option<U256>> {
201 self.consistent_provider()?.header_td(hash)
202 }
203
204 fn header_td_by_number(&self, number: BlockNumber) -> ProviderResult<Option<U256>> {
205 self.consistent_provider()?.header_td_by_number(number)
206 }
207
208 fn headers_range(
209 &self,
210 range: impl RangeBounds<BlockNumber>,
211 ) -> ProviderResult<Vec<Self::Header>> {
212 self.consistent_provider()?.headers_range(range)
213 }
214
215 fn sealed_header(
216 &self,
217 number: BlockNumber,
218 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
219 self.consistent_provider()?.sealed_header(number)
220 }
221
222 fn sealed_headers_range(
223 &self,
224 range: impl RangeBounds<BlockNumber>,
225 ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
226 self.consistent_provider()?.sealed_headers_range(range)
227 }
228
229 fn sealed_headers_while(
230 &self,
231 range: impl RangeBounds<BlockNumber>,
232 predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
233 ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
234 self.consistent_provider()?.sealed_headers_while(range, predicate)
235 }
236}
237
238impl<N: ProviderNodeTypes> BlockHashReader for BlockchainProvider<N> {
239 fn block_hash(&self, number: u64) -> ProviderResult<Option<B256>> {
240 self.consistent_provider()?.block_hash(number)
241 }
242
243 fn canonical_hashes_range(
244 &self,
245 start: BlockNumber,
246 end: BlockNumber,
247 ) -> ProviderResult<Vec<B256>> {
248 self.consistent_provider()?.canonical_hashes_range(start, end)
249 }
250}
251
252impl<N: ProviderNodeTypes> BlockNumReader for BlockchainProvider<N> {
253 fn chain_info(&self) -> ProviderResult<ChainInfo> {
254 Ok(self.canonical_in_memory_state.chain_info())
255 }
256
257 fn best_block_number(&self) -> ProviderResult<BlockNumber> {
258 Ok(self.canonical_in_memory_state.get_canonical_block_number())
259 }
260
261 fn last_block_number(&self) -> ProviderResult<BlockNumber> {
262 self.database.last_block_number()
263 }
264
265 fn block_number(&self, hash: B256) -> ProviderResult<Option<BlockNumber>> {
266 self.consistent_provider()?.block_number(hash)
267 }
268}
269
270impl<N: ProviderNodeTypes> BlockIdReader for BlockchainProvider<N> {
271 fn pending_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
272 Ok(self.canonical_in_memory_state.pending_block_num_hash())
273 }
274
275 fn safe_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
276 Ok(self.canonical_in_memory_state.get_safe_num_hash())
277 }
278
279 fn finalized_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
280 Ok(self.canonical_in_memory_state.get_finalized_num_hash())
281 }
282}
283
284impl<N: ProviderNodeTypes> BlockReader for BlockchainProvider<N> {
285 type Block = BlockTy<N>;
286
287 fn find_block_by_hash(
288 &self,
289 hash: B256,
290 source: BlockSource,
291 ) -> ProviderResult<Option<Self::Block>> {
292 self.consistent_provider()?.find_block_by_hash(hash, source)
293 }
294
295 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
296 self.consistent_provider()?.block(id)
297 }
298
299 fn pending_block(&self) -> ProviderResult<Option<SealedBlock<Self::Block>>> {
300 Ok(self.canonical_in_memory_state.pending_block())
301 }
302
303 fn pending_block_with_senders(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
304 Ok(self.canonical_in_memory_state.pending_recovered_block())
305 }
306
307 fn pending_block_and_receipts(
308 &self,
309 ) -> ProviderResult<Option<(SealedBlock<Self::Block>, Vec<Self::Receipt>)>> {
310 Ok(self.canonical_in_memory_state.pending_block_and_receipts())
311 }
312
313 fn recovered_block(
320 &self,
321 id: BlockHashOrNumber,
322 transaction_kind: TransactionVariant,
323 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
324 self.consistent_provider()?.recovered_block(id, transaction_kind)
325 }
326
327 fn sealed_block_with_senders(
328 &self,
329 id: BlockHashOrNumber,
330 transaction_kind: TransactionVariant,
331 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
332 self.consistent_provider()?.sealed_block_with_senders(id, transaction_kind)
333 }
334
335 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
336 self.consistent_provider()?.block_range(range)
337 }
338
339 fn block_with_senders_range(
340 &self,
341 range: RangeInclusive<BlockNumber>,
342 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
343 self.consistent_provider()?.block_with_senders_range(range)
344 }
345
346 fn recovered_block_range(
347 &self,
348 range: RangeInclusive<BlockNumber>,
349 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
350 self.consistent_provider()?.recovered_block_range(range)
351 }
352}
353
354impl<N: ProviderNodeTypes> TransactionsProvider for BlockchainProvider<N> {
355 type Transaction = TxTy<N>;
356
357 fn transaction_id(&self, tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
358 self.consistent_provider()?.transaction_id(tx_hash)
359 }
360
361 fn transaction_by_id(&self, id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
362 self.consistent_provider()?.transaction_by_id(id)
363 }
364
365 fn transaction_by_id_unhashed(
366 &self,
367 id: TxNumber,
368 ) -> ProviderResult<Option<Self::Transaction>> {
369 self.consistent_provider()?.transaction_by_id_unhashed(id)
370 }
371
372 fn transaction_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
373 self.consistent_provider()?.transaction_by_hash(hash)
374 }
375
376 fn transaction_by_hash_with_meta(
377 &self,
378 tx_hash: TxHash,
379 ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
380 self.consistent_provider()?.transaction_by_hash_with_meta(tx_hash)
381 }
382
383 fn transaction_block(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
384 self.consistent_provider()?.transaction_block(id)
385 }
386
387 fn transactions_by_block(
388 &self,
389 id: BlockHashOrNumber,
390 ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
391 self.consistent_provider()?.transactions_by_block(id)
392 }
393
394 fn transactions_by_block_range(
395 &self,
396 range: impl RangeBounds<BlockNumber>,
397 ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
398 self.consistent_provider()?.transactions_by_block_range(range)
399 }
400
401 fn transactions_by_tx_range(
402 &self,
403 range: impl RangeBounds<TxNumber>,
404 ) -> ProviderResult<Vec<Self::Transaction>> {
405 self.consistent_provider()?.transactions_by_tx_range(range)
406 }
407
408 fn senders_by_tx_range(
409 &self,
410 range: impl RangeBounds<TxNumber>,
411 ) -> ProviderResult<Vec<Address>> {
412 self.consistent_provider()?.senders_by_tx_range(range)
413 }
414
415 fn transaction_sender(&self, id: TxNumber) -> ProviderResult<Option<Address>> {
416 self.consistent_provider()?.transaction_sender(id)
417 }
418}
419
420impl<N: ProviderNodeTypes> ReceiptProvider for BlockchainProvider<N> {
421 type Receipt = ReceiptTy<N>;
422
423 fn receipt(&self, id: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
424 self.consistent_provider()?.receipt(id)
425 }
426
427 fn receipt_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
428 self.consistent_provider()?.receipt_by_hash(hash)
429 }
430
431 fn receipts_by_block(
432 &self,
433 block: BlockHashOrNumber,
434 ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
435 self.consistent_provider()?.receipts_by_block(block)
436 }
437
438 fn receipts_by_tx_range(
439 &self,
440 range: impl RangeBounds<TxNumber>,
441 ) -> ProviderResult<Vec<Self::Receipt>> {
442 self.consistent_provider()?.receipts_by_tx_range(range)
443 }
444}
445
446impl<N: ProviderNodeTypes> ReceiptProviderIdExt for BlockchainProvider<N> {
447 fn receipts_by_block_id(&self, block: BlockId) -> ProviderResult<Option<Vec<Self::Receipt>>> {
448 self.consistent_provider()?.receipts_by_block_id(block)
449 }
450}
451
452impl<N: ProviderNodeTypes> WithdrawalsProvider for BlockchainProvider<N> {
453 fn withdrawals_by_block(
454 &self,
455 id: BlockHashOrNumber,
456 timestamp: u64,
457 ) -> ProviderResult<Option<Withdrawals>> {
458 self.consistent_provider()?.withdrawals_by_block(id, timestamp)
459 }
460}
461
462impl<N: ProviderNodeTypes> OmmersProvider for BlockchainProvider<N> {
463 fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Self::Header>>> {
464 self.consistent_provider()?.ommers(id)
465 }
466}
467
468impl<N: ProviderNodeTypes> BlockBodyIndicesProvider for BlockchainProvider<N> {
469 fn block_body_indices(
470 &self,
471 number: BlockNumber,
472 ) -> ProviderResult<Option<StoredBlockBodyIndices>> {
473 self.consistent_provider()?.block_body_indices(number)
474 }
475
476 fn block_body_indices_range(
477 &self,
478 range: RangeInclusive<BlockNumber>,
479 ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
480 self.consistent_provider()?.block_body_indices_range(range)
481 }
482}
483
484impl<N: ProviderNodeTypes> StageCheckpointReader for BlockchainProvider<N> {
485 fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
486 self.consistent_provider()?.get_stage_checkpoint(id)
487 }
488
489 fn get_stage_checkpoint_progress(&self, id: StageId) -> ProviderResult<Option<Vec<u8>>> {
490 self.consistent_provider()?.get_stage_checkpoint_progress(id)
491 }
492
493 fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
494 self.consistent_provider()?.get_all_checkpoints()
495 }
496}
497
498impl<N: ProviderNodeTypes> PruneCheckpointReader for BlockchainProvider<N> {
499 fn get_prune_checkpoint(
500 &self,
501 segment: PruneSegment,
502 ) -> ProviderResult<Option<PruneCheckpoint>> {
503 self.consistent_provider()?.get_prune_checkpoint(segment)
504 }
505
506 fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
507 self.consistent_provider()?.get_prune_checkpoints()
508 }
509}
510
511impl<N: NodeTypesWithDB> ChainSpecProvider for BlockchainProvider<N> {
512 type ChainSpec = N::ChainSpec;
513
514 fn chain_spec(&self) -> Arc<N::ChainSpec> {
515 self.database.chain_spec()
516 }
517}
518
519impl<N: ProviderNodeTypes> StateProviderFactory for BlockchainProvider<N> {
520 fn latest(&self) -> ProviderResult<StateProviderBox> {
522 trace!(target: "providers::blockchain", "Getting latest block state provider");
523 if let Some(state) = self.canonical_in_memory_state.head_state() {
525 trace!(target: "providers::blockchain", "Using head state for latest state provider");
526 Ok(self.block_state_provider(&state)?.boxed())
527 } else {
528 trace!(target: "providers::blockchain", "Using database state for latest state provider");
529 self.database.latest()
530 }
531 }
532
533 fn history_by_block_number(
534 &self,
535 block_number: BlockNumber,
536 ) -> ProviderResult<StateProviderBox> {
537 trace!(target: "providers::blockchain", ?block_number, "Getting history by block number");
538 let provider = self.consistent_provider()?;
539 provider.ensure_canonical_block(block_number)?;
540 let hash = provider
541 .block_hash(block_number)?
542 .ok_or_else(|| ProviderError::HeaderNotFound(block_number.into()))?;
543 self.history_by_block_hash(hash)
544 }
545
546 fn history_by_block_hash(&self, block_hash: BlockHash) -> ProviderResult<StateProviderBox> {
547 trace!(target: "providers::blockchain", ?block_hash, "Getting history by block hash");
548
549 self.consistent_provider()?.get_in_memory_or_storage_by_block(
550 block_hash.into(),
551 |_| self.database.history_by_block_hash(block_hash),
552 |block_state| {
553 let state_provider = self.block_state_provider(block_state)?;
554 Ok(Box::new(state_provider))
555 },
556 )
557 }
558
559 fn state_by_block_hash(&self, hash: BlockHash) -> ProviderResult<StateProviderBox> {
560 trace!(target: "providers::blockchain", ?hash, "Getting state by block hash");
561 if let Ok(state) = self.history_by_block_hash(hash) {
562 Ok(state)
564 } else if let Ok(Some(pending)) = self.pending_state_by_hash(hash) {
565 Ok(pending)
567 } else {
568 Err(ProviderError::StateForHashNotFound(hash))
570 }
571 }
572
573 fn pending(&self) -> ProviderResult<StateProviderBox> {
578 trace!(target: "providers::blockchain", "Getting provider for pending state");
579
580 if let Some(pending) = self.canonical_in_memory_state.pending_state() {
581 return Ok(Box::new(self.block_state_provider(&pending)?));
583 }
584
585 self.latest()
587 }
588
589 fn pending_state_by_hash(&self, block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
590 if let Some(pending) = self.canonical_in_memory_state.pending_state() {
591 if pending.hash() == block_hash {
592 return Ok(Some(Box::new(self.block_state_provider(&pending)?)));
593 }
594 }
595 Ok(None)
596 }
597
598 fn state_by_block_number_or_tag(
600 &self,
601 number_or_tag: BlockNumberOrTag,
602 ) -> ProviderResult<StateProviderBox> {
603 match number_or_tag {
604 BlockNumberOrTag::Latest => self.latest(),
605 BlockNumberOrTag::Finalized => {
606 let hash =
608 self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
609 self.state_by_block_hash(hash)
610 }
611 BlockNumberOrTag::Safe => {
612 let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
614 self.state_by_block_hash(hash)
615 }
616 BlockNumberOrTag::Earliest => self.history_by_block_number(0),
617 BlockNumberOrTag::Pending => self.pending(),
618 BlockNumberOrTag::Number(num) => {
619 let hash = self
620 .block_hash(num)?
621 .ok_or_else(|| ProviderError::HeaderNotFound(num.into()))?;
622 self.state_by_block_hash(hash)
623 }
624 }
625 }
626}
627
628impl<N: NodeTypesWithDB> HashedPostStateProvider for BlockchainProvider<N> {
629 fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState {
630 HashedPostState::from_bundle_state::<<N::StateCommitment as StateCommitment>::KeyHasher>(
631 bundle_state.state(),
632 )
633 }
634}
635
636impl<N: ProviderNodeTypes> CanonChainTracker for BlockchainProvider<N> {
637 type Header = HeaderTy<N>;
638
639 fn on_forkchoice_update_received(&self, _update: &ForkchoiceState) {
640 self.canonical_in_memory_state.on_forkchoice_update_received();
642 }
643
644 fn last_received_update_timestamp(&self) -> Option<Instant> {
645 self.canonical_in_memory_state.last_received_update_timestamp()
646 }
647
648 fn on_transition_configuration_exchanged(&self) {
649 self.canonical_in_memory_state.on_transition_configuration_exchanged();
650 }
651
652 fn last_exchanged_transition_configuration_timestamp(&self) -> Option<Instant> {
653 self.canonical_in_memory_state.last_exchanged_transition_configuration_timestamp()
654 }
655
656 fn set_canonical_head(&self, header: SealedHeader<Self::Header>) {
657 self.canonical_in_memory_state.set_canonical_head(header);
658 }
659
660 fn set_safe(&self, header: SealedHeader<Self::Header>) {
661 self.canonical_in_memory_state.set_safe(header);
662 }
663
664 fn set_finalized(&self, header: SealedHeader<Self::Header>) {
665 self.canonical_in_memory_state.set_finalized(header);
666 }
667}
668
669impl<N: ProviderNodeTypes> BlockReaderIdExt for BlockchainProvider<N>
670where
671 Self: ReceiptProviderIdExt,
672{
673 fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>> {
674 self.consistent_provider()?.block_by_id(id)
675 }
676
677 fn header_by_number_or_tag(
678 &self,
679 id: BlockNumberOrTag,
680 ) -> ProviderResult<Option<Self::Header>> {
681 self.consistent_provider()?.header_by_number_or_tag(id)
682 }
683
684 fn sealed_header_by_number_or_tag(
685 &self,
686 id: BlockNumberOrTag,
687 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
688 self.consistent_provider()?.sealed_header_by_number_or_tag(id)
689 }
690
691 fn sealed_header_by_id(
692 &self,
693 id: BlockId,
694 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
695 self.consistent_provider()?.sealed_header_by_id(id)
696 }
697
698 fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>> {
699 self.consistent_provider()?.header_by_id(id)
700 }
701
702 fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<Self::Header>>> {
703 self.consistent_provider()?.ommers_by_id(id)
704 }
705}
706
707impl<N: ProviderNodeTypes> CanonStateSubscriptions for BlockchainProvider<N> {
708 fn subscribe_to_canonical_state(&self) -> CanonStateNotifications<Self::Primitives> {
709 self.canonical_in_memory_state.subscribe_canon_state()
710 }
711}
712
713impl<N: ProviderNodeTypes> ForkChoiceSubscriptions for BlockchainProvider<N> {
714 type Header = HeaderTy<N>;
715
716 fn subscribe_safe_block(&self) -> ForkChoiceNotifications<Self::Header> {
717 let receiver = self.canonical_in_memory_state.subscribe_safe_block();
718 ForkChoiceNotifications(receiver)
719 }
720
721 fn subscribe_finalized_block(&self) -> ForkChoiceNotifications<Self::Header> {
722 let receiver = self.canonical_in_memory_state.subscribe_finalized_block();
723 ForkChoiceNotifications(receiver)
724 }
725}
726
727impl<N: ProviderNodeTypes> StorageChangeSetReader for BlockchainProvider<N> {
728 fn storage_changeset(
729 &self,
730 block_number: BlockNumber,
731 ) -> ProviderResult<Vec<(BlockNumberAddress, StorageEntry)>> {
732 self.consistent_provider()?.storage_changeset(block_number)
733 }
734}
735
736impl<N: ProviderNodeTypes> ChangeSetReader for BlockchainProvider<N> {
737 fn account_block_changeset(
738 &self,
739 block_number: BlockNumber,
740 ) -> ProviderResult<Vec<AccountBeforeTx>> {
741 self.consistent_provider()?.account_block_changeset(block_number)
742 }
743}
744
745impl<N: ProviderNodeTypes> AccountReader for BlockchainProvider<N> {
746 fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
748 self.consistent_provider()?.basic_account(address)
749 }
750}
751
752impl<N: ProviderNodeTypes> StateReader for BlockchainProvider<N> {
753 type Receipt = ReceiptTy<N>;
754
755 fn get_state(
765 &self,
766 block: BlockNumber,
767 ) -> ProviderResult<Option<ExecutionOutcome<Self::Receipt>>> {
768 StateReader::get_state(&self.consistent_provider()?, block)
769 }
770}
771
772#[cfg(test)]
773mod tests {
774 use crate::{
775 providers::BlockchainProvider,
776 test_utils::{
777 create_test_provider_factory, create_test_provider_factory_with_chain_spec,
778 MockNodeTypesWithDB,
779 },
780 writer::UnifiedStorageWriter,
781 BlockWriter, CanonChainTracker, ProviderFactory, StaticFileProviderFactory,
782 StaticFileWriter,
783 };
784 use alloy_eips::{eip4895::Withdrawals, BlockHashOrNumber, BlockNumHash, BlockNumberOrTag};
785 use alloy_primitives::{BlockNumber, TxNumber, B256};
786 use itertools::Itertools;
787 use rand::Rng;
788 use reth_chain_state::{
789 test_utils::TestBlockBuilder, CanonStateNotification, CanonStateSubscriptions,
790 CanonicalInMemoryState, ExecutedBlock, ExecutedBlockWithTrieUpdates, NewCanonicalChain,
791 };
792 use reth_chainspec::{
793 ChainSpec, ChainSpecBuilder, ChainSpecProvider, EthereumHardfork, MAINNET,
794 };
795 use reth_db_api::{
796 cursor::DbCursorRO,
797 models::{AccountBeforeTx, StoredBlockBodyIndices},
798 tables,
799 transaction::DbTx,
800 };
801 use reth_errors::ProviderError;
802 use reth_execution_types::{Chain, ExecutionOutcome};
803 use reth_primitives::{EthPrimitives, Receipt, RecoveredBlock, SealedBlock, StaticFileSegment};
804 use reth_primitives_traits::{BlockBody, SignedTransaction};
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>, Vec<SealedBlock>) {
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 #[allow(clippy::type_complexity, clippy::too_many_arguments)]
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>,
869 Vec<SealedBlock>,
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 #[allow(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>,
969 Vec<SealedBlock>,
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(reth_primitives::RecoveredBlock::new_sealed(
1231 block.clone(),
1232 block.senders().unwrap()
1233 ))
1234 );
1235
1236 assert_eq!(provider.pending_block_and_receipts()?, Some((block, vec![])));
1237
1238 Ok(())
1239 }
1240
1241 #[test]
1242 fn test_block_reader_ommers() -> eyre::Result<()> {
1243 let mut rng = generators::rng();
1245 let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
1246 &mut rng,
1247 TEST_BLOCKS_COUNT,
1248 TEST_BLOCKS_COUNT,
1249 BlockRangeParams::default(),
1250 )?;
1251
1252 let first_in_mem_block = in_memory_blocks.first().unwrap();
1253
1254 assert_eq!(
1256 provider.ommers(
1257 (provider.chain_spec().paris_block_and_final_difficulty.unwrap().0 + 2).into()
1258 )?,
1259 Some(vec![])
1260 );
1261
1262 assert_eq!(
1264 provider.ommers(first_in_mem_block.number.into())?,
1265 Some(first_in_mem_block.body().ommers.clone())
1266 );
1267 assert_eq!(
1268 provider.ommers(first_in_mem_block.hash().into())?,
1269 Some(first_in_mem_block.body().ommers.clone())
1270 );
1271
1272 assert_eq!(provider.ommers(B256::random().into())?, None);
1274
1275 Ok(())
1276 }
1277
1278 #[test]
1279 fn test_block_body_indices() -> eyre::Result<()> {
1280 let mut rng = generators::rng();
1282 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1283 &mut rng,
1284 TEST_BLOCKS_COUNT,
1285 TEST_BLOCKS_COUNT,
1286 BlockRangeParams {
1287 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
1288 ..Default::default()
1289 },
1290 )?;
1291
1292 let first_in_mem_block = in_memory_blocks.first().unwrap();
1293
1294 let in_memory_block_senders =
1296 first_in_mem_block.senders().expect("failed to recover senders");
1297 let chain = NewCanonicalChain::Commit {
1298 new: vec![ExecutedBlockWithTrieUpdates::new(
1299 Arc::new(RecoveredBlock::new_sealed(
1300 first_in_mem_block.clone(),
1301 in_memory_block_senders,
1302 )),
1303 Default::default(),
1304 Default::default(),
1305 Default::default(),
1306 )],
1307 };
1308 provider.canonical_in_memory_state.update_chain(chain);
1309
1310 let first_db_block = database_blocks.first().unwrap().clone();
1311 let first_in_mem_block = in_memory_blocks.first().unwrap().clone();
1312
1313 assert_eq!(
1315 provider.block_body_indices(first_db_block.number)?.unwrap(),
1316 StoredBlockBodyIndices { first_tx_num: 0, tx_count: 4 }
1317 );
1318
1319 assert_eq!(
1322 provider.block_body_indices(first_in_mem_block.number)?.unwrap(),
1323 StoredBlockBodyIndices { first_tx_num: 20, tx_count: 4 }
1324 );
1325
1326 let mut rng = rand::thread_rng();
1328 let random_block_number: u64 = rng.gen();
1329 assert_eq!(provider.block_body_indices(random_block_number)?, None);
1330
1331 Ok(())
1332 }
1333
1334 #[test]
1335 fn test_block_hash_reader() -> eyre::Result<()> {
1336 let mut rng = generators::rng();
1337 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1338 &mut rng,
1339 TEST_BLOCKS_COUNT,
1340 TEST_BLOCKS_COUNT,
1341 BlockRangeParams::default(),
1342 )?;
1343
1344 let database_block = database_blocks.first().unwrap().clone();
1345 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1346
1347 assert_eq!(provider.block_hash(database_block.number)?, Some(database_block.hash()));
1348 assert_eq!(provider.block_hash(in_memory_block.number)?, Some(in_memory_block.hash()));
1349
1350 assert_eq!(
1351 provider.canonical_hashes_range(0, 10)?,
1352 [database_blocks, in_memory_blocks]
1353 .concat()
1354 .iter()
1355 .map(|block| block.hash())
1356 .collect::<Vec<_>>()
1357 );
1358
1359 Ok(())
1360 }
1361
1362 #[test]
1363 fn test_header_provider() -> eyre::Result<()> {
1364 let mut rng = generators::rng();
1365 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1366 &mut rng,
1367 TEST_BLOCKS_COUNT,
1368 TEST_BLOCKS_COUNT,
1369 BlockRangeParams::default(),
1370 )?;
1371
1372 let database_block = database_blocks.first().unwrap().clone();
1373 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1374 let finalized_block = database_blocks.get(database_blocks.len() - 3).unwrap();
1376 provider.set_finalized(finalized_block.clone_sealed_header());
1377
1378 let blocks = [database_blocks, in_memory_blocks].concat();
1379
1380 assert_eq!(
1381 provider.header_td_by_number(database_block.number)?,
1382 Some(database_block.difficulty)
1383 );
1384
1385 assert_eq!(
1386 provider.header_td_by_number(in_memory_block.number)?,
1387 Some(in_memory_block.difficulty)
1388 );
1389
1390 assert_eq!(
1391 provider.sealed_headers_while(0..=10, |header| header.number <= 8)?,
1392 blocks
1393 .iter()
1394 .take_while(|header| header.number <= 8)
1395 .map(|b| b.clone_sealed_header())
1396 .collect::<Vec<_>>()
1397 );
1398
1399 Ok(())
1400 }
1401
1402 #[tokio::test]
1403 async fn test_canon_state_subscriptions() -> eyre::Result<()> {
1404 let factory = create_test_provider_factory();
1405
1406 let mut test_block_builder = TestBlockBuilder::eth();
1408 let block_1 = test_block_builder.generate_random_block(0, B256::ZERO);
1409 let block_hash_1 = block_1.hash();
1410
1411 let provider_rw = factory.provider_rw()?;
1413 provider_rw.insert_historical_block(block_1)?;
1414 provider_rw.commit()?;
1415
1416 let provider = BlockchainProvider::new(factory)?;
1417
1418 let in_memory_state = provider.canonical_in_memory_state();
1420 let mut rx_1 = provider.subscribe_to_canonical_state();
1421 let mut rx_2 = provider.subscribe_to_canonical_state();
1422
1423 let block_2 = test_block_builder.generate_random_block(1, block_hash_1);
1425 let chain = Chain::new(vec![block_2], ExecutionOutcome::default(), None);
1426 let commit = CanonStateNotification::Commit { new: Arc::new(chain.clone()) };
1427 in_memory_state.notify_canon_state(commit.clone());
1428 let (notification_1, notification_2) = tokio::join!(rx_1.recv(), rx_2.recv());
1429 assert_eq!(notification_1, Ok(commit.clone()));
1430 assert_eq!(notification_2, Ok(commit.clone()));
1431
1432 let block_3 = test_block_builder.generate_random_block(1, block_hash_1);
1434 let block_4 = test_block_builder.generate_random_block(2, block_3.hash());
1435 let new_chain = Chain::new(vec![block_3, block_4], ExecutionOutcome::default(), None);
1436 let re_org =
1437 CanonStateNotification::Reorg { old: Arc::new(chain), new: Arc::new(new_chain) };
1438 in_memory_state.notify_canon_state(re_org.clone());
1439 let (notification_1, notification_2) = tokio::join!(rx_1.recv(), rx_2.recv());
1440 assert_eq!(notification_1, Ok(re_org.clone()));
1441 assert_eq!(notification_2, Ok(re_org.clone()));
1442
1443 Ok(())
1444 }
1445
1446 #[test]
1447 fn test_withdrawals_provider() -> eyre::Result<()> {
1448 let mut rng = generators::rng();
1449 let chain_spec = Arc::new(ChainSpecBuilder::mainnet().shanghai_activated().build());
1450 let (provider, database_blocks, in_memory_blocks, _) =
1451 provider_with_chain_spec_and_random_blocks(
1452 &mut rng,
1453 chain_spec.clone(),
1454 TEST_BLOCKS_COUNT,
1455 TEST_BLOCKS_COUNT,
1456 BlockRangeParams { withdrawals_count: Some(1..3), ..Default::default() },
1457 )?;
1458 let blocks = [database_blocks, in_memory_blocks].concat();
1459
1460 let shainghai_timestamp =
1461 chain_spec.hardforks.fork(EthereumHardfork::Shanghai).as_timestamp().unwrap();
1462
1463 assert_eq!(
1464 provider
1465 .withdrawals_by_block(
1466 alloy_eips::BlockHashOrNumber::Number(15),
1467 shainghai_timestamp
1468 )
1469 .expect("could not call withdrawals by block"),
1470 Some(Withdrawals::new(vec![])),
1471 "Expected withdrawals_by_block to return empty list if block does not exist"
1472 );
1473
1474 for block in blocks {
1475 assert_eq!(
1476 provider
1477 .withdrawals_by_block(
1478 alloy_eips::BlockHashOrNumber::Number(block.number),
1479 shainghai_timestamp
1480 )?
1481 .unwrap(),
1482 block.body().withdrawals.clone().unwrap(),
1483 "Expected withdrawals_by_block to return correct withdrawals"
1484 );
1485 }
1486
1487 Ok(())
1488 }
1489
1490 #[test]
1491 fn test_block_num_reader() -> eyre::Result<()> {
1492 let mut rng = generators::rng();
1493 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1494 &mut rng,
1495 TEST_BLOCKS_COUNT,
1496 TEST_BLOCKS_COUNT,
1497 BlockRangeParams::default(),
1498 )?;
1499
1500 assert_eq!(provider.best_block_number()?, in_memory_blocks.last().unwrap().number);
1501 assert_eq!(provider.last_block_number()?, database_blocks.last().unwrap().number);
1502
1503 let database_block = database_blocks.first().unwrap().clone();
1504 let in_memory_block = in_memory_blocks.first().unwrap().clone();
1505 assert_eq!(provider.block_number(database_block.hash())?, Some(database_block.number));
1506 assert_eq!(provider.block_number(in_memory_block.hash())?, Some(in_memory_block.number));
1507
1508 Ok(())
1509 }
1510
1511 #[test]
1512 fn test_block_reader_id_ext_block_by_id() -> eyre::Result<()> {
1513 let mut rng = generators::rng();
1514 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1515 &mut rng,
1516 TEST_BLOCKS_COUNT,
1517 TEST_BLOCKS_COUNT,
1518 BlockRangeParams::default(),
1519 )?;
1520
1521 let database_block = database_blocks.first().unwrap().clone();
1522 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1523
1524 let block_number = database_block.number;
1525 let block_hash = database_block.hash();
1526
1527 assert_eq!(
1528 provider.block_by_id(block_number.into()).unwrap(),
1529 Some(database_block.clone().into_block())
1530 );
1531 assert_eq!(
1532 provider.block_by_id(block_hash.into()).unwrap(),
1533 Some(database_block.into_block())
1534 );
1535
1536 let block_number = in_memory_block.number;
1537 let block_hash = in_memory_block.hash();
1538 assert_eq!(
1539 provider.block_by_id(block_number.into()).unwrap(),
1540 Some(in_memory_block.clone().into_block())
1541 );
1542 assert_eq!(
1543 provider.block_by_id(block_hash.into()).unwrap(),
1544 Some(in_memory_block.into_block())
1545 );
1546
1547 Ok(())
1548 }
1549
1550 #[test]
1551 fn test_block_reader_id_ext_header_by_number_or_tag() -> eyre::Result<()> {
1552 let mut rng = generators::rng();
1553 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1554 &mut rng,
1555 TEST_BLOCKS_COUNT,
1556 TEST_BLOCKS_COUNT,
1557 BlockRangeParams::default(),
1558 )?;
1559
1560 let database_block = database_blocks.first().unwrap().clone();
1561
1562 let in_memory_block_count = in_memory_blocks.len();
1563 let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
1564 let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
1565 let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();
1566
1567 let block_number = database_block.number;
1568 assert_eq!(
1569 provider.header_by_number_or_tag(block_number.into()).unwrap(),
1570 Some(database_block.header().clone())
1571 );
1572 assert_eq!(
1573 provider.sealed_header_by_number_or_tag(block_number.into())?,
1574 Some(database_block.clone_sealed_header())
1575 );
1576
1577 assert_eq!(
1578 provider.header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
1579 Some(canonical_block.header().clone())
1580 );
1581 assert_eq!(
1582 provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
1583 Some(canonical_block.clone_sealed_header())
1584 );
1585
1586 assert_eq!(
1587 provider.header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
1588 Some(safe_block.header().clone())
1589 );
1590 assert_eq!(
1591 provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
1592 Some(safe_block.clone_sealed_header())
1593 );
1594
1595 assert_eq!(
1596 provider.header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
1597 Some(finalized_block.header().clone())
1598 );
1599 assert_eq!(
1600 provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
1601 Some(finalized_block.clone_sealed_header())
1602 );
1603
1604 Ok(())
1605 }
1606
1607 #[test]
1608 fn test_block_reader_id_ext_header_by_id() -> eyre::Result<()> {
1609 let mut rng = generators::rng();
1610 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1611 &mut rng,
1612 TEST_BLOCKS_COUNT,
1613 TEST_BLOCKS_COUNT,
1614 BlockRangeParams::default(),
1615 )?;
1616
1617 let database_block = database_blocks.first().unwrap().clone();
1618 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1619
1620 let block_number = database_block.number;
1621 let block_hash = database_block.hash();
1622
1623 assert_eq!(
1624 provider.header_by_id(block_number.into()).unwrap(),
1625 Some(database_block.header().clone())
1626 );
1627 assert_eq!(
1628 provider.sealed_header_by_id(block_number.into()).unwrap(),
1629 Some(database_block.clone_sealed_header())
1630 );
1631
1632 assert_eq!(
1633 provider.header_by_id(block_hash.into()).unwrap(),
1634 Some(database_block.header().clone())
1635 );
1636 assert_eq!(
1637 provider.sealed_header_by_id(block_hash.into()).unwrap(),
1638 Some(database_block.clone_sealed_header())
1639 );
1640
1641 let block_number = in_memory_block.number;
1642 let block_hash = in_memory_block.hash();
1643
1644 assert_eq!(
1645 provider.header_by_id(block_number.into()).unwrap(),
1646 Some(in_memory_block.header().clone())
1647 );
1648 assert_eq!(
1649 provider.sealed_header_by_id(block_number.into()).unwrap(),
1650 Some(in_memory_block.clone_sealed_header())
1651 );
1652
1653 assert_eq!(
1654 provider.header_by_id(block_hash.into()).unwrap(),
1655 Some(in_memory_block.header().clone())
1656 );
1657 assert_eq!(
1658 provider.sealed_header_by_id(block_hash.into()).unwrap(),
1659 Some(in_memory_block.clone_sealed_header())
1660 );
1661
1662 Ok(())
1663 }
1664
1665 #[test]
1666 fn test_block_reader_id_ext_ommers_by_id() -> eyre::Result<()> {
1667 let mut rng = generators::rng();
1668 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1669 &mut rng,
1670 TEST_BLOCKS_COUNT,
1671 TEST_BLOCKS_COUNT,
1672 BlockRangeParams::default(),
1673 )?;
1674
1675 let database_block = database_blocks.first().unwrap().clone();
1676 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1677
1678 let block_number = database_block.number;
1679 let block_hash = database_block.hash();
1680
1681 assert_eq!(
1682 provider.ommers_by_id(block_number.into()).unwrap().unwrap_or_default(),
1683 database_block.body().ommers
1684 );
1685 assert_eq!(
1686 provider.ommers_by_id(block_hash.into()).unwrap().unwrap_or_default(),
1687 database_block.body().ommers
1688 );
1689
1690 let block_number = in_memory_block.number;
1691 let block_hash = in_memory_block.hash();
1692
1693 assert_eq!(
1694 provider.ommers_by_id(block_number.into()).unwrap().unwrap_or_default(),
1695 in_memory_block.body().ommers
1696 );
1697 assert_eq!(
1698 provider.ommers_by_id(block_hash.into()).unwrap().unwrap_or_default(),
1699 in_memory_block.body().ommers
1700 );
1701
1702 Ok(())
1703 }
1704
1705 #[test]
1706 fn test_receipt_provider_id_ext_receipts_by_block_id() -> eyre::Result<()> {
1707 let mut rng = generators::rng();
1708 let (provider, database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
1709 &mut rng,
1710 TEST_BLOCKS_COUNT,
1711 TEST_BLOCKS_COUNT,
1712 BlockRangeParams { tx_count: 1..3, ..Default::default() },
1713 )?;
1714
1715 let database_block = database_blocks.first().unwrap().clone();
1716 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1717
1718 let block_number = database_block.number;
1719 let block_hash = database_block.hash();
1720
1721 assert!(!receipts.get(database_block.number as usize).unwrap().is_empty());
1722 assert!(!provider
1723 .receipts_by_number_or_tag(database_block.number.into())?
1724 .unwrap()
1725 .is_empty());
1726
1727 assert_eq!(
1728 provider.receipts_by_block_id(block_number.into())?.unwrap(),
1729 receipts.get(block_number as usize).unwrap().clone()
1730 );
1731 assert_eq!(
1732 provider.receipts_by_block_id(block_hash.into())?.unwrap(),
1733 receipts.get(block_number as usize).unwrap().clone()
1734 );
1735
1736 let block_number = in_memory_block.number;
1737 let block_hash = in_memory_block.hash();
1738
1739 assert_eq!(
1740 provider.receipts_by_block_id(block_number.into())?.unwrap(),
1741 receipts.get(block_number as usize).unwrap().clone()
1742 );
1743 assert_eq!(
1744 provider.receipts_by_block_id(block_hash.into())?.unwrap(),
1745 receipts.get(block_number as usize).unwrap().clone()
1746 );
1747
1748 Ok(())
1749 }
1750
1751 #[test]
1752 fn test_receipt_provider_id_ext_receipts_by_block_number_or_tag() -> eyre::Result<()> {
1753 let mut rng = generators::rng();
1754 let (provider, database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
1755 &mut rng,
1756 TEST_BLOCKS_COUNT,
1757 TEST_BLOCKS_COUNT,
1758 BlockRangeParams { tx_count: 1..3, ..Default::default() },
1759 )?;
1760
1761 let database_block = database_blocks.first().unwrap().clone();
1762
1763 let in_memory_block_count = in_memory_blocks.len();
1764 let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
1765 let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
1766 let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();
1767
1768 assert!(!receipts.get(database_block.number as usize).unwrap().is_empty());
1769 assert!(!provider
1770 .receipts_by_number_or_tag(database_block.number.into())?
1771 .unwrap()
1772 .is_empty());
1773
1774 assert_eq!(
1775 provider.receipts_by_number_or_tag(database_block.number.into())?.unwrap(),
1776 receipts.get(database_block.number as usize).unwrap().clone()
1777 );
1778 assert_eq!(
1779 provider.receipts_by_number_or_tag(BlockNumberOrTag::Latest)?.unwrap(),
1780 receipts.get(canonical_block.number as usize).unwrap().clone()
1781 );
1782 assert_eq!(
1783 provider.receipts_by_number_or_tag(BlockNumberOrTag::Safe)?.unwrap(),
1784 receipts.get(safe_block.number as usize).unwrap().clone()
1785 );
1786 assert_eq!(
1787 provider.receipts_by_number_or_tag(BlockNumberOrTag::Finalized)?.unwrap(),
1788 receipts.get(finalized_block.number as usize).unwrap().clone()
1789 );
1790
1791 Ok(())
1792 }
1793
1794 #[test]
1795 fn test_changeset_reader() -> eyre::Result<()> {
1796 let mut rng = generators::rng();
1797
1798 let (database_blocks, in_memory_blocks) =
1799 random_blocks(&mut rng, TEST_BLOCKS_COUNT, 1, None, None, 0..1);
1800
1801 let first_database_block = database_blocks.first().map(|block| block.number).unwrap();
1802 let last_database_block = database_blocks.last().map(|block| block.number).unwrap();
1803 let first_in_memory_block = in_memory_blocks.first().map(|block| block.number).unwrap();
1804
1805 let accounts = random_eoa_accounts(&mut rng, 2);
1806
1807 let (database_changesets, database_state) = random_changeset_range(
1808 &mut rng,
1809 &database_blocks,
1810 accounts.into_iter().map(|(address, account)| (address, (account, Vec::new()))),
1811 0..0,
1812 0..0,
1813 );
1814 let (in_memory_changesets, in_memory_state) = random_changeset_range(
1815 &mut rng,
1816 &in_memory_blocks,
1817 database_state
1818 .iter()
1819 .map(|(address, (account, storage))| (*address, (*account, storage.clone()))),
1820 0..0,
1821 0..0,
1822 );
1823
1824 let factory = create_test_provider_factory();
1825
1826 let provider_rw = factory.provider_rw()?;
1827 provider_rw.append_blocks_with_state(
1828 database_blocks
1829 .into_iter()
1830 .map(|b| b.try_recover().expect("failed to seal block with senders"))
1831 .collect(),
1832 &ExecutionOutcome {
1833 bundle: BundleState::new(
1834 database_state.into_iter().map(|(address, (account, _))| {
1835 (address, None, Some(account.into()), Default::default())
1836 }),
1837 database_changesets
1838 .iter()
1839 .map(|block_changesets| {
1840 block_changesets.iter().map(|(address, account, _)| {
1841 (*address, Some(Some((*account).into())), [])
1842 })
1843 })
1844 .collect::<Vec<_>>(),
1845 Vec::new(),
1846 ),
1847 first_block: first_database_block,
1848 ..Default::default()
1849 },
1850 Default::default(),
1851 Default::default(),
1852 )?;
1853 provider_rw.commit()?;
1854
1855 let provider = BlockchainProvider::new(factory)?;
1856
1857 let in_memory_changesets = in_memory_changesets.into_iter().next().unwrap();
1858 let chain = NewCanonicalChain::Commit {
1859 new: vec![in_memory_blocks
1860 .first()
1861 .map(|block| {
1862 let senders = block.senders().expect("failed to recover senders");
1863 ExecutedBlockWithTrieUpdates::new(
1864 Arc::new(RecoveredBlock::new_sealed(block.clone(), senders)),
1865 Arc::new(ExecutionOutcome {
1866 bundle: BundleState::new(
1867 in_memory_state.into_iter().map(|(address, (account, _))| {
1868 (address, None, Some(account.into()), Default::default())
1869 }),
1870 [in_memory_changesets.iter().map(|(address, account, _)| {
1871 (*address, Some(Some((*account).into())), Vec::new())
1872 })],
1873 [],
1874 ),
1875 first_block: first_in_memory_block,
1876 ..Default::default()
1877 }),
1878 Default::default(),
1879 Default::default(),
1880 )
1881 })
1882 .unwrap()],
1883 };
1884 provider.canonical_in_memory_state.update_chain(chain);
1885
1886 assert_eq!(
1887 provider.account_block_changeset(last_database_block).unwrap(),
1888 database_changesets
1889 .into_iter()
1890 .next_back()
1891 .unwrap()
1892 .into_iter()
1893 .sorted_by_key(|(address, _, _)| *address)
1894 .map(|(address, account, _)| AccountBeforeTx { address, info: Some(account) })
1895 .collect::<Vec<_>>()
1896 );
1897 assert_eq!(
1898 provider.account_block_changeset(first_in_memory_block).unwrap(),
1899 in_memory_changesets
1900 .into_iter()
1901 .sorted_by_key(|(address, _, _)| *address)
1902 .map(|(address, account, _)| AccountBeforeTx { address, info: Some(account) })
1903 .collect::<Vec<_>>()
1904 );
1905
1906 Ok(())
1907 }
1908
1909 #[test]
1910 fn test_state_provider_factory() -> eyre::Result<()> {
1911 let mut rng = generators::rng();
1912
1913 let (in_memory_provider, _, in_memory_blocks, _) = provider_with_random_blocks(
1915 &mut rng,
1916 TEST_BLOCKS_COUNT,
1917 TEST_BLOCKS_COUNT,
1918 BlockRangeParams::default(),
1919 )?;
1920
1921 let (only_database_provider, database_blocks, _, _) = provider_with_random_blocks(
1923 &mut rng,
1924 TEST_BLOCKS_COUNT,
1925 0,
1926 BlockRangeParams::default(),
1927 )?;
1928
1929 let blocks = [database_blocks.clone(), in_memory_blocks.clone()].concat();
1930 let first_in_memory_block = in_memory_blocks.first().unwrap();
1931 let first_db_block = database_blocks.first().unwrap();
1932
1933 assert_eq!(
1935 first_in_memory_block.hash(),
1936 in_memory_provider.latest().unwrap().block_hash(first_in_memory_block.number)?.unwrap()
1937 );
1938 assert_eq!(
1940 first_db_block.hash(),
1941 only_database_provider.latest().unwrap().block_hash(first_db_block.number)?.unwrap()
1942 );
1943
1944 assert_eq!(
1946 first_in_memory_block.hash(),
1947 in_memory_provider
1948 .history_by_block_number(first_in_memory_block.number)?
1949 .block_hash(first_in_memory_block.number)?
1950 .unwrap()
1951 );
1952 assert_eq!(
1953 first_db_block.hash(),
1954 only_database_provider
1955 .history_by_block_number(first_db_block.number)?
1956 .block_hash(first_db_block.number)?
1957 .unwrap()
1958 );
1959 assert_eq!(
1960 first_in_memory_block.hash(),
1961 in_memory_provider
1962 .history_by_block_hash(first_in_memory_block.hash())?
1963 .block_hash(first_in_memory_block.number)?
1964 .unwrap()
1965 );
1966 assert!(only_database_provider.history_by_block_hash(B256::random()).is_err());
1967
1968 assert_eq!(
1970 first_in_memory_block.hash(),
1971 in_memory_provider
1972 .state_by_block_hash(first_in_memory_block.hash())?
1973 .block_hash(first_in_memory_block.number)?
1974 .unwrap()
1975 );
1976 assert_eq!(
1977 first_db_block.hash(),
1978 only_database_provider
1979 .state_by_block_hash(first_db_block.hash())?
1980 .block_hash(first_db_block.number)?
1981 .unwrap()
1982 );
1983 assert!(only_database_provider.state_by_block_hash(B256::random()).is_err());
1984
1985 assert_eq!(
1987 first_in_memory_block.hash(),
1988 in_memory_provider
1989 .pending()
1990 .unwrap()
1991 .block_hash(first_in_memory_block.number)
1992 .unwrap()
1993 .unwrap()
1994 );
1995
1996 let pending_block = database_blocks[database_blocks.len() - 1].clone();
1998 only_database_provider.canonical_in_memory_state.set_pending_block(
1999 ExecutedBlockWithTrieUpdates {
2000 block: ExecutedBlock {
2001 recovered_block: Arc::new(RecoveredBlock::new_sealed(
2002 pending_block.clone(),
2003 Default::default(),
2004 )),
2005 execution_output: Default::default(),
2006 hashed_state: Default::default(),
2007 },
2008 trie: Default::default(),
2009 },
2010 );
2011
2012 assert_eq!(
2013 pending_block.hash(),
2014 only_database_provider
2015 .pending()
2016 .unwrap()
2017 .block_hash(pending_block.number)
2018 .unwrap()
2019 .unwrap()
2020 );
2021
2022 assert_eq!(
2023 pending_block.hash(),
2024 only_database_provider
2025 .pending_state_by_hash(pending_block.hash())?
2026 .unwrap()
2027 .block_hash(pending_block.number)?
2028 .unwrap()
2029 );
2030
2031 assert_eq!(
2033 first_in_memory_block.hash(),
2034 in_memory_provider
2035 .state_by_block_number_or_tag(BlockNumberOrTag::Number(
2036 first_in_memory_block.number
2037 ))?
2038 .block_hash(first_in_memory_block.number)?
2039 .unwrap()
2040 );
2041 assert_eq!(
2042 first_in_memory_block.hash(),
2043 in_memory_provider
2044 .state_by_block_number_or_tag(BlockNumberOrTag::Latest)?
2045 .block_hash(first_in_memory_block.number)?
2046 .unwrap()
2047 );
2048 let safe_block = in_memory_blocks[in_memory_blocks.len() - 2].clone();
2050 in_memory_provider.canonical_in_memory_state.set_safe(safe_block.clone_sealed_header());
2051 assert_eq!(
2052 safe_block.hash(),
2053 in_memory_provider
2054 .state_by_block_number_or_tag(BlockNumberOrTag::Safe)?
2055 .block_hash(safe_block.number)?
2056 .unwrap()
2057 );
2058 let finalized_block = in_memory_blocks[in_memory_blocks.len() - 3].clone();
2060 in_memory_provider
2061 .canonical_in_memory_state
2062 .set_finalized(finalized_block.clone_sealed_header());
2063 assert_eq!(
2064 finalized_block.hash(),
2065 in_memory_provider
2066 .state_by_block_number_or_tag(BlockNumberOrTag::Finalized)?
2067 .block_hash(finalized_block.number)?
2068 .unwrap()
2069 );
2070 let earliest_block = blocks.first().unwrap().clone();
2072 assert_eq!(
2073 earliest_block.hash(),
2074 only_database_provider
2075 .state_by_block_number_or_tag(BlockNumberOrTag::Earliest)?
2076 .block_hash(earliest_block.number)?
2077 .unwrap()
2078 );
2079
2080 Ok(())
2081 }
2082
2083 #[test]
2084 fn test_canon_state_tracker() -> eyre::Result<()> {
2085 let mut rng = generators::rng();
2086 let (provider, _, _, _) = provider_with_random_blocks(
2087 &mut rng,
2088 TEST_BLOCKS_COUNT,
2089 TEST_BLOCKS_COUNT,
2090 BlockRangeParams::default(),
2091 )?;
2092
2093 let before = Instant::now();
2094 provider.on_forkchoice_update_received(&Default::default());
2095 let last_update_ts = provider.last_received_update_timestamp().unwrap();
2096 let after = Instant::now();
2097
2098 assert!(before < last_update_ts && last_update_ts < after);
2100
2101 let before = Instant::now();
2102 provider.on_transition_configuration_exchanged();
2103 let last_update_ts = provider.last_exchanged_transition_configuration_timestamp().unwrap();
2104 let after = Instant::now();
2105
2106 assert!(before < last_update_ts && last_update_ts < after);
2108
2109 Ok(())
2110 }
2111
2112 #[test]
2113 fn test_block_id_reader() -> eyre::Result<()> {
2114 let mut rng = generators::rng();
2116 let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
2117 &mut rng,
2118 TEST_BLOCKS_COUNT,
2119 TEST_BLOCKS_COUNT,
2120 BlockRangeParams::default(),
2121 )?;
2122
2123 let pending_block = in_memory_blocks.last().unwrap();
2125 provider.canonical_in_memory_state.set_pending_block(ExecutedBlockWithTrieUpdates {
2126 block: ExecutedBlock {
2127 recovered_block: Arc::new(RecoveredBlock::new_sealed(
2128 pending_block.clone(),
2129 Default::default(),
2130 )),
2131 execution_output: Default::default(),
2132 hashed_state: Default::default(),
2133 },
2134 trie: Default::default(),
2135 });
2136
2137 let safe_block = in_memory_blocks[in_memory_blocks.len() - 2].clone();
2139 provider.canonical_in_memory_state.set_safe(safe_block.clone_sealed_header());
2140
2141 let finalized_block = in_memory_blocks[in_memory_blocks.len() - 3].clone();
2143 provider.canonical_in_memory_state.set_finalized(finalized_block.clone_sealed_header());
2144
2145 assert_eq!(
2147 provider.pending_block_num_hash()?,
2148 Some(BlockNumHash { number: pending_block.number, hash: pending_block.hash() })
2149 );
2150
2151 assert_eq!(
2153 provider.safe_block_num_hash()?,
2154 Some(BlockNumHash { number: safe_block.number, hash: safe_block.hash() })
2155 );
2156
2157 assert_eq!(
2159 provider.finalized_block_num_hash()?,
2160 Some(BlockNumHash { number: finalized_block.number, hash: finalized_block.hash() })
2161 );
2162
2163 Ok(())
2164 }
2165
2166 macro_rules! test_by_tx_range {
2167 ([$(($method:ident, $data_extractor:expr)),* $(,)?]) => {{
2168
2169 let extra_blocks = [$(stringify!($method)),*].len();
2172
2173 let mut rng = generators::rng();
2174 let (provider, mut database_blocks, mut in_memory_blocks, receipts) = provider_with_random_blocks(
2175 &mut rng,
2176 TEST_BLOCKS_COUNT,
2177 TEST_BLOCKS_COUNT + extra_blocks,
2178 BlockRangeParams {
2179 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2180 ..Default::default()
2181 },
2182 )?;
2183
2184 $(
2185 let db_tx_count =
2187 database_blocks.iter().map(|b| b.transaction_count()).sum::<usize>() as u64;
2188 let in_mem_tx_count =
2189 in_memory_blocks.iter().map(|b| b.transaction_count()).sum::<usize>() as u64;
2190
2191 let db_range = 0..=(db_tx_count - 1);
2192 let in_mem_range = db_tx_count..=(in_mem_tx_count + db_range.end());
2193
2194 let database_data =
2196 database_blocks.iter().flat_map(|b| $data_extractor(b, &receipts)).collect::<Vec<_>>();
2197 assert_eq!(provider.$method(db_range.clone())?, database_data, "full db data");
2198
2199 let in_memory_data =
2201 in_memory_blocks.iter().flat_map(|b| $data_extractor(b, &receipts)).collect::<Vec<_>>();
2202 assert_eq!(provider.$method(in_mem_range.clone())?, in_memory_data, "full mem data");
2203
2204 assert_eq!(
2206 &provider.$method(in_mem_range.start() + 1..=in_mem_range.end() - 1)?,
2207 &in_memory_data[1..in_memory_data.len() - 1],
2208 "partial mem data"
2209 );
2210
2211 assert_eq!(provider.$method(in_mem_range.start() + 1..)?, &in_memory_data[1..], "unbounded mem data");
2213
2214 assert_eq!(provider.$method(in_mem_range.end()..)?, &in_memory_data[in_memory_data.len() -1 ..], "last mem data");
2216
2217 assert_eq!(
2219 provider.$method(in_mem_range.start() - 2..)?,
2220 database_data[database_data.len() - 2..]
2221 .iter()
2222 .chain(&in_memory_data[..])
2223 .cloned()
2224 .collect::<Vec<_>>(),
2225 "unbounded span data"
2226 );
2227
2228 #[allow(unused_assignments)]
2230 {
2231 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2233
2234 assert_eq!(
2235 provider.$method(in_mem_range.start() - 2..=in_mem_range.end() - 1)?,
2236 database_data[database_data.len() - 2..]
2237 .iter()
2238 .chain(&in_memory_data[..in_memory_data.len() - 1])
2239 .cloned()
2240 .collect::<Vec<_>>(),
2241 "span data"
2242 );
2243
2244 database_blocks.push(in_memory_blocks.remove(0));
2246 }
2247
2248 let start_tx_num = u64::MAX;
2250 let end_tx_num = u64::MAX;
2251 let result = provider.$method(start_tx_num..end_tx_num)?;
2252 assert!(result.is_empty(), "No data should be found for an invalid transaction range");
2253
2254 let result = provider.$method(in_mem_range.end()+10..in_mem_range.end()+20)?;
2256 assert!(result.is_empty(), "No data should be found for an empty transaction range");
2257 )*
2258 }};
2259 }
2260
2261 #[test]
2262 fn test_methods_by_tx_range() -> eyre::Result<()> {
2263 test_by_tx_range!([
2264 (senders_by_tx_range, |block: &SealedBlock, _: &Vec<Vec<Receipt>>| block
2265 .senders()
2266 .unwrap()),
2267 (transactions_by_tx_range, |block: &SealedBlock, _: &Vec<Vec<Receipt>>| block
2268 .body()
2269 .transactions
2270 .clone()),
2271 (receipts_by_tx_range, |block: &SealedBlock, receipts: &Vec<Vec<Receipt>>| receipts
2272 [block.number as usize]
2273 .clone())
2274 ]);
2275
2276 Ok(())
2277 }
2278
2279 macro_rules! test_by_block_range {
2280 ([$(($method:ident, $data_extractor:expr)),* $(,)?]) => {{
2281 let extra_blocks = [$(stringify!($method)),*].len();
2284
2285 let mut rng = generators::rng();
2286 let (provider, mut database_blocks, mut in_memory_blocks, _) = provider_with_random_blocks(
2287 &mut rng,
2288 TEST_BLOCKS_COUNT,
2289 TEST_BLOCKS_COUNT + extra_blocks,
2290 BlockRangeParams {
2291 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2292 ..Default::default()
2293 },
2294 )?;
2295
2296 $(
2297 let db_block_count = database_blocks.len() as u64;
2299 let in_mem_block_count = in_memory_blocks.len() as u64;
2300
2301 let db_range = 0..=db_block_count - 1;
2302 let in_mem_range = db_block_count..=(in_mem_block_count + db_range.end());
2303
2304 let database_data =
2306 database_blocks.iter().map(|b| $data_extractor(b)).collect::<Vec<_>>();
2307 assert_eq!(provider.$method(db_range.clone())?, database_data);
2308
2309 let in_memory_data =
2311 in_memory_blocks.iter().map(|b| $data_extractor(b)).collect::<Vec<_>>();
2312 assert_eq!(provider.$method(in_mem_range.clone())?, in_memory_data);
2313
2314 assert_eq!(
2316 &provider.$method(in_mem_range.start() + 1..=in_mem_range.end() - 1)?,
2317 &in_memory_data[1..in_memory_data.len() - 1]
2318 );
2319
2320 {
2322
2323 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2325
2326 assert_eq!(
2327 provider.$method(in_mem_range.start() - 2..=in_mem_range.end() - 1)?,
2328 database_data[database_data.len() - 2..]
2329 .iter()
2330 .chain(&in_memory_data[..in_memory_data.len() - 1])
2331 .cloned()
2332 .collect::<Vec<_>>()
2333 );
2334
2335 database_blocks.push(in_memory_blocks.remove(0));
2337 }
2338
2339 let start_block_num = u64::MAX;
2341 let end_block_num = u64::MAX;
2342 let result = provider.$method(start_block_num..=end_block_num-1)?;
2343 assert!(result.is_empty(), "No data should be found for an invalid block range");
2344
2345 let result = provider.$method(in_mem_range.end() + 10..=in_mem_range.end() + 20)?;
2347 assert!(result.is_empty(), "No data should be found for an empty block range");
2348 )*
2349 }};
2350 }
2351
2352 #[test]
2353 fn test_methods_by_block_range() -> eyre::Result<()> {
2354 test_by_block_range!([
2357 (headers_range, |block: &SealedBlock| block.header().clone()),
2358 (sealed_headers_range, |block: &SealedBlock| block.clone_sealed_header()),
2359 (block_range, |block: &SealedBlock| block.clone().into_block()),
2360 (block_with_senders_range, |block: &SealedBlock| block.clone().try_recover().unwrap()),
2361 (recovered_block_range, |block: &SealedBlock| block.clone().try_recover().unwrap()),
2362 (transactions_by_block_range, |block: &SealedBlock| block.body().transactions.clone()),
2363 ]);
2364
2365 Ok(())
2366 }
2367
2368 macro_rules! call_method {
2370 ($provider:expr, $method:ident, ($($args:expr),*), $expected_item:expr) => {{
2371 let result = $provider.$method($($args),*)?;
2372 assert_eq!(
2373 result,
2374 $expected_item,
2375 "{}: item does not match the expected item for arguments {:?}",
2376 stringify!($method),
2377 ($($args),*)
2378 );
2379 }};
2380
2381 (ONE, $provider:expr, $method:ident, $item_extractor:expr, $txnum:expr, $txhash:expr, $block:expr, $receipts:expr) => {{
2383 let (arg, expected_item) = $item_extractor($block, $txnum($block), $txhash($block), $receipts);
2384 call_method!($provider, $method, (arg), expected_item);
2385 }};
2386
2387 (TWO, $provider:expr, $method:ident, $item_extractor:expr, $txnum:expr, $txhash:expr, $block:expr, $receipts:expr) => {{
2389 let ((arg1, arg2), expected_item) = $item_extractor($block, $txnum($block), $txhash($block), $receipts);
2390 call_method!($provider, $method, (arg1, arg2), expected_item);
2391 }};
2392 }
2393
2394 macro_rules! test_non_range {
2399 ([$(($arg_count:ident, $method:ident, $item_extractor:expr, $invalid_args:expr)),* $(,)?]) => {{
2400
2401 let extra_blocks = [$(stringify!($arg_count)),*].len();
2404
2405 let mut rng = generators::rng();
2406 let (provider, mut database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
2407 &mut rng,
2408 TEST_BLOCKS_COUNT,
2409 TEST_BLOCKS_COUNT + extra_blocks,
2410 BlockRangeParams {
2411 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2412 ..Default::default()
2413 },
2414 )?;
2415
2416 let mut in_memory_blocks: std::collections::VecDeque<_> = in_memory_blocks.into();
2417
2418 $(
2419 let tx_hash = |block: &SealedBlock| *block.body().transactions[0].tx_hash();
2420 let tx_num = |block: &SealedBlock| {
2421 database_blocks
2422 .iter()
2423 .chain(in_memory_blocks.iter())
2424 .take_while(|b| b.number < block.number)
2425 .map(|b| b.transaction_count())
2426 .sum::<usize>() as u64
2427 };
2428
2429 {
2431 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2433
2434 call_method!($arg_count, provider, $method, $item_extractor, tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2435
2436 database_blocks.push(in_memory_blocks.pop_front().unwrap());
2438 }
2439
2440 let tx_num = |block: &SealedBlock| {
2442 database_blocks
2443 .iter()
2444 .chain(in_memory_blocks.iter())
2445 .take_while(|b| b.number < block.number)
2446 .map(|b| b.transaction_count())
2447 .sum::<usize>() as u64
2448 };
2449
2450 {
2452 call_method!($arg_count, provider, $method, |_,_,_,_| ( ($invalid_args, None)), tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2453 }
2454
2455 {
2457 let last_mem_block = &in_memory_blocks[in_memory_blocks.len() - 1];
2458
2459 let (args, expected_item) = $item_extractor(last_mem_block, tx_num(last_mem_block), tx_hash(last_mem_block), &receipts);
2460 call_method!($arg_count, provider, $method, |_,_,_,_| (args.clone(), expected_item), tx_num, tx_hash, last_mem_block, &receipts);
2461
2462 call_method!($arg_count, provider.database, $method, |_,_,_,_| ( (args, None)), tx_num, tx_hash, last_mem_block, &receipts);
2464 }
2465 )*
2466 }};
2467}
2468
2469 #[test]
2470 fn test_non_range_methods() -> eyre::Result<()> {
2471 let test_tx_index = 0;
2472
2473 test_non_range!([
2474 (
2482 ONE,
2483 header_by_number,
2484 |block: &SealedBlock, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2485 block.number,
2486 Some(block.header().clone())
2487 ),
2488 u64::MAX
2489 ),
2490 (
2491 ONE,
2492 sealed_header,
2493 |block: &SealedBlock, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2494 block.number,
2495 Some(block.clone_sealed_header())
2496 ),
2497 u64::MAX
2498 ),
2499 (
2500 ONE,
2501 block_hash,
2502 |block: &SealedBlock, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2503 block.number,
2504 Some(block.hash())
2505 ),
2506 u64::MAX
2507 ),
2508 (
2509 ONE,
2510 block_number,
2511 |block: &SealedBlock, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2512 block.hash(),
2513 Some(block.number)
2514 ),
2515 B256::random()
2516 ),
2517 (
2518 ONE,
2519 block,
2520 |block: &SealedBlock, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2521 BlockHashOrNumber::Hash(block.hash()),
2522 Some(block.clone().into_block())
2523 ),
2524 BlockHashOrNumber::Hash(B256::random())
2525 ),
2526 (
2527 ONE,
2528 block,
2529 |block: &SealedBlock, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2530 BlockHashOrNumber::Number(block.number),
2531 Some(block.clone().into_block())
2532 ),
2533 BlockHashOrNumber::Number(u64::MAX)
2534 ),
2535 (
2536 ONE,
2537 block_body_indices,
2538 |block: &SealedBlock, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2539 block.number,
2540 Some(StoredBlockBodyIndices {
2541 first_tx_num: tx_num,
2542 tx_count: block.transaction_count() as u64
2543 })
2544 ),
2545 u64::MAX
2546 ),
2547 (
2548 TWO,
2549 recovered_block,
2550 |block: &SealedBlock, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2551 (BlockHashOrNumber::Number(block.number), TransactionVariant::WithHash),
2552 block.clone().try_recover().ok()
2553 ),
2554 (BlockHashOrNumber::Number(u64::MAX), TransactionVariant::WithHash)
2555 ),
2556 (
2557 TWO,
2558 recovered_block,
2559 |block: &SealedBlock, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2560 (BlockHashOrNumber::Hash(block.hash()), TransactionVariant::WithHash),
2561 block.clone().try_recover().ok()
2562 ),
2563 (BlockHashOrNumber::Hash(B256::random()), TransactionVariant::WithHash)
2564 ),
2565 (
2566 TWO,
2567 sealed_block_with_senders,
2568 |block: &SealedBlock, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2569 (BlockHashOrNumber::Number(block.number), TransactionVariant::WithHash),
2570 block.clone().try_recover().ok()
2571 ),
2572 (BlockHashOrNumber::Number(u64::MAX), TransactionVariant::WithHash)
2573 ),
2574 (
2575 TWO,
2576 sealed_block_with_senders,
2577 |block: &SealedBlock, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2578 (BlockHashOrNumber::Hash(block.hash()), TransactionVariant::WithHash),
2579 block.clone().try_recover().ok()
2580 ),
2581 (BlockHashOrNumber::Hash(B256::random()), TransactionVariant::WithHash)
2582 ),
2583 (
2584 ONE,
2585 transaction_id,
2586 |_: &SealedBlock, tx_num: TxNumber, tx_hash: B256, _: &Vec<Vec<Receipt>>| (
2587 tx_hash,
2588 Some(tx_num)
2589 ),
2590 B256::random()
2591 ),
2592 (
2593 ONE,
2594 transaction_by_id,
2595 |block: &SealedBlock, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2596 tx_num,
2597 Some(block.body().transactions[test_tx_index].clone())
2598 ),
2599 u64::MAX
2600 ),
2601 (
2602 ONE,
2603 transaction_by_id_unhashed,
2604 |block: &SealedBlock, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2605 tx_num,
2606 Some(block.body().transactions[test_tx_index].clone())
2607 ),
2608 u64::MAX
2609 ),
2610 (
2611 ONE,
2612 transaction_by_hash,
2613 |block: &SealedBlock, _: TxNumber, tx_hash: B256, _: &Vec<Vec<Receipt>>| (
2614 tx_hash,
2615 Some(block.body().transactions[test_tx_index].clone())
2616 ),
2617 B256::random()
2618 ),
2619 (
2620 ONE,
2621 transaction_block,
2622 |block: &SealedBlock, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2623 tx_num,
2624 Some(block.number)
2625 ),
2626 u64::MAX
2627 ),
2628 (
2629 ONE,
2630 transactions_by_block,
2631 |block: &SealedBlock, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2632 BlockHashOrNumber::Number(block.number),
2633 Some(block.body().transactions.clone())
2634 ),
2635 BlockHashOrNumber::Number(u64::MAX)
2636 ),
2637 (
2638 ONE,
2639 transactions_by_block,
2640 |block: &SealedBlock, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2641 BlockHashOrNumber::Hash(block.hash()),
2642 Some(block.body().transactions.clone())
2643 ),
2644 BlockHashOrNumber::Number(u64::MAX)
2645 ),
2646 (
2647 ONE,
2648 transaction_sender,
2649 |block: &SealedBlock, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2650 tx_num,
2651 block.body().transactions[test_tx_index].recover_signer().ok()
2652 ),
2653 u64::MAX
2654 ),
2655 (
2656 ONE,
2657 receipt,
2658 |block: &SealedBlock, tx_num: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2659 tx_num,
2660 Some(receipts[block.number as usize][test_tx_index].clone())
2661 ),
2662 u64::MAX
2663 ),
2664 (
2665 ONE,
2666 receipt_by_hash,
2667 |block: &SealedBlock, _: TxNumber, tx_hash: B256, receipts: &Vec<Vec<Receipt>>| (
2668 tx_hash,
2669 Some(receipts[block.number as usize][test_tx_index].clone())
2670 ),
2671 B256::random()
2672 ),
2673 (
2674 ONE,
2675 receipts_by_block,
2676 |block: &SealedBlock, _: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2677 BlockHashOrNumber::Number(block.number),
2678 Some(receipts[block.number as usize].clone())
2679 ),
2680 BlockHashOrNumber::Number(u64::MAX)
2681 ),
2682 (
2683 ONE,
2684 receipts_by_block,
2685 |block: &SealedBlock, _: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2686 BlockHashOrNumber::Hash(block.hash()),
2687 Some(receipts[block.number as usize].clone())
2688 ),
2689 BlockHashOrNumber::Hash(B256::random())
2690 ),
2691 ]);
2693
2694 Ok(())
2695 }
2696
2697 #[test]
2698 fn test_race() -> eyre::Result<()> {
2699 let mut rng = generators::rng();
2700 let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
2701 &mut rng,
2702 TEST_BLOCKS_COUNT - 1,
2703 TEST_BLOCKS_COUNT + 1,
2704 BlockRangeParams {
2705 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2706 ..Default::default()
2707 },
2708 )?;
2709
2710 let old_transaction_hash_fn =
2713 |hash: B256,
2714 canonical_in_memory_state: CanonicalInMemoryState,
2715 factory: ProviderFactory<MockNodeTypesWithDB>| {
2716 assert!(factory.transaction_by_hash(hash)?.is_none(), "should not be in database");
2717 Ok::<_, ProviderError>(canonical_in_memory_state.transaction_by_hash(hash))
2718 };
2719
2720 let correct_transaction_hash_fn =
2722 |hash: B256,
2723 canonical_in_memory_state: CanonicalInMemoryState,
2724 _factory: ProviderFactory<MockNodeTypesWithDB>| {
2725 if let Some(tx) = canonical_in_memory_state.transaction_by_hash(hash) {
2726 return Ok::<_, ProviderError>(Some(tx));
2727 }
2728 panic!("should not be in database");
2729 };
2731
2732 {
2734 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2737 let to_be_persisted_tx = in_memory_blocks[0].body().transactions[0].clone();
2738
2739 assert!(matches!(
2742 old_transaction_hash_fn(
2743 *to_be_persisted_tx.tx_hash(),
2744 provider.canonical_in_memory_state(),
2745 provider.database.clone()
2746 ),
2747 Ok(None)
2748 ));
2749 }
2750
2751 {
2753 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[1].number);
2756 let to_be_persisted_tx = in_memory_blocks[1].body().transactions[0].clone();
2757
2758 assert!(matches!(
2759 correct_transaction_hash_fn(
2760 *to_be_persisted_tx.tx_hash(),
2761 provider.canonical_in_memory_state(),
2762 provider.database
2763 ),
2764 Ok(Some(to_be_persisted_tx))
2765 ));
2766 }
2767
2768 Ok(())
2769 }
2770}