Skip to content

Commit

Permalink
refactor: adopt REVM in edr_evm
Browse files Browse the repository at this point in the history
  • Loading branch information
Wodann committed Sep 16, 2024
1 parent 706b1bf commit 00ab711
Show file tree
Hide file tree
Showing 23 changed files with 371 additions and 397 deletions.
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions crates/edr_eth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ itertools = { version = "0.10.5", default-features = false, features = ["use_all
k256 = { version = "0.13.1", default-features = false, features = ["arithmetic", "ecdsa", "pkcs8", ] }
log = { version = "0.4.17", default-features = false }
once_cell = { version = "1.18.0", default-features = false, features = ["alloc", "race", "std"] }
revm = { git = "https://github.com/Wodann/revm", rev = "f57e3e6", version = "14.0", default-features = false, features = ["c-kzg", "dev", "serde"] }
revm-primitives = { git = "https://github.com/Wodann/revm", rev = "f57e3e6", version = "9.0", default-features = false, features = ["c-kzg", "hashbrown"] }
revm = { git = "https://github.com/Wodann/revm", rev = "dfc2f28f", version = "14.0", default-features = false, features = ["c-kzg", "dev", "serde"] }
revm-primitives = { git = "https://github.com/Wodann/revm", rev = "dfc2f28f", version = "9.0", default-features = false, features = ["c-kzg", "hashbrown", "rand"] }
serde = { version = "1.0.209", default-features = false, features = ["derive"], optional = true }
sha2 = { version = "0.10.8", default-features = false }
sha3 = { version = "0.10.8", default-features = false }
Expand All @@ -41,7 +41,6 @@ tokio = { version = "1.23.0", features = ["macros"] }

[features]
default = ["std"]
rand = ["revm-primitives/rand"]
serde = ["dep:serde", "c-kzg/serde", "revm/serde", "revm-primitives/serde"]
std = ["alloy-eips/std", "hash256-std-hasher/std", "hash-db/std", "hex/std", "itertools/use_std", "k256/std", "k256/precomputed-tables", "revm/std", "revm-primitives/std", "serde?/std", "sha2/std", "sha3/std", "triehash/std"]
test-remote = []
Expand Down
50 changes: 28 additions & 22 deletions crates/edr_eth/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,60 @@ use std::marker::PhantomData;
use alloy_rlp::RlpEncodable;
use revm::Database;
pub use revm_primitives::EvmWiring;
use revm_primitives::{ChainSpec, InvalidTransaction, TransactionValidation};

use crate::{
eips::eip1559::{BaseFeeParams, ConstantBaseFeeParams},
transaction,
};

/// The chain specification for Ethereum Layer 1.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, RlpEncodable)]
pub struct L1ChainSpec<DatabaseT: Database, ExternalContextT> {
phantom: PhantomData<(DatabaseT, ExternalContextT)>,
/// A wrapper around the EVM's wiring.
pub struct Wiring<ChainSpecT: ChainSpec, DatabaseT: Database, ExternalContextT> {
_phantom: PhantomData<(ChainSpecT, DatabaseT, ExternalContextT)>,
}

impl<DatabaseT: Database, ExternalContextT> EvmWiring for L1ChainSpec<DatabaseT, ExternalContextT> {
impl<ChainSpecT: ChainSpec, DatabaseT: Database, ExternalContextT> EvmWiring
for Wiring<ChainSpecT, DatabaseT, ExternalContextT>
{
type ChainSpec = ChainSpecT;
type ExternalContext = ExternalContextT;

type ChainContext = ();

type Database = DatabaseT;

type Block = revm_primitives::BlockEnv;

type Hardfork = revm_primitives::SpecId;

type HaltReason = revm_primitives::HaltReason;

type Transaction = transaction::Signed;
}

impl<DatabaseT: Database, ExternalContextT> revm::EvmWiring
for L1ChainSpec<DatabaseT, ExternalContextT>
impl<ChainSpecT, DatabaseT, ExternalContextT> revm::EvmWiring
for Wiring<ChainSpecT, DatabaseT, ExternalContextT>
where
ChainSpecT:
ChainSpec<Transaction: TransactionValidation<ValidationError: From<InvalidTransaction>>>,
DatabaseT: Database,
{
fn handler<'evm>(hardfork: Self::Hardfork) -> revm::EvmHandler<'evm, Self> {
revm::EvmHandler::mainnet_with_spec(hardfork)
}
}

/// The chain specification for Ethereum Layer 1.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, RlpEncodable)]
pub struct L1ChainSpec;

impl ChainSpec for L1ChainSpec {
type ChainContext = ();
type Block = revm_primitives::BlockEnv;
type Transaction = transaction::Signed;
type Hardfork = revm_primitives::SpecId;
type HaltReason = revm_primitives::HaltReason;
}

/// Constants for constructing Ethereum headers.
pub trait EthHeaderConstants: revm_primitives::EvmWiring<Hardfork: 'static + PartialOrd> {
pub trait EthHeaderConstants: ChainSpec<Hardfork: 'static + PartialOrd> {
/// Parameters for the EIP-1559 base fee calculation.
const BASE_FEE_PARAMS: BaseFeeParams<Self::Hardfork>;

/// The minimum difficulty for the Ethash proof-of-work algorithm.
const MIN_ETHASH_DIFFICULTY: u64;
}

impl<DatabaseT: Database, ExternalContextT> EthHeaderConstants
for L1ChainSpec<DatabaseT, ExternalContextT>
{
impl EthHeaderConstants for L1ChainSpec {
const BASE_FEE_PARAMS: BaseFeeParams<Self::Hardfork> =
BaseFeeParams::Constant(ConstantBaseFeeParams::ethereum());

Expand Down
6 changes: 2 additions & 4 deletions crates/edr_eth/tests/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ mod remote {
async fn [<remote_block_receipt_root_ $name>]() -> anyhow::Result<()> {
use edr_eth::{
chain_spec::L1ChainSpec,
db::EmptyDB,
eips::eip2718::TypedEnvelope,
log::FilterLog,
receipt,
Expand All @@ -23,7 +22,7 @@ mod remote {
use edr_rpc_eth::{client::EthRpcClient};
use edr_test_utils::env::get_alchemy_url;

let client = EthRpcClient::<L1ChainSpec<EmptyDB, ()>>::new(&get_alchemy_url(), edr_defaults::CACHE_DIR.into(), None)?;
let client = EthRpcClient::<L1ChainSpec>::new(&get_alchemy_url(), edr_defaults::CACHE_DIR.into(), None)?;

let block = client
.get_block_by_number_with_transaction_data(PreEip1898BlockSpec::Number($block_number))
Expand Down Expand Up @@ -71,7 +70,6 @@ mod remote {
use alloy_rlp::Decodable as _;
use edr_eth::{
chain_spec::L1ChainSpec,
db::EmptyDB,
eips::eip2718::TypedEnvelope,
log::{ExecutionLog, FilterLog},
receipt::{self, MapReceiptLogs as _},
Expand All @@ -82,7 +80,7 @@ mod remote {
use tempfile::TempDir;

let tempdir = TempDir::new().unwrap();
let client = EthRpcClient::<L1ChainSpec<EmptyDB, ()>>::new(&get_alchemy_url(), tempdir.path().into(), None).unwrap();
let client = EthRpcClient::<L1ChainSpec>::new(&get_alchemy_url(), tempdir.path().into(), None).unwrap();

let transaction_hash = B256::from_slice(&hex::decode($transaction_hash).unwrap());

Expand Down
4 changes: 2 additions & 2 deletions crates/edr_evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ log = { version = "0.4.17", default-features = false }
once_cell = { version = "1.18.0", default-features = false, features = ["alloc", "race", "std"] }
parking_lot = { version = "0.12.1", default-features = false }
edr_defaults = { version = "0.3.5", path = "../edr_defaults" }
edr_eth = { version = "0.3.5", path = "../edr_eth", features = ["rand", "serde"] }
edr_eth = { version = "0.3.5", path = "../edr_eth", features = ["serde"] }
edr_rpc_eth = { version = "0.3.5", path = "../edr_rpc_eth" }
revm = { git = "https://github.com/Wodann/revm", rev = "f57e3e6", version = "14.0", default-features = false, features = ["c-kzg", "dev", "serde", "std"] }
revm = { git = "https://github.com/Wodann/revm", rev = "dfc2f28f", version = "14.0", default-features = false, features = ["c-kzg", "dev", "serde", "std"] }
rpds = { version = "1.1.0", default-features = false, features = ["std"] }
serde = { version = "1.0.209", default-features = false, features = ["std"] }
serde_json = { version = "1.0.127", default-features = false, features = ["std"] }
Expand Down
67 changes: 36 additions & 31 deletions crates/edr_evm/src/block/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use std::{

use edr_eth::{
block::{BlobGas, BlockOptions, PartialHeader},
chain_spec::Wiring,
env::{CfgEnv, Env},
log::ExecutionLog,
receipt::{ExecutionReceiptBuilder as _, Receipt as _, TransactionReceipt},
result::InvalidTransaction,
Expand All @@ -14,8 +16,7 @@ use edr_eth::{
Address, Bloom, U256,
};
use revm::{
db::{DatabaseComponents, StateRef},
handler::{CfgEnvWithEvmWiring, EnvWithEvmWiring},
db::{DatabaseComponents, StateRef, WrapDatabaseRef},
primitives::{
ExecutionResult, ResultAndState, SpecId, Transaction as _, TransactionValidation,
MAX_BLOB_GAS_PER_BLOCK,
Expand Down Expand Up @@ -48,7 +49,7 @@ where
#[derive(Debug, thiserror::Error)]
pub enum BlockTransactionError<ChainSpecT, BlockchainErrorT, StateErrorT>
where
ChainSpecT: revm::primitives::EvmWiring,
ChainSpecT: revm::primitives::ChainSpec,
{
/// Transaction has higher gas limit than is remaining in block
#[error("Transaction has a higher gas limit than the remaining gas in the block")]
Expand All @@ -65,17 +66,15 @@ where
/// was executed.
pub struct ExecutionResultWithContext<
'evm,
ChainSpecT,
ChainSpecT: ChainSpec<Transaction: TransactionValidation<ValidationError: From<InvalidTransaction>>>,
BlockchainErrorT,
StateErrorT,
DebugDataT,
StateT: StateRef,
> where
ChainSpecT: revm::EvmWiring,
{
> {
/// The result of executing the transaction.
pub result: Result<
ExecutionResult<ChainSpecT>,
ExecutionResult<ChainSpecT::HaltReason>,
BlockTransactionError<ChainSpecT, BlockchainErrorT, StateErrorT>,
>,
/// The context in which the transaction was executed.
Expand All @@ -92,7 +91,8 @@ pub struct BuildBlockResult<ChainSpecT: ChainSpec> {

/// A builder for constructing Ethereum blocks.
pub struct BlockBuilder<ChainSpecT: ChainSpec> {
cfg: CfgEnvWithEvmWiring<ChainSpecT>,
cfg: CfgEnv,
hardfork: ChainSpecT::Hardfork,
header: PartialHeader,
transactions: Vec<ChainSpecT::Transaction>,
state_diff: StateDiff,
Expand All @@ -108,12 +108,14 @@ where
/// Creates an intance of [`BlockBuilder`].
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
pub fn new<BlockchainErrorT>(
cfg: CfgEnvWithEvmWiring<ChainSpecT>,
cfg: CfgEnv,
hardfork: ChainSpecT::Hardfork,
parent: &dyn SyncBlock<ChainSpecT, Error = BlockchainErrorT>,
mut options: BlockOptions,
) -> Result<Self, BlockBuilderCreationError<ChainSpecT>> {
if cfg.spec_id.into() < SpecId::BYZANTIUM {
return Err(BlockBuilderCreationError::UnsupportedHardfork(cfg.spec_id));
let evm_spec_id = hardfork.into();
if evm_spec_id < SpecId::BYZANTIUM {
return Err(BlockBuilderCreationError::UnsupportedHardfork(hardfork));
}

let parent_header = parent.header();
Expand All @@ -124,18 +126,19 @@ where
};

let withdrawals = std::mem::take(&mut options.withdrawals).or_else(|| {
if cfg.spec_id.into() >= SpecId::SHANGHAI {
if evm_spec_id >= SpecId::SHANGHAI {
Some(Vec::new())
} else {
None
}
});

options.parent_hash = Some(*parent.hash());
let header = PartialHeader::new::<ChainSpecT>(cfg.spec_id, options, Some(parent_header));
let header = PartialHeader::new::<ChainSpecT>(hardfork, options, Some(parent_header));

Ok(Self {
cfg,
hardfork,
header,
transactions: Vec::new(),
state_diff: StateDiff::default(),
Expand All @@ -148,10 +151,15 @@ where

impl<ChainSpecT: ChainSpec> BlockBuilder<ChainSpecT> {
/// Retrieves the config of the block builder.
pub fn config(&self) -> &CfgEnvWithEvmWiring<ChainSpecT> {
pub fn config(&self) -> &CfgEnv {
&self.cfg
}

/// Retrieves the hardfork of the block builder.
pub fn hardfork(&self) -> ChainSpecT::Hardfork {
self.hardfork
}

/// Retrieves the amount of gas used in the block, so far.
pub fn gas_used(&self) -> u64 {
self.header.gas_used
Expand Down Expand Up @@ -296,8 +304,7 @@ where
}
}

let spec_id = self.cfg.spec_id;
let block = ChainSpecT::Block::new_block_env(&self.header, spec_id);
let block = ChainSpecT::Block::new_block_env(&self.header, self.hardfork);

let receipt_builder = {
let builder = ChainSpecT::ReceiptBuilder::new_receipt_builder(&state, &transaction);
Expand All @@ -316,12 +323,11 @@ where
}
};

let env = EnvWithEvmWiring::new_with_cfg_env(self.cfg.clone(), block, transaction.clone());

let db = DatabaseComponents {
let env = Env::boxed(self.cfg.clone(), block, transaction.clone());
let db = WrapDatabaseRef(DatabaseComponents {
state,
block_hash: blockchain,
};
});

let (
mut evm_context,
Expand All @@ -331,11 +337,10 @@ where
},
) = {
if let Some(debug_context) = debug_context {
let mut evm = Evm::builder()
.with_chain_spec::<ChainSpecT>()
.with_ref_db(db)
let mut evm = Evm::<Wiring<ChainSpecT, _, _>>::builder()
.with_db(db)
.with_external_context(debug_context.data)
.with_env_with_handler_cfg(env)
.with_env(env)
.append_handler_register(debug_context.register_handles_fn)
.build();

Expand Down Expand Up @@ -367,10 +372,9 @@ where
}
}
} else {
let mut evm = Evm::builder()
.with_chain_spec::<ChainSpecT>()
.with_ref_db(db)
.with_env_with_handler_cfg(env)
let mut evm = Evm::<Wiring<ChainSpecT, _, ()>>::builder()
.with_db(db)
.with_env(env)
.build();

let result = evm.transact();
Expand Down Expand Up @@ -412,14 +416,15 @@ where
*gas_used += blob_gas_used;
}

let receipt = receipt_builder.build_receipt(&self.header, &transaction, &result, spec_id);
let receipt =
receipt_builder.build_receipt(&self.header, &transaction, &result, self.hardfork);
let receipt = TransactionReceipt::new(
receipt,
&transaction,
&result,
self.transactions.len() as u64,
self.header.base_fee.unwrap_or(U256::ZERO),
spec_id,
self.hardfork,
);
self.receipts.push(receipt);

Expand Down
Loading

0 comments on commit 00ab711

Please sign in to comment.