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        Ok(StateRoot::overlay_root(self.tx(), &hashed_state.into_sorted())?)
63    }
64
65    fn state_root_from_nodes(&self, input: TrieInput) -> ProviderResult<B256> {
66        Ok(StateRoot::overlay_root_from_nodes(self.tx(), TrieInputSorted::from_unsorted(input))?)
67    }
68
69    fn state_root_with_updates(
70        &self,
71        hashed_state: HashedPostState,
72    ) -> ProviderResult<(B256, TrieUpdates)> {
73        Ok(StateRoot::overlay_root_with_updates(self.tx(), &hashed_state.into_sorted())?)
74    }
75
76    fn state_root_from_nodes_with_updates(
77        &self,
78        input: TrieInput,
79    ) -> ProviderResult<(B256, TrieUpdates)> {
80        Ok(StateRoot::overlay_root_from_nodes_with_updates(
81            self.tx(),
82            TrieInputSorted::from_unsorted(input),
83        )?)
84    }
85}
86
87impl<Provider: DBProvider> StorageRootProvider for LatestStateProviderRef<'_, Provider> {
88    fn storage_root(
89        &self,
90        address: Address,
91        hashed_storage: HashedStorage,
92    ) -> ProviderResult<B256> {
93        StorageRoot::overlay_root(self.tx(), address, hashed_storage)
94            .map_err(|err| ProviderError::Database(err.into()))
95    }
96
97    fn storage_proof(
98        &self,
99        address: Address,
100        slot: B256,
101        hashed_storage: HashedStorage,
102    ) -> ProviderResult<reth_trie::StorageProof> {
103        StorageProof::overlay_storage_proof(self.tx(), address, slot, hashed_storage)
104            .map_err(ProviderError::from)
105    }
106
107    fn storage_multiproof(
108        &self,
109        address: Address,
110        slots: &[B256],
111        hashed_storage: HashedStorage,
112    ) -> ProviderResult<StorageMultiProof> {
113        StorageProof::overlay_storage_multiproof(self.tx(), address, slots, hashed_storage)
114            .map_err(ProviderError::from)
115    }
116}
117
118impl<Provider: DBProvider> StateProofProvider for LatestStateProviderRef<'_, Provider> {
119    fn proof(
120        &self,
121        input: TrieInput,
122        address: Address,
123        slots: &[B256],
124    ) -> ProviderResult<AccountProof> {
125        let proof = <Proof<_, _> as DatabaseProof>::from_tx(self.tx());
126        proof.overlay_account_proof(input, address, slots).map_err(ProviderError::from)
127    }
128
129    fn multiproof(
130        &self,
131        input: TrieInput,
132        targets: MultiProofTargets,
133    ) -> ProviderResult<MultiProof> {
134        let proof = <Proof<_, _> as DatabaseProof>::from_tx(self.tx());
135        proof.overlay_multiproof(input, targets).map_err(ProviderError::from)
136    }
137
138    fn witness(&self, input: TrieInput, target: HashedPostState) -> ProviderResult<Vec<Bytes>> {
139        TrieWitness::overlay_witness(self.tx(), input, target)
140            .map_err(ProviderError::from)
141            .map(|hm| hm.into_values().collect())
142    }
143}
144
145impl<Provider: DBProvider> HashedPostStateProvider for LatestStateProviderRef<'_, Provider> {
146    fn hashed_post_state(&self, bundle_state: &revm_database::BundleState) -> HashedPostState {
147        HashedPostState::from_bundle_state::<KeccakKeyHasher>(bundle_state.state())
148    }
149}
150
151impl<Provider: DBProvider + BlockHashReader> StateProvider
152    for LatestStateProviderRef<'_, Provider>
153{
154    /// Get storage.
155    fn storage(
156        &self,
157        account: Address,
158        storage_key: StorageKey,
159    ) -> ProviderResult<Option<StorageValue>> {
160        let mut cursor = self.tx().cursor_dup_read::<tables::PlainStorageState>()?;
161        if let Some(entry) = cursor.seek_by_key_subkey(account, storage_key)? &&
162            entry.key == storage_key
163        {
164            return Ok(Some(entry.value))
165        }
166        Ok(None)
167    }
168}
169
170impl<Provider: DBProvider + BlockHashReader> BytecodeReader
171    for LatestStateProviderRef<'_, Provider>
172{
173    /// Get account code by its hash
174    fn bytecode_by_hash(&self, code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
175        self.tx().get_by_encoded_key::<tables::Bytecodes>(code_hash).map_err(Into::into)
176    }
177}
178
179/// State provider for the latest state.
180#[derive(Debug)]
181pub struct LatestStateProvider<Provider>(Provider);
182
183impl<Provider: DBProvider> LatestStateProvider<Provider> {
184    /// Create new state provider
185    pub const fn new(db: Provider) -> Self {
186        Self(db)
187    }
188
189    /// Returns a new provider that takes the `TX` as reference
190    #[inline(always)]
191    const fn as_ref(&self) -> LatestStateProviderRef<'_, Provider> {
192        LatestStateProviderRef::new(&self.0)
193    }
194}
195
196// Delegates all provider impls to [LatestStateProviderRef]
197reth_storage_api::macros::delegate_provider_impls!(LatestStateProvider<Provider> where [Provider: DBProvider + BlockHashReader ]);
198
199#[cfg(test)]
200mod tests {
201    use super::*;
202
203    const fn assert_state_provider<T: StateProvider>() {}
204    #[expect(dead_code)]
205    const fn assert_latest_state_provider<T: DBProvider + BlockHashReader>() {
206        assert_state_provider::<LatestStateProvider<T>>();
207    }
208}