reth_provider/providers/state/
latest.rs

1use crate::{
2    providers::state::macros::delegate_provider_impls, AccountReader, BlockHashReader,
3    HashedPostStateProvider, StateProvider, StateRootProvider,
4};
5use alloy_primitives::{Address, BlockNumber, Bytes, StorageKey, B256};
6use reth_db_api::{cursor::DbDupCursorRO, tables, transaction::DbTx};
7use reth_primitives_traits::{Account, Bytecode};
8use reth_storage_api::{
9    DBProvider, StateCommitmentProvider, StateProofProvider, StorageRootProvider,
10};
11use reth_storage_errors::provider::{ProviderError, ProviderResult};
12use reth_trie::{
13    proof::{Proof, StorageProof},
14    updates::TrieUpdates,
15    witness::TrieWitness,
16    AccountProof, HashedPostState, HashedStorage, MultiProof, MultiProofTargets, StateRoot,
17    StorageMultiProof, StorageRoot, TrieInput,
18};
19use reth_trie_db::{
20    DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot,
21    DatabaseTrieWitness, StateCommitment,
22};
23use revm_state::FlaggedStorage;
24
25/// State provider over latest state that takes tx reference.
26///
27/// Wraps a [`DBProvider`] to get access to database.
28#[derive(Debug)]
29pub struct LatestStateProviderRef<'b, Provider>(&'b Provider);
30
31impl<'b, Provider: DBProvider> LatestStateProviderRef<'b, Provider> {
32    /// Create new state provider
33    pub const fn new(provider: &'b Provider) -> Self {
34        Self(provider)
35    }
36
37    fn tx(&self) -> &Provider::Tx {
38        self.0.tx_ref()
39    }
40}
41
42impl<Provider: DBProvider> AccountReader for LatestStateProviderRef<'_, Provider> {
43    /// Get basic account information.
44    fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
45        self.tx().get_by_encoded_key::<tables::PlainAccountState>(address).map_err(Into::into)
46    }
47}
48
49impl<Provider: BlockHashReader> BlockHashReader for LatestStateProviderRef<'_, Provider> {
50    /// Get block hash by number.
51    fn block_hash(&self, number: u64) -> ProviderResult<Option<B256>> {
52        self.0.block_hash(number)
53    }
54
55    fn canonical_hashes_range(
56        &self,
57        start: BlockNumber,
58        end: BlockNumber,
59    ) -> ProviderResult<Vec<B256>> {
60        self.0.canonical_hashes_range(start, end)
61    }
62}
63
64impl<Provider: DBProvider + StateCommitmentProvider> StateRootProvider
65    for LatestStateProviderRef<'_, Provider>
66{
67    fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult<B256> {
68        StateRoot::overlay_root(self.tx(), hashed_state)
69            .map_err(|err| ProviderError::Database(err.into()))
70    }
71
72    fn state_root_from_nodes(&self, input: TrieInput) -> ProviderResult<B256> {
73        StateRoot::overlay_root_from_nodes(self.tx(), input)
74            .map_err(|err| ProviderError::Database(err.into()))
75    }
76
77    fn state_root_with_updates(
78        &self,
79        hashed_state: HashedPostState,
80    ) -> ProviderResult<(B256, TrieUpdates)> {
81        StateRoot::overlay_root_with_updates(self.tx(), hashed_state)
82            .map_err(|err| ProviderError::Database(err.into()))
83    }
84
85    fn state_root_from_nodes_with_updates(
86        &self,
87        input: TrieInput,
88    ) -> ProviderResult<(B256, TrieUpdates)> {
89        StateRoot::overlay_root_from_nodes_with_updates(self.tx(), input)
90            .map_err(|err| ProviderError::Database(err.into()))
91    }
92}
93
94impl<Provider: DBProvider + StateCommitmentProvider> StorageRootProvider
95    for LatestStateProviderRef<'_, Provider>
96{
97    fn storage_root(
98        &self,
99        address: Address,
100        hashed_storage: HashedStorage,
101    ) -> ProviderResult<B256> {
102        StorageRoot::overlay_root(self.tx(), address, hashed_storage)
103            .map_err(|err| ProviderError::Database(err.into()))
104    }
105
106    fn storage_proof(
107        &self,
108        address: Address,
109        slot: B256,
110        hashed_storage: HashedStorage,
111    ) -> ProviderResult<reth_trie::StorageProof> {
112        StorageProof::overlay_storage_proof(self.tx(), address, slot, hashed_storage)
113            .map_err(ProviderError::from)
114    }
115
116    fn storage_multiproof(
117        &self,
118        address: Address,
119        slots: &[B256],
120        hashed_storage: HashedStorage,
121    ) -> ProviderResult<StorageMultiProof> {
122        StorageProof::overlay_storage_multiproof(self.tx(), address, slots, hashed_storage)
123            .map_err(ProviderError::from)
124    }
125}
126
127impl<Provider: DBProvider + StateCommitmentProvider> StateProofProvider
128    for LatestStateProviderRef<'_, Provider>
129{
130    fn proof(
131        &self,
132        input: TrieInput,
133        address: Address,
134        slots: &[B256],
135    ) -> ProviderResult<AccountProof> {
136        Proof::overlay_account_proof(self.tx(), input, address, slots).map_err(ProviderError::from)
137    }
138
139    fn multiproof(
140        &self,
141        input: TrieInput,
142        targets: MultiProofTargets,
143    ) -> ProviderResult<MultiProof> {
144        Proof::overlay_multiproof(self.tx(), input, targets).map_err(ProviderError::from)
145    }
146
147    fn witness(&self, input: TrieInput, target: HashedPostState) -> ProviderResult<Vec<Bytes>> {
148        TrieWitness::overlay_witness(self.tx(), input, target)
149            .map_err(ProviderError::from)
150            .map(|hm| hm.into_values().collect())
151    }
152}
153
154impl<Provider: DBProvider + StateCommitmentProvider> HashedPostStateProvider
155    for LatestStateProviderRef<'_, Provider>
156{
157    fn hashed_post_state(&self, bundle_state: &revm_database::BundleState) -> HashedPostState {
158        HashedPostState::from_bundle_state::<
159            <Provider::StateCommitment as StateCommitment>::KeyHasher,
160        >(bundle_state.state())
161    }
162}
163
164impl<Provider: DBProvider + BlockHashReader + StateCommitmentProvider> StateProvider
165    for LatestStateProviderRef<'_, Provider>
166{
167    /// Get storage.
168    fn storage(
169        &self,
170        account: Address,
171        storage_key: StorageKey,
172    ) -> ProviderResult<Option<FlaggedStorage>> {
173        let mut cursor = self.tx().cursor_dup_read::<tables::PlainStorageState>()?;
174        if let Some(entry) = cursor.seek_by_key_subkey(account, storage_key)? {
175            if entry.key == storage_key {
176                return Ok(Some(entry.into()))
177            }
178        }
179        Ok(None)
180    }
181
182    /// Get account code by its hash
183    fn bytecode_by_hash(&self, code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
184        self.tx().get_by_encoded_key::<tables::Bytecodes>(code_hash).map_err(Into::into)
185    }
186}
187
188impl<Provider: StateCommitmentProvider> StateCommitmentProvider
189    for LatestStateProviderRef<'_, Provider>
190{
191    type StateCommitment = Provider::StateCommitment;
192}
193
194/// State provider for the latest state.
195#[derive(Debug)]
196pub struct LatestStateProvider<Provider>(Provider);
197
198impl<Provider: DBProvider + StateCommitmentProvider> LatestStateProvider<Provider> {
199    /// Create new state provider
200    pub const fn new(db: Provider) -> Self {
201        Self(db)
202    }
203
204    /// Returns a new provider that takes the `TX` as reference
205    #[inline(always)]
206    const fn as_ref(&self) -> LatestStateProviderRef<'_, Provider> {
207        LatestStateProviderRef::new(&self.0)
208    }
209}
210
211impl<Provider: StateCommitmentProvider> StateCommitmentProvider for LatestStateProvider<Provider> {
212    type StateCommitment = Provider::StateCommitment;
213}
214
215// Delegates all provider impls to [LatestStateProviderRef]
216delegate_provider_impls!(LatestStateProvider<Provider> where [Provider: DBProvider + BlockHashReader + StateCommitmentProvider]);
217
218#[cfg(test)]
219mod tests {
220    use super::*;
221
222    const fn assert_state_provider<T: StateProvider>() {}
223    #[expect(dead_code)]
224    const fn assert_latest_state_provider<
225        T: DBProvider + BlockHashReader + StateCommitmentProvider,
226    >() {
227        assert_state_provider::<LatestStateProvider<T>>();
228    }
229}