Skip to main content

reth_evm/
database.rs

1//! State provider database adapter used by EVM execution.
2
3#[cfg(feature = "std")]
4use alloy_primitives::{Address, B256};
5use core::ops::{Deref, DerefMut};
6#[cfg(feature = "std")]
7use evm2::{
8    bytecode::Bytecode,
9    evm::{AccountInfo, Database},
10    interpreter::Word,
11};
12#[cfg(feature = "std")]
13use reth_storage_api::EvmStateProvider;
14#[cfg(feature = "std")]
15use reth_storage_errors::provider::ProviderError;
16
17/// A database wrapper backed by a [`reth_storage_api::EvmStateProvider`].
18#[derive(Clone)]
19pub struct StateProviderDatabase<DB>(pub DB);
20
21impl<DB> StateProviderDatabase<DB> {
22    /// Creates a new database wrapper with the given state provider.
23    pub const fn new(db: DB) -> Self {
24        Self(db)
25    }
26
27    /// Consumes the wrapper and returns the inner state provider.
28    pub fn into_inner(self) -> DB {
29        self.0
30    }
31}
32
33impl<DB> core::fmt::Debug for StateProviderDatabase<DB> {
34    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
35        f.debug_struct("StateProviderDatabase").finish_non_exhaustive()
36    }
37}
38
39impl<DB> AsRef<DB> for StateProviderDatabase<DB> {
40    fn as_ref(&self) -> &DB {
41        &self.0
42    }
43}
44
45impl<DB> Deref for StateProviderDatabase<DB> {
46    type Target = DB;
47
48    fn deref(&self) -> &Self::Target {
49        &self.0
50    }
51}
52
53impl<DB> DerefMut for StateProviderDatabase<DB> {
54    fn deref_mut(&mut self) -> &mut Self::Target {
55        &mut self.0
56    }
57}
58
59#[cfg(feature = "std")]
60impl<DB> Database for StateProviderDatabase<DB>
61where
62    DB: EvmStateProvider,
63{
64    type Error = ProviderError;
65
66    fn get_account(&mut self, address: &Address) -> Result<Option<AccountInfo>, Self::Error> {
67        Ok(self.0.basic_account(address)?.map(Into::into))
68    }
69
70    fn get_code_by_hash(&mut self, code_hash: &B256) -> Result<Bytecode, Self::Error> {
71        Ok(self.0.bytecode_by_hash(code_hash)?.map(|code| code.0).unwrap_or_default())
72    }
73
74    fn get_storage(&mut self, address: &Address, key: &Word) -> Result<Word, Self::Error> {
75        Ok(self.0.storage(*address, B256::from(*key))?.unwrap_or_default())
76    }
77
78    fn get_block_hash(&mut self, number: &Word) -> Result<B256, Self::Error> {
79        let number = number.saturating_to::<u64>();
80        Ok(self.0.block_hash(number)?.unwrap_or_default())
81    }
82}
83
84#[cfg(all(test, feature = "std"))]
85mod tests {
86    use super::*;
87    use reth_storage_api::{noop::NoopProvider, StateProvider};
88
89    #[test]
90    fn missing_block_hash_returns_zero() {
91        let mut native =
92            StateProviderDatabase::new(NoopProvider::mainnet().into_evm_state_provider());
93        assert_eq!(native.get_block_hash(&Word::from(42)).unwrap(), B256::ZERO);
94    }
95}