From c448b8a5cc13df31a9b9ec88536fe91b15f0d74d Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 1 Sep 2023 15:12:35 +0200 Subject: [PATCH 1/2] chore(state): Make database more generic --- crates/revm/src/db/states/state.rs | 20 +++++++++++--------- crates/revm/src/db/states/state_builder.rs | 19 +++++++++---------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/crates/revm/src/db/states/state.rs b/crates/revm/src/db/states/state.rs index 6ec5daba2c..de281ca6c7 100644 --- a/crates/revm/src/db/states/state.rs +++ b/crates/revm/src/db/states/state.rs @@ -9,11 +9,13 @@ use revm_interpreter::primitives::{ hash_map, Account, AccountInfo, Bytecode, HashMap, B160, B256, BLOCK_HASH_HISTORY, U256, }; +pub type StateDBBox<'a, DBError> = State + Send + 'a>>; + /// State of blockchain. /// /// State clear flag is set inside CacheState and by default it is enabled. /// If you want to disable it use `set_state_clear_flag` function. -pub struct State<'a, DBError> { +pub struct State { /// Cached state contains both changed from evm execution and cached/loaded account/storages /// from database. This allows us to have only one layer of cache where we can fetch data. /// Additionaly we can introduce some preloading of data from database. @@ -22,7 +24,7 @@ pub struct State<'a, DBError> { /// return not existing account and storage. /// /// Note: It is marked as Send so database can be shared between threads. - pub database: Box + Send + 'a>, + pub database: DB, //Box + Send + 'a>, /// Block state, it aggregates transactions transitions into one state. /// /// Build reverts and state that gets applied to the state. @@ -46,7 +48,7 @@ pub struct State<'a, DBError> { pub block_hashes: BTreeMap, } -impl<'a, DBError> State<'a, DBError> { +impl State { /// Iterate over received balances and increment all account balances. /// If account is not found inside cache state it will be loaded from database. /// @@ -54,7 +56,7 @@ impl<'a, DBError> State<'a, DBError> { pub fn increment_balances( &mut self, balances: impl IntoIterator, - ) -> Result<(), DBError> { + ) -> Result<(), DB::Error> { // make transition and update cache state let mut transitions = Vec::new(); for (address, balance) in balances { @@ -74,7 +76,7 @@ impl<'a, DBError> State<'a, DBError> { pub fn drain_balances( &mut self, addresses: impl IntoIterator, - ) -> Result, DBError> { + ) -> Result, DB::Error> { // make transition and update cache state let mut transitions = Vec::new(); let mut balances = Vec::new(); @@ -134,7 +136,7 @@ impl<'a, DBError> State<'a, DBError> { } } - pub fn load_cache_account(&mut self, address: B160) -> Result<&mut CacheAccount, DBError> { + pub fn load_cache_account(&mut self, address: B160) -> Result<&mut CacheAccount, DB::Error> { match self.cache.accounts.entry(address) { hash_map::Entry::Vacant(entry) => { if self.use_preloaded_bundle { @@ -171,8 +173,8 @@ impl<'a, DBError> State<'a, DBError> { } } -impl<'a, DBError> Database for State<'a, DBError> { - type Error = DBError; +impl Database for State { + type Error = DB::Error; fn basic(&mut self, address: B160) -> Result, Self::Error> { self.load_cache_account(address).map(|a| a.account_info()) @@ -254,7 +256,7 @@ impl<'a, DBError> Database for State<'a, DBError> { } } -impl<'a, DBError> DatabaseCommit for State<'a, DBError> { +impl DatabaseCommit for State { fn commit(&mut self, evm_state: HashMap) { let transitions = self.cache.apply_evm_state(evm_state); self.apply_transition(transitions); diff --git a/crates/revm/src/db/states/state_builder.rs b/crates/revm/src/db/states/state_builder.rs index d3d65d2080..fb943815a7 100644 --- a/crates/revm/src/db/states/state_builder.rs +++ b/crates/revm/src/db/states/state_builder.rs @@ -1,17 +1,16 @@ use super::{cache::CacheState, BundleState, State, TransitionState}; use crate::db::EmptyDB; use alloc::collections::BTreeMap; -use core::convert::Infallible; use revm_interpreter::primitives::{db::Database, B256}; /// Allows building of State and initializing it with different options. -pub struct StateBuilder<'a, DBError> { +pub struct StateBuilder { pub with_state_clear: bool, /// Optional database that we use to fetch data from. If database is not present, we will /// return not existing account and storage. /// /// Note: It is marked as Send so database can be shared between threads. - pub database: Box + Send + 'a>, + pub database: DB, //Box + Send + 'a>, /// if there is prestate that we want to use. /// This would mean that we have additional state layer between evm and disk/database. pub with_bundle_prestate: Option, @@ -28,7 +27,7 @@ pub struct StateBuilder<'a, DBError> { pub with_block_hashes: BTreeMap, } -impl Default for StateBuilder<'_, Infallible> { +impl Default for StateBuilder> { fn default() -> Self { Self { with_state_clear: true, @@ -42,16 +41,16 @@ impl Default for StateBuilder<'_, Infallible> { } } -impl<'a, DBError> StateBuilder<'a, DBError> { +impl StateBuilder { /// Create default instance of builder. - pub fn new() -> StateBuilder<'a, Infallible> { - StateBuilder::<'a, Infallible>::default() + pub fn new() -> StateBuilder> { + StateBuilder::>::default() } - pub fn with_database( + pub fn with_database_boxed<'a, NewDBError>( self, database: Box + Send + 'a>, - ) -> StateBuilder<'a, NewDBError> { + ) -> StateBuilder + Send + 'a>> { // cast to the different database, // Note that we return different type depending of the database NewDBError. StateBuilder { @@ -124,7 +123,7 @@ impl<'a, DBError> StateBuilder<'a, DBError> { } } - pub fn build(mut self) -> State<'a, DBError> { + pub fn build(mut self) -> State { let use_preloaded_bundle = if self.with_cache_prestate.is_some() { self.with_bundle_prestate = None; false From cbe64464149500fb17eb75b96482adf79bc1b697 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 5 Sep 2023 19:29:25 +0200 Subject: [PATCH 2/2] doc --- crates/revm/src/db/states/state.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/revm/src/db/states/state.rs b/crates/revm/src/db/states/state.rs index a4fc928fe1..71cef87fed 100644 --- a/crates/revm/src/db/states/state.rs +++ b/crates/revm/src/db/states/state.rs @@ -9,6 +9,9 @@ use revm_interpreter::primitives::{ hash_map, Account, AccountInfo, Bytecode, HashMap, B160, B256, BLOCK_HASH_HISTORY, U256, }; +/// More constrained version of State that uses Boxed database with a lifetime. +/// +/// This is used to make it easier to use State. pub type StateDBBox<'a, DBError> = State + Send + 'a>>; /// State of blockchain.