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