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