1use crate::{
4 AccountReader, BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader,
5 BlockReader, BlockReaderIdExt, BlockSource, BytecodeReader, ChangeSetReader,
6 HashedPostStateProvider, HeaderProvider, NodePrimitivesProvider, PruneCheckpointReader,
7 ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateProofProvider,
8 StateProvider, StateProviderBox, StateProviderFactory, StateReader, StateRootProvider,
9 StorageRootProvider, TransactionVariant, TransactionsProvider,
10};
11
12#[cfg(feature = "db-api")]
13use crate::{DBProvider, DatabaseProviderFactory};
14use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
15use alloy_consensus::transaction::TransactionMeta;
16use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumberOrTag};
17use alloy_primitives::{
18 Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, TxHash, TxNumber, B256, U256,
19};
20use core::{
21 fmt::Debug,
22 marker::PhantomData,
23 ops::{RangeBounds, RangeInclusive},
24};
25use reth_chainspec::{ChainInfo, ChainSpecProvider, EthChainSpec, MAINNET};
26#[cfg(feature = "db-api")]
27use reth_db_api::mock::{DatabaseMock, TxMock};
28use reth_db_models::{AccountBeforeTx, StoredBlockBodyIndices};
29use reth_ethereum_primitives::EthPrimitives;
30use reth_execution_types::ExecutionOutcome;
31use reth_primitives_traits::{Account, Bytecode, NodePrimitives, RecoveredBlock, SealedHeader};
32#[cfg(feature = "db-api")]
33use reth_prune_types::PruneModes;
34use reth_prune_types::{PruneCheckpoint, PruneSegment};
35use reth_stages_types::{StageCheckpoint, StageId};
36use reth_storage_errors::provider::{ProviderError, ProviderResult};
37use reth_trie_common::{
38 updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
39 MultiProofTargets, StorageMultiProof, StorageProof, TrieInput,
40};
41
42#[derive(Debug)]
44#[non_exhaustive]
45pub struct NoopProvider<ChainSpec = reth_chainspec::ChainSpec, N = EthPrimitives> {
46 chain_spec: Arc<ChainSpec>,
47 #[cfg(feature = "db-api")]
48 tx: TxMock,
49 #[cfg(feature = "db-api")]
50 prune_modes: PruneModes,
51 _phantom: PhantomData<N>,
52}
53
54impl<ChainSpec, N> NoopProvider<ChainSpec, N> {
55 pub fn new(chain_spec: Arc<ChainSpec>) -> Self {
57 Self {
58 chain_spec,
59 #[cfg(feature = "db-api")]
60 tx: TxMock::default(),
61 #[cfg(feature = "db-api")]
62 prune_modes: PruneModes::none(),
63 _phantom: Default::default(),
64 }
65 }
66}
67
68impl<ChainSpec> NoopProvider<ChainSpec> {
69 pub fn eth(chain_spec: Arc<ChainSpec>) -> Self {
71 Self {
72 chain_spec,
73 #[cfg(feature = "db-api")]
74 tx: TxMock::default(),
75 #[cfg(feature = "db-api")]
76 prune_modes: PruneModes::none(),
77 _phantom: Default::default(),
78 }
79 }
80}
81
82impl NoopProvider {
83 pub fn mainnet() -> Self {
85 Self::eth(MAINNET.clone())
86 }
87}
88
89impl Default for NoopProvider {
90 fn default() -> Self {
91 Self::mainnet()
92 }
93}
94
95impl<ChainSpec, N> Clone for NoopProvider<ChainSpec, N> {
96 fn clone(&self) -> Self {
97 Self {
98 chain_spec: Arc::clone(&self.chain_spec),
99 #[cfg(feature = "db-api")]
100 tx: self.tx.clone(),
101 #[cfg(feature = "db-api")]
102 prune_modes: self.prune_modes.clone(),
103 _phantom: Default::default(),
104 }
105 }
106}
107
108impl<ChainSpec: Send + Sync, N: Send + Sync> BlockHashReader for NoopProvider<ChainSpec, N> {
110 fn block_hash(&self, _number: u64) -> ProviderResult<Option<B256>> {
111 Ok(None)
112 }
113
114 fn canonical_hashes_range(
115 &self,
116 _start: BlockNumber,
117 _end: BlockNumber,
118 ) -> ProviderResult<Vec<B256>> {
119 Ok(Vec::new())
120 }
121}
122
123impl<ChainSpec: Send + Sync, N: Send + Sync> BlockNumReader for NoopProvider<ChainSpec, N> {
124 fn chain_info(&self) -> ProviderResult<ChainInfo> {
125 Ok(ChainInfo::default())
126 }
127
128 fn best_block_number(&self) -> ProviderResult<BlockNumber> {
129 Ok(0)
130 }
131
132 fn last_block_number(&self) -> ProviderResult<BlockNumber> {
133 Ok(0)
134 }
135
136 fn block_number(&self, _hash: B256) -> ProviderResult<Option<BlockNumber>> {
137 Ok(None)
138 }
139}
140
141impl<ChainSpec: EthChainSpec + 'static, N: Debug + Send + Sync + 'static> ChainSpecProvider
142 for NoopProvider<ChainSpec, N>
143{
144 type ChainSpec = ChainSpec;
145
146 fn chain_spec(&self) -> Arc<Self::ChainSpec> {
147 self.chain_spec.clone()
148 }
149}
150
151impl<C: Send + Sync, N: NodePrimitives> BlockIdReader for NoopProvider<C, N> {
152 fn pending_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
153 Ok(None)
154 }
155
156 fn safe_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
157 Ok(None)
158 }
159
160 fn finalized_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
161 Ok(None)
162 }
163}
164
165impl<C: Send + Sync, N: NodePrimitives> BlockReaderIdExt for NoopProvider<C, N> {
166 fn block_by_id(&self, _id: BlockId) -> ProviderResult<Option<N::Block>> {
167 Ok(None)
168 }
169
170 fn sealed_header_by_id(
171 &self,
172 _id: BlockId,
173 ) -> ProviderResult<Option<SealedHeader<N::BlockHeader>>> {
174 Ok(None)
175 }
176
177 fn header_by_id(&self, _id: BlockId) -> ProviderResult<Option<N::BlockHeader>> {
178 Ok(None)
179 }
180}
181
182impl<C: Send + Sync, N: NodePrimitives> BlockReader for NoopProvider<C, N> {
183 type Block = N::Block;
184
185 fn find_block_by_hash(
186 &self,
187 _hash: B256,
188 _source: BlockSource,
189 ) -> ProviderResult<Option<Self::Block>> {
190 Ok(None)
191 }
192
193 fn block(&self, _id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
194 Ok(None)
195 }
196
197 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
198 Ok(None)
199 }
200
201 fn pending_block_and_receipts(
202 &self,
203 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
204 Ok(None)
205 }
206
207 fn recovered_block(
208 &self,
209 _id: BlockHashOrNumber,
210 _transaction_kind: TransactionVariant,
211 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
212 Ok(None)
213 }
214
215 fn sealed_block_with_senders(
216 &self,
217 _id: BlockHashOrNumber,
218 _transaction_kind: TransactionVariant,
219 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
220 Ok(None)
221 }
222
223 fn block_range(&self, _range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
224 Ok(Vec::new())
225 }
226
227 fn block_with_senders_range(
228 &self,
229 _range: RangeInclusive<BlockNumber>,
230 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
231 Ok(Vec::new())
232 }
233
234 fn recovered_block_range(
235 &self,
236 _range: RangeInclusive<BlockNumber>,
237 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
238 Ok(Vec::new())
239 }
240}
241
242impl<C: Send + Sync, N: NodePrimitives> TransactionsProvider for NoopProvider<C, N> {
243 type Transaction = N::SignedTx;
244
245 fn transaction_id(&self, _tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
246 Ok(None)
247 }
248
249 fn transaction_by_id(&self, _id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
250 Ok(None)
251 }
252
253 fn transaction_by_id_unhashed(
254 &self,
255 _id: TxNumber,
256 ) -> ProviderResult<Option<Self::Transaction>> {
257 Ok(None)
258 }
259
260 fn transaction_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
261 Ok(None)
262 }
263
264 fn transaction_by_hash_with_meta(
265 &self,
266 _hash: TxHash,
267 ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
268 Ok(None)
269 }
270
271 fn transaction_block(&self, _id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
272 Ok(None)
273 }
274
275 fn transactions_by_block(
276 &self,
277 _block_id: BlockHashOrNumber,
278 ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
279 Ok(None)
280 }
281
282 fn transactions_by_block_range(
283 &self,
284 _range: impl RangeBounds<BlockNumber>,
285 ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
286 Ok(Vec::default())
287 }
288
289 fn transactions_by_tx_range(
290 &self,
291 _range: impl RangeBounds<TxNumber>,
292 ) -> ProviderResult<Vec<Self::Transaction>> {
293 Ok(Vec::default())
294 }
295
296 fn senders_by_tx_range(
297 &self,
298 _range: impl RangeBounds<TxNumber>,
299 ) -> ProviderResult<Vec<Address>> {
300 Ok(Vec::default())
301 }
302
303 fn transaction_sender(&self, _id: TxNumber) -> ProviderResult<Option<Address>> {
304 Ok(None)
305 }
306}
307
308impl<C: Send + Sync, N: NodePrimitives> ReceiptProvider for NoopProvider<C, N> {
309 type Receipt = N::Receipt;
310
311 fn receipt(&self, _id: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
312 Ok(None)
313 }
314
315 fn receipt_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
316 Ok(None)
317 }
318
319 fn receipts_by_block(
320 &self,
321 _block: BlockHashOrNumber,
322 ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
323 Ok(None)
324 }
325
326 fn receipts_by_tx_range(
327 &self,
328 _range: impl RangeBounds<TxNumber>,
329 ) -> ProviderResult<Vec<Self::Receipt>> {
330 Ok(Vec::new())
331 }
332
333 fn receipts_by_block_range(
334 &self,
335 _block_range: RangeInclusive<BlockNumber>,
336 ) -> ProviderResult<Vec<Vec<Self::Receipt>>> {
337 Ok(Vec::new())
338 }
339}
340
341impl<C: Send + Sync, N: NodePrimitives> ReceiptProviderIdExt for NoopProvider<C, N> {}
342
343impl<C: Send + Sync, N: NodePrimitives> HeaderProvider for NoopProvider<C, N> {
344 type Header = N::BlockHeader;
345
346 fn header(&self, _block_hash: &BlockHash) -> ProviderResult<Option<Self::Header>> {
347 Ok(None)
348 }
349
350 fn header_by_number(&self, _num: u64) -> ProviderResult<Option<Self::Header>> {
351 Ok(None)
352 }
353
354 fn header_td(&self, _hash: &BlockHash) -> ProviderResult<Option<U256>> {
355 Ok(None)
356 }
357
358 fn header_td_by_number(&self, _number: BlockNumber) -> ProviderResult<Option<U256>> {
359 Ok(None)
360 }
361
362 fn headers_range(
363 &self,
364 _range: impl RangeBounds<BlockNumber>,
365 ) -> ProviderResult<Vec<Self::Header>> {
366 Ok(Vec::new())
367 }
368
369 fn sealed_header(
370 &self,
371 _number: BlockNumber,
372 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
373 Ok(None)
374 }
375
376 fn sealed_headers_while(
377 &self,
378 _range: impl RangeBounds<BlockNumber>,
379 _predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
380 ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
381 Ok(Vec::new())
382 }
383}
384
385impl<C: Send + Sync, N: NodePrimitives> AccountReader for NoopProvider<C, N> {
386 fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
387 Ok(None)
388 }
389}
390
391impl<C: Send + Sync, N: NodePrimitives> ChangeSetReader for NoopProvider<C, N> {
392 fn account_block_changeset(
393 &self,
394 _block_number: BlockNumber,
395 ) -> ProviderResult<Vec<AccountBeforeTx>> {
396 Ok(Vec::default())
397 }
398}
399
400impl<C: Send + Sync, N: NodePrimitives> StateRootProvider for NoopProvider<C, N> {
401 fn state_root(&self, _state: HashedPostState) -> ProviderResult<B256> {
402 Ok(B256::default())
403 }
404
405 fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
406 Ok(B256::default())
407 }
408
409 fn state_root_with_updates(
410 &self,
411 _state: HashedPostState,
412 ) -> ProviderResult<(B256, TrieUpdates)> {
413 Ok((B256::default(), TrieUpdates::default()))
414 }
415
416 fn state_root_from_nodes_with_updates(
417 &self,
418 _input: TrieInput,
419 ) -> ProviderResult<(B256, TrieUpdates)> {
420 Ok((B256::default(), TrieUpdates::default()))
421 }
422}
423
424impl<C: Send + Sync, N: NodePrimitives> StorageRootProvider for NoopProvider<C, N> {
425 fn storage_root(
426 &self,
427 _address: Address,
428 _hashed_storage: HashedStorage,
429 ) -> ProviderResult<B256> {
430 Ok(B256::default())
431 }
432
433 fn storage_proof(
434 &self,
435 _address: Address,
436 slot: B256,
437 _hashed_storage: HashedStorage,
438 ) -> ProviderResult<StorageProof> {
439 Ok(StorageProof::new(slot))
440 }
441
442 fn storage_multiproof(
443 &self,
444 _address: Address,
445 _slots: &[B256],
446 _hashed_storage: HashedStorage,
447 ) -> ProviderResult<StorageMultiProof> {
448 Ok(StorageMultiProof::empty())
449 }
450}
451
452impl<C: Send + Sync, N: NodePrimitives> StateProofProvider for NoopProvider<C, N> {
453 fn proof(
454 &self,
455 _input: TrieInput,
456 address: Address,
457 _slots: &[B256],
458 ) -> ProviderResult<AccountProof> {
459 Ok(AccountProof::new(address))
460 }
461
462 fn multiproof(
463 &self,
464 _input: TrieInput,
465 _targets: MultiProofTargets,
466 ) -> ProviderResult<MultiProof> {
467 Ok(MultiProof::default())
468 }
469
470 fn witness(&self, _input: TrieInput, _target: HashedPostState) -> ProviderResult<Vec<Bytes>> {
471 Ok(Vec::default())
472 }
473}
474
475impl<C: Send + Sync, N: NodePrimitives> HashedPostStateProvider for NoopProvider<C, N> {
476 fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
477 HashedPostState::default()
478 }
479}
480
481impl<C: Send + Sync, N: NodePrimitives> StateReader for NoopProvider<C, N> {
482 type Receipt = N::Receipt;
483
484 fn get_state(
485 &self,
486 _block: BlockNumber,
487 ) -> ProviderResult<Option<ExecutionOutcome<Self::Receipt>>> {
488 Ok(None)
489 }
490}
491
492impl<C: Send + Sync, N: NodePrimitives> StateProvider for NoopProvider<C, N> {
493 fn storage(
494 &self,
495 _account: Address,
496 _storage_key: StorageKey,
497 ) -> ProviderResult<Option<StorageValue>> {
498 Ok(None)
499 }
500}
501
502impl<C: Send + Sync, N: NodePrimitives> BytecodeReader for NoopProvider<C, N> {
503 fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
504 Ok(None)
505 }
506}
507
508impl<C: Send + Sync + 'static, N: NodePrimitives> StateProviderFactory for NoopProvider<C, N> {
509 fn latest(&self) -> ProviderResult<StateProviderBox> {
510 Ok(Box::new(self.clone()))
511 }
512
513 fn state_by_block_number_or_tag(
514 &self,
515 number_or_tag: BlockNumberOrTag,
516 ) -> ProviderResult<StateProviderBox> {
517 match number_or_tag {
518 BlockNumberOrTag::Latest => self.latest(),
519 BlockNumberOrTag::Finalized => {
520 let hash =
522 self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
523
524 self.history_by_block_hash(hash)
526 }
527 BlockNumberOrTag::Safe => {
528 let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
530
531 self.history_by_block_hash(hash)
532 }
533 BlockNumberOrTag::Earliest => {
534 self.history_by_block_number(self.earliest_block_number()?)
535 }
536 BlockNumberOrTag::Pending => self.pending(),
537 BlockNumberOrTag::Number(num) => self.history_by_block_number(num),
538 }
539 }
540
541 fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox> {
542 Ok(Box::new(self.clone()))
543 }
544
545 fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
546 Ok(Box::new(self.clone()))
547 }
548
549 fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
550 Ok(Box::new(self.clone()))
551 }
552
553 fn pending(&self) -> ProviderResult<StateProviderBox> {
554 Ok(Box::new(self.clone()))
555 }
556
557 fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
558 Ok(Some(Box::new(self.clone())))
559 }
560}
561
562impl<C: Send + Sync, N: NodePrimitives> StageCheckpointReader for NoopProvider<C, N> {
563 fn get_stage_checkpoint(&self, _id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
564 Ok(None)
565 }
566
567 fn get_stage_checkpoint_progress(&self, _id: StageId) -> ProviderResult<Option<Vec<u8>>> {
568 Ok(None)
569 }
570
571 fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
572 Ok(Vec::new())
573 }
574}
575
576impl<C: Send + Sync, N: NodePrimitives> PruneCheckpointReader for NoopProvider<C, N> {
577 fn get_prune_checkpoint(
578 &self,
579 _segment: PruneSegment,
580 ) -> ProviderResult<Option<PruneCheckpoint>> {
581 Ok(None)
582 }
583
584 fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
585 Ok(Vec::new())
586 }
587}
588
589impl<C: Send + Sync, N: NodePrimitives> NodePrimitivesProvider for NoopProvider<C, N> {
590 type Primitives = N;
591}
592
593impl<C: Send + Sync, N: Send + Sync> BlockBodyIndicesProvider for NoopProvider<C, N> {
594 fn block_body_indices(&self, _num: u64) -> ProviderResult<Option<StoredBlockBodyIndices>> {
595 Ok(None)
596 }
597
598 fn block_body_indices_range(
599 &self,
600 _range: RangeInclusive<BlockNumber>,
601 ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
602 Ok(Vec::new())
603 }
604}
605
606#[cfg(feature = "db-api")]
607impl<ChainSpec: Send + Sync, N: NodePrimitives> DBProvider for NoopProvider<ChainSpec, N> {
608 type Tx = TxMock;
609
610 fn tx_ref(&self) -> &Self::Tx {
611 &self.tx
612 }
613
614 fn tx_mut(&mut self) -> &mut Self::Tx {
615 &mut self.tx
616 }
617
618 fn into_tx(self) -> Self::Tx {
619 self.tx
620 }
621
622 fn prune_modes_ref(&self) -> &PruneModes {
623 &self.prune_modes
624 }
625}
626
627#[cfg(feature = "db-api")]
628impl<ChainSpec: Send + Sync, N: NodePrimitives> DatabaseProviderFactory
629 for NoopProvider<ChainSpec, N>
630{
631 type DB = DatabaseMock;
632 type Provider = Self;
633 type ProviderRW = Self;
634
635 fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
636 Ok(self.clone())
637 }
638
639 fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
640 Ok(self.clone())
641 }
642}