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::{BlockBody, RecoveredBlock, SealedBlock, SignedTransaction};
796 use reth_static_file_types::StaticFileSegment;
797 use reth_storage_api::{
798 BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader,
799 BlockReaderIdExt, BlockSource, ChangeSetReader, DatabaseProviderFactory, HeaderProvider,
800 OmmersProvider, ReceiptProvider, ReceiptProviderIdExt, StateProviderFactory,
801 TransactionVariant, TransactionsProvider, WithdrawalsProvider,
802 };
803 use reth_testing_utils::generators::{
804 self, random_block, random_block_range, random_changeset_range, random_eoa_accounts,
805 random_receipt, BlockParams, BlockRangeParams,
806 };
807 use revm_database::BundleState;
808 use std::{
809 ops::{Bound, Deref, Range, RangeBounds},
810 sync::Arc,
811 time::Instant,
812 };
813
814 const TEST_BLOCKS_COUNT: usize = 5;
815
816 const TEST_TRANSACTIONS_COUNT: u8 = 4;
817
818 fn random_blocks(
819 rng: &mut impl Rng,
820 database_blocks: usize,
821 in_memory_blocks: usize,
822 requests_count: Option<Range<u8>>,
823 withdrawals_count: Option<Range<u8>>,
824 tx_count: impl RangeBounds<u8>,
825 ) -> (Vec<SealedBlock<Block>>, Vec<SealedBlock<Block>>) {
826 let block_range = (database_blocks + in_memory_blocks - 1) as u64;
827
828 let tx_start = match tx_count.start_bound() {
829 Bound::Included(&n) | Bound::Excluded(&n) => n,
830 Bound::Unbounded => u8::MIN,
831 };
832 let tx_end = match tx_count.end_bound() {
833 Bound::Included(&n) | Bound::Excluded(&n) => n + 1,
834 Bound::Unbounded => u8::MAX,
835 };
836
837 let blocks = random_block_range(
838 rng,
839 0..=block_range,
840 BlockRangeParams {
841 parent: Some(B256::ZERO),
842 tx_count: tx_start..tx_end,
843 requests_count,
844 withdrawals_count,
845 },
846 );
847 let (database_blocks, in_memory_blocks) = blocks.split_at(database_blocks);
848 (database_blocks.to_vec(), in_memory_blocks.to_vec())
849 }
850
851 #[expect(clippy::type_complexity)]
852 fn provider_with_chain_spec_and_random_blocks(
853 rng: &mut impl Rng,
854 chain_spec: Arc<ChainSpec>,
855 database_blocks: usize,
856 in_memory_blocks: usize,
857 block_range_params: BlockRangeParams,
858 ) -> eyre::Result<(
859 BlockchainProvider<MockNodeTypesWithDB>,
860 Vec<SealedBlock<Block>>,
861 Vec<SealedBlock<Block>>,
862 Vec<Vec<Receipt>>,
863 )> {
864 let (database_blocks, in_memory_blocks) = random_blocks(
865 rng,
866 database_blocks,
867 in_memory_blocks,
868 block_range_params.requests_count,
869 block_range_params.withdrawals_count,
870 block_range_params.tx_count,
871 );
872
873 let receipts: Vec<Vec<_>> = database_blocks
874 .iter()
875 .chain(in_memory_blocks.iter())
876 .map(|block| block.body().transactions.iter())
877 .map(|tx| tx.map(|tx| random_receipt(rng, tx, Some(2))).collect())
878 .collect();
879
880 let factory = create_test_provider_factory_with_chain_spec(chain_spec);
881 let provider_rw = factory.database_provider_rw()?;
882 let static_file_provider = factory.static_file_provider();
883
884 let mut tx_num = provider_rw
886 .block_body_indices(database_blocks.first().as_ref().unwrap().number.saturating_sub(1))?
887 .map(|indices| indices.next_tx_num())
888 .unwrap_or_default();
889
890 for (block, receipts) in database_blocks.iter().zip(&receipts) {
892 let mut transactions_writer =
894 static_file_provider.latest_writer(StaticFileSegment::Transactions)?;
895 let mut receipts_writer =
896 static_file_provider.latest_writer(StaticFileSegment::Receipts)?;
897 transactions_writer.increment_block(block.number)?;
898 receipts_writer.increment_block(block.number)?;
899
900 for (tx, receipt) in block.body().transactions().zip(receipts) {
901 transactions_writer.append_transaction(tx_num, tx)?;
902 receipts_writer.append_receipt(tx_num, receipt)?;
903 tx_num += 1;
904 }
905
906 provider_rw.insert_historical_block(
907 block.clone().try_recover().expect("failed to seal block with senders"),
908 )?;
909 }
910
911 UnifiedStorageWriter::commit(provider_rw)?;
913
914 let provider = BlockchainProvider::new(factory)?;
915
916 let chain = NewCanonicalChain::Commit {
918 new: in_memory_blocks
919 .iter()
920 .map(|block| {
921 let senders = block.senders().expect("failed to recover senders");
922 let block_receipts = receipts.get(block.number as usize).unwrap().clone();
923 let execution_outcome =
924 ExecutionOutcome { receipts: vec![block_receipts], ..Default::default() };
925
926 ExecutedBlockWithTrieUpdates::new(
927 Arc::new(RecoveredBlock::new_sealed(block.clone(), senders)),
928 execution_outcome.into(),
929 Default::default(),
930 Default::default(),
931 )
932 })
933 .collect(),
934 };
935 provider.canonical_in_memory_state.update_chain(chain);
936
937 let blocks = database_blocks.iter().chain(in_memory_blocks.iter()).collect::<Vec<_>>();
939 let block_count = blocks.len();
940 let canonical_block = blocks.get(block_count - 1).unwrap();
941 let safe_block = blocks.get(block_count - 2).unwrap();
942 let finalized_block = blocks.get(block_count - 3).unwrap();
943
944 provider.set_canonical_head(canonical_block.clone_sealed_header());
946 provider.set_safe(safe_block.clone_sealed_header());
947 provider.set_finalized(finalized_block.clone_sealed_header());
948
949 Ok((provider, database_blocks.clone(), in_memory_blocks.clone(), receipts))
950 }
951
952 #[expect(clippy::type_complexity)]
953 fn provider_with_random_blocks(
954 rng: &mut impl Rng,
955 database_blocks: usize,
956 in_memory_blocks: usize,
957 block_range_params: BlockRangeParams,
958 ) -> eyre::Result<(
959 BlockchainProvider<MockNodeTypesWithDB>,
960 Vec<SealedBlock<Block>>,
961 Vec<SealedBlock<Block>>,
962 Vec<Vec<Receipt>>,
963 )> {
964 provider_with_chain_spec_and_random_blocks(
965 rng,
966 MAINNET.clone(),
967 database_blocks,
968 in_memory_blocks,
969 block_range_params,
970 )
971 }
972
973 fn persist_block_after_db_tx_creation(
979 provider: BlockchainProvider<MockNodeTypesWithDB>,
980 block_number: BlockNumber,
981 ) {
982 let hook_provider = provider.clone();
983 provider.database.db_ref().set_post_transaction_hook(Box::new(move || {
984 if let Some(state) = hook_provider.canonical_in_memory_state.head_state() {
985 if state.anchor().number + 1 == block_number {
986 let mut lowest_memory_block =
987 state.parent_state_chain().last().expect("qed").block();
988 let num_hash = lowest_memory_block.recovered_block().num_hash();
989
990 let mut execution_output = (*lowest_memory_block.execution_output).clone();
991 execution_output.first_block = lowest_memory_block.recovered_block().number;
992 lowest_memory_block.execution_output = Arc::new(execution_output);
993
994 let provider_rw = hook_provider.database_provider_rw().unwrap();
996 UnifiedStorageWriter::from(&provider_rw, &hook_provider.static_file_provider())
997 .save_blocks(vec![lowest_memory_block])
998 .unwrap();
999 UnifiedStorageWriter::commit(provider_rw).unwrap();
1000
1001 hook_provider.canonical_in_memory_state.remove_persisted_blocks(num_hash);
1003 }
1004 }
1005 }));
1006 }
1007
1008 #[test]
1009 fn test_block_reader_find_block_by_hash() -> eyre::Result<()> {
1010 let mut rng = generators::rng();
1012 let factory = create_test_provider_factory();
1013
1014 let blocks = random_block_range(
1016 &mut rng,
1017 0..=10,
1018 BlockRangeParams { parent: Some(B256::ZERO), tx_count: 0..1, ..Default::default() },
1019 );
1020 let (database_blocks, in_memory_blocks) = blocks.split_at(5);
1021
1022 let provider_rw = factory.provider_rw()?;
1024 for block in database_blocks {
1025 provider_rw.insert_historical_block(
1026 block.clone().try_recover().expect("failed to seal block with senders"),
1027 )?;
1028 }
1029 provider_rw.commit()?;
1030
1031 let provider = BlockchainProvider::new(factory)?;
1033
1034 let first_db_block = database_blocks.first().unwrap();
1036 let first_in_mem_block = in_memory_blocks.first().unwrap();
1037 let last_in_mem_block = in_memory_blocks.last().unwrap();
1038
1039 assert_eq!(provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Any)?, None);
1041 assert_eq!(
1042 provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Canonical)?,
1043 None
1044 );
1045 assert_eq!(
1047 provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Pending)?,
1048 None
1049 );
1050
1051 let in_memory_block_senders =
1053 first_in_mem_block.senders().expect("failed to recover senders");
1054 let chain = NewCanonicalChain::Commit {
1055 new: vec![ExecutedBlockWithTrieUpdates::new(
1056 Arc::new(RecoveredBlock::new_sealed(
1057 first_in_mem_block.clone(),
1058 in_memory_block_senders,
1059 )),
1060 Default::default(),
1061 Default::default(),
1062 Default::default(),
1063 )],
1064 };
1065 provider.canonical_in_memory_state.update_chain(chain);
1066
1067 assert_eq!(
1069 provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Any)?,
1070 Some(first_in_mem_block.clone().into_block())
1071 );
1072 assert_eq!(
1073 provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Canonical)?,
1074 Some(first_in_mem_block.clone().into_block())
1075 );
1076
1077 assert_eq!(
1079 provider.find_block_by_hash(first_db_block.hash(), BlockSource::Any)?,
1080 Some(first_db_block.clone().into_block())
1081 );
1082 assert_eq!(
1083 provider.find_block_by_hash(first_db_block.hash(), BlockSource::Canonical)?,
1084 Some(first_db_block.clone().into_block())
1085 );
1086
1087 assert_eq!(provider.find_block_by_hash(first_db_block.hash(), BlockSource::Pending)?, None);
1089
1090 provider.canonical_in_memory_state.set_pending_block(ExecutedBlockWithTrieUpdates {
1092 block: ExecutedBlock {
1093 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1094 last_in_mem_block.clone(),
1095 Default::default(),
1096 )),
1097 execution_output: Default::default(),
1098 hashed_state: Default::default(),
1099 },
1100 trie: Default::default(),
1101 });
1102
1103 assert_eq!(
1105 provider.find_block_by_hash(last_in_mem_block.hash(), BlockSource::Pending)?,
1106 Some(last_in_mem_block.clone().into_block())
1107 );
1108
1109 Ok(())
1110 }
1111
1112 #[test]
1113 fn test_block_reader_block() -> eyre::Result<()> {
1114 let mut rng = generators::rng();
1116 let factory = create_test_provider_factory();
1117
1118 let blocks = random_block_range(
1120 &mut rng,
1121 0..=10,
1122 BlockRangeParams { parent: Some(B256::ZERO), tx_count: 0..1, ..Default::default() },
1123 );
1124 let (database_blocks, in_memory_blocks) = blocks.split_at(5);
1125
1126 let provider_rw = factory.provider_rw()?;
1128 for block in database_blocks {
1129 provider_rw.insert_historical_block(
1130 block.clone().try_recover().expect("failed to seal block with senders"),
1131 )?;
1132 }
1133 provider_rw.commit()?;
1134
1135 let provider = BlockchainProvider::new(factory)?;
1137
1138 let first_in_mem_block = in_memory_blocks.first().unwrap();
1140 let first_db_block = database_blocks.first().unwrap();
1142
1143 assert_eq!(provider.block(BlockHashOrNumber::Hash(first_in_mem_block.hash()))?, None);
1145 assert_eq!(provider.block(BlockHashOrNumber::Number(first_in_mem_block.number))?, None);
1146
1147 let in_memory_block_senders =
1149 first_in_mem_block.senders().expect("failed to recover senders");
1150 let chain = NewCanonicalChain::Commit {
1151 new: vec![ExecutedBlockWithTrieUpdates::new(
1152 Arc::new(RecoveredBlock::new_sealed(
1153 first_in_mem_block.clone(),
1154 in_memory_block_senders,
1155 )),
1156 Default::default(),
1157 Default::default(),
1158 Default::default(),
1159 )],
1160 };
1161 provider.canonical_in_memory_state.update_chain(chain);
1162
1163 assert_eq!(
1165 provider.block(BlockHashOrNumber::Hash(first_in_mem_block.hash()))?,
1166 Some(first_in_mem_block.clone().into_block())
1167 );
1168 assert_eq!(
1169 provider.block(BlockHashOrNumber::Number(first_in_mem_block.number))?,
1170 Some(first_in_mem_block.clone().into_block())
1171 );
1172
1173 assert_eq!(
1175 provider.block(BlockHashOrNumber::Hash(first_db_block.hash()))?,
1176 Some(first_db_block.clone().into_block())
1177 );
1178 assert_eq!(
1179 provider.block(BlockHashOrNumber::Number(first_db_block.number))?,
1180 Some(first_db_block.clone().into_block())
1181 );
1182
1183 Ok(())
1184 }
1185
1186 #[test]
1187 fn test_block_reader_pending_block() -> eyre::Result<()> {
1188 let mut rng = generators::rng();
1189 let (provider, _, _, _) = provider_with_random_blocks(
1190 &mut rng,
1191 TEST_BLOCKS_COUNT,
1192 TEST_BLOCKS_COUNT,
1193 BlockRangeParams::default(),
1194 )?;
1195
1196 let mut rng = generators::rng();
1198 let block = random_block(
1199 &mut rng,
1200 0,
1201 BlockParams { parent: Some(B256::ZERO), ..Default::default() },
1202 );
1203
1204 provider.canonical_in_memory_state.set_pending_block(ExecutedBlockWithTrieUpdates {
1206 block: ExecutedBlock {
1207 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1208 block.clone(),
1209 block.senders().unwrap(),
1210 )),
1211 execution_output: Default::default(),
1212 hashed_state: Default::default(),
1213 },
1214 trie: Default::default(),
1215 });
1216
1217 assert_eq!(provider.pending_block()?, Some(block.clone()));
1219
1220 assert_eq!(
1221 provider.pending_block_with_senders()?,
1222 Some(RecoveredBlock::new_sealed(block.clone(), block.senders().unwrap()))
1223 );
1224
1225 assert_eq!(provider.pending_block_and_receipts()?, Some((block, vec![])));
1226
1227 Ok(())
1228 }
1229
1230 #[test]
1231 fn test_block_reader_ommers() -> eyre::Result<()> {
1232 let mut rng = generators::rng();
1234 let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
1235 &mut rng,
1236 TEST_BLOCKS_COUNT,
1237 TEST_BLOCKS_COUNT,
1238 BlockRangeParams::default(),
1239 )?;
1240
1241 let first_in_mem_block = in_memory_blocks.first().unwrap();
1242
1243 assert_eq!(
1245 provider.ommers(
1246 (provider.chain_spec().paris_block_and_final_difficulty.unwrap().0 + 2).into()
1247 )?,
1248 Some(vec![])
1249 );
1250
1251 assert_eq!(
1253 provider.ommers(first_in_mem_block.number.into())?,
1254 Some(first_in_mem_block.body().ommers.clone())
1255 );
1256 assert_eq!(
1257 provider.ommers(first_in_mem_block.hash().into())?,
1258 Some(first_in_mem_block.body().ommers.clone())
1259 );
1260
1261 assert_eq!(provider.ommers(B256::random().into())?, None);
1263
1264 Ok(())
1265 }
1266
1267 #[test]
1268 fn test_block_body_indices() -> eyre::Result<()> {
1269 let mut rng = generators::rng();
1271 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1272 &mut rng,
1273 TEST_BLOCKS_COUNT,
1274 TEST_BLOCKS_COUNT,
1275 BlockRangeParams {
1276 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
1277 ..Default::default()
1278 },
1279 )?;
1280
1281 let first_in_mem_block = in_memory_blocks.first().unwrap();
1282
1283 let in_memory_block_senders =
1285 first_in_mem_block.senders().expect("failed to recover senders");
1286 let chain = NewCanonicalChain::Commit {
1287 new: vec![ExecutedBlockWithTrieUpdates::new(
1288 Arc::new(RecoveredBlock::new_sealed(
1289 first_in_mem_block.clone(),
1290 in_memory_block_senders,
1291 )),
1292 Default::default(),
1293 Default::default(),
1294 Default::default(),
1295 )],
1296 };
1297 provider.canonical_in_memory_state.update_chain(chain);
1298
1299 let first_db_block = database_blocks.first().unwrap().clone();
1300 let first_in_mem_block = in_memory_blocks.first().unwrap().clone();
1301
1302 assert_eq!(
1304 provider.block_body_indices(first_db_block.number)?.unwrap(),
1305 StoredBlockBodyIndices { first_tx_num: 0, tx_count: 4 }
1306 );
1307
1308 assert_eq!(
1311 provider.block_body_indices(first_in_mem_block.number)?.unwrap(),
1312 StoredBlockBodyIndices { first_tx_num: 20, tx_count: 4 }
1313 );
1314
1315 let mut rng = rand::rng();
1317 let random_block_number: u64 = rng.random();
1318 assert_eq!(provider.block_body_indices(random_block_number)?, None);
1319
1320 Ok(())
1321 }
1322
1323 #[test]
1324 fn test_block_hash_reader() -> eyre::Result<()> {
1325 let mut rng = generators::rng();
1326 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1327 &mut rng,
1328 TEST_BLOCKS_COUNT,
1329 TEST_BLOCKS_COUNT,
1330 BlockRangeParams::default(),
1331 )?;
1332
1333 let database_block = database_blocks.first().unwrap().clone();
1334 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1335
1336 assert_eq!(provider.block_hash(database_block.number)?, Some(database_block.hash()));
1337 assert_eq!(provider.block_hash(in_memory_block.number)?, Some(in_memory_block.hash()));
1338
1339 assert_eq!(
1340 provider.canonical_hashes_range(0, 10)?,
1341 [database_blocks, in_memory_blocks]
1342 .concat()
1343 .iter()
1344 .map(|block| block.hash())
1345 .collect::<Vec<_>>()
1346 );
1347
1348 Ok(())
1349 }
1350
1351 #[test]
1352 fn test_header_provider() -> eyre::Result<()> {
1353 let mut rng = generators::rng();
1354 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1355 &mut rng,
1356 TEST_BLOCKS_COUNT,
1357 TEST_BLOCKS_COUNT,
1358 BlockRangeParams::default(),
1359 )?;
1360
1361 let database_block = database_blocks.first().unwrap().clone();
1362 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1363 let finalized_block = database_blocks.get(database_blocks.len() - 3).unwrap();
1365 provider.set_finalized(finalized_block.clone_sealed_header());
1366
1367 let blocks = [database_blocks, in_memory_blocks].concat();
1368
1369 assert_eq!(
1370 provider.header_td_by_number(database_block.number)?,
1371 Some(database_block.difficulty)
1372 );
1373
1374 assert_eq!(
1375 provider.header_td_by_number(in_memory_block.number)?,
1376 Some(in_memory_block.difficulty)
1377 );
1378
1379 assert_eq!(
1380 provider.sealed_headers_while(0..=10, |header| header.number <= 8)?,
1381 blocks
1382 .iter()
1383 .take_while(|header| header.number <= 8)
1384 .map(|b| b.clone_sealed_header())
1385 .collect::<Vec<_>>()
1386 );
1387
1388 Ok(())
1389 }
1390
1391 #[tokio::test]
1392 async fn test_canon_state_subscriptions() -> eyre::Result<()> {
1393 let factory = create_test_provider_factory();
1394
1395 let mut test_block_builder = TestBlockBuilder::eth();
1397 let block_1 = test_block_builder.generate_random_block(0, B256::ZERO);
1398 let block_hash_1 = block_1.hash();
1399
1400 let provider_rw = factory.provider_rw()?;
1402 provider_rw.insert_historical_block(block_1)?;
1403 provider_rw.commit()?;
1404
1405 let provider = BlockchainProvider::new(factory)?;
1406
1407 let in_memory_state = provider.canonical_in_memory_state();
1409 let mut rx_1 = provider.subscribe_to_canonical_state();
1410 let mut rx_2 = provider.subscribe_to_canonical_state();
1411
1412 let block_2 = test_block_builder.generate_random_block(1, block_hash_1);
1414 let chain = Chain::new(vec![block_2], ExecutionOutcome::default(), None);
1415 let commit = CanonStateNotification::Commit { new: Arc::new(chain.clone()) };
1416 in_memory_state.notify_canon_state(commit.clone());
1417 let (notification_1, notification_2) = tokio::join!(rx_1.recv(), rx_2.recv());
1418 assert_eq!(notification_1, Ok(commit.clone()));
1419 assert_eq!(notification_2, Ok(commit.clone()));
1420
1421 let block_3 = test_block_builder.generate_random_block(1, block_hash_1);
1423 let block_4 = test_block_builder.generate_random_block(2, block_3.hash());
1424 let new_chain = Chain::new(vec![block_3, block_4], ExecutionOutcome::default(), None);
1425 let re_org =
1426 CanonStateNotification::Reorg { old: Arc::new(chain), new: Arc::new(new_chain) };
1427 in_memory_state.notify_canon_state(re_org.clone());
1428 let (notification_1, notification_2) = tokio::join!(rx_1.recv(), rx_2.recv());
1429 assert_eq!(notification_1, Ok(re_org.clone()));
1430 assert_eq!(notification_2, Ok(re_org.clone()));
1431
1432 Ok(())
1433 }
1434
1435 #[test]
1436 fn test_withdrawals_provider() -> eyre::Result<()> {
1437 let mut rng = generators::rng();
1438 let chain_spec = Arc::new(ChainSpecBuilder::mainnet().shanghai_activated().build());
1439 let (provider, database_blocks, in_memory_blocks, _) =
1440 provider_with_chain_spec_and_random_blocks(
1441 &mut rng,
1442 chain_spec.clone(),
1443 TEST_BLOCKS_COUNT,
1444 TEST_BLOCKS_COUNT,
1445 BlockRangeParams { withdrawals_count: Some(1..3), ..Default::default() },
1446 )?;
1447 let blocks = [database_blocks, in_memory_blocks].concat();
1448
1449 let shainghai_timestamp =
1450 chain_spec.hardforks.fork(EthereumHardfork::Shanghai).as_timestamp().unwrap();
1451
1452 assert_eq!(
1453 provider
1454 .withdrawals_by_block(
1455 alloy_eips::BlockHashOrNumber::Number(15),
1456 shainghai_timestamp
1457 )
1458 .expect("could not call withdrawals by block"),
1459 Some(Withdrawals::new(vec![])),
1460 "Expected withdrawals_by_block to return empty list if block does not exist"
1461 );
1462
1463 for block in blocks {
1464 assert_eq!(
1465 provider
1466 .withdrawals_by_block(
1467 alloy_eips::BlockHashOrNumber::Number(block.number),
1468 shainghai_timestamp
1469 )?
1470 .unwrap(),
1471 block.body().withdrawals.clone().unwrap(),
1472 "Expected withdrawals_by_block to return correct withdrawals"
1473 );
1474 }
1475
1476 Ok(())
1477 }
1478
1479 #[test]
1480 fn test_block_num_reader() -> eyre::Result<()> {
1481 let mut rng = generators::rng();
1482 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1483 &mut rng,
1484 TEST_BLOCKS_COUNT,
1485 TEST_BLOCKS_COUNT,
1486 BlockRangeParams::default(),
1487 )?;
1488
1489 assert_eq!(provider.best_block_number()?, in_memory_blocks.last().unwrap().number);
1490 assert_eq!(provider.last_block_number()?, database_blocks.last().unwrap().number);
1491
1492 let database_block = database_blocks.first().unwrap().clone();
1493 let in_memory_block = in_memory_blocks.first().unwrap().clone();
1494 assert_eq!(provider.block_number(database_block.hash())?, Some(database_block.number));
1495 assert_eq!(provider.block_number(in_memory_block.hash())?, Some(in_memory_block.number));
1496
1497 Ok(())
1498 }
1499
1500 #[test]
1501 fn test_block_reader_id_ext_block_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.block_by_id(block_number.into()).unwrap(),
1518 Some(database_block.clone().into_block())
1519 );
1520 assert_eq!(
1521 provider.block_by_id(block_hash.into()).unwrap(),
1522 Some(database_block.into_block())
1523 );
1524
1525 let block_number = in_memory_block.number;
1526 let block_hash = in_memory_block.hash();
1527 assert_eq!(
1528 provider.block_by_id(block_number.into()).unwrap(),
1529 Some(in_memory_block.clone().into_block())
1530 );
1531 assert_eq!(
1532 provider.block_by_id(block_hash.into()).unwrap(),
1533 Some(in_memory_block.into_block())
1534 );
1535
1536 Ok(())
1537 }
1538
1539 #[test]
1540 fn test_block_reader_id_ext_header_by_number_or_tag() -> eyre::Result<()> {
1541 let mut rng = generators::rng();
1542 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1543 &mut rng,
1544 TEST_BLOCKS_COUNT,
1545 TEST_BLOCKS_COUNT,
1546 BlockRangeParams::default(),
1547 )?;
1548
1549 let database_block = database_blocks.first().unwrap().clone();
1550
1551 let in_memory_block_count = in_memory_blocks.len();
1552 let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
1553 let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
1554 let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();
1555
1556 let block_number = database_block.number;
1557 assert_eq!(
1558 provider.header_by_number_or_tag(block_number.into()).unwrap(),
1559 Some(database_block.header().clone())
1560 );
1561 assert_eq!(
1562 provider.sealed_header_by_number_or_tag(block_number.into())?,
1563 Some(database_block.clone_sealed_header())
1564 );
1565
1566 assert_eq!(
1567 provider.header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
1568 Some(canonical_block.header().clone())
1569 );
1570 assert_eq!(
1571 provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
1572 Some(canonical_block.clone_sealed_header())
1573 );
1574
1575 assert_eq!(
1576 provider.header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
1577 Some(safe_block.header().clone())
1578 );
1579 assert_eq!(
1580 provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
1581 Some(safe_block.clone_sealed_header())
1582 );
1583
1584 assert_eq!(
1585 provider.header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
1586 Some(finalized_block.header().clone())
1587 );
1588 assert_eq!(
1589 provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
1590 Some(finalized_block.clone_sealed_header())
1591 );
1592
1593 Ok(())
1594 }
1595
1596 #[test]
1597 fn test_block_reader_id_ext_header_by_id() -> eyre::Result<()> {
1598 let mut rng = generators::rng();
1599 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1600 &mut rng,
1601 TEST_BLOCKS_COUNT,
1602 TEST_BLOCKS_COUNT,
1603 BlockRangeParams::default(),
1604 )?;
1605
1606 let database_block = database_blocks.first().unwrap().clone();
1607 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1608
1609 let block_number = database_block.number;
1610 let block_hash = database_block.hash();
1611
1612 assert_eq!(
1613 provider.header_by_id(block_number.into()).unwrap(),
1614 Some(database_block.header().clone())
1615 );
1616 assert_eq!(
1617 provider.sealed_header_by_id(block_number.into()).unwrap(),
1618 Some(database_block.clone_sealed_header())
1619 );
1620
1621 assert_eq!(
1622 provider.header_by_id(block_hash.into()).unwrap(),
1623 Some(database_block.header().clone())
1624 );
1625 assert_eq!(
1626 provider.sealed_header_by_id(block_hash.into()).unwrap(),
1627 Some(database_block.clone_sealed_header())
1628 );
1629
1630 let block_number = in_memory_block.number;
1631 let block_hash = in_memory_block.hash();
1632
1633 assert_eq!(
1634 provider.header_by_id(block_number.into()).unwrap(),
1635 Some(in_memory_block.header().clone())
1636 );
1637 assert_eq!(
1638 provider.sealed_header_by_id(block_number.into()).unwrap(),
1639 Some(in_memory_block.clone_sealed_header())
1640 );
1641
1642 assert_eq!(
1643 provider.header_by_id(block_hash.into()).unwrap(),
1644 Some(in_memory_block.header().clone())
1645 );
1646 assert_eq!(
1647 provider.sealed_header_by_id(block_hash.into()).unwrap(),
1648 Some(in_memory_block.clone_sealed_header())
1649 );
1650
1651 Ok(())
1652 }
1653
1654 #[test]
1655 fn test_block_reader_id_ext_ommers_by_id() -> eyre::Result<()> {
1656 let mut rng = generators::rng();
1657 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1658 &mut rng,
1659 TEST_BLOCKS_COUNT,
1660 TEST_BLOCKS_COUNT,
1661 BlockRangeParams::default(),
1662 )?;
1663
1664 let database_block = database_blocks.first().unwrap().clone();
1665 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1666
1667 let block_number = database_block.number;
1668 let block_hash = database_block.hash();
1669
1670 assert_eq!(
1671 provider.ommers_by_id(block_number.into()).unwrap().unwrap_or_default(),
1672 database_block.body().ommers
1673 );
1674 assert_eq!(
1675 provider.ommers_by_id(block_hash.into()).unwrap().unwrap_or_default(),
1676 database_block.body().ommers
1677 );
1678
1679 let block_number = in_memory_block.number;
1680 let block_hash = in_memory_block.hash();
1681
1682 assert_eq!(
1683 provider.ommers_by_id(block_number.into()).unwrap().unwrap_or_default(),
1684 in_memory_block.body().ommers
1685 );
1686 assert_eq!(
1687 provider.ommers_by_id(block_hash.into()).unwrap().unwrap_or_default(),
1688 in_memory_block.body().ommers
1689 );
1690
1691 Ok(())
1692 }
1693
1694 #[test]
1695 fn test_receipt_provider_id_ext_receipts_by_block_id() -> eyre::Result<()> {
1696 let mut rng = generators::rng();
1697 let (provider, database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
1698 &mut rng,
1699 TEST_BLOCKS_COUNT,
1700 TEST_BLOCKS_COUNT,
1701 BlockRangeParams { tx_count: 1..3, ..Default::default() },
1702 )?;
1703
1704 let database_block = database_blocks.first().unwrap().clone();
1705 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1706
1707 let block_number = database_block.number;
1708 let block_hash = database_block.hash();
1709
1710 assert!(!receipts.get(database_block.number as usize).unwrap().is_empty());
1711 assert!(!provider
1712 .receipts_by_number_or_tag(database_block.number.into())?
1713 .unwrap()
1714 .is_empty());
1715
1716 assert_eq!(
1717 provider.receipts_by_block_id(block_number.into())?.unwrap(),
1718 receipts.get(block_number as usize).unwrap().clone()
1719 );
1720 assert_eq!(
1721 provider.receipts_by_block_id(block_hash.into())?.unwrap(),
1722 receipts.get(block_number as usize).unwrap().clone()
1723 );
1724
1725 let block_number = in_memory_block.number;
1726 let block_hash = in_memory_block.hash();
1727
1728 assert_eq!(
1729 provider.receipts_by_block_id(block_number.into())?.unwrap(),
1730 receipts.get(block_number as usize).unwrap().clone()
1731 );
1732 assert_eq!(
1733 provider.receipts_by_block_id(block_hash.into())?.unwrap(),
1734 receipts.get(block_number as usize).unwrap().clone()
1735 );
1736
1737 Ok(())
1738 }
1739
1740 #[test]
1741 fn test_receipt_provider_id_ext_receipts_by_block_number_or_tag() -> eyre::Result<()> {
1742 let mut rng = generators::rng();
1743 let (provider, database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
1744 &mut rng,
1745 TEST_BLOCKS_COUNT,
1746 TEST_BLOCKS_COUNT,
1747 BlockRangeParams { tx_count: 1..3, ..Default::default() },
1748 )?;
1749
1750 let database_block = database_blocks.first().unwrap().clone();
1751
1752 let in_memory_block_count = in_memory_blocks.len();
1753 let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
1754 let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
1755 let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();
1756
1757 assert!(!receipts.get(database_block.number as usize).unwrap().is_empty());
1758 assert!(!provider
1759 .receipts_by_number_or_tag(database_block.number.into())?
1760 .unwrap()
1761 .is_empty());
1762
1763 assert_eq!(
1764 provider.receipts_by_number_or_tag(database_block.number.into())?.unwrap(),
1765 receipts.get(database_block.number as usize).unwrap().clone()
1766 );
1767 assert_eq!(
1768 provider.receipts_by_number_or_tag(BlockNumberOrTag::Latest)?.unwrap(),
1769 receipts.get(canonical_block.number as usize).unwrap().clone()
1770 );
1771 assert_eq!(
1772 provider.receipts_by_number_or_tag(BlockNumberOrTag::Safe)?.unwrap(),
1773 receipts.get(safe_block.number as usize).unwrap().clone()
1774 );
1775 assert_eq!(
1776 provider.receipts_by_number_or_tag(BlockNumberOrTag::Finalized)?.unwrap(),
1777 receipts.get(finalized_block.number as usize).unwrap().clone()
1778 );
1779
1780 Ok(())
1781 }
1782
1783 #[test]
1784 fn test_changeset_reader() -> eyre::Result<()> {
1785 let mut rng = generators::rng();
1786
1787 let (database_blocks, in_memory_blocks) =
1788 random_blocks(&mut rng, TEST_BLOCKS_COUNT, 1, None, None, 0..1);
1789
1790 let first_database_block = database_blocks.first().map(|block| block.number).unwrap();
1791 let last_database_block = database_blocks.last().map(|block| block.number).unwrap();
1792 let first_in_memory_block = in_memory_blocks.first().map(|block| block.number).unwrap();
1793
1794 let accounts = random_eoa_accounts(&mut rng, 2);
1795
1796 let (database_changesets, database_state) = random_changeset_range(
1797 &mut rng,
1798 &database_blocks,
1799 accounts.into_iter().map(|(address, account)| (address, (account, Vec::new()))),
1800 0..0,
1801 0..0,
1802 );
1803 let (in_memory_changesets, in_memory_state) = random_changeset_range(
1804 &mut rng,
1805 &in_memory_blocks,
1806 database_state
1807 .iter()
1808 .map(|(address, (account, storage))| (*address, (*account, storage.clone()))),
1809 0..0,
1810 0..0,
1811 );
1812
1813 let factory = create_test_provider_factory();
1814
1815 let provider_rw = factory.provider_rw()?;
1816 provider_rw.append_blocks_with_state(
1817 database_blocks
1818 .into_iter()
1819 .map(|b| b.try_recover().expect("failed to seal block with senders"))
1820 .collect(),
1821 &ExecutionOutcome {
1822 bundle: BundleState::new(
1823 database_state.into_iter().map(|(address, (account, _))| {
1824 (address, None, Some(account.into()), Default::default())
1825 }),
1826 database_changesets
1827 .iter()
1828 .map(|block_changesets| {
1829 block_changesets.iter().map(|(address, account, _)| {
1830 (*address, Some(Some((*account).into())), [])
1831 })
1832 })
1833 .collect::<Vec<_>>(),
1834 Vec::new(),
1835 ),
1836 first_block: first_database_block,
1837 ..Default::default()
1838 },
1839 Default::default(),
1840 Default::default(),
1841 )?;
1842 provider_rw.commit()?;
1843
1844 let provider = BlockchainProvider::new(factory)?;
1845
1846 let in_memory_changesets = in_memory_changesets.into_iter().next().unwrap();
1847 let chain = NewCanonicalChain::Commit {
1848 new: vec![in_memory_blocks
1849 .first()
1850 .map(|block| {
1851 let senders = block.senders().expect("failed to recover senders");
1852 ExecutedBlockWithTrieUpdates::new(
1853 Arc::new(RecoveredBlock::new_sealed(block.clone(), senders)),
1854 Arc::new(ExecutionOutcome {
1855 bundle: BundleState::new(
1856 in_memory_state.into_iter().map(|(address, (account, _))| {
1857 (address, None, Some(account.into()), Default::default())
1858 }),
1859 [in_memory_changesets.iter().map(|(address, account, _)| {
1860 (*address, Some(Some((*account).into())), Vec::new())
1861 })],
1862 [],
1863 ),
1864 first_block: first_in_memory_block,
1865 ..Default::default()
1866 }),
1867 Default::default(),
1868 Default::default(),
1869 )
1870 })
1871 .unwrap()],
1872 };
1873 provider.canonical_in_memory_state.update_chain(chain);
1874
1875 assert_eq!(
1876 provider.account_block_changeset(last_database_block).unwrap(),
1877 database_changesets
1878 .into_iter()
1879 .next_back()
1880 .unwrap()
1881 .into_iter()
1882 .sorted_by_key(|(address, _, _)| *address)
1883 .map(|(address, account, _)| AccountBeforeTx { address, info: Some(account) })
1884 .collect::<Vec<_>>()
1885 );
1886 assert_eq!(
1887 provider.account_block_changeset(first_in_memory_block).unwrap(),
1888 in_memory_changesets
1889 .into_iter()
1890 .sorted_by_key(|(address, _, _)| *address)
1891 .map(|(address, account, _)| AccountBeforeTx { address, info: Some(account) })
1892 .collect::<Vec<_>>()
1893 );
1894
1895 Ok(())
1896 }
1897
1898 #[test]
1899 fn test_state_provider_factory() -> eyre::Result<()> {
1900 let mut rng = generators::rng();
1901
1902 let (in_memory_provider, _, in_memory_blocks, _) = provider_with_random_blocks(
1904 &mut rng,
1905 TEST_BLOCKS_COUNT,
1906 TEST_BLOCKS_COUNT,
1907 BlockRangeParams::default(),
1908 )?;
1909
1910 let (only_database_provider, database_blocks, _, _) = provider_with_random_blocks(
1912 &mut rng,
1913 TEST_BLOCKS_COUNT,
1914 0,
1915 BlockRangeParams::default(),
1916 )?;
1917
1918 let blocks = [database_blocks.clone(), in_memory_blocks.clone()].concat();
1919 let first_in_memory_block = in_memory_blocks.first().unwrap();
1920 let first_db_block = database_blocks.first().unwrap();
1921
1922 assert_eq!(
1924 first_in_memory_block.hash(),
1925 in_memory_provider.latest().unwrap().block_hash(first_in_memory_block.number)?.unwrap()
1926 );
1927 assert_eq!(
1929 first_db_block.hash(),
1930 only_database_provider.latest().unwrap().block_hash(first_db_block.number)?.unwrap()
1931 );
1932
1933 assert_eq!(
1935 first_in_memory_block.hash(),
1936 in_memory_provider
1937 .history_by_block_number(first_in_memory_block.number)?
1938 .block_hash(first_in_memory_block.number)?
1939 .unwrap()
1940 );
1941 assert_eq!(
1942 first_db_block.hash(),
1943 only_database_provider
1944 .history_by_block_number(first_db_block.number)?
1945 .block_hash(first_db_block.number)?
1946 .unwrap()
1947 );
1948 assert_eq!(
1949 first_in_memory_block.hash(),
1950 in_memory_provider
1951 .history_by_block_hash(first_in_memory_block.hash())?
1952 .block_hash(first_in_memory_block.number)?
1953 .unwrap()
1954 );
1955 assert!(only_database_provider.history_by_block_hash(B256::random()).is_err());
1956
1957 assert_eq!(
1959 first_in_memory_block.hash(),
1960 in_memory_provider
1961 .state_by_block_hash(first_in_memory_block.hash())?
1962 .block_hash(first_in_memory_block.number)?
1963 .unwrap()
1964 );
1965 assert_eq!(
1966 first_db_block.hash(),
1967 only_database_provider
1968 .state_by_block_hash(first_db_block.hash())?
1969 .block_hash(first_db_block.number)?
1970 .unwrap()
1971 );
1972 assert!(only_database_provider.state_by_block_hash(B256::random()).is_err());
1973
1974 assert_eq!(
1976 first_in_memory_block.hash(),
1977 in_memory_provider
1978 .pending()
1979 .unwrap()
1980 .block_hash(first_in_memory_block.number)
1981 .unwrap()
1982 .unwrap()
1983 );
1984
1985 let pending_block = database_blocks[database_blocks.len() - 1].clone();
1987 only_database_provider.canonical_in_memory_state.set_pending_block(
1988 ExecutedBlockWithTrieUpdates {
1989 block: ExecutedBlock {
1990 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1991 pending_block.clone(),
1992 Default::default(),
1993 )),
1994 execution_output: Default::default(),
1995 hashed_state: Default::default(),
1996 },
1997 trie: Default::default(),
1998 },
1999 );
2000
2001 assert_eq!(
2002 pending_block.hash(),
2003 only_database_provider
2004 .pending()
2005 .unwrap()
2006 .block_hash(pending_block.number)
2007 .unwrap()
2008 .unwrap()
2009 );
2010
2011 assert_eq!(
2012 pending_block.hash(),
2013 only_database_provider
2014 .pending_state_by_hash(pending_block.hash())?
2015 .unwrap()
2016 .block_hash(pending_block.number)?
2017 .unwrap()
2018 );
2019
2020 assert_eq!(
2022 first_in_memory_block.hash(),
2023 in_memory_provider
2024 .state_by_block_number_or_tag(BlockNumberOrTag::Number(
2025 first_in_memory_block.number
2026 ))?
2027 .block_hash(first_in_memory_block.number)?
2028 .unwrap()
2029 );
2030 assert_eq!(
2031 first_in_memory_block.hash(),
2032 in_memory_provider
2033 .state_by_block_number_or_tag(BlockNumberOrTag::Latest)?
2034 .block_hash(first_in_memory_block.number)?
2035 .unwrap()
2036 );
2037 let safe_block = in_memory_blocks[in_memory_blocks.len() - 2].clone();
2039 in_memory_provider.canonical_in_memory_state.set_safe(safe_block.clone_sealed_header());
2040 assert_eq!(
2041 safe_block.hash(),
2042 in_memory_provider
2043 .state_by_block_number_or_tag(BlockNumberOrTag::Safe)?
2044 .block_hash(safe_block.number)?
2045 .unwrap()
2046 );
2047 let finalized_block = in_memory_blocks[in_memory_blocks.len() - 3].clone();
2049 in_memory_provider
2050 .canonical_in_memory_state
2051 .set_finalized(finalized_block.clone_sealed_header());
2052 assert_eq!(
2053 finalized_block.hash(),
2054 in_memory_provider
2055 .state_by_block_number_or_tag(BlockNumberOrTag::Finalized)?
2056 .block_hash(finalized_block.number)?
2057 .unwrap()
2058 );
2059 let earliest_block = blocks.first().unwrap().clone();
2061 assert_eq!(
2062 earliest_block.hash(),
2063 only_database_provider
2064 .state_by_block_number_or_tag(BlockNumberOrTag::Earliest)?
2065 .block_hash(earliest_block.number)?
2066 .unwrap()
2067 );
2068
2069 Ok(())
2070 }
2071
2072 #[test]
2073 fn test_block_id_reader() -> eyre::Result<()> {
2074 let mut rng = generators::rng();
2076 let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
2077 &mut rng,
2078 TEST_BLOCKS_COUNT,
2079 TEST_BLOCKS_COUNT,
2080 BlockRangeParams::default(),
2081 )?;
2082
2083 let pending_block = in_memory_blocks.last().unwrap();
2085 provider.canonical_in_memory_state.set_pending_block(ExecutedBlockWithTrieUpdates {
2086 block: ExecutedBlock {
2087 recovered_block: Arc::new(RecoveredBlock::new_sealed(
2088 pending_block.clone(),
2089 Default::default(),
2090 )),
2091 execution_output: Default::default(),
2092 hashed_state: Default::default(),
2093 },
2094 trie: Default::default(),
2095 });
2096
2097 let safe_block = in_memory_blocks[in_memory_blocks.len() - 2].clone();
2099 provider.canonical_in_memory_state.set_safe(safe_block.clone_sealed_header());
2100
2101 let finalized_block = in_memory_blocks[in_memory_blocks.len() - 3].clone();
2103 provider.canonical_in_memory_state.set_finalized(finalized_block.clone_sealed_header());
2104
2105 assert_eq!(
2107 provider.pending_block_num_hash()?,
2108 Some(BlockNumHash { number: pending_block.number, hash: pending_block.hash() })
2109 );
2110
2111 assert_eq!(
2113 provider.safe_block_num_hash()?,
2114 Some(BlockNumHash { number: safe_block.number, hash: safe_block.hash() })
2115 );
2116
2117 assert_eq!(
2119 provider.finalized_block_num_hash()?,
2120 Some(BlockNumHash { number: finalized_block.number, hash: finalized_block.hash() })
2121 );
2122
2123 Ok(())
2124 }
2125
2126 macro_rules! test_by_tx_range {
2127 ([$(($method:ident, $data_extractor:expr)),* $(,)?]) => {{
2128
2129 let extra_blocks = [$(stringify!($method)),*].len();
2132
2133 let mut rng = generators::rng();
2134 let (provider, mut database_blocks, mut in_memory_blocks, receipts) = provider_with_random_blocks(
2135 &mut rng,
2136 TEST_BLOCKS_COUNT,
2137 TEST_BLOCKS_COUNT + extra_blocks,
2138 BlockRangeParams {
2139 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2140 ..Default::default()
2141 },
2142 )?;
2143
2144 $(
2145 let db_tx_count =
2147 database_blocks.iter().map(|b| b.transaction_count()).sum::<usize>() as u64;
2148 let in_mem_tx_count =
2149 in_memory_blocks.iter().map(|b| b.transaction_count()).sum::<usize>() as u64;
2150
2151 let db_range = 0..=(db_tx_count - 1);
2152 let in_mem_range = db_tx_count..=(in_mem_tx_count + db_range.end());
2153
2154 let database_data =
2156 database_blocks.iter().flat_map(|b| $data_extractor(b, &receipts)).collect::<Vec<_>>();
2157 assert_eq!(provider.$method(db_range.clone())?, database_data, "full db data");
2158
2159 let in_memory_data =
2161 in_memory_blocks.iter().flat_map(|b| $data_extractor(b, &receipts)).collect::<Vec<_>>();
2162 assert_eq!(provider.$method(in_mem_range.clone())?, in_memory_data, "full mem data");
2163
2164 assert_eq!(
2166 &provider.$method(in_mem_range.start() + 1..=in_mem_range.end() - 1)?,
2167 &in_memory_data[1..in_memory_data.len() - 1],
2168 "partial mem data"
2169 );
2170
2171 assert_eq!(provider.$method(in_mem_range.start() + 1..)?, &in_memory_data[1..], "unbounded mem data");
2173
2174 assert_eq!(provider.$method(in_mem_range.end()..)?, &in_memory_data[in_memory_data.len() -1 ..], "last mem data");
2176
2177 assert_eq!(
2179 provider.$method(in_mem_range.start() - 2..)?,
2180 database_data[database_data.len() - 2..]
2181 .iter()
2182 .chain(&in_memory_data[..])
2183 .cloned()
2184 .collect::<Vec<_>>(),
2185 "unbounded span data"
2186 );
2187
2188 {
2190 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2192
2193 assert_eq!(
2194 provider.$method(in_mem_range.start() - 2..=in_mem_range.end() - 1)?,
2195 database_data[database_data.len() - 2..]
2196 .iter()
2197 .chain(&in_memory_data[..in_memory_data.len() - 1])
2198 .cloned()
2199 .collect::<Vec<_>>(),
2200 "span data"
2201 );
2202
2203 database_blocks.push(in_memory_blocks.remove(0));
2205 }
2206
2207 let start_tx_num = u64::MAX;
2209 let end_tx_num = u64::MAX;
2210 let result = provider.$method(start_tx_num..end_tx_num)?;
2211 assert!(result.is_empty(), "No data should be found for an invalid transaction range");
2212
2213 let result = provider.$method(in_mem_range.end()+10..in_mem_range.end()+20)?;
2215 assert!(result.is_empty(), "No data should be found for an empty transaction range");
2216 )*
2217 }};
2218 }
2219
2220 #[test]
2221 fn test_methods_by_tx_range() -> eyre::Result<()> {
2222 test_by_tx_range!([
2223 (senders_by_tx_range, |block: &SealedBlock<Block>, _: &Vec<Vec<Receipt>>| block
2224 .senders()
2225 .unwrap()),
2226 (transactions_by_tx_range, |block: &SealedBlock<Block>, _: &Vec<Vec<Receipt>>| block
2227 .body()
2228 .transactions
2229 .clone()),
2230 (receipts_by_tx_range, |block: &SealedBlock<Block>, receipts: &Vec<Vec<Receipt>>| {
2231 receipts[block.number as usize].clone()
2232 })
2233 ]);
2234
2235 Ok(())
2236 }
2237
2238 macro_rules! test_by_block_range {
2239 ([$(($method:ident, $data_extractor:expr)),* $(,)?]) => {{
2240 let extra_blocks = [$(stringify!($method)),*].len();
2243
2244 let mut rng = generators::rng();
2245 let (provider, mut database_blocks, mut in_memory_blocks, _) = provider_with_random_blocks(
2246 &mut rng,
2247 TEST_BLOCKS_COUNT,
2248 TEST_BLOCKS_COUNT + extra_blocks,
2249 BlockRangeParams {
2250 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2251 ..Default::default()
2252 },
2253 )?;
2254
2255 $(
2256 let db_block_count = database_blocks.len() as u64;
2258 let in_mem_block_count = in_memory_blocks.len() as u64;
2259
2260 let db_range = 0..=db_block_count - 1;
2261 let in_mem_range = db_block_count..=(in_mem_block_count + db_range.end());
2262
2263 let database_data =
2265 database_blocks.iter().map(|b| $data_extractor(b)).collect::<Vec<_>>();
2266 assert_eq!(provider.$method(db_range.clone())?, database_data);
2267
2268 let in_memory_data =
2270 in_memory_blocks.iter().map(|b| $data_extractor(b)).collect::<Vec<_>>();
2271 assert_eq!(provider.$method(in_mem_range.clone())?, in_memory_data);
2272
2273 assert_eq!(
2275 &provider.$method(in_mem_range.start() + 1..=in_mem_range.end() - 1)?,
2276 &in_memory_data[1..in_memory_data.len() - 1]
2277 );
2278
2279 {
2281
2282 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2284
2285 assert_eq!(
2286 provider.$method(in_mem_range.start() - 2..=in_mem_range.end() - 1)?,
2287 database_data[database_data.len() - 2..]
2288 .iter()
2289 .chain(&in_memory_data[..in_memory_data.len() - 1])
2290 .cloned()
2291 .collect::<Vec<_>>()
2292 );
2293
2294 database_blocks.push(in_memory_blocks.remove(0));
2296 }
2297
2298 let start_block_num = u64::MAX;
2300 let end_block_num = u64::MAX;
2301 let result = provider.$method(start_block_num..=end_block_num-1)?;
2302 assert!(result.is_empty(), "No data should be found for an invalid block range");
2303
2304 let result = provider.$method(in_mem_range.end() + 10..=in_mem_range.end() + 20)?;
2306 assert!(result.is_empty(), "No data should be found for an empty block range");
2307 )*
2308 }};
2309 }
2310
2311 #[test]
2312 fn test_methods_by_block_range() -> eyre::Result<()> {
2313 test_by_block_range!([
2316 (headers_range, |block: &SealedBlock<Block>| block.header().clone()),
2317 (sealed_headers_range, |block: &SealedBlock<Block>| block.clone_sealed_header()),
2318 (block_range, |block: &SealedBlock<Block>| block.clone().into_block()),
2319 (block_with_senders_range, |block: &SealedBlock<Block>| block
2320 .clone()
2321 .try_recover()
2322 .unwrap()),
2323 (recovered_block_range, |block: &SealedBlock<Block>| block
2324 .clone()
2325 .try_recover()
2326 .unwrap()),
2327 (transactions_by_block_range, |block: &SealedBlock<Block>| block
2328 .body()
2329 .transactions
2330 .clone()),
2331 ]);
2332
2333 Ok(())
2334 }
2335
2336 macro_rules! call_method {
2338 ($provider:expr, $method:ident, ($($args:expr),*), $expected_item:expr) => {{
2339 let result = $provider.$method($($args),*)?;
2340 assert_eq!(
2341 result,
2342 $expected_item,
2343 "{}: item does not match the expected item for arguments {:?}",
2344 stringify!($method),
2345 ($($args),*)
2346 );
2347 }};
2348
2349 (ONE, $provider:expr, $method:ident, $item_extractor:expr, $txnum:expr, $txhash:expr, $block:expr, $receipts:expr) => {{
2351 let (arg, expected_item) = $item_extractor($block, $txnum($block), $txhash($block), $receipts);
2352 call_method!($provider, $method, (arg), expected_item);
2353 }};
2354
2355 (TWO, $provider:expr, $method:ident, $item_extractor:expr, $txnum:expr, $txhash:expr, $block:expr, $receipts:expr) => {{
2357 let ((arg1, arg2), expected_item) = $item_extractor($block, $txnum($block), $txhash($block), $receipts);
2358 call_method!($provider, $method, (arg1, arg2), expected_item);
2359 }};
2360 }
2361
2362 macro_rules! test_non_range {
2367 ([$(($arg_count:ident, $method:ident, $item_extractor:expr, $invalid_args:expr)),* $(,)?]) => {{
2368
2369 let extra_blocks = [$(stringify!($arg_count)),*].len();
2372
2373 let mut rng = generators::rng();
2374 let (provider, mut database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
2375 &mut rng,
2376 TEST_BLOCKS_COUNT,
2377 TEST_BLOCKS_COUNT + extra_blocks,
2378 BlockRangeParams {
2379 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2380 ..Default::default()
2381 },
2382 )?;
2383
2384 let mut in_memory_blocks: std::collections::VecDeque<_> = in_memory_blocks.into();
2385
2386 $(
2387 let tx_hash = |block: &SealedBlock<Block>| *block.body().transactions[0].tx_hash();
2388 let tx_num = |block: &SealedBlock<Block>| {
2389 database_blocks
2390 .iter()
2391 .chain(in_memory_blocks.iter())
2392 .take_while(|b| b.number < block.number)
2393 .map(|b| b.transaction_count())
2394 .sum::<usize>() as u64
2395 };
2396
2397 {
2399 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2401
2402 call_method!($arg_count, provider, $method, $item_extractor, tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2403
2404 database_blocks.push(in_memory_blocks.pop_front().unwrap());
2406 }
2407
2408 let tx_num = |block: &SealedBlock<Block>| {
2410 database_blocks
2411 .iter()
2412 .chain(in_memory_blocks.iter())
2413 .take_while(|b| b.number < block.number)
2414 .map(|b| b.transaction_count())
2415 .sum::<usize>() as u64
2416 };
2417
2418 {
2420 call_method!($arg_count, provider, $method, |_,_,_,_| ( ($invalid_args, None)), tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2421 }
2422
2423 {
2425 let last_mem_block = &in_memory_blocks[in_memory_blocks.len() - 1];
2426
2427 let (args, expected_item) = $item_extractor(last_mem_block, tx_num(last_mem_block), tx_hash(last_mem_block), &receipts);
2428 call_method!($arg_count, provider, $method, |_,_,_,_| (args.clone(), expected_item), tx_num, tx_hash, last_mem_block, &receipts);
2429
2430 call_method!($arg_count, provider.database, $method, |_,_,_,_| ( (args, None)), tx_num, tx_hash, last_mem_block, &receipts);
2432 }
2433 )*
2434 }};
2435}
2436
2437 #[test]
2438 fn test_non_range_methods() -> eyre::Result<()> {
2439 let test_tx_index = 0;
2440
2441 test_non_range!([
2442 (
2450 ONE,
2451 header_by_number,
2452 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2453 block.number,
2454 Some(block.header().clone())
2455 ),
2456 u64::MAX
2457 ),
2458 (
2459 ONE,
2460 sealed_header,
2461 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2462 block.number,
2463 Some(block.clone_sealed_header())
2464 ),
2465 u64::MAX
2466 ),
2467 (
2468 ONE,
2469 block_hash,
2470 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2471 block.number,
2472 Some(block.hash())
2473 ),
2474 u64::MAX
2475 ),
2476 (
2477 ONE,
2478 block_number,
2479 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2480 block.hash(),
2481 Some(block.number)
2482 ),
2483 B256::random()
2484 ),
2485 (
2486 ONE,
2487 block,
2488 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2489 BlockHashOrNumber::Hash(block.hash()),
2490 Some(block.clone().into_block())
2491 ),
2492 BlockHashOrNumber::Hash(B256::random())
2493 ),
2494 (
2495 ONE,
2496 block,
2497 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2498 BlockHashOrNumber::Number(block.number),
2499 Some(block.clone().into_block())
2500 ),
2501 BlockHashOrNumber::Number(u64::MAX)
2502 ),
2503 (
2504 ONE,
2505 block_body_indices,
2506 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2507 block.number,
2508 Some(StoredBlockBodyIndices {
2509 first_tx_num: tx_num,
2510 tx_count: block.transaction_count() as u64
2511 })
2512 ),
2513 u64::MAX
2514 ),
2515 (
2516 TWO,
2517 recovered_block,
2518 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2519 (BlockHashOrNumber::Number(block.number), TransactionVariant::WithHash),
2520 block.clone().try_recover().ok()
2521 ),
2522 (BlockHashOrNumber::Number(u64::MAX), TransactionVariant::WithHash)
2523 ),
2524 (
2525 TWO,
2526 recovered_block,
2527 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2528 (BlockHashOrNumber::Hash(block.hash()), TransactionVariant::WithHash),
2529 block.clone().try_recover().ok()
2530 ),
2531 (BlockHashOrNumber::Hash(B256::random()), TransactionVariant::WithHash)
2532 ),
2533 (
2534 TWO,
2535 sealed_block_with_senders,
2536 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2537 (BlockHashOrNumber::Number(block.number), TransactionVariant::WithHash),
2538 block.clone().try_recover().ok()
2539 ),
2540 (BlockHashOrNumber::Number(u64::MAX), TransactionVariant::WithHash)
2541 ),
2542 (
2543 TWO,
2544 sealed_block_with_senders,
2545 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2546 (BlockHashOrNumber::Hash(block.hash()), TransactionVariant::WithHash),
2547 block.clone().try_recover().ok()
2548 ),
2549 (BlockHashOrNumber::Hash(B256::random()), TransactionVariant::WithHash)
2550 ),
2551 (
2552 ONE,
2553 transaction_id,
2554 |_: &SealedBlock<Block>, tx_num: TxNumber, tx_hash: B256, _: &Vec<Vec<Receipt>>| (
2555 tx_hash,
2556 Some(tx_num)
2557 ),
2558 B256::random()
2559 ),
2560 (
2561 ONE,
2562 transaction_by_id,
2563 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2564 tx_num,
2565 Some(block.body().transactions[test_tx_index].clone())
2566 ),
2567 u64::MAX
2568 ),
2569 (
2570 ONE,
2571 transaction_by_id_unhashed,
2572 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2573 tx_num,
2574 Some(block.body().transactions[test_tx_index].clone())
2575 ),
2576 u64::MAX
2577 ),
2578 (
2579 ONE,
2580 transaction_by_hash,
2581 |block: &SealedBlock<Block>, _: TxNumber, tx_hash: B256, _: &Vec<Vec<Receipt>>| (
2582 tx_hash,
2583 Some(block.body().transactions[test_tx_index].clone())
2584 ),
2585 B256::random()
2586 ),
2587 (
2588 ONE,
2589 transaction_block,
2590 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2591 tx_num,
2592 Some(block.number)
2593 ),
2594 u64::MAX
2595 ),
2596 (
2597 ONE,
2598 transactions_by_block,
2599 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2600 BlockHashOrNumber::Number(block.number),
2601 Some(block.body().transactions.clone())
2602 ),
2603 BlockHashOrNumber::Number(u64::MAX)
2604 ),
2605 (
2606 ONE,
2607 transactions_by_block,
2608 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2609 BlockHashOrNumber::Hash(block.hash()),
2610 Some(block.body().transactions.clone())
2611 ),
2612 BlockHashOrNumber::Number(u64::MAX)
2613 ),
2614 (
2615 ONE,
2616 transaction_sender,
2617 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2618 tx_num,
2619 block.body().transactions[test_tx_index].recover_signer().ok()
2620 ),
2621 u64::MAX
2622 ),
2623 (
2624 ONE,
2625 receipt,
2626 |block: &SealedBlock<Block>,
2627 tx_num: TxNumber,
2628 _: B256,
2629 receipts: &Vec<Vec<Receipt>>| (
2630 tx_num,
2631 Some(receipts[block.number as usize][test_tx_index].clone())
2632 ),
2633 u64::MAX
2634 ),
2635 (
2636 ONE,
2637 receipt_by_hash,
2638 |block: &SealedBlock<Block>,
2639 _: TxNumber,
2640 tx_hash: B256,
2641 receipts: &Vec<Vec<Receipt>>| (
2642 tx_hash,
2643 Some(receipts[block.number as usize][test_tx_index].clone())
2644 ),
2645 B256::random()
2646 ),
2647 (
2648 ONE,
2649 receipts_by_block,
2650 |block: &SealedBlock<Block>, _: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2651 BlockHashOrNumber::Number(block.number),
2652 Some(receipts[block.number as usize].clone())
2653 ),
2654 BlockHashOrNumber::Number(u64::MAX)
2655 ),
2656 (
2657 ONE,
2658 receipts_by_block,
2659 |block: &SealedBlock<Block>, _: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2660 BlockHashOrNumber::Hash(block.hash()),
2661 Some(receipts[block.number as usize].clone())
2662 ),
2663 BlockHashOrNumber::Hash(B256::random())
2664 ),
2665 ]);
2667
2668 Ok(())
2669 }
2670
2671 #[test]
2672 fn test_race() -> eyre::Result<()> {
2673 let mut rng = generators::rng();
2674 let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
2675 &mut rng,
2676 TEST_BLOCKS_COUNT - 1,
2677 TEST_BLOCKS_COUNT + 1,
2678 BlockRangeParams {
2679 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2680 ..Default::default()
2681 },
2682 )?;
2683
2684 let old_transaction_hash_fn =
2687 |hash: B256,
2688 canonical_in_memory_state: CanonicalInMemoryState,
2689 factory: ProviderFactory<MockNodeTypesWithDB>| {
2690 assert!(factory.transaction_by_hash(hash)?.is_none(), "should not be in database");
2691 Ok::<_, ProviderError>(canonical_in_memory_state.transaction_by_hash(hash))
2692 };
2693
2694 let correct_transaction_hash_fn =
2696 |hash: B256,
2697 canonical_in_memory_state: CanonicalInMemoryState,
2698 _factory: ProviderFactory<MockNodeTypesWithDB>| {
2699 if let Some(tx) = canonical_in_memory_state.transaction_by_hash(hash) {
2700 return Ok::<_, ProviderError>(Some(tx));
2701 }
2702 panic!("should not be in database");
2703 };
2705
2706 {
2708 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2711 let to_be_persisted_tx = in_memory_blocks[0].body().transactions[0].clone();
2712
2713 assert!(matches!(
2716 old_transaction_hash_fn(
2717 *to_be_persisted_tx.tx_hash(),
2718 provider.canonical_in_memory_state(),
2719 provider.database.clone()
2720 ),
2721 Ok(None)
2722 ));
2723 }
2724
2725 {
2727 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[1].number);
2730 let to_be_persisted_tx = in_memory_blocks[1].body().transactions[0].clone();
2731
2732 assert!(matches!(
2733 correct_transaction_hash_fn(
2734 *to_be_persisted_tx.tx_hash(),
2735 provider.canonical_in_memory_state(),
2736 provider.database
2737 ),
2738 Ok(Some(to_be_persisted_tx))
2739 ));
2740 }
2741
2742 Ok(())
2743 }
2744}