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