diff --git a/crates/interpreter/src/gas.rs b/crates/interpreter/src/gas.rs index a7797186c8..79d6f3905d 100644 --- a/crates/interpreter/src/gas.rs +++ b/crates/interpreter/src/gas.rs @@ -109,9 +109,9 @@ impl Gas { true } - #[inline] - #[deprecated = "Use `record_refund` instead"] #[doc(hidden)] + #[deprecated = "use `record_refund` instead"] + #[inline] pub fn gas_refund(&mut self, refund: i64) { self.record_refund(refund); } diff --git a/crates/primitives/src/db.rs b/crates/primitives/src/db.rs index ce3334d9b4..f376bd6f1e 100644 --- a/crates/primitives/src/db.rs +++ b/crates/primitives/src/db.rs @@ -1,5 +1,3 @@ -pub mod components; - use crate::AccountInfo; use crate::U256; use crate::{Account, Bytecode}; @@ -7,21 +5,26 @@ use crate::{B160, B256}; use auto_impl::auto_impl; use hashbrown::HashMap as Map; +pub mod components; pub use components::{ BlockHash, BlockHashRef, DatabaseComponentError, DatabaseComponents, State, StateRef, }; +/// EVM database interface. #[auto_impl(&mut, Box)] pub trait Database { type Error; + /// Get basic account information. fn basic(&mut self, address: B160) -> Result, Self::Error>; - /// Get account code by its hash + + /// Get account code by its hash. fn code_by_hash(&mut self, code_hash: B256) -> Result; + /// Get storage value of address at index. fn storage(&mut self, address: B160, index: U256) -> Result; - // History related + /// Get block hash by block number. fn block_hash(&mut self, number: U256) -> Result; } @@ -36,39 +39,46 @@ pub trait DatabaseCommit { fn commit(&mut self, changes: Map); } +/// Same as [Database], but uses immutable references. #[auto_impl(&, Box, Arc)] pub trait DatabaseRef { type Error; - /// Whether account at address exists. - //fn exists(&self, address: B160) -> Option; + /// Get basic account information. fn basic(&self, address: B160) -> Result, Self::Error>; - /// Get account code by its hash + + /// Get account code by its hash. fn code_by_hash(&self, code_hash: B256) -> Result; + /// Get storage value of address at index. fn storage(&self, address: B160, index: U256) -> Result; - // History related + /// Get block hash by block number. fn block_hash(&self, number: U256) -> Result; } +/// Wraps a [`DatabaseRef`] to provide a [`Database`] implementation. pub struct WrapDatabaseRef(pub T); impl Database for WrapDatabaseRef { type Error = T::Error; + #[inline] fn basic(&mut self, address: B160) -> Result, Self::Error> { self.0.basic(address) } + #[inline] fn code_by_hash(&mut self, code_hash: B256) -> Result { self.0.code_by_hash(code_hash) } + #[inline] fn storage(&mut self, address: B160, index: U256) -> Result { self.0.storage(address, index) } + #[inline] fn block_hash(&mut self, number: U256) -> Result { self.0.block_hash(number) } diff --git a/crates/revm/src/db/emptydb.rs b/crates/revm/src/db/emptydb.rs index 65bc67cab3..eeaaaf928d 100644 --- a/crates/revm/src/db/emptydb.rs +++ b/crates/revm/src/db/emptydb.rs @@ -1,80 +1,106 @@ -use core::{convert::Infallible, marker::PhantomData}; +use core::{convert::Infallible, fmt, marker::PhantomData}; use revm_interpreter::primitives::{ db::{Database, DatabaseRef}, - keccak256, AccountInfo, Bytecode, B160, B256, U256, + AccountInfo, Bytecode, B160, B256, U256, }; +/// An empty database that always returns default values when queried. pub type EmptyDB = EmptyDBTyped; -impl Default for EmptyDB { +/// An empty database that always returns default values when queried. +/// +/// This is generic over a type which is used as the database error type. +pub struct EmptyDBTyped { + _phantom: PhantomData, +} + +// Don't derive traits, because the type parameter is unused. +impl Clone for EmptyDBTyped { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for EmptyDBTyped {} + +impl Default for EmptyDBTyped { fn default() -> Self { - Self { - keccak_block_hash: false, - _phantom: PhantomData, - } + Self::new() } } -/// An empty database that always returns default values when queried. -#[derive(Debug, Clone)] -pub struct EmptyDBTyped { - pub keccak_block_hash: bool, - pub _phantom: PhantomData, +impl fmt::Debug for EmptyDBTyped { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EmptyDB").finish_non_exhaustive() + } +} + +impl PartialEq for EmptyDBTyped { + fn eq(&self, _: &Self) -> bool { + true + } } -impl EmptyDBTyped { +impl Eq for EmptyDBTyped {} + +impl EmptyDBTyped { pub fn new() -> Self { Self { - keccak_block_hash: false, _phantom: PhantomData, } } + #[doc(hidden)] + #[deprecated = "use `new` instead"] pub fn new_keccak_block_hash() -> Self { - Self { - keccak_block_hash: true, - _phantom: PhantomData, - } + Self::new() } } -impl Database for EmptyDBTyped { - type Error = T; +impl Database for EmptyDBTyped { + type Error = E; + #[inline] fn basic(&mut self, address: B160) -> Result, Self::Error> { ::basic(self, address) } + #[inline] fn code_by_hash(&mut self, code_hash: B256) -> Result { ::code_by_hash(self, code_hash) } + #[inline] fn storage(&mut self, address: B160, index: U256) -> Result { ::storage(self, address, index) } + #[inline] fn block_hash(&mut self, number: U256) -> Result { ::block_hash(self, number) } } -impl DatabaseRef for EmptyDBTyped { - type Error = T; - /// Get basic account information. +impl DatabaseRef for EmptyDBTyped { + type Error = E; + + #[inline] fn basic(&self, _address: B160) -> Result, Self::Error> { Ok(None) } - /// Get account code by its hash + + #[inline] fn code_by_hash(&self, _code_hash: B256) -> Result { Ok(Bytecode::new()) } - /// Get storage value of address at index. + + #[inline] fn storage(&self, _address: B160, _index: U256) -> Result { Ok(U256::default()) } - // History related + #[inline] fn block_hash(&self, number: U256) -> Result { - Ok(keccak256(&number.to_be_bytes::<{ U256::BYTES }>())) + Ok(number.to_be_bytes().into()) } } diff --git a/crates/revm/src/db/ethersdb.rs b/crates/revm/src/db/ethersdb.rs index 2de1307df7..69bbc6b5b8 100644 --- a/crates/revm/src/db/ethersdb.rs +++ b/crates/revm/src/db/ethersdb.rs @@ -5,19 +5,13 @@ use ethers_providers::Middleware; use std::sync::Arc; use tokio::runtime::{Handle, Runtime}; -pub struct EthersDB -where - M: Middleware, -{ +pub struct EthersDB { client: Arc, runtime: Option, block_number: Option, } -impl EthersDB -where - M: Middleware, -{ +impl EthersDB { /// create ethers db connector inputs are url and block on what we are basing our database (None for latest) pub fn new(client: Arc, block_number: Option) -> Option { let runtime = Handle::try_current() @@ -52,10 +46,7 @@ where } } -impl Database for EthersDB -where - M: Middleware, -{ +impl Database for EthersDB { type Error = (); fn basic(&mut self, address: B160) -> Result, Self::Error> { @@ -124,14 +115,13 @@ where } } -/// Run tests with `cargo test -- --nocapture` to see print statements +// Run tests with `cargo test -- --nocapture` to see print statements #[cfg(test)] mod tests { - use std::str::FromStr; - use super::*; use ethers_core::types::U256 as eU256; use ethers_providers::{Http, Provider}; + use std::str::FromStr; #[test] fn can_get_basic() { diff --git a/crates/revm/src/db/in_memory_db.rs b/crates/revm/src/db/in_memory_db.rs index 521bb77af2..648513c2cc 100644 --- a/crates/revm/src/db/in_memory_db.rs +++ b/crates/revm/src/db/in_memory_db.rs @@ -6,17 +6,9 @@ use crate::Database; use alloc::vec::Vec; use core::convert::Infallible; +/// A [Database] implementation that stores all state changes in memory. pub type InMemoryDB = CacheDB; -impl Default for InMemoryDB { - fn default() -> Self { - CacheDB::new(EmptyDB { - keccak_block_hash: true, - _phantom: core::marker::PhantomData, - }) - } -} - /// A [Database] implementation that stores all state changes in memory. /// /// This implementation wraps a [DatabaseRef] that is used to load data ([AccountInfo]). @@ -41,6 +33,12 @@ pub struct CacheDB { pub db: ExtDB, } +impl Default for CacheDB { + fn default() -> Self { + Self::new(ExtDB::default()) + } +} + impl CacheDB { pub fn new(db: ExtDB) -> Self { let mut contracts = HashMap::new(); @@ -302,6 +300,7 @@ impl DbAccount { ..Default::default() } } + pub fn info(&self) -> Option { if matches!(self.account_state, AccountState::NotExisting) { None @@ -313,15 +312,7 @@ impl DbAccount { impl From> for DbAccount { fn from(from: Option) -> Self { - if let Some(info) = from { - Self { - info, - account_state: AccountState::None, - ..Default::default() - } - } else { - Self::new_not_existing() - } + from.map(Self::from).unwrap_or_else(Self::new_not_existing) } } diff --git a/crates/revm/src/db/states/state.rs b/crates/revm/src/db/states/state.rs index fcbd59109f..80b4d793d9 100644 --- a/crates/revm/src/db/states/state.rs +++ b/crates/revm/src/db/states/state.rs @@ -295,7 +295,7 @@ mod tests { states::reverts::AccountInfoRevert, AccountRevert, AccountStatus, BundleAccount, RevertToSlot, }; - use revm_interpreter::primitives::{keccak256, StorageSlot}; + use revm_interpreter::primitives::StorageSlot; #[test] fn block_hash_cache() { @@ -305,9 +305,9 @@ mod tests { let test_number = BLOCK_HASH_HISTORY as u64 + 2; - let block1_hash = keccak256(&U256::from(1).to_be_bytes::<{ U256::BYTES }>()); - let block2_hash = keccak256(&U256::from(2).to_be_bytes::<{ U256::BYTES }>()); - let block_test_hash = keccak256(&U256::from(test_number).to_be_bytes::<{ U256::BYTES }>()); + let block1_hash = B256::from(U256::from(1).to_be_bytes()); + let block2_hash = B256::from(U256::from(2).to_be_bytes()); + let block_test_hash = B256::from(U256::from(test_number).to_be_bytes()); assert_eq!( state.block_hashes,