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