chore: Bump revm to newest (#6357)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
rakita
2024-02-06 23:59:10 +01:00
committed by GitHub
parent 37a8780a4d
commit 13947e509b
37 changed files with 467 additions and 358 deletions

16
Cargo.lock generated
View File

@ -7038,17 +7038,20 @@ dependencies = [
[[package]]
name = "revm"
version = "3.5.0"
source = "git+https://github.com/bluealloy/revm?branch=reth_freeze#ba28a42393604beeb2da5a339ac47d3d5d3f2271"
source = "git+https://github.com/bluealloy/revm?branch=main#773b0b2ba7b961d80e8cb3fcd89b9edf2239f8f3"
dependencies = [
"auto_impl",
"cfg-if",
"revm-interpreter",
"revm-precompile",
"serde",
"serde_json",
]
[[package]]
name = "revm-inspectors"
version = "0.1.0"
source = "git+https://github.com/paradigmxyz/evm-inspectors?rev=e900523#e90052361276aebcdc67cb24d8e2c4d907b6d299"
source = "git+https://github.com/paradigmxyz/evm-inspectors?branch=main#a6779fd969da55ff6a30397e8e5fd927001e443f"
dependencies = [
"alloy-primitives",
"alloy-rpc-trace-types",
@ -7065,15 +7068,16 @@ dependencies = [
[[package]]
name = "revm-interpreter"
version = "1.3.0"
source = "git+https://github.com/bluealloy/revm?branch=reth_freeze#ba28a42393604beeb2da5a339ac47d3d5d3f2271"
source = "git+https://github.com/bluealloy/revm?branch=main#773b0b2ba7b961d80e8cb3fcd89b9edf2239f8f3"
dependencies = [
"revm-primitives",
"serde",
]
[[package]]
name = "revm-precompile"
version = "2.2.0"
source = "git+https://github.com/bluealloy/revm?branch=reth_freeze#ba28a42393604beeb2da5a339ac47d3d5d3f2271"
source = "git+https://github.com/bluealloy/revm?branch=main#773b0b2ba7b961d80e8cb3fcd89b9edf2239f8f3"
dependencies = [
"aurora-engine-modexp",
"c-kzg",
@ -7089,10 +7093,9 @@ dependencies = [
[[package]]
name = "revm-primitives"
version = "1.3.0"
source = "git+https://github.com/bluealloy/revm?branch=reth_freeze#ba28a42393604beeb2da5a339ac47d3d5d3f2271"
source = "git+https://github.com/bluealloy/revm?branch=main#773b0b2ba7b961d80e8cb3fcd89b9edf2239f8f3"
dependencies = [
"alloy-primitives",
"alloy-rlp",
"auto_impl",
"bitflags 2.4.2",
"bitvec",
@ -7614,6 +7617,7 @@ version = "1.0.113"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
dependencies = [
"indexmap 2.2.2",
"itoa",
"ryu",
"serde",

View File

@ -168,14 +168,14 @@ reth-transaction-pool = { path = "crates/transaction-pool" }
reth-trie = { path = "crates/trie" }
# revm
revm = { git = "https://github.com/bluealloy/revm", branch = "reth_freeze", features = [
revm = { git = "https://github.com/bluealloy/revm", branch = "main", features = [
"std",
"secp256k1",
], default-features = false }
revm-primitives = { git = "https://github.com/bluealloy/revm", branch = "reth_freeze", features = [
revm-primitives = { git = "https://github.com/bluealloy/revm", branch = "main", features = [
"std",
], default-features = false }
revm-inspectors = { git = "https://github.com/paradigmxyz/evm-inspectors", rev="e900523"}
revm-inspectors = { git = "https://github.com/paradigmxyz/evm-inspectors", branch = "main" }
# eth
alloy-chains = { version = "0.1", feature = ["serde", "rlp", "arbitrary"] }
@ -220,7 +220,7 @@ strum = "0.26"
rayon = "1.7"
itertools = "0.12"
parking_lot = "0.12"
metrics = "0.21.1" # Needed for `metrics-macro` to resolve the crate using `::metrics` notation
metrics = "0.21.1" # Needed for `metrics-macro` to resolve the crate using `::metrics` notation
hex-literal = "0.4"
once_cell = "1.17"
syn = "2.0"

View File

@ -55,13 +55,19 @@ reth-trie.workspace = true
reth-nippy-jar.workspace = true
reth-node-api.workspace = true
reth-node-ethereum.workspace = true
reth-node-optimism = { workspace = true, optional = true, features = ["optimism"] }
reth-node-optimism = { workspace = true, optional = true, features = [
"optimism",
] }
reth-node-core.workspace = true
# crypto
alloy-rlp.workspace = true
alloy-chains.workspace = true
secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery"] }
secp256k1 = { workspace = true, features = [
"global-context",
"rand-std",
"recovery",
] }
revm-inspectors.workspace = true
# tracing
@ -93,7 +99,12 @@ ratatui = "0.25.0"
human_bytes = "0.4.1"
# async
tokio = { workspace = true, features = ["sync", "macros", "time", "rt-multi-thread"] }
tokio = { workspace = true, features = [
"sync",
"macros",
"time",
"rt-multi-thread",
] }
futures.workspace = true
pin-project.workspace = true

View File

@ -1,7 +1,7 @@
use crate::{validate_version_specific_fields, AttributesValidationError, EngineApiMessageVersion};
use reth_primitives::{
revm::config::revm_spec_by_timestamp_after_merge,
revm_primitives::{BlobExcessGasAndPrice, BlockEnv, CfgEnv, SpecId},
revm_primitives::{BlobExcessGasAndPrice, BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId},
Address, ChainSpec, Header, SealedBlock, Withdrawals, B256, U256,
};
use reth_rpc_types::{
@ -74,8 +74,8 @@ pub trait PayloadBuilderAttributes: Send + Sync + std::fmt::Debug {
/// Returns the withdrawals for the running payload job.
fn withdrawals(&self) -> &Withdrawals;
/// Returns the configured [CfgEnv] and [BlockEnv] for the targeted payload (that has the
/// `parent` as its parent).
/// Returns the configured [CfgEnvWithHandlerCfg] and [BlockEnv] for the targeted payload (that
/// has the `parent` as its parent).
///
/// The `chain_spec` is used to determine the correct chain id and hardfork for the payload
/// based on its timestamp.
@ -83,19 +83,18 @@ pub trait PayloadBuilderAttributes: Send + Sync + std::fmt::Debug {
/// Block related settings are derived from the `parent` block and the configured attributes.
///
/// NOTE: This is only intended for beacon consensus (after merge).
fn cfg_and_block_env(&self, chain_spec: &ChainSpec, parent: &Header) -> (CfgEnv, BlockEnv) {
// TODO: should be different once revm has configurable cfgenv
fn cfg_and_block_env(
&self,
chain_spec: &ChainSpec,
parent: &Header,
) -> (CfgEnvWithHandlerCfg, BlockEnv) {
// TODO: should be different once revm has configurable CfgEnvWithHandlerCfg
// configure evm env based on parent block
let mut cfg = CfgEnv::default();
cfg.chain_id = chain_spec.chain().id();
#[cfg(feature = "optimism")]
{
cfg.optimism = chain_spec.is_optimism();
}
// ensure we're not missing any timestamp based hardforks
cfg.spec_id = revm_spec_by_timestamp_after_merge(chain_spec, self.timestamp());
let spec_id = revm_spec_by_timestamp_after_merge(chain_spec, self.timestamp());
// if the parent block did not have excess blob gas (i.e. it was pre-cancun), but it is
// cancun now, we need to set the excess blob gas to the default value
@ -103,7 +102,7 @@ pub trait PayloadBuilderAttributes: Send + Sync + std::fmt::Debug {
.next_block_excess_blob_gas()
.map_or_else(
|| {
if cfg.spec_id == SpecId::CANCUN {
if spec_id == SpecId::CANCUN {
// default excess blob gas is zero
Some(0)
} else {
@ -131,7 +130,7 @@ pub trait PayloadBuilderAttributes: Send + Sync + std::fmt::Debug {
blob_excess_gas_and_price,
};
(cfg, block_env)
(CfgEnvWithHandlerCfg::new(cfg, spec_id), block_env)
}
}

View File

@ -1,5 +1,5 @@
use reth_primitives::{revm::env::fill_block_env, Address, ChainSpec, Header, Transaction, U256};
use revm_primitives::{BlockEnv, CfgEnv, SpecId, TxEnv};
use revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg, SpecId, TxEnv};
/// This represents the set of methods used to configure the EVM before execution.
pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone {
@ -11,9 +11,9 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone {
where
T: AsRef<Transaction>;
/// Fill [CfgEnv] fields according to the chain spec and given header
/// Fill [CfgEnvWithHandlerCfg] fields according to the chain spec and given header
fn fill_cfg_env(
cfg_env: &mut CfgEnv,
cfg_env: &mut CfgEnvWithHandlerCfg,
chain_spec: &ChainSpec,
header: &Header,
total_difficulty: U256,
@ -22,14 +22,14 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone {
/// Convenience function to call both [fill_cfg_env](ConfigureEvmEnv::fill_cfg_env) and
/// [fill_block_env].
fn fill_cfg_and_block_env(
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
chain_spec: &ChainSpec,
header: &Header,
total_difficulty: U256,
) {
Self::fill_cfg_env(cfg, chain_spec, header, total_difficulty);
let after_merge = cfg.spec_id >= SpecId::MERGE;
let after_merge = cfg.handler_cfg.spec_id >= SpecId::MERGE;
fill_block_env(block_env, chain_spec, header, after_merge);
}
}

View File

@ -1,7 +1,7 @@
use reth_node_api::ConfigureEvmEnv;
use reth_primitives::{
revm::{config::revm_spec, env::fill_tx_env},
revm_primitives::{AnalysisKind, CfgEnv, TxEnv},
revm_primitives::{AnalysisKind, CfgEnvWithHandlerCfg, TxEnv},
Address, ChainSpec, Head, Header, Transaction, U256,
};
@ -21,7 +21,7 @@ impl ConfigureEvmEnv for EthEvmConfig {
}
fn fill_cfg_env(
cfg_env: &mut CfgEnv,
cfg_env: &mut CfgEnvWithHandlerCfg,
chain_spec: &ChainSpec,
header: &Header,
total_difficulty: U256,
@ -38,20 +38,21 @@ impl ConfigureEvmEnv for EthEvmConfig {
);
cfg_env.chain_id = chain_spec.chain().id();
cfg_env.spec_id = spec_id;
cfg_env.perf_analyse_created_bytecodes = AnalysisKind::Analyse;
cfg_env.handler_cfg.spec_id = spec_id;
}
}
#[cfg(test)]
mod tests {
use super::*;
use reth_primitives::revm_primitives::BlockEnv;
use reth_primitives::revm_primitives::{BlockEnv, CfgEnv, SpecId};
#[test]
#[ignore]
fn test_fill_cfg_and_block_env() {
let mut cfg_env = CfgEnv::default();
let mut cfg_env = CfgEnvWithHandlerCfg::new(CfgEnv::default(), SpecId::LATEST);
let mut block_env = BlockEnv::default();
let header = Header::default();
let chain_spec = ChainSpec::default();

View File

@ -1,7 +1,7 @@
use reth_node_api::ConfigureEvmEnv;
use reth_primitives::{
revm::{config::revm_spec, env::fill_op_tx_env},
revm_primitives::{AnalysisKind, CfgEnv, TxEnv},
revm_primitives::{AnalysisKind, CfgEnvWithHandlerCfg, TxEnv},
Address, Bytes, ChainSpec, Head, Header, Transaction, U256,
};
@ -21,7 +21,7 @@ impl ConfigureEvmEnv for OptimismEvmConfig {
}
fn fill_cfg_env(
cfg_env: &mut CfgEnv,
cfg_env: &mut CfgEnvWithHandlerCfg,
chain_spec: &ChainSpec,
header: &Header,
total_difficulty: U256,
@ -38,23 +38,22 @@ impl ConfigureEvmEnv for OptimismEvmConfig {
);
cfg_env.chain_id = chain_spec.chain().id();
cfg_env.spec_id = spec_id;
cfg_env.perf_analyse_created_bytecodes = AnalysisKind::Analyse;
// optimism-specific configuration
cfg_env.optimism = chain_spec.is_optimism();
cfg_env.handler_cfg.spec_id = spec_id;
cfg_env.handler_cfg.is_optimism = chain_spec.is_optimism();
}
}
#[cfg(test)]
mod tests {
use super::*;
use reth_primitives::revm_primitives::BlockEnv;
use reth_primitives::revm_primitives::{BlockEnv, CfgEnv, SpecId};
#[test]
#[ignore]
fn test_fill_cfg_and_block_env() {
let mut cfg_env = CfgEnv::default();
let mut cfg_env = CfgEnvWithHandlerCfg::new(CfgEnv::default(), SpecId::LATEST);
let mut block_env = BlockEnv::default();
let header = Header::default();
let chain_spec = ChainSpec::default();

View File

@ -31,8 +31,8 @@ use reth_revm::state_change::{
use reth_tasks::TaskSpawner;
use reth_transaction_pool::TransactionPool;
use revm::{
primitives::{BlockEnv, CfgEnv, Env},
Database, DatabaseCommit, State,
primitives::{BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg},
Database, DatabaseCommit, Evm, State,
};
use std::{
future::Future,
@ -633,7 +633,7 @@ pub struct PayloadConfig<Attributes> {
/// Pre-configured block environment.
pub initialized_block_env: BlockEnv,
/// Configuration for the environment.
pub initialized_cfg: CfgEnv,
pub initialized_cfg: CfgEnvWithHandlerCfg,
/// The parent block.
pub parent_block: Arc<SealedBlock>,
/// Block extra data.
@ -849,8 +849,8 @@ pub fn commit_withdrawals<DB: Database<Error = ProviderError>>(
/// Apply the [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) pre block contract call.
///
/// This constructs a new [EVM](revm::EVM) with the given DB, and environment ([CfgEnv] and
/// [BlockEnv]) to execute the pre block contract call.
/// This constructs a new [Evm] with the given DB, and environment
/// ([CfgEnvWithHandlerCfg] and [BlockEnv]) to execute the pre block contract call.
///
/// The parent beacon block root used for the call is gathered from the given
/// [PayloadBuilderAttributes].
@ -861,7 +861,7 @@ pub fn pre_block_beacon_root_contract_call<DB: Database + DatabaseCommit, Attrib
db: &mut DB,
chain_spec: &ChainSpec,
block_number: u64,
initialized_cfg: &CfgEnv,
initialized_cfg: &CfgEnvWithHandlerCfg,
initialized_block_env: &BlockEnv,
attributes: &Attributes,
) -> Result<(), PayloadBuilderError>
@ -869,16 +869,15 @@ where
DB::Error: std::fmt::Display,
Attributes: PayloadBuilderAttributes,
{
// Configure the environment for the block.
let env = Env {
cfg: initialized_cfg.clone(),
block: initialized_block_env.clone(),
..Default::default()
};
// apply pre-block EIP-4788 contract call
let mut evm_pre_block = revm::EVM::with_env(env);
evm_pre_block.database(db);
let mut evm_pre_block = Evm::builder()
.with_db(db)
.with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env(
initialized_cfg.clone(),
initialized_block_env.clone(),
Default::default(),
))
.build();
// initialize a block from the env, because the pre block call needs the block itself
apply_beacon_root_contract_call(

View File

@ -25,7 +25,7 @@ mod builder {
},
eip4844::calculate_excess_blob_gas,
proofs,
revm::{compat::into_reth_log, env::tx_env_with_recovered},
revm::env::tx_env_with_recovered,
Block, Header, IntoRecoveredTransaction, Receipt, Receipts, EMPTY_OMMER_ROOT_HASH, U256,
};
use reth_provider::{BundleStateWithReceipts, StateProviderFactory};
@ -33,7 +33,7 @@ mod builder {
use reth_transaction_pool::{BestTransactionsAttributes, TransactionPool};
use revm::{
db::states::bundle_state::BundleRetention,
primitives::{EVMError, Env, InvalidTransaction, ResultAndState},
primitives::{EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState},
DatabaseCommit, State,
};
use tracing::{debug, trace, warn};
@ -262,14 +262,14 @@ mod builder {
}
// Configure the environment for the block.
let env = Env {
cfg: initialized_cfg.clone(),
block: initialized_block_env.clone(),
tx: tx_env_with_recovered(&tx),
};
let mut evm = revm::EVM::with_env(env);
evm.database(&mut db);
let mut evm = revm::Evm::builder()
.with_db(&mut db)
.with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env(
initialized_cfg.clone(),
initialized_block_env.clone(),
tx_env_with_recovered(&tx),
))
.build();
let ResultAndState { result, state } = match evm.transact() {
Ok(res) => res,
@ -295,7 +295,8 @@ mod builder {
}
}
};
// drop evm so db is released.
drop(evm);
// commit changes
db.commit(state);
@ -320,7 +321,7 @@ mod builder {
tx_type: tx.tx_type(),
success: result.is_success(),
cumulative_gas_used,
logs: result.logs().into_iter().map(into_reth_log).collect(),
logs: result.logs().into_iter().map(Into::into).collect(),
}));
// update add to total fees

View File

@ -22,7 +22,7 @@ mod builder {
use reth_primitives::{
constants::{BEACON_NONCE, EMPTY_RECEIPTS, EMPTY_TRANSACTIONS},
proofs,
revm::{compat::into_reth_log, env::tx_env_with_recovered},
revm::env::tx_env_with_recovered,
Block, Hardfork, Header, IntoRecoveredTransaction, Receipt, Receipts,
EMPTY_OMMER_ROOT_HASH, U256,
};
@ -31,7 +31,7 @@ mod builder {
use reth_transaction_pool::{BestTransactionsAttributes, TransactionPool};
use revm::{
db::states::bundle_state::BundleRetention,
primitives::{EVMError, Env, InvalidTransaction, ResultAndState},
primitives::{EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState},
DatabaseCommit, State,
};
use tracing::{debug, trace, warn};
@ -209,11 +209,6 @@ mod builder {
Client: StateProviderFactory,
Pool: TransactionPool,
{
debug_assert!(
args.config.initialized_cfg.optimism,
"optimism payload builder called on non-optimism chain"
);
let BuildArguments { client, pool, mut cached_reads, config, cancel, best_payload } = args;
let state_provider = client.state_by_block_hash(config.parent_block.hash)?;
@ -299,15 +294,14 @@ mod builder {
))
})?;
// Configure the environment for the block.
let env = Env {
cfg: initialized_cfg.clone(),
block: initialized_block_env.clone(),
tx: tx_env_with_recovered(&sequencer_tx),
};
let mut evm = revm::EVM::with_env(env);
evm.database(&mut db);
let mut evm = revm::Evm::builder()
.with_db(&mut db)
.with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env(
initialized_cfg.clone(),
initialized_block_env.clone(),
tx_env_with_recovered(&sequencer_tx),
))
.build();
let ResultAndState { result, state } = match evm.transact() {
Ok(res) => res,
@ -325,6 +319,8 @@ mod builder {
}
};
// to realease the db reference drop evm.
drop(evm);
// commit changes
db.commit(state);
@ -338,7 +334,7 @@ mod builder {
tx_type: sequencer_tx.tx_type(),
success: result.is_success(),
cumulative_gas_used,
logs: result.logs().into_iter().map(into_reth_log).collect(),
logs: result.logs().into_iter().map(Into::into).collect(),
deposit_nonce: depositor.map(|account| account.nonce),
// The deposit receipt version was introduced in Canyon to indicate an update to how
// receipt hashes should be computed when set. The state transition process
@ -375,14 +371,15 @@ mod builder {
let tx = pool_tx.to_recovered_transaction();
// Configure the environment for the block.
let env = Env {
cfg: initialized_cfg.clone(),
block: initialized_block_env.clone(),
tx: tx_env_with_recovered(&tx),
};
let mut evm = revm::EVM::with_env(env);
evm.database(&mut db);
let mut evm = revm::Evm::builder()
.with_db(&mut db)
.with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env(
initialized_cfg.clone(),
initialized_block_env.clone(),
tx_env_with_recovered(&tx),
))
.build();
let ResultAndState { result, state } = match evm.transact() {
Ok(res) => res,
@ -408,7 +405,8 @@ mod builder {
}
}
};
// to realease the db reference drop evm.
drop(evm);
// commit changes
db.commit(state);
@ -423,7 +421,7 @@ mod builder {
tx_type: tx.tx_type(),
success: result.is_success(),
cumulative_gas_used,
logs: result.logs().into_iter().map(into_reth_log).collect(),
logs: result.logs().into_iter().map(Into::into).collect(),
deposit_nonce: None,
deposit_receipt_version: None,
}));

View File

@ -2987,7 +2987,6 @@ Post-merge hard forks (timestamp based):
assert_eq!(header.parent_beacon_block_root, Some(B256::ZERO));
assert_eq!(header.blob_gas_used, Some(0));
assert_eq!(header.excess_blob_gas, Some(0));
println!("header: {:?}", header);
// check the genesis hash
let genesis_hash = header.hash_slow();

View File

@ -1,4 +1,5 @@
use crate::{Address, Bloom, Bytes, B256};
use alloy_primitives::Log as AlloyLog;
use alloy_rlp::{RlpDecodable, RlpEncodable};
use reth_codecs::{main_codec, Compact};
@ -20,6 +21,12 @@ pub struct Log {
pub data: Bytes,
}
impl From<AlloyLog> for Log {
fn from(log: AlloyLog) -> Self {
Self { address: log.address, topics: log.topics().to_vec(), data: log.data.data }
}
}
/// Calculate receipt logs bloom.
pub fn logs_bloom<'a, It>(logs: It) -> Bloom
where

View File

@ -3,20 +3,15 @@ use crate::{
Account, Address, Log as RethLog, TransactionKind, KECCAK_EMPTY, U256,
};
use revm::{
interpreter::gas::initial_tx_gas,
interpreter::gas::validate_initial_tx_gas,
primitives::{MergeSpec, ShanghaiSpec},
};
/// Check equality between Revm and Reth `Log`s.
pub fn is_log_equal(revm_log: &Log, reth_log: &crate::Log) -> bool {
pub fn is_log_equal(revm_log: &Log, reth_log: &RethLog) -> bool {
revm_log.address == reth_log.address &&
revm_log.data == reth_log.data &&
revm_log.topics == reth_log.topics
}
/// Converts a Revm `Log` into a Reth `Log`.
pub fn into_reth_log(log: Log) -> RethLog {
RethLog { address: log.address, topics: log.topics, data: log.data }
revm_log.data.data == reth_log.data &&
revm_log.topics() == reth_log.topics
}
/// Converts a Revm [`AccountInfo`] into a Reth [`Account`].
@ -54,8 +49,8 @@ pub fn calculate_intrinsic_gas_after_merge(
is_shanghai: bool,
) -> u64 {
if is_shanghai {
initial_tx_gas::<ShanghaiSpec>(input, kind.is_create(), access_list)
validate_initial_tx_gas::<ShanghaiSpec>(input, kind.is_create(), access_list)
} else {
initial_tx_gas::<MergeSpec>(input, kind.is_create(), access_list)
validate_initial_tx_gas::<MergeSpec>(input, kind.is_create(), access_list)
}
}

View File

@ -6,7 +6,7 @@ use reth_primitives::{
address, b256, hex, Address, Block, Bytes, ChainSpec, Hardfork, TransactionKind, B256, U256,
};
use revm::{
primitives::{BedrockSpec, Bytecode, HashMap, RegolithSpec},
primitives::{Bytecode, HashMap, SpecId},
DatabaseCommit, L1BlockInfo,
};
use std::sync::Arc;
@ -86,7 +86,12 @@ pub fn parse_l1_info_tx(data: &[u8]) -> Result<L1BlockInfo, BlockExecutionError>
),
)?;
Ok(L1BlockInfo { l1_base_fee, l1_fee_overhead, l1_fee_scalar })
let mut l1block = L1BlockInfo::default();
l1block.l1_base_fee = l1_base_fee;
l1block.l1_fee_overhead = Some(l1_fee_overhead);
l1block.l1_base_fee_scalar = l1_fee_scalar;
Ok(l1block)
}
/// An extension trait for [L1BlockInfo] that allows us to calculate the L1 cost of a transaction
@ -133,17 +138,18 @@ impl RethL1BlockInfo for L1BlockInfo {
return Ok(U256::ZERO)
}
if chain_spec.is_fork_active_at_timestamp(Hardfork::Regolith, timestamp) {
Ok(self.calculate_tx_l1_cost::<RegolithSpec>(input))
let spec_id = if chain_spec.is_fork_active_at_timestamp(Hardfork::Regolith, timestamp) {
SpecId::REGOLITH
} else if chain_spec.is_fork_active_at_timestamp(Hardfork::Bedrock, timestamp) {
Ok(self.calculate_tx_l1_cost::<BedrockSpec>(input))
SpecId::BEDROCK
} else {
Err(reth_executor::BlockExecutionError::OptimismBlockExecution(
return Err(reth_executor::BlockExecutionError::OptimismBlockExecution(
reth_executor::OptimismBlockExecutionError::L1BlockInfoError {
message: "Optimism hardforks are not active".to_string(),
},
))
}
};
Ok(self.calculate_tx_l1_cost(input, spec_id))
}
fn l1_data_gas(
@ -152,17 +158,18 @@ impl RethL1BlockInfo for L1BlockInfo {
timestamp: u64,
input: &Bytes,
) -> Result<U256, BlockExecutionError> {
if chain_spec.is_fork_active_at_timestamp(Hardfork::Regolith, timestamp) {
Ok(self.data_gas::<RegolithSpec>(input))
let spec_id = if chain_spec.is_fork_active_at_timestamp(Hardfork::Regolith, timestamp) {
SpecId::REGOLITH
} else if chain_spec.is_fork_active_at_timestamp(Hardfork::Bedrock, timestamp) {
Ok(self.data_gas::<BedrockSpec>(input))
SpecId::BEDROCK
} else {
Err(reth_executor::BlockExecutionError::OptimismBlockExecution(
return Err(reth_executor::BlockExecutionError::OptimismBlockExecution(
reth_executor::OptimismBlockExecutionError::L1BlockInfoError {
message: "Optimism hardforks are not active".to_string(),
},
))
}
};
Ok(self.data_gas(input, spec_id))
}
}
@ -226,7 +233,7 @@ mod test_l1_fee {
let l1_info: L1BlockInfo = super::extract_l1_info(&mock_block).unwrap();
assert_eq!(l1_info.l1_base_fee, U256::from(652_114));
assert_eq!(l1_info.l1_fee_overhead, U256::from(2100));
assert_eq!(l1_info.l1_fee_scalar, U256::from(1_000_000));
assert_eq!(l1_info.l1_fee_overhead, Some(U256::from(2100)));
assert_eq!(l1_info.l1_base_fee_scalar, U256::from(1_000_000));
}
}

View File

@ -3,10 +3,7 @@ use reth_interfaces::executor::{
BlockExecutionError, BlockValidationError, OptimismBlockExecutionError,
};
use reth_node_api::ConfigureEvmEnv;
use reth_primitives::{
revm::compat::into_reth_log, revm_primitives::ResultAndState, BlockWithSenders, Hardfork,
Receipt, U256,
};
use reth_primitives::{revm_primitives::ResultAndState, BlockWithSenders, Hardfork, Receipt, U256};
use reth_provider::{BlockExecutor, BlockExecutorStats, BundleStateWithReceipts};
use revm::DatabaseCommit;
use std::time::Instant;
@ -137,7 +134,7 @@ where
success: result.is_success(),
cumulative_gas_used,
// convert to reth log
logs: result.into_logs().into_iter().map(into_reth_log).collect(),
logs: result.into_logs().into_iter().map(Into::into).collect(),
#[cfg(feature = "optimism")]
deposit_nonce: depositor.map(|account| account.nonce),
// The deposit receipt version was introduced in Canyon to indicate an update to how
@ -157,7 +154,7 @@ where
fn take_output_state(&mut self) -> BundleStateWithReceipts {
let receipts = std::mem::take(&mut self.receipts);
BundleStateWithReceipts::new(
self.evm.db().unwrap().take_bundle(),
self.evm.context.evm.db.take_bundle(),
receipts,
self.first_block.unwrap_or_default(),
)
@ -168,6 +165,6 @@ where
}
fn size_hint(&self) -> Option<usize> {
self.evm.db.as_ref().map(|db| db.bundle_size_hint())
Some(self.evm.context.evm.db.bundle_size_hint())
}
}

View File

@ -15,9 +15,11 @@ use reth_provider::{
BlockExecutor, BlockExecutorStats, ProviderError, PrunableBlockExecutor, StateProvider,
};
use revm::{
db::{states::bundle_state::BundleRetention, StateDBBox},
primitives::ResultAndState,
State, EVM,
db::{states::bundle_state::BundleRetention, EmptyDBTyped, StateDBBox},
inspector_handle_register,
interpreter::Host,
primitives::{CfgEnvWithHandlerCfg, ResultAndState},
Evm, State, StateBuilder,
};
use std::{sync::Arc, time::Instant};
@ -26,8 +28,6 @@ use reth_primitives::revm::env::fill_op_tx_env;
#[cfg(not(feature = "optimism"))]
use reth_primitives::revm::env::fill_tx_env;
#[cfg(not(feature = "optimism"))]
use reth_primitives::revm::compat::into_reth_log;
#[cfg(not(feature = "optimism"))]
use reth_provider::BundleStateWithReceipts;
#[cfg(not(feature = "optimism"))]
@ -57,9 +57,7 @@ pub struct EVMProcessor<'a, EvmConfig> {
/// The configured chain-spec
pub(crate) chain_spec: Arc<ChainSpec>,
/// revm instance that contains database and env environment.
pub(crate) evm: EVM<StateDBBox<'a, ProviderError>>,
/// Hook and inspector stack that we want to invoke on that hook.
stack: InspectorStack,
pub(crate) evm: Evm<'a, InspectorStack, StateDBBox<'a, ProviderError>>,
/// The collection of receipts.
/// Outer vector stores receipts for each block sequentially.
/// The inner vector stores receipts ordered by transaction number.
@ -94,11 +92,21 @@ where
/// Create a new pocessor with the given chain spec.
pub fn new(chain_spec: Arc<ChainSpec>, evm_config: EvmConfig) -> Self {
let evm = EVM::new();
// create evm with boxed empty db that is going to be set later.
let evm = Evm::builder()
.with_db(
Box::new(
StateBuilder::new()
.with_database_boxed(Box::new(EmptyDBTyped::<ProviderError>::new())),
)
.build(),
)
// Hook and inspector stack that we want to invoke on that hook.
.with_external_context(InspectorStack::new(InspectorStackConfig::default()))
.build();
EVMProcessor {
chain_spec,
evm,
stack: InspectorStack::new(InspectorStackConfig::default()),
receipts: Receipts::new(),
first_block: None,
tip: None,
@ -129,12 +137,13 @@ where
revm_state: StateDBBox<'a, ProviderError>,
evm_config: EvmConfig,
) -> Self {
let mut evm = EVM::new();
evm.database(revm_state);
let evm = Evm::builder()
.with_db(revm_state)
.with_external_context(InspectorStack::new(InspectorStackConfig::default()))
.build();
EVMProcessor {
chain_spec,
evm,
stack: InspectorStack::new(InspectorStackConfig::default()),
receipts: Receipts::new(),
first_block: None,
tip: None,
@ -147,7 +156,7 @@ where
/// Configures the executor with the given inspectors.
pub fn set_stack(&mut self, stack: InspectorStack) {
self.stack = stack;
self.evm.context.external = stack;
}
/// Configure the executor with the given block.
@ -157,10 +166,7 @@ where
/// Returns a reference to the database
pub fn db_mut(&mut self) -> &mut StateDBBox<'a, ProviderError> {
// Option will be removed from EVM in the future.
// as it is always some.
// https://github.com/bluealloy/revm/issues/697
self.evm.db().expect("Database inside EVM is always set")
&mut self.evm.context.evm.db
}
/// Initializes the config and block env.
@ -171,13 +177,17 @@ where
self.db_mut().set_state_clear_flag(state_clear_flag);
let mut cfg: CfgEnvWithHandlerCfg =
CfgEnvWithHandlerCfg::new(self.evm.cfg().clone(), self.evm.spec_id());
EvmConfig::fill_cfg_and_block_env(
&mut self.evm.env.cfg,
&mut self.evm.env.block,
&mut cfg,
self.evm.block_mut(),
&self.chain_spec,
header,
total_difficulty,
);
*self.evm.cfg_mut() = cfg.cfg_env;
self.evm.handler.modify_spec_id(cfg.handler_cfg.spec_id);
}
/// Applies the pre-block call to the EIP-4788 beacon block root contract.
@ -248,30 +258,34 @@ where
) -> Result<ResultAndState, BlockExecutionError> {
// Fill revm structure.
#[cfg(not(feature = "optimism"))]
fill_tx_env(&mut self.evm.env.tx, transaction, sender);
fill_tx_env(self.evm.tx_mut(), transaction, sender);
#[cfg(feature = "optimism")]
{
let mut envelope_buf = Vec::with_capacity(transaction.length_without_header());
transaction.encode_enveloped(&mut envelope_buf);
fill_op_tx_env(&mut self.evm.env.tx, transaction, sender, envelope_buf.into());
fill_op_tx_env(self.evm.tx_mut(), transaction, sender, envelope_buf.into());
}
let hash = transaction.hash();
let out = if self.stack.should_inspect(&self.evm.env, hash) {
// execution with inspector.
let output = self.evm.inspect(&mut self.stack);
let should_inspect = self.evm.context.external.should_inspect(self.evm.env(), hash);
let out = if should_inspect {
// push inspector handle register.
self.evm.handler.append_handler_register_plain(inspector_handle_register);
let output = self.evm.transact();
tracing::trace!(
target: "evm",
?hash, ?output, ?transaction, env = ?self.evm.env,
?hash, ?output, ?transaction, env = ?self.evm.context.evm.env,
"Executed transaction"
);
// pop last handle register
self.evm.handler.pop_handle_register();
output
} else {
// main execution.
self.evm.transact()
};
out.map_err(|e| BlockValidationError::EVM { hash, error: e.into() }.into())
out.map_err(move |e| BlockValidationError::EVM { hash, error: e.into() }.into())
}
/// Execute the block, verify gas usage and apply post-block state changes.
@ -478,7 +492,7 @@ where
success: result.is_success(),
cumulative_gas_used,
// convert to reth log
logs: result.into_logs().into_iter().map(into_reth_log).collect(),
logs: result.into_logs().into_iter().map(Into::into).collect(),
});
}
@ -488,7 +502,7 @@ where
fn take_output_state(&mut self) -> BundleStateWithReceipts {
let receipts = std::mem::take(&mut self.receipts);
BundleStateWithReceipts::new(
self.evm.db().unwrap().take_bundle(),
self.evm.context.evm.db.take_bundle(),
receipts,
self.first_block.unwrap_or_default(),
)
@ -499,7 +513,7 @@ where
}
fn size_hint(&self) -> Option<usize> {
self.evm.db.as_ref().map(|db| db.bundle_size_hint())
Some(self.evm.context.evm.db.bundle_size_hint())
}
}
@ -785,7 +799,7 @@ mod tests {
executor.init_env(&header, U256::ZERO);
// get the env
let previous_env = executor.evm.env.clone();
let previous_env = executor.evm.context.evm.env.clone();
// attempt to execute an empty block with parent beacon block root, this should not fail
executor
@ -806,7 +820,7 @@ mod tests {
);
// ensure that the env has not changed
assert_eq!(executor.evm.env, previous_env);
assert_eq!(executor.evm.context.evm.env, previous_env);
}
#[test]
@ -953,7 +967,7 @@ mod tests {
// there is no system contract call so there should be NO STORAGE CHANGES
// this means we'll check the transition state
let state = executor.evm.db().unwrap();
let state = executor.evm.context.evm.db;
let transition_state = state
.transition_state
.clone()
@ -1007,7 +1021,7 @@ mod tests {
executor.init_env(&header, U256::ZERO);
// ensure that the env is configured with a base fee
assert_eq!(executor.evm.env.block.basefee, U256::from(u64::MAX));
assert_eq!(executor.evm.block().basefee, U256::from(u64::MAX));
// Now execute a block with the fixed header, ensure that it does not fail
executor

View File

@ -4,7 +4,7 @@ use reth_primitives::{
constants::SYSTEM_ADDRESS, revm::env::fill_tx_env_with_beacon_root_contract_call, Address,
ChainSpec, Header, Withdrawal, B256, U256,
};
use revm::{Database, DatabaseCommit, EVM};
use revm::{interpreter::Host, Database, DatabaseCommit, Evm};
use std::collections::HashMap;
/// Collect all balance changes at the end of the block.
@ -57,12 +57,12 @@ pub fn post_block_balance_increments(
/// If cancun is not activated or the block is the genesis block, then this is a no-op, and no
/// state changes are made.
#[inline]
pub fn apply_beacon_root_contract_call<DB: Database + DatabaseCommit>(
pub fn apply_beacon_root_contract_call<EXT, DB: Database + DatabaseCommit>(
chain_spec: &ChainSpec,
block_timestamp: u64,
block_number: u64,
parent_beacon_block_root: Option<B256>,
evm: &mut EVM<DB>,
evm: &mut Evm<'_, EXT, DB>,
) -> Result<(), BlockExecutionError>
where
DB::Error: std::fmt::Display,
@ -87,15 +87,15 @@ where
}
// get previous env
let previous_env = evm.env.clone();
let previous_env = Box::new(evm.env().clone());
// modify env for pre block call
fill_tx_env_with_beacon_root_contract_call(&mut evm.env, parent_beacon_block_root);
fill_tx_env_with_beacon_root_contract_call(&mut evm.context.evm.env, parent_beacon_block_root);
let mut state = match evm.transact() {
Ok(res) => res.state,
Err(e) => {
evm.env = previous_env;
evm.context.evm.env = previous_env;
return Err(BlockValidationError::BeaconRootContractCall {
parent_beacon_block_root: Box::new(parent_beacon_block_root),
message: e.to_string(),
@ -105,13 +105,12 @@ where
};
state.remove(&SYSTEM_ADDRESS);
state.remove(&evm.env.block.coinbase);
state.remove(&evm.block().coinbase);
let db = evm.db().expect("db to not be moved");
db.commit(state);
evm.context.evm.db.commit(state);
// re-set the previous env
evm.env = previous_env;
evm.context.evm.env = previous_env;
Ok(())
}

View File

@ -248,7 +248,7 @@ impl AuthServerConfigBuilder {
.max_connections(500)
// bump the default request size slightly, there aren't any methods exposed with
// dynamic request params that can exceed this
.max_request_body_size(25 * 1024 * 1024)
.max_request_body_size(5 * 1024 * 1024)
.set_id_provider(EthSubscriptionIdProvider::default())
}),
}

View File

@ -295,12 +295,12 @@ where
self.inner.task_spawner.spawn_blocking(Box::pin(async move {
if count > MAX_PAYLOAD_BODIES_LIMIT {
tx.send(Err(EngineApiError::PayloadRequestTooLarge { len: count })).ok();
return
return;
}
if start == 0 || count == 0 {
tx.send(Err(EngineApiError::InvalidBodiesRange { start, count })).ok();
return
return;
}
let mut result = Vec::with_capacity(count as usize);
@ -324,7 +324,7 @@ where
}
Err(err) => {
tx.send(Err(EngineApiError::Internal(Box::new(err)))).ok();
return
return;
}
};
}

View File

@ -14,10 +14,8 @@ use alloy_rlp::{Decodable, Encodable};
use async_trait::async_trait;
use jsonrpsee::core::RpcResult;
use reth_primitives::{
revm::env::tx_env_with_recovered,
revm_primitives::{db::DatabaseCommit, BlockEnv, CfgEnv},
Address, Block, BlockId, BlockNumberOrTag, Bytes, TransactionSignedEcRecovered, Withdrawals,
B256,
revm::env::tx_env_with_recovered, Address, Block, BlockId, BlockNumberOrTag, Bytes,
TransactionSignedEcRecovered, Withdrawals, B256,
};
use reth_provider::{
BlockReaderIdExt, ChainSpecProvider, HeaderProvider, StateProviderBox, TransactionVariant,
@ -31,7 +29,10 @@ use reth_rpc_types::{
},
BlockError, Bundle, CallRequest, RichBlock, StateContext,
};
use revm::{db::CacheDB, primitives::Env};
use revm::{
db::CacheDB,
primitives::{db::DatabaseCommit, BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg},
};
use revm_inspectors::tracing::{
js::{JsInspector, TransactionContext},
FourByteInspector, TracingInspector, TracingInspectorConfig,
@ -73,7 +74,7 @@ where
&self,
at: BlockId,
transactions: Vec<TransactionSignedEcRecovered>,
cfg: CfgEnv,
cfg: CfgEnvWithHandlerCfg,
block_env: BlockEnv,
opts: GethDebugTracingOptions,
) -> EthResult<Vec<TraceResult>> {
@ -89,7 +90,10 @@ where
while let Some((index, tx)) = transactions.next() {
let tx_hash = tx.hash;
let tx = tx_env_with_recovered(&tx);
let env = Env { cfg: cfg.clone(), block: block_env.clone(), tx };
let env = EnvWithHandlerCfg::new(
Env::boxed(cfg.cfg_env.clone(), block_env.clone(), tx),
cfg.handler_cfg.spec_id,
);
let (result, state_changes) = this
.trace_transaction(
opts.clone(),
@ -233,7 +237,10 @@ where
tx.hash,
)?;
let env = Env { cfg, block: block_env, tx: tx_env_with_recovered(&tx) };
let env = EnvWithHandlerCfg::new(
Env::boxed(cfg.cfg_env.clone(), block_env, tx_env_with_recovered(&tx)),
cfg.handler_cfg.spec_id,
);
this.trace_transaction(
opts,
env,
@ -426,7 +433,10 @@ where
// Execute all transactions until index
for tx in transactions {
let tx = tx_env_with_recovered(&tx);
let env = Env { cfg: cfg.clone(), block: block_env.clone(), tx };
let env = EnvWithHandlerCfg::new(
Env::boxed(cfg.cfg_env.clone(), block_env.clone(), tx),
cfg.handler_cfg.spec_id,
);
let (res, _) = transact(&mut db, env)?;
db.commit(res.state);
}
@ -483,7 +493,7 @@ where
fn trace_transaction(
&self,
opts: GethDebugTracingOptions,
env: Env,
env: EnvWithHandlerCfg,
db: &mut SubState<StateProviderBox>,
transaction_context: Option<TransactionContext>,
) -> EthResult<(GethTrace, revm_primitives::State)> {

View File

@ -25,7 +25,9 @@ use reth_rpc_types::{
use reth_transaction_pool::TransactionPool;
use revm::{
db::{CacheDB, DatabaseRef},
primitives::{BlockEnv, CfgEnv, Env, ExecutionResult, Halt, TransactTo},
primitives::{
BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, ExecutionResult, HaltReason, TransactTo,
},
DatabaseCommit,
};
use tracing::trace;
@ -124,7 +126,8 @@ where
let transactions = block.into_transactions_ecrecovered().take(num_txs);
for tx in transactions {
let tx = tx_env_with_recovered(&tx);
let env = Env { cfg: cfg.clone(), block: block_env.clone(), tx };
let env =
EnvWithHandlerCfg::new_with_cfg_env(cfg.clone(), block_env.clone(), tx);
let (res, _) = transact(&mut db, env)?;
db.commit(res.state);
}
@ -173,7 +176,7 @@ where
/// This will execute the [CallRequest] and find the best gas limit via binary search
pub fn estimate_gas_with<S>(
&self,
mut cfg: CfgEnv,
mut cfg: CfgEnvWithHandlerCfg,
block: BlockEnv,
request: CallRequest,
state: S,
@ -328,7 +331,7 @@ where
}
ExecutionResult::Halt { reason, .. } => {
match reason {
Halt::OutOfGas(_) | Halt::InvalidFEOpcode => {
HaltReason::OutOfGas(_) | HaltReason::InvalidFEOpcode => {
// either out of gas or invalid opcode can be thrown dynamically if
// gasLeft is too low, so we treat this as `out of gas`, we know this
// call succeeds with a higher gaslimit. common usage of invalid opcode in openzeppelin <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/94697be8a3f0dfcd95dfb13ffbd39b5973f5c65d/contracts/metatx/ERC2771Forwarder.sol#L360-L367>
@ -401,13 +404,13 @@ where
// can consume the list since we're not using the request anymore
let initial = request.access_list.take().unwrap_or_default();
let precompiles = get_precompiles(env.cfg.spec_id);
let precompiles = get_precompiles(env.handler_cfg.spec_id);
let mut inspector = AccessListInspector::new(initial, from, to, precompiles);
let (result, env) = inspect(&mut db, env, &mut inspector)?;
match result.result {
ExecutionResult::Halt { reason, .. } => Err(match reason {
Halt::NonceOverflow => RpcInvalidTransactionError::NonceMaxValue,
HaltReason::NonceOverflow => RpcInvalidTransactionError::NonceMaxValue,
halt => RpcInvalidTransactionError::EvmHalt(halt),
}),
ExecutionResult::Revert { output, .. } => {
@ -418,9 +421,16 @@ where
let access_list = inspector.into_access_list();
let cfg_with_spec_id = CfgEnvWithHandlerCfg::new(env.cfg.clone(), env.handler_cfg.spec_id);
// calculate the gas used using the access list
request.access_list = Some(access_list.clone());
let gas_used = self.estimate_gas_with(env.cfg, env.block, request, db.db.state(), None)?;
let gas_used = self.estimate_gas_with(
cfg_with_spec_id,
env.block.clone(),
request,
db.db.state(),
None,
)?;
Ok(AccessListWithGasUsed { access_list, gas_used })
}
@ -431,7 +441,7 @@ where
#[inline]
fn map_out_of_gas_err<S>(
env_gas_limit: U256,
mut env: Env,
mut env: EnvWithHandlerCfg,
mut db: &mut CacheDB<StateProviderDatabase<S>>,
) -> EthApiError
where

View File

@ -17,7 +17,7 @@ use reth_interfaces::RethResult;
use reth_network_api::NetworkInfo;
use reth_node_api::ConfigureEvmEnv;
use reth_primitives::{
revm_primitives::{BlockEnv, CfgEnv},
revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg},
Address, BlockId, BlockNumberOrTag, ChainInfo, SealedBlockWithSenders, B256, U256, U64,
};
@ -27,6 +27,7 @@ use reth_provider::{
use reth_rpc_types::{SyncInfo, SyncStatus};
use reth_tasks::{TaskSpawner, TokioTaskExecutor};
use reth_transaction_pool::TransactionPool;
use revm_primitives::{CfgEnv, SpecId};
use std::{
fmt::Debug,
future::Future,
@ -265,7 +266,7 @@ where
Network: NetworkInfo + Send + Sync + 'static,
EvmConfig: ConfigureEvmEnv + Clone + 'static,
{
/// Configures the [CfgEnv] and [BlockEnv] for the pending block
/// Configures the [CfgEnvWithHandlerCfg] and [BlockEnv] for the pending block
///
/// If no pending block is available, this will derive it from the `latest` block
pub(crate) fn pending_block_env_and_cfg(&self) -> EthResult<PendingBlockEnv> {
@ -289,11 +290,11 @@ where
PendingBlockEnvOrigin::DerivedFromLatest(latest)
};
let mut cfg = CfgEnv::default();
let mut cfg = CfgEnvWithHandlerCfg::new(CfgEnv::default(), SpecId::LATEST);
#[cfg(feature = "optimism")]
{
cfg.optimism = self.provider().chain_spec().is_optimism();
cfg.handler_cfg.is_optimism = self.provider().chain_spec().is_optimism();
}
let mut block_env = BlockEnv::default();

View File

@ -4,9 +4,9 @@ use crate::eth::error::{EthApiError, EthResult};
use reth_primitives::{
constants::{eip4844::MAX_DATA_GAS_PER_BLOCK, BEACON_NONCE},
proofs,
revm::{compat::into_reth_log, env::tx_env_with_recovered},
revm::env::tx_env_with_recovered,
revm_primitives::{
BlockEnv, CfgEnv, EVMError, Env, InvalidTransaction, ResultAndState, SpecId,
BlockEnv, CfgEnvWithHandlerCfg, EVMError, Env, InvalidTransaction, ResultAndState, SpecId,
},
Block, BlockId, BlockNumberOrTag, ChainSpec, Header, IntoRecoveredTransaction, Receipt,
Receipts, SealedBlockWithSenders, SealedHeader, B256, EMPTY_OMMER_ROOT_HASH, U256,
@ -18,13 +18,14 @@ use reth_revm::{
};
use reth_transaction_pool::{BestTransactionsAttributes, TransactionPool};
use revm::{db::states::bundle_state::BundleRetention, Database, DatabaseCommit, State};
use revm_primitives::EnvWithHandlerCfg;
use std::time::Instant;
/// Configured [BlockEnv] and [CfgEnv] for a pending block
/// Configured [BlockEnv] and [CfgEnvWithHandlerCfg] for a pending block
#[derive(Debug, Clone)]
pub(crate) struct PendingBlockEnv {
/// Configured [CfgEnv] for the pending block.
pub(crate) cfg: CfgEnv,
/// Configured [CfgEnvWithHandlerCfg] for the pending block.
pub(crate) cfg: CfgEnvWithHandlerCfg,
/// Configured [BlockEnv] for the pending block.
pub(crate) block_env: BlockEnv,
/// Origin block for the config
@ -131,10 +132,9 @@ impl PendingBlockEnv {
// Configure the environment for the block.
let env =
Env { cfg: cfg.clone(), block: block_env.clone(), tx: tx_env_with_recovered(&tx) };
Env::boxed(cfg.cfg_env.clone(), block_env.clone(), tx_env_with_recovered(&tx));
let mut evm = revm::EVM::with_env(env);
evm.database(&mut db);
let mut evm = revm::Evm::builder().with_env(env).with_db(&mut db).build();
let ResultAndState { result, state } = match evm.transact() {
Ok(res) => res,
@ -157,7 +157,8 @@ impl PendingBlockEnv {
}
}
};
// drop evm to release db reference.
drop(evm);
// commit changes
db.commit(state);
@ -182,7 +183,7 @@ impl PendingBlockEnv {
tx_type: tx.tx_type(),
success: result.is_success(),
cumulative_gas_used,
logs: result.logs().into_iter().map(into_reth_log).collect(),
logs: result.logs().into_iter().map(Into::into).collect(),
#[cfg(feature = "optimism")]
deposit_nonce: None,
#[cfg(feature = "optimism")]
@ -233,7 +234,7 @@ impl PendingBlockEnv {
// check if cancun is activated to set eip4844 header fields correctly
let blob_gas_used =
if cfg.spec_id >= SpecId::CANCUN { Some(sum_blob_gas_used) } else { None };
if cfg.handler_cfg.spec_id >= SpecId::CANCUN { Some(sum_blob_gas_used) } else { None };
let header = Header {
parent_hash,
@ -266,8 +267,8 @@ impl PendingBlockEnv {
/// Apply the [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) pre block contract call.
///
/// This constructs a new [EVM](revm::EVM) with the given DB, and environment ([CfgEnv] and
/// [BlockEnv]) to execute the pre block contract call.
/// This constructs a new [Evm](revm::Evm) with the given DB, and environment [CfgEnvWithHandlerCfg]
/// and [BlockEnv]) to execute the pre block contract call.
///
/// This uses [apply_beacon_root_contract_call] to ultimately apply the beacon root contract state
/// change.
@ -275,23 +276,22 @@ fn pre_block_beacon_root_contract_call<DB: Database + DatabaseCommit>(
db: &mut DB,
chain_spec: &ChainSpec,
block_number: u64,
initialized_cfg: &CfgEnv,
initialized_cfg: &CfgEnvWithHandlerCfg,
initialized_block_env: &BlockEnv,
parent_beacon_block_root: Option<B256>,
) -> EthResult<()>
where
DB::Error: std::fmt::Display,
{
// Configure the environment for the block.
let env = Env {
cfg: initialized_cfg.clone(),
block: initialized_block_env.clone(),
..Default::default()
};
// apply pre-block EIP-4788 contract call
let mut evm_pre_block = revm::EVM::with_env(env);
evm_pre_block.database(db);
let mut evm_pre_block = revm::Evm::builder()
.with_db(db)
.with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env(
initialized_cfg.clone(),
initialized_block_env.clone(),
Default::default(),
))
.build();
// initialize a block from the env, because the pre block call needs the block itself
apply_beacon_root_contract_call(

View File

@ -18,7 +18,6 @@ use reth_node_api::ConfigureEvmEnv;
use reth_primitives::{
eip4844::calc_blob_gasprice,
revm::env::{fill_block_env_with_coinbase, tx_env_with_recovered},
revm_primitives::{db::DatabaseCommit, Env, ExecutionResult, ResultAndState, SpecId, State},
Address, BlockId, BlockNumberOrTag, Bytes, FromRecoveredPooledTransaction, Header,
IntoRecoveredTransaction, Receipt, SealedBlock, SealedBlockWithSenders,
TransactionKind::{Call, Create},
@ -39,7 +38,10 @@ use reth_rpc_types_compat::transaction::from_recovered_with_block_context;
use reth_transaction_pool::{TransactionOrigin, TransactionPool};
use revm::{
db::CacheDB,
primitives::{BlockEnv, CfgEnv},
primitives::{
db::DatabaseCommit, BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, ExecutionResult,
ResultAndState, SpecId, State,
},
Inspector,
};
@ -70,7 +72,8 @@ pub(crate) type StateCacheDB = CacheDB<StateProviderDatabase<StateProviderBox>>;
/// There are subtle differences between when transacting [CallRequest]:
///
/// The endpoints `eth_call` and `eth_estimateGas` and `eth_createAccessList` should always
/// __disable__ the base fee check in the [Env] [Cfg](revm_primitives::CfgEnv).
/// __disable__ the base fee check in the [EnvWithHandlerCfg]
/// [Cfg](revm_primitives::CfgEnvWithHandlerCfg).
///
/// The behaviour for tracing endpoints is not consistent across clients.
/// Geth also disables the basefee check for tracing: <https://github.com/ethereum/go-ethereum/blob/bc0b87ca196f92e5af49bd33cc190ef0ec32b197/eth/tracers/api.go#L955-L955>
@ -104,12 +107,16 @@ pub trait EthTransactions: Send + Sync {
/// for.
/// If the [BlockId] is pending, this will return the "Pending" tag, otherwise this returns the
/// hash of the exact block.
async fn evm_env_at(&self, at: BlockId) -> EthResult<(CfgEnv, BlockEnv, BlockId)>;
async fn evm_env_at(&self, at: BlockId)
-> EthResult<(CfgEnvWithHandlerCfg, BlockEnv, BlockId)>;
/// Returns the revm evm env for the raw block header
///
/// This is used for tracing raw blocks
async fn evm_env_for_raw_block(&self, at: &Header) -> EthResult<(CfgEnv, BlockEnv)>;
async fn evm_env_for_raw_block(
&self,
at: &Header,
) -> EthResult<(CfgEnvWithHandlerCfg, BlockEnv)>;
/// Get all transactions in the block with the given hash.
///
@ -177,8 +184,8 @@ pub trait EthTransactions: Send + Sync {
/// Prepares the state and env for the given [CallRequest] at the given [BlockId] and executes
/// the closure on a new task returning the result of the closure.
///
/// This returns the configured [Env] for the given [CallRequest] at the given [BlockId] and
/// with configured call settings: `prepare_call_env`.
/// This returns the configured [EnvWithHandlerCfg] for the given [CallRequest] at the given
/// [BlockId] and with configured call settings: `prepare_call_env`.
async fn spawn_with_call_at<F, R>(
&self,
request: CallRequest,
@ -187,7 +194,7 @@ pub trait EthTransactions: Send + Sync {
f: F,
) -> EthResult<R>
where
F: FnOnce(StateCacheDB, Env) -> EthResult<R> + Send + 'static,
F: FnOnce(StateCacheDB, EnvWithHandlerCfg) -> EthResult<R> + Send + 'static,
R: Send + 'static;
/// Executes the call request at the given [BlockId].
@ -196,7 +203,7 @@ pub trait EthTransactions: Send + Sync {
request: CallRequest,
at: BlockId,
overrides: EvmOverrides,
) -> EthResult<(ResultAndState, Env)>;
) -> EthResult<(ResultAndState, EnvWithHandlerCfg)>;
/// Executes the call request at the given [BlockId] on a new task and returns the result of the
/// inspect call.
@ -206,7 +213,7 @@ pub trait EthTransactions: Send + Sync {
at: BlockId,
overrides: EvmOverrides,
inspector: I,
) -> EthResult<(ResultAndState, Env)>
) -> EthResult<(ResultAndState, EnvWithHandlerCfg)>
where
I: Inspector<StateCacheDB> + Send + 'static;
@ -214,12 +221,12 @@ pub trait EthTransactions: Send + Sync {
/// config.
///
/// The callback is then called with the [TracingInspector] and the [ResultAndState] after the
/// configured [Env] was inspected.
/// configured [EnvWithHandlerCfg] was inspected.
///
/// Caution: this is blocking
fn trace_at<F, R>(
&self,
env: Env,
env: EnvWithHandlerCfg,
config: TracingInspectorConfig,
at: BlockId,
f: F,
@ -233,10 +240,10 @@ pub trait EthTransactions: Send + Sync {
/// config.
///
/// The callback is then called with the [TracingInspector] and the [ResultAndState] after the
/// configured [Env] was inspected.
/// configured [EnvWithHandlerCfg] was inspected.
async fn spawn_trace_at_with_state<F, R>(
&self,
env: Env,
env: EnvWithHandlerCfg,
config: TracingInspectorConfig,
at: BlockId,
f: F,
@ -364,7 +371,10 @@ where
.await
}
async fn evm_env_at(&self, at: BlockId) -> EthResult<(CfgEnv, BlockEnv, BlockId)> {
async fn evm_env_at(
&self,
at: BlockId,
) -> EthResult<(CfgEnvWithHandlerCfg, BlockEnv, BlockId)> {
if at.is_pending() {
let PendingBlockEnv { cfg, block_env, origin } = self.pending_block_env_and_cfg()?;
Ok((cfg, block_env, origin.state_block_id()))
@ -379,11 +389,14 @@ where
}
}
async fn evm_env_for_raw_block(&self, header: &Header) -> EthResult<(CfgEnv, BlockEnv)> {
async fn evm_env_for_raw_block(
&self,
header: &Header,
) -> EthResult<(CfgEnvWithHandlerCfg, BlockEnv)> {
// get the parent config first
let (cfg, mut block_env, _) = self.evm_env_at(header.parent_hash.into()).await?;
let after_merge = cfg.spec_id >= SpecId::MERGE;
let after_merge = cfg.handler_cfg.spec_id >= SpecId::MERGE;
fill_block_env_with_coinbase(&mut block_env, header, after_merge, header.beneficiary);
Ok((cfg, block_env))
@ -634,7 +647,7 @@ where
f: F,
) -> EthResult<R>
where
F: FnOnce(StateCacheDB, Env) -> EthResult<R> + Send + 'static,
F: FnOnce(StateCacheDB, EnvWithHandlerCfg) -> EthResult<R> + Send + 'static,
R: Send + 'static,
{
let (cfg, block_env, at) = self.evm_env_at(at).await?;
@ -664,7 +677,7 @@ where
request: CallRequest,
at: BlockId,
overrides: EvmOverrides,
) -> EthResult<(ResultAndState, Env)> {
) -> EthResult<(ResultAndState, EnvWithHandlerCfg)> {
self.spawn_with_call_at(request, at, overrides, move |mut db, env| transact(&mut db, env))
.await
}
@ -675,7 +688,7 @@ where
at: BlockId,
overrides: EvmOverrides,
inspector: I,
) -> EthResult<(ResultAndState, Env)>
) -> EthResult<(ResultAndState, EnvWithHandlerCfg)>
where
I: Inspector<StateCacheDB> + Send + 'static,
{
@ -685,7 +698,7 @@ where
fn trace_at<F, R>(
&self,
env: Env,
env: EnvWithHandlerCfg,
config: TracingInspectorConfig,
at: BlockId,
f: F,
@ -705,7 +718,7 @@ where
async fn spawn_trace_at_with_state<F, R>(
&self,
env: Env,
env: EnvWithHandlerCfg,
config: TracingInspectorConfig,
at: BlockId,
f: F,
@ -773,7 +786,8 @@ where
// replay all transactions prior to the targeted transaction
replay_transactions_until(&mut db, cfg.clone(), block_env.clone(), block_txs, tx.hash)?;
let env = Env { cfg, block: block_env, tx: tx_env_with_recovered(&tx) };
let env =
EnvWithHandlerCfg::new_with_cfg_env(cfg, block_env, tx_env_with_recovered(&tx));
let mut inspector = TracingInspector::new(config);
let (res, _, db) = inspect_and_return_db(db, env, &mut inspector)?;
@ -866,7 +880,7 @@ where
let mut db = CacheDB::new(StateProviderDatabase::new(state));
while let Some((tx_info, tx)) = transactions.next() {
let env = Env { cfg: cfg.clone(), block: block_env.clone(), tx };
let env = EnvWithHandlerCfg::new_with_cfg_env(cfg.clone(), block_env.clone(), tx);
let mut inspector = TracingInspector::new(config);
let (res, _) = inspect(&mut db, env, &mut inspector)?;
@ -1240,10 +1254,11 @@ pub(crate) fn build_transaction_receipt_with_block_receipts(
if let Some(l1_block_info) = optimism_tx_meta.l1_block_info {
if !transaction.is_deposit() {
op_fields.l1_fee = optimism_tx_meta.l1_fee;
op_fields.l1_gas_used =
optimism_tx_meta.l1_data_gas.map(|dg| dg + l1_block_info.l1_fee_overhead);
op_fields.l1_gas_used = optimism_tx_meta
.l1_data_gas
.map(|dg| dg + l1_block_info.l1_fee_overhead.unwrap_or_default());
op_fields.l1_fee_scalar =
Some(l1_block_info.l1_fee_scalar.div(U256::from(1_000_000)));
Some(l1_block_info.l1_base_fee_scalar.div(U256::from(1_000_000)));
op_fields.l1_gas_price = Some(l1_block_info.l1_base_fee);
}
}

View File

@ -20,8 +20,9 @@ use reth_rpc_api::EthCallBundleApiServer;
use reth_rpc_types::{EthCallBundle, EthCallBundleResponse, EthCallBundleTransactionResult};
use revm::{
db::CacheDB,
primitives::{Env, ResultAndState, TxEnv},
primitives::{ResultAndState, TxEnv},
};
use revm_primitives::EnvWithHandlerCfg;
use std::sync::Arc;
/// `Eth` bundle implementation.
@ -79,7 +80,7 @@ where
.spawn_with_state_at_block(at, move |state| {
let coinbase = block_env.coinbase;
let basefee = Some(block_env.basefee.to::<u64>());
let env = Env { cfg, block: block_env, tx: TxEnv::default() };
let env = EnvWithHandlerCfg::new_with_cfg_env(cfg, block_env, TxEnv::default());
let db = CacheDB::new(StateProviderDatabase::new(state));
let initial_coinbase = DatabaseRef::basic_ref(&db, coinbase)?
@ -91,8 +92,8 @@ where
let mut total_gas_fess = U256::ZERO;
let mut hash_bytes = Vec::with_capacity(32 * transactions.len());
let mut evm = revm::EVM::with_env(env);
evm.database(db);
let mut evm =
revm::Evm::builder().with_db(db).with_env_with_handler_cfg(env).build();
let mut results = Vec::with_capacity(transactions.len());
let mut transactions = transactions.into_iter().peekable();
@ -103,7 +104,7 @@ where
let gas_price = tx
.effective_tip_per_gas(basefee)
.ok_or_else(|| RpcInvalidTransactionError::FeeCapTooLow)?;
tx.try_fill_tx_env(&mut evm.env.tx)?;
tx.try_fill_tx_env(evm.tx_mut())?;
let ResultAndState { result, state } = evm.transact()?;
let gas_used = result.gas_used();
@ -150,7 +151,7 @@ where
if transactions.peek().is_some() {
// need to apply the state changes of this call before executing
// the next call
evm.db.as_mut().expect("is set").commit(state)
evm.context.evm.db.commit(state)
}
}

View File

@ -11,7 +11,7 @@ use reth_provider::{
BlockReader, CanonStateNotification, EvmEnvProvider, StateProviderFactory, TransactionVariant,
};
use reth_tasks::{TaskSpawner, TokioTaskExecutor};
use revm::primitives::{BlockEnv, CfgEnv};
use revm::primitives::{BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId};
use schnellru::{ByLength, Limiter};
use std::{
future::Future,
@ -44,7 +44,7 @@ type BlockWithSendersResponseSender = oneshot::Sender<ProviderResult<Option<Bloc
type ReceiptsResponseSender = oneshot::Sender<ProviderResult<Option<Arc<Vec<Receipt>>>>>;
/// The type that can send the response to a requested env
type EnvResponseSender = oneshot::Sender<ProviderResult<(CfgEnv, BlockEnv)>>;
type EnvResponseSender = oneshot::Sender<ProviderResult<(CfgEnvWithHandlerCfg, BlockEnv)>>;
type BlockLruCache<L> = MultiConsumerLruCache<
B256,
@ -56,7 +56,8 @@ type BlockLruCache<L> = MultiConsumerLruCache<
type ReceiptsLruCache<L> =
MultiConsumerLruCache<B256, Arc<Vec<Receipt>>, L, ReceiptsResponseSender>;
type EnvLruCache<L> = MultiConsumerLruCache<B256, (CfgEnv, BlockEnv), L, EnvResponseSender>;
type EnvLruCache<L> =
MultiConsumerLruCache<B256, (CfgEnvWithHandlerCfg, BlockEnv), L, EnvResponseSender>;
/// Provides async access to cached eth data
///
@ -252,7 +253,10 @@ impl EthStateCache {
///
/// Returns an error if the corresponding header (required for populating the envs) was not
/// found.
pub async fn get_evm_env(&self, block_hash: B256) -> ProviderResult<(CfgEnv, BlockEnv)> {
pub async fn get_evm_env(
&self,
block_hash: B256,
) -> ProviderResult<(CfgEnvWithHandlerCfg, BlockEnv)> {
let (response_tx, rx) = oneshot::channel();
let _ = self.to_service.send(CacheAction::GetEnv { block_hash, response_tx });
rx.await.map_err(|_| ProviderError::CacheServiceUnavailable)?
@ -285,7 +289,7 @@ pub(crate) struct EthStateCacheService<
> where
LimitBlocks: Limiter<B256, BlockWithSenders>,
LimitReceipts: Limiter<B256, Arc<Vec<Receipt>>>,
LimitEnvs: Limiter<B256, (CfgEnv, BlockEnv)>,
LimitEnvs: Limiter<B256, (CfgEnvWithHandlerCfg, BlockEnv)>,
{
/// The type used to lookup data from disk
provider: Provider,
@ -476,7 +480,10 @@ where
this.action_task_spawner.spawn_blocking(Box::pin(async move {
// Acquire permit
let _permit = rate_limiter.acquire().await;
let mut cfg = CfgEnv::default();
let mut cfg = CfgEnvWithHandlerCfg::new(
CfgEnv::default(),
SpecId::LATEST,
);
let mut block_env = BlockEnv::default();
let res = provider
.fill_env_at(
@ -551,7 +558,7 @@ enum CacheAction {
GetReceipts { block_hash: B256, response_tx: ReceiptsResponseSender },
BlockWithSendersResult { block_hash: B256, res: ProviderResult<Option<BlockWithSenders>> },
ReceiptsResult { block_hash: B256, res: ProviderResult<Option<Arc<Vec<Receipt>>>> },
EnvResult { block_hash: B256, res: Box<ProviderResult<(CfgEnv, BlockEnv)>> },
EnvResult { block_hash: B256, res: Box<ProviderResult<(CfgEnvWithHandlerCfg, BlockEnv)>> },
CacheNewCanonicalChain { blocks: Vec<SealedBlockWithSenders>, receipts: Vec<BlockReceipts> },
}

View File

@ -14,7 +14,7 @@ use reth_transaction_pool::error::{
Eip4844PoolTransactionError, InvalidPoolTransactionError, PoolError, PoolErrorKind,
PoolTransactionError,
};
use revm::primitives::{EVMError, ExecutionResult, Halt, OutOfGasError};
use revm::primitives::{EVMError, ExecutionResult, HaltReason, OutOfGasError};
use std::time::Duration;
/// Result alias
@ -110,6 +110,9 @@ pub enum EthApiError {
#[error(transparent)]
#[cfg(feature = "optimism")]
Optimism(#[from] OptimismEthApiError),
/// Evm generic purpose error.
#[error("Revm error: {0}")]
EvmCustom(String),
}
/// Eth Optimism Api Error
@ -150,7 +153,8 @@ impl From<EthApiError> for ErrorObject<'static> {
EthApiError::ExcessBlobGasNotSet |
EthApiError::InvalidBlockData(_) |
EthApiError::Internal(_) |
EthApiError::TransactionNotFound => internal_rpc_err(error.to_string()),
EthApiError::TransactionNotFound |
EthApiError::EvmCustom(_) => internal_rpc_err(error.to_string()),
EthApiError::UnknownBlockNumber | EthApiError::UnknownBlockOrTxIndex => {
rpc_error_with_code(EthRpcErrorCode::ResourceNotFound.code(), error.to_string())
}
@ -234,6 +238,7 @@ where
EthApiError::ExcessBlobGasNotSet
}
EVMError::Database(err) => err.into(),
EVMError::Custom(err) => EthApiError::EvmCustom(err),
}
}
}
@ -320,7 +325,7 @@ pub enum RpcInvalidTransactionError {
Revert(RevertError),
/// Unspecific EVM halt error.
#[error("EVM error {0:?}")]
EvmHalt(Halt),
EvmHalt(HaltReason),
/// Invalid chain id set for the transaction.
#[error("invalid chain ID")]
InvalidChainId,
@ -385,10 +390,10 @@ impl RpcInvalidTransactionError {
/// Converts the halt error
///
/// Takes the configured gas limit of the transaction which is attached to the error
pub(crate) fn halt(reason: Halt, gas_limit: u64) -> Self {
pub(crate) fn halt(reason: HaltReason, gas_limit: u64) -> Self {
match reason {
Halt::OutOfGas(err) => RpcInvalidTransactionError::out_of_gas(err, gas_limit),
Halt::NonceOverflow => RpcInvalidTransactionError::NonceMaxValue,
HaltReason::OutOfGas(err) => RpcInvalidTransactionError::out_of_gas(err, gas_limit),
HaltReason::NonceOverflow => RpcInvalidTransactionError::NonceMaxValue,
err => RpcInvalidTransactionError::EvmHalt(err),
}
}
@ -397,7 +402,7 @@ impl RpcInvalidTransactionError {
pub(crate) fn out_of_gas(reason: OutOfGasError, gas_limit: u64) -> Self {
let gas_limit = U256::from(gas_limit);
match reason {
OutOfGasError::BasicOutOfGas => RpcInvalidTransactionError::BasicOutOfGas(gas_limit),
OutOfGasError::Basic => RpcInvalidTransactionError::BasicOutOfGas(gas_limit),
OutOfGasError::Memory => RpcInvalidTransactionError::MemoryOutOfGas(gas_limit),
OutOfGasError::Precompile => RpcInvalidTransactionError::PrecompileOutOfGas(gas_limit),
OutOfGasError::InvalidOperand => {
@ -449,7 +454,7 @@ impl From<revm::primitives::InvalidTransaction> for RpcInvalidTransactionError {
InvalidTransaction::NonceOverflowInTransaction => {
RpcInvalidTransactionError::NonceMaxValue
}
InvalidTransaction::CreateInitcodeSizeLimit => {
InvalidTransaction::CreateInitCodeSizeLimit => {
RpcInvalidTransactionError::MaxInitCodeSizeExceeded
}
InvalidTransaction::NonceTooHigh { .. } => RpcInvalidTransactionError::NonceTooHigh,

View File

@ -17,13 +17,13 @@ use reth_rpc_types::{
use revm::primitives::{Bytes, OptimismFields};
use revm::{
db::CacheDB,
precompile::{Precompiles, SpecId as PrecompilesSpecId},
primitives::{BlockEnv, CfgEnv, Env, ResultAndState, SpecId, TransactTo, TxEnv},
Database, Inspector,
};
use revm_primitives::{
db::{DatabaseCommit, DatabaseRef},
Bytecode,
inspector_handle_register,
precompile::{PrecompileSpecId, Precompiles},
primitives::{
db::DatabaseRef, BlockEnv, Bytecode, CfgEnvWithHandlerCfg, EnvWithHandlerCfg,
ResultAndState, SpecId, TransactTo, TxEnv,
},
Database, GetInspector,
};
use tracing::trace;
@ -116,33 +116,45 @@ impl FillableTransaction for TransactionSigned {
/// Returns the addresses of the precompiles corresponding to the SpecId.
#[inline]
pub(crate) fn get_precompiles(spec_id: SpecId) -> impl IntoIterator<Item = Address> {
let spec = PrecompilesSpecId::from_spec_id(spec_id);
Precompiles::new(spec).addresses().into_iter().copied().map(Address::from)
let spec = PrecompileSpecId::from_spec_id(spec_id);
Precompiles::new(spec).addresses().copied().map(Address::from)
}
/// Executes the [Env] against the given [Database] without committing state changes.
pub(crate) fn transact<DB>(db: DB, env: Env) -> EthResult<(ResultAndState, Env)>
/// Executes the [EnvWithHandlerCfg] against the given [Database] without committing state changes.
pub(crate) fn transact<DB>(
db: DB,
env: EnvWithHandlerCfg,
) -> EthResult<(ResultAndState, EnvWithHandlerCfg)>
where
DB: Database,
<DB as Database>::Error: Into<EthApiError>,
{
let mut evm = revm::EVM::with_env(env);
evm.database(db);
let mut evm = revm::Evm::builder().with_db(db).with_env_with_handler_cfg(env).build();
let res = evm.transact()?;
Ok((res, evm.env))
let (_, env) = evm.into_db_and_env_with_handler_cfg();
Ok((res, env))
}
/// Executes the [Env] against the given [Database] without committing state changes.
pub(crate) fn inspect<DB, I>(db: DB, env: Env, inspector: I) -> EthResult<(ResultAndState, Env)>
/// Executes the [EnvWithHandlerCfg] against the given [Database] without committing state changes.
pub(crate) fn inspect<DB, I>(
db: DB,
env: EnvWithHandlerCfg,
inspector: I,
) -> EthResult<(ResultAndState, EnvWithHandlerCfg)>
where
DB: Database,
<DB as Database>::Error: Into<EthApiError>,
I: Inspector<DB>,
I: GetInspector<DB>,
{
let mut evm = revm::EVM::with_env(env);
evm.database(db);
let res = evm.inspect(inspector)?;
Ok((res, evm.env))
let mut evm = revm::Evm::builder()
.with_db(db)
.with_external_context(inspector)
.with_env_with_handler_cfg(env)
.append_handler_register(inspector_handle_register)
.build();
let res = evm.transact()?;
let (_, env) = evm.into_db_and_env_with_handler_cfg();
Ok((res, env))
}
/// Same as [inspect] but also returns the database again.
@ -151,19 +163,23 @@ where
/// this is still useful if there are certain trait bounds on the Inspector's database generic type
pub(crate) fn inspect_and_return_db<DB, I>(
db: DB,
env: Env,
env: EnvWithHandlerCfg,
inspector: I,
) -> EthResult<(ResultAndState, Env, DB)>
) -> EthResult<(ResultAndState, EnvWithHandlerCfg, DB)>
where
DB: Database,
<DB as Database>::Error: Into<EthApiError>,
I: Inspector<DB>,
I: GetInspector<DB>,
{
let mut evm = revm::EVM::with_env(env);
evm.database(db);
let res = evm.inspect(inspector)?;
let db = evm.take_db();
Ok((res, evm.env, db))
let mut evm = revm::Evm::builder()
.with_external_context(inspector)
.with_db(db)
.with_env_with_handler_cfg(env)
.append_handler_register(inspector_handle_register)
.build();
let res = evm.transact()?;
let (db, env) = evm.into_db_and_env_with_handler_cfg();
Ok((res, env, db))
}
/// Replays all the transactions until the target transaction is found.
@ -175,7 +191,7 @@ where
/// Returns the index of the target transaction in the given iterator.
pub(crate) fn replay_transactions_until<DB, I, Tx>(
db: &mut CacheDB<DB>,
cfg: CfgEnv,
cfg: CfgEnvWithHandlerCfg,
block_env: BlockEnv,
transactions: I,
target_tx_hash: B256,
@ -186,9 +202,14 @@ where
I: IntoIterator<Item = Tx>,
Tx: FillableTransaction,
{
let env = Env { cfg, block: block_env, tx: TxEnv::default() };
let mut evm = revm::EVM::with_env(env);
evm.database(db);
let mut evm = revm::Evm::builder()
.with_db(db)
.with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env(
cfg,
block_env,
Default::default(),
))
.build();
let mut index = 0;
for tx in transactions.into_iter() {
if tx.hash() == target_tx_hash {
@ -196,15 +217,14 @@ where
break
}
tx.try_fill_tx_env(&mut evm.env.tx)?;
let res = evm.transact()?;
evm.db.as_mut().expect("is set").commit(res.state);
tx.try_fill_tx_env(evm.tx_mut())?;
evm.transact_commit()?;
index += 1;
}
Ok(index)
}
/// Prepares the [Env] for execution.
/// Prepares the [EnvWithHandlerCfg] for execution.
///
/// Does not commit any changes to the underlying database.
///
@ -213,13 +233,13 @@ where
/// - `disable_eip3607` is set to `true`
/// - `disable_base_fee` is set to `true`
pub(crate) fn prepare_call_env<DB>(
mut cfg: CfgEnv,
mut cfg: CfgEnvWithHandlerCfg,
block: BlockEnv,
request: CallRequest,
gas_limit: u64,
db: &mut CacheDB<DB>,
overrides: EvmOverrides,
) -> EthResult<Env>
) -> EthResult<EnvWithHandlerCfg>
where
DB: DatabaseRef,
EthApiError: From<<DB as DatabaseRef>::Error>,
@ -253,7 +273,7 @@ where
db.block_hashes
.extend(block_hashes.into_iter().map(|(num, hash)| (U256::from(num), hash)))
}
apply_block_overrides(*block_overrides, &mut env.block);
apply_block_overrides(*block_overrides, &mut env.env.block);
}
if request_gas.is_none() {
@ -276,16 +296,16 @@ where
Ok(env)
}
/// Creates a new [Env] to be used for executing the [CallRequest] in `eth_call`.
/// Creates a new [EnvWithHandlerCfg] to be used for executing the [CallRequest] in `eth_call`.
///
/// Note: this does _not_ access the Database to check the sender.
pub(crate) fn build_call_evm_env(
cfg: CfgEnv,
cfg: CfgEnvWithHandlerCfg,
block: BlockEnv,
request: CallRequest,
) -> EthResult<Env> {
) -> EthResult<EnvWithHandlerCfg> {
let tx = create_txn_env(&block, request)?;
Ok(Env { cfg, block, tx })
Ok(EnvWithHandlerCfg::new_with_cfg_env(cfg, block, tx))
}
/// Configures a new [TxEnv] for the [CallRequest]

View File

@ -11,8 +11,7 @@ use async_trait::async_trait;
use jsonrpsee::core::RpcResult as Result;
use reth_consensus_common::calc::{base_block_reward, block_reward};
use reth_primitives::{
revm::env::tx_env_with_recovered, revm_primitives::db::DatabaseCommit, BlockId,
BlockNumberOrTag, Bytes, SealedHeader, B256, U256,
revm::env::tx_env_with_recovered, BlockId, BlockNumberOrTag, Bytes, SealedHeader, B256, U256,
};
use reth_provider::{BlockReader, ChainSpecProvider, EvmEnvProvider, StateProviderFactory};
use reth_revm::{
@ -25,7 +24,10 @@ use reth_rpc_types::{
trace::{filter::TraceFilter, parity::*, tracerequest::TraceCallRequest},
BlockError, BlockOverrides, CallRequest, Index,
};
use revm::{db::CacheDB, primitives::Env};
use revm::{
db::{CacheDB, DatabaseCommit},
primitives::EnvWithHandlerCfg,
};
use std::{collections::HashSet, sync::Arc};
use tokio::sync::{AcquireError, OwnedSemaphorePermit};
@ -101,7 +103,7 @@ where
.evm_env_at(block_id.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest)))
.await?;
let tx = tx_env_with_recovered(&tx.into_ecrecovered_transaction());
let env = Env { cfg, block, tx };
let env = EnvWithHandlerCfg::new_with_cfg_env(cfg, block, tx);
let config = TracingInspectorConfig::from_parity_config(&trace_types);

View File

@ -383,7 +383,8 @@ mod tests {
tx.get::<tables::Transactions>(0).err(),
Some(DatabaseError::Open(reth_libmdbx::Error::NotFound.into()))
); // Transaction is not timeout-ed
assert!(!tx.metrics_handler.unwrap().backtrace_recorded.load(Ordering::Relaxed)); // Backtrace is not recorded
assert!(!tx.metrics_handler.unwrap().backtrace_recorded.load(Ordering::Relaxed));
// Backtrace is not recorded
}
#[test]
@ -402,6 +403,7 @@ mod tests {
tx.get::<tables::Transactions>(0).err(),
Some(DatabaseError::Open(reth_libmdbx::Error::ReadTransactionAborted.into()))
); // Transaction is timeout-ed
assert!(tx.metrics_handler.unwrap().backtrace_recorded.load(Ordering::Relaxed)); // Backtrace is recorded
assert!(tx.metrics_handler.unwrap().backtrace_recorded.load(Ordering::Relaxed));
// Backtrace is recorded
}
}

View File

@ -20,7 +20,7 @@ use reth_primitives::{
SealedHeader, TransactionMeta, TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber,
Withdrawal, Withdrawals, B256, U256,
};
use revm::primitives::{BlockEnv, CfgEnv};
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
use std::{
ops::{RangeBounds, RangeInclusive},
path::{Path, PathBuf},
@ -440,7 +440,7 @@ impl<DB: Database> StageCheckpointReader for ProviderFactory<DB> {
impl<DB: Database> EvmEnvProvider for ProviderFactory<DB> {
fn fill_env_at<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
at: BlockHashOrNumber,
evm_config: EvmConfig,
@ -453,7 +453,7 @@ impl<DB: Database> EvmEnvProvider for ProviderFactory<DB> {
fn fill_env_with_header<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
header: &Header,
evm_config: EvmConfig,
@ -482,7 +482,7 @@ impl<DB: Database> EvmEnvProvider for ProviderFactory<DB> {
fn fill_cfg_env_at<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
at: BlockHashOrNumber,
evm_config: EvmConfig,
) -> ProviderResult<()>
@ -494,7 +494,7 @@ impl<DB: Database> EvmEnvProvider for ProviderFactory<DB> {
fn fill_cfg_env_with_header<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
header: &Header,
evm_config: EvmConfig,
) -> ProviderResult<()>

View File

@ -43,7 +43,7 @@ use reth_primitives::{
TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, U256,
};
use reth_trie::{prefix_set::PrefixSetMut, updates::TrieUpdates, HashedPostState, StateRoot};
use revm::primitives::{BlockEnv, CfgEnv, SpecId};
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg, SpecId};
use std::{
collections::{hash_map, BTreeMap, BTreeSet, HashMap, HashSet},
fmt::Debug,
@ -1728,7 +1728,7 @@ impl<TX: DbTx> WithdrawalsProvider for DatabaseProvider<TX> {
impl<TX: DbTx> EvmEnvProvider for DatabaseProvider<TX> {
fn fill_env_at<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
at: BlockHashOrNumber,
evm_config: EvmConfig,
@ -1743,7 +1743,7 @@ impl<TX: DbTx> EvmEnvProvider for DatabaseProvider<TX> {
fn fill_env_with_header<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
header: &Header,
_evm_config: EvmConfig,
@ -1801,7 +1801,7 @@ impl<TX: DbTx> EvmEnvProvider for DatabaseProvider<TX> {
fn fill_cfg_env_at<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
at: BlockHashOrNumber,
evm_config: EvmConfig,
) -> ProviderResult<()>
@ -1815,7 +1815,7 @@ impl<TX: DbTx> EvmEnvProvider for DatabaseProvider<TX> {
fn fill_cfg_env_with_header<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
header: &Header,
_evm_config: EvmConfig,
) -> ProviderResult<()>

View File

@ -22,7 +22,7 @@ use reth_primitives::{
TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256,
U256,
};
use revm::primitives::{BlockEnv, CfgEnv};
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
use std::{
collections::{BTreeMap, HashSet},
ops::{RangeBounds, RangeInclusive},
@ -460,7 +460,7 @@ where
{
fn fill_env_at<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
at: BlockHashOrNumber,
evm_config: EvmConfig,
@ -473,7 +473,7 @@ where
fn fill_env_with_header<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
header: &Header,
evm_config: EvmConfig,
@ -502,7 +502,7 @@ where
fn fill_cfg_env_at<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
at: BlockHashOrNumber,
evm_config: EvmConfig,
) -> ProviderResult<()>
@ -514,7 +514,7 @@ where
fn fill_cfg_env_with_header<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
header: &Header,
evm_config: EvmConfig,
) -> ProviderResult<()>

View File

@ -18,7 +18,7 @@ use reth_primitives::{
U256,
};
use reth_trie::updates::TrieUpdates;
use revm::primitives::{BlockEnv, CfgEnv};
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
use std::{
collections::{BTreeMap, HashMap},
ops::{RangeBounds, RangeInclusive},
@ -558,7 +558,7 @@ impl StateProvider for MockEthProvider {
impl EvmEnvProvider for MockEthProvider {
fn fill_env_at<EvmConfig>(
&self,
_cfg: &mut CfgEnv,
_cfg: &mut CfgEnvWithHandlerCfg,
_block_env: &mut BlockEnv,
_at: BlockHashOrNumber,
_evm_config: EvmConfig,
@ -571,7 +571,7 @@ impl EvmEnvProvider for MockEthProvider {
fn fill_env_with_header<EvmConfig>(
&self,
_cfg: &mut CfgEnv,
_cfg: &mut CfgEnvWithHandlerCfg,
_block_env: &mut BlockEnv,
_header: &Header,
_evm_config: EvmConfig,
@ -600,7 +600,7 @@ impl EvmEnvProvider for MockEthProvider {
fn fill_cfg_env_at<EvmConfig>(
&self,
_cfg: &mut CfgEnv,
_cfg: &mut CfgEnvWithHandlerCfg,
_at: BlockHashOrNumber,
_evm_config: EvmConfig,
) -> ProviderResult<()>
@ -612,7 +612,7 @@ impl EvmEnvProvider for MockEthProvider {
fn fill_cfg_env_with_header<EvmConfig>(
&self,
_cfg: &mut CfgEnv,
_cfg: &mut CfgEnvWithHandlerCfg,
_header: &Header,
_evm_config: EvmConfig,
) -> ProviderResult<()>

View File

@ -20,7 +20,7 @@ use reth_primitives::{
MAINNET, U256,
};
use reth_trie::updates::TrieUpdates;
use revm::primitives::{BlockEnv, CfgEnv};
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
use std::{
ops::{RangeBounds, RangeInclusive},
sync::Arc,
@ -318,7 +318,7 @@ impl StateProvider for NoopProvider {
impl EvmEnvProvider for NoopProvider {
fn fill_env_at<EvmConfig>(
&self,
_cfg: &mut CfgEnv,
_cfg: &mut CfgEnvWithHandlerCfg,
_block_env: &mut BlockEnv,
_at: BlockHashOrNumber,
_evm_config: EvmConfig,
@ -331,7 +331,7 @@ impl EvmEnvProvider for NoopProvider {
fn fill_env_with_header<EvmConfig>(
&self,
_cfg: &mut CfgEnv,
_cfg: &mut CfgEnvWithHandlerCfg,
_block_env: &mut BlockEnv,
_header: &Header,
_evm_config: EvmConfig,
@ -360,7 +360,7 @@ impl EvmEnvProvider for NoopProvider {
fn fill_cfg_env_at<EvmConfig>(
&self,
_cfg: &mut CfgEnv,
_cfg: &mut CfgEnvWithHandlerCfg,
_at: BlockHashOrNumber,
_evm_config: EvmConfig,
) -> ProviderResult<()>
@ -372,7 +372,7 @@ impl EvmEnvProvider for NoopProvider {
fn fill_cfg_env_with_header<EvmConfig>(
&self,
_cfg: &mut CfgEnv,
_cfg: &mut CfgEnvWithHandlerCfg,
_header: &Header,
_evm_config: EvmConfig,
) -> ProviderResult<()>

View File

@ -1,19 +1,19 @@
use reth_interfaces::provider::ProviderResult;
use reth_node_api::ConfigureEvmEnv;
use reth_primitives::{BlockHashOrNumber, Header};
use revm::primitives::{BlockEnv, CfgEnv};
use revm::primitives::{BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId};
/// A provider type that knows chain specific information required to configure an
/// [Env](revm::primitives::Env).
/// [CfgEnvWithHandlerCfg].
///
/// This type is mainly used to provide required data to configure the EVM environment.
#[auto_impl::auto_impl(&, Arc)]
pub trait EvmEnvProvider: Send + Sync {
/// Fills the [CfgEnv] and [BlockEnv] fields with values specific to the given
/// Fills the [CfgEnvWithHandlerCfg] and [BlockEnv] fields with values specific to the given
/// [BlockHashOrNumber].
fn fill_env_at<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
at: BlockHashOrNumber,
evm_config: EvmConfig,
@ -21,25 +21,27 @@ pub trait EvmEnvProvider: Send + Sync {
where
EvmConfig: ConfigureEvmEnv;
/// Fills the default [CfgEnv] and [BlockEnv] fields with values specific to the given [Header].
/// Fills the default [CfgEnvWithHandlerCfg] and [BlockEnv] fields with values specific to the
/// given [Header].
fn env_with_header<EvmConfig>(
&self,
header: &Header,
evm_config: EvmConfig,
) -> ProviderResult<(CfgEnv, BlockEnv)>
) -> ProviderResult<(CfgEnvWithHandlerCfg, BlockEnv)>
where
EvmConfig: ConfigureEvmEnv,
{
let mut cfg = CfgEnv::default();
let mut cfg = CfgEnvWithHandlerCfg::new(CfgEnv::default(), SpecId::LATEST);
let mut block_env = BlockEnv::default();
self.fill_env_with_header::<EvmConfig>(&mut cfg, &mut block_env, header, evm_config)?;
Ok((cfg, block_env))
}
/// Fills the [CfgEnv] and [BlockEnv] fields with values specific to the given [Header].
/// Fills the [CfgEnvWithHandlerCfg] and [BlockEnv] fields with values specific to the given
/// [Header].
fn fill_env_with_header<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
header: &Header,
evm_config: EvmConfig,
@ -61,20 +63,21 @@ pub trait EvmEnvProvider: Send + Sync {
header: &Header,
) -> ProviderResult<()>;
/// Fills the [CfgEnv] fields with values specific to the given [BlockHashOrNumber].
/// Fills the [CfgEnvWithHandlerCfg] fields with values specific to the given
/// [BlockHashOrNumber].
fn fill_cfg_env_at<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
at: BlockHashOrNumber,
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv;
/// Fills the [CfgEnv] fields with values specific to the given [Header].
/// Fills the [CfgEnvWithHandlerCfg] fields with values specific to the given [Header].
fn fill_cfg_env_with_header<EvmConfig>(
&self,
cfg: &mut CfgEnv,
cfg: &mut CfgEnvWithHandlerCfg,
header: &Header,
evm_config: EvmConfig,
) -> ProviderResult<()>

View File

@ -305,6 +305,8 @@ pub enum ForkSpec {
/// After Merge plus new PUSH0 opcode
#[serde(alias = "Merge+3855")]
MergePush0,
/// Cancun
Cancun,
/// Fork Spec which is unknown to us
#[serde(other)]
Unknown,
@ -335,6 +337,7 @@ impl From<ForkSpec> for ChainSpec {
ForkSpec::MergeMeterInitCode => spec_builder.paris_activated(),
ForkSpec::MergePush0 => spec_builder.paris_activated(),
ForkSpec::Shanghai => spec_builder.shanghai_activated(),
ForkSpec::Cancun => spec_builder.cancun_activated(),
ForkSpec::ByzantiumToConstantinopleAt5 | ForkSpec::Constantinople => {
panic!("Overridden with PETERSBURG")
}