1use crate::{
2 providers::{
3 ConsistentProvider, OverlayStateProvider, OverlayStateProviderFactory, ProviderNodeTypes,
4 RocksDBProvider, StaticFileProvider, StaticFileProviderRWRefMut,
5 },
6 AccountReader, BalProvider, BalStoreHandle, BlockHashReader, BlockIdReader, BlockNumReader,
7 BlockReader, BlockReaderIdExt, BlockSource, CanonChainTracker, CanonStateNotifications,
8 CanonStateSubscriptions, ChainSpecProvider, ChainStateBlockReader, ChangeSetReader,
9 DatabaseProviderFactory, HashedPostStateProvider, HeaderProvider, ProviderError,
10 ProviderFactory, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt,
11 RocksDBProviderFactory, StageCheckpointReader, StateProviderBox, StateProviderFactory,
12 StateReader, StaticFileProviderFactory, TransactionVariant, TransactionsProvider,
13};
14use alloy_consensus::{transaction::TransactionMeta, BlockHeader};
15use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumHash, BlockNumberOrTag};
16use alloy_primitives::{Address, BlockHash, BlockNumber, Bytes, TxHash, TxNumber, B256};
17use alloy_rpc_types_engine::ForkchoiceState;
18use reth_chain_state::{
19 BlockState, CanonicalInMemoryState, ForkChoiceNotifications, ForkChoiceSubscriptions,
20 MemoryOverlayStateProvider, PersistedBlockNotifications, PersistedBlockSubscriptions,
21};
22use reth_chainspec::ChainInfo;
23use reth_db_api::models::{AccountBeforeTx, BlockNumberAddress, StoredBlockBodyIndices};
24use reth_execution_types::ExecutionOutcome;
25use reth_node_types::{BlockTy, HeaderTy, NodeTypesWithDB, ReceiptTy, TxTy};
26use reth_primitives_traits::{
27 Account, RecoveredBlock, SealedHeader, SealedOrRecoveredBlock, StorageEntry,
28};
29use reth_prune_types::{PruneCheckpoint, PruneSegment};
30use reth_stages_types::{StageCheckpoint, StageId};
31use reth_static_file_types::StaticFileSegment;
32use reth_storage_api::{
33 BlockBodyIndicesProvider, NodePrimitivesProvider, RangeEnd, RangeResponse, RangeResult,
34 StateRangeProvider, StateRangeProviderFactory, StateRangeView, StorageChangeSetReader,
35 StorageRangeResult,
36};
37use reth_storage_errors::provider::ProviderResult;
38use reth_trie::{
39 hashed_cursor::{HashedCursor, HashedCursorFactory},
40 metrics::TrieRootMetrics,
41 proof::{Proof, StorageProof},
42 HashedPostState, KeccakKeyHasher, MultiProofTargets, StorageRoot, TrieInput, TrieInputSorted,
43 TrieType,
44};
45use revm::database::BundleState;
46use std::{
47 ops::{RangeBounds, RangeInclusive},
48 sync::Arc,
49 time::Instant,
50};
51use tracing::trace;
52
53pub const SNAPSHOT_STATE_RETENTION: u64 = 128;
56
57type StateRangeDbProvider<N> = <ProviderFactory<N> as DatabaseProviderFactory>::Provider;
58type HistoricalStateRangeProvider<N> = OverlayStateProvider<StateRangeDbProvider<N>>;
59
60#[derive(Debug)]
66pub struct BlockchainProvider<N: NodeTypesWithDB> {
67 pub(crate) database: ProviderFactory<N>,
69 pub(crate) canonical_in_memory_state: CanonicalInMemoryState<N::Primitives>,
72 pub(crate) bal_store: BalStoreHandle,
74}
75
76impl<N: NodeTypesWithDB> Clone for BlockchainProvider<N> {
77 fn clone(&self) -> Self {
78 Self {
79 database: self.database.clone(),
80 canonical_in_memory_state: self.canonical_in_memory_state.clone(),
81 bal_store: self.bal_store.clone(),
82 }
83 }
84}
85
86impl<N: ProviderNodeTypes> BlockchainProvider<N> {
87 pub fn new(storage: ProviderFactory<N>) -> ProviderResult<Self> {
90 let provider = storage.provider()?;
91 let best = provider.chain_info()?;
92 match provider.header_by_number(best.best_number)? {
93 Some(header) => {
94 drop(provider);
95 Ok(Self::with_latest(storage, SealedHeader::new(header, best.best_hash))?)
96 }
97 None => Err(ProviderError::HeaderNotFound(best.best_number.into())),
98 }
99 }
100
101 pub fn with_latest(
107 storage: ProviderFactory<N>,
108 latest: SealedHeader<HeaderTy<N>>,
109 ) -> ProviderResult<Self> {
110 let provider = storage.provider()?;
111 let finalized_header = provider
112 .last_finalized_block_number()?
113 .map(|num| provider.sealed_header(num))
114 .transpose()?
115 .flatten();
116 let safe_header = provider
117 .last_safe_block_number()?
118 .or_else(|| {
119 provider.last_finalized_block_number().ok().flatten()
122 })
123 .map(|num| provider.sealed_header(num))
124 .transpose()?
125 .flatten();
126 let bal_store = storage.bal_store().clone();
127
128 Ok(Self {
129 database: storage,
130 canonical_in_memory_state: CanonicalInMemoryState::with_head(
131 latest,
132 finalized_header,
133 safe_header,
134 ),
135 bal_store,
136 })
137 }
138
139 pub fn canonical_in_memory_state(&self) -> CanonicalInMemoryState<N::Primitives> {
141 self.canonical_in_memory_state.clone()
142 }
143
144 #[track_caller]
148 pub fn consistent_provider(&self) -> ProviderResult<ConsistentProvider<N>> {
149 ConsistentProvider::new(self.database.clone(), self.canonical_in_memory_state())
150 }
151
152 fn block_state_provider(
154 &self,
155 state: &BlockState<N::Primitives>,
156 ) -> ProviderResult<MemoryOverlayStateProvider<N::Primitives>> {
157 let anchor_hash = state.anchor().hash;
158 let latest_historical = self.database.history_by_block_hash(anchor_hash)?;
159 Ok(state.state_provider(latest_historical))
160 }
161
162 fn block_state_range_provider(
165 &self,
166 state_root: B256,
167 ) -> ProviderResult<Option<HistoricalStateRangeProvider<N>>> {
168 let Some(matched) = self
169 .canonical_in_memory_state
170 .canonical_chain()
171 .find(|state| state.state_root() == state_root)
172 else {
173 return Ok(None)
174 };
175
176 let blocks: Vec<_> = matched.chain().map(|state| state.block()).collect();
178 let sorted: Vec<_> =
179 blocks.iter().rev().map(|block| (block.hashed_state(), block.trie_updates())).collect();
180 let input = TrieInput::from_blocks_sorted(
181 sorted.iter().map(|(state, nodes)| (state.as_ref(), nodes.as_ref())),
182 );
183 let merged = TrieInputSorted::from_unsorted(input);
184
185 let overlay_factory = OverlayStateProviderFactory::new(
188 self.database.clone(),
189 self.database
190 .overlay_manager()
191 .overlay_builder(matched.anchor().hash)
192 .with_immediate_state_trie_overlay(merged.state, merged.nodes),
193 );
194 reth_storage_api::DatabaseProviderROFactory::database_provider_ro(&overlay_factory)
195 .map(Some)
196 }
197
198 fn historical_state_range_provider(
200 &self,
201 state_root: B256,
202 ) -> ProviderResult<Option<HistoricalStateRangeProvider<N>>> {
203 let provider = self.database.provider()?;
204 let Some(finish) = provider.get_stage_checkpoint(StageId::Finish)? else { return Ok(None) };
205 let oldest = finish.block_number.saturating_sub(SNAPSHOT_STATE_RETENTION - 1);
206 let mut block_hash = None;
207
208 for number in (oldest..=finish.block_number).rev() {
209 let Some(header) = provider.sealed_header(number)? else { continue };
210 if header.state_root() == state_root {
211 block_hash = Some(header.hash());
212 break
213 }
214 }
215 drop(provider);
216
217 let Some(block_hash) = block_hash else { return Ok(None) };
218 let overlay_factory = OverlayStateProviderFactory::new(
219 self.database.clone(),
220 self.database.overlay_manager().overlay_builder(block_hash),
221 );
222 reth_storage_api::DatabaseProviderROFactory::database_provider_ro(&overlay_factory)
223 .map(Some)
224 }
225}
226
227impl<N: NodeTypesWithDB> NodePrimitivesProvider for BlockchainProvider<N> {
228 type Primitives = N::Primitives;
229}
230
231impl<N: NodeTypesWithDB> BalProvider for BlockchainProvider<N> {
232 fn bal_store(&self) -> &BalStoreHandle {
233 &self.bal_store
234 }
235}
236
237struct HistoricalStateRangeView<N: ProviderNodeTypes> {
239 provider: HistoricalStateRangeProvider<N>,
240}
241
242impl<N: ProviderNodeTypes> StateRangeProviderFactory for BlockchainProvider<N> {
243 fn state_range_provider(&self, state_root: B256) -> ProviderResult<Option<StateRangeView>> {
246 let provider = match self.block_state_range_provider(state_root)? {
247 Some(provider) => Some(provider),
248 None => self.historical_state_range_provider(state_root)?,
249 };
250 Ok(provider
251 .map(|provider| Box::new(HistoricalStateRangeView { provider }) as StateRangeView))
252 }
253}
254
255impl<N: ProviderNodeTypes> StateRangeProvider for HistoricalStateRangeView<N> {
256 fn account_range(
257 &self,
258 start: B256,
259 limit: B256,
260 response_bytes: usize,
261 ) -> RangeResult<(B256, Account)> {
262 let mut cursor = self.provider.hashed_account_cursor().map_err(ProviderError::Database)?;
263
264 let mut accounts = Vec::new();
265 let mut total_bytes = 0usize;
266 let mut end = RangeEnd::Exhausted;
267
268 let mut entry = cursor.seek(start).map_err(ProviderError::Database)?;
271 while let Some((hash, account)) = entry {
272 total_bytes += 32 + 4 * 32; accounts.push((hash, account));
274 if hash >= limit {
275 end = RangeEnd::HashLimit;
276 break
277 }
278 if total_bytes > response_bytes {
279 end = RangeEnd::ByteLimit;
280 break
281 }
282 entry = cursor.next().map_err(ProviderError::Database)?;
283 }
284
285 Ok(RangeResponse { items: accounts, end })
286 }
287
288 fn storage_root_by_hash(&self, hashed_address: B256) -> ProviderResult<B256> {
289 let root = StorageRoot::new_hashed(
290 &self.provider,
291 &self.provider,
292 hashed_address,
293 Default::default(),
294 TrieRootMetrics::new(TrieType::Storage),
295 )
296 .root()
297 .map_err(|err| ProviderError::Database(err.into()))?;
298 Ok(root)
299 }
300
301 fn storage_range(
302 &self,
303 hashed_address: B256,
304 start: B256,
305 limit: B256,
306 response_bytes: usize,
307 ) -> StorageRangeResult {
308 let mut account_cursor =
311 self.provider.hashed_account_cursor().map_err(ProviderError::Database)?;
312 let found = account_cursor.seek(hashed_address).map_err(ProviderError::Database)?;
313 if found.map(|(hash, _)| hash) != Some(hashed_address) {
314 return Ok(None)
315 }
316
317 let mut cursor =
318 self.provider.hashed_storage_cursor(hashed_address).map_err(ProviderError::Database)?;
319
320 let mut slots = Vec::new();
321 let mut total_bytes = 0usize;
322 let mut end = RangeEnd::Exhausted;
323
324 let mut entry = cursor.seek(start).map_err(ProviderError::Database)?;
327 while let Some((hash, value)) = entry {
328 total_bytes += 64;
329 slots.push((hash, value));
330 if hash >= limit {
331 end = RangeEnd::HashLimit;
332 break
333 }
334 if total_bytes > response_bytes {
335 end = RangeEnd::ByteLimit;
336 break
337 }
338 entry = cursor.next().map_err(ProviderError::Database)?;
339 }
340
341 Ok(Some(RangeResponse { items: slots, end }))
342 }
343
344 fn account_range_proof(&self, keys: &[B256]) -> ProviderResult<Vec<Bytes>> {
345 let multiproof = Proof::new(&self.provider, &self.provider)
346 .multiproof(MultiProofTargets::accounts(keys.iter().copied()))
347 .map_err(ProviderError::from)?;
348 Ok(multiproof
349 .account_subtree
350 .into_nodes_sorted()
351 .into_iter()
352 .map(|(_, bytes)| bytes)
353 .collect())
354 }
355
356 fn storage_range_proof(
357 &self,
358 hashed_address: B256,
359 keys: &[B256],
360 ) -> ProviderResult<Vec<Bytes>> {
361 let multiproof = StorageProof::new_hashed(&self.provider, &self.provider, hashed_address)
362 .storage_multiproof(keys.iter().copied().collect())
363 .map_err(ProviderError::from)?;
364 Ok(multiproof.subtree.into_nodes_sorted().into_iter().map(|(_, bytes)| bytes).collect())
365 }
366}
367
368impl<N: ProviderNodeTypes> DatabaseProviderFactory for BlockchainProvider<N> {
369 type DB = N::DB;
370 type Provider = <ProviderFactory<N> as DatabaseProviderFactory>::Provider;
371 type ProviderRW = <ProviderFactory<N> as DatabaseProviderFactory>::ProviderRW;
372
373 fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
374 DatabaseProviderFactory::database_provider_ro(&self.database)
375 }
376
377 fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
378 DatabaseProviderFactory::database_provider_rw(&self.database)
379 }
380}
381
382impl<N: ProviderNodeTypes> StaticFileProviderFactory for BlockchainProvider<N> {
383 fn static_file_provider(&self) -> StaticFileProvider<Self::Primitives> {
384 self.database.static_file_provider()
385 }
386
387 fn get_static_file_writer(
388 &self,
389 block: BlockNumber,
390 segment: StaticFileSegment,
391 ) -> ProviderResult<StaticFileProviderRWRefMut<'_, Self::Primitives>> {
392 self.database.get_static_file_writer(block, segment)
393 }
394}
395
396impl<N: ProviderNodeTypes> RocksDBProviderFactory for BlockchainProvider<N> {
397 fn rocksdb_provider(&self) -> RocksDBProvider {
398 self.database.rocksdb_provider()
399 }
400
401 fn set_pending_rocksdb_batch(&self, _batch: rocksdb::WriteBatchWithTransaction<true>) {
402 unimplemented!("BlockchainProvider wraps ProviderFactory - use DatabaseProvider::set_pending_rocksdb_batch instead")
403 }
404
405 fn commit_pending_rocksdb_batches(&self) -> ProviderResult<()> {
406 unimplemented!("BlockchainProvider wraps ProviderFactory - use DatabaseProvider::commit_pending_rocksdb_batches instead")
407 }
408}
409
410impl<N: ProviderNodeTypes> HeaderProvider for BlockchainProvider<N> {
411 type Header = HeaderTy<N>;
412
413 fn header(&self, block_hash: BlockHash) -> ProviderResult<Option<Self::Header>> {
414 self.consistent_provider()?.header(block_hash)
415 }
416
417 fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Self::Header>> {
418 self.consistent_provider()?.header_by_number(num)
419 }
420
421 fn headers_range(
422 &self,
423 range: impl RangeBounds<BlockNumber>,
424 ) -> ProviderResult<Vec<Self::Header>> {
425 self.consistent_provider()?.headers_range(range)
426 }
427
428 fn sealed_header(
429 &self,
430 number: BlockNumber,
431 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
432 self.consistent_provider()?.sealed_header(number)
433 }
434
435 fn sealed_headers_range(
436 &self,
437 range: impl RangeBounds<BlockNumber>,
438 ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
439 self.consistent_provider()?.sealed_headers_range(range)
440 }
441
442 fn sealed_headers_while(
443 &self,
444 range: impl RangeBounds<BlockNumber>,
445 predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
446 ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
447 self.consistent_provider()?.sealed_headers_while(range, predicate)
448 }
449}
450
451impl<N: ProviderNodeTypes> BlockHashReader for BlockchainProvider<N> {
452 fn block_hash(&self, number: u64) -> ProviderResult<Option<B256>> {
453 self.consistent_provider()?.block_hash(number)
454 }
455
456 fn canonical_hashes_range(
457 &self,
458 start: BlockNumber,
459 end: BlockNumber,
460 ) -> ProviderResult<Vec<B256>> {
461 self.consistent_provider()?.canonical_hashes_range(start, end)
462 }
463}
464
465impl<N: ProviderNodeTypes> BlockNumReader for BlockchainProvider<N> {
466 fn chain_info(&self) -> ProviderResult<ChainInfo> {
467 Ok(self.canonical_in_memory_state.chain_info())
468 }
469
470 fn best_block_number(&self) -> ProviderResult<BlockNumber> {
471 Ok(self.canonical_in_memory_state.get_canonical_block_number())
472 }
473
474 fn last_block_number(&self) -> ProviderResult<BlockNumber> {
475 self.database.last_block_number()
476 }
477
478 fn earliest_block_number(&self) -> ProviderResult<BlockNumber> {
479 self.database.earliest_block_number()
480 }
481
482 fn block_number(&self, hash: B256) -> ProviderResult<Option<BlockNumber>> {
483 self.consistent_provider()?.block_number(hash)
484 }
485}
486
487impl<N: ProviderNodeTypes> BlockIdReader for BlockchainProvider<N> {
488 fn pending_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
489 Ok(self.canonical_in_memory_state.pending_block_num_hash())
490 }
491
492 fn safe_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
493 Ok(self.canonical_in_memory_state.get_safe_num_hash())
494 }
495
496 fn finalized_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
497 Ok(self.canonical_in_memory_state.get_finalized_num_hash())
498 }
499}
500
501impl<N: ProviderNodeTypes> BlockReader for BlockchainProvider<N> {
502 type Block = BlockTy<N>;
503
504 fn find_block_by_hash(
505 &self,
506 hash: B256,
507 source: BlockSource,
508 ) -> ProviderResult<Option<Self::Block>> {
509 self.consistent_provider()?.find_block_by_hash(hash, source)
510 }
511
512 fn find_sealed_or_recovered_block(
513 &self,
514 hash: B256,
515 source: BlockSource,
516 ) -> ProviderResult<Option<SealedOrRecoveredBlock<Self::Block>>> {
517 self.consistent_provider()?.find_sealed_or_recovered_block(hash, source)
518 }
519
520 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
521 self.consistent_provider()?.block(id)
522 }
523
524 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
525 Ok(self.canonical_in_memory_state.pending_recovered_block())
526 }
527
528 fn pending_block_and_receipts(
529 &self,
530 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
531 Ok(self.canonical_in_memory_state.pending_block_and_receipts())
532 }
533
534 fn recovered_block(
541 &self,
542 id: BlockHashOrNumber,
543 transaction_kind: TransactionVariant,
544 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
545 self.consistent_provider()?.recovered_block(id, transaction_kind)
546 }
547
548 fn sealed_block_with_senders(
549 &self,
550 id: BlockHashOrNumber,
551 transaction_kind: TransactionVariant,
552 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
553 self.consistent_provider()?.sealed_block_with_senders(id, transaction_kind)
554 }
555
556 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
557 self.consistent_provider()?.block_range(range)
558 }
559
560 fn block_with_senders_range(
561 &self,
562 range: RangeInclusive<BlockNumber>,
563 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
564 self.consistent_provider()?.block_with_senders_range(range)
565 }
566
567 fn recovered_block_range(
568 &self,
569 range: RangeInclusive<BlockNumber>,
570 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
571 self.consistent_provider()?.recovered_block_range(range)
572 }
573
574 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
575 self.consistent_provider()?.block_by_transaction_id(id)
576 }
577}
578
579impl<N: ProviderNodeTypes> TransactionsProvider for BlockchainProvider<N> {
580 type Transaction = TxTy<N>;
581
582 fn transaction_id(&self, tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
583 self.consistent_provider()?.transaction_id(tx_hash)
584 }
585
586 fn transaction_by_id(&self, id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
587 self.consistent_provider()?.transaction_by_id(id)
588 }
589
590 fn transaction_by_id_unhashed(
591 &self,
592 id: TxNumber,
593 ) -> ProviderResult<Option<Self::Transaction>> {
594 self.consistent_provider()?.transaction_by_id_unhashed(id)
595 }
596
597 fn transaction_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
598 self.consistent_provider()?.transaction_by_hash(hash)
599 }
600
601 fn transaction_by_hash_with_meta(
602 &self,
603 tx_hash: TxHash,
604 ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
605 self.consistent_provider()?.transaction_by_hash_with_meta(tx_hash)
606 }
607
608 fn transactions_by_block(
609 &self,
610 id: BlockHashOrNumber,
611 ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
612 self.consistent_provider()?.transactions_by_block(id)
613 }
614
615 fn transactions_by_block_range(
616 &self,
617 range: impl RangeBounds<BlockNumber>,
618 ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
619 self.consistent_provider()?.transactions_by_block_range(range)
620 }
621
622 fn transactions_by_tx_range(
623 &self,
624 range: impl RangeBounds<TxNumber>,
625 ) -> ProviderResult<Vec<Self::Transaction>> {
626 self.consistent_provider()?.transactions_by_tx_range(range)
627 }
628
629 fn senders_by_tx_range(
630 &self,
631 range: impl RangeBounds<TxNumber>,
632 ) -> ProviderResult<Vec<Address>> {
633 self.consistent_provider()?.senders_by_tx_range(range)
634 }
635
636 fn transaction_sender(&self, id: TxNumber) -> ProviderResult<Option<Address>> {
637 self.consistent_provider()?.transaction_sender(id)
638 }
639}
640
641impl<N: ProviderNodeTypes> ReceiptProvider for BlockchainProvider<N> {
642 type Receipt = ReceiptTy<N>;
643
644 fn receipt(&self, id: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
645 self.consistent_provider()?.receipt(id)
646 }
647
648 fn receipt_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
649 self.consistent_provider()?.receipt_by_hash(hash)
650 }
651
652 fn receipts_by_block(
653 &self,
654 block: BlockHashOrNumber,
655 ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
656 self.consistent_provider()?.receipts_by_block(block)
657 }
658
659 fn receipts_by_tx_range(
660 &self,
661 range: impl RangeBounds<TxNumber>,
662 ) -> ProviderResult<Vec<Self::Receipt>> {
663 self.consistent_provider()?.receipts_by_tx_range(range)
664 }
665
666 fn receipts_by_block_range(
667 &self,
668 block_range: RangeInclusive<BlockNumber>,
669 ) -> ProviderResult<Vec<Vec<Self::Receipt>>> {
670 self.consistent_provider()?.receipts_by_block_range(block_range)
671 }
672}
673
674impl<N: ProviderNodeTypes> ReceiptProviderIdExt for BlockchainProvider<N> {
675 fn receipts_by_block_id(&self, block: BlockId) -> ProviderResult<Option<Vec<Self::Receipt>>> {
676 self.consistent_provider()?.receipts_by_block_id(block)
677 }
678}
679
680impl<N: ProviderNodeTypes> BlockBodyIndicesProvider for BlockchainProvider<N> {
681 fn block_body_indices(
682 &self,
683 number: BlockNumber,
684 ) -> ProviderResult<Option<StoredBlockBodyIndices>> {
685 self.consistent_provider()?.block_body_indices(number)
686 }
687
688 fn block_body_indices_range(
689 &self,
690 range: RangeInclusive<BlockNumber>,
691 ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
692 self.consistent_provider()?.block_body_indices_range(range)
693 }
694}
695
696impl<N: ProviderNodeTypes> StageCheckpointReader for BlockchainProvider<N> {
697 fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
698 self.consistent_provider()?.get_stage_checkpoint(id)
699 }
700
701 fn get_stage_checkpoint_progress(&self, id: StageId) -> ProviderResult<Option<Vec<u8>>> {
702 self.consistent_provider()?.get_stage_checkpoint_progress(id)
703 }
704
705 fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
706 self.consistent_provider()?.get_all_checkpoints()
707 }
708}
709
710impl<N: ProviderNodeTypes> PruneCheckpointReader for BlockchainProvider<N> {
711 fn get_prune_checkpoint(
712 &self,
713 segment: PruneSegment,
714 ) -> ProviderResult<Option<PruneCheckpoint>> {
715 self.consistent_provider()?.get_prune_checkpoint(segment)
716 }
717
718 fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
719 self.consistent_provider()?.get_prune_checkpoints()
720 }
721}
722
723impl<N: NodeTypesWithDB> ChainSpecProvider for BlockchainProvider<N> {
724 type ChainSpec = N::ChainSpec;
725
726 fn chain_spec(&self) -> Arc<N::ChainSpec> {
727 self.database.chain_spec()
728 }
729}
730
731impl<N: ProviderNodeTypes> StateProviderFactory for BlockchainProvider<N> {
732 fn latest(&self) -> ProviderResult<StateProviderBox> {
734 trace!(target: "providers::blockchain", "Getting latest block state provider");
735 if let Some(state) = self.canonical_in_memory_state.head_state() {
737 trace!(target: "providers::blockchain", "Using head state for latest state provider");
738 Ok(self.block_state_provider(&state)?.boxed())
739 } else {
740 trace!(target: "providers::blockchain", "Using database state for latest state provider");
741 self.database.latest()
742 }
743 }
744
745 fn state_by_block_number_or_tag(
747 &self,
748 number_or_tag: BlockNumberOrTag,
749 ) -> ProviderResult<StateProviderBox> {
750 match number_or_tag {
751 BlockNumberOrTag::Latest => self.latest(),
752 BlockNumberOrTag::Finalized => {
753 let hash =
755 self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
756 self.state_by_block_hash(hash)
757 }
758 BlockNumberOrTag::Safe => {
759 let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
761 self.state_by_block_hash(hash)
762 }
763 BlockNumberOrTag::Earliest => {
764 self.history_by_block_number(self.earliest_block_number()?)
765 }
766 BlockNumberOrTag::Pending => self.pending(),
767 BlockNumberOrTag::Number(num) => {
768 let hash = self
769 .block_hash(num)?
770 .ok_or_else(|| ProviderError::HeaderNotFound(num.into()))?;
771 self.state_by_block_hash(hash)
772 }
773 }
774 }
775
776 fn history_by_block_number(
777 &self,
778 block_number: BlockNumber,
779 ) -> ProviderResult<StateProviderBox> {
780 trace!(target: "providers::blockchain", ?block_number, "Getting history by block number");
781 let provider = self.consistent_provider()?;
782 let hash = provider
783 .block_hash(block_number)?
784 .ok_or_else(|| ProviderError::HeaderNotFound(block_number.into()))?;
785 provider.into_state_provider_at_block_hash(hash)
786 }
787
788 fn history_by_block_hash(&self, block_hash: BlockHash) -> ProviderResult<StateProviderBox> {
789 trace!(target: "providers::blockchain", ?block_hash, "Getting history by block hash");
790 self.consistent_provider()?.into_state_provider_at_block_hash(block_hash)
791 }
792
793 fn state_by_block_hash(&self, hash: BlockHash) -> ProviderResult<StateProviderBox> {
794 trace!(target: "providers::blockchain", ?hash, "Getting state by block hash");
795 if let Ok(state) = self.history_by_block_hash(hash) {
796 Ok(state)
798 } else if let Ok(Some(pending)) = self.pending_state_by_hash(hash) {
799 Ok(pending)
801 } else {
802 Err(ProviderError::StateForHashNotFound(hash))
804 }
805 }
806
807 fn pending(&self) -> ProviderResult<StateProviderBox> {
812 trace!(target: "providers::blockchain", "Getting provider for pending state");
813
814 if let Some(pending) = self.canonical_in_memory_state.pending_state() {
815 return Ok(Box::new(self.block_state_provider(&pending)?));
817 }
818
819 self.latest()
821 }
822
823 fn pending_state_by_hash(&self, block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
824 if let Some(pending) = self.canonical_in_memory_state.pending_state() &&
825 pending.hash() == block_hash
826 {
827 return Ok(Some(Box::new(self.block_state_provider(&pending)?)));
828 }
829 Ok(None)
830 }
831
832 fn maybe_pending(&self) -> ProviderResult<Option<StateProviderBox>> {
833 if let Some(pending) = self.canonical_in_memory_state.pending_state() {
834 return Ok(Some(Box::new(self.block_state_provider(&pending)?)))
835 }
836
837 Ok(None)
838 }
839}
840
841impl<N: NodeTypesWithDB> HashedPostStateProvider for BlockchainProvider<N> {
842 fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState {
843 HashedPostState::from_bundle_state::<KeccakKeyHasher>(bundle_state.state())
844 }
845}
846
847impl<N: ProviderNodeTypes> CanonChainTracker for BlockchainProvider<N> {
848 type Header = HeaderTy<N>;
849
850 fn on_forkchoice_update_received(&self, _update: &ForkchoiceState) {
851 self.canonical_in_memory_state.on_forkchoice_update_received();
853 }
854
855 fn last_received_update_timestamp(&self) -> Option<Instant> {
856 self.canonical_in_memory_state.last_received_update_timestamp()
857 }
858
859 fn set_canonical_head(&self, header: SealedHeader<Self::Header>) {
860 self.canonical_in_memory_state.set_canonical_head(header);
861 }
862
863 fn set_safe(&self, header: SealedHeader<Self::Header>) {
864 self.canonical_in_memory_state.set_safe(header);
865 }
866
867 fn set_finalized(&self, header: SealedHeader<Self::Header>) {
868 self.canonical_in_memory_state.set_finalized(header);
869 }
870}
871
872impl<N: ProviderNodeTypes> BlockReaderIdExt for BlockchainProvider<N>
873where
874 Self: ReceiptProviderIdExt,
875{
876 fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>> {
877 self.consistent_provider()?.block_by_id(id)
878 }
879
880 fn header_by_number_or_tag(
881 &self,
882 id: BlockNumberOrTag,
883 ) -> ProviderResult<Option<Self::Header>> {
884 self.consistent_provider()?.header_by_number_or_tag(id)
885 }
886
887 fn sealed_header_by_number_or_tag(
888 &self,
889 id: BlockNumberOrTag,
890 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
891 self.consistent_provider()?.sealed_header_by_number_or_tag(id)
892 }
893
894 fn sealed_header_by_id(
895 &self,
896 id: BlockId,
897 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
898 self.consistent_provider()?.sealed_header_by_id(id)
899 }
900
901 fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>> {
902 self.consistent_provider()?.header_by_id(id)
903 }
904}
905
906impl<N: ProviderNodeTypes> CanonStateSubscriptions for BlockchainProvider<N> {
907 fn subscribe_to_canonical_state(&self) -> CanonStateNotifications<Self::Primitives> {
908 self.canonical_in_memory_state.subscribe_canon_state()
909 }
910}
911
912impl<N: ProviderNodeTypes> ForkChoiceSubscriptions for BlockchainProvider<N> {
913 type Header = HeaderTy<N>;
914
915 fn subscribe_safe_block(&self) -> ForkChoiceNotifications<Self::Header> {
916 let receiver = self.canonical_in_memory_state.subscribe_safe_block();
917 ForkChoiceNotifications(receiver)
918 }
919
920 fn subscribe_finalized_block(&self) -> ForkChoiceNotifications<Self::Header> {
921 let receiver = self.canonical_in_memory_state.subscribe_finalized_block();
922 ForkChoiceNotifications(receiver)
923 }
924}
925
926impl<N: ProviderNodeTypes> PersistedBlockSubscriptions for BlockchainProvider<N> {
927 fn subscribe_persisted_block(&self) -> PersistedBlockNotifications {
928 let receiver = self.canonical_in_memory_state.subscribe_persisted_block();
929 PersistedBlockNotifications(receiver)
930 }
931}
932
933impl<N: ProviderNodeTypes> StorageChangeSetReader for BlockchainProvider<N> {
934 fn storage_changeset(
935 &self,
936 block_number: BlockNumber,
937 ) -> ProviderResult<Vec<(BlockNumberAddress, StorageEntry)>> {
938 self.consistent_provider()?.storage_changeset(block_number)
939 }
940
941 fn get_storage_before_block(
942 &self,
943 block_number: BlockNumber,
944 address: Address,
945 storage_key: B256,
946 ) -> ProviderResult<Option<StorageEntry>> {
947 self.consistent_provider()?.get_storage_before_block(block_number, address, storage_key)
948 }
949
950 fn storage_changesets_range(
951 &self,
952 range: impl RangeBounds<BlockNumber>,
953 ) -> ProviderResult<Vec<(BlockNumberAddress, StorageEntry)>> {
954 self.consistent_provider()?.storage_changesets_range(range)
955 }
956}
957
958impl<N: ProviderNodeTypes> ChangeSetReader for BlockchainProvider<N> {
959 fn account_block_changeset(
960 &self,
961 block_number: BlockNumber,
962 ) -> ProviderResult<Vec<AccountBeforeTx>> {
963 self.consistent_provider()?.account_block_changeset(block_number)
964 }
965
966 fn get_account_before_block(
967 &self,
968 block_number: BlockNumber,
969 address: Address,
970 ) -> ProviderResult<Option<AccountBeforeTx>> {
971 self.consistent_provider()?.get_account_before_block(block_number, address)
972 }
973
974 fn account_changesets_range(
975 &self,
976 range: impl core::ops::RangeBounds<BlockNumber>,
977 ) -> ProviderResult<Vec<(BlockNumber, AccountBeforeTx)>> {
978 self.consistent_provider()?.account_changesets_range(range)
979 }
980}
981
982impl<N: ProviderNodeTypes> AccountReader for BlockchainProvider<N> {
983 fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
985 self.consistent_provider()?.basic_account(address)
986 }
987}
988
989impl<N: ProviderNodeTypes> StateReader for BlockchainProvider<N> {
990 type Receipt = ReceiptTy<N>;
991
992 fn get_state(
1002 &self,
1003 block: BlockNumber,
1004 ) -> ProviderResult<Option<ExecutionOutcome<Self::Receipt>>> {
1005 self.consistent_provider()?.get_state(block)
1006 }
1007}
1008
1009#[cfg(test)]
1010mod tests {
1011 use super::SNAPSHOT_STATE_RETENTION;
1012 use crate::{
1013 providers::BlockchainProvider,
1014 test_utils::{
1015 create_test_provider_factory, create_test_provider_factory_with_chain_spec,
1016 MockNodeTypesWithDB,
1017 },
1018 BlockWriter, CanonChainTracker, ProviderFactory, SaveBlocksInput,
1019 };
1020 use alloy_consensus::constants::EMPTY_ROOT_HASH;
1021 use alloy_eips::{BlockHashOrNumber, BlockNumHash, BlockNumberOrTag};
1022 use alloy_primitives::{keccak256, Address, BlockNumber, TxNumber, B256, U256};
1023 use itertools::Itertools;
1024 use rand::Rng;
1025 use reth_chain_state::{
1026 test_utils::TestBlockBuilder, CanonStateNotification, CanonStateSubscriptions,
1027 CanonicalInMemoryState, ExecutedBlock, NewCanonicalChain,
1028 };
1029 use reth_chainspec::{ChainSpec, MAINNET};
1030 use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices};
1031 use reth_errors::ProviderError;
1032 use reth_ethereum_primitives::{Block, Receipt};
1033 use reth_execution_types::{
1034 BlockExecutionOutput, BlockExecutionResult, Chain, ExecutionOutcome,
1035 };
1036 use reth_primitives_traits::{
1037 Account, Block as _, RecoveredBlock, SealedBlock, SignerRecoverable, StorageEntry,
1038 };
1039 use reth_stages_types::{StageCheckpoint, StageId};
1040 use reth_storage_api::{
1041 BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader,
1042 BlockReaderIdExt, BlockSource, ChangeSetReader, DBProvider, DatabaseProviderFactory,
1043 HashingWriter, HeaderProvider, RangeEnd, ReceiptProvider, ReceiptProviderIdExt,
1044 StageCheckpointWriter, StateProviderFactory, StateRangeProvider, StateRangeProviderFactory,
1045 StateRootProvider, StateWriteConfig, StateWriter, StorageRootProvider, TransactionVariant,
1046 TransactionsProvider,
1047 };
1048 use reth_testing_utils::generators::{
1049 self, random_block, random_block_range, random_changeset_range, random_eoa_accounts,
1050 random_receipt, BlockParams, BlockRangeParams,
1051 };
1052 use reth_trie::{updates::TrieUpdates, ComputedTrieData, HashedPostState, HashedStorage};
1053 use revm::database::{BundleState, OriginalValuesKnown};
1054 use std::{
1055 collections::{BTreeMap, HashMap},
1056 ops::{Bound, Range, RangeBounds},
1057 sync::Arc,
1058 };
1059
1060 const TEST_BLOCKS_COUNT: usize = 5;
1061
1062 const TEST_TRANSACTIONS_COUNT: u8 = 4;
1063
1064 fn random_blocks(
1065 rng: &mut impl Rng,
1066 database_blocks: usize,
1067 in_memory_blocks: usize,
1068 requests_count: Option<Range<u8>>,
1069 withdrawals_count: Option<Range<u8>>,
1070 tx_count: impl RangeBounds<u8>,
1071 ) -> (Vec<SealedBlock<Block>>, Vec<SealedBlock<Block>>) {
1072 let block_range = (database_blocks + in_memory_blocks - 1) as u64;
1073
1074 let tx_start = match tx_count.start_bound() {
1075 Bound::Included(&n) | Bound::Excluded(&n) => n,
1076 Bound::Unbounded => u8::MIN,
1077 };
1078 let tx_end = match tx_count.end_bound() {
1079 Bound::Included(&n) | Bound::Excluded(&n) => n + 1,
1080 Bound::Unbounded => u8::MAX,
1081 };
1082
1083 let blocks = random_block_range(
1084 rng,
1085 0..=block_range,
1086 BlockRangeParams {
1087 parent: Some(B256::ZERO),
1088 tx_count: tx_start..tx_end,
1089 requests_count,
1090 withdrawals_count,
1091 },
1092 );
1093 let (database_blocks, in_memory_blocks) = blocks.split_at(database_blocks);
1094 (database_blocks.to_vec(), in_memory_blocks.to_vec())
1095 }
1096
1097 #[expect(clippy::type_complexity)]
1098 fn provider_with_chain_spec_and_random_blocks(
1099 rng: &mut impl Rng,
1100 chain_spec: Arc<ChainSpec>,
1101 database_blocks: usize,
1102 in_memory_blocks: usize,
1103 block_range_params: BlockRangeParams,
1104 ) -> eyre::Result<(
1105 BlockchainProvider<MockNodeTypesWithDB>,
1106 Vec<SealedBlock<Block>>,
1107 Vec<SealedBlock<Block>>,
1108 Vec<Vec<Receipt>>,
1109 )> {
1110 let (database_blocks, in_memory_blocks) = random_blocks(
1111 rng,
1112 database_blocks,
1113 in_memory_blocks,
1114 block_range_params.requests_count,
1115 block_range_params.withdrawals_count,
1116 block_range_params.tx_count,
1117 );
1118
1119 let receipts: Vec<Vec<_>> = database_blocks
1120 .iter()
1121 .chain(in_memory_blocks.iter())
1122 .map(|block| block.body().transactions.iter())
1123 .map(|tx| tx.map(|tx| random_receipt(rng, tx, Some(2), None)).collect())
1124 .collect();
1125
1126 let factory = create_test_provider_factory_with_chain_spec(chain_spec);
1127 let provider_rw = factory.database_provider_rw()?;
1128
1129 for block in &database_blocks {
1131 provider_rw.insert_block(
1132 &block.clone().try_recover().expect("failed to seal block with senders"),
1133 )?;
1134 }
1135
1136 if let Some(first_block) = database_blocks.first() {
1138 provider_rw.write_state(
1139 &ExecutionOutcome {
1140 first_block: first_block.number,
1141 receipts: receipts.iter().take(database_blocks.len()).cloned().collect(),
1142 ..Default::default()
1143 },
1144 OriginalValuesKnown::No,
1145 StateWriteConfig::default(),
1146 )?;
1147 }
1148
1149 provider_rw.commit()?;
1150
1151 let provider = BlockchainProvider::new(factory)?;
1152
1153 let chain = NewCanonicalChain::Commit {
1155 new: in_memory_blocks
1156 .iter()
1157 .map(|block| {
1158 let senders = block.senders().expect("failed to recover senders");
1159 let block_receipts = receipts.get(block.number as usize).unwrap().clone();
1160 let execution_outcome = BlockExecutionOutput {
1161 result: BlockExecutionResult {
1162 receipts: block_receipts,
1163 requests: Default::default(),
1164 gas_used: 0,
1165 blob_gas_used: 0,
1166 },
1167 state: BundleState::default(),
1168 };
1169
1170 ExecutedBlock {
1171 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1172 block.clone(),
1173 senders,
1174 )),
1175 execution_output: execution_outcome.into(),
1176 ..Default::default()
1177 }
1178 })
1179 .collect(),
1180 };
1181 provider.canonical_in_memory_state.update_chain(chain);
1182
1183 let blocks = database_blocks.iter().chain(in_memory_blocks.iter()).collect::<Vec<_>>();
1185 let block_count = blocks.len();
1186 let canonical_block = blocks.get(block_count - 1).unwrap();
1187 let safe_block = blocks.get(block_count - 2).unwrap();
1188 let finalized_block = blocks.get(block_count - 3).unwrap();
1189
1190 provider.set_canonical_head(canonical_block.clone_sealed_header());
1192 provider.set_safe(safe_block.clone_sealed_header());
1193 provider.set_finalized(finalized_block.clone_sealed_header());
1194
1195 Ok((provider, database_blocks.clone(), in_memory_blocks.clone(), receipts))
1196 }
1197
1198 #[expect(clippy::type_complexity)]
1199 fn provider_with_random_blocks(
1200 rng: &mut impl Rng,
1201 database_blocks: usize,
1202 in_memory_blocks: usize,
1203 block_range_params: BlockRangeParams,
1204 ) -> eyre::Result<(
1205 BlockchainProvider<MockNodeTypesWithDB>,
1206 Vec<SealedBlock<Block>>,
1207 Vec<SealedBlock<Block>>,
1208 Vec<Vec<Receipt>>,
1209 )> {
1210 provider_with_chain_spec_and_random_blocks(
1211 rng,
1212 MAINNET.clone(),
1213 database_blocks,
1214 in_memory_blocks,
1215 block_range_params,
1216 )
1217 }
1218
1219 fn persist_block_after_db_tx_creation(
1225 provider: BlockchainProvider<MockNodeTypesWithDB>,
1226 block_number: BlockNumber,
1227 ) {
1228 let hook_provider = provider.clone();
1229 provider.database.db_ref().set_post_transaction_hook(Box::new(move || {
1230 if let Some(state) = hook_provider.canonical_in_memory_state.head_state() &&
1231 state.anchor().number + 1 == block_number
1232 {
1233 let mut lowest_memory_block =
1234 state.parent_state_chain().last().expect("qed").block();
1235 let num_hash = lowest_memory_block.recovered_block().num_hash();
1236
1237 let execution_output = (*lowest_memory_block.execution_output).clone();
1238 lowest_memory_block.execution_output = Arc::new(execution_output);
1239
1240 let provider_rw = hook_provider.database_provider_rw().unwrap();
1242 let input = SaveBlocksInput::new(
1243 vec![lowest_memory_block],
1244 state.anchor().number,
1245 state.anchor().number,
1246 block_number,
1247 block_number,
1248 );
1249 provider_rw.save_blocks(&input).unwrap();
1250 provider_rw.commit().unwrap();
1251
1252 hook_provider.canonical_in_memory_state.remove_persisted_blocks(num_hash);
1254 }
1255 }));
1256 }
1257
1258 #[test]
1259 fn test_block_reader_find_block_by_hash() -> eyre::Result<()> {
1260 let mut rng = generators::rng();
1262 let factory = create_test_provider_factory();
1263
1264 let blocks = random_block_range(
1266 &mut rng,
1267 0..=10,
1268 BlockRangeParams { parent: Some(B256::ZERO), tx_count: 0..1, ..Default::default() },
1269 );
1270 let (database_blocks, in_memory_blocks) = blocks.split_at(5);
1271
1272 let provider_rw = factory.provider_rw()?;
1274 for block in database_blocks {
1275 provider_rw.insert_block(
1276 &block.clone().try_recover().expect("failed to seal block with senders"),
1277 )?;
1278 }
1279
1280 provider_rw.commit()?;
1281
1282 let provider = BlockchainProvider::new(factory)?;
1284
1285 let first_db_block = database_blocks.first().unwrap();
1287 let first_in_mem_block = in_memory_blocks.first().unwrap();
1288 let last_in_mem_block = in_memory_blocks.last().unwrap();
1289
1290 assert_eq!(provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Any)?, None);
1292 assert_eq!(
1293 provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Canonical)?,
1294 None
1295 );
1296 assert_eq!(
1298 provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Pending)?,
1299 None
1300 );
1301
1302 let in_memory_block_senders =
1304 first_in_mem_block.senders().expect("failed to recover senders");
1305 let chain = NewCanonicalChain::Commit {
1306 new: vec![ExecutedBlock {
1307 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1308 first_in_mem_block.clone(),
1309 in_memory_block_senders,
1310 )),
1311 ..Default::default()
1312 }],
1313 };
1314 provider.canonical_in_memory_state.update_chain(chain);
1315
1316 assert_eq!(
1318 provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Any)?,
1319 Some(first_in_mem_block.clone().into_block())
1320 );
1321 assert_eq!(
1322 provider.find_block_by_hash(first_in_mem_block.hash(), BlockSource::Canonical)?,
1323 Some(first_in_mem_block.clone().into_block())
1324 );
1325
1326 assert_eq!(
1328 provider.find_block_by_hash(first_db_block.hash(), BlockSource::Any)?,
1329 Some(first_db_block.clone().into_block())
1330 );
1331 assert_eq!(
1332 provider.find_block_by_hash(first_db_block.hash(), BlockSource::Canonical)?,
1333 Some(first_db_block.clone().into_block())
1334 );
1335
1336 assert_eq!(provider.find_block_by_hash(first_db_block.hash(), BlockSource::Pending)?, None);
1338
1339 provider.canonical_in_memory_state.set_pending_block(ExecutedBlock {
1341 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1342 last_in_mem_block.clone(),
1343 Default::default(),
1344 )),
1345 ..Default::default()
1346 });
1347
1348 assert_eq!(
1350 provider.find_block_by_hash(last_in_mem_block.hash(), BlockSource::Pending)?,
1351 Some(last_in_mem_block.clone().into_block())
1352 );
1353
1354 Ok(())
1355 }
1356
1357 #[test]
1358 fn test_block_reader_block() -> eyre::Result<()> {
1359 let mut rng = generators::rng();
1361 let factory = create_test_provider_factory();
1362
1363 let blocks = random_block_range(
1365 &mut rng,
1366 0..=10,
1367 BlockRangeParams { parent: Some(B256::ZERO), tx_count: 0..1, ..Default::default() },
1368 );
1369 let (database_blocks, in_memory_blocks) = blocks.split_at(5);
1370
1371 let provider_rw = factory.provider_rw()?;
1373 for block in database_blocks {
1374 provider_rw.insert_block(
1375 &block.clone().try_recover().expect("failed to seal block with senders"),
1376 )?;
1377 }
1378 provider_rw.commit()?;
1379
1380 let provider = BlockchainProvider::new(factory)?;
1382
1383 let first_in_mem_block = in_memory_blocks.first().unwrap();
1385 let first_db_block = database_blocks.first().unwrap();
1387
1388 assert_eq!(provider.block(BlockHashOrNumber::Hash(first_in_mem_block.hash()))?, None);
1390 assert_eq!(provider.block(BlockHashOrNumber::Number(first_in_mem_block.number))?, None);
1391
1392 let in_memory_block_senders =
1394 first_in_mem_block.senders().expect("failed to recover senders");
1395 let chain = NewCanonicalChain::Commit {
1396 new: vec![ExecutedBlock {
1397 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1398 first_in_mem_block.clone(),
1399 in_memory_block_senders,
1400 )),
1401 ..Default::default()
1402 }],
1403 };
1404 provider.canonical_in_memory_state.update_chain(chain);
1405
1406 assert_eq!(
1408 provider.block(BlockHashOrNumber::Hash(first_in_mem_block.hash()))?,
1409 Some(first_in_mem_block.clone().into_block())
1410 );
1411 assert_eq!(
1412 provider.block(BlockHashOrNumber::Number(first_in_mem_block.number))?,
1413 Some(first_in_mem_block.clone().into_block())
1414 );
1415
1416 assert_eq!(
1418 provider.block(BlockHashOrNumber::Hash(first_db_block.hash()))?,
1419 Some(first_db_block.clone().into_block())
1420 );
1421 assert_eq!(
1422 provider.block(BlockHashOrNumber::Number(first_db_block.number))?,
1423 Some(first_db_block.clone().into_block())
1424 );
1425
1426 Ok(())
1427 }
1428
1429 #[test]
1430 fn test_block_reader_pending_block() -> eyre::Result<()> {
1431 let mut rng = generators::rng();
1432 let (provider, _, _, _) = provider_with_random_blocks(
1433 &mut rng,
1434 TEST_BLOCKS_COUNT,
1435 TEST_BLOCKS_COUNT,
1436 BlockRangeParams::default(),
1437 )?;
1438
1439 let mut rng = generators::rng();
1441 let block = random_block(
1442 &mut rng,
1443 0,
1444 BlockParams { parent: Some(B256::ZERO), ..Default::default() },
1445 );
1446
1447 provider.canonical_in_memory_state.set_pending_block(ExecutedBlock {
1449 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1450 block.clone(),
1451 block.senders().unwrap(),
1452 )),
1453 ..Default::default()
1454 });
1455
1456 assert_eq!(
1459 provider.pending_block()?,
1460 Some(RecoveredBlock::new_sealed(block.clone(), block.senders().unwrap()))
1461 );
1462
1463 assert_eq!(
1464 provider.pending_block_and_receipts()?,
1465 Some((RecoveredBlock::new_sealed(block.clone(), block.senders().unwrap()), vec![]))
1466 );
1467
1468 Ok(())
1469 }
1470
1471 #[test]
1472 fn test_block_body_indices() -> eyre::Result<()> {
1473 let mut rng = generators::rng();
1475 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1476 &mut rng,
1477 TEST_BLOCKS_COUNT,
1478 TEST_BLOCKS_COUNT,
1479 BlockRangeParams {
1480 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
1481 ..Default::default()
1482 },
1483 )?;
1484
1485 let first_in_mem_block = in_memory_blocks.first().unwrap();
1486
1487 let in_memory_block_senders =
1489 first_in_mem_block.senders().expect("failed to recover senders");
1490 let chain = NewCanonicalChain::Commit {
1491 new: vec![ExecutedBlock {
1492 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1493 first_in_mem_block.clone(),
1494 in_memory_block_senders,
1495 )),
1496 ..Default::default()
1497 }],
1498 };
1499 provider.canonical_in_memory_state.update_chain(chain);
1500
1501 let first_db_block = database_blocks.first().unwrap().clone();
1502 let first_in_mem_block = in_memory_blocks.first().unwrap().clone();
1503
1504 assert_eq!(
1506 provider.block_body_indices(first_db_block.number)?.unwrap(),
1507 StoredBlockBodyIndices { first_tx_num: 0, tx_count: 4 }
1508 );
1509
1510 assert_eq!(
1513 provider.block_body_indices(first_in_mem_block.number)?.unwrap(),
1514 StoredBlockBodyIndices { first_tx_num: 20, tx_count: 4 }
1515 );
1516
1517 let mut rng = rand::rng();
1519 let random_block_number: u64 = rng.random();
1520 assert_eq!(provider.block_body_indices(random_block_number)?, None);
1521
1522 Ok(())
1523 }
1524
1525 #[test]
1526 fn test_block_hash_reader() -> eyre::Result<()> {
1527 let mut rng = generators::rng();
1528 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1529 &mut rng,
1530 TEST_BLOCKS_COUNT,
1531 TEST_BLOCKS_COUNT,
1532 BlockRangeParams::default(),
1533 )?;
1534
1535 let database_block = database_blocks.first().unwrap().clone();
1536 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1537
1538 assert_eq!(provider.block_hash(database_block.number)?, Some(database_block.hash()));
1539 assert_eq!(provider.block_hash(in_memory_block.number)?, Some(in_memory_block.hash()));
1540
1541 assert_eq!(
1542 provider.canonical_hashes_range(0, 10)?,
1543 [database_blocks, in_memory_blocks]
1544 .concat()
1545 .iter()
1546 .map(|block| block.hash())
1547 .collect::<Vec<_>>()
1548 );
1549
1550 Ok(())
1551 }
1552
1553 #[test]
1554 fn test_header_provider() -> eyre::Result<()> {
1555 let mut rng = generators::rng();
1556 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1557 &mut rng,
1558 TEST_BLOCKS_COUNT,
1559 TEST_BLOCKS_COUNT,
1560 BlockRangeParams::default(),
1561 )?;
1562
1563 let finalized_block = database_blocks.get(database_blocks.len() - 3).unwrap();
1565 provider.set_finalized(finalized_block.clone_sealed_header());
1566
1567 let blocks = [database_blocks, in_memory_blocks].concat();
1568
1569 assert_eq!(
1570 provider.sealed_headers_while(0..=10, |header| header.number <= 8)?,
1571 blocks
1572 .iter()
1573 .take_while(|header| header.number <= 8)
1574 .map(|b| b.clone_sealed_header())
1575 .collect::<Vec<_>>()
1576 );
1577
1578 Ok(())
1579 }
1580
1581 #[tokio::test]
1582 async fn test_canon_state_subscriptions() -> eyre::Result<()> {
1583 let factory = create_test_provider_factory();
1584
1585 let mut test_block_builder = TestBlockBuilder::eth();
1587 let block_1 = test_block_builder.generate_random_block(0, B256::ZERO).try_recover()?;
1588 let block_hash_1 = block_1.hash();
1589
1590 let provider_rw = factory.provider_rw()?;
1592 provider_rw.insert_block(&block_1)?;
1593 provider_rw.commit()?;
1594
1595 let provider = BlockchainProvider::new(factory)?;
1596
1597 let in_memory_state = provider.canonical_in_memory_state();
1599 let mut rx_1 = provider.subscribe_to_canonical_state();
1600 let mut rx_2 = provider.subscribe_to_canonical_state();
1601
1602 let block_2 = test_block_builder.generate_random_block(1, block_hash_1).try_recover()?;
1604 let chain = Chain::new(vec![block_2], ExecutionOutcome::default(), BTreeMap::new());
1605 let commit = CanonStateNotification::Commit { new: Arc::new(chain.clone()) };
1606 in_memory_state.notify_canon_state(commit.clone());
1607 let (notification_1, notification_2) = tokio::join!(rx_1.recv(), rx_2.recv());
1608 assert_eq!(notification_1, Ok(commit.clone()));
1609 assert_eq!(notification_2, Ok(commit.clone()));
1610
1611 let block_3 = test_block_builder.generate_random_block(1, block_hash_1).try_recover()?;
1613 let block_4 = test_block_builder.generate_random_block(2, block_3.hash()).try_recover()?;
1614 let new_chain =
1615 Chain::new(vec![block_3, block_4], ExecutionOutcome::default(), BTreeMap::new());
1616 let re_org =
1617 CanonStateNotification::Reorg { old: Arc::new(chain), new: Arc::new(new_chain) };
1618 in_memory_state.notify_canon_state(re_org.clone());
1619 let (notification_1, notification_2) = tokio::join!(rx_1.recv(), rx_2.recv());
1620 assert_eq!(notification_1, Ok(re_org.clone()));
1621 assert_eq!(notification_2, Ok(re_org.clone()));
1622
1623 Ok(())
1624 }
1625
1626 #[test]
1627 fn test_block_num_reader() -> eyre::Result<()> {
1628 let mut rng = generators::rng();
1629 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1630 &mut rng,
1631 TEST_BLOCKS_COUNT,
1632 TEST_BLOCKS_COUNT,
1633 BlockRangeParams::default(),
1634 )?;
1635
1636 assert_eq!(provider.best_block_number()?, in_memory_blocks.last().unwrap().number);
1637 assert_eq!(provider.last_block_number()?, database_blocks.last().unwrap().number);
1638
1639 let database_block = database_blocks.first().unwrap().clone();
1640 let in_memory_block = in_memory_blocks.first().unwrap().clone();
1641 assert_eq!(provider.block_number(database_block.hash())?, Some(database_block.number));
1642 assert_eq!(provider.block_number(in_memory_block.hash())?, Some(in_memory_block.number));
1643
1644 Ok(())
1645 }
1646
1647 #[test]
1648 fn test_block_reader_id_ext_block_by_id() -> eyre::Result<()> {
1649 let mut rng = generators::rng();
1650 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1651 &mut rng,
1652 TEST_BLOCKS_COUNT,
1653 TEST_BLOCKS_COUNT,
1654 BlockRangeParams::default(),
1655 )?;
1656
1657 let database_block = database_blocks.first().unwrap().clone();
1658 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1659
1660 let block_number = database_block.number;
1661 let block_hash = database_block.hash();
1662
1663 assert_eq!(
1664 provider.block_by_id(block_number.into()).unwrap(),
1665 Some(database_block.clone().into_block())
1666 );
1667 assert_eq!(
1668 provider.block_by_id(block_hash.into()).unwrap(),
1669 Some(database_block.into_block())
1670 );
1671
1672 let block_number = in_memory_block.number;
1673 let block_hash = in_memory_block.hash();
1674 assert_eq!(
1675 provider.block_by_id(block_number.into()).unwrap(),
1676 Some(in_memory_block.clone().into_block())
1677 );
1678 assert_eq!(
1679 provider.block_by_id(block_hash.into()).unwrap(),
1680 Some(in_memory_block.into_block())
1681 );
1682
1683 Ok(())
1684 }
1685
1686 #[test]
1687 fn test_block_reader_id_ext_header_by_number_or_tag() -> eyre::Result<()> {
1688 let mut rng = generators::rng();
1689 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1690 &mut rng,
1691 TEST_BLOCKS_COUNT,
1692 TEST_BLOCKS_COUNT,
1693 BlockRangeParams::default(),
1694 )?;
1695
1696 let database_block = database_blocks.first().unwrap().clone();
1697
1698 let in_memory_block_count = in_memory_blocks.len();
1699 let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
1700 let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
1701 let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();
1702
1703 let block_number = database_block.number;
1704 assert_eq!(
1705 provider.header_by_number_or_tag(block_number.into()).unwrap(),
1706 Some(database_block.header().clone())
1707 );
1708 assert_eq!(
1709 provider.sealed_header_by_number_or_tag(block_number.into())?,
1710 Some(database_block.clone_sealed_header())
1711 );
1712
1713 assert_eq!(
1714 provider.header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
1715 Some(canonical_block.header().clone())
1716 );
1717 assert_eq!(
1718 provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Latest).unwrap(),
1719 Some(canonical_block.clone_sealed_header())
1720 );
1721
1722 assert_eq!(
1723 provider.header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
1724 Some(safe_block.header().clone())
1725 );
1726 assert_eq!(
1727 provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Safe).unwrap(),
1728 Some(safe_block.clone_sealed_header())
1729 );
1730
1731 assert_eq!(
1732 provider.header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
1733 Some(finalized_block.header().clone())
1734 );
1735 assert_eq!(
1736 provider.sealed_header_by_number_or_tag(BlockNumberOrTag::Finalized).unwrap(),
1737 Some(finalized_block.clone_sealed_header())
1738 );
1739
1740 Ok(())
1741 }
1742
1743 #[test]
1744 fn test_block_reader_id_ext_header_by_id() -> eyre::Result<()> {
1745 let mut rng = generators::rng();
1746 let (provider, database_blocks, in_memory_blocks, _) = provider_with_random_blocks(
1747 &mut rng,
1748 TEST_BLOCKS_COUNT,
1749 TEST_BLOCKS_COUNT,
1750 BlockRangeParams::default(),
1751 )?;
1752
1753 let database_block = database_blocks.first().unwrap().clone();
1754 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1755
1756 let block_number = database_block.number;
1757 let block_hash = database_block.hash();
1758
1759 assert_eq!(
1760 provider.header_by_id(block_number.into()).unwrap(),
1761 Some(database_block.header().clone())
1762 );
1763 assert_eq!(
1764 provider.sealed_header_by_id(block_number.into()).unwrap(),
1765 Some(database_block.clone_sealed_header())
1766 );
1767
1768 assert_eq!(
1769 provider.header_by_id(block_hash.into()).unwrap(),
1770 Some(database_block.header().clone())
1771 );
1772 assert_eq!(
1773 provider.sealed_header_by_id(block_hash.into()).unwrap(),
1774 Some(database_block.clone_sealed_header())
1775 );
1776
1777 let block_number = in_memory_block.number;
1778 let block_hash = in_memory_block.hash();
1779
1780 assert_eq!(
1781 provider.header_by_id(block_number.into()).unwrap(),
1782 Some(in_memory_block.header().clone())
1783 );
1784 assert_eq!(
1785 provider.sealed_header_by_id(block_number.into()).unwrap(),
1786 Some(in_memory_block.clone_sealed_header())
1787 );
1788
1789 assert_eq!(
1790 provider.header_by_id(block_hash.into()).unwrap(),
1791 Some(in_memory_block.header().clone())
1792 );
1793 assert_eq!(
1794 provider.sealed_header_by_id(block_hash.into()).unwrap(),
1795 Some(in_memory_block.clone_sealed_header())
1796 );
1797
1798 Ok(())
1799 }
1800
1801 #[test]
1802 fn test_receipt_provider_id_ext_receipts_by_block_id() -> eyre::Result<()> {
1803 let mut rng = generators::rng();
1804 let (provider, database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
1805 &mut rng,
1806 TEST_BLOCKS_COUNT,
1807 TEST_BLOCKS_COUNT,
1808 BlockRangeParams { tx_count: 1..3, ..Default::default() },
1809 )?;
1810
1811 let database_block = database_blocks.first().unwrap().clone();
1812 let in_memory_block = in_memory_blocks.last().unwrap().clone();
1813
1814 let block_number = database_block.number;
1815 let block_hash = database_block.hash();
1816
1817 assert!(!receipts.get(database_block.number as usize).unwrap().is_empty());
1818 assert!(!provider
1819 .receipts_by_number_or_tag(database_block.number.into())?
1820 .unwrap()
1821 .is_empty());
1822
1823 assert_eq!(
1824 provider.receipts_by_block_id(block_number.into())?.unwrap(),
1825 receipts.get(block_number as usize).unwrap().clone()
1826 );
1827 assert_eq!(
1828 provider.receipts_by_block_id(block_hash.into())?.unwrap(),
1829 receipts.get(block_number as usize).unwrap().clone()
1830 );
1831
1832 let block_number = in_memory_block.number;
1833 let block_hash = in_memory_block.hash();
1834
1835 assert_eq!(
1836 provider.receipts_by_block_id(block_number.into())?.unwrap(),
1837 receipts.get(block_number as usize).unwrap().clone()
1838 );
1839 assert_eq!(
1840 provider.receipts_by_block_id(block_hash.into())?.unwrap(),
1841 receipts.get(block_number as usize).unwrap().clone()
1842 );
1843
1844 Ok(())
1845 }
1846
1847 #[test]
1848 fn test_receipt_provider_id_ext_receipts_by_block_number_or_tag() -> eyre::Result<()> {
1849 let mut rng = generators::rng();
1850 let (provider, database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
1851 &mut rng,
1852 TEST_BLOCKS_COUNT,
1853 TEST_BLOCKS_COUNT,
1854 BlockRangeParams { tx_count: 1..3, ..Default::default() },
1855 )?;
1856
1857 let database_block = database_blocks.first().unwrap().clone();
1858
1859 let in_memory_block_count = in_memory_blocks.len();
1860 let canonical_block = in_memory_blocks.get(in_memory_block_count - 1).unwrap().clone();
1861 let safe_block = in_memory_blocks.get(in_memory_block_count - 2).unwrap().clone();
1862 let finalized_block = in_memory_blocks.get(in_memory_block_count - 3).unwrap().clone();
1863
1864 assert!(!receipts.get(database_block.number as usize).unwrap().is_empty());
1865 assert!(!provider
1866 .receipts_by_number_or_tag(database_block.number.into())?
1867 .unwrap()
1868 .is_empty());
1869
1870 assert_eq!(
1871 provider.receipts_by_number_or_tag(database_block.number.into())?.unwrap(),
1872 receipts.get(database_block.number as usize).unwrap().clone()
1873 );
1874 assert_eq!(
1875 provider.receipts_by_number_or_tag(BlockNumberOrTag::Latest)?.unwrap(),
1876 receipts.get(canonical_block.number as usize).unwrap().clone()
1877 );
1878 assert_eq!(
1879 provider.receipts_by_number_or_tag(BlockNumberOrTag::Safe)?.unwrap(),
1880 receipts.get(safe_block.number as usize).unwrap().clone()
1881 );
1882 assert_eq!(
1883 provider.receipts_by_number_or_tag(BlockNumberOrTag::Finalized)?.unwrap(),
1884 receipts.get(finalized_block.number as usize).unwrap().clone()
1885 );
1886
1887 Ok(())
1888 }
1889
1890 #[test]
1891 fn test_changeset_reader() -> eyre::Result<()> {
1892 let mut rng = generators::rng();
1893
1894 let (database_blocks, in_memory_blocks) =
1895 random_blocks(&mut rng, TEST_BLOCKS_COUNT, 1, None, None, 0..1);
1896
1897 let first_database_block = database_blocks.first().map(|block| block.number).unwrap();
1898 let last_database_block = database_blocks.last().map(|block| block.number).unwrap();
1899 let first_in_memory_block = in_memory_blocks.first().map(|block| block.number).unwrap();
1900
1901 let accounts = random_eoa_accounts(&mut rng, 2);
1902
1903 let (database_changesets, database_state) = random_changeset_range(
1904 &mut rng,
1905 &database_blocks,
1906 accounts.into_iter().map(|(address, account)| (address, (account, Vec::new()))),
1907 0..0,
1908 0..0,
1909 );
1910 let (in_memory_changesets, in_memory_state) = random_changeset_range(
1911 &mut rng,
1912 &in_memory_blocks,
1913 database_state
1914 .iter()
1915 .map(|(address, (account, storage))| (*address, (*account, storage.clone()))),
1916 0..0,
1917 0..0,
1918 );
1919
1920 let factory = create_test_provider_factory();
1921
1922 let provider_rw = factory.provider_rw()?;
1923 provider_rw.append_blocks_with_state(
1924 database_blocks
1925 .into_iter()
1926 .map(|b| b.try_recover().expect("failed to seal block with senders"))
1927 .collect(),
1928 &ExecutionOutcome {
1929 bundle: BundleState::new(
1930 database_state.into_iter().map(|(address, (account, _))| {
1931 (address, None, Some(account.into()), Default::default())
1932 }),
1933 database_changesets.iter().map(|block_changesets| {
1934 block_changesets.iter().map(|(address, account, _)| {
1935 (*address, Some(Some((*account).into())), [])
1936 })
1937 }),
1938 Vec::new(),
1939 ),
1940 first_block: first_database_block,
1941 ..Default::default()
1942 },
1943 Default::default(),
1944 )?;
1945 provider_rw.commit()?;
1946
1947 let provider = BlockchainProvider::new(factory)?;
1948
1949 let in_memory_changesets = in_memory_changesets.into_iter().next().unwrap();
1950 let chain = NewCanonicalChain::Commit {
1951 new: vec![in_memory_blocks
1952 .first()
1953 .map(|block| {
1954 let senders = block.senders().expect("failed to recover senders");
1955 ExecutedBlock {
1956 recovered_block: Arc::new(RecoveredBlock::new_sealed(
1957 block.clone(),
1958 senders,
1959 )),
1960 execution_output: Arc::new(BlockExecutionOutput {
1961 state: BundleState::new(
1962 in_memory_state.into_iter().map(|(address, (account, _))| {
1963 (address, None, Some(account.into()), Default::default())
1964 }),
1965 [in_memory_changesets.iter().map(|(address, account, _)| {
1966 (*address, Some(Some((*account).into())), Vec::new())
1967 })],
1968 [],
1969 ),
1970 result: BlockExecutionResult {
1971 receipts: Default::default(),
1972 requests: Default::default(),
1973 gas_used: 0,
1974 blob_gas_used: 0,
1975 },
1976 }),
1977 ..Default::default()
1978 }
1979 })
1980 .unwrap()],
1981 };
1982 provider.canonical_in_memory_state.update_chain(chain);
1983
1984 assert_eq!(
1985 provider.account_block_changeset(last_database_block).unwrap(),
1986 database_changesets
1987 .into_iter()
1988 .next_back()
1989 .unwrap()
1990 .into_iter()
1991 .sorted_by_key(|(address, _, _)| *address)
1992 .map(|(address, account, _)| AccountBeforeTx { address, info: Some(account) })
1993 .collect::<Vec<_>>()
1994 );
1995 assert_eq!(
1996 provider.account_block_changeset(first_in_memory_block).unwrap(),
1997 in_memory_changesets
1998 .into_iter()
1999 .sorted_by_key(|(address, _, _)| *address)
2000 .map(|(address, account, _)| AccountBeforeTx { address, info: Some(account) })
2001 .collect::<Vec<_>>()
2002 );
2003
2004 Ok(())
2005 }
2006
2007 #[test]
2008 fn test_state_provider_factory() -> eyre::Result<()> {
2009 let mut rng = generators::rng();
2010
2011 let (in_memory_provider, _, in_memory_blocks, _) = provider_with_random_blocks(
2013 &mut rng,
2014 TEST_BLOCKS_COUNT,
2015 TEST_BLOCKS_COUNT,
2016 BlockRangeParams::default(),
2017 )?;
2018
2019 let (only_database_provider, database_blocks, _, _) = provider_with_random_blocks(
2021 &mut rng,
2022 TEST_BLOCKS_COUNT,
2023 0,
2024 BlockRangeParams::default(),
2025 )?;
2026
2027 let blocks = [database_blocks.clone(), in_memory_blocks.clone()].concat();
2028 let first_in_memory_block = in_memory_blocks.first().unwrap();
2029 let first_db_block = database_blocks.first().unwrap();
2030
2031 assert_eq!(
2033 first_in_memory_block.hash(),
2034 in_memory_provider.latest().unwrap().block_hash(first_in_memory_block.number)?.unwrap()
2035 );
2036 assert_eq!(
2038 first_db_block.hash(),
2039 only_database_provider.latest().unwrap().block_hash(first_db_block.number)?.unwrap()
2040 );
2041
2042 assert_eq!(
2044 first_in_memory_block.hash(),
2045 in_memory_provider
2046 .history_by_block_number(first_in_memory_block.number)?
2047 .block_hash(first_in_memory_block.number)?
2048 .unwrap()
2049 );
2050 assert_eq!(
2051 first_db_block.hash(),
2052 only_database_provider
2053 .history_by_block_number(first_db_block.number)?
2054 .block_hash(first_db_block.number)?
2055 .unwrap()
2056 );
2057 assert_eq!(
2058 first_in_memory_block.hash(),
2059 in_memory_provider
2060 .history_by_block_hash(first_in_memory_block.hash())?
2061 .block_hash(first_in_memory_block.number)?
2062 .unwrap()
2063 );
2064 assert!(only_database_provider.history_by_block_hash(B256::random()).is_err());
2065
2066 assert_eq!(
2068 first_in_memory_block.hash(),
2069 in_memory_provider
2070 .state_by_block_hash(first_in_memory_block.hash())?
2071 .block_hash(first_in_memory_block.number)?
2072 .unwrap()
2073 );
2074 assert_eq!(
2075 first_db_block.hash(),
2076 only_database_provider
2077 .state_by_block_hash(first_db_block.hash())?
2078 .block_hash(first_db_block.number)?
2079 .unwrap()
2080 );
2081 assert!(only_database_provider.state_by_block_hash(B256::random()).is_err());
2082
2083 assert_eq!(
2085 first_in_memory_block.hash(),
2086 in_memory_provider
2087 .pending()
2088 .unwrap()
2089 .block_hash(first_in_memory_block.number)
2090 .unwrap()
2091 .unwrap()
2092 );
2093
2094 let pending_block = database_blocks[database_blocks.len() - 1].clone();
2096 only_database_provider.canonical_in_memory_state.set_pending_block(ExecutedBlock {
2097 recovered_block: Arc::new(RecoveredBlock::new_sealed(
2098 pending_block.clone(),
2099 Default::default(),
2100 )),
2101 ..Default::default()
2102 });
2103
2104 assert_eq!(
2105 pending_block.hash(),
2106 only_database_provider
2107 .pending()
2108 .unwrap()
2109 .block_hash(pending_block.number)
2110 .unwrap()
2111 .unwrap()
2112 );
2113
2114 assert_eq!(
2115 pending_block.hash(),
2116 only_database_provider
2117 .pending_state_by_hash(pending_block.hash())?
2118 .unwrap()
2119 .block_hash(pending_block.number)?
2120 .unwrap()
2121 );
2122
2123 assert_eq!(
2125 first_in_memory_block.hash(),
2126 in_memory_provider
2127 .state_by_block_number_or_tag(BlockNumberOrTag::Number(
2128 first_in_memory_block.number
2129 ))?
2130 .block_hash(first_in_memory_block.number)?
2131 .unwrap()
2132 );
2133 assert_eq!(
2134 first_in_memory_block.hash(),
2135 in_memory_provider
2136 .state_by_block_number_or_tag(BlockNumberOrTag::Latest)?
2137 .block_hash(first_in_memory_block.number)?
2138 .unwrap()
2139 );
2140 let safe_block = in_memory_blocks[in_memory_blocks.len() - 2].clone();
2142 in_memory_provider.canonical_in_memory_state.set_safe(safe_block.clone_sealed_header());
2143 assert_eq!(
2144 safe_block.hash(),
2145 in_memory_provider
2146 .state_by_block_number_or_tag(BlockNumberOrTag::Safe)?
2147 .block_hash(safe_block.number)?
2148 .unwrap()
2149 );
2150 let finalized_block = in_memory_blocks[in_memory_blocks.len() - 3].clone();
2152 in_memory_provider
2153 .canonical_in_memory_state
2154 .set_finalized(finalized_block.clone_sealed_header());
2155 assert_eq!(
2156 finalized_block.hash(),
2157 in_memory_provider
2158 .state_by_block_number_or_tag(BlockNumberOrTag::Finalized)?
2159 .block_hash(finalized_block.number)?
2160 .unwrap()
2161 );
2162 let earliest_block = blocks.first().unwrap().clone();
2164 assert_eq!(
2165 earliest_block.hash(),
2166 only_database_provider
2167 .state_by_block_number_or_tag(BlockNumberOrTag::Earliest)?
2168 .block_hash(earliest_block.number)?
2169 .unwrap()
2170 );
2171
2172 Ok(())
2173 }
2174
2175 #[test]
2176 fn test_block_id_reader() -> eyre::Result<()> {
2177 let mut rng = generators::rng();
2179 let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
2180 &mut rng,
2181 TEST_BLOCKS_COUNT,
2182 TEST_BLOCKS_COUNT,
2183 BlockRangeParams::default(),
2184 )?;
2185
2186 let pending_block = in_memory_blocks.last().unwrap();
2188 provider.canonical_in_memory_state.set_pending_block(ExecutedBlock {
2189 recovered_block: Arc::new(RecoveredBlock::new_sealed(
2190 pending_block.clone(),
2191 Default::default(),
2192 )),
2193 ..Default::default()
2194 });
2195
2196 let safe_block = in_memory_blocks[in_memory_blocks.len() - 2].clone();
2198 provider.canonical_in_memory_state.set_safe(safe_block.clone_sealed_header());
2199
2200 let finalized_block = in_memory_blocks[in_memory_blocks.len() - 3].clone();
2202 provider.canonical_in_memory_state.set_finalized(finalized_block.clone_sealed_header());
2203
2204 assert_eq!(
2206 provider.pending_block_num_hash()?,
2207 Some(BlockNumHash { number: pending_block.number, hash: pending_block.hash() })
2208 );
2209
2210 assert_eq!(
2212 provider.safe_block_num_hash()?,
2213 Some(BlockNumHash { number: safe_block.number, hash: safe_block.hash() })
2214 );
2215
2216 assert_eq!(
2218 provider.finalized_block_num_hash()?,
2219 Some(BlockNumHash { number: finalized_block.number, hash: finalized_block.hash() })
2220 );
2221
2222 Ok(())
2223 }
2224
2225 macro_rules! test_by_tx_range {
2226 ([$(($method:ident, $data_extractor:expr)),* $(,)?]) => {{
2227
2228 let extra_blocks = [$(stringify!($method)),*].len();
2231
2232 let mut rng = generators::rng();
2233 let (provider, mut database_blocks, mut in_memory_blocks, receipts) = provider_with_random_blocks(
2234 &mut rng,
2235 TEST_BLOCKS_COUNT,
2236 TEST_BLOCKS_COUNT + extra_blocks,
2237 BlockRangeParams {
2238 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2239 ..Default::default()
2240 },
2241 )?;
2242
2243 $(
2244 let db_tx_count =
2246 database_blocks.iter().map(|b| b.transaction_count()).sum::<usize>() as u64;
2247 let in_mem_tx_count =
2248 in_memory_blocks.iter().map(|b| b.transaction_count()).sum::<usize>() as u64;
2249
2250 let db_range = 0..=(db_tx_count - 1);
2251 let in_mem_range = db_tx_count..=(in_mem_tx_count + db_range.end());
2252
2253 let database_data =
2255 database_blocks.iter().flat_map(|b| $data_extractor(b, &receipts)).collect::<Vec<_>>();
2256 assert_eq!(provider.$method(db_range.clone())?, database_data, "full db data");
2257
2258 let in_memory_data =
2260 in_memory_blocks.iter().flat_map(|b| $data_extractor(b, &receipts)).collect::<Vec<_>>();
2261 assert_eq!(provider.$method(in_mem_range.clone())?, in_memory_data, "full mem data");
2262
2263 assert_eq!(
2265 &provider.$method(in_mem_range.start() + 1..=in_mem_range.end() - 1)?,
2266 &in_memory_data[1..in_memory_data.len() - 1],
2267 "partial mem data"
2268 );
2269
2270 assert_eq!(provider.$method(in_mem_range.start() + 1..)?, &in_memory_data[1..], "unbounded mem data");
2272
2273 assert_eq!(provider.$method(in_mem_range.end()..)?, &in_memory_data[in_memory_data.len() -1 ..], "last mem data");
2275
2276 assert_eq!(
2278 provider.$method(in_mem_range.start() - 2..)?,
2279 database_data[database_data.len() - 2..]
2280 .iter()
2281 .chain(&in_memory_data[..])
2282 .cloned()
2283 .collect::<Vec<_>>(),
2284 "unbounded span data"
2285 );
2286
2287 {
2289 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2291
2292 assert_eq!(
2293 provider.$method(in_mem_range.start() - 2..=in_mem_range.end() - 1)?,
2294 database_data[database_data.len() - 2..]
2295 .iter()
2296 .chain(&in_memory_data[..in_memory_data.len() - 1])
2297 .cloned()
2298 .collect::<Vec<_>>(),
2299 "span data"
2300 );
2301
2302 database_blocks.push(in_memory_blocks.remove(0));
2304 }
2305
2306 let start_tx_num = u64::MAX;
2308 let end_tx_num = u64::MAX;
2309 let result = provider.$method(start_tx_num..end_tx_num)?;
2310 assert!(result.is_empty(), "No data should be found for an invalid transaction range");
2311
2312 let result = provider.$method(in_mem_range.end()+10..in_mem_range.end()+20)?;
2314 assert!(result.is_empty(), "No data should be found for an empty transaction range");
2315 )*
2316 }};
2317 }
2318
2319 #[test]
2320 fn test_methods_by_tx_range() -> eyre::Result<()> {
2321 test_by_tx_range!([
2322 (senders_by_tx_range, |block: &SealedBlock<Block>, _: &Vec<Vec<Receipt>>| block
2323 .senders()
2324 .unwrap()),
2325 (transactions_by_tx_range, |block: &SealedBlock<Block>, _: &Vec<Vec<Receipt>>| block
2326 .body()
2327 .transactions
2328 .clone()),
2329 (receipts_by_tx_range, |block: &SealedBlock<Block>, receipts: &Vec<Vec<Receipt>>| {
2330 receipts[block.number as usize].clone()
2331 })
2332 ]);
2333
2334 Ok(())
2335 }
2336
2337 macro_rules! test_by_block_range {
2338 ([$(($method:ident, $data_extractor:expr)),* $(,)?]) => {{
2339 let extra_blocks = [$(stringify!($method)),*].len();
2342
2343 let mut rng = generators::rng();
2344 let (provider, mut database_blocks, mut in_memory_blocks, _) = provider_with_random_blocks(
2345 &mut rng,
2346 TEST_BLOCKS_COUNT,
2347 TEST_BLOCKS_COUNT + extra_blocks,
2348 BlockRangeParams {
2349 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2350 ..Default::default()
2351 },
2352 )?;
2353
2354 $(
2355 let db_block_count = database_blocks.len() as u64;
2357 let in_mem_block_count = in_memory_blocks.len() as u64;
2358
2359 let db_range = 0..=db_block_count - 1;
2360 let in_mem_range = db_block_count..=(in_mem_block_count + db_range.end());
2361
2362 let database_data =
2364 database_blocks.iter().map(|b| $data_extractor(b)).collect::<Vec<_>>();
2365 assert_eq!(provider.$method(db_range.clone())?, database_data);
2366
2367 let in_memory_data =
2369 in_memory_blocks.iter().map(|b| $data_extractor(b)).collect::<Vec<_>>();
2370 assert_eq!(provider.$method(in_mem_range.clone())?, in_memory_data);
2371
2372 assert_eq!(
2374 &provider.$method(in_mem_range.start() + 1..=in_mem_range.end() - 1)?,
2375 &in_memory_data[1..in_memory_data.len() - 1]
2376 );
2377
2378 {
2380
2381 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2383
2384 assert_eq!(
2385 provider.$method(in_mem_range.start() - 2..=in_mem_range.end() - 1)?,
2386 database_data[database_data.len() - 2..]
2387 .iter()
2388 .chain(&in_memory_data[..in_memory_data.len() - 1])
2389 .cloned()
2390 .collect::<Vec<_>>()
2391 );
2392
2393 database_blocks.push(in_memory_blocks.remove(0));
2395 }
2396
2397 let start_block_num = u64::MAX;
2399 let end_block_num = u64::MAX;
2400 let result = provider.$method(start_block_num..=end_block_num-1)?;
2401 assert!(result.is_empty(), "No data should be found for an invalid block range");
2402
2403 let result = provider.$method(in_mem_range.end() + 10..=in_mem_range.end() + 20)?;
2405 assert!(result.is_empty(), "No data should be found for an empty block range");
2406 )*
2407 }};
2408 }
2409
2410 #[test]
2411 fn test_methods_by_block_range() -> eyre::Result<()> {
2412 test_by_block_range!([
2415 (headers_range, |block: &SealedBlock<Block>| block.header().clone()),
2416 (sealed_headers_range, |block: &SealedBlock<Block>| block.clone_sealed_header()),
2417 (block_range, |block: &SealedBlock<Block>| block.clone().into_block()),
2418 (block_with_senders_range, |block: &SealedBlock<Block>| block
2419 .clone()
2420 .try_recover()
2421 .unwrap()),
2422 (recovered_block_range, |block: &SealedBlock<Block>| block
2423 .clone()
2424 .try_recover()
2425 .unwrap()),
2426 (transactions_by_block_range, |block: &SealedBlock<Block>| block
2427 .body()
2428 .transactions
2429 .clone()),
2430 ]);
2431
2432 Ok(())
2433 }
2434
2435 macro_rules! call_method {
2437 ($provider:expr, $method:ident, ($($args:expr),*), $expected_item:expr) => {{
2438 let result = $provider.$method($($args),*)?;
2439 assert_eq!(
2440 result,
2441 $expected_item,
2442 "{}: item does not match the expected item for arguments {:?}",
2443 stringify!($method),
2444 ($($args),*)
2445 );
2446 }};
2447
2448 (ONE, $provider:expr, $method:ident, $item_extractor:expr, $txnum:expr, $txhash:expr, $block:expr, $receipts:expr) => {{
2450 let (arg, expected_item) = $item_extractor($block, $txnum($block), $txhash($block), $receipts);
2451 call_method!($provider, $method, (arg), expected_item);
2452 }};
2453
2454 (TWO, $provider:expr, $method:ident, $item_extractor:expr, $txnum:expr, $txhash:expr, $block:expr, $receipts:expr) => {{
2456 let ((arg1, arg2), expected_item) = $item_extractor($block, $txnum($block), $txhash($block), $receipts);
2457 call_method!($provider, $method, (arg1, arg2), expected_item);
2458 }};
2459 }
2460
2461 macro_rules! test_non_range {
2466 ([$(($arg_count:ident, $method:ident, $item_extractor:expr, $invalid_args:expr)),* $(,)?]) => {{
2467
2468 let extra_blocks = [$(stringify!($arg_count)),*].len();
2471
2472 let mut rng = generators::rng();
2473 let (provider, mut database_blocks, in_memory_blocks, receipts) = provider_with_random_blocks(
2474 &mut rng,
2475 TEST_BLOCKS_COUNT,
2476 TEST_BLOCKS_COUNT + extra_blocks,
2477 BlockRangeParams {
2478 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2479 ..Default::default()
2480 },
2481 )?;
2482
2483 let mut in_memory_blocks: std::collections::VecDeque<_> = in_memory_blocks.into();
2484
2485 $(
2486 let tx_hash = |block: &SealedBlock<Block>| *block.body().transactions[0].tx_hash();
2487 let tx_num = |block: &SealedBlock<Block>| {
2488 database_blocks
2489 .iter()
2490 .chain(in_memory_blocks.iter())
2491 .take_while(|b| b.number < block.number)
2492 .map(|b| b.transaction_count())
2493 .sum::<usize>() as u64
2494 };
2495
2496 {
2498 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2500
2501 call_method!($arg_count, provider, $method, $item_extractor, tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2502
2503 database_blocks.push(in_memory_blocks.pop_front().unwrap());
2505 }
2506
2507 let tx_num = |block: &SealedBlock<Block>| {
2509 database_blocks
2510 .iter()
2511 .chain(in_memory_blocks.iter())
2512 .take_while(|b| b.number < block.number)
2513 .map(|b| b.transaction_count())
2514 .sum::<usize>() as u64
2515 };
2516
2517 {
2519 call_method!($arg_count, provider, $method, |_,_,_,_| ($invalid_args, None), tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2520 }
2521
2522 {
2524 let last_mem_block = &in_memory_blocks[in_memory_blocks.len() - 1];
2525
2526 let (args, expected_item) = $item_extractor(last_mem_block, tx_num(last_mem_block), tx_hash(last_mem_block), &receipts);
2527 call_method!($arg_count, provider, $method, |_,_,_,_| (args.clone(), expected_item), tx_num, tx_hash, last_mem_block, &receipts);
2528
2529 call_method!($arg_count, provider.database, $method, |_,_,_,_| (args, None), tx_num, tx_hash, last_mem_block, &receipts);
2531 }
2532 )*
2533 }};
2534}
2535
2536 #[test]
2537 fn test_non_range_methods() -> eyre::Result<()> {
2538 let test_tx_index = 0;
2539
2540 test_non_range!([
2541 (
2542 ONE,
2543 header,
2544 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2545 block.hash(),
2546 Some(block.header().clone())
2547 ),
2548 B256::random()
2549 ),
2550 (
2551 ONE,
2552 header_by_number,
2553 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2554 block.number,
2555 Some(block.header().clone())
2556 ),
2557 u64::MAX
2558 ),
2559 (
2560 ONE,
2561 sealed_header,
2562 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2563 block.number,
2564 Some(block.clone_sealed_header())
2565 ),
2566 u64::MAX
2567 ),
2568 (
2569 ONE,
2570 block_hash,
2571 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2572 block.number,
2573 Some(block.hash())
2574 ),
2575 u64::MAX
2576 ),
2577 (
2578 ONE,
2579 block_number,
2580 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2581 block.hash(),
2582 Some(block.number)
2583 ),
2584 B256::random()
2585 ),
2586 (
2587 ONE,
2588 block,
2589 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2590 BlockHashOrNumber::Hash(block.hash()),
2591 Some(block.clone().into_block())
2592 ),
2593 BlockHashOrNumber::Hash(B256::random())
2594 ),
2595 (
2596 ONE,
2597 block,
2598 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2599 BlockHashOrNumber::Number(block.number),
2600 Some(block.clone().into_block())
2601 ),
2602 BlockHashOrNumber::Number(u64::MAX)
2603 ),
2604 (
2605 ONE,
2606 block_body_indices,
2607 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2608 block.number,
2609 Some(StoredBlockBodyIndices {
2610 first_tx_num: tx_num,
2611 tx_count: block.transaction_count() as u64
2612 })
2613 ),
2614 u64::MAX
2615 ),
2616 (
2617 TWO,
2618 recovered_block,
2619 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2620 (BlockHashOrNumber::Number(block.number), TransactionVariant::WithHash),
2621 block.clone().try_recover().ok()
2622 ),
2623 (BlockHashOrNumber::Number(u64::MAX), TransactionVariant::WithHash)
2624 ),
2625 (
2626 TWO,
2627 recovered_block,
2628 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2629 (BlockHashOrNumber::Hash(block.hash()), TransactionVariant::WithHash),
2630 block.clone().try_recover().ok()
2631 ),
2632 (BlockHashOrNumber::Hash(B256::random()), TransactionVariant::WithHash)
2633 ),
2634 (
2635 TWO,
2636 sealed_block_with_senders,
2637 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2638 (BlockHashOrNumber::Number(block.number), TransactionVariant::WithHash),
2639 block.clone().try_recover().ok()
2640 ),
2641 (BlockHashOrNumber::Number(u64::MAX), TransactionVariant::WithHash)
2642 ),
2643 (
2644 TWO,
2645 sealed_block_with_senders,
2646 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2647 (BlockHashOrNumber::Hash(block.hash()), TransactionVariant::WithHash),
2648 block.clone().try_recover().ok()
2649 ),
2650 (BlockHashOrNumber::Hash(B256::random()), TransactionVariant::WithHash)
2651 ),
2652 (
2653 ONE,
2654 transaction_id,
2655 |_: &SealedBlock<Block>, tx_num: TxNumber, tx_hash: B256, _: &Vec<Vec<Receipt>>| (
2656 tx_hash,
2657 Some(tx_num)
2658 ),
2659 B256::random()
2660 ),
2661 (
2662 ONE,
2663 transaction_by_id,
2664 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2665 tx_num,
2666 Some(block.body().transactions[test_tx_index].clone())
2667 ),
2668 u64::MAX
2669 ),
2670 (
2671 ONE,
2672 transaction_by_id_unhashed,
2673 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2674 tx_num,
2675 Some(block.body().transactions[test_tx_index].clone())
2676 ),
2677 u64::MAX
2678 ),
2679 (
2680 ONE,
2681 transaction_by_hash,
2682 |block: &SealedBlock<Block>, _: TxNumber, tx_hash: B256, _: &Vec<Vec<Receipt>>| (
2683 tx_hash,
2684 Some(block.body().transactions[test_tx_index].clone())
2685 ),
2686 B256::random()
2687 ),
2688 (
2689 ONE,
2690 block_by_transaction_id,
2691 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2692 tx_num,
2693 Some(block.number)
2694 ),
2695 u64::MAX
2696 ),
2697 (
2698 ONE,
2699 transactions_by_block,
2700 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2701 BlockHashOrNumber::Number(block.number),
2702 Some(block.body().transactions.clone())
2703 ),
2704 BlockHashOrNumber::Number(u64::MAX)
2705 ),
2706 (
2707 ONE,
2708 transactions_by_block,
2709 |block: &SealedBlock<Block>, _: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2710 BlockHashOrNumber::Hash(block.hash()),
2711 Some(block.body().transactions.clone())
2712 ),
2713 BlockHashOrNumber::Number(u64::MAX)
2714 ),
2715 (
2716 ONE,
2717 transaction_sender,
2718 |block: &SealedBlock<Block>, tx_num: TxNumber, _: B256, _: &Vec<Vec<Receipt>>| (
2719 tx_num,
2720 block.body().transactions[test_tx_index].recover_signer().ok()
2721 ),
2722 u64::MAX
2723 ),
2724 (
2725 ONE,
2726 receipt,
2727 |block: &SealedBlock<Block>,
2728 tx_num: TxNumber,
2729 _: B256,
2730 receipts: &Vec<Vec<Receipt>>| (
2731 tx_num,
2732 Some(receipts[block.number as usize][test_tx_index].clone())
2733 ),
2734 u64::MAX
2735 ),
2736 (
2737 ONE,
2738 receipt_by_hash,
2739 |block: &SealedBlock<Block>,
2740 _: TxNumber,
2741 tx_hash: B256,
2742 receipts: &Vec<Vec<Receipt>>| (
2743 tx_hash,
2744 Some(receipts[block.number as usize][test_tx_index].clone())
2745 ),
2746 B256::random()
2747 ),
2748 (
2749 ONE,
2750 receipts_by_block,
2751 |block: &SealedBlock<Block>, _: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2752 BlockHashOrNumber::Number(block.number),
2753 Some(receipts[block.number as usize].clone())
2754 ),
2755 BlockHashOrNumber::Number(u64::MAX)
2756 ),
2757 (
2758 ONE,
2759 receipts_by_block,
2760 |block: &SealedBlock<Block>, _: TxNumber, _: B256, receipts: &Vec<Vec<Receipt>>| (
2761 BlockHashOrNumber::Hash(block.hash()),
2762 Some(receipts[block.number as usize].clone())
2763 ),
2764 BlockHashOrNumber::Hash(B256::random())
2765 ),
2766 ]);
2768
2769 Ok(())
2770 }
2771
2772 #[test]
2773 fn test_race() -> eyre::Result<()> {
2774 let mut rng = generators::rng();
2775 let (provider, _, in_memory_blocks, _) = provider_with_random_blocks(
2776 &mut rng,
2777 TEST_BLOCKS_COUNT - 1,
2778 TEST_BLOCKS_COUNT + 1,
2779 BlockRangeParams {
2780 tx_count: TEST_TRANSACTIONS_COUNT..TEST_TRANSACTIONS_COUNT,
2781 ..Default::default()
2782 },
2783 )?;
2784
2785 let old_transaction_hash_fn =
2788 |hash: B256,
2789 canonical_in_memory_state: CanonicalInMemoryState,
2790 factory: ProviderFactory<MockNodeTypesWithDB>| {
2791 assert!(factory.transaction_by_hash(hash)?.is_none(), "should not be in database");
2792 Ok::<_, ProviderError>(canonical_in_memory_state.transaction_by_hash(hash))
2793 };
2794
2795 let correct_transaction_hash_fn =
2797 |hash: B256,
2798 canonical_in_memory_state: CanonicalInMemoryState,
2799 _factory: ProviderFactory<MockNodeTypesWithDB>| {
2800 if let Some(tx) = canonical_in_memory_state.transaction_by_hash(hash) {
2801 return Ok::<_, ProviderError>(Some(tx));
2802 }
2803 panic!("should not be in database");
2804 };
2806
2807 {
2809 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[0].number);
2812 let to_be_persisted_tx = in_memory_blocks[0].body().transactions[0].clone();
2813
2814 assert!(matches!(
2817 old_transaction_hash_fn(
2818 *to_be_persisted_tx.tx_hash(),
2819 provider.canonical_in_memory_state(),
2820 provider.database.clone()
2821 ),
2822 Ok(None)
2823 ));
2824 }
2825
2826 {
2828 persist_block_after_db_tx_creation(provider.clone(), in_memory_blocks[1].number);
2831 let to_be_persisted_tx = in_memory_blocks[1].body().transactions[0].clone();
2832
2833 assert_eq!(
2834 correct_transaction_hash_fn(
2835 *to_be_persisted_tx.tx_hash(),
2836 provider.canonical_in_memory_state(),
2837 provider.database
2838 )
2839 .unwrap(),
2840 Some(to_be_persisted_tx)
2841 );
2842 }
2843
2844 Ok(())
2845 }
2846
2847 fn random_account(nonce: u64) -> (Address, Account) {
2848 (Address::random(), Account { nonce, balance: U256::from(nonce), bytecode_hash: None })
2849 }
2850
2851 fn test_provider_factory_with_genesis() -> eyre::Result<ProviderFactory<MockNodeTypesWithDB>> {
2853 let factory = create_test_provider_factory();
2854 let provider_rw = factory.provider_rw()?;
2855 let mut rng = generators::rng();
2856 let genesis =
2857 random_block(&mut rng, 0, BlockParams { tx_count: Some(0), ..Default::default() });
2858 provider_rw
2859 .insert_block(&genesis.try_recover().expect("failed to seal block with senders"))?;
2860 provider_rw.save_stage_checkpoint(StageId::Finish, StageCheckpoint::new(0))?;
2861 provider_rw.commit()?;
2862 Ok(factory)
2863 }
2864
2865 #[test]
2866 fn state_range_provider_account_range_is_sorted_and_bounded() -> eyre::Result<()> {
2867 let factory = test_provider_factory_with_genesis()?;
2868 let provider_rw = factory.provider_rw()?;
2869
2870 let accounts: Vec<_> = (0..5u64).map(random_account).collect();
2871 provider_rw.insert_account_for_hashing(
2872 accounts.iter().map(|(address, account)| (*address, Some(*account))),
2873 )?;
2874 provider_rw.commit()?;
2875
2876 let provider = BlockchainProvider::new(factory)?;
2877
2878 let mut expected: Vec<_> =
2879 accounts.iter().map(|(address, account)| (keccak256(address), *account)).collect();
2880 expected.sort_by_key(|(hash, _)| *hash);
2881 let state = provider.state_range_provider(EMPTY_ROOT_HASH)?.unwrap();
2882
2883 let all = state.account_range(B256::ZERO, B256::repeat_byte(0xff), 10_000)?;
2884 assert_eq!(all.end, RangeEnd::Exhausted);
2885 assert_eq!(all.items, expected);
2886
2887 let bounded = state.account_range(B256::ZERO, expected[1].0, 10_000)?;
2890 assert_eq!(bounded.end, RangeEnd::HashLimit);
2891 assert_eq!(bounded.items, expected[..2]);
2892
2893 Ok(())
2894 }
2895
2896 #[test]
2897 fn state_range_provider_account_range_respects_response_bytes() -> eyre::Result<()> {
2898 let factory = test_provider_factory_with_genesis()?;
2899 let provider_rw = factory.provider_rw()?;
2900
2901 let accounts: Vec<_> = (0..5u64).map(random_account).collect();
2902 provider_rw.insert_account_for_hashing(
2903 accounts.iter().map(|(address, account)| (*address, Some(*account))),
2904 )?;
2905 provider_rw.commit()?;
2906
2907 let provider = BlockchainProvider::new(factory)?;
2908 let state = provider.state_range_provider(EMPTY_ROOT_HASH)?.unwrap();
2909
2910 let partial = state.account_range(B256::ZERO, B256::repeat_byte(0xff), 150)?;
2912 assert_eq!(partial.end, RangeEnd::ByteLimit);
2913 assert_eq!(partial.items.len(), 1);
2914
2915 Ok(())
2916 }
2917
2918 #[test]
2919 fn state_range_provider_storage_range_and_root() -> eyre::Result<()> {
2920 let factory = test_provider_factory_with_genesis()?;
2921 let provider_rw = factory.provider_rw()?;
2922
2923 let (address, account) = random_account(1);
2924 let hashed_address = keccak256(address);
2925 provider_rw.insert_account_for_hashing([(address, Some(account))])?;
2926 let slots = [
2927 StorageEntry { key: B256::with_last_byte(1), value: U256::from(10) },
2928 StorageEntry { key: B256::with_last_byte(2), value: U256::from(20) },
2929 ];
2930 provider_rw.insert_storage_for_hashing([(address, slots)])?;
2931 provider_rw.commit()?;
2932
2933 let provider = BlockchainProvider::new(factory)?;
2934 let state = provider.state_range_provider(EMPTY_ROOT_HASH)?.unwrap();
2935
2936 let expected_root = provider.latest()?.storage_root(address, HashedStorage::default())?;
2937 assert_eq!(state.storage_root_by_hash(hashed_address)?, expected_root);
2938
2939 let returned = state
2940 .storage_range(hashed_address, B256::ZERO, B256::repeat_byte(0xff), 10_000)?
2941 .unwrap();
2942 assert_eq!(returned.end, RangeEnd::Exhausted);
2943 let mut expected: Vec<_> =
2944 slots.iter().map(|entry| (keccak256(entry.key), entry.value)).collect();
2945 expected.sort_by_key(|(hash, _)| *hash);
2946 assert_eq!(returned.items, expected);
2947
2948 let empty_window =
2950 state.storage_range(hashed_address, B256::ZERO, B256::ZERO, 10_000)?.unwrap();
2951 assert_eq!(empty_window.end, RangeEnd::HashLimit);
2952 assert_eq!(empty_window.items, expected[..1]);
2953
2954 assert!(state
2956 .storage_range(B256::repeat_byte(0xee), B256::ZERO, B256::repeat_byte(0xff), 10_000)?
2957 .is_none());
2958
2959 Ok(())
2960 }
2961
2962 #[test]
2963 fn state_range_provider_proofs_start_at_the_real_root() -> eyre::Result<()> {
2964 let factory = test_provider_factory_with_genesis()?;
2965 let provider_rw = factory.provider_rw()?;
2966
2967 let (address, account) = random_account(1);
2968 let hashed_address = keccak256(address);
2969 let hashed_slot = keccak256(B256::with_last_byte(1));
2970 provider_rw.insert_account_for_hashing([(address, Some(account))])?;
2971 provider_rw.insert_storage_for_hashing([(
2972 address,
2973 [StorageEntry { key: B256::with_last_byte(1), value: U256::from(10) }],
2974 )])?;
2975 provider_rw.commit()?;
2976
2977 let provider = BlockchainProvider::new(factory)?;
2978
2979 let state_root = provider.latest()?.state_root(HashedPostState::default())?;
2982 let state = provider.state_range_provider(EMPTY_ROOT_HASH)?.unwrap();
2983 let account_proof = state.account_range_proof(&[hashed_address])?;
2984 assert!(!account_proof.is_empty());
2985 assert_eq!(keccak256(&account_proof[0]), state_root);
2986
2987 let storage_root = state.storage_root_by_hash(hashed_address)?;
2988 let storage_proof = state.storage_range_proof(hashed_address, &[hashed_slot])?;
2989 assert!(!storage_proof.is_empty());
2990 assert_eq!(keccak256(&storage_proof[0]), storage_root);
2991
2992 Ok(())
2993 }
2994
2995 #[test]
2996 fn state_range_provider_serves_recent_root_and_rejects_expired_root() -> eyre::Result<()> {
2997 let mut rng = generators::rng();
2998 let factory = create_test_provider_factory();
2999 let provider_rw = factory.provider_rw()?;
3000 let expired_root = B256::repeat_byte(0x11);
3001 let recent_root = B256::repeat_byte(0x22);
3002 let mut parent = B256::ZERO;
3003
3004 for number in 0..=SNAPSHOT_STATE_RETENTION {
3005 let mut block = random_block(
3006 &mut rng,
3007 number,
3008 BlockParams { parent: Some(parent), tx_count: Some(0), ..Default::default() },
3009 )
3010 .unseal();
3011 block.header.state_root = match number {
3012 0 => expired_root,
3013 64 => recent_root,
3014 _ => EMPTY_ROOT_HASH,
3015 };
3016 let block = block.seal_slow();
3017 parent = block.hash();
3018 provider_rw
3019 .insert_block(&block.try_recover().expect("failed to seal block with senders"))?;
3020 }
3021 provider_rw.save_stage_checkpoint(
3022 StageId::Finish,
3023 StageCheckpoint::new(SNAPSHOT_STATE_RETENTION),
3024 )?;
3025 provider_rw.commit()?;
3026
3027 let provider = BlockchainProvider::new(factory)?;
3028 assert!(provider.state_range_provider(recent_root)?.is_some());
3029 assert!(provider.state_range_provider(expired_root)?.is_none());
3030
3031 Ok(())
3032 }
3033
3034 #[test]
3035 fn state_range_provider_serves_persisted_root_with_in_memory_overlay() -> eyre::Result<()> {
3036 let mut rng = generators::rng();
3037 let (provider, _, _, _) = provider_with_random_blocks(
3038 &mut rng,
3039 TEST_BLOCKS_COUNT - 1,
3040 1,
3041 BlockRangeParams::default(),
3042 )?;
3043 assert!(provider.canonical_in_memory_state.head_state().is_some());
3044 let provider_rw = provider.database.provider_rw()?;
3045 provider_rw.save_stage_checkpoint(
3046 StageId::Finish,
3047 StageCheckpoint::new((TEST_BLOCKS_COUNT - 2) as u64),
3048 )?;
3049 provider_rw.commit()?;
3050
3051 assert!(provider.state_range_provider(EMPTY_ROOT_HASH)?.is_some());
3052
3053 Ok(())
3054 }
3055
3056 #[test]
3057 fn state_range_provider_resolves_root_from_in_memory_block() -> eyre::Result<()> {
3058 let mut rng = generators::rng();
3059 let factory = test_provider_factory_with_genesis()?;
3060 let provider = BlockchainProvider::new(factory)?;
3061
3062 let (address, account) = random_account(1);
3063 let hashed_address = keccak256(address);
3064 let mut hashed_state = HashedPostState::default();
3065 hashed_state.accounts.insert(hashed_address, Some(account));
3066
3067 let unique_root = B256::repeat_byte(0x77);
3070 let parent = provider.canonical_in_memory_state.get_canonical_head();
3071 let mut block = random_block(
3072 &mut rng,
3073 parent.number + 1,
3074 BlockParams { parent: Some(parent.hash()), tx_count: Some(0), ..Default::default() },
3075 )
3076 .unseal();
3077 block.header.state_root = unique_root;
3078 let block = block.seal_slow().try_recover().expect("failed to seal block with senders");
3079
3080 let trie_data = ComputedTrieData::new(
3081 Arc::new(hashed_state.into_sorted()),
3082 Arc::new(TrieUpdates::default().into_sorted()),
3083 );
3084 let execution_output = BlockExecutionOutput {
3085 result: BlockExecutionResult {
3086 receipts: Default::default(),
3087 requests: Default::default(),
3088 gas_used: 0,
3089 blob_gas_used: 0,
3090 },
3091 state: Default::default(),
3092 };
3093 let executed = ExecutedBlock::new(Arc::new(block), Arc::new(execution_output), trie_data);
3094 provider
3095 .canonical_in_memory_state
3096 .update_chain(NewCanonicalChain::Commit { new: vec![executed] });
3097
3098 let state =
3099 provider.state_range_provider(unique_root)?.expect("in-memory root must resolve");
3100 let range = state.account_range(B256::ZERO, B256::repeat_byte(0xff), 10_000)?;
3101 assert_eq!(range.items, vec![(hashed_address, account)]);
3102
3103 Ok(())
3104 }
3105
3106 #[test]
3107 fn state_range_provider_reverts_database_advancement_past_anchor() -> eyre::Result<()> {
3108 let mut rng = generators::rng();
3109 let factory = test_provider_factory_with_genesis()?;
3110 let provider = BlockchainProvider::new(factory)?;
3111 let genesis = provider.canonical_in_memory_state.get_canonical_head();
3112
3113 let (target_address, target_account) = random_account(1);
3115 let target_hashed = keccak256(target_address);
3116 let mut target_state = HashedPostState::default();
3117 target_state.accounts.insert(target_hashed, Some(target_account));
3118
3119 let unique_root = B256::repeat_byte(0x77);
3120 let mut block = random_block(
3121 &mut rng,
3122 genesis.number + 1,
3123 BlockParams { parent: Some(genesis.hash()), tx_count: Some(0), ..Default::default() },
3124 )
3125 .unseal();
3126 block.header.state_root = unique_root;
3127 let block = block.seal_slow().try_recover().expect("failed to seal block with senders");
3128 let trie_data = ComputedTrieData::new(
3129 Arc::new(target_state.into_sorted()),
3130 Arc::new(TrieUpdates::default().into_sorted()),
3131 );
3132 let execution_output = BlockExecutionOutput {
3133 result: BlockExecutionResult {
3134 receipts: Default::default(),
3135 requests: Default::default(),
3136 gas_used: 0,
3137 blob_gas_used: 0,
3138 },
3139 state: Default::default(),
3140 };
3141 let executed = ExecutedBlock::new(Arc::new(block), Arc::new(execution_output), trie_data);
3142 provider
3143 .canonical_in_memory_state
3144 .update_chain(NewCanonicalChain::Commit { new: vec![executed] });
3145
3146 let (noise_address, noise_account) = random_account(2);
3150 let noise_block = random_block(
3151 &mut rng,
3152 genesis.number + 1,
3153 BlockParams { parent: Some(genesis.hash()), tx_count: Some(0), ..Default::default() },
3154 )
3155 .try_recover()
3156 .expect("failed to seal block with senders");
3157 let mut noise_state = HashedPostState::default();
3158 noise_state.accounts.insert(keccak256(noise_address), Some(noise_account));
3159 let provider_rw = provider.database.provider_rw()?;
3160 provider_rw.append_blocks_with_state(
3161 vec![noise_block],
3162 &ExecutionOutcome {
3163 bundle: BundleState::new(
3164 [(noise_address, None, Some(noise_account.into()), Default::default())],
3165 [[(noise_address, Some(None), [])]],
3166 [],
3167 ),
3168 first_block: genesis.number + 1,
3169 ..Default::default()
3170 },
3171 noise_state.into_sorted(),
3172 )?;
3173 provider_rw
3174 .save_stage_checkpoint(StageId::Finish, StageCheckpoint::new(genesis.number + 1))?;
3175 provider_rw.commit()?;
3176
3177 let state =
3180 provider.state_range_provider(unique_root)?.expect("in-memory root must resolve");
3181 let range = state.account_range(B256::ZERO, B256::repeat_byte(0xff), 10_000)?;
3182 assert_eq!(range.items, vec![(target_hashed, target_account)]);
3183
3184 Ok(())
3185 }
3186
3187 #[test]
3188 fn historical_state_range_provider_reverts_state_change_past_retained_anchor(
3189 ) -> eyre::Result<()> {
3190 let mut rng = generators::rng();
3191
3192 let (address, account_a) = random_account(1);
3194 let hashed_address = keccak256(address);
3195 let slot_key = B256::with_last_byte(1);
3196 let slot = U256::from_be_bytes(slot_key.0);
3197 let hashed_slot = keccak256(slot_key);
3198 let value_a = U256::from(1);
3199
3200 let factory = test_provider_factory_with_genesis()?;
3201 let provider_rw = factory.provider_rw()?;
3202 provider_rw.insert_account_for_hashing([(address, Some(account_a))])?;
3203 provider_rw.insert_storage_for_hashing([(
3204 address,
3205 [StorageEntry { key: slot_key, value: value_a }],
3206 )])?;
3207 provider_rw.commit()?;
3208 let anchor_root = factory.latest()?.state_root(HashedPostState::default())?;
3209
3210 let genesis_hash = factory.sealed_header(0)?.unwrap().hash();
3211 let mut anchor_block = random_block(
3212 &mut rng,
3213 1,
3214 BlockParams { parent: Some(genesis_hash), tx_count: Some(0), ..Default::default() },
3215 )
3216 .unseal();
3217 anchor_block.header.state_root = anchor_root;
3218 let anchor_block =
3219 anchor_block.seal_slow().try_recover().expect("failed to seal block with senders");
3220 let anchor_hash = anchor_block.hash();
3221
3222 let provider_rw = factory.provider_rw()?;
3223 provider_rw.insert_block(&anchor_block)?;
3224 provider_rw.save_stage_checkpoint(StageId::Finish, StageCheckpoint::new(1))?;
3225 provider_rw.commit()?;
3226
3227 let account_b = Account { nonce: 2, balance: U256::from(2), ..account_a };
3229 let value_b = U256::from(2);
3230
3231 let mut storage = HashMap::default();
3232 storage.insert(slot, (value_a, value_b));
3233
3234 let mut state_b = HashedPostState::default();
3235 state_b.accounts.insert(hashed_address, Some(account_b));
3236 state_b
3237 .storages
3238 .insert(hashed_address, HashedStorage::from_iter(false, [(hashed_slot, value_b)]));
3239
3240 let state_b_root = factory.latest()?.state_root(state_b.clone())?;
3241 let mut later_block = random_block(
3242 &mut rng,
3243 2,
3244 BlockParams { parent: Some(anchor_hash), tx_count: Some(0), ..Default::default() },
3245 )
3246 .unseal();
3247 later_block.header.state_root = state_b_root;
3248 let later_block =
3249 later_block.seal_slow().try_recover().expect("failed to seal block with senders");
3250
3251 let provider_rw = factory.provider_rw()?;
3252 provider_rw.append_blocks_with_state(
3253 vec![later_block],
3254 &ExecutionOutcome {
3255 bundle: BundleState::new(
3256 [(address, Some(account_a.into()), Some(account_b.into()), storage)],
3257 [[(address, Some(Some(account_a.into())), [(slot, value_a)])]],
3258 [],
3259 ),
3260 first_block: 2,
3261 ..Default::default()
3262 },
3263 state_b.into_sorted(),
3264 )?;
3265 provider_rw.save_stage_checkpoint(StageId::Finish, StageCheckpoint::new(2))?;
3266 provider_rw.commit()?;
3267
3268 let provider = BlockchainProvider::new(factory)?;
3271 let state =
3272 provider.state_range_provider(anchor_root)?.expect("retained root must resolve");
3273 let range = state.account_range(B256::ZERO, B256::repeat_byte(0xff), 10_000)?;
3274 assert_eq!(range.items, vec![(hashed_address, account_a)]);
3275
3276 let storage_range = state
3277 .storage_range(hashed_address, B256::ZERO, B256::repeat_byte(0xff), 10_000)?
3278 .expect("account must have storage");
3279 assert_eq!(storage_range.items, vec![(hashed_slot, value_a)]);
3280
3281 Ok(())
3282 }
3283}