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