reth_provider/providers/state/
latest.rs

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