-
Notifications
You must be signed in to change notification settings - Fork 603
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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() | ||
|
@@ -34,23 +34,23 @@ fn analysis(c: &mut Criterion) { | |
.sample_size(10); | ||
|
||
let raw = Bytecode::new_raw(contract_data.clone()); | ||
evm.database(BenchmarkDB::new_bytecode(raw)); | ||
*evm.db() = BenchmarkDB::new_bytecode(raw); | ||
bench_transact(&mut g, &mut evm); | ||
|
||
let checked = Bytecode::new_raw(contract_data.clone()).to_checked(); | ||
evm.database(BenchmarkDB::new_bytecode(checked)); | ||
*evm.db() = BenchmarkDB::new_bytecode(checked); | ||
bench_transact(&mut g, &mut evm); | ||
|
||
let analysed = to_analysed(Bytecode::new_raw(contract_data)); | ||
evm.database(BenchmarkDB::new_bytecode(analysed)); | ||
*evm.db() = BenchmarkDB::new_bytecode(analysed); | ||
bench_transact(&mut g, &mut evm); | ||
|
||
g.finish(); | ||
} | ||
|
||
fn snailtracer(c: &mut Criterion) { | ||
let mut evm = revm::new(); | ||
evm.database(BenchmarkDB::new_bytecode(bytecode(SNAILTRACER))); | ||
let mut evm = revm::new(Default::default()); | ||
*evm.db() = BenchmarkDB::new_bytecode(bytecode(SNAILTRACER)); | ||
|
||
evm.env.tx.caller = "0x1000000000000000000000000000000000000000" | ||
.parse() | ||
|
@@ -73,8 +73,8 @@ fn snailtracer(c: &mut Criterion) { | |
} | ||
|
||
fn transfer(c: &mut Criterion) { | ||
let mut evm = revm::new(); | ||
evm.database(BenchmarkDB::new_bytecode(Bytecode::new())); | ||
let mut evm = revm::new(Default::default()); | ||
*evm.db() = BenchmarkDB::new_bytecode(Bytecode::new()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here and in this file |
||
|
||
evm.env.tx.caller = "0x0000000000000000000000000000000000000001" | ||
.parse() | ||
|
@@ -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", | ||
|
@@ -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()); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,31 +34,30 @@ use revm_precompile::Precompiles; | |
/// # struct SomeDatabase; // Mocking a database type for the purpose of this example | ||
/// # struct Env; // Assuming the type Env is defined somewhere | ||
/// | ||
/// 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>(db: DB) -> EVM<DB> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would love to refresh this in the future, so to not break API two times can you revert this? |
||
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) | ||
} | ||
|
||
|
@@ -68,133 +67,95 @@ 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> { | ||
/// 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 database(&mut self, db: DB) { | ||
self.db = Some(db); | ||
} | ||
|
||
pub fn db(&mut self) -> Option<&mut DB> { | ||
self.db.as_mut() | ||
pub fn with_env(env: Env, db: DB) -> Self { | ||
Self { env, db } | ||
} | ||
|
||
pub fn take_db(&mut self) -> DB { | ||
core::mem::take(&mut self.db).unwrap() | ||
pub fn db(&mut self) -> &mut DB { | ||
&mut self.db | ||
} | ||
} | ||
Comment on lines
-179
to
160
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you revert this so as to not break functions
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can move this into the new call above