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