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, TrieReader,
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::{updates::TrieUpdatesSorted, 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
716impl<N: ProviderNodeTypes> ChangeSetReader for BlockchainProvider<N> {
717 fn account_block_changeset(
718 &self,
719 block_number: BlockNumber,
720 ) -> ProviderResult<Vec<AccountBeforeTx>> {
721 self.consistent_provider()?.account_block_changeset(block_number)
722 }
723
724 fn get_account_before_block(
725 &self,
726 block_number: BlockNumber,
727 address: Address,
728 ) -> ProviderResult<Option<AccountBeforeTx>> {
729 self.consistent_provider()?.get_account_before_block(block_number, address)
730 }
731
732 fn account_changesets_range(
733 &self,
734 range: impl core::ops::RangeBounds<BlockNumber>,
735 ) -> ProviderResult<Vec<(BlockNumber, AccountBeforeTx)>> {
736 self.consistent_provider()?.account_changesets_range(range)
737 }
738
739 fn account_changeset_count(&self) -> ProviderResult<usize> {
740 self.consistent_provider()?.account_changeset_count()
741 }
742}
743
744impl<N: ProviderNodeTypes> AccountReader for BlockchainProvider<N> {
745 fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
747 self.consistent_provider()?.basic_account(address)
748 }
749}
750
751impl<N: ProviderNodeTypes> StateReader for BlockchainProvider<N> {
752 type Receipt = ReceiptTy<N>;
753
754 fn get_state(
764 &self,
765 block: BlockNumber,
766 ) -> ProviderResult<Option<ExecutionOutcome<Self::Receipt>>> {
767 StateReader::get_state(&self.consistent_provider()?, block)
768 }
769}
770
771impl<N: ProviderNodeTypes> TrieReader for BlockchainProvider<N> {
772 fn trie_reverts(&self, from: BlockNumber) -> ProviderResult<TrieUpdatesSorted> {
773 self.consistent_provider()?.trie_reverts(from)
774 }
775
776 fn get_block_trie_updates(
777 &self,
778 block_number: BlockNumber,
779 ) -> ProviderResult<TrieUpdatesSorted> {
780 self.consistent_provider()?.get_block_trie_updates(block_number)
781 }
782}
783
784#[cfg(test)]
785mod tests {
786 use crate::{
787 providers::BlockchainProvider,
788 test_utils::{
789 create_test_provider_factory, create_test_provider_factory_with_chain_spec,
790 MockNodeTypesWithDB,
791 },
792 BlockWriter, CanonChainTracker, ProviderFactory,
793 };
794 use alloy_eips::{BlockHashOrNumber, BlockNumHash, BlockNumberOrTag};
795 use alloy_primitives::{BlockNumber, TxNumber, B256};
796 use itertools::Itertools;
797 use rand::Rng;
798 use reth_chain_state::{
799 test_utils::TestBlockBuilder, CanonStateNotification, CanonStateSubscriptions,
800 CanonicalInMemoryState, ExecutedBlock, NewCanonicalChain,
801 };
802 use reth_chainspec::{ChainSpec, MAINNET};
803 use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices};
804 use reth_errors::ProviderError;
805 use reth_ethereum_primitives::{Block, Receipt};
806 use reth_execution_types::{Chain, ExecutionOutcome};
807 use reth_primitives_traits::{RecoveredBlock, SealedBlock, SignerRecoverable};
808 use reth_storage_api::{
809 BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader,
810 BlockReaderIdExt, BlockSource, ChangeSetReader, DBProvider, DatabaseProviderFactory,
811 HeaderProvider, ReceiptProvider, ReceiptProviderIdExt, StateProviderFactory, StateWriter,
812 TransactionVariant, TransactionsProvider,
813 };
814 use reth_testing_utils::generators::{
815 self, random_block, random_block_range, random_changeset_range, random_eoa_accounts,
816 random_receipt, BlockParams, BlockRangeParams,
817 };
818 use revm_database::{BundleState, OriginalValuesKnown};
819 use std::{
820 collections::BTreeMap,
821 ops::{Bound, Range, RangeBounds},
822 sync::Arc,
823 };
824
825 const TEST_BLOCKS_COUNT: usize = 5;
826
827 const TEST_TRANSACTIONS_COUNT: u8 = 4;
828
829 fn random_blocks(
830 rng: &mut impl Rng,
831 database_blocks: usize,
832 in_memory_blocks: usize,
833 requests_count: Option<Range<u8>>,
834 withdrawals_count: Option<Range<u8>>,
835 tx_count: impl RangeBounds<u8>,
836 ) -> (Vec<SealedBlock<Block>>, Vec<SealedBlock<Block>>) {
837 let block_range = (database_blocks + in_memory_blocks - 1) as u64;
838
839 let tx_start = match tx_count.start_bound() {
840 Bound::Included(&n) | Bound::Excluded(&n) => n,
841 Bound::Unbounded => u8::MIN,
842 };
843 let tx_end = match tx_count.end_bound() {
844 Bound::Included(&n) | Bound::Excluded(&n) => n + 1,
845 Bound::Unbounded => u8::MAX,
846 };
847
848 let blocks = random_block_range(
849 rng,
850 0..=block_range,
851 BlockRangeParams {
852 parent: Some(B256::ZERO),
853 tx_count: tx_start..tx_end,
854 requests_count,
855 withdrawals_count,
856 },
857 );
858 let (database_blocks, in_memory_blocks) = blocks.split_at(database_blocks);
859 (database_blocks.to_vec(), in_memory_blocks.to_vec())
860 }
861
862 #[expect(clippy::type_complexity)]
863 fn provider_with_chain_spec_and_random_blocks(
864 rng: &mut impl Rng,
865 chain_spec: Arc<ChainSpec>,
866 database_blocks: usize,
867 in_memory_blocks: usize,
868 block_range_params: BlockRangeParams,
869 ) -> eyre::Result<(
870 BlockchainProvider<MockNodeTypesWithDB>,
871 Vec<SealedBlock<Block>>,
872 Vec<SealedBlock<Block>>,
873 Vec<Vec<Receipt>>,
874 )> {
875 let (database_blocks, in_memory_blocks) = random_blocks(
876 rng,
877 database_blocks,
878 in_memory_blocks,
879 block_range_params.requests_count,
880 block_range_params.withdrawals_count,
881 block_range_params.tx_count,
882 );
883
884 let receipts: Vec<Vec<_>> = database_blocks
885 .iter()
886 .chain(in_memory_blocks.iter())
887 .map(|block| block.body().transactions.iter())
888 .map(|tx| tx.map(|tx| random_receipt(rng, tx, Some(2), None)).collect())
889 .collect();
890
891 let factory = create_test_provider_factory_with_chain_spec(chain_spec);
892 let provider_rw = factory.database_provider_rw()?;
893
894 for block in &database_blocks {
896 provider_rw.insert_block(
897 &block.clone().try_recover().expect("failed to seal block with senders"),
898 )?;
899 }
900
901 if let Some(first_block) = database_blocks.first() {
903 provider_rw.write_state(
904 &ExecutionOutcome {
905 first_block: first_block.number,
906 receipts: receipts.iter().take(database_blocks.len()).cloned().collect(),
907 ..Default::default()
908 },
909 OriginalValuesKnown::No,
910 )?;
911 }
912
913 provider_rw.commit()?;
914
915 let provider = BlockchainProvider::new(factory)?;
916
917 let chain = NewCanonicalChain::Commit {
919 new: in_memory_blocks
920 .iter()
921 .map(|block| {
922 let senders = block.senders().expect("failed to recover senders");
923 let block_receipts = receipts.get(block.number as usize).unwrap().clone();
924 let execution_outcome =
925 ExecutionOutcome { receipts: vec![block_receipts], ..Default::default() };
926
927 ExecutedBlock {
928 recovered_block: Arc::new(RecoveredBlock::new_sealed(
929 block.clone(),
930 senders,
931 )),
932 execution_output: execution_outcome.into(),
933 ..Default::default()
934 }
935 })
936 .collect(),
937 };
938 provider.canonical_in_memory_state.update_chain(chain);
939
940 let blocks = database_blocks.iter().chain(in_memory_blocks.iter()).collect::<Vec<_>>();
942 let block_count = blocks.len();
943 let canonical_block = blocks.get(block_count - 1).unwrap();
944 let safe_block = blocks.get(block_count - 2).unwrap();
945 let finalized_block = blocks.get(block_count - 3).unwrap();
946
947 provider.set_canonical_head(canonical_block.clone_sealed_header());
949 provider.set_safe(safe_block.clone_sealed_header());
950 provider.set_finalized(finalized_block.clone_sealed_header());
951
952 Ok((provider, database_blocks.clone(), in_memory_blocks.clone(), receipts))
953 }
954
955 #[expect(clippy::type_complexity)]
956 fn provider_with_random_blocks(
957 rng: &mut impl Rng,
958 database_blocks: usize,
959 in_memory_blocks: usize,
960 block_range_params: BlockRangeParams,
961 ) -> eyre::Result<(
962 BlockchainProvider<MockNodeTypesWithDB>,
963 Vec<SealedBlock<Block>>,
964 Vec<SealedBlock<Block>>,
965 Vec<Vec<Receipt>>,
966 )> {
967 provider_with_chain_spec_and_random_blocks(
968 rng,
969 MAINNET.clone(),
970 database_blocks,
971 in_memory_blocks,
972 block_range_params,
973 )
974 }
975
976 fn persist_block_after_db_tx_creation(
982 provider: BlockchainProvider<MockNodeTypesWithDB>,
983 block_number: BlockNumber,
984 ) {
985 let hook_provider = provider.clone();
986 provider.database.db_ref().set_post_transaction_hook(Box::new(move || {
987 if let Some(state) = hook_provider.canonical_in_memory_state.head_state() &&
988 state.anchor().number + 1 == block_number
989 {
990 let mut lowest_memory_block =
991 state.parent_state_chain().last().expect("qed").block();
992 let num_hash = lowest_memory_block.recovered_block().num_hash();
993
994 let mut execution_output = (*lowest_memory_block.execution_output).clone();
995 execution_output.first_block = lowest_memory_block.recovered_block().number;
996 lowest_memory_block.execution_output = Arc::new(execution_output);
997
998 let provider_rw = hook_provider.database_provider_rw().unwrap();
1000 provider_rw.save_blocks(vec![lowest_memory_block]).unwrap();
1001 provider_rw.commit().unwrap();
1002
1003 hook_provider.canonical_in_memory_state.remove_persisted_blocks(num_hash);
1005 }
1006 }));
1007 }
1008
1009 #[test]
1010 fn test_block_reader_find_block_by_hash() -> eyre::Result<()> {
1011 let mut rng = generators::rng();
1013 let factory = create_test_provider_factory();
1014
1015 let blocks = random_block_range(
1017 &mut rng,
1018 0..=10,
1019 BlockRangeParams { parent: Some(B256::ZERO), tx_count: 0..1, ..Default::default() },
1020 );
1021 let (database_blocks, in_memory_blocks) = blocks.split_at(5);
1022
1023 let provider_rw = factory.provider_rw()?;
1025 for block in database_blocks {
1026 provider_rw.insert_block(
1027 &block.clone().try_recover().expect("failed to seal block with senders"),
1028 )?;
1029 }
1030
1031 provider_rw.commit()?;
1032
1033 let provider = BlockchainProvider::new(factory)?;
1035
1036 let first_db_block = database_blocks.first().unwrap();
1038 let first_in_mem_block = in_memory_blocks.first().unwrap();
1039 let last_in_mem_block = in_memory_blocks.last().unwrap();
1040
1041 assert_eq!(provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Any)?, None);
1043 assert_eq!(
1044 provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Canonical)?,
1045 None
1046 );
1047 assert_eq!(
1049 provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Pending)?,
1050 None
1051 );
1052
1053 let in_memory_block_senders =
1055 first_in_mem_block.senders().expect("failed to recover senders");
1056 let chain = NewCanonicalChain::Commit {
1057 new: vec![ExecutedBlock {
1058 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1059 first_in_mem_block.clone(),
1060 in_memory_block_senders,
1061 )),
1062 ..Default::default()
1063 }],
1064 };
1065 provider.canonical_in_memory_state.update_chain(chain);
1066
1067 assert_eq!(
1069 provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Any)?,
1070 Some(first_in_mem_block.clone().into_block())
1071 );
1072 assert_eq!(
1073 provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Canonical)?,
1074 Some(first_in_mem_block.clone().into_block())
1075 );
1076
1077 assert_eq!(
1079 provider.find_block_by_hash(first_db_block.hash(), BlockSource::Any)?,
1080 Some(first_db_block.clone().into_block())
1081 );
1082 assert_eq!(
1083 provider.find_block_by_hash(first_db_block.hash(), BlockSource::Canonical)?,
1084 Some(first_db_block.clone().into_block())
1085 );
1086
1087 assert_eq!(provider.find_block_by_hash(first_db_block.hash(), BlockSource::Pending)?, None);
1089
1090 provider.canonical_in_memory_state.set_pending_block(ExecutedBlock {
1092 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1093 last_in_mem_block.clone(),
1094 Default::default(),
1095 )),
1096 ..Default::default()
1097 });
1098
1099 assert_eq!(
1101 provider.find_block_by_hash(last_in_mem_block.hash(), BlockSource::Pending)?,
1102 Some(last_in_mem_block.clone().into_block())
1103 );
1104
1105 Ok(())
1106 }
1107
1108 #[test]
1109 fn test_block_reader_block() -> eyre::Result<()> {
1110 let mut rng = generators::rng();
1112 let factory = create_test_provider_factory();
1113
1114 let blocks = random_block_range(
1116 &mut rng,
1117 0..=10,
1118 BlockRangeParams { parent: Some(B256::ZERO), tx_count: 0..1, ..Default::default() },
1119 );
1120 let (database_blocks, in_memory_blocks) = blocks.split_at(5);
1121
1122 let provider_rw = factory.provider_rw()?;
1124 for block in database_blocks {
1125 provider_rw.insert_block(
1126 &block.clone().try_recover().expect("failed to seal block with senders"),
1127 )?;
1128 }
1129 provider_rw.commit()?;
1130
1131 let provider = BlockchainProvider::new(factory)?;
1133
1134 let first_in_mem_block = in_memory_blocks.first().unwrap();
1136 let first_db_block = database_blocks.first().unwrap();
1138
1139 assert_eq!(provider.block(BlockHashOrNumber::Hash(first_in_mem_block.hash()))?, None);
1141 assert_eq!(provider.block(BlockHashOrNumber::Number(first_in_mem_block.number))?, None);
1142
1143 let in_memory_block_senders =
1145 first_in_mem_block.senders().expect("failed to recover senders");
1146 let chain = NewCanonicalChain::Commit {
1147 new: vec![ExecutedBlock {
1148 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1149 first_in_mem_block.clone(),
1150 in_memory_block_senders,
1151 )),
1152 ..Default::default()
1153 }],
1154 };
1155 provider.canonical_in_memory_state.update_chain(chain);
1156
1157 assert_eq!(
1159 provider.block(BlockHashOrNumber::Hash(first_in_mem_block.hash()))?,
1160 Some(first_in_mem_block.clone().into_block())
1161 );
1162 assert_eq!(
1163 provider.block(BlockHashOrNumber::Number(first_in_mem_block.number))?,
1164 Some(first_in_mem_block.clone().into_block())
1165 );
1166
1167 assert_eq!(
1169 provider.block(BlockHashOrNumber::Hash(first_db_block.hash()))?,
1170 Some(first_db_block.clone().into_block())
1171 );
1172 assert_eq!(
1173 provider.block(BlockHashOrNumber::Number(first_db_block.number))?,
1174 Some(first_db_block.clone().into_block())
1175 );
1176
1177 Ok(())
1178 }
1179
1180 #[test]
1181 fn test_block_reader_pending_block() -> eyre::Result<()> {
1182 let mut rng = generators::rng();
1183 let (provider, _, _, _) = provider_with_random_blocks(
1184 &mut rng,
1185 TEST_BLOCKS_COUNT,
1186 TEST_BLOCKS_COUNT,
1187 BlockRangeParams::default(),
1188 )?;
1189
1190 let mut rng = generators::rng();
1192 let block = random_block(
1193 &mut rng,
1194 0,
1195 BlockParams { parent: Some(B256::ZERO), ..Default::default() },
1196 );
1197
1198 provider.canonical_in_memory_state.set_pending_block(ExecutedBlock {
1200 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1201 block.clone(),
1202 block.senders().unwrap(),
1203 )),
1204 ..Default::default()
1205 });
1206
1207 assert_eq!(
1210 provider.pending_block()?,
1211 Some(RecoveredBlock::new_sealed(block.clone(), block.senders().unwrap()))
1212 );
1213
1214 assert_eq!(
1215 provider.pending_block_and_receipts()?,
1216 Some((RecoveredBlock::new_sealed(block.clone(), block.senders().unwrap()), vec![]))
1217 );
1218
1219 Ok(())
1220 }
1221
1222 #[test]
1223 fn test_block_body_indices() -> eyre::Result<()> {
1224 let mut rng = generators::rng();
1226 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1227 &mut rng,
1228 TEST_BLOCKS_COUNT,
1229 TEST_BLOCKS_COUNT,
1230 BlockRangeParams {
1231 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
1232 ..Default::default()
1233 },
1234 )?;
1235
1236 let first_in_mem_block = in_memory_blocks.first().unwrap();
1237
1238 let in_memory_block_senders =
1240 first_in_mem_block.senders().expect("failed to recover senders");
1241 let chain = NewCanonicalChain::Commit {
1242 new: vec![ExecutedBlock {
1243 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1244 first_in_mem_block.clone(),
1245 in_memory_block_senders,
1246 )),
1247 ..Default::default()
1248 }],
1249 };
1250 provider.canonical_in_memory_state.update_chain(chain);
1251
1252 let first_db_block = database_blocks.first().unwrap().clone();
1253 let first_in_mem_block = in_memory_blocks.first().unwrap().clone();
1254
1255 assert_eq!(
1257 provider.block_body_indices(first_db_block.number)?.unwrap(),
1258 StoredBlockBodyIndices { first_tx_num: 0, tx_count: 4 }
1259 );
1260
1261 assert_eq!(
1264 provider.block_body_indices(first_in_mem_block.number)?.unwrap(),
1265 StoredBlockBodyIndices { first_tx_num: 20, tx_count: 4 }
1266 );
1267
1268 let mut rng = rand::rng();
1270 let random_block_number: u64 = rng.random();
1271 assert_eq!(provider.block_body_indices(random_block_number)?, None);
1272
1273 Ok(())
1274 }
1275
1276 #[test]
1277 fn test_block_hash_reader() -> eyre::Result<()> {
1278 let mut rng = generators::rng();
1279 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1280 &mut rng,
1281 TEST_BLOCKS_COUNT,
1282 TEST_BLOCKS_COUNT,
1283 BlockRangeParams::default(),
1284 )?;
1285
1286 let database_block = database_blocks.first().unwrap().clone();
1287 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1288
1289 assert_eq!(provider.block_hash(database_block.number)?, Some(database_block.hash()));
1290 assert_eq!(provider.block_hash(in_memory_block.number)?, Some(in_memory_block.hash()));
1291
1292 assert_eq!(
1293 provider.canonical_hashes_range(0, 10)?,
1294 [database_blocks, in_memory_blocks]
1295 .concat()
1296 .iter()
1297 .map(|block| block.hash())
1298 .collect::<Vec<_>>()
1299 );
1300
1301 Ok(())
1302 }
1303
1304 #[test]
1305 fn test_header_provider() -> eyre::Result<()> {
1306 let mut rng = generators::rng();
1307 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1308 &mut rng,
1309 TEST_BLOCKS_COUNT,
1310 TEST_BLOCKS_COUNT,
1311 BlockRangeParams::default(),
1312 )?;
1313
1314 let finalized_block = database_blocks.get(database_blocks.len() - 3).unwrap();
1316 provider.set_finalized(finalized_block.clone_sealed_header());
1317
1318 let blocks = [database_blocks, in_memory_blocks].concat();
1319
1320 assert_eq!(
1321 provider.sealed_headers_while(0..=10, |header| header.number <= 8)?,
1322 blocks
1323 .iter()
1324 .take_while(|header| header.number <= 8)
1325 .map(|b| b.clone_sealed_header())
1326 .collect::<Vec<_>>()
1327 );
1328
1329 Ok(())
1330 }
1331
1332 #[tokio::test]
1333 async fn test_canon_state_subscriptions() -> eyre::Result<()> {
1334 let factory = create_test_provider_factory();
1335
1336 let mut test_block_builder = TestBlockBuilder::eth();
1338 let block_1 = test_block_builder.generate_random_block(0, B256::ZERO).try_recover()?;
1339 let block_hash_1 = block_1.hash();
1340
1341 let provider_rw = factory.provider_rw()?;
1343 provider_rw.insert_block(&block_1)?;
1344 provider_rw.commit()?;
1345
1346 let provider = BlockchainProvider::new(factory)?;
1347
1348 let in_memory_state = provider.canonical_in_memory_state();
1350 let mut rx_1 = provider.subscribe_to_canonical_state();
1351 let mut rx_2 = provider.subscribe_to_canonical_state();
1352
1353 let block_2 = test_block_builder.generate_random_block(1, block_hash_1).try_recover()?;
1355 let chain = Chain::new(
1356 vec![block_2],
1357 ExecutionOutcome::default(),
1358 BTreeMap::new(),
1359 BTreeMap::new(),
1360 );
1361 let commit = CanonStateNotification::Commit { new: Arc::new(chain.clone()) };
1362 in_memory_state.notify_canon_state(commit.clone());
1363 let (notification_1, notification_2) = tokio::join!(rx_1.recv(), rx_2.recv());
1364 assert_eq!(notification_1, Ok(commit.clone()));
1365 assert_eq!(notification_2, Ok(commit.clone()));
1366
1367 let block_3 = test_block_builder.generate_random_block(1, block_hash_1).try_recover()?;
1369 let block_4 = test_block_builder.generate_random_block(2, block_3.hash()).try_recover()?;
1370 let new_chain = Chain::new(
1371 vec![block_3, block_4],
1372 ExecutionOutcome::default(),
1373 BTreeMap::new(),
1374 BTreeMap::new(),
1375 );
1376 let re_org =
1377 CanonStateNotification::Reorg { old: Arc::new(chain), new: Arc::new(new_chain) };
1378 in_memory_state.notify_canon_state(re_org.clone());
1379 let (notification_1, notification_2) = tokio::join!(rx_1.recv(), rx_2.recv());
1380 assert_eq!(notification_1, Ok(re_org.clone()));
1381 assert_eq!(notification_2, Ok(re_org.clone()));
1382
1383 Ok(())
1384 }
1385
1386 #[test]
1387 fn test_block_num_reader() -> eyre::Result<()> {
1388 let mut rng = generators::rng();
1389 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1390 &mut rng,
1391 TEST_BLOCKS_COUNT,
1392 TEST_BLOCKS_COUNT,
1393 BlockRangeParams::default(),
1394 )?;
1395
1396 assert_eq!(provider.best_block_number()?, in_memory_blocks.last().unwrap().number);
1397 assert_eq!(provider.last_block_number()?, database_blocks.last().unwrap().number);
1398
1399 let database_block = database_blocks.first().unwrap().clone();
1400 let in_memory_block = in_memory_blocks.first().unwrap().clone();
1401 assert_eq!(provider.block_number(database_block.hash())?, Some(database_block.number));
1402 assert_eq!(provider.block_number(in_memory_block.hash())?, Some(in_memory_block.number));
1403
1404 Ok(())
1405 }
1406
1407 #[test]
1408 fn test_block_reader_id_ext_block_by_id() -> eyre::Result<()> {
1409 let mut rng = generators::rng();
1410 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1411 &mut rng,
1412 TEST_BLOCKS_COUNT,
1413 TEST_BLOCKS_COUNT,
1414 BlockRangeParams::default(),
1415 )?;
1416
1417 let database_block = database_blocks.first().unwrap().clone();
1418 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1419
1420 let block_number = database_block.number;
1421 let block_hash = database_block.hash();
1422
1423 assert_eq!(
1424 provider.block_by_id(block_number.into()).unwrap(),
1425 Some(database_block.clone().into_block())
1426 );
1427 assert_eq!(
1428 provider.block_by_id(block_hash.into()).unwrap(),
1429 Some(database_block.into_block())
1430 );
1431
1432 let block_number = in_memory_block.number;
1433 let block_hash = in_memory_block.hash();
1434 assert_eq!(
1435 provider.block_by_id(block_number.into()).unwrap(),
1436 Some(in_memory_block.clone().into_block())
1437 );
1438 assert_eq!(
1439 provider.block_by_id(block_hash.into()).unwrap(),
1440 Some(in_memory_block.into_block())
1441 );
1442
1443 Ok(())
1444 }
1445
1446 #[test]
1447 fn test_block_reader_id_ext_header_by_number_or_tag() -> eyre::Result<()> {
1448 let mut rng = generators::rng();
1449 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1450 &mut rng,
1451 TEST_BLOCKS_COUNT,
1452 TEST_BLOCKS_COUNT,
1453 BlockRangeParams::default(),
1454 )?;
1455
1456 let database_block = database_blocks.first().unwrap().clone();
1457
1458 let in_memory_block_count = in_memory_blocks.len();
1459 let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
1460 let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
1461 let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();
1462
1463 let block_number = database_block.number;
1464 assert_eq!(
1465 provider.header_by_number_or_tag(block_number.into()).unwrap(),
1466 Some(database_block.header().clone())
1467 );
1468 assert_eq!(
1469 provider.sealed_header_by_number_or_tag(block_number.into())?,
1470 Some(database_block.clone_sealed_header())
1471 );
1472
1473 assert_eq!(
1474 provider.header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
1475 Some(canonical_block.header().clone())
1476 );
1477 assert_eq!(
1478 provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
1479 Some(canonical_block.clone_sealed_header())
1480 );
1481
1482 assert_eq!(
1483 provider.header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
1484 Some(safe_block.header().clone())
1485 );
1486 assert_eq!(
1487 provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
1488 Some(safe_block.clone_sealed_header())
1489 );
1490
1491 assert_eq!(
1492 provider.header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
1493 Some(finalized_block.header().clone())
1494 );
1495 assert_eq!(
1496 provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
1497 Some(finalized_block.clone_sealed_header())
1498 );
1499
1500 Ok(())
1501 }
1502
1503 #[test]
1504 fn test_block_reader_id_ext_header_by_id() -> eyre::Result<()> {
1505 let mut rng = generators::rng();
1506 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1507 &mut rng,
1508 TEST_BLOCKS_COUNT,
1509 TEST_BLOCKS_COUNT,
1510 BlockRangeParams::default(),
1511 )?;
1512
1513 let database_block = database_blocks.first().unwrap().clone();
1514 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1515
1516 let block_number = database_block.number;
1517 let block_hash = database_block.hash();
1518
1519 assert_eq!(
1520 provider.header_by_id(block_number.into()).unwrap(),
1521 Some(database_block.header().clone())
1522 );
1523 assert_eq!(
1524 provider.sealed_header_by_id(block_number.into()).unwrap(),
1525 Some(database_block.clone_sealed_header())
1526 );
1527
1528 assert_eq!(
1529 provider.header_by_id(block_hash.into()).unwrap(),
1530 Some(database_block.header().clone())
1531 );
1532 assert_eq!(
1533 provider.sealed_header_by_id(block_hash.into()).unwrap(),
1534 Some(database_block.clone_sealed_header())
1535 );
1536
1537 let block_number = in_memory_block.number;
1538 let block_hash = in_memory_block.hash();
1539
1540 assert_eq!(
1541 provider.header_by_id(block_number.into()).unwrap(),
1542 Some(in_memory_block.header().clone())
1543 );
1544 assert_eq!(
1545 provider.sealed_header_by_id(block_number.into()).unwrap(),
1546 Some(in_memory_block.clone_sealed_header())
1547 );
1548
1549 assert_eq!(
1550 provider.header_by_id(block_hash.into()).unwrap(),
1551 Some(in_memory_block.header().clone())
1552 );
1553 assert_eq!(
1554 provider.sealed_header_by_id(block_hash.into()).unwrap(),
1555 Some(in_memory_block.clone_sealed_header())
1556 );
1557
1558 Ok(())
1559 }
1560
1561 #[test]
1562 fn test_receipt_provider_id_ext_receipts_by_block_id() -> eyre::Result<()> {
1563 let mut rng = generators::rng();
1564 let (provider, database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
1565 &mut rng,
1566 TEST_BLOCKS_COUNT,
1567 TEST_BLOCKS_COUNT,
1568 BlockRangeParams { tx_count: 1..3, ..Default::default() },
1569 )?;
1570
1571 let database_block = database_blocks.first().unwrap().clone();
1572 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1573
1574 let block_number = database_block.number;
1575 let block_hash = database_block.hash();
1576
1577 assert!(!receipts.get(database_block.number as usize).unwrap().is_empty());
1578 assert!(!provider
1579 .receipts_by_number_or_tag(database_block.number.into())?
1580 .unwrap()
1581 .is_empty());
1582
1583 assert_eq!(
1584 provider.receipts_by_block_id(block_number.into())?.unwrap(),
1585 receipts.get(block_number as usize).unwrap().clone()
1586 );
1587 assert_eq!(
1588 provider.receipts_by_block_id(block_hash.into())?.unwrap(),
1589 receipts.get(block_number as usize).unwrap().clone()
1590 );
1591
1592 let block_number = in_memory_block.number;
1593 let block_hash = in_memory_block.hash();
1594
1595 assert_eq!(
1596 provider.receipts_by_block_id(block_number.into())?.unwrap(),
1597 receipts.get(block_number as usize).unwrap().clone()
1598 );
1599 assert_eq!(
1600 provider.receipts_by_block_id(block_hash.into())?.unwrap(),
1601 receipts.get(block_number as usize).unwrap().clone()
1602 );
1603
1604 Ok(())
1605 }
1606
1607 #[test]
1608 fn test_receipt_provider_id_ext_receipts_by_block_number_or_tag() -> eyre::Result<()> {
1609 let mut rng = generators::rng();
1610 let (provider, database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
1611 &mut rng,
1612 TEST_BLOCKS_COUNT,
1613 TEST_BLOCKS_COUNT,
1614 BlockRangeParams { tx_count: 1..3, ..Default::default() },
1615 )?;
1616
1617 let database_block = database_blocks.first().unwrap().clone();
1618
1619 let in_memory_block_count = in_memory_blocks.len();
1620 let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
1621 let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
1622 let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();
1623
1624 assert!(!receipts.get(database_block.number as usize).unwrap().is_empty());
1625 assert!(!provider
1626 .receipts_by_number_or_tag(database_block.number.into())?
1627 .unwrap()
1628 .is_empty());
1629
1630 assert_eq!(
1631 provider.receipts_by_number_or_tag(database_block.number.into())?.unwrap(),
1632 receipts.get(database_block.number as usize).unwrap().clone()
1633 );
1634 assert_eq!(
1635 provider.receipts_by_number_or_tag(BlockNumberOrTag::Latest)?.unwrap(),
1636 receipts.get(canonical_block.number as usize).unwrap().clone()
1637 );
1638 assert_eq!(
1639 provider.receipts_by_number_or_tag(BlockNumberOrTag::Safe)?.unwrap(),
1640 receipts.get(safe_block.number as usize).unwrap().clone()
1641 );
1642 assert_eq!(
1643 provider.receipts_by_number_or_tag(BlockNumberOrTag::Finalized)?.unwrap(),
1644 receipts.get(finalized_block.number as usize).unwrap().clone()
1645 );
1646
1647 Ok(())
1648 }
1649
1650 #[test]
1651 fn test_changeset_reader() -> eyre::Result<()> {
1652 let mut rng = generators::rng();
1653
1654 let (database_blocks, in_memory_blocks) =
1655 random_blocks(&mut rng, TEST_BLOCKS_COUNT, 1, None, None, 0..1);
1656
1657 let first_database_block = database_blocks.first().map(|block| block.number).unwrap();
1658 let last_database_block = database_blocks.last().map(|block| block.number).unwrap();
1659 let first_in_memory_block = in_memory_blocks.first().map(|block| block.number).unwrap();
1660
1661 let accounts = random_eoa_accounts(&mut rng, 2);
1662
1663 let (database_changesets, database_state) = random_changeset_range(
1664 &mut rng,
1665 &database_blocks,
1666 accounts.into_iter().map(|(address, account)| (address, (account, Vec::new()))),
1667 0..0,
1668 0..0,
1669 );
1670 let (in_memory_changesets, in_memory_state) = random_changeset_range(
1671 &mut rng,
1672 &in_memory_blocks,
1673 database_state
1674 .iter()
1675 .map(|(address, (account, storage))| (*address, (*account, storage.clone()))),
1676 0..0,
1677 0..0,
1678 );
1679
1680 let factory = create_test_provider_factory();
1681
1682 let provider_rw = factory.provider_rw()?;
1683 provider_rw.append_blocks_with_state(
1684 database_blocks
1685 .into_iter()
1686 .map(|b| b.try_recover().expect("failed to seal block with senders"))
1687 .collect(),
1688 &ExecutionOutcome {
1689 bundle: BundleState::new(
1690 database_state.into_iter().map(|(address, (account, _))| {
1691 (address, None, Some(account.into()), Default::default())
1692 }),
1693 database_changesets
1694 .iter()
1695 .map(|block_changesets| {
1696 block_changesets.iter().map(|(address, account, _)| {
1697 (*address, Some(Some((*account).into())), [])
1698 })
1699 })
1700 .collect::<Vec<_>>(),
1701 Vec::new(),
1702 ),
1703 first_block: first_database_block,
1704 ..Default::default()
1705 },
1706 Default::default(),
1707 )?;
1708 provider_rw.commit()?;
1709
1710 let provider = BlockchainProvider::new(factory)?;
1711
1712 let in_memory_changesets = in_memory_changesets.into_iter().next().unwrap();
1713 let chain = NewCanonicalChain::Commit {
1714 new: vec![in_memory_blocks
1715 .first()
1716 .map(|block| {
1717 let senders = block.senders().expect("failed to recover senders");
1718 ExecutedBlock {
1719 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1720 block.clone(),
1721 senders,
1722 )),
1723 execution_output: Arc::new(ExecutionOutcome {
1724 bundle: BundleState::new(
1725 in_memory_state.into_iter().map(|(address, (account, _))| {
1726 (address, None, Some(account.into()), Default::default())
1727 }),
1728 [in_memory_changesets.iter().map(|(address, account, _)| {
1729 (*address, Some(Some((*account).into())), Vec::new())
1730 })],
1731 [],
1732 ),
1733 first_block: first_in_memory_block,
1734 ..Default::default()
1735 }),
1736 ..Default::default()
1737 }
1738 })
1739 .unwrap()],
1740 };
1741 provider.canonical_in_memory_state.update_chain(chain);
1742
1743 assert_eq!(
1744 provider.account_block_changeset(last_database_block).unwrap(),
1745 database_changesets
1746 .into_iter()
1747 .next_back()
1748 .unwrap()
1749 .into_iter()
1750 .sorted_by_key(|(address, _, _)| *address)
1751 .map(|(address, account, _)| AccountBeforeTx { address, info: Some(account) })
1752 .collect::<Vec<_>>()
1753 );
1754 assert_eq!(
1755 provider.account_block_changeset(first_in_memory_block).unwrap(),
1756 in_memory_changesets
1757 .into_iter()
1758 .sorted_by_key(|(address, _, _)| *address)
1759 .map(|(address, account, _)| AccountBeforeTx { address, info: Some(account) })
1760 .collect::<Vec<_>>()
1761 );
1762
1763 Ok(())
1764 }
1765
1766 #[test]
1767 fn test_state_provider_factory() -> eyre::Result<()> {
1768 let mut rng = generators::rng();
1769
1770 let (in_memory_provider, _, in_memory_blocks, _) = provider_with_random_blocks(
1772 &mut rng,
1773 TEST_BLOCKS_COUNT,
1774 TEST_BLOCKS_COUNT,
1775 BlockRangeParams::default(),
1776 )?;
1777
1778 let (only_database_provider, database_blocks, _, _) = provider_with_random_blocks(
1780 &mut rng,
1781 TEST_BLOCKS_COUNT,
1782 0,
1783 BlockRangeParams::default(),
1784 )?;
1785
1786 let blocks = [database_blocks.clone(), in_memory_blocks.clone()].concat();
1787 let first_in_memory_block = in_memory_blocks.first().unwrap();
1788 let first_db_block = database_blocks.first().unwrap();
1789
1790 assert_eq!(
1792 first_in_memory_block.hash(),
1793 in_memory_provider.latest().unwrap().block_hash(first_in_memory_block.number)?.unwrap()
1794 );
1795 assert_eq!(
1797 first_db_block.hash(),
1798 only_database_provider.latest().unwrap().block_hash(first_db_block.number)?.unwrap()
1799 );
1800
1801 assert_eq!(
1803 first_in_memory_block.hash(),
1804 in_memory_provider
1805 .history_by_block_number(first_in_memory_block.number)?
1806 .block_hash(first_in_memory_block.number)?
1807 .unwrap()
1808 );
1809 assert_eq!(
1810 first_db_block.hash(),
1811 only_database_provider
1812 .history_by_block_number(first_db_block.number)?
1813 .block_hash(first_db_block.number)?
1814 .unwrap()
1815 );
1816 assert_eq!(
1817 first_in_memory_block.hash(),
1818 in_memory_provider
1819 .history_by_block_hash(first_in_memory_block.hash())?
1820 .block_hash(first_in_memory_block.number)?
1821 .unwrap()
1822 );
1823 assert!(only_database_provider.history_by_block_hash(B256::random()).is_err());
1824
1825 assert_eq!(
1827 first_in_memory_block.hash(),
1828 in_memory_provider
1829 .state_by_block_hash(first_in_memory_block.hash())?
1830 .block_hash(first_in_memory_block.number)?
1831 .unwrap()
1832 );
1833 assert_eq!(
1834 first_db_block.hash(),
1835 only_database_provider
1836 .state_by_block_hash(first_db_block.hash())?
1837 .block_hash(first_db_block.number)?
1838 .unwrap()
1839 );
1840 assert!(only_database_provider.state_by_block_hash(B256::random()).is_err());
1841
1842 assert_eq!(
1844 first_in_memory_block.hash(),
1845 in_memory_provider
1846 .pending()
1847 .unwrap()
1848 .block_hash(first_in_memory_block.number)
1849 .unwrap()
1850 .unwrap()
1851 );
1852
1853 let pending_block = database_blocks[database_blocks.len() - 1].clone();
1855 only_database_provider.canonical_in_memory_state.set_pending_block(ExecutedBlock {
1856 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1857 pending_block.clone(),
1858 Default::default(),
1859 )),
1860 ..Default::default()
1861 });
1862
1863 assert_eq!(
1864 pending_block.hash(),
1865 only_database_provider
1866 .pending()
1867 .unwrap()
1868 .block_hash(pending_block.number)
1869 .unwrap()
1870 .unwrap()
1871 );
1872
1873 assert_eq!(
1874 pending_block.hash(),
1875 only_database_provider
1876 .pending_state_by_hash(pending_block.hash())?
1877 .unwrap()
1878 .block_hash(pending_block.number)?
1879 .unwrap()
1880 );
1881
1882 assert_eq!(
1884 first_in_memory_block.hash(),
1885 in_memory_provider
1886 .state_by_block_number_or_tag(BlockNumberOrTag::Number(
1887 first_in_memory_block.number
1888 ))?
1889 .block_hash(first_in_memory_block.number)?
1890 .unwrap()
1891 );
1892 assert_eq!(
1893 first_in_memory_block.hash(),
1894 in_memory_provider
1895 .state_by_block_number_or_tag(BlockNumberOrTag::Latest)?
1896 .block_hash(first_in_memory_block.number)?
1897 .unwrap()
1898 );
1899 let safe_block = in_memory_blocks[in_memory_blocks.len() - 2].clone();
1901 in_memory_provider.canonical_in_memory_state.set_safe(safe_block.clone_sealed_header());
1902 assert_eq!(
1903 safe_block.hash(),
1904 in_memory_provider
1905 .state_by_block_number_or_tag(BlockNumberOrTag::Safe)?
1906 .block_hash(safe_block.number)?
1907 .unwrap()
1908 );
1909 let finalized_block = in_memory_blocks[in_memory_blocks.len() - 3].clone();
1911 in_memory_provider
1912 .canonical_in_memory_state
1913 .set_finalized(finalized_block.clone_sealed_header());
1914 assert_eq!(
1915 finalized_block.hash(),
1916 in_memory_provider
1917 .state_by_block_number_or_tag(BlockNumberOrTag::Finalized)?
1918 .block_hash(finalized_block.number)?
1919 .unwrap()
1920 );
1921 let earliest_block = blocks.first().unwrap().clone();
1923 assert_eq!(
1924 earliest_block.hash(),
1925 only_database_provider
1926 .state_by_block_number_or_tag(BlockNumberOrTag::Earliest)?
1927 .block_hash(earliest_block.number)?
1928 .unwrap()
1929 );
1930
1931 Ok(())
1932 }
1933
1934 #[test]
1935 fn test_block_id_reader() -> eyre::Result<()> {
1936 let mut rng = generators::rng();
1938 let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
1939 &mut rng,
1940 TEST_BLOCKS_COUNT,
1941 TEST_BLOCKS_COUNT,
1942 BlockRangeParams::default(),
1943 )?;
1944
1945 let pending_block = in_memory_blocks.last().unwrap();
1947 provider.canonical_in_memory_state.set_pending_block(ExecutedBlock {
1948 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1949 pending_block.clone(),
1950 Default::default(),
1951 )),
1952 ..Default::default()
1953 });
1954
1955 let safe_block = in_memory_blocks[in_memory_blocks.len() - 2].clone();
1957 provider.canonical_in_memory_state.set_safe(safe_block.clone_sealed_header());
1958
1959 let finalized_block = in_memory_blocks[in_memory_blocks.len() - 3].clone();
1961 provider.canonical_in_memory_state.set_finalized(finalized_block.clone_sealed_header());
1962
1963 assert_eq!(
1965 provider.pending_block_num_hash()?,
1966 Some(BlockNumHash { number: pending_block.number, hash: pending_block.hash() })
1967 );
1968
1969 assert_eq!(
1971 provider.safe_block_num_hash()?,
1972 Some(BlockNumHash { number: safe_block.number, hash: safe_block.hash() })
1973 );
1974
1975 assert_eq!(
1977 provider.finalized_block_num_hash()?,
1978 Some(BlockNumHash { number: finalized_block.number, hash: finalized_block.hash() })
1979 );
1980
1981 Ok(())
1982 }
1983
1984 macro_rules! test_by_tx_range {
1985 ([$(($method:ident, $data_extractor:expr)),* $(,)?]) => {{
1986
1987 let extra_blocks = [$(stringify!($method)),*].len();
1990
1991 let mut rng = generators::rng();
1992 let (provider, mut database_blocks, mut in_memory_blocks, receipts) = provider_with_random_blocks(
1993 &mut rng,
1994 TEST_BLOCKS_COUNT,
1995 TEST_BLOCKS_COUNT + extra_blocks,
1996 BlockRangeParams {
1997 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
1998 ..Default::default()
1999 },
2000 )?;
2001
2002 $(
2003 let db_tx_count =
2005 database_blocks.iter().map(|b| b.transaction_count()).sum::<usize>() as u64;
2006 let in_mem_tx_count =
2007 in_memory_blocks.iter().map(|b| b.transaction_count()).sum::<usize>() as u64;
2008
2009 let db_range = 0..=(db_tx_count - 1);
2010 let in_mem_range = db_tx_count..=(in_mem_tx_count + db_range.end());
2011
2012 let database_data =
2014 database_blocks.iter().flat_map(|b| $data_extractor(b, &receipts)).collect::<Vec<_>>();
2015 assert_eq!(provider.$method(db_range.clone())?, database_data, "full db data");
2016
2017 let in_memory_data =
2019 in_memory_blocks.iter().flat_map(|b| $data_extractor(b, &receipts)).collect::<Vec<_>>();
2020 assert_eq!(provider.$method(in_mem_range.clone())?, in_memory_data, "full mem data");
2021
2022 assert_eq!(
2024 &provider.$method(in_mem_range.start() + 1..=in_mem_range.end() - 1)?,
2025 &in_memory_data[1..in_memory_data.len() - 1],
2026 "partial mem data"
2027 );
2028
2029 assert_eq!(provider.$method(in_mem_range.start() + 1..)?, &in_memory_data[1..], "unbounded mem data");
2031
2032 assert_eq!(provider.$method(in_mem_range.end()..)?, &in_memory_data[in_memory_data.len() -1 ..], "last mem data");
2034
2035 assert_eq!(
2037 provider.$method(in_mem_range.start() - 2..)?,
2038 database_data[database_data.len() - 2..]
2039 .iter()
2040 .chain(&in_memory_data[..])
2041 .cloned()
2042 .collect::<Vec<_>>(),
2043 "unbounded span data"
2044 );
2045
2046 {
2048 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2050
2051 assert_eq!(
2052 provider.$method(in_mem_range.start() - 2..=in_mem_range.end() - 1)?,
2053 database_data[database_data.len() - 2..]
2054 .iter()
2055 .chain(&in_memory_data[..in_memory_data.len() - 1])
2056 .cloned()
2057 .collect::<Vec<_>>(),
2058 "span data"
2059 );
2060
2061 database_blocks.push(in_memory_blocks.remove(0));
2063 }
2064
2065 let start_tx_num = u64::MAX;
2067 let end_tx_num = u64::MAX;
2068 let result = provider.$method(start_tx_num..end_tx_num)?;
2069 assert!(result.is_empty(), "No data should be found for an invalid transaction range");
2070
2071 let result = provider.$method(in_mem_range.end()+10..in_mem_range.end()+20)?;
2073 assert!(result.is_empty(), "No data should be found for an empty transaction range");
2074 )*
2075 }};
2076 }
2077
2078 #[test]
2079 fn test_methods_by_tx_range() -> eyre::Result<()> {
2080 test_by_tx_range!([
2081 (senders_by_tx_range, |block: &SealedBlock<Block>, _: &Vec<Vec<Receipt>>| block
2082 .senders()
2083 .unwrap()),
2084 (transactions_by_tx_range, |block: &SealedBlock<Block>, _: &Vec<Vec<Receipt>>| block
2085 .body()
2086 .transactions
2087 .clone()),
2088 (receipts_by_tx_range, |block: &SealedBlock<Block>, receipts: &Vec<Vec<Receipt>>| {
2089 receipts[block.number as usize].clone()
2090 })
2091 ]);
2092
2093 Ok(())
2094 }
2095
2096 macro_rules! test_by_block_range {
2097 ([$(($method:ident, $data_extractor:expr)),* $(,)?]) => {{
2098 let extra_blocks = [$(stringify!($method)),*].len();
2101
2102 let mut rng = generators::rng();
2103 let (provider, mut database_blocks, mut in_memory_blocks, _) = provider_with_random_blocks(
2104 &mut rng,
2105 TEST_BLOCKS_COUNT,
2106 TEST_BLOCKS_COUNT + extra_blocks,
2107 BlockRangeParams {
2108 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2109 ..Default::default()
2110 },
2111 )?;
2112
2113 $(
2114 let db_block_count = database_blocks.len() as u64;
2116 let in_mem_block_count = in_memory_blocks.len() as u64;
2117
2118 let db_range = 0..=db_block_count - 1;
2119 let in_mem_range = db_block_count..=(in_mem_block_count + db_range.end());
2120
2121 let database_data =
2123 database_blocks.iter().map(|b| $data_extractor(b)).collect::<Vec<_>>();
2124 assert_eq!(provider.$method(db_range.clone())?, database_data);
2125
2126 let in_memory_data =
2128 in_memory_blocks.iter().map(|b| $data_extractor(b)).collect::<Vec<_>>();
2129 assert_eq!(provider.$method(in_mem_range.clone())?, in_memory_data);
2130
2131 assert_eq!(
2133 &provider.$method(in_mem_range.start() + 1..=in_mem_range.end() - 1)?,
2134 &in_memory_data[1..in_memory_data.len() - 1]
2135 );
2136
2137 {
2139
2140 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2142
2143 assert_eq!(
2144 provider.$method(in_mem_range.start() - 2..=in_mem_range.end() - 1)?,
2145 database_data[database_data.len() - 2..]
2146 .iter()
2147 .chain(&in_memory_data[..in_memory_data.len() - 1])
2148 .cloned()
2149 .collect::<Vec<_>>()
2150 );
2151
2152 database_blocks.push(in_memory_blocks.remove(0));
2154 }
2155
2156 let start_block_num = u64::MAX;
2158 let end_block_num = u64::MAX;
2159 let result = provider.$method(start_block_num..=end_block_num-1)?;
2160 assert!(result.is_empty(), "No data should be found for an invalid block range");
2161
2162 let result = provider.$method(in_mem_range.end() + 10..=in_mem_range.end() + 20)?;
2164 assert!(result.is_empty(), "No data should be found for an empty block range");
2165 )*
2166 }};
2167 }
2168
2169 #[test]
2170 fn test_methods_by_block_range() -> eyre::Result<()> {
2171 test_by_block_range!([
2174 (headers_range, |block: &SealedBlock<Block>| block.header().clone()),
2175 (sealed_headers_range, |block: &SealedBlock<Block>| block.clone_sealed_header()),
2176 (block_range, |block: &SealedBlock<Block>| block.clone().into_block()),
2177 (block_with_senders_range, |block: &SealedBlock<Block>| block
2178 .clone()
2179 .try_recover()
2180 .unwrap()),
2181 (recovered_block_range, |block: &SealedBlock<Block>| block
2182 .clone()
2183 .try_recover()
2184 .unwrap()),
2185 (transactions_by_block_range, |block: &SealedBlock<Block>| block
2186 .body()
2187 .transactions
2188 .clone()),
2189 ]);
2190
2191 Ok(())
2192 }
2193
2194 macro_rules! call_method {
2196 ($provider:expr, $method:ident, ($($args:expr),*), $expected_item:expr) => {{
2197 let result = $provider.$method($($args),*)?;
2198 assert_eq!(
2199 result,
2200 $expected_item,
2201 "{}: item does not match the expected item for arguments {:?}",
2202 stringify!($method),
2203 ($($args),*)
2204 );
2205 }};
2206
2207 (ONE, $provider:expr, $method:ident, $item_extractor:expr, $txnum:expr, $txhash:expr, $block:expr, $receipts:expr) => {{
2209 let (arg, expected_item) = $item_extractor($block, $txnum($block), $txhash($block), $receipts);
2210 call_method!($provider, $method, (arg), expected_item);
2211 }};
2212
2213 (TWO, $provider:expr, $method:ident, $item_extractor:expr, $txnum:expr, $txhash:expr, $block:expr, $receipts:expr) => {{
2215 let ((arg1, arg2), expected_item) = $item_extractor($block, $txnum($block), $txhash($block), $receipts);
2216 call_method!($provider, $method, (arg1, arg2), expected_item);
2217 }};
2218 }
2219
2220 macro_rules! test_non_range {
2225 ([$(($arg_count:ident, $method:ident, $item_extractor:expr, $invalid_args:expr)),* $(,)?]) => {{
2226
2227 let extra_blocks = [$(stringify!($arg_count)),*].len();
2230
2231 let mut rng = generators::rng();
2232 let (provider, mut database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
2233 &mut rng,
2234 TEST_BLOCKS_COUNT,
2235 TEST_BLOCKS_COUNT + extra_blocks,
2236 BlockRangeParams {
2237 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2238 ..Default::default()
2239 },
2240 )?;
2241
2242 let mut in_memory_blocks: std::collections::VecDeque<_> = in_memory_blocks.into();
2243
2244 $(
2245 let tx_hash = |block: &SealedBlock<Block>| *block.body().transactions[0].tx_hash();
2246 let tx_num = |block: &SealedBlock<Block>| {
2247 database_blocks
2248 .iter()
2249 .chain(in_memory_blocks.iter())
2250 .take_while(|b| b.number < block.number)
2251 .map(|b| b.transaction_count())
2252 .sum::<usize>() as u64
2253 };
2254
2255 {
2257 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2259
2260 call_method!($arg_count, provider, $method, $item_extractor, tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2261
2262 database_blocks.push(in_memory_blocks.pop_front().unwrap());
2264 }
2265
2266 let tx_num = |block: &SealedBlock<Block>| {
2268 database_blocks
2269 .iter()
2270 .chain(in_memory_blocks.iter())
2271 .take_while(|b| b.number < block.number)
2272 .map(|b| b.transaction_count())
2273 .sum::<usize>() as u64
2274 };
2275
2276 {
2278 call_method!($arg_count, provider, $method, |_,_,_,_| ($invalid_args, None), tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2279 }
2280
2281 {
2283 let last_mem_block = &in_memory_blocks[in_memory_blocks.len() - 1];
2284
2285 let (args, expected_item) = $item_extractor(last_mem_block, tx_num(last_mem_block), tx_hash(last_mem_block), &receipts);
2286 call_method!($arg_count, provider, $method, |_,_,_,_| (args.clone(), expected_item), tx_num, tx_hash, last_mem_block, &receipts);
2287
2288 call_method!($arg_count, provider.database, $method, |_,_,_,_| (args, None), tx_num, tx_hash, last_mem_block, &receipts);
2290 }
2291 )*
2292 }};
2293}
2294
2295 #[test]
2296 fn test_non_range_methods() -> eyre::Result<()> {
2297 let test_tx_index = 0;
2298
2299 test_non_range!([
2300 (
2301 ONE,
2302 header,
2303 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2304 block.hash(),
2305 Some(block.header().clone())
2306 ),
2307 B256::random()
2308 ),
2309 (
2310 ONE,
2311 header_by_number,
2312 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2313 block.number,
2314 Some(block.header().clone())
2315 ),
2316 u64::MAX
2317 ),
2318 (
2319 ONE,
2320 sealed_header,
2321 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2322 block.number,
2323 Some(block.clone_sealed_header())
2324 ),
2325 u64::MAX
2326 ),
2327 (
2328 ONE,
2329 block_hash,
2330 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2331 block.number,
2332 Some(block.hash())
2333 ),
2334 u64::MAX
2335 ),
2336 (
2337 ONE,
2338 block_number,
2339 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2340 block.hash(),
2341 Some(block.number)
2342 ),
2343 B256::random()
2344 ),
2345 (
2346 ONE,
2347 block,
2348 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2349 BlockHashOrNumber::Hash(block.hash()),
2350 Some(block.clone().into_block())
2351 ),
2352 BlockHashOrNumber::Hash(B256::random())
2353 ),
2354 (
2355 ONE,
2356 block,
2357 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2358 BlockHashOrNumber::Number(block.number),
2359 Some(block.clone().into_block())
2360 ),
2361 BlockHashOrNumber::Number(u64::MAX)
2362 ),
2363 (
2364 ONE,
2365 block_body_indices,
2366 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2367 block.number,
2368 Some(StoredBlockBodyIndices {
2369 first_tx_num: tx_num,
2370 tx_count: block.transaction_count() as u64
2371 })
2372 ),
2373 u64::MAX
2374 ),
2375 (
2376 TWO,
2377 recovered_block,
2378 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2379 (BlockHashOrNumber::Number(block.number), TransactionVariant::WithHash),
2380 block.clone().try_recover().ok()
2381 ),
2382 (BlockHashOrNumber::Number(u64::MAX), TransactionVariant::WithHash)
2383 ),
2384 (
2385 TWO,
2386 recovered_block,
2387 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2388 (BlockHashOrNumber::Hash(block.hash()), TransactionVariant::WithHash),
2389 block.clone().try_recover().ok()
2390 ),
2391 (BlockHashOrNumber::Hash(B256::random()), TransactionVariant::WithHash)
2392 ),
2393 (
2394 TWO,
2395 sealed_block_with_senders,
2396 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2397 (BlockHashOrNumber::Number(block.number), TransactionVariant::WithHash),
2398 block.clone().try_recover().ok()
2399 ),
2400 (BlockHashOrNumber::Number(u64::MAX), TransactionVariant::WithHash)
2401 ),
2402 (
2403 TWO,
2404 sealed_block_with_senders,
2405 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2406 (BlockHashOrNumber::Hash(block.hash()), TransactionVariant::WithHash),
2407 block.clone().try_recover().ok()
2408 ),
2409 (BlockHashOrNumber::Hash(B256::random()), TransactionVariant::WithHash)
2410 ),
2411 (
2412 ONE,
2413 transaction_id,
2414 |_: &SealedBlock<Block>, tx_num: TxNumber, tx_hash: B256, _: &Vec<Vec<Receipt>>| (
2415 tx_hash,
2416 Some(tx_num)
2417 ),
2418 B256::random()
2419 ),
2420 (
2421 ONE,
2422 transaction_by_id,
2423 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2424 tx_num,
2425 Some(block.body().transactions[test_tx_index].clone())
2426 ),
2427 u64::MAX
2428 ),
2429 (
2430 ONE,
2431 transaction_by_id_unhashed,
2432 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2433 tx_num,
2434 Some(block.body().transactions[test_tx_index].clone())
2435 ),
2436 u64::MAX
2437 ),
2438 (
2439 ONE,
2440 transaction_by_hash,
2441 |block: &SealedBlock<Block>, _: TxNumber, tx_hash: B256, _: &Vec<Vec<Receipt>>| (
2442 tx_hash,
2443 Some(block.body().transactions[test_tx_index].clone())
2444 ),
2445 B256::random()
2446 ),
2447 (
2448 ONE,
2449 block_by_transaction_id,
2450 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2451 tx_num,
2452 Some(block.number)
2453 ),
2454 u64::MAX
2455 ),
2456 (
2457 ONE,
2458 transactions_by_block,
2459 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2460 BlockHashOrNumber::Number(block.number),
2461 Some(block.body().transactions.clone())
2462 ),
2463 BlockHashOrNumber::Number(u64::MAX)
2464 ),
2465 (
2466 ONE,
2467 transactions_by_block,
2468 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2469 BlockHashOrNumber::Hash(block.hash()),
2470 Some(block.body().transactions.clone())
2471 ),
2472 BlockHashOrNumber::Number(u64::MAX)
2473 ),
2474 (
2475 ONE,
2476 transaction_sender,
2477 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2478 tx_num,
2479 block.body().transactions[test_tx_index].recover_signer().ok()
2480 ),
2481 u64::MAX
2482 ),
2483 (
2484 ONE,
2485 receipt,
2486 |block: &SealedBlock<Block>,
2487 tx_num: TxNumber,
2488 _: B256,
2489 receipts: &Vec<Vec<Receipt>>| (
2490 tx_num,
2491 Some(receipts[block.number as usize][test_tx_index].clone())
2492 ),
2493 u64::MAX
2494 ),
2495 (
2496 ONE,
2497 receipt_by_hash,
2498 |block: &SealedBlock<Block>,
2499 _: TxNumber,
2500 tx_hash: B256,
2501 receipts: &Vec<Vec<Receipt>>| (
2502 tx_hash,
2503 Some(receipts[block.number as usize][test_tx_index].clone())
2504 ),
2505 B256::random()
2506 ),
2507 (
2508 ONE,
2509 receipts_by_block,
2510 |block: &SealedBlock<Block>, _: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2511 BlockHashOrNumber::Number(block.number),
2512 Some(receipts[block.number as usize].clone())
2513 ),
2514 BlockHashOrNumber::Number(u64::MAX)
2515 ),
2516 (
2517 ONE,
2518 receipts_by_block,
2519 |block: &SealedBlock<Block>, _: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2520 BlockHashOrNumber::Hash(block.hash()),
2521 Some(receipts[block.number as usize].clone())
2522 ),
2523 BlockHashOrNumber::Hash(B256::random())
2524 ),
2525 ]);
2527
2528 Ok(())
2529 }
2530
2531 #[test]
2532 fn test_race() -> eyre::Result<()> {
2533 let mut rng = generators::rng();
2534 let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
2535 &mut rng,
2536 TEST_BLOCKS_COUNT - 1,
2537 TEST_BLOCKS_COUNT + 1,
2538 BlockRangeParams {
2539 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2540 ..Default::default()
2541 },
2542 )?;
2543
2544 let old_transaction_hash_fn =
2547 |hash: B256,
2548 canonical_in_memory_state: CanonicalInMemoryState,
2549 factory: ProviderFactory<MockNodeTypesWithDB>| {
2550 assert!(factory.transaction_by_hash(hash)?.is_none(), "should not be in database");
2551 Ok::<_, ProviderError>(canonical_in_memory_state.transaction_by_hash(hash))
2552 };
2553
2554 let correct_transaction_hash_fn =
2556 |hash: B256,
2557 canonical_in_memory_state: CanonicalInMemoryState,
2558 _factory: ProviderFactory<MockNodeTypesWithDB>| {
2559 if let Some(tx) = canonical_in_memory_state.transaction_by_hash(hash) {
2560 return Ok::<_, ProviderError>(Some(tx));
2561 }
2562 panic!("should not be in database");
2563 };
2565
2566 {
2568 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2571 let to_be_persisted_tx = in_memory_blocks[0].body().transactions[0].clone();
2572
2573 assert!(matches!(
2576 old_transaction_hash_fn(
2577 *to_be_persisted_tx.tx_hash(),
2578 provider.canonical_in_memory_state(),
2579 provider.database.clone()
2580 ),
2581 Ok(None)
2582 ));
2583 }
2584
2585 {
2587 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[1].number);
2590 let to_be_persisted_tx = in_memory_blocks[1].body().transactions[0].clone();
2591
2592 assert_eq!(
2593 correct_transaction_hash_fn(
2594 *to_be_persisted_tx.tx_hash(),
2595 provider.canonical_in_memory_state(),
2596 provider.database
2597 )
2598 .unwrap(),
2599 Some(to_be_persisted_tx)
2600 );
2601 }
2602
2603 Ok(())
2604 }
2605}