reth_provider/providers/
consistent_view.rs1use crate::{BlockNumReader, DatabaseProviderFactory, HeaderProvider};
2use alloy_primitives::B256;
3use reth_errors::ProviderError;
4use reth_primitives::GotExpected;
5use reth_storage_api::{BlockReader, DBProvider, StateCommitmentProvider};
6use reth_storage_errors::provider::ProviderResult;
7
8use reth_trie::HashedPostState;
9use reth_trie_db::{DatabaseHashedPostState, StateCommitment};
10
11pub use reth_storage_errors::provider::ConsistentViewError;
12
13#[derive(Clone, Debug)]
29pub struct ConsistentDbView<Factory> {
30 factory: Factory,
31 tip: Option<B256>,
32}
33
34impl<Factory> ConsistentDbView<Factory>
35where
36 Factory: DatabaseProviderFactory<Provider: BlockReader> + StateCommitmentProvider,
37{
38 pub const fn new(factory: Factory, tip: Option<B256>) -> Self {
40 Self { factory, tip }
41 }
42
43 pub fn new_with_latest_tip(provider: Factory) -> ProviderResult<Self> {
45 let provider_ro = provider.database_provider_ro()?;
46 let last_num = provider_ro.last_block_number()?;
47 let tip = provider_ro.sealed_header(last_num)?.map(|h| h.hash());
48 Ok(Self::new(provider, tip))
49 }
50
51 pub fn revert_state(&self, block_hash: B256) -> ProviderResult<HashedPostState> {
53 let provider = self.provider_ro()?;
54 let block_number = provider
55 .block_number(block_hash)?
56 .ok_or(ProviderError::BlockHashNotFound(block_hash))?;
57 if block_number == provider.best_block_number()? &&
58 block_number == provider.last_block_number()?
59 {
60 Ok(HashedPostState::default())
61 } else {
62 Ok(HashedPostState::from_reverts::<
63 <Factory::StateCommitment as StateCommitment>::KeyHasher,
64 >(provider.tx_ref(), block_number + 1)?)
65 }
66 }
67
68 pub fn provider_ro(&self) -> ProviderResult<Factory::Provider> {
70 let provider_ro = self.factory.database_provider_ro()?;
72
73 let last_num = provider_ro.last_block_number()?;
79 let tip = provider_ro.sealed_header(last_num)?.map(|h| h.hash());
80 if self.tip != tip {
81 return Err(ConsistentViewError::Inconsistent {
82 tip: GotExpected { got: tip, expected: self.tip },
83 }
84 .into())
85 }
86
87 let best_block_number = provider_ro.best_block_number()?;
91 if last_num != best_block_number {
92 return Err(ConsistentViewError::Syncing {
93 best_block: GotExpected { got: best_block_number, expected: last_num },
94 }
95 .into())
96 }
97
98 Ok(provider_ro)
99 }
100}