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