Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make evm.db not optional #713

Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions bins/revme/src/statetest/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,12 +255,12 @@ pub fn execute_test_suit(
env.cfg.spec_id,
revm::primitives::SpecId::SPURIOUS_DRAGON,
));
let mut state = revm::db::State::builder()
let state = revm::db::State::builder()
.with_cached_prestate(cache)
.with_bundle_update()
.build();
let mut evm = revm::new();
evm.database(&mut state);
let mut evm = revm::new(Default::default());
evm.database(state);
evm.env = env.clone();
// do the deed

Expand All @@ -275,7 +275,7 @@ pub fn execute_test_suit(

*elapsed.lock().unwrap() += timer;

let db = evm.db().unwrap();
let db = &evm.db;
let state_root = state_merkle_trie_root(db.cache.trie_account());
let logs = match &exec_result {
Ok(ExecutionResult::Success { logs, .. }) => logs.clone(),
Expand All @@ -293,14 +293,14 @@ pub fn execute_test_suit(
env.cfg.spec_id,
revm::primitives::SpecId::SPURIOUS_DRAGON,
));
let mut state = revm::db::StateBuilder::default()
let state = revm::db::StateBuilder::default()
.with_cached_prestate(cache)
.with_bundle_update()
.build();
evm.database(&mut state);
evm.database(state);
let _ =
evm.inspect_commit(TracerEip3155::new(Box::new(stdout()), false, false));
let db = evm.db().unwrap();
let db = evm.db;
println!("{path:?} UNIT_TEST:{name}\n");
match &exec_result {
Ok(ExecutionResult::Success {
Expand Down
10 changes: 5 additions & 5 deletions crates/revm/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::time::Duration;
type Evm = revm::EVM<BenchmarkDB>;

fn analysis(c: &mut Criterion) {
let mut evm = revm::new();
let mut evm = revm::new(Default::default());

evm.env.tx.caller = "0x1000000000000000000000000000000000000000"
.parse()
Expand Down Expand Up @@ -49,7 +49,7 @@ fn analysis(c: &mut Criterion) {
}

fn snailtracer(c: &mut Criterion) {
let mut evm = revm::new();
let mut evm = revm::new(Default::default());
evm.database(BenchmarkDB::new_bytecode(bytecode(SNAILTRACER)));

evm.env.tx.caller = "0x1000000000000000000000000000000000000000"
Expand All @@ -73,7 +73,7 @@ fn snailtracer(c: &mut Criterion) {
}

fn transfer(c: &mut Criterion) {
let mut evm = revm::new();
let mut evm = revm::new(Default::default());
evm.database(BenchmarkDB::new_bytecode(Bytecode::new()));

evm.env.tx.caller = "0x0000000000000000000000000000000000000001"
Expand All @@ -93,7 +93,7 @@ fn transfer(c: &mut Criterion) {
}

fn bench_transact(g: &mut BenchmarkGroup<'_, WallTime>, evm: &mut Evm) {
let state = match evm.db.as_mut().unwrap().0.state {
let state = match evm.db.0.state {
BytecodeState::Raw => "raw",
BytecodeState::Checked { .. } => "checked",
BytecodeState::Analysed { .. } => "analysed",
Expand All @@ -106,7 +106,7 @@ fn bench_eval(g: &mut BenchmarkGroup<'_, WallTime>, evm: &Evm) {
g.bench_function("eval", |b| {
let contract = Contract {
input: evm.env.tx.data.clone(),
bytecode: BytecodeLocked::try_from(evm.db.as_ref().unwrap().0.clone()).unwrap(),
bytecode: BytecodeLocked::try_from(evm.db.0.clone()).unwrap(),
..Default::default()
};
let mut host = DummyHost::new(evm.env.clone());
Expand Down
13 changes: 13 additions & 0 deletions crates/revm/src/db/states/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ impl State<EmptyDB> {
}
}

impl<DB: Database + Default> Default for State<DB> {
fn default() -> Self {
Self {
cache: Default::default(),
database: Default::default(),
transition_state: Default::default(),
bundle_state: Default::default(),
use_preloaded_bundle: Default::default(),
block_hashes: Default::default(),
}
}
}

impl<DB: Database> State<DB> {
/// Returns the size hint for the inner bundle state.
/// See [BundleState::size_hint] for more info.
Expand Down
131 changes: 53 additions & 78 deletions crates/revm/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,32 +33,37 @@ use revm_precompile::Precompiles;
/// # use revm::EVM; // Assuming this struct is in 'your_crate_name'
/// # struct SomeDatabase; // Mocking a database type for the purpose of this example
/// # struct Env; // Assuming the type Env is defined somewhere
///
/// impl Default for SomeDatabase {
/// fn default() -> Self {
/// unimplemented!()
/// }
/// }
alessandromazza98 marked this conversation as resolved.
Show resolved Hide resolved
///
/// let evm: EVM<SomeDatabase> = EVM::new();
/// assert!(evm.db.is_none());
/// let evm: EVM<SomeDatabase> = EVM::new(SomeDatabase);
/// ```
///
#[derive(Clone)]
pub struct EVM<DB> {
pub env: Env,
pub db: Option<DB>,
pub db: DB,
}

pub fn new<DB>() -> EVM<DB> {
EVM::new()
pub fn new<DB: Default>(db: DB) -> EVM<DB> {
alessandromazza98 marked this conversation as resolved.
Show resolved Hide resolved
EVM::new(db)
}

impl<DB> Default for EVM<DB> {
impl<DB: Default> Default for EVM<DB> {
fn default() -> Self {
Self::new()
Self::new(Default::default())
}
}

impl<DB: Database + DatabaseCommit> EVM<DB> {
/// Execute transaction and apply result to database
pub fn transact_commit(&mut self) -> Result<ExecutionResult, EVMError<DB::Error>> {
let ResultAndState { result, state } = self.transact()?;
self.db.as_mut().unwrap().commit(state);
self.db.commit(state);
Ok(result)
}

Expand All @@ -68,133 +73,103 @@ impl<DB: Database + DatabaseCommit> EVM<DB> {
inspector: INSP,
) -> Result<ExecutionResult, EVMError<DB::Error>> {
let ResultAndState { result, state } = self.inspect(inspector)?;
self.db.as_mut().unwrap().commit(state);
self.db.commit(state);
Ok(result)
}
}

impl<DB: Database> EVM<DB> {
/// Do checks that could make transaction fail before call/create
pub fn preverify_transaction(&mut self) -> Result<(), EVMError<DB::Error>> {
if let Some(db) = self.db.as_mut() {
evm_inner::<DB, false>(&mut self.env, db, &mut NoOpInspector).preverify_transaction()
} else {
panic!("Database needs to be set");
}
evm_inner::<DB, false>(&mut self.env, &mut self.db, &mut NoOpInspector)
.preverify_transaction()
}

/// Skip preverification steps and execute transaction without writing to DB, return change
/// state.
pub fn transact_preverified(&mut self) -> EVMResult<DB::Error> {
if let Some(db) = self.db.as_mut() {
evm_inner::<DB, false>(&mut self.env, db, &mut NoOpInspector).transact_preverified()
} else {
panic!("Database needs to be set");
}
evm_inner::<DB, false>(&mut self.env, &mut self.db, &mut NoOpInspector)
.transact_preverified()
}

/// Execute transaction without writing to DB, return change state.
pub fn transact(&mut self) -> EVMResult<DB::Error> {
if let Some(db) = self.db.as_mut() {
evm_inner::<DB, false>(&mut self.env, db, &mut NoOpInspector).transact()
} else {
panic!("Database needs to be set");
}
evm_inner::<DB, false>(&mut self.env, &mut self.db, &mut NoOpInspector).transact()
}

/// Execute transaction with given inspector, without wring to DB. Return change state.
pub fn inspect<INSP: Inspector<DB>>(&mut self, mut inspector: INSP) -> EVMResult<DB::Error> {
if let Some(db) = self.db.as_mut() {
evm_inner::<DB, true>(&mut self.env, db, &mut inspector).transact()
} else {
panic!("Database needs to be set");
}
evm_inner::<DB, true>(&mut self.env, &mut self.db, &mut inspector).transact()
}
}

impl<'a, DB: DatabaseRef> EVM<DB> {
/// Do checks that could make transaction fail before call/create
pub fn preverify_transaction_ref(&self) -> Result<(), EVMError<DB::Error>> {
if let Some(db) = self.db.as_ref() {
evm_inner::<_, false>(
&mut self.env.clone(),
&mut WrapDatabaseRef(db),
&mut NoOpInspector,
)
.preverify_transaction()
} else {
panic!("Database needs to be set");
}
evm_inner::<_, false>(
&mut self.env.clone(),
&mut WrapDatabaseRef(&self.db),
&mut NoOpInspector,
)
.preverify_transaction()
}

/// Skip preverification steps and execute transaction
/// without writing to DB, return change state.
pub fn transact_preverified_ref(&self) -> EVMResult<DB::Error> {
if let Some(db) = self.db.as_ref() {
evm_inner::<_, false>(
&mut self.env.clone(),
&mut WrapDatabaseRef(db),
&mut NoOpInspector,
)
.transact_preverified()
} else {
panic!("Database needs to be set");
}
evm_inner::<_, false>(
&mut self.env.clone(),
&mut WrapDatabaseRef(&self.db),
&mut NoOpInspector,
)
.transact_preverified()
}

/// Execute transaction without writing to DB, return change state.
pub fn transact_ref(&self) -> EVMResult<DB::Error> {
if let Some(db) = self.db.as_ref() {
evm_inner::<_, false>(
&mut self.env.clone(),
&mut WrapDatabaseRef(db),
&mut NoOpInspector,
)
.transact()
} else {
panic!("Database needs to be set");
}
evm_inner::<_, false>(
&mut self.env.clone(),
&mut WrapDatabaseRef(&self.db),
&mut NoOpInspector,
)
.transact()
}

/// Execute transaction with given inspector, without wring to DB. Return change state.
pub fn inspect_ref<I: Inspector<WrapDatabaseRef<&'a DB>>>(
&'a self,
mut inspector: I,
) -> EVMResult<DB::Error> {
if let Some(db) = self.db.as_ref() {
evm_inner::<_, true>(
&mut self.env.clone(),
&mut WrapDatabaseRef(db),
&mut inspector,
)
.transact()
} else {
panic!("Database needs to be set");
}
evm_inner::<_, true>(
&mut self.env.clone(),
&mut WrapDatabaseRef(&self.db),
&mut inspector,
)
.transact()
}
}

impl<DB> EVM<DB> {
impl<DB: Default> EVM<DB> {
alessandromazza98 marked this conversation as resolved.
Show resolved Hide resolved
/// Creates a new [EVM] instance with the default environment,
pub fn new() -> Self {
Self::with_env(Default::default())
pub fn new(db: DB) -> Self {
Self::with_env(Default::default(), db)
}

/// Creates a new [EVM] instance with the given environment.
pub fn with_env(env: Env) -> Self {
Self { env, db: None }
pub fn with_env(env: Env, db: DB) -> Self {
Self { env, db }
}

pub fn database(&mut self, db: DB) {
self.db = Some(db);
self.db = db;
}
alessandromazza98 marked this conversation as resolved.
Show resolved Hide resolved

pub fn db(&mut self) -> Option<&mut DB> {
self.db.as_mut()
pub fn db(&mut self) -> &mut DB {
&mut self.db
}

pub fn take_db(&mut self) -> DB {
core::mem::take(&mut self.db).unwrap()
core::mem::take(&mut self.db)
}
alessandromazza98 marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down
2 changes: 1 addition & 1 deletion crates/revm/src/inspector/customprinter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ mod test {
use crate::primitives::hex_literal;
// https://github.com/bluealloy/revm/issues/277
// checks this use case
let mut evm = crate::new();
let mut evm = crate::new(Default::default());
let mut database = crate::InMemoryDB::default();
let code: crate::primitives::Bytes = hex_literal::hex!("5b597fb075978b6c412c64d169d56d839a8fe01b3f4607ed603b2c78917ce8be1430fe6101e8527ffe64706ecad72a2f5c97a95e006e279dc57081902029ce96af7edae5de116fec610208527f9fc1ef09d4dd80683858ae3ea18869fe789ddc365d8d9d800e26c9872bac5e5b6102285260276102485360d461024953601661024a53600e61024b53607d61024c53600961024d53600b61024e5360b761024f5360596102505360796102515360a061025253607261025353603a6102545360fb61025553601261025653602861025753600761025853606f61025953601761025a53606161025b53606061025c5360a661025d53602b61025e53608961025f53607a61026053606461026153608c6102625360806102635360d56102645360826102655360ae61026653607f6101e8610146610220677a814b184591c555735fdcca53617f4d2b9134b29090c87d01058e27e962047654f259595947443b1b816b65cdb6277f4b59c10a36f4e7b8658f5a5e6f5561").to_vec().into();

Expand Down
2 changes: 1 addition & 1 deletion crates/revm/src/inspector/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ mod tests {
]);
let bytecode = Bytecode::new_raw(contract_data);

let mut evm = crate::new();
let mut evm = crate::new(Default::default());
evm.database(BenchmarkDB::new_bytecode(bytecode.clone()));
evm.env.tx.caller = B160(hex!("1000000000000000000000000000000000000000"));
evm.env.tx.transact_to =
Expand Down
2 changes: 1 addition & 1 deletion examples/fork_ref_transact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ async fn main() -> Result<()> {
.unwrap();

// initialise an empty (default) EVM
let mut evm = EVM::new();
let mut evm = EVM::new(Default::default());

// insert pre-built database from above
evm.database(cache_db);
Expand Down