Skip to content

Commit fc6b765

Browse files
committed
refactor anvil Env and reduce changes in tx processing
1 parent a928abc commit fc6b765

File tree

5 files changed

+64
-75
lines changed

5 files changed

+64
-75
lines changed

crates/anvil/src/config.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use op_revm::OpTransaction;
4545
use parking_lot::RwLock;
4646
use rand::thread_rng;
4747
use revm::{
48-
context::{BlockEnv, TxEnv},
48+
context::{BlockEnv, CfgEnv, TxEnv},
4949
context_interface::block::BlobExcessGasAndPrice,
5050
primitives::hardfork::SpecId,
5151
};
@@ -1024,7 +1024,8 @@ impl NodeConfig {
10241024
pub(crate) async fn setup(&mut self) -> Result<mem::Backend> {
10251025
// configure the revm environment
10261026

1027-
let mut cfg = Env::default_with_spec_id(self.get_hardfork().into()).evm_env.cfg_env;
1027+
let mut cfg = CfgEnv::default();
1028+
cfg.spec = self.get_hardfork().into();
10281029

10291030
cfg.chain_id = self.get_chain_id();
10301031
cfg.limit_contract_code_size = self.code_size_limit;
@@ -1039,7 +1040,7 @@ impl NodeConfig {
10391040
}
10401041

10411042
let spec_id = cfg.spec;
1042-
let mut env = Env::from(
1043+
let mut env = Env::new(
10431044
cfg,
10441045
BlockEnv {
10451046
gas_limit: self.gas_limit(),
@@ -1390,7 +1391,7 @@ async fn derive_block_and_transactions(
13901391
ForkChoice::Block(block_number) => {
13911392
let block_number = *block_number;
13921393
if block_number >= 0 {
1393-
return Ok((block_number as u64, None))
1394+
return Ok((block_number as u64, None));
13941395
}
13951396
// subtract from latest block number
13961397
let latest = provider.get_block_number().await?;

crates/anvil/src/eth/backend/env.rs

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
use alloy_evm::EvmEnv;
22
use foundry_evm::EnvMut;
33
use foundry_evm_core::AsEnvMut;
4-
use op_revm::{transaction::deposit::DepositTransactionParts, OpTransaction};
5-
use revm::{
6-
context::{BlockEnv, CfgEnv, TxEnv},
7-
primitives::hardfork::SpecId,
8-
};
4+
use op_revm::OpTransaction;
5+
use revm::context::{BlockEnv, CfgEnv, TxEnv};
96

107
/// Helper container type for [`EvmEnv`] and [`OpTransaction<TxEnd>`].
118
#[derive(Clone, Debug, Default)]
@@ -17,33 +14,9 @@ pub struct Env {
1714

1815
/// Helper container type for [`EvmEnv`] and [`OpTransaction<TxEnv>`].
1916
impl Env {
20-
pub fn default_with_spec_id(spec_id: SpecId) -> Self {
21-
let mut cfg = CfgEnv::default();
22-
cfg.spec = spec_id;
23-
24-
Self::from(cfg, BlockEnv::default(), OpTransaction::default())
25-
}
26-
27-
pub fn from(cfg: CfgEnv, block: BlockEnv, tx: OpTransaction<TxEnv>) -> Self {
17+
pub fn new(cfg: CfgEnv, block: BlockEnv, tx: OpTransaction<TxEnv>) -> Self {
2818
Self { evm_env: EvmEnv { cfg_env: cfg, block_env: block }, tx, is_optimism: false }
2919
}
30-
31-
pub fn new_with_spec_id(
32-
cfg: CfgEnv,
33-
block: BlockEnv,
34-
tx: OpTransaction<TxEnv>,
35-
spec_id: SpecId,
36-
) -> Self {
37-
let mut cfg = cfg;
38-
cfg.spec = spec_id;
39-
40-
Self::from(cfg, block, tx)
41-
}
42-
43-
pub fn with_deposit(mut self, deposit: DepositTransactionParts) -> Self {
44-
self.tx.deposit = deposit;
45-
self
46-
}
4720
}
4821

4922
impl AsEnvMut for Env {

crates/anvil/src/eth/backend/executor.rs

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ use anvil_core::eth::{
2626
};
2727
use foundry_evm::{backend::DatabaseError, traces::CallTraceNode};
2828
use foundry_evm_core::{either_evm::EitherEvm, evm::FoundryPrecompiles};
29-
use op_revm::{
30-
transaction::deposit::DEPOSIT_TRANSACTION_TYPE, L1BlockInfo, OpContext, OpTransactionError,
31-
};
29+
use op_revm::{L1BlockInfo, OpContext};
3230
use revm::{
3331
context::{Block as RevmBlock, BlockEnv, CfgEnv, Evm as RevmEvm, JournalTr},
3432
context_interface::result::{EVMError, ExecutionResult, Output},
@@ -114,6 +112,7 @@ pub struct TransactionExecutor<'a, Db: ?Sized, V: TransactionValidator> {
114112
pub blob_gas_used: u64,
115113
pub enable_steps_tracing: bool,
116114
pub odyssey: bool,
115+
pub optimism: bool,
117116
pub print_logs: bool,
118117
pub print_traces: bool,
119118
/// Precompiles to inject to the EVM.
@@ -248,13 +247,15 @@ impl<DB: Db + ?Sized, V: TransactionValidator> TransactionExecutor<'_, DB, V> {
248247
}
249248

250249
fn env_for(&self, tx: &PendingTransaction) -> Env {
251-
let op_tx = tx.to_revm_tx_env();
250+
let mut tx_env = tx.to_revm_tx_env();
252251

253-
let mut env = Env::from(self.cfg_env.clone(), self.block_env.clone(), op_tx.clone());
254-
if env.tx.base.tx_type == DEPOSIT_TRANSACTION_TYPE {
255-
env = env.with_deposit(op_tx.deposit);
252+
if self.optimism {
253+
tx_env.enveloped_tx = Some(alloy_rlp::encode(&tx.transaction.transaction).into());
256254
}
257255

256+
let mut env = Env::new(self.cfg_env.clone(), self.block_env.clone(), op_tx);
257+
env.is_optimism = self.optimism;
258+
258259
env
259260
}
260261
}
@@ -308,7 +309,7 @@ impl<DB: Db + ?Sized, V: TransactionValidator> Iterator for &mut TransactionExec
308309
&env,
309310
) {
310311
warn!(target: "backend", "Skipping invalid tx execution [{:?}] {}", transaction.hash(), err);
311-
return Some(TransactionExecutionOutcome::Invalid(transaction, err))
312+
return Some(TransactionExecutionOutcome::Invalid(transaction, err));
312313
}
313314

314315
let nonce = account.nonce;
@@ -324,32 +325,35 @@ impl<DB: Db + ?Sized, V: TransactionValidator> Iterator for &mut TransactionExec
324325
inspector = inspector.with_trace_printer();
325326
}
326327

327-
let mut evm = evm_with_inspector(
328-
&mut *self.db,
329-
&env,
330-
&mut inspector,
331-
transaction.tx_type() == DEPOSIT_TRANSACTION_TYPE,
332-
);
333-
trace!(target: "backend", "[{:?}] executing", transaction.hash());
334-
let exec_result = match evm.transact_commit(env.tx) {
335-
Ok(exec_result) => exec_result,
336-
Err(err) => {
337-
warn!(target: "backend", "[{:?}] failed to execute: {:?}", transaction.hash(), err);
338-
match err {
339-
EVMError::Database(err) => {
340-
return Some(TransactionExecutionOutcome::DatabaseError(transaction, err))
341-
}
342-
EVMError::Transaction(err) => {
343-
let err = match err {
344-
OpTransactionError::Base(err) => err.into(),
345-
OpTransactionError::HaltedDepositPostRegolith |
346-
OpTransactionError::DepositSystemTxPostRegolith => {
347-
InvalidTransactionError::DepositTxErrorPostRegolith
348-
}
349-
};
350-
return Some(TransactionExecutionOutcome::Invalid(transaction, err))
328+
let exec_result = {
329+
let mut evm = new_evm_with_inspector(&mut *self.db, &env, &mut inspector);
330+
// if let Some(factory) = &self.precompile_factory {
331+
// inject_precompiles(&mut evm, factory.precompiles());
332+
// }
333+
334+
trace!(target: "backend", "[{:?}] executing", transaction.hash());
335+
// transact and commit the transaction
336+
match evm.transact_commit(env.tx) {
337+
Ok(exec_result) => exec_result,
338+
Err(err) => {
339+
warn!(target: "backend", "[{:?}] failed to execute: {:?}", transaction.hash(), err);
340+
match err {
341+
EVMError::Database(err) => {
342+
return Some(TransactionExecutionOutcome::DatabaseError(
343+
transaction,
344+
err,
345+
))
346+
}
347+
EVMError::Transaction(err) => {
348+
return Some(TransactionExecutionOutcome::Invalid(
349+
transaction,
350+
err.into(),
351+
))
352+
}
353+
// This will correspond to prevrandao not set, and it should never happen.
354+
// If it does, it's a bug.
355+
e => panic!("failed to execute transaction: {e}"),
351356
}
352-
e => panic!("failed to execute transaction: {e}"),
353357
}
354358
}
355359
};
@@ -413,17 +417,16 @@ fn build_logs_bloom(logs: Vec<Log>, bloom: &mut Bloom) {
413417
}
414418

415419
/// Creates a database with given database and inspector, optionally enabling odyssey features.
416-
pub fn evm_with_inspector<DB, I>(
420+
pub fn new_evm_with_inspector<DB, I>(
417421
db: DB,
418422
env: &Env,
419423
inspector: I,
420-
is_optimism: bool,
421424
) -> EitherEvm<DB, I, FoundryPrecompiles>
422425
where
423426
DB: Database<Error = DatabaseError>,
424427
I: Inspector<EthEvmContext<DB>> + Inspector<OpContext<DB>>,
425428
{
426-
if is_optimism {
429+
if env.is_optimism {
427430
let op_context = OpContext {
428431
journaled_state: {
429432
let mut journal = Journal::new(db);
@@ -476,17 +479,16 @@ where
476479
}
477480

478481
/// Creates a new EVM with the given inspector and wraps the database in a `WrapDatabaseRef`.
479-
pub fn evm_with_inspector_ref<'db, DB, I>(
482+
pub fn new_evm_with_inspector_ref<'db, DB, I>(
480483
db: &'db DB,
481484
env: &Env,
482485
inspector: &'db mut I,
483-
is_optimism: bool,
484486
) -> EitherEvm<WrapDatabaseRef<&'db DB>, &'db mut I, FoundryPrecompiles>
485487
where
486488
DB: DatabaseRef<Error = DatabaseError> + 'db + ?Sized,
487489
I: Inspector<EthEvmContext<WrapDatabaseRef<&'db DB>>>
488490
+ Inspector<OpContext<WrapDatabaseRef<&'db DB>>>,
489491
WrapDatabaseRef<&'db DB>: Database<Error = DatabaseError>,
490492
{
491-
evm_with_inspector(WrapDatabaseRef(db), env, inspector, is_optimism)
493+
new_evm_with_inspector(WrapDatabaseRef(db), env, inspector)
492494
}

crates/anvil/src/eth/backend/mem/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! In-memory blockchain backend.
22
33
use self::state::trie_storage;
4-
use super::executor::evm_with_inspector_ref;
54
use crate::{
65
config::PruneStateHistoryConfig,
76
eth::{
@@ -124,6 +123,8 @@ use std::{
124123
use storage::{Blockchain, MinedTransaction, DEFAULT_HISTORY_LIMIT};
125124
use tokio::sync::RwLock as AsyncRwLock;
126125

126+
use super::executor::new_evm_with_inspector_ref;
127+
127128
pub mod cache;
128129
pub mod fork_db;
129130
pub mod in_memory_db;
@@ -1069,7 +1070,7 @@ impl Backend {
10691070
WrapDatabaseRef<&'db dyn DatabaseRef<Error = DatabaseError>>:
10701071
Database<Error = DatabaseError>,
10711072
{
1072-
evm_with_inspector_ref(db, env, inspector, self.is_optimism())
1073+
new_evm_with_inspector_ref(db, env, inspector)
10731074
// TODO(yash): inject precompiles
10741075
// if let Some(factory) = &self.precompile_factory {
10751076
// inject_precompiles(&mut evm, factory.precompiles());
@@ -1158,6 +1159,7 @@ impl Backend {
11581159
print_traces: self.print_traces,
11591160
precompile_factory: self.precompile_factory.clone(),
11601161
odyssey: self.odyssey,
1162+
optimism: self.is_optimism(),
11611163
};
11621164

11631165
// create a new pending block
@@ -1241,6 +1243,7 @@ impl Backend {
12411243
print_traces: self.print_traces,
12421244
odyssey: self.odyssey,
12431245
precompile_factory: self.precompile_factory.clone(),
1246+
optimism: self.is_optimism(),
12441247
};
12451248
let executed_tx = executor.execute();
12461249

crates/anvil/src/eth/error.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,16 @@ impl From<InvalidTransaction> for InvalidTransactionError {
338338
}
339339
}
340340
}
341+
342+
impl From<OpTransactionError> for InvalidTransactionError {
343+
fn from(value: OpTransactionError) -> Self {
344+
match value {
345+
OpTransactionError::Base(err) => err.into(),
346+
OpTransactionError::DepositSystemTxPostRegolith |
347+
OpTransactionError::HaltedDepositPostRegolith => Self::DepositTxErrorPostRegolith,
348+
}
349+
}
350+
}
341351
/// Helper trait to easily convert results to rpc results
342352
pub(crate) trait ToRpcResponseResult {
343353
fn to_rpc_result(self) -> ResponseResult;

0 commit comments

Comments
 (0)