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