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