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