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