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