1use super::state::latest::LatestStateProvider;
2use crate::{
3 providers::{
4 ConsistentProvider, ProviderNodeTypes, RocksDBProvider, StaticFileProvider,
5 StaticFileProviderRWRefMut,
6 },
7 BalProvider, BalStoreHandle, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader,
8 BlockReaderIdExt, BlockSource, CanonChainTracker, CanonStateNotifications,
9 CanonStateSubscriptions, ChainSpecProvider, ChainStateBlockReader, ChangeSetReader,
10 DatabaseProviderFactory, HeaderProvider, ProviderError, ProviderFactory, PruneCheckpointReader,
11 ReceiptProvider, ReceiptProviderIdExt, RocksDBProviderFactory, StageCheckpointReader,
12 StateProviderBox, StateProviderFactory, StateReader, StaticFileProviderFactory,
13 TransactionVariant, TransactionsProvider,
14};
15use alloy_consensus::{transaction::TransactionMeta, BlockHeader};
16use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumHash, BlockNumberOrTag};
17use alloy_primitives::{Address, BlockHash, BlockNumber, Bytes, TxHash, TxNumber, B256};
18use alloy_rpc_types_engine::ForkchoiceState;
19use reth_chain_state::{
20 BlockState, CanonicalInMemoryState, ForkChoiceNotifications, ForkChoiceSubscriptions,
21 MemoryOverlayStateProvider, PersistedBlockNotifications, PersistedBlockSubscriptions,
22};
23use reth_chainspec::ChainInfo;
24use reth_db_api::models::{AccountBeforeTx, BlockNumberAddress, StoredBlockBodyIndices};
25use reth_execution_types::ExecutionOutcome;
26use reth_node_types::{BlockTy, HeaderTy, NodeTypesWithDB, ReceiptTy, TxTy};
27use reth_primitives_traits::{
28 Account, RecoveredBlock, SealedHeader, SealedOrRecoveredBlock, StorageEntry,
29};
30use reth_prune_types::{PruneCheckpoint, PruneSegment};
31use reth_stages_types::{StageCheckpoint, StageId};
32use reth_static_file_types::StaticFileSegment;
33use reth_storage_api::{
34 BlockBodyIndicesProvider, NodePrimitivesProvider, RangeEnd, RangeResponse, RangeResult,
35 StateRangeProvider, StateRangeProviderFactory, StateRangeView, StorageChangeSetReader,
36 StorageRangeResult, TryIntoHistoricalStateProvider,
37};
38use reth_storage_errors::provider::ProviderResult;
39use reth_storage_overlay::{
40 anchor_for_parent, AnchorForParent, OverlayStateProvider, OverlayStateProviderFactory,
41};
42use reth_trie::{
43 hashed_cursor::{HashedCursor, HashedCursorFactory},
44 metrics::TrieRootMetrics,
45 proof::{Proof, StorageProof},
46 MultiProofTargets, StorageRoot, TrieInput, TrieInputSorted, TrieType,
47};
48use std::{
49 ops::{RangeBounds, RangeInclusive},
50 sync::Arc,
51 time::Instant,
52};
53use tracing::trace;
54
55pub const SNAPSHOT_STATE_RETENTION: u64 = 128;
58
59type StateRangeDbProvider<N> = <ProviderFactory<N> as DatabaseProviderFactory>::Provider;
60type HistoricalStateRangeProvider<N> = OverlayStateProvider<StateRangeDbProvider<N>>;
61
62#[derive(Debug)]
68pub struct BlockchainProvider<N: NodeTypesWithDB> {
69 pub(crate) database: ProviderFactory<N>,
71 pub(crate) canonical_in_memory_state: CanonicalInMemoryState<N::Primitives>,
74 pub(crate) bal_store: BalStoreHandle,
76}
77
78impl<N: NodeTypesWithDB> Clone for BlockchainProvider<N> {
79 fn clone(&self) -> Self {
80 Self {
81 database: self.database.clone(),
82 canonical_in_memory_state: self.canonical_in_memory_state.clone(),
83 bal_store: self.bal_store.clone(),
84 }
85 }
86}
87
88impl<N: ProviderNodeTypes> BlockchainProvider<N> {
89 pub fn new(storage: ProviderFactory<N>) -> ProviderResult<Self> {
92 let provider = storage.provider()?;
93 let best = provider.chain_info()?;
94 match provider.header_by_number(best.best_number)? {
95 Some(header) => {
96 drop(provider);
97 Ok(Self::with_latest(storage, SealedHeader::new(header, best.best_hash))?)
98 }
99 None => Err(ProviderError::HeaderNotFound(best.best_number.into())),
100 }
101 }
102
103 pub fn with_latest(
109 storage: ProviderFactory<N>,
110 latest: SealedHeader<HeaderTy<N>>,
111 ) -> ProviderResult<Self> {
112 let provider = storage.provider()?;
113 let finalized_header = provider
114 .last_finalized_block_number()?
115 .map(|num| provider.sealed_header(num))
116 .transpose()?
117 .flatten();
118 let safe_header = provider
119 .last_safe_block_number()?
120 .or_else(|| {
121 provider.last_finalized_block_number().ok().flatten()
124 })
125 .map(|num| provider.sealed_header(num))
126 .transpose()?
127 .flatten();
128 let bal_store = storage.bal_store().clone();
129
130 Ok(Self {
131 database: storage,
132 canonical_in_memory_state: CanonicalInMemoryState::with_head(
133 latest,
134 finalized_header,
135 safe_header,
136 ),
137 bal_store,
138 })
139 }
140
141 pub fn canonical_in_memory_state(&self) -> CanonicalInMemoryState<N::Primitives> {
143 self.canonical_in_memory_state.clone()
144 }
145
146 #[track_caller]
150 pub fn consistent_provider(&self) -> ProviderResult<ConsistentProvider<N>> {
151 ConsistentProvider::new(self.database.clone(), self.canonical_in_memory_state())
152 }
153
154 fn block_state_provider(
156 &self,
157 state: &BlockState<N::Primitives>,
158 ) -> ProviderResult<MemoryOverlayStateProvider<N::Primitives>> {
159 let provider = self.database.provider()?;
160 let anchor =
161 anchor_for_parent(state.hash(), state.chain().map(|state| state.block()), &provider)?;
162
163 let (historical, overlay): (StateProviderBox, _) = match anchor {
164 AnchorForParent::NoReverts { overlay, .. } => {
165 (Box::new(LatestStateProvider::new(provider)), overlay)
166 }
167 AnchorForParent::RevertsRequired { anchor, overlay, .. } => {
168 (provider.try_into_history_at_block(anchor.number)?, overlay)
169 }
170 };
171
172 Ok(MemoryOverlayStateProvider::new(historical, overlay))
173 }
174
175 fn block_state_range_provider(
178 &self,
179 state_root: B256,
180 ) -> ProviderResult<Option<HistoricalStateRangeProvider<N>>> {
181 let Some(matched) = self
182 .canonical_in_memory_state
183 .canonical_chain()
184 .find(|state| state.state_root() == state_root)
185 else {
186 return Ok(None)
187 };
188
189 let blocks: Vec<_> = matched.chain().map(|state| state.block()).collect();
191 let sorted: Vec<_> =
192 blocks.iter().rev().map(|block| (block.hashed_state(), block.trie_updates())).collect();
193 let input = TrieInput::from_blocks_sorted(
194 sorted.iter().map(|(state, nodes)| (state.as_ref(), nodes.as_ref())),
195 );
196 let merged = TrieInputSorted::from_unsorted(input);
197
198 let overlay_factory = OverlayStateProviderFactory::new(
201 self.database.clone(),
202 self.database
203 .overlay_manager()
204 .overlay_builder(matched.anchor().hash)
205 .with_immediate_state_trie_overlay(merged.state, merged.nodes),
206 );
207 reth_storage_api::DatabaseProviderROFactory::database_provider_ro(&overlay_factory)
208 .map(Some)
209 }
210
211 fn historical_state_range_provider(
213 &self,
214 state_root: B256,
215 ) -> ProviderResult<Option<HistoricalStateRangeProvider<N>>> {
216 let provider = self.database.provider()?;
217 let Some(finish) = provider.get_stage_checkpoint(StageId::Finish)? else { return Ok(None) };
218 let oldest = finish.block_number.saturating_sub(SNAPSHOT_STATE_RETENTION - 1);
219 let mut block_hash = None;
220
221 for number in (oldest..=finish.block_number).rev() {
222 let Some(header) = provider.sealed_header(number)? else { continue };
223 if header.state_root() == state_root {
224 block_hash = Some(header.hash());
225 break
226 }
227 }
228 drop(provider);
229
230 let Some(block_hash) = block_hash else { return Ok(None) };
231 let overlay_factory = OverlayStateProviderFactory::new(
232 self.database.clone(),
233 self.database.overlay_manager().overlay_builder(block_hash),
234 );
235 reth_storage_api::DatabaseProviderROFactory::database_provider_ro(&overlay_factory)
236 .map(Some)
237 }
238}
239
240impl<N: NodeTypesWithDB> NodePrimitivesProvider for BlockchainProvider<N> {
241 type Primitives = N::Primitives;
242}
243
244impl<N: ProviderNodeTypes> BalProvider for BlockchainProvider<N> {
245 fn bal_store(&self) -> &BalStoreHandle {
246 &self.bal_store
247 }
248}
249
250struct HistoricalStateRangeView<N: ProviderNodeTypes> {
252 provider: HistoricalStateRangeProvider<N>,
253}
254
255impl<N: ProviderNodeTypes> StateRangeProviderFactory for BlockchainProvider<N> {
256 fn state_range_provider(&self, state_root: B256) -> ProviderResult<Option<StateRangeView>> {
259 let provider = match self.block_state_range_provider(state_root)? {
260 Some(provider) => Some(provider),
261 None => self.historical_state_range_provider(state_root)?,
262 };
263 Ok(provider
264 .map(|provider| Box::new(HistoricalStateRangeView { provider }) as StateRangeView))
265 }
266}
267
268impl<N: ProviderNodeTypes> StateRangeProvider for HistoricalStateRangeView<N> {
269 fn account_range(
270 &self,
271 start: B256,
272 limit: B256,
273 response_bytes: usize,
274 ) -> RangeResult<(B256, Account)> {
275 let mut cursor = self.provider.hashed_account_cursor().map_err(ProviderError::Database)?;
276
277 let mut accounts = Vec::new();
278 let mut total_bytes = 0usize;
279 let mut end = RangeEnd::Exhausted;
280
281 let mut entry = cursor.seek(start).map_err(ProviderError::Database)?;
284 while let Some((hash, account)) = entry {
285 total_bytes += 32 + 4 * 32; accounts.push((hash, account));
287 if hash >= limit {
288 end = RangeEnd::HashLimit;
289 break
290 }
291 if total_bytes > response_bytes {
292 end = RangeEnd::ByteLimit;
293 break
294 }
295 entry = cursor.next().map_err(ProviderError::Database)?;
296 }
297
298 Ok(RangeResponse { items: accounts, end })
299 }
300
301 fn storage_root_by_hash(&self, hashed_address: B256) -> ProviderResult<B256> {
302 let root = StorageRoot::new_hashed(
303 &self.provider,
304 &self.provider,
305 hashed_address,
306 Default::default(),
307 TrieRootMetrics::new(TrieType::Storage),
308 )
309 .root()
310 .map_err(|err| ProviderError::Database(err.into()))?;
311 Ok(root)
312 }
313
314 fn storage_range(
315 &self,
316 hashed_address: B256,
317 start: B256,
318 limit: B256,
319 response_bytes: usize,
320 ) -> StorageRangeResult {
321 let mut account_cursor =
324 self.provider.hashed_account_cursor().map_err(ProviderError::Database)?;
325 let found = account_cursor.seek(hashed_address).map_err(ProviderError::Database)?;
326 if found.map(|(hash, _)| hash) != Some(hashed_address) {
327 return Ok(None)
328 }
329
330 let mut cursor =
331 self.provider.hashed_storage_cursor(hashed_address).map_err(ProviderError::Database)?;
332
333 let mut slots = Vec::new();
334 let mut total_bytes = 0usize;
335 let mut end = RangeEnd::Exhausted;
336
337 let mut entry = cursor.seek(start).map_err(ProviderError::Database)?;
340 while let Some((hash, value)) = entry {
341 total_bytes += 64;
342 slots.push((hash, value));
343 if hash >= limit {
344 end = RangeEnd::HashLimit;
345 break
346 }
347 if total_bytes > response_bytes {
348 end = RangeEnd::ByteLimit;
349 break
350 }
351 entry = cursor.next().map_err(ProviderError::Database)?;
352 }
353
354 Ok(Some(RangeResponse { items: slots, end }))
355 }
356
357 fn account_range_proof(&self, keys: &[B256]) -> ProviderResult<Vec<Bytes>> {
358 let multiproof = Proof::new(&self.provider, &self.provider)
359 .multiproof(MultiProofTargets::accounts(keys.iter().copied()))
360 .map_err(ProviderError::from)?;
361 Ok(multiproof
362 .account_subtree
363 .into_nodes_sorted()
364 .into_iter()
365 .map(|(_, bytes)| bytes)
366 .collect())
367 }
368
369 fn storage_range_proof(
370 &self,
371 hashed_address: B256,
372 keys: &[B256],
373 ) -> ProviderResult<Vec<Bytes>> {
374 let multiproof = StorageProof::new_hashed(&self.provider, &self.provider, hashed_address)
375 .storage_multiproof(keys.iter().copied().collect())
376 .map_err(ProviderError::from)?;
377 Ok(multiproof.subtree.into_nodes_sorted().into_iter().map(|(_, bytes)| bytes).collect())
378 }
379}
380
381impl<N: ProviderNodeTypes> DatabaseProviderFactory for BlockchainProvider<N> {
382 type DB = N::DB;
383 type Provider = <ProviderFactory<N> as DatabaseProviderFactory>::Provider;
384 type ProviderRW = <ProviderFactory<N> as DatabaseProviderFactory>::ProviderRW;
385
386 fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
387 DatabaseProviderFactory::database_provider_ro(&self.database)
388 }
389
390 fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
391 DatabaseProviderFactory::database_provider_rw(&self.database)
392 }
393}
394
395impl<N: ProviderNodeTypes> StaticFileProviderFactory for BlockchainProvider<N> {
396 fn static_file_provider(&self) -> StaticFileProvider<Self::Primitives> {
397 self.database.static_file_provider()
398 }
399
400 fn get_static_file_writer(
401 &self,
402 block: BlockNumber,
403 segment: StaticFileSegment,
404 ) -> ProviderResult<StaticFileProviderRWRefMut<'_, Self::Primitives>> {
405 self.database.get_static_file_writer(block, segment)
406 }
407}
408
409impl<N: ProviderNodeTypes> RocksDBProviderFactory for BlockchainProvider<N> {
410 fn rocksdb_provider(&self) -> RocksDBProvider {
411 self.database.rocksdb_provider()
412 }
413
414 fn set_pending_rocksdb_batch(&self, _batch: rocksdb::WriteBatchWithTransaction<true>) {
415 unimplemented!("BlockchainProvider wraps ProviderFactory - use DatabaseProvider::set_pending_rocksdb_batch instead")
416 }
417
418 fn commit_pending_rocksdb_batches(&self) -> ProviderResult<()> {
419 unimplemented!("BlockchainProvider wraps ProviderFactory - use DatabaseProvider::commit_pending_rocksdb_batches instead")
420 }
421}
422
423impl<N: ProviderNodeTypes> HeaderProvider for BlockchainProvider<N> {
424 type Header = HeaderTy<N>;
425
426 fn header(&self, block_hash: BlockHash) -> ProviderResult<Option<Self::Header>> {
427 self.consistent_provider()?.header(block_hash)
428 }
429
430 fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Self::Header>> {
431 self.consistent_provider()?.header_by_number(num)
432 }
433
434 fn headers_range(
435 &self,
436 range: impl RangeBounds<BlockNumber>,
437 ) -> ProviderResult<Vec<Self::Header>> {
438 self.consistent_provider()?.headers_range(range)
439 }
440
441 fn sealed_header(
442 &self,
443 number: BlockNumber,
444 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
445 self.consistent_provider()?.sealed_header(number)
446 }
447
448 fn sealed_headers_range(
449 &self,
450 range: impl RangeBounds<BlockNumber>,
451 ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
452 self.consistent_provider()?.sealed_headers_range(range)
453 }
454
455 fn sealed_headers_while(
456 &self,
457 range: impl RangeBounds<BlockNumber>,
458 predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
459 ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
460 self.consistent_provider()?.sealed_headers_while(range, predicate)
461 }
462}
463
464impl<N: ProviderNodeTypes> BlockHashReader for BlockchainProvider<N> {
465 fn block_hash(&self, number: u64) -> ProviderResult<Option<B256>> {
466 self.consistent_provider()?.block_hash(number)
467 }
468
469 fn canonical_hashes_range(
470 &self,
471 start: BlockNumber,
472 end: BlockNumber,
473 ) -> ProviderResult<Vec<B256>> {
474 self.consistent_provider()?.canonical_hashes_range(start, end)
475 }
476}
477
478impl<N: ProviderNodeTypes> BlockNumReader for BlockchainProvider<N> {
479 fn chain_info(&self) -> ProviderResult<ChainInfo> {
480 Ok(self.canonical_in_memory_state.chain_info())
481 }
482
483 fn best_block_number(&self) -> ProviderResult<BlockNumber> {
484 Ok(self.canonical_in_memory_state.get_canonical_block_number())
485 }
486
487 fn last_block_number(&self) -> ProviderResult<BlockNumber> {
488 self.database.last_block_number()
489 }
490
491 fn earliest_block_number(&self) -> ProviderResult<BlockNumber> {
492 self.database.earliest_block_number()
493 }
494
495 fn block_number(&self, hash: B256) -> ProviderResult<Option<BlockNumber>> {
496 self.consistent_provider()?.block_number(hash)
497 }
498}
499
500impl<N: ProviderNodeTypes> BlockIdReader for BlockchainProvider<N> {
501 fn pending_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
502 Ok(self.canonical_in_memory_state.pending_block_num_hash())
503 }
504
505 fn safe_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
506 Ok(self.canonical_in_memory_state.get_safe_num_hash())
507 }
508
509 fn finalized_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
510 Ok(self.canonical_in_memory_state.get_finalized_num_hash())
511 }
512}
513
514impl<N: ProviderNodeTypes> BlockReader for BlockchainProvider<N> {
515 type Block = BlockTy<N>;
516
517 fn find_block_by_hash(
518 &self,
519 hash: B256,
520 source: BlockSource,
521 ) -> ProviderResult<Option<Self::Block>> {
522 self.consistent_provider()?.find_block_by_hash(hash, source)
523 }
524
525 fn find_sealed_or_recovered_block(
526 &self,
527 hash: B256,
528 source: BlockSource,
529 ) -> ProviderResult<Option<SealedOrRecoveredBlock<Self::Block>>> {
530 self.consistent_provider()?.find_sealed_or_recovered_block(hash, source)
531 }
532
533 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
534 self.consistent_provider()?.block(id)
535 }
536
537 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
538 Ok(self.canonical_in_memory_state.pending_recovered_block())
539 }
540
541 fn pending_block_and_receipts(
542 &self,
543 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
544 Ok(self.canonical_in_memory_state.pending_block_and_receipts())
545 }
546
547 fn recovered_block(
554 &self,
555 id: BlockHashOrNumber,
556 transaction_kind: TransactionVariant,
557 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
558 self.consistent_provider()?.recovered_block(id, transaction_kind)
559 }
560
561 fn sealed_block_with_senders(
562 &self,
563 id: BlockHashOrNumber,
564 transaction_kind: TransactionVariant,
565 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
566 self.consistent_provider()?.sealed_block_with_senders(id, transaction_kind)
567 }
568
569 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
570 self.consistent_provider()?.block_range(range)
571 }
572
573 fn block_with_senders_range(
574 &self,
575 range: RangeInclusive<BlockNumber>,
576 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
577 self.consistent_provider()?.block_with_senders_range(range)
578 }
579
580 fn recovered_block_range(
581 &self,
582 range: RangeInclusive<BlockNumber>,
583 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
584 self.consistent_provider()?.recovered_block_range(range)
585 }
586
587 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
588 self.consistent_provider()?.block_by_transaction_id(id)
589 }
590}
591
592impl<N: ProviderNodeTypes> TransactionsProvider for BlockchainProvider<N> {
593 type Transaction = TxTy<N>;
594
595 fn transaction_id(&self, tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
596 self.consistent_provider()?.transaction_id(tx_hash)
597 }
598
599 fn transaction_by_id(&self, id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
600 self.consistent_provider()?.transaction_by_id(id)
601 }
602
603 fn transaction_by_id_unhashed(
604 &self,
605 id: TxNumber,
606 ) -> ProviderResult<Option<Self::Transaction>> {
607 self.consistent_provider()?.transaction_by_id_unhashed(id)
608 }
609
610 fn transaction_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
611 self.consistent_provider()?.transaction_by_hash(hash)
612 }
613
614 fn transaction_by_hash_with_meta(
615 &self,
616 tx_hash: TxHash,
617 ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
618 self.consistent_provider()?.transaction_by_hash_with_meta(tx_hash)
619 }
620
621 fn transactions_by_block(
622 &self,
623 id: BlockHashOrNumber,
624 ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
625 self.consistent_provider()?.transactions_by_block(id)
626 }
627
628 fn transactions_by_block_range(
629 &self,
630 range: impl RangeBounds<BlockNumber>,
631 ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
632 self.consistent_provider()?.transactions_by_block_range(range)
633 }
634
635 fn transactions_by_tx_range(
636 &self,
637 range: impl RangeBounds<TxNumber>,
638 ) -> ProviderResult<Vec<Self::Transaction>> {
639 self.consistent_provider()?.transactions_by_tx_range(range)
640 }
641
642 fn senders_by_tx_range(
643 &self,
644 range: impl RangeBounds<TxNumber>,
645 ) -> ProviderResult<Vec<Address>> {
646 self.consistent_provider()?.senders_by_tx_range(range)
647 }
648
649 fn transaction_sender(&self, id: TxNumber) -> ProviderResult<Option<Address>> {
650 self.consistent_provider()?.transaction_sender(id)
651 }
652}
653
654impl<N: ProviderNodeTypes> ReceiptProvider for BlockchainProvider<N> {
655 type Receipt = ReceiptTy<N>;
656
657 fn receipt(&self, id: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
658 self.consistent_provider()?.receipt(id)
659 }
660
661 fn receipt_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
662 self.consistent_provider()?.receipt_by_hash(hash)
663 }
664
665 fn receipts_by_block(
666 &self,
667 block: BlockHashOrNumber,
668 ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
669 self.consistent_provider()?.receipts_by_block(block)
670 }
671
672 fn receipts_by_tx_range(
673 &self,
674 range: impl RangeBounds<TxNumber>,
675 ) -> ProviderResult<Vec<Self::Receipt>> {
676 self.consistent_provider()?.receipts_by_tx_range(range)
677 }
678
679 fn receipts_by_block_range(
680 &self,
681 block_range: RangeInclusive<BlockNumber>,
682 ) -> ProviderResult<Vec<Vec<Self::Receipt>>> {
683 self.consistent_provider()?.receipts_by_block_range(block_range)
684 }
685}
686
687impl<N: ProviderNodeTypes> ReceiptProviderIdExt for BlockchainProvider<N> {
688 fn receipts_by_block_id(&self, block: BlockId) -> ProviderResult<Option<Vec<Self::Receipt>>> {
689 self.consistent_provider()?.receipts_by_block_id(block)
690 }
691}
692
693impl<N: ProviderNodeTypes> BlockBodyIndicesProvider for BlockchainProvider<N> {
694 fn block_body_indices(
695 &self,
696 number: BlockNumber,
697 ) -> ProviderResult<Option<StoredBlockBodyIndices>> {
698 self.consistent_provider()?.block_body_indices(number)
699 }
700
701 fn block_body_indices_range(
702 &self,
703 range: RangeInclusive<BlockNumber>,
704 ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
705 self.consistent_provider()?.block_body_indices_range(range)
706 }
707}
708
709impl<N: ProviderNodeTypes> StageCheckpointReader for BlockchainProvider<N> {
710 fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
711 self.consistent_provider()?.get_stage_checkpoint(id)
712 }
713
714 fn get_stage_checkpoint_progress(&self, id: StageId) -> ProviderResult<Option<Vec<u8>>> {
715 self.consistent_provider()?.get_stage_checkpoint_progress(id)
716 }
717
718 fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
719 self.consistent_provider()?.get_all_checkpoints()
720 }
721}
722
723impl<N: ProviderNodeTypes> PruneCheckpointReader for BlockchainProvider<N> {
724 fn get_prune_checkpoint(
725 &self,
726 segment: PruneSegment,
727 ) -> ProviderResult<Option<PruneCheckpoint>> {
728 self.consistent_provider()?.get_prune_checkpoint(segment)
729 }
730
731 fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
732 self.consistent_provider()?.get_prune_checkpoints()
733 }
734}
735
736impl<N: NodeTypesWithDB> ChainSpecProvider for BlockchainProvider<N> {
737 type ChainSpec = N::ChainSpec;
738
739 fn chain_spec(&self) -> Arc<N::ChainSpec> {
740 self.database.chain_spec()
741 }
742}
743
744impl<N: ProviderNodeTypes> StateProviderFactory for BlockchainProvider<N> {
745 fn latest(&self) -> ProviderResult<StateProviderBox> {
747 trace!(target: "providers::blockchain", "Getting latest block state provider");
748 if let Some(state) = self.canonical_in_memory_state.head_state() {
750 trace!(target: "providers::blockchain", "Using head state for latest state provider");
751 Ok(self.block_state_provider(&state)?.boxed())
752 } else {
753 trace!(target: "providers::blockchain", "Using database state for latest state provider");
754 self.database.latest()
755 }
756 }
757
758 fn state_by_block_number_or_tag(
760 &self,
761 number_or_tag: BlockNumberOrTag,
762 ) -> ProviderResult<StateProviderBox> {
763 match number_or_tag {
764 BlockNumberOrTag::Latest => self.latest(),
765 BlockNumberOrTag::Finalized => {
766 let hash =
768 self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
769 self.state_by_block_hash(hash)
770 }
771 BlockNumberOrTag::Safe => {
772 let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
774 self.state_by_block_hash(hash)
775 }
776 BlockNumberOrTag::Earliest => {
777 self.history_by_block_number(self.earliest_block_number()?)
778 }
779 BlockNumberOrTag::Pending => self.pending(),
780 BlockNumberOrTag::Number(num) => {
781 let hash = self
782 .block_hash(num)?
783 .ok_or_else(|| ProviderError::HeaderNotFound(num.into()))?;
784 self.state_by_block_hash(hash)
785 }
786 }
787 }
788
789 fn history_by_block_number(
790 &self,
791 block_number: BlockNumber,
792 ) -> ProviderResult<StateProviderBox> {
793 trace!(target: "providers::blockchain", ?block_number, "Getting history by block number");
794 let provider = self.consistent_provider()?;
795 let hash = provider
796 .block_hash(block_number)?
797 .ok_or_else(|| ProviderError::HeaderNotFound(block_number.into()))?;
798 provider.into_state_provider_at_block_hash(hash)
799 }
800
801 fn history_by_block_hash(&self, block_hash: BlockHash) -> ProviderResult<StateProviderBox> {
802 trace!(target: "providers::blockchain", ?block_hash, "Getting history by block hash");
803 self.consistent_provider()?.into_state_provider_at_block_hash(block_hash)
804 }
805
806 fn state_by_block_hash(&self, hash: BlockHash) -> ProviderResult<StateProviderBox> {
807 trace!(target: "providers::blockchain", ?hash, "Getting state by block hash");
808 if let Ok(state) = self.history_by_block_hash(hash) {
809 Ok(state)
811 } else if let Ok(Some(pending)) = self.pending_state_by_hash(hash) {
812 Ok(pending)
814 } else {
815 Err(ProviderError::StateForHashNotFound(hash))
817 }
818 }
819
820 fn pending(&self) -> ProviderResult<StateProviderBox> {
825 trace!(target: "providers::blockchain", "Getting provider for pending state");
826
827 if let Some(pending) = self.canonical_in_memory_state.pending_state() {
828 return Ok(Box::new(self.block_state_provider(&pending)?));
830 }
831
832 self.latest()
834 }
835
836 fn pending_state_by_hash(&self, block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
837 if let Some(pending) = self.canonical_in_memory_state.pending_state() &&
838 pending.hash() == block_hash
839 {
840 return Ok(Some(Box::new(self.block_state_provider(&pending)?)));
841 }
842 Ok(None)
843 }
844
845 fn maybe_pending(&self) -> ProviderResult<Option<StateProviderBox>> {
846 if let Some(pending) = self.canonical_in_memory_state.pending_state() {
847 return Ok(Some(Box::new(self.block_state_provider(&pending)?)))
848 }
849
850 Ok(None)
851 }
852}
853
854impl<N: ProviderNodeTypes> CanonChainTracker for BlockchainProvider<N> {
855 type Header = HeaderTy<N>;
856
857 fn on_forkchoice_update_received(&self, _update: &ForkchoiceState) {
858 self.canonical_in_memory_state.on_forkchoice_update_received();
860 }
861
862 fn last_received_update_timestamp(&self) -> Option<Instant> {
863 self.canonical_in_memory_state.last_received_update_timestamp()
864 }
865
866 fn set_canonical_head(&self, header: SealedHeader<Self::Header>) {
867 self.canonical_in_memory_state.set_canonical_head(header);
868 }
869
870 fn set_safe(&self, header: SealedHeader<Self::Header>) {
871 self.canonical_in_memory_state.set_safe(header);
872 }
873
874 fn set_finalized(&self, header: SealedHeader<Self::Header>) {
875 self.canonical_in_memory_state.set_finalized(header);
876 }
877}
878
879impl<N: ProviderNodeTypes> BlockReaderIdExt for BlockchainProvider<N>
880where
881 Self: ReceiptProviderIdExt,
882{
883 fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>> {
884 self.consistent_provider()?.block_by_id(id)
885 }
886
887 fn header_by_number_or_tag(
888 &self,
889 id: BlockNumberOrTag,
890 ) -> ProviderResult<Option<Self::Header>> {
891 self.consistent_provider()?.header_by_number_or_tag(id)
892 }
893
894 fn sealed_header_by_number_or_tag(
895 &self,
896 id: BlockNumberOrTag,
897 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
898 self.consistent_provider()?.sealed_header_by_number_or_tag(id)
899 }
900
901 fn sealed_header_by_id(
902 &self,
903 id: BlockId,
904 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
905 self.consistent_provider()?.sealed_header_by_id(id)
906 }
907
908 fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>> {
909 self.consistent_provider()?.header_by_id(id)
910 }
911}
912
913impl<N: ProviderNodeTypes> CanonStateSubscriptions for BlockchainProvider<N> {
914 fn subscribe_to_canonical_state(&self) -> CanonStateNotifications<Self::Primitives> {
915 self.canonical_in_memory_state.subscribe_canon_state()
916 }
917}
918
919impl<N: ProviderNodeTypes> ForkChoiceSubscriptions for BlockchainProvider<N> {
920 type Header = HeaderTy<N>;
921
922 fn subscribe_safe_block(&self) -> ForkChoiceNotifications<Self::Header> {
923 let receiver = self.canonical_in_memory_state.subscribe_safe_block();
924 ForkChoiceNotifications(receiver)
925 }
926
927 fn subscribe_finalized_block(&self) -> ForkChoiceNotifications<Self::Header> {
928 let receiver = self.canonical_in_memory_state.subscribe_finalized_block();
929 ForkChoiceNotifications(receiver)
930 }
931}
932
933impl<N: ProviderNodeTypes> PersistedBlockSubscriptions for BlockchainProvider<N> {
934 fn subscribe_persisted_block(&self) -> PersistedBlockNotifications {
935 let receiver = self.canonical_in_memory_state.subscribe_persisted_block();
936 PersistedBlockNotifications(receiver)
937 }
938}
939
940impl<N: ProviderNodeTypes> StorageChangeSetReader for BlockchainProvider<N> {
941 fn storage_changeset(
942 &self,
943 block_number: BlockNumber,
944 ) -> ProviderResult<Vec<(BlockNumberAddress, StorageEntry)>> {
945 self.consistent_provider()?.storage_changeset(block_number)
946 }
947
948 fn get_storage_before_block(
949 &self,
950 block_number: BlockNumber,
951 address: Address,
952 storage_key: B256,
953 ) -> ProviderResult<Option<StorageEntry>> {
954 self.consistent_provider()?.get_storage_before_block(block_number, address, storage_key)
955 }
956
957 fn storage_changesets_range(
958 &self,
959 range: impl RangeBounds<BlockNumber>,
960 ) -> ProviderResult<Vec<(BlockNumberAddress, StorageEntry)>> {
961 self.consistent_provider()?.storage_changesets_range(range)
962 }
963}
964
965impl<N: ProviderNodeTypes> ChangeSetReader for BlockchainProvider<N> {
966 fn account_block_changeset(
967 &self,
968 block_number: BlockNumber,
969 ) -> ProviderResult<Vec<AccountBeforeTx>> {
970 self.consistent_provider()?.account_block_changeset(block_number)
971 }
972
973 fn get_account_before_block(
974 &self,
975 block_number: BlockNumber,
976 address: Address,
977 ) -> ProviderResult<Option<AccountBeforeTx>> {
978 self.consistent_provider()?.get_account_before_block(block_number, address)
979 }
980
981 fn account_changesets_range(
982 &self,
983 range: impl core::ops::RangeBounds<BlockNumber>,
984 ) -> ProviderResult<Vec<(BlockNumber, AccountBeforeTx)>> {
985 self.consistent_provider()?.account_changesets_range(range)
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.storages.insert(hashed_address, HashedStorage::from_iter([(hashed_slot, value_b)]));
3237
3238 let state_b_root = factory.latest()?.state_root(state_b.clone())?;
3239 let mut later_block = random_block(
3240 &mut rng,
3241 2,
3242 BlockParams { parent: Some(anchor_hash), tx_count: Some(0), ..Default::default() },
3243 )
3244 .unseal();
3245 later_block.header.state_root = state_b_root;
3246 let later_block =
3247 later_block.seal_slow().try_recover().expect("failed to seal block with senders");
3248
3249 let provider_rw = factory.provider_rw()?;
3250 provider_rw.append_blocks_with_state(
3251 vec![later_block],
3252 &ExecutionOutcome {
3253 bundle: BundleState::new(
3254 [(address, Some(account_a.into()), Some(account_b.into()), storage)],
3255 [[(address, Some(Some(account_a.into())), [(slot, value_a)])]],
3256 [],
3257 ),
3258 first_block: 2,
3259 ..Default::default()
3260 },
3261 state_b.into_sorted(),
3262 )?;
3263 provider_rw.save_stage_checkpoint(StageId::Finish, StageCheckpoint::new(2))?;
3264 provider_rw.commit()?;
3265
3266 let provider = BlockchainProvider::new(factory)?;
3269 let state =
3270 provider.state_range_provider(anchor_root)?.expect("retained root must resolve");
3271 let range = state.account_range(B256::ZERO, B256::repeat_byte(0xff), 10_000)?;
3272 assert_eq!(range.items, vec![(hashed_address, account_a)]);
3273
3274 let storage_range = state
3275 .storage_range(hashed_address, B256::ZERO, B256::repeat_byte(0xff), 10_000)?
3276 .expect("account must have storage");
3277 assert_eq!(storage_range.items, vec![(hashed_slot, value_a)]);
3278
3279 Ok(())
3280 }
3281}