diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 3cfe860376..e14a223ed9 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -114,6 +114,11 @@ name = "generate_block_traces" path = "../../examples/generate_block_traces.rs" required-features = ["std", "serde-json", "ethersdb"] +[[example]] +name = "db_by_ref" +path = "../../examples/db_by_ref.rs" +required-features = ["std", "serde-json"] + [[bench]] name = "bench" path = "benches/bench.rs" diff --git a/crates/revm/src/handler/register.rs b/crates/revm/src/handler/register.rs index 835b80e2c8..3e2a8aefa3 100644 --- a/crates/revm/src/handler/register.rs +++ b/crates/revm/src/handler/register.rs @@ -8,7 +8,7 @@ pub type EvmHandler<'a, EXT, DB> = Handler<'a, Evm<'a, EXT, DB>, EXT, DB>; pub type EvmInstructionTables<'a, EXT, DB> = InstructionTables<'a, Evm<'a, EXT, DB>>; // Handle register -pub type HandleRegister<'a, EXT, DB> = fn(&mut EvmHandler<'a, EXT, DB>); +pub type HandleRegister<'a, EXT, DB> = for<'evm> fn(&'evm mut EvmHandler<'a, EXT, DB>); // Boxed handle register pub type HandleRegisterBox<'a, EXT, DB> = Box)>; diff --git a/examples/db_by_ref.rs b/examples/db_by_ref.rs new file mode 100644 index 0000000000..4896017a95 --- /dev/null +++ b/examples/db_by_ref.rs @@ -0,0 +1,74 @@ +use revm::{ + db::{CacheDB, EmptyDB, WrapDatabaseRef}, + handler::register::HandleRegister, + inspector_handle_register, + inspectors::TracerEip3155, + primitives::ResultAndState, + Database, DatabaseCommit, Evm, +}; + +struct DebugContext<'evm, EXT, DB: Database> { + ext: EXT, + register_handles_fn: HandleRegister<'evm, EXT, DB>, +} + +fn run_transaction<'db, 'evm, EXT>( + db: &'db CacheDB, + ext: EXT, + register_handles_fn: HandleRegister<'evm, EXT, WrapDatabaseRef<&'evm CacheDB>>, +) -> anyhow::Result +where + 'db: 'evm, +{ + let mut evm = Evm::builder() + .with_ref_db(db) + .with_external_context(ext) + .append_handler_register(register_handles_fn) + .build(); + + let result = evm.transact()?; + + Ok(result) +} + +fn run_transaction_and_commit_with_ext<'db, 'evm, EXT>( + db: &'db mut CacheDB, + ext: EXT, + register_handles_fn: HandleRegister<'evm, EXT, WrapDatabaseRef<&'evm CacheDB>>, +) -> anyhow::Result<()> +where + 'db: 'evm, +{ + let ResultAndState { state: changes, .. } = { + let db: &'evm _ = &*db; + run_transaction(db, ext, register_handles_fn)? + }; + + // Compile error: error[E0502]: cannot borrow `*db` as mutable because it is also borrowed as immutable + // The lifetime of `'evm` is extended beyond this function's scope because it is used in the `HandleRegister` function + db.commit(changes); + + Ok(()) +} + +fn run_transaction_and_commit<'db>(db: &mut CacheDB) -> anyhow::Result<()> { + let mut evm = Evm::builder().with_ref_db(db).build(); + + let ResultAndState { state: changes, .. } = evm.transact()?; + + // No compiler error because there is no lifetime parameter for the `HandleRegister` function + db.commit(changes); + + Ok(()) +} + +fn main() -> anyhow::Result<()> { + let mut cache_db = CacheDB::new(EmptyDB::default()); + + let mut tracer = TracerEip3155::new(Box::new(std::io::stdout()), true, true); + + run_transaction_and_commit_with_ext(&mut cache_db, &mut tracer, inspector_handle_register)?; + run_transaction_and_commit(&mut cache_db)?; + + Ok(()) +}