From 31b281906637ddc867eeabaa0ab23494228d9dc1 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Tue, 18 Feb 2025 15:56:49 +0100 Subject: [PATCH 01/21] fix: add clear tx l1 cost back (#14564) --- crates/optimism/rpc/src/eth/block.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/optimism/rpc/src/eth/block.rs b/crates/optimism/rpc/src/eth/block.rs index 83a9ce7f2bde..72ddfa0dfdf5 100644 --- a/crates/optimism/rpc/src/eth/block.rs +++ b/crates/optimism/rpc/src/eth/block.rs @@ -59,6 +59,11 @@ where timestamp, }; + // We must clear this cache as different L2 transactions can have different + // L1 costs. A potential improvement here is to only clear the cache if the + // new transaction input has changed, since otherwise the L1 cost wouldn't. + l1_block_info.clear_tx_l1_cost(); + Ok(OpReceiptBuilder::new( &self.inner.eth_api.provider().chain_spec(), tx, From c0a30f051e3a6fb3ccc56d87959a29cf77657e80 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Tue, 18 Feb 2025 16:29:59 +0100 Subject: [PATCH 02/21] feat(op): isthmus genesis header (#14560) Co-authored-by: Matthias Seitz --- Cargo.lock | 1 + crates/optimism/chainspec/Cargo.toml | 2 ++ crates/optimism/chainspec/src/base.rs | 6 ++-- crates/optimism/chainspec/src/base_sepolia.rs | 6 ++-- crates/optimism/chainspec/src/dev.rs | 6 ++-- crates/optimism/chainspec/src/lib.rs | 29 ++++++++++++++++++- crates/optimism/chainspec/src/op.rs | 6 ++-- crates/optimism/chainspec/src/op_sepolia.rs | 6 ++-- 8 files changed, 46 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2cdaedf5659a..062c7b4bd9b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8456,6 +8456,7 @@ dependencies = [ "reth-ethereum-forks", "reth-network-peers", "reth-optimism-forks", + "reth-optimism-primitives", "reth-primitives-traits", "serde_json", "thiserror 2.0.11", diff --git a/crates/optimism/chainspec/Cargo.toml b/crates/optimism/chainspec/Cargo.toml index 404402a6cb9b..b2c48bf36f3d 100644 --- a/crates/optimism/chainspec/Cargo.toml +++ b/crates/optimism/chainspec/Cargo.toml @@ -20,6 +20,7 @@ reth-network-peers.workspace = true # op-reth reth-optimism-forks.workspace = true +reth-optimism-primitives.workspace = true # ethereum alloy-chains.workspace = true @@ -57,6 +58,7 @@ std = [ "reth-ethereum-forks/std", "reth-primitives-traits/std", "reth-optimism-forks/std", + "reth-optimism-primitives/std", "alloy-consensus/std", "once_cell/std", "derive_more/std", diff --git a/crates/optimism/chainspec/src/base.rs b/crates/optimism/chainspec/src/base.rs index a6d302b507f5..4965e499f5e9 100644 --- a/crates/optimism/chainspec/src/base.rs +++ b/crates/optimism/chainspec/src/base.rs @@ -4,12 +4,12 @@ use alloc::{sync::Arc, vec}; use alloy_chains::Chain; use alloy_primitives::{b256, U256}; -use reth_chainspec::{make_genesis_header, BaseFeeParams, BaseFeeParamsKind, ChainSpec}; +use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec}; use reth_ethereum_forks::{EthereumHardfork, Hardfork}; use reth_optimism_forks::OpHardfork; use reth_primitives_traits::SealedHeader; -use crate::{LazyLock, OpChainSpec}; +use crate::{make_op_genesis_header, LazyLock, OpChainSpec}; /// The Base mainnet spec pub static BASE_MAINNET: LazyLock> = LazyLock::new(|| { @@ -20,7 +20,7 @@ pub static BASE_MAINNET: LazyLock> = LazyLock::new(|| { inner: ChainSpec { chain: Chain::base_mainnet(), genesis_header: SealedHeader::new( - make_genesis_header(&genesis, &hardforks), + make_op_genesis_header(&genesis, &hardforks), b256!("f712aa9241cc24369b143cf6dce85f0902a9731e70d66818a3a5845b296c73dd"), ), genesis, diff --git a/crates/optimism/chainspec/src/base_sepolia.rs b/crates/optimism/chainspec/src/base_sepolia.rs index ef412f10946f..bfec355a63d7 100644 --- a/crates/optimism/chainspec/src/base_sepolia.rs +++ b/crates/optimism/chainspec/src/base_sepolia.rs @@ -4,12 +4,12 @@ use alloc::{sync::Arc, vec}; use alloy_chains::Chain; use alloy_primitives::{b256, U256}; -use reth_chainspec::{make_genesis_header, BaseFeeParams, BaseFeeParamsKind, ChainSpec, Hardfork}; +use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec, Hardfork}; use reth_ethereum_forks::EthereumHardfork; use reth_optimism_forks::OpHardfork; use reth_primitives_traits::SealedHeader; -use crate::{LazyLock, OpChainSpec}; +use crate::{make_op_genesis_header, LazyLock, OpChainSpec}; /// The Base Sepolia spec pub static BASE_SEPOLIA: LazyLock> = LazyLock::new(|| { @@ -20,7 +20,7 @@ pub static BASE_SEPOLIA: LazyLock> = LazyLock::new(|| { inner: ChainSpec { chain: Chain::base_sepolia(), genesis_header: SealedHeader::new( - make_genesis_header(&genesis, &hardforks), + make_op_genesis_header(&genesis, &hardforks), b256!("0dcc9e089e30b90ddfc55be9a37dd15bc551aeee999d2e2b51414c54eaf934e4"), ), genesis, diff --git a/crates/optimism/chainspec/src/dev.rs b/crates/optimism/chainspec/src/dev.rs index f7614a8bc06c..57d84ce0b0b0 100644 --- a/crates/optimism/chainspec/src/dev.rs +++ b/crates/optimism/chainspec/src/dev.rs @@ -5,11 +5,11 @@ use alloc::sync::Arc; use alloy_chains::Chain; use alloy_consensus::constants::DEV_GENESIS_HASH; use alloy_primitives::U256; -use reth_chainspec::{make_genesis_header, BaseFeeParams, BaseFeeParamsKind, ChainSpec}; +use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec}; use reth_optimism_forks::DEV_HARDFORKS; use reth_primitives_traits::SealedHeader; -use crate::{LazyLock, OpChainSpec}; +use crate::{make_op_genesis_header, LazyLock, OpChainSpec}; /// OP dev testnet specification /// @@ -23,7 +23,7 @@ pub static OP_DEV: LazyLock> = LazyLock::new(|| { inner: ChainSpec { chain: Chain::dev(), genesis_header: SealedHeader::new( - make_genesis_header(&genesis, &hardforks), + make_op_genesis_header(&genesis, &hardforks), DEV_GENESIS_HASH, ), genesis, diff --git a/crates/optimism/chainspec/src/lib.rs b/crates/optimism/chainspec/src/lib.rs index 8f54193a2e64..e90d621d8afd 100644 --- a/crates/optimism/chainspec/src/lib.rs +++ b/crates/optimism/chainspec/src/lib.rs @@ -19,7 +19,7 @@ mod op_sepolia; use alloc::{boxed::Box, vec, vec::Vec}; use alloy_chains::Chain; -use alloy_consensus::Header; +use alloy_consensus::{proofs::storage_root_unhashed, Header}; use alloy_eips::eip7840::BlobParams; use alloy_genesis::Genesis; use alloy_primitives::{B256, U256}; @@ -36,6 +36,7 @@ use reth_chainspec::{ use reth_ethereum_forks::{ChainHardforks, EthereumHardfork, ForkCondition, Hardfork}; use reth_network_peers::NodeRecord; use reth_optimism_forks::{OpHardfork, OpHardforks}; +use reth_optimism_primitives::ADDRESS_L2_TO_L1_MESSAGE_PASSER; use reth_primitives_traits::{sync::LazyLock, SealedHeader}; /// Chain spec builder for a OP stack chain. @@ -421,6 +422,32 @@ impl OpGenesisInfo { } } +/// Helper method building a [`Header`] given [`Genesis`] and [`ChainHardforks`]. +pub fn make_op_genesis_header(genesis: &Genesis, hardforks: &ChainHardforks) -> Header { + let mut header = reth_chainspec::make_genesis_header(genesis, hardforks); + + // If Isthmus is active, overwrite the withdrawals root with the storage root of predeploy + // `L2ToL1MessagePasser.sol` + if hardforks.fork(OpHardfork::Isthmus).active_at_timestamp(header.timestamp) { + match genesis.alloc.get(&ADDRESS_L2_TO_L1_MESSAGE_PASSER) { + Some(predeploy) => { + if let Some(ref storage) = predeploy.storage { + header.withdrawals_root = + Some(storage_root_unhashed(storage.iter().map(|(k, v)| (*k, (*v).into())))) + } + } + None => + // todo: log this when no_std tracing available + /*debug!(target: "reth::cli", + "Isthmus active but predeploy L2ToL1MessagePasser.sol not found in genesis alloc" + ),*/ + {} + } + } + + header +} + #[cfg(test)] mod tests { use alloy_genesis::{ChainConfig, Genesis}; diff --git a/crates/optimism/chainspec/src/op.rs b/crates/optimism/chainspec/src/op.rs index 2d6777d277f0..dddd26dfb29d 100644 --- a/crates/optimism/chainspec/src/op.rs +++ b/crates/optimism/chainspec/src/op.rs @@ -1,10 +1,10 @@ //! Chain specification for the Optimism Mainnet network. -use crate::{LazyLock, OpChainSpec}; +use crate::{make_op_genesis_header, LazyLock, OpChainSpec}; use alloc::{sync::Arc, vec}; use alloy_chains::Chain; use alloy_primitives::{b256, U256}; -use reth_chainspec::{make_genesis_header, BaseFeeParams, BaseFeeParamsKind, ChainSpec, Hardfork}; +use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec, Hardfork}; use reth_ethereum_forks::EthereumHardfork; use reth_optimism_forks::OpHardfork; use reth_primitives_traits::SealedHeader; @@ -20,7 +20,7 @@ pub static OP_MAINNET: LazyLock> = LazyLock::new(|| { inner: ChainSpec { chain: Chain::optimism_mainnet(), genesis_header: SealedHeader::new( - make_genesis_header(&genesis, &hardforks), + make_op_genesis_header(&genesis, &hardforks), b256!("7ca38a1916c42007829c55e69d3e9a73265554b586a499015373241b8a3fa48b"), ), genesis, diff --git a/crates/optimism/chainspec/src/op_sepolia.rs b/crates/optimism/chainspec/src/op_sepolia.rs index 2c963d360e66..3ed22db6457f 100644 --- a/crates/optimism/chainspec/src/op_sepolia.rs +++ b/crates/optimism/chainspec/src/op_sepolia.rs @@ -1,10 +1,10 @@ //! Chain specification for the Optimism Sepolia testnet network. -use crate::{LazyLock, OpChainSpec}; +use crate::{make_op_genesis_header, LazyLock, OpChainSpec}; use alloc::{sync::Arc, vec}; use alloy_chains::{Chain, NamedChain}; use alloy_primitives::{b256, U256}; -use reth_chainspec::{make_genesis_header, BaseFeeParams, BaseFeeParamsKind, ChainSpec, Hardfork}; +use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec, Hardfork}; use reth_ethereum_forks::EthereumHardfork; use reth_optimism_forks::OpHardfork; use reth_primitives_traits::SealedHeader; @@ -18,7 +18,7 @@ pub static OP_SEPOLIA: LazyLock> = LazyLock::new(|| { inner: ChainSpec { chain: Chain::from_named(NamedChain::OptimismSepolia), genesis_header: SealedHeader::new( - make_genesis_header(&genesis, &hardforks), + make_op_genesis_header(&genesis, &hardforks), b256!("102de6ffb001480cc9b8b548fd05c34cd4f46ae4aa91759393db90ea0409887d"), ), genesis, From 3485ce45be8e90c04b8d42d172f0d899ef62cb1d Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 18 Feb 2025 16:36:57 +0100 Subject: [PATCH 03/21] chore(chainspec): remove `MAINNET` usage from `ChainSpec::default` (#14565) --- crates/chainspec/src/constants.rs | 4 ++++ crates/chainspec/src/lib.rs | 4 ++-- crates/chainspec/src/spec.rs | 7 +++++-- crates/prune/prune/src/builder.rs | 4 ++-- crates/prune/types/src/lib.rs | 3 ++- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/crates/chainspec/src/constants.rs b/crates/chainspec/src/constants.rs index 3f46fb6b746a..946a9681ba1a 100644 --- a/crates/chainspec/src/constants.rs +++ b/crates/chainspec/src/constants.rs @@ -4,6 +4,10 @@ use alloy_primitives::b256; /// Gas per transaction not creating a contract. pub const MIN_TRANSACTION_GAS: u64 = 21_000u64; + +/// Mainnet prune delete limit. +pub const MAINNET_PRUNE_DELETE_LIMIT: usize = 20000; + /// Deposit contract address: `0x00000000219ab540356cbb839cbe05303d7705fa` pub(crate) const MAINNET_DEPOSIT_CONTRACT: DepositContract = DepositContract::new( MAINNET_DEPOSIT_CONTRACT_ADDRESS, diff --git a/crates/chainspec/src/lib.rs b/crates/chainspec/src/lib.rs index aa70706debbf..3989b5983660 100644 --- a/crates/chainspec/src/lib.rs +++ b/crates/chainspec/src/lib.rs @@ -12,8 +12,8 @@ extern crate alloc; /// Chain specific constants -pub(crate) mod constants; -pub use constants::MIN_TRANSACTION_GAS; +mod constants; +pub use constants::*; mod api; /// The chain info module. diff --git a/crates/chainspec/src/spec.rs b/crates/chainspec/src/spec.rs index 7223d93b2309..496a171e5265 100644 --- a/crates/chainspec/src/spec.rs +++ b/crates/chainspec/src/spec.rs @@ -1,6 +1,9 @@ pub use alloy_eips::eip1559::BaseFeeParams; -use crate::{constants::MAINNET_DEPOSIT_CONTRACT, EthChainSpec}; +use crate::{ + constants::{MAINNET_DEPOSIT_CONTRACT, MAINNET_PRUNE_DELETE_LIMIT}, + EthChainSpec, +}; use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, vec::Vec}; use alloy_chains::{Chain, NamedChain}; use alloy_consensus::{ @@ -320,7 +323,7 @@ impl Default for ChainSpec { hardforks: Default::default(), deposit_contract: Default::default(), base_fee_params: BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()), - prune_delete_limit: MAINNET.prune_delete_limit, + prune_delete_limit: MAINNET_PRUNE_DELETE_LIMIT, blob_params: Default::default(), } } diff --git a/crates/prune/prune/src/builder.rs b/crates/prune/prune/src/builder.rs index 26992e78e168..f5bb95df3f52 100644 --- a/crates/prune/prune/src/builder.rs +++ b/crates/prune/prune/src/builder.rs @@ -1,6 +1,6 @@ use crate::{segments::SegmentSet, Pruner}; use alloy_eips::eip2718::Encodable2718; -use reth_chainspec::MAINNET; +use reth_chainspec::MAINNET_PRUNE_DELETE_LIMIT; use reth_config::PruneConfig; use reth_db_api::{table::Value, transaction::DbTxMut}; use reth_exex_types::FinishedExExHeight; @@ -129,7 +129,7 @@ impl Default for PrunerBuilder { Self { block_interval: 5, segments: PruneModes::none(), - delete_limit: MAINNET.prune_delete_limit, + delete_limit: MAINNET_PRUNE_DELETE_LIMIT, timeout: None, finished_exex_height: watch::channel(FinishedExExHeight::NoExExs).1, } diff --git a/crates/prune/types/src/lib.rs b/crates/prune/types/src/lib.rs index 1aedce38fcef..ef8ef882b8cb 100644 --- a/crates/prune/types/src/lib.rs +++ b/crates/prune/types/src/lib.rs @@ -20,8 +20,9 @@ mod target; use alloc::{collections::BTreeMap, vec::Vec}; use alloy_primitives::{Address, BlockNumber}; -pub use checkpoint::PruneCheckpoint; use core::ops::Deref; + +pub use checkpoint::PruneCheckpoint; pub use event::PrunerEvent; pub use mode::PruneMode; pub use pruner::{ From 545d5bdf1620a7c68aa5883af453f35adc6b1e50 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 18 Feb 2025 17:24:55 +0100 Subject: [PATCH 04/21] chore(chainspec): use `MAINNET_PRUNE_DELETE_LIMIT` in `MAINNET` (#14569) --- crates/chainspec/src/spec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/chainspec/src/spec.rs b/crates/chainspec/src/spec.rs index 496a171e5265..eba0bb421f16 100644 --- a/crates/chainspec/src/spec.rs +++ b/crates/chainspec/src/spec.rs @@ -109,7 +109,7 @@ pub static MAINNET: LazyLock> = LazyLock::new(|| { b256!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5"), )), base_fee_params: BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()), - prune_delete_limit: 20000, + prune_delete_limit: MAINNET_PRUNE_DELETE_LIMIT, blob_params: HardforkBlobParams::default(), }; spec.genesis.config.dao_fork_support = true; From 534b028203b47b996895c6c39d48f6ffbf0fb5c0 Mon Sep 17 00:00:00 2001 From: cakevm Date: Tue, 18 Feb 2025 19:42:15 +0100 Subject: [PATCH 05/21] chore: make return for debug_codeByHash optional (#14572) --- crates/rpc/rpc-api/src/debug.rs | 6 +++++- crates/rpc/rpc/src/debug.rs | 15 +++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/crates/rpc/rpc-api/src/debug.rs b/crates/rpc/rpc-api/src/debug.rs index 427bcfc7515a..c3246c333b4a 100644 --- a/crates/rpc/rpc-api/src/debug.rs +++ b/crates/rpc/rpc-api/src/debug.rs @@ -198,7 +198,11 @@ pub trait DebugApi { /// Returns the code associated with a given hash at the specified block ID. /// If no block ID is provided, it defaults to the latest block. #[method(name = "codeByHash")] - async fn debug_code_by_hash(&self, hash: B256, block_id: Option) -> RpcResult; + async fn debug_code_by_hash( + &self, + hash: B256, + block_id: Option, + ) -> RpcResult>; /// Turns on CPU profiling for the given duration and writes profile data to disk. #[method(name = "cpuProfile")] diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index d15d16033e06..cdae15763d3f 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -654,21 +654,20 @@ where .await } - /// Returns the code associated with a given hash at the specified block ID. - /// If no block ID is provided, it defaults to the latest block. + /// Returns the code associated with a given hash at the specified block ID. If no code is + /// found, it returns None. If no block ID is provided, it defaults to the latest block. pub async fn debug_code_by_hash( &self, hash: B256, block_id: Option, - ) -> Result { + ) -> Result, Eth::Error> { Ok(self .provider() .state_by_block_id(block_id.unwrap_or_default()) .map_err(Eth::Error::from_eth_err)? .bytecode_by_hash(&hash) .map_err(Eth::Error::from_eth_err)? - .unwrap_or_default() - .original_bytes()) + .map(|b| b.original_bytes())) } /// Executes the configured transaction with the environment on the given database. @@ -1051,7 +1050,11 @@ where Ok(()) } - async fn debug_code_by_hash(&self, hash: B256, block_id: Option) -> RpcResult { + async fn debug_code_by_hash( + &self, + hash: B256, + block_id: Option, + ) -> RpcResult> { Self::debug_code_by_hash(self, hash, block_id).await.map_err(Into::into) } From 3570f6b2f37201979b3161487cd4fe592cebe690 Mon Sep 17 00:00:00 2001 From: Federico Gimenez Date: Tue, 18 Feb 2025 21:53:10 +0100 Subject: [PATCH 06/21] feat(reth-bench): substract block fetch waiting time from benchmark duration (#14299) --- bin/reth-bench/src/bench/new_payload_fcu.rs | 17 ++++++++++++----- bin/reth-bench/src/bench/new_payload_only.rs | 17 ++++++++++++----- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/bin/reth-bench/src/bench/new_payload_fcu.rs b/bin/reth-bench/src/bench/new_payload_fcu.rs index 37f8aae01f72..36b726289cf9 100644 --- a/bin/reth-bench/src/bench/new_payload_fcu.rs +++ b/bin/reth-bench/src/bench/new_payload_fcu.rs @@ -20,7 +20,7 @@ use reth_cli_runner::CliContext; use reth_node_core::args::BenchmarkArgs; use reth_primitives::SealedBlock; use reth_primitives_traits::SealedHeader; -use std::time::Instant; +use std::time::{Duration, Instant}; use tracing::{debug, info}; /// `reth benchmark new-payload-fcu` command @@ -71,8 +71,14 @@ impl Command { // put results in a summary vec so they can be printed at the end let mut results = Vec::new(); let total_benchmark_duration = Instant::now(); - - while let Some((block, head, safe, finalized)) = receiver.recv().await { + let mut total_wait_time = Duration::ZERO; + + while let Some((block, head, safe, finalized)) = { + let wait_start = Instant::now(); + let result = receiver.recv().await; + total_wait_time += wait_start.elapsed(); + result + } { // just put gas used here let gas_used = block.gas_used; let block_number = block.number; @@ -112,8 +118,9 @@ impl Command { let combined_result = CombinedResult { block_number, new_payload_result, fcu_latency, total_latency }; - // current duration since the start of the benchmark - let current_duration = total_benchmark_duration.elapsed(); + // current duration since the start of the benchmark minus the time + // waiting for blocks + let current_duration = total_benchmark_duration.elapsed() - total_wait_time; // convert gas used to gigagas, then compute gigagas per second info!(%combined_result); diff --git a/bin/reth-bench/src/bench/new_payload_only.rs b/bin/reth-bench/src/bench/new_payload_only.rs index 327829442b62..877695f97b1f 100644 --- a/bin/reth-bench/src/bench/new_payload_only.rs +++ b/bin/reth-bench/src/bench/new_payload_only.rs @@ -18,7 +18,7 @@ use clap::Parser; use csv::Writer; use reth_cli_runner::CliContext; use reth_node_core::args::BenchmarkArgs; -use std::time::Instant; +use std::time::{Duration, Instant}; use tracing::{debug, info}; /// `reth benchmark new-payload-only` command @@ -56,8 +56,14 @@ impl Command { // put results in a summary vec so they can be printed at the end let mut results = Vec::new(); let total_benchmark_duration = Instant::now(); - - while let Some(block) = receiver.recv().await { + let mut total_wait_time = Duration::ZERO; + + while let Some(block) = { + let wait_start = Instant::now(); + let result = receiver.recv().await; + total_wait_time += wait_start.elapsed(); + result + } { // just put gas used here let gas_used = block.gas_used; @@ -82,8 +88,9 @@ impl Command { let new_payload_result = NewPayloadResult { gas_used, latency: start.elapsed() }; info!(%new_payload_result); - // current duration since the start of the benchmark - let current_duration = total_benchmark_duration.elapsed(); + // current duration since the start of the benchmark minus the time + // waiting for blocks + let current_duration = total_benchmark_duration.elapsed() - total_wait_time; // record the current result let row = TotalGasRow { block_number, gas_used, time: current_duration }; From cec1c11ece5f6da30215c06a7e3f61c737020f65 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Wed, 19 Feb 2025 02:28:39 +0100 Subject: [PATCH 07/21] chore: handle all revm errors (#14574) --- crates/rpc/rpc-eth-types/src/error/mod.rs | 25 ++++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/crates/rpc/rpc-eth-types/src/error/mod.rs b/crates/rpc/rpc-eth-types/src/error/mod.rs index 1327625fd9ff..da1e34af1a9d 100644 --- a/crates/rpc/rpc-eth-types/src/error/mod.rs +++ b/crates/rpc/rpc-eth-types/src/error/mod.rs @@ -538,6 +538,13 @@ impl From for RpcInvalidTransactionError { // tx.gas < cost Self::GasTooLow } + InvalidTransaction::GasFloorMoreThanGasLimit => { + // Post prague EIP-7623 tx floor calldata gas cost > tx.gas_limit + // where floor gas is the minimum amount of gas that will be spent + // In other words, the tx's gas limit is lower that the minimum gas requirements of + // the tx's calldata + Self::GasTooLow + } InvalidTransaction::RejectCallerWithCode => Self::SenderNoEOA, InvalidTransaction::LackOfFundForMaxFee { fee, balance } => { Self::InsufficientFunds { cost: *fee, balance: *balance } @@ -561,18 +568,12 @@ impl From for RpcInvalidTransactionError { InvalidTransaction::AuthorizationListNotSupported => { Self::AuthorizationListNotSupported } - InvalidTransaction::AuthorizationListInvalidFields => { - Self::AuthorizationListInvalidFields - } - #[allow(unreachable_patterns)] - err => { - error!(target: "rpc", - ?err, - "unexpected transaction error" - ); - - Self::other(internal_rpc_err(format!("unexpected transaction error: {err}"))) - } + InvalidTransaction::AuthorizationListInvalidFields | + InvalidTransaction::EmptyAuthorizationList => Self::AuthorizationListInvalidFields, + InvalidTransaction::Eip2930NotSupported | + InvalidTransaction::Eip1559NotSupported | + InvalidTransaction::Eip4844NotSupported | + InvalidTransaction::Eip7702NotSupported => Self::TxTypeNotSupported, } } } From dde5269b7eabb05747508f78cdb1f3983d75b93d Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Wed, 19 Feb 2025 13:08:43 +0400 Subject: [PATCH 08/21] chore: bump revm (#14568) --- Cargo.lock | 36 ++++++++++++++++++------------------ Cargo.toml | 34 +++++++++++++++++----------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 062c7b4bd9b4..5226079a39e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -261,7 +261,7 @@ dependencies = [ [[package]] name = "alloy-evm" version = "0.1.0" -source = "git+https://github.com/alloy-rs/evm?rev=bcb0ebe#bcb0ebed25d8b7a0184b78543144eda21b8b98c7" +source = "git+https://github.com/alloy-rs/evm?rev=b77a39a#b77a39aa954a95b1c0385905b7d39c9d096b0a1b" dependencies = [ "alloy-primitives", "revm", @@ -368,7 +368,7 @@ dependencies = [ [[package]] name = "alloy-op-evm" version = "0.1.0" -source = "git+https://github.com/alloy-rs/evm?rev=bcb0ebe#bcb0ebed25d8b7a0184b78543144eda21b8b98c7" +source = "git+https://github.com/alloy-rs/evm?rev=b77a39a#b77a39aa954a95b1c0385905b7d39c9d096b0a1b" dependencies = [ "alloy-evm", "alloy-primitives", @@ -9819,7 +9819,7 @@ dependencies = [ [[package]] name = "revm" version = "20.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "revm-bytecode", "revm-context", @@ -9838,7 +9838,7 @@ dependencies = [ [[package]] name = "revm-bytecode" version = "1.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "bitvec", "revm-primitives", @@ -9849,7 +9849,7 @@ dependencies = [ [[package]] name = "revm-context" version = "1.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -9869,7 +9869,7 @@ dependencies = [ [[package]] name = "revm-context-interface" version = "1.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -9884,7 +9884,7 @@ dependencies = [ [[package]] name = "revm-database" version = "1.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "auto_impl", "revm-bytecode", @@ -9897,7 +9897,7 @@ dependencies = [ [[package]] name = "revm-database-interface" version = "1.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "auto_impl", "revm-primitives", @@ -9908,13 +9908,13 @@ dependencies = [ [[package]] name = "revm-handler" version = "1.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "auto_impl", "revm-bytecode", "revm-context", "revm-context-interface", - "revm-database", + "revm-database-interface", "revm-interpreter", "revm-precompile", "revm-primitives", @@ -9926,7 +9926,7 @@ dependencies = [ [[package]] name = "revm-inspector" version = "1.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "auto_impl", "revm-context", @@ -9943,7 +9943,7 @@ dependencies = [ [[package]] name = "revm-inspectors" version = "0.15.0" -source = "git+https://github.com/paradigmxyz/revm-inspectors?rev=74b6aa4#74b6aa48107b93a9f661a30bd1d763bbf145e828" +source = "git+https://github.com/paradigmxyz/revm-inspectors?rev=8900c2b#8900c2bf8430e41f1a1cc92dbc1cf0615f00a26b" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -9962,7 +9962,7 @@ dependencies = [ [[package]] name = "revm-interpreter" version = "16.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -9974,7 +9974,7 @@ dependencies = [ [[package]] name = "revm-optimism" version = "1.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "auto_impl", "once_cell", @@ -9987,7 +9987,7 @@ dependencies = [ [[package]] name = "revm-precompile" version = "17.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "aurora-engine-modexp", "blst", @@ -10009,7 +10009,7 @@ dependencies = [ [[package]] name = "revm-primitives" version = "16.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "alloy-primitives", ] @@ -10017,7 +10017,7 @@ dependencies = [ [[package]] name = "revm-specification" version = "1.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "enumn", "revm-primitives", @@ -10027,7 +10027,7 @@ dependencies = [ [[package]] name = "revm-state" version = "1.0.0-alpha.1" -source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +source = "git+https://github.com/bluealloy/revm?rev=a8a9893b#a8a9893b11c480a4f1c2fa8742d8ca60bf3d7ba4" dependencies = [ "bitflags 2.8.0", "revm-bytecode", diff --git a/Cargo.toml b/Cargo.toml index 0e788e3eb3a7..d6230ba9b199 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -623,23 +623,23 @@ snmalloc-rs = { version = "0.3.7", features = ["build_cc"] } crunchy = "=0.2.2" [patch.crates-io] -alloy-evm = { git = "https://github.com/alloy-rs/evm", rev = "bcb0ebe" } -alloy-op-evm = { git = "https://github.com/alloy-rs/evm", rev = "bcb0ebe" } - -revm = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } -revm-bytecode = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } -revm-database = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } -revm-state = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } -revm-primitives = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } -revm-interpreter = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } -revm-inspector = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } -revm-context = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } -revm-context-interface = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } -revm-database-interface = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } -revm-specification = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } -revm-optimism = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } - -revm-inspectors = { git = "https://github.com/paradigmxyz/revm-inspectors", rev = "74b6aa4" } +alloy-evm = { git = "https://github.com/alloy-rs/evm", rev = "b77a39a" } +alloy-op-evm = { git = "https://github.com/alloy-rs/evm", rev = "b77a39a" } + +revm = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } +revm-bytecode = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } +revm-database = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } +revm-state = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } +revm-primitives = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } +revm-interpreter = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } +revm-inspector = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } +revm-context = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } +revm-context-interface = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } +revm-database-interface = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } +revm-specification = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } +revm-optimism = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } + +revm-inspectors = { git = "https://github.com/paradigmxyz/revm-inspectors", rev = "8900c2b" } # alloy-consensus = { git = "https://github.com/alloy-rs/alloy", rev = "cfb13aa" } # alloy-contract = { git = "https://github.com/alloy-rs/alloy", rev = "cfb13aa" } From 974cfa192f935a4754e46e414f96a102e12791a0 Mon Sep 17 00:00:00 2001 From: Federico Gimenez Date: Wed, 19 Feb 2025 10:10:47 +0100 Subject: [PATCH 09/21] chore(hive): rename expected eest failures (#14577) --- .github/assets/hive/expected_failures.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/assets/hive/expected_failures.yaml b/.github/assets/hive/expected_failures.yaml index cc7e5d931526..f74cea63aafd 100644 --- a/.github/assets/hive/expected_failures.yaml +++ b/.github/assets/hive/expected_failures.yaml @@ -52,6 +52,6 @@ sync: [] # no fix: it’s too expensive to check whether the storage is empty on each creation eest/consume-engine: - - tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_non_empty_storage[fork_Prague-blockchain_test_engine-zero_nonce]-blockchain_test_engine-reth + - tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_non_empty_storage[fork_Prague-blockchain_test_engine-zero_nonce]-reth eest/consume-rlp: - - tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_non_empty_storage[fork_Prague-blockchain_test-zero_nonce]-blockchain_test-reth + - tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_non_empty_storage[fork_Prague-blockchain_test-zero_nonce]-reth From 849c04cb34a9ffb99a30ba3d167f530739c67fd3 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Feb 2025 10:25:29 +0100 Subject: [PATCH 10/21] feat(l2-withdrawals): Decompose `ExecutionPayloadValidator::ensure_well_formed_payload` (#14566) --- Cargo.lock | 3 +- crates/payload/validator/Cargo.toml | 3 +- crates/payload/validator/src/cancun.rs | 119 +++++++++++++++++++++++ crates/payload/validator/src/lib.rs | 103 ++++---------------- crates/payload/validator/src/prague.rs | 48 +++++++++ crates/payload/validator/src/shanghai.rs | 23 +++++ 6 files changed, 214 insertions(+), 85 deletions(-) create mode 100644 crates/payload/validator/src/cancun.rs create mode 100644 crates/payload/validator/src/prague.rs create mode 100644 crates/payload/validator/src/shanghai.rs diff --git a/Cargo.lock b/Cargo.lock index 5226079a39e8..8b2f528c890c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8866,7 +8866,8 @@ dependencies = [ name = "reth-payload-validator" version = "1.2.0" dependencies = [ - "alloy-rpc-types", + "alloy-consensus", + "alloy-rpc-types-engine", "reth-chainspec", "reth-primitives", "reth-primitives-traits", diff --git a/crates/payload/validator/Cargo.toml b/crates/payload/validator/Cargo.toml index 5c34a9f456f9..e95300153e6f 100644 --- a/crates/payload/validator/Cargo.toml +++ b/crates/payload/validator/Cargo.toml @@ -18,4 +18,5 @@ reth-primitives.workspace = true reth-primitives-traits.workspace = true # alloy -alloy-rpc-types = { workspace = true, features = ["engine"] } +alloy-rpc-types-engine.workspace = true +alloy-consensus.workspace = true diff --git a/crates/payload/validator/src/cancun.rs b/crates/payload/validator/src/cancun.rs new file mode 100644 index 000000000000..b35573b9dc15 --- /dev/null +++ b/crates/payload/validator/src/cancun.rs @@ -0,0 +1,119 @@ +//! Cancun rules for new payloads. + +use alloy_consensus::{BlockBody, Transaction, Typed2718}; +use alloy_rpc_types_engine::{CancunPayloadFields, PayloadError}; +use reth_primitives_traits::{AlloyBlockHeader, Block, SealedBlock}; + +/// Checks block and sidecar w.r.t new Cancun fields and new transaction type EIP-4844. +/// +/// Checks that: +/// - Cancun fields are present if Cancun is active +/// - contains EIP-4844 transactions if Cancun is active and vv +/// - checks blob versioned hashes in block and sidecar match +#[inline] +pub fn ensure_well_formed_fields( + block: &SealedBlock, + cancun_sidecar_fields: Option<&CancunPayloadFields>, + is_cancun_active: bool, +) -> Result<(), PayloadError> +where + T: Transaction + Typed2718, + B: Block>, +{ + ensure_well_formed_header_and_sidecar_fields(block, cancun_sidecar_fields, is_cancun_active)?; + ensure_well_formed_transactions_field_with_sidecar( + block.body(), + cancun_sidecar_fields, + is_cancun_active, + ) +} + +/// Checks that Cancun fields on block header and sidecar are present if Cancun is active and vv. +#[inline] +pub fn ensure_well_formed_header_and_sidecar_fields( + block: &SealedBlock, + cancun_sidecar_fields: Option<&CancunPayloadFields>, + is_cancun_active: bool, +) -> Result<(), PayloadError> { + if is_cancun_active { + if block.blob_gas_used().is_none() { + // cancun active but blob gas used not present + return Err(PayloadError::PostCancunBlockWithoutBlobGasUsed) + } + if block.excess_blob_gas().is_none() { + // cancun active but excess blob gas not present + return Err(PayloadError::PostCancunBlockWithoutExcessBlobGas) + } + if cancun_sidecar_fields.is_none() { + // cancun active but cancun fields not present + return Err(PayloadError::PostCancunWithoutCancunFields) + } + } else { + if block.blob_gas_used().is_some() { + // cancun not active but blob gas used present + return Err(PayloadError::PreCancunBlockWithBlobGasUsed) + } + if block.excess_blob_gas().is_some() { + // cancun not active but excess blob gas present + return Err(PayloadError::PreCancunBlockWithExcessBlobGas) + } + if cancun_sidecar_fields.is_some() { + // cancun not active but cancun fields present + return Err(PayloadError::PreCancunWithCancunFields) + } + } + + Ok(()) +} + +/// Checks transactions field and sidecar w.r.t new Cancun fields and new transaction type EIP-4844. +/// +/// Checks that: +/// - contains EIP-4844 transactions if Cancun is active +/// - checks blob versioned hashes in block and sidecar match +#[inline] +pub fn ensure_well_formed_transactions_field_with_sidecar( + block_body: &BlockBody, + cancun_sidecar_fields: Option<&CancunPayloadFields>, + is_cancun_active: bool, +) -> Result<(), PayloadError> { + if is_cancun_active { + ensure_matching_blob_versioned_hashes(block_body, cancun_sidecar_fields)? + } else if block_body.has_eip4844_transactions() { + return Err(PayloadError::PreCancunBlockWithBlobTransactions) + } + + Ok(()) +} + +/// Ensures that the number of blob versioned hashes of a EIP-4844 transactions in block, matches +/// the number hashes included in the _separate_ `block_versioned_hashes` of the cancun payload +/// fields on the sidecar. +pub fn ensure_matching_blob_versioned_hashes( + block_body: &BlockBody, + cancun_sidecar_fields: Option<&CancunPayloadFields>, +) -> Result<(), PayloadError> { + let num_blob_versioned_hashes = block_body.blob_versioned_hashes_iter().count(); + // Additional Cancun checks for blob transactions + if let Some(versioned_hashes) = cancun_sidecar_fields.map(|fields| &fields.versioned_hashes) { + if num_blob_versioned_hashes != versioned_hashes.len() { + // Number of blob versioned hashes does not match + return Err(PayloadError::InvalidVersionedHashes) + } + // we can use `zip` safely here because we already compared their length + for (payload_versioned_hash, block_versioned_hash) in + versioned_hashes.iter().zip(block_body.blob_versioned_hashes_iter()) + { + if payload_versioned_hash != block_versioned_hash { + return Err(PayloadError::InvalidVersionedHashes) + } + } + } else { + // No Cancun fields, if block includes any blobs, this is an error + if num_blob_versioned_hashes > 0 { + return Err(PayloadError::InvalidVersionedHashes) + } + } + + Ok(()) +} diff --git a/crates/payload/validator/src/lib.rs b/crates/payload/validator/src/lib.rs index e1bded98c873..a2088ba113d1 100644 --- a/crates/payload/validator/src/lib.rs +++ b/crates/payload/validator/src/lib.rs @@ -8,7 +8,11 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] -use alloy_rpc_types::engine::{ExecutionData, MaybeCancunPayloadFields, PayloadError}; +pub mod cancun; +pub mod prague; +pub mod shanghai; + +use alloy_rpc_types_engine::{ExecutionData, PayloadError}; use reth_chainspec::EthereumHardforks; use reth_primitives::SealedBlock; use reth_primitives_traits::{Block, SignedTransaction}; @@ -53,40 +57,6 @@ impl ExecutionPayloadValidator { self.chain_spec().is_prague_active_at_timestamp(timestamp) } - /// Cancun specific checks for EIP-4844 blob transactions. - /// - /// Ensures that the number of blob versioned hashes matches the number hashes included in the - /// _separate_ `block_versioned_hashes` of the cancun payload fields. - fn ensure_matching_blob_versioned_hashes( - &self, - sealed_block: &SealedBlock, - cancun_fields: &MaybeCancunPayloadFields, - ) -> Result<(), PayloadError> { - let num_blob_versioned_hashes = sealed_block.blob_versioned_hashes_iter().count(); - // Additional Cancun checks for blob transactions - if let Some(versioned_hashes) = cancun_fields.versioned_hashes() { - if num_blob_versioned_hashes != versioned_hashes.len() { - // Number of blob versioned hashes does not match - return Err(PayloadError::InvalidVersionedHashes) - } - // we can use `zip` safely here because we already compared their length - for (payload_versioned_hash, block_versioned_hash) in - versioned_hashes.iter().zip(sealed_block.blob_versioned_hashes_iter()) - { - if payload_versioned_hash != block_versioned_hash { - return Err(PayloadError::InvalidVersionedHashes) - } - } - } else { - // No Cancun fields, if block includes any blobs, this is an error - if num_blob_versioned_hashes > 0 { - return Err(PayloadError::InvalidVersionedHashes) - } - } - - Ok(()) - } - /// Ensures that the given payload does not violate any consensus rules that concern the block's /// layout, like: /// - missing or invalid base fee @@ -100,11 +70,11 @@ impl ExecutionPayloadValidator { /// The checks are done in the order that conforms with the engine-API specification. /// /// This is intended to be invoked after receiving the payload from the CLI. - /// The additional [`MaybeCancunPayloadFields`] are not part of the payload, but are additional fields in the `engine_newPayloadV3` RPC call, See also + /// The additional [`MaybeCancunPayloadFields`](alloy_rpc_types_engine::MaybeCancunPayloadFields) are not part of the payload, but are additional fields in the `engine_newPayloadV3` RPC call, See also /// /// If the cancun fields are provided this also validates that the versioned hashes in the block /// match the versioned hashes passed in the - /// [`CancunPayloadFields`](alloy_rpc_types::engine::CancunPayloadFields), if the cancun payload + /// [`CancunPayloadFields`](alloy_rpc_types_engine::CancunPayloadFields), if the cancun payload /// fields are provided. If the payload fields are not provided, but versioned hashes exist /// in the block, this is considered an error: [`PayloadError::InvalidVersionedHashes`]. /// @@ -129,54 +99,21 @@ impl ExecutionPayloadValidator { }) } - if self.is_cancun_active_at_timestamp(sealed_block.timestamp) { - if sealed_block.blob_gas_used.is_none() { - // cancun active but blob gas used not present - return Err(PayloadError::PostCancunBlockWithoutBlobGasUsed) - } - if sealed_block.excess_blob_gas.is_none() { - // cancun active but excess blob gas not present - return Err(PayloadError::PostCancunBlockWithoutExcessBlobGas) - } - if sidecar.cancun().is_none() { - // cancun active but cancun fields not present - return Err(PayloadError::PostCancunWithoutCancunFields) - } - } else { - if sealed_block.body().has_eip4844_transactions() { - // cancun not active but blob transactions present - return Err(PayloadError::PreCancunBlockWithBlobTransactions) - } - if sealed_block.blob_gas_used.is_some() { - // cancun not active but blob gas used present - return Err(PayloadError::PreCancunBlockWithBlobGasUsed) - } - if sealed_block.excess_blob_gas.is_some() { - // cancun not active but excess blob gas present - return Err(PayloadError::PreCancunBlockWithExcessBlobGas) - } - if sidecar.cancun().is_some() { - // cancun not active but cancun fields present - return Err(PayloadError::PreCancunWithCancunFields) - } - } - - let shanghai_active = self.is_shanghai_active_at_timestamp(sealed_block.timestamp); - if !shanghai_active && sealed_block.body().withdrawals.is_some() { - // shanghai not active but withdrawals present - return Err(PayloadError::PreShanghaiBlockWithWithdrawals) - } - - if !self.is_prague_active_at_timestamp(sealed_block.timestamp) && - sealed_block.body().has_eip7702_transactions() - { - return Err(PayloadError::PrePragueBlockWithEip7702Transactions) - } + shanghai::ensure_well_formed_fields( + sealed_block.body(), + self.is_shanghai_active_at_timestamp(sealed_block.timestamp), + )?; - // EIP-4844 checks - self.ensure_matching_blob_versioned_hashes( + cancun::ensure_well_formed_fields( &sealed_block, - &sidecar.cancun().cloned().into(), + sidecar.cancun(), + self.is_cancun_active_at_timestamp(sealed_block.timestamp), + )?; + + prague::ensure_well_formed_fields( + sealed_block.body(), + sidecar.prague(), + self.is_prague_active_at_timestamp(sealed_block.timestamp), )?; Ok(sealed_block) diff --git a/crates/payload/validator/src/prague.rs b/crates/payload/validator/src/prague.rs new file mode 100644 index 000000000000..4d26e5bf01ea --- /dev/null +++ b/crates/payload/validator/src/prague.rs @@ -0,0 +1,48 @@ +//! Prague rules for new payloads. + +use alloy_consensus::{BlockBody, Typed2718}; +use alloy_rpc_types_engine::{PayloadError, PraguePayloadFields}; + +/// Checks block and sidecar well-formedness w.r.t new Prague fields and new transaction type +/// EIP-7702. +/// +/// Checks that: +/// - Prague fields are not present unless Prague is active +/// - does not contain EIP-7702 transactions if Prague is not active +#[inline] +pub fn ensure_well_formed_fields( + block_body: &BlockBody, + prague_fields: Option<&PraguePayloadFields>, + is_prague_active: bool, +) -> Result<(), PayloadError> { + ensure_well_formed_sidecar_fields(prague_fields, is_prague_active)?; + ensure_well_formed_transactions_field(block_body, is_prague_active) +} + +/// Checks that Prague fields are not present on sidecar unless Prague is active. +#[inline] +pub fn ensure_well_formed_sidecar_fields( + prague_fields: Option<&PraguePayloadFields>, + is_prague_active: bool, +) -> Result<(), PayloadError> { + if !is_prague_active && prague_fields.is_some() { + // prague _not_ active but prague fields present + return Err(PayloadError::PrePragueBlockRequests) + } + + Ok(()) +} + +/// Checks that transactions field doesn't contain EIP-7702 transactions if Prague is not +/// active. +#[inline] +pub fn ensure_well_formed_transactions_field( + block_body: &BlockBody, + is_prague_active: bool, +) -> Result<(), PayloadError> { + if !is_prague_active && block_body.has_eip7702_transactions() { + return Err(PayloadError::PrePragueBlockWithEip7702Transactions) + } + + Ok(()) +} diff --git a/crates/payload/validator/src/shanghai.rs b/crates/payload/validator/src/shanghai.rs new file mode 100644 index 000000000000..f106ac0f761f --- /dev/null +++ b/crates/payload/validator/src/shanghai.rs @@ -0,0 +1,23 @@ +//! Shanghai rules for new payloads. + +use alloy_rpc_types_engine::PayloadError; +use reth_primitives_traits::BlockBody; + +/// Checks that block body contains withdrawals if Shanghai is active and vv. +#[inline] +pub fn ensure_well_formed_fields( + block_body: &T, + is_shanghai_active: bool, +) -> Result<(), PayloadError> { + if is_shanghai_active { + if block_body.withdrawals().is_none() { + // shanghai not active but withdrawals present + return Err(PayloadError::PostShanghaiBlockWithoutWithdrawals) + } + } else if block_body.withdrawals().is_some() { + // shanghai not active but withdrawals present + return Err(PayloadError::PreShanghaiBlockWithWithdrawals) + } + + Ok(()) +} From e92cf35ac9233e35854adb582f993ffe088031be Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Wed, 19 Feb 2025 14:08:49 +0400 Subject: [PATCH 11/21] refactor: simplify `SystemCaller` API (#14578) --- .../engine/invalid-block-hooks/src/witness.rs | 3 +- crates/engine/util/src/reorg.rs | 10 +- crates/ethereum/evm/src/execute.rs | 4 +- crates/ethereum/payload/src/lib.rs | 12 +- crates/evm/src/system_calls/eip2935.rs | 6 +- crates/evm/src/system_calls/eip4788.rs | 6 +- crates/evm/src/system_calls/mod.rs | 140 +++--------------- crates/optimism/evm/src/execute.rs | 12 +- crates/optimism/payload/src/builder.rs | 74 +++++---- .../rpc-eth-api/src/helpers/pending_block.rs | 16 +- crates/rpc/rpc-eth-api/src/helpers/trace.rs | 13 +- 11 files changed, 80 insertions(+), 216 deletions(-) diff --git a/crates/engine/invalid-block-hooks/src/witness.rs b/crates/engine/invalid-block-hooks/src/witness.rs index 1f4cd1f19cd9..8257baca3465 100644 --- a/crates/engine/invalid-block-hooks/src/witness.rs +++ b/crates/engine/invalid-block-hooks/src/witness.rs @@ -78,8 +78,7 @@ where // Setup EVM let mut evm = self.evm_config.evm_for_block(&mut db, block.header()); - let mut system_caller = - SystemCaller::new(self.evm_config.clone(), self.provider.chain_spec()); + let mut system_caller = SystemCaller::new(self.provider.chain_spec()); // Apply pre-block system contract calls. system_caller.apply_pre_execution_changes(block.header(), &mut evm)?; diff --git a/crates/engine/util/src/reorg.rs b/crates/engine/util/src/reorg.rs index 25ee604600ef..b79da3f6c42f 100644 --- a/crates/engine/util/src/reorg.rs +++ b/crates/engine/util/src/reorg.rs @@ -293,14 +293,10 @@ where let mut evm = evm_config.evm_for_block(&mut state, &reorg_target.header); // apply eip-4788 pre block contract call - let mut system_caller = SystemCaller::new(evm_config.clone(), chain_spec.clone()); + let mut system_caller = SystemCaller::new(chain_spec.clone()); - system_caller.apply_beacon_root_contract_call( - reorg_target.timestamp, - reorg_target.number, - reorg_target.parent_beacon_block_root, - &mut evm, - )?; + system_caller + .apply_beacon_root_contract_call(reorg_target.parent_beacon_block_root, &mut evm)?; let mut cumulative_gas_used = 0; let mut sum_blob_gas_used = 0; diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index fc570d01a926..f4427dd4a005 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -90,7 +90,7 @@ where /// Current state for block execution. state: State, /// Utility to call system smart contracts. - system_caller: SystemCaller, + system_caller: SystemCaller>, } impl EthExecutionStrategy @@ -99,7 +99,7 @@ where { /// Creates a new [`EthExecutionStrategy`] pub fn new(state: State, chain_spec: Arc, evm_config: EvmConfig) -> Self { - let system_caller = SystemCaller::new(evm_config.clone(), chain_spec.clone()); + let system_caller = SystemCaller::new(chain_spec.clone()); Self { state, chain_spec, evm_config, system_caller } } } diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index 49ff2d908b4f..d659012d54f7 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -202,11 +202,12 @@ where let block_number = evm_env.block_env.number; let beneficiary = evm_env.block_env.beneficiary; - let mut system_caller = SystemCaller::new(evm_config.clone(), chain_spec.clone()); + let mut evm = evm_config.evm_with_env(&mut db, evm_env); + let mut system_caller = SystemCaller::new(chain_spec.clone()); // apply eip-4788 pre block contract call system_caller - .pre_block_beacon_root_contract_call(&mut db, &evm_env, attributes.parent_beacon_block_root) + .apply_beacon_root_contract_call(attributes.parent_beacon_block_root, &mut evm) .map_err(|err| { warn!(target: "payload_builder", parent_hash=%parent_header.hash(), @@ -217,18 +218,15 @@ where })?; // apply eip-2935 blockhashes update - system_caller.pre_block_blockhashes_contract_call( - &mut db, - &evm_env, + system_caller.apply_blockhashes_contract_call( parent_header.hash(), + &mut evm, ) .map_err(|err| { warn!(target: "payload_builder", parent_hash=%parent_header.hash(), %err, "failed to update parent header blockhashes for payload"); PayloadBuilderError::Internal(err.into()) })?; - let mut evm = evm_config.evm_with_env(&mut db, evm_env); - let mut receipts = Vec::new(); let mut block_blob_count = 0; let blob_params = chain_spec.blob_params_at_timestamp(attributes.timestamp); diff --git a/crates/evm/src/system_calls/eip2935.rs b/crates/evm/src/system_calls/eip2935.rs index b156e7e9574a..dbd3d0d92247 100644 --- a/crates/evm/src/system_calls/eip2935.rs +++ b/crates/evm/src/system_calls/eip2935.rs @@ -23,18 +23,16 @@ use revm::context_interface::result::ResultAndState; #[inline] pub(crate) fn transact_blockhashes_contract_call( chain_spec: impl EthereumHardforks, - block_timestamp: u64, - block_number: u64, parent_block_hash: B256, evm: &mut impl Evm, ) -> Result>, BlockExecutionError> { - if !chain_spec.is_prague_active_at_timestamp(block_timestamp) { + if !chain_spec.is_prague_active_at_timestamp(evm.block().timestamp) { return Ok(None) } // if the block number is zero (genesis block) then no system transaction may occur as per // EIP-2935 - if block_number == 0 { + if evm.block().number == 0 { return Ok(None) } diff --git a/crates/evm/src/system_calls/eip4788.rs b/crates/evm/src/system_calls/eip4788.rs index 457954d7c59f..f6f7989a86f9 100644 --- a/crates/evm/src/system_calls/eip4788.rs +++ b/crates/evm/src/system_calls/eip4788.rs @@ -20,12 +20,10 @@ use revm::context_interface::result::ResultAndState; #[inline] pub(crate) fn transact_beacon_root_contract_call( chain_spec: impl EthereumHardforks, - block_timestamp: u64, - block_number: u64, parent_beacon_block_root: Option, evm: &mut impl Evm, ) -> Result>, BlockExecutionError> { - if !chain_spec.is_cancun_active_at_timestamp(block_timestamp) { + if !chain_spec.is_cancun_active_at_timestamp(evm.block().timestamp) { return Ok(None) } @@ -34,7 +32,7 @@ pub(crate) fn transact_beacon_root_contract_call( // if the block number is zero (genesis block) then the parent beacon block root must // be 0x0 and no system transaction may occur as per EIP-4788 - if block_number == 0 { + if evm.block().number == 0 { if !parent_beacon_block_root.is_zero() { return Err(BlockValidationError::CancunGenesisParentBeaconBlockRootNotZero { parent_beacon_block_root, diff --git a/crates/evm/src/system_calls/mod.rs b/crates/evm/src/system_calls/mod.rs index f99e1ca0a488..53f194740c28 100644 --- a/crates/evm/src/system_calls/mod.rs +++ b/crates/evm/src/system_calls/mod.rs @@ -1,7 +1,7 @@ //! System contract call functions. -use crate::{ConfigureEvm, Database, Evm, EvmEnv}; -use alloc::{boxed::Box, sync::Arc}; +use crate::Evm; +use alloc::boxed::Box; use alloy_consensus::BlockHeader; use alloy_eips::{ eip7002::WITHDRAWAL_REQUEST_TYPE, eip7251::CONSOLIDATION_REQUEST_TYPE, eip7685::Requests, @@ -78,18 +78,17 @@ impl OnStateHook for NoopHook { /// /// This can be used to chain system transaction calls. #[allow(missing_debug_implementations)] -pub struct SystemCaller { - evm_config: EvmConfig, - chain_spec: Arc, +pub struct SystemCaller { + chain_spec: ChainSpec, /// Optional hook to be called after each state change. hook: Option>, } -impl SystemCaller { +impl SystemCaller { /// Create a new system caller with the given EVM config, database, and chain spec, and creates /// the EVM with the given initialized config and block environment. - pub const fn new(evm_config: EvmConfig, chain_spec: Arc) -> Self { - Self { evm_config, chain_spec, hook: None } + pub const fn new(chain_spec: ChainSpec) -> Self { + Self { chain_spec, hook: None } } /// Installs a custom hook to be called after each state change. @@ -102,29 +101,18 @@ impl SystemCaller { pub fn finish(self) {} } -impl SystemCaller +impl SystemCaller where - EvmConfig: ConfigureEvm, Chainspec: EthereumHardforks, { /// Apply pre execution changes. pub fn apply_pre_execution_changes( &mut self, - header: &EvmConfig::Header, + header: impl BlockHeader, evm: &mut impl Evm, ) -> Result<(), BlockExecutionError> { - self.apply_blockhashes_contract_call( - header.timestamp(), - header.number(), - header.parent_hash(), - evm, - )?; - self.apply_beacon_root_contract_call( - header.timestamp(), - header.number(), - header.parent_beacon_block_root(), - evm, - )?; + self.apply_blockhashes_contract_call(header.parent_hash(), evm)?; + self.apply_beacon_root_contract_call(header.parent_beacon_block_root(), evm)?; Ok(()) } @@ -151,45 +139,14 @@ where Ok(requests) } - /// Applies the pre-block call to the EIP-2935 blockhashes contract. - pub fn pre_block_blockhashes_contract_call( - &mut self, - db: &mut DB, - evm_env: &EvmEnv, - parent_block_hash: B256, - ) -> Result<(), BlockExecutionError> - where - DB: Database + DatabaseCommit, - DB::Error: Display, - { - let evm_config = self.evm_config.clone(); - let mut evm = evm_config.evm_with_env(db, evm_env.clone()); - - self.apply_blockhashes_contract_call( - evm_env.block_env.timestamp, - evm_env.block_env.number, - parent_block_hash, - &mut evm, - )?; - - Ok(()) - } - /// Applies the pre-block call to the EIP-2935 blockhashes contract. pub fn apply_blockhashes_contract_call( &mut self, - timestamp: u64, - block_number: u64, parent_block_hash: B256, - evm: &mut impl Evm, + evm: &mut impl Evm, ) -> Result<(), BlockExecutionError> { - let result_and_state = eip2935::transact_blockhashes_contract_call( - &self.chain_spec, - timestamp, - block_number, - parent_block_hash, - evm, - )?; + let result_and_state = + eip2935::transact_blockhashes_contract_call(&self.chain_spec, parent_block_hash, evm)?; if let Some(res) = result_and_state { if let Some(ref mut hook) = self.hook { @@ -204,43 +161,15 @@ where Ok(()) } - /// Applies the pre-block call to the EIP-4788 beacon root contract. - pub fn pre_block_beacon_root_contract_call( - &mut self, - db: &mut DB, - evm_env: &EvmEnv, - parent_beacon_block_root: Option, - ) -> Result<(), BlockExecutionError> - where - DB: Database + DatabaseCommit, - DB::Error: Display, - { - let evm_config = self.evm_config.clone(); - let mut evm = evm_config.evm_with_env(db, evm_env.clone()); - - self.apply_beacon_root_contract_call( - evm_env.block_env.timestamp, - evm_env.block_env.number, - parent_beacon_block_root, - &mut evm, - )?; - - Ok(()) - } - /// Applies the pre-block call to the EIP-4788 beacon root contract. pub fn apply_beacon_root_contract_call( &mut self, - timestamp: u64, - block_number: u64, - parent_block_hash: Option, - evm: &mut impl Evm, + parent_beacon_block_root: Option, + evm: &mut impl Evm, ) -> Result<(), BlockExecutionError> { let result_and_state = eip4788::transact_beacon_root_contract_call( &self.chain_spec, - timestamp, - block_number, - parent_block_hash, + parent_beacon_block_root, evm, )?; @@ -257,24 +186,6 @@ where Ok(()) } - /// Applies the post-block call to the EIP-7002 withdrawal request contract. - pub fn post_block_withdrawal_requests_contract_call( - &mut self, - db: &mut DB, - evm_env: &EvmEnv, - ) -> Result - where - DB: Database + DatabaseCommit, - DB::Error: Display, - { - let evm_config = self.evm_config.clone(); - let mut evm = evm_config.evm_with_env(db, evm_env.clone()); - - let result = self.apply_withdrawal_requests_contract_call(&mut evm)?; - - Ok(result) - } - /// Applies the post-block call to the EIP-7002 withdrawal request contract. pub fn apply_withdrawal_requests_contract_call( &mut self, @@ -295,23 +206,6 @@ where eip7002::post_commit(result_and_state.result) } - /// Applies the post-block call to the EIP-7251 consolidation requests contract. - pub fn post_block_consolidation_requests_contract_call( - &mut self, - db: &mut DB, - evm_env: &EvmEnv, - ) -> Result - where - DB: Database + DatabaseCommit, - { - let evm_config = self.evm_config.clone(); - let mut evm = evm_config.evm_with_env(db, evm_env.clone()); - - let res = self.apply_consolidation_requests_contract_call(&mut evm)?; - - Ok(res) - } - /// Applies the post-block call to the EIP-7251 consolidation requests contract. pub fn apply_consolidation_requests_contract_call( &mut self, diff --git a/crates/optimism/evm/src/execute.rs b/crates/optimism/evm/src/execute.rs index 524d73bd3b1e..6e0d948559e3 100644 --- a/crates/optimism/evm/src/execute.rs +++ b/crates/optimism/evm/src/execute.rs @@ -109,7 +109,7 @@ where /// Current state for block execution. state: State, /// Utility to call system smart contracts. - system_caller: SystemCaller, + system_caller: SystemCaller>, /// Receipt builder. receipt_builder: Arc, Receipt = N::Receipt>>, @@ -130,7 +130,7 @@ where dyn OpReceiptBuilder, Receipt = N::Receipt>, >, ) -> Self { - let system_caller = SystemCaller::new(evm_config.clone(), chain_spec.clone()); + let system_caller = SystemCaller::new(chain_spec.clone()); Self { state, chain_spec, evm_config, system_caller, receipt_builder } } } @@ -158,12 +158,8 @@ where let mut evm = self.evm_config.evm_for_block(&mut self.state, block.header()); - self.system_caller.apply_beacon_root_contract_call( - block.header().timestamp(), - block.header().number(), - block.header().parent_beacon_block_root(), - &mut evm, - )?; + self.system_caller + .apply_beacon_root_contract_call(block.header().parent_beacon_block_root(), &mut evm)?; // Ensure that the create2deployer is force-deployed at the canyon transition. Optimism // blocks will always have at least a single transaction in them (the L1 info transaction), diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index b7e0066b1187..34ff1f7152c3 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -55,7 +55,7 @@ use revm::{ result::{ExecutionResult, ResultAndState}, Block, }, - DatabaseCommit, + Database as _, DatabaseCommit, }; use std::{fmt::Display, sync::Arc}; use tracing::{debug, trace, warn}; @@ -368,19 +368,21 @@ impl OpBuilder<'_, Txs> { let Self { best } = self; debug!(target: "payload_builder", id=%ctx.payload_id(), parent_header = ?ctx.parent().hash(), parent_number = ctx.parent().number, "building new payload"); + let mut evm = ctx.evm_config.evm_with_env(&mut *state, ctx.evm_env.clone()); + // 1. apply eip-4788 pre block contract call - ctx.apply_pre_beacon_root_contract_call(state)?; + ctx.apply_pre_beacon_root_contract_call(&mut evm)?; // 2. ensure create2deployer is force deployed - ctx.ensure_create2_deployer(state)?; + ctx.ensure_create2_deployer(evm.db_mut())?; // 3. execute sequencer transactions - let mut info = ctx.execute_sequencer_transactions(state)?; + let mut info = ctx.execute_sequencer_transactions(&mut evm)?; // 4. if mem pool transactions are requested we execute them if !ctx.attributes().no_tx_pool { let best_txs = best(ctx.best_transaction_attributes()); - if ctx.execute_best_transactions(&mut info, state, best_txs)?.is_some() { + if ctx.execute_best_transactions(&mut info, &mut evm, best_txs)?.is_some() { return Ok(BuildOutcomeKind::Cancelled) } @@ -391,6 +393,8 @@ impl OpBuilder<'_, Txs> { } } + drop(evm); + // merge all transitions into bundle state, this would apply the withdrawal balance changes // and 4788 contract call state.merge_transitions(BundleRetention::Reverts); @@ -822,19 +826,14 @@ where N: OpPayloadPrimitives, { /// apply eip-4788 pre block contract call - pub fn apply_pre_beacon_root_contract_call( + pub fn apply_pre_beacon_root_contract_call( &self, - db: &mut DB, - ) -> Result<(), PayloadBuilderError> - where - DB: Database + DatabaseCommit, - DB::Error: Display, - { - SystemCaller::new(self.evm_config.clone(), self.chain_spec.clone()) - .pre_block_beacon_root_contract_call( - db, - &self.evm_env, + evm: &mut impl Evm, + ) -> Result<(), PayloadBuilderError> { + SystemCaller::new(&self.chain_spec) + .apply_beacon_root_contract_call( self.attributes().payload_attributes.parent_beacon_block_root, + evm, ) .map_err(|err| { warn!(target: "payload_builder", @@ -886,15 +885,15 @@ where } /// Executes all sequencer transactions that are included in the payload attributes. - pub fn execute_sequencer_transactions( + pub fn execute_sequencer_transactions( &self, - db: &mut State, - ) -> Result, PayloadBuilderError> - where - DB: Database, - { + evm: &mut impl Evm< + DB: Database + DatabaseCommit, + Tx = EvmConfig::TxEnv, + HaltReason = HaltReasonFor, + >, + ) -> Result, PayloadBuilderError> { let mut info = ExecutionInfo::with_capacity(self.attributes().transactions.len()); - let mut evm = self.evm_config.evm_with_env(&mut *db, self.evm_env.clone()); for sequencer_tx in &self.attributes().transactions { // A sequencer's block should never contain blob transactions. @@ -920,8 +919,8 @@ where let depositor_nonce = (self.is_regolith_active() && sequencer_tx.is_deposit()) .then(|| { evm.db_mut() - .load_cache_account(sequencer_tx.signer()) - .map(|acc| acc.account_info().unwrap_or_default().nonce) + .basic(sequencer_tx.signer()) + .map(|acc| acc.unwrap_or_default().nonce) }) .transpose() .map_err(|_| { @@ -932,7 +931,7 @@ where let tx_env = self.evm_config.tx_env(sequencer_tx.tx(), sequencer_tx.signer()); - let ResultAndState { result, state } = match evm.transact(tx_env) { + let ResultAndState { result, state: _ } = match evm.transact_commit(tx_env) { Ok(res) => res, Err(err) => { if err.is_invalid_tx_err() { @@ -944,9 +943,6 @@ where } }; - // commit changes - evm.db_mut().commit(state); - let gas_used = result.gas_used(); // add gas used by the transaction to cumulative gas used, before creating the receipt @@ -971,24 +967,23 @@ where /// Executes the given best transactions and updates the execution info. /// /// Returns `Ok(Some(())` if the job was cancelled. - pub fn execute_best_transactions( + pub fn execute_best_transactions( &self, info: &mut ExecutionInfo, - db: &mut State, + evm: &mut impl Evm< + DB: DatabaseCommit, + Tx = EvmConfig::TxEnv, + HaltReason = HaltReasonFor, + >, mut best_txs: impl PayloadTransactions< Transaction: PoolTransaction, >, - ) -> Result, PayloadBuilderError> - where - DB: Database, - { + ) -> Result, PayloadBuilderError> { let block_gas_limit = self.block_gas_limit(); let block_da_limit = self.da_config.max_da_block_size(); let tx_da_limit = self.da_config.max_da_tx_size(); let base_fee = self.base_fee(); - let mut evm = self.evm_config.evm_with_env(&mut *db, self.evm_env.clone()); - while let Some(tx) = best_txs.next(()) { let tx = tx.into_consensus(); if info.is_tx_over_limits(tx.tx(), block_gas_limit, tx_da_limit, block_da_limit) { @@ -1013,7 +1008,7 @@ where // Configure the environment for the tx. let tx_env = self.evm_config.tx_env(tx.tx(), tx.signer()); - let ResultAndState { result, state } = match evm.transact(tx_env) { + let ResultAndState { result, state: _ } = match evm.transact_commit(tx_env) { Ok(res) => res, Err(err) => { if let Some(err) = err.as_invalid_tx_err() { @@ -1034,9 +1029,6 @@ where } }; - // commit changes - evm.db_mut().commit(state); - let gas_used = result.gas_used(); // add gas used by the transaction to cumulative gas used, before creating the diff --git a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs index d465810fd9e4..8a62c226b1d8 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs @@ -36,7 +36,6 @@ use revm::{ result::{ExecutionResult, ResultAndState}, Block, }, - DatabaseCommit, }; use std::time::{Duration, Instant}; use tokio::sync::Mutex; @@ -277,10 +276,11 @@ pub trait LoadPendingBlock: let chain_spec = self.provider().chain_spec(); - let mut system_caller = SystemCaller::new(self.evm_config().clone(), chain_spec.clone()); + let mut system_caller = SystemCaller::new(chain_spec.clone()); + let mut evm = self.evm_config().evm_with_env(&mut db, evm_env.clone()); system_caller - .pre_block_blockhashes_contract_call(&mut db, &evm_env, parent_hash) + .apply_blockhashes_contract_call(parent_hash, &mut evm) .map_err(|err| EthApiError::Internal(err.into()))?; let mut results = Vec::new(); @@ -337,9 +337,8 @@ pub trait LoadPendingBlock: } let tx_env = self.evm_config().tx_env(tx.tx(), tx.signer()); - let mut evm = self.evm_config().evm_with_env(&mut db, evm_env.clone()); - let ResultAndState { result, state } = match evm.transact(tx_env) { + let ResultAndState { result, state: _ } = match evm.transact_commit(tx_env) { Ok(res) => res, Err(err) => { if let Some(err) = err.as_invalid_tx_err() { @@ -361,10 +360,6 @@ pub trait LoadPendingBlock: return Err(Self::Error::from_evm_err(err)); } }; - // drop evm to release db reference. - drop(evm); - // commit changes - db.commit(state); // add to the total blob gas used if the transaction successfully executed if let Some(tx_blob_gas) = tx.blob_gas_used() { @@ -395,6 +390,9 @@ pub trait LoadPendingBlock: &[], ); + // release db + drop(evm); + // increment account balances for withdrawals db.increment_balances(balance_increments).map_err(Self::Error::from_eth_err)?; diff --git a/crates/rpc/rpc-eth-api/src/helpers/trace.rs b/crates/rpc/rpc-eth-api/src/helpers/trace.rs index d517651be2b6..2e72f8b4f932 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/trace.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/trace.rs @@ -468,19 +468,14 @@ pub trait Trace: db: &mut DB, evm_env: &EvmEnv<::Spec>, ) -> Result<(), Self::Error> { - let mut system_caller = - SystemCaller::new(self.evm_config().clone(), self.provider().chain_spec()); + let mut system_caller = SystemCaller::new(self.provider().chain_spec()); + // apply relevant system calls + let mut evm = self.evm_config().evm_with_env(db, evm_env.clone()); system_caller - .pre_block_beacon_root_contract_call(db, evm_env, block.parent_beacon_block_root()) + .apply_pre_execution_changes(block.header(), &mut evm) .map_err(|_| EthApiError::EvmCustom("failed to apply 4788 system call".to_string()))?; - system_caller - .pre_block_blockhashes_contract_call(db, evm_env, block.parent_hash()) - .map_err(|_| { - EthApiError::EvmCustom("failed to apply blockhashes system call".to_string()) - })?; - Ok(()) } } From 1e40e2dca270335b4e0b24ee8a7787488d33678c Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Feb 2025 12:02:59 +0100 Subject: [PATCH 12/21] chore(deps): Bump `op-alloy` (#14579) --- Cargo.lock | 24 ++++++++++++------------ Cargo.toml | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b2f528c890c..087209916939 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5545,9 +5545,9 @@ checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "op-alloy-consensus" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23f7ff02e5f3ba62c8dd5d9a630c818f50147bca7b0d78e89de59ed46b5d02e1" +checksum = "bc796860410e85a9cd881ee074c3dc0120b90696d82d09348ebb563d4ade67e4" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5563,15 +5563,15 @@ dependencies = [ [[package]] name = "op-alloy-flz" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740324977f089db5b2cd96975260308c3f52daeaa103570995211748d282e560" +checksum = "4d4ab80587d9f98aae42d255c21bd183ae4423a4d7cb320e738d2b2e96d1591b" [[package]] name = "op-alloy-network" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab4dd4e260be40a7ab8debf5300baf1f02f1d2a6e0c1ab5741732d612de7d6e" +checksum = "74f787eb3752a847369a3eefb6cbb3f8bfc9c365a2435116f84ef68d0edfe821" dependencies = [ "alloy-consensus", "alloy-network", @@ -5584,9 +5584,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-jsonrpsee" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "725e79490887d768e5f22badf93d8c8d12349aca6db63a050acb3472f2535e6c" +checksum = "0a47074c77544a3f6fe062809d0c74b137668a93f788513250577873b2a93b14" dependencies = [ "alloy-primitives", "jsonrpsee", @@ -5594,9 +5594,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9af4583c4b3ea93f54092ebfe41172974de2042672e9850500f4d1f99844e" +checksum = "e70bef5860f87412848c40a9f71f23923c6d59726aae678251911acdbc7380b2" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5612,9 +5612,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types-engine" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20120c629465e52e5cdb0ac8df0ba45e184b456fcd55d17ea9ec1247d6968bb4" +checksum = "24a03ea4f6374aa13524753136eeceee76196acad6b1306399ab8f1856872384" dependencies = [ "alloy-consensus", "alloy-eips", diff --git a/Cargo.toml b/Cargo.toml index d6230ba9b199..c63166f6cd09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -483,12 +483,12 @@ alloy-transport-ws = { version = "0.11.1", default-features = false } # op alloy-op-evm = { version = "0.1", default-features = false } -op-alloy-rpc-types = { version = "0.10.3", default-features = false } -op-alloy-rpc-types-engine = { version = "0.10.3", default-features = false } -op-alloy-network = { version = "0.10.3", default-features = false } -op-alloy-consensus = { version = "0.10.3", default-features = false } -op-alloy-flz = { version = "0.10.3", default-features = false } -op-alloy-rpc-jsonrpsee = { version = "0.10.3", default-features = false } +op-alloy-rpc-types = { version = "0.10.4", default-features = false } +op-alloy-rpc-types-engine = { version = "0.10.4", default-features = false } +op-alloy-network = { version = "0.10.4", default-features = false } +op-alloy-consensus = { version = "0.10.4", default-features = false } +op-alloy-flz = { version = "0.10.4", default-features = false } +op-alloy-rpc-jsonrpsee = { version = "0.10.4", default-features = false } # misc aquamarine = "0.6" From c9a348dd2ccbcb7e1f7553dc6b19776bbe85b70a Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 19 Feb 2025 12:36:15 +0100 Subject: [PATCH 13/21] chore(deps): bump breaking deps (#14570) Co-authored-by: Matthias Seitz --- Cargo.lock | 426 ++++++++++-------- Cargo.toml | 20 +- crates/cli/commands/Cargo.toml | 4 +- crates/net/discv4/Cargo.toml | 2 +- crates/net/discv4/src/proto.rs | 4 +- crates/net/discv5/Cargo.toml | 2 +- crates/net/discv5/src/lib.rs | 8 +- crates/net/dns/Cargo.toml | 4 +- crates/net/ecies/Cargo.toml | 2 +- crates/net/ecies/src/algorithm.rs | 4 +- crates/net/eth-wire/Cargo.toml | 2 +- crates/net/network/Cargo.toml | 3 +- crates/node/builder/Cargo.toml | 2 +- crates/node/core/Cargo.toml | 2 +- crates/node/metrics/Cargo.toml | 5 +- crates/optimism/chainspec/src/lib.rs | 4 +- .../primitives/src/transaction/signed.rs | 1 + crates/primitives-traits/src/crypto.rs | 4 +- crates/storage/codecs/derive/Cargo.toml | 2 +- crates/storage/db/Cargo.toml | 2 +- crates/storage/db/src/lockfile.rs | 10 +- crates/storage/libmdbx-rs/Cargo.toml | 1 - .../storage/libmdbx-rs/benches/transaction.rs | 11 +- crates/trie/db/src/prefix_set.rs | 6 +- examples/bsc-p2p/Cargo.toml | 2 +- examples/manual-p2p/Cargo.toml | 2 +- examples/polygon-p2p/Cargo.toml | 2 +- 27 files changed, 304 insertions(+), 233 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 087209916939..93cec435ccdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,7 +116,7 @@ dependencies = [ "num_enum", "proptest", "serde", - "strum", + "strum 0.26.3", ] [[package]] @@ -133,7 +133,7 @@ dependencies = [ "arbitrary", "auto_impl", "c-kzg", - "derive_more", + "derive_more 1.0.0", "rand 0.8.5", "serde", "serde_with", @@ -184,7 +184,7 @@ dependencies = [ "alloy-sol-type-parser", "alloy-sol-types", "const-hex", - "derive_more", + "derive_more 1.0.0", "itoa", "serde", "serde_json", @@ -228,7 +228,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "arbitrary", - "derive_more", + "derive_more 1.0.0", "k256", "rand 0.8.5", "serde", @@ -250,7 +250,7 @@ dependencies = [ "arbitrary", "auto_impl", "c-kzg", - "derive_more", + "derive_more 1.0.0", "ethereum_ssz", "ethereum_ssz_derive", "once_cell", @@ -388,7 +388,7 @@ dependencies = [ "cfg-if", "const-hex", "derive_arbitrary", - "derive_more", + "derive_more 1.0.0", "foldhash", "getrandom 0.2.15", "hashbrown 0.15.2", @@ -601,14 +601,14 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "alloy-serde", - "derive_more", + "derive_more 1.0.0", "ethereum_ssz", "ethereum_ssz_derive", "jsonrpsee-types", "jsonwebtoken", "rand 0.8.5", "serde", - "strum", + "strum 0.26.3", ] [[package]] @@ -871,7 +871,7 @@ dependencies = [ "arbitrary", "arrayvec", "derive_arbitrary", - "derive_more", + "derive_more 1.0.0", "nybbles", "proptest", "proptest-derive", @@ -1375,6 +1375,22 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +[[package]] +name = "bitcoin-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -1759,6 +1775,20 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "cargo_metadata" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.25", + "serde", + "serde_json", + "thiserror 2.0.11", +] + [[package]] name = "cassowary" version = "0.3.0" @@ -2135,9 +2165,9 @@ checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "convert_case" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" dependencies = [ "unicode-segmentation", ] @@ -2305,7 +2335,7 @@ checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ "bitflags 2.8.0", "crossterm_winapi", - "mio 1.0.3", + "mio", "parking_lot", "rustix", "signal-hook", @@ -2603,7 +2633,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "derive_more-impl", + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl 2.0.1", ] [[package]] @@ -2611,6 +2650,18 @@ name = "derive_more-impl" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", + "unicode-xid", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "convert_case", "proc-macro2", @@ -2690,9 +2741,9 @@ dependencies = [ [[package]] name = "discv5" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e6b70634e26c909d1edbb3142b3eaf3b89da0e52f284f00ca7c80d9901ad9e" +checksum = "c4b4e7798d2ff74e29cee344dc490af947ae657d6ab5273dde35d58ce06a4d71" dependencies = [ "aes", "aes-gcm", @@ -2849,19 +2900,19 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "enr" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "972070166c68827e64bd1ebc8159dd8e32d9bc2da7ebe8f20b61308f7974ad30" +checksum = "851bd664a3d3a3c175cff92b2f0df02df3c541b4895d0ae307611827aae46152" dependencies = [ "alloy-rlp", - "base64 0.21.7", + "base64 0.22.1", "bytes", "ed25519-dalek", "hex", "k256", "log", "rand 0.8.5", - "secp256k1", + "secp256k1 0.30.0", "serde", "sha3", "zeroize", @@ -3025,7 +3076,7 @@ dependencies = [ "reth-network-peers", "reth-primitives", "reth-tracing", - "secp256k1", + "secp256k1 0.30.0", "serde_json", "tokio", "tokio-stream", @@ -3196,7 +3247,7 @@ dependencies = [ "reth-network", "reth-network-peers", "reth-primitives", - "secp256k1", + "secp256k1 0.30.0", "tokio", ] @@ -3267,7 +3318,7 @@ dependencies = [ "reth-network-api", "reth-primitives", "reth-tracing", - "secp256k1", + "secp256k1 0.30.0", "serde_json", "tokio", "tokio-stream", @@ -3857,6 +3908,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + [[package]] name = "hickory-proto" version = "0.25.0-alpha.5" @@ -4387,11 +4447,11 @@ dependencies = [ [[package]] name = "inotify" -version = "0.9.6" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.8.0", "inotify-sys", "libc", ] @@ -5115,7 +5175,7 @@ dependencies = [ "mach2", "metrics", "once_cell", - "procfs 0.17.0", + "procfs", "rlimit", "windows 0.58.0", ] @@ -5204,18 +5264,6 @@ dependencies = [ "adler2", ] -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", -] - [[package]] name = "mio" version = "1.0.3" @@ -5337,9 +5385,9 @@ dependencies = [ [[package]] name = "notify" -version = "6.1.1" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" dependencies = [ "bitflags 2.8.0", "filetime", @@ -5348,10 +5396,19 @@ dependencies = [ "kqueue", "libc", "log", - "mio 0.8.11", - "serde", + "mio", + "notify-types", "walkdir", - "windows-sys 0.48.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "notify-types" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" +dependencies = [ + "serde", ] [[package]] @@ -5555,7 +5612,7 @@ dependencies = [ "alloy-rlp", "alloy-serde", "arbitrary", - "derive_more", + "derive_more 1.0.0", "serde", "serde_with", "thiserror 2.0.11", @@ -5604,7 +5661,7 @@ dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", "alloy-serde", - "derive_more", + "derive_more 1.0.0", "op-alloy-consensus", "serde", "serde_json", @@ -5621,7 +5678,7 @@ dependencies = [ "alloy-primitives", "alloy-rpc-types-engine", "alloy-serde", - "derive_more", + "derive_more 1.0.0", "ethereum_ssz", "op-alloy-consensus", "serde", @@ -6083,42 +6140,18 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "procfs" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731e0d9356b0c25f16f33b5be79b1c57b562f141ebfcdb0ad8ac2c13a24293b4" -dependencies = [ - "bitflags 2.8.0", - "chrono", - "flate2", - "hex", - "lazy_static", - "procfs-core 0.16.0", - "rustix", -] - [[package]] name = "procfs" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc5b72d8145275d844d4b5f6d4e1eef00c8cd889edb6035c21675d1bb1f45c9f" -dependencies = [ - "bitflags 2.8.0", - "hex", - "procfs-core 0.17.0", - "rustix", -] - -[[package]] -name = "procfs-core" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29" dependencies = [ "bitflags 2.8.0", "chrono", + "flate2", "hex", + "procfs-core", + "rustix", ] [[package]] @@ -6128,6 +6161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "239df02d8349b06fc07398a3a1697b06418223b1c7725085e801e7c0fc6a12ec" dependencies = [ "bitflags 2.8.0", + "chrono", "hex", ] @@ -6412,23 +6446,23 @@ dependencies = [ [[package]] name = "ratatui" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdef7f9be5c0122f890d58bdf4d964349ba6a6161f705907526d891efabba57d" +checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" dependencies = [ "bitflags 2.8.0", "cassowary", "compact_str", "crossterm", + "indoc", "instability", "itertools 0.13.0", "lru 0.12.5", "paste", - "strum", - "strum_macros", + "strum 0.26.3", "unicode-segmentation", "unicode-truncate", - "unicode-width 0.1.14", + "unicode-width 0.2.0", ] [[package]] @@ -6750,7 +6784,7 @@ dependencies = [ "alloy-primitives", "alloy-signer", "alloy-signer-local", - "derive_more", + "derive_more 2.0.1", "metrics", "parking_lot", "pin-project", @@ -6783,7 +6817,7 @@ dependencies = [ "alloy-rlp", "alloy-trie", "auto_impl", - "derive_more", + "derive_more 2.0.1", "reth-ethereum-forks", "reth-network-peers", "reth-primitives-traits", @@ -6821,7 +6855,7 @@ dependencies = [ "fdlimit", "futures", "human_bytes", - "itertools 0.13.0", + "itertools 0.14.0", "proptest", "proptest-arbitrary-interop", "ratatui", @@ -6863,7 +6897,7 @@ dependencies = [ "reth-trie", "reth-trie-common", "reth-trie-db", - "secp256k1", + "secp256k1 0.30.0", "serde", "serde_json", "tokio", @@ -6891,7 +6925,7 @@ dependencies = [ "libc", "rand 0.8.5", "reth-fs-util", - "secp256k1", + "secp256k1 0.30.0", "serde", "snmalloc-rs", "thiserror 2.0.11", @@ -7007,7 +7041,7 @@ dependencies = [ "arbitrary", "assert_matches", "codspeed-criterion-compat", - "derive_more", + "derive_more 2.0.1", "eyre", "metrics", "page_size", @@ -7026,7 +7060,7 @@ dependencies = [ "rustc-hash 2.1.1", "serde", "serde_json", - "strum", + "strum 0.27.1", "sysinfo", "tempfile", "thiserror 2.0.11", @@ -7041,7 +7075,7 @@ dependencies = [ "alloy-primitives", "arbitrary", "bytes", - "derive_more", + "derive_more 2.0.1", "metrics", "modular-bitfield", "parity-scale-codec", @@ -7118,7 +7152,7 @@ dependencies = [ "discv5", "enr", "generic-array", - "itertools 0.13.0", + "itertools 0.14.0", "parking_lot", "rand 0.8.5", "reth-ethereum-forks", @@ -7127,7 +7161,7 @@ dependencies = [ "reth-network-peers", "reth-tracing", "schnellru", - "secp256k1", + "secp256k1 0.30.0", "serde", "thiserror 2.0.11", "tokio", @@ -7141,11 +7175,11 @@ version = "1.2.0" dependencies = [ "alloy-primitives", "alloy-rlp", - "derive_more", + "derive_more 2.0.1", "discv5", "enr", "futures", - "itertools 0.13.0", + "itertools 0.14.0", "metrics", "rand 0.8.5", "reth-chainspec", @@ -7153,7 +7187,7 @@ dependencies = [ "reth-metrics", "reth-network-peers", "reth-tracing", - "secp256k1", + "secp256k1 0.30.0", "thiserror 2.0.11", "tokio", "tracing", @@ -7178,7 +7212,7 @@ dependencies = [ "reth-tokio-util", "reth-tracing", "schnellru", - "secp256k1", + "secp256k1 0.30.0", "serde", "serde_with", "thiserror 2.0.11", @@ -7198,7 +7232,7 @@ dependencies = [ "assert_matches", "futures", "futures-util", - "itertools 0.13.0", + "itertools 0.14.0", "metrics", "pin-project", "rand 0.8.5", @@ -7239,7 +7273,7 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-signer", "alloy-signer-local", - "derive_more", + "derive_more 2.0.1", "eyre", "futures-util", "jsonrpsee", @@ -7291,7 +7325,7 @@ dependencies = [ "pin-project", "rand 0.8.5", "reth-network-peers", - "secp256k1", + "secp256k1 0.30.0", "sha2 0.10.8", "sha3", "thiserror 2.0.11", @@ -7395,7 +7429,7 @@ dependencies = [ "assert_matches", "codspeed-criterion-compat", "crossbeam-channel", - "derive_more", + "derive_more 2.0.1", "futures", "metrics", "mini-moka", @@ -7452,7 +7486,7 @@ dependencies = [ "alloy-rpc-types-engine", "eyre", "futures", - "itertools 0.13.0", + "itertools 0.14.0", "pin-project", "reth-chainspec", "reth-consensus-common", @@ -7499,7 +7533,7 @@ dependencies = [ "arbitrary", "async-stream", "bytes", - "derive_more", + "derive_more 2.0.1", "futures", "pin-project", "proptest", @@ -7514,7 +7548,7 @@ dependencies = [ "reth-primitives", "reth-primitives-traits", "reth-tracing", - "secp256k1", + "secp256k1 0.30.0", "serde", "snap", "test-fuzz", @@ -7537,7 +7571,7 @@ dependencies = [ "alloy-rlp", "arbitrary", "bytes", - "derive_more", + "derive_more 2.0.1", "proptest", "proptest-arbitrary-interop", "rand 0.8.5", @@ -7676,7 +7710,7 @@ dependencies = [ "alloy-serde", "arbitrary", "bincode", - "derive_more", + "derive_more 2.0.1", "modular-bitfield", "proptest", "proptest-arbitrary-interop", @@ -7686,7 +7720,7 @@ dependencies = [ "reth-testing-utils", "reth-zstd-compressors", "revm-context", - "secp256k1", + "secp256k1 0.30.0", "serde", "test-fuzz", ] @@ -7750,7 +7784,7 @@ dependencies = [ "reth-primitives-traits", "reth-revm", "reth-testing-utils", - "secp256k1", + "secp256k1 0.30.0", "serde_json", ] @@ -7776,7 +7810,7 @@ dependencies = [ "alloy-primitives", "arbitrary", "bincode", - "derive_more", + "derive_more 2.0.1", "rand 0.8.5", "reth-ethereum-primitives", "reth-execution-errors", @@ -7798,7 +7832,7 @@ dependencies = [ "alloy-primitives", "eyre", "futures", - "itertools 0.13.0", + "itertools 0.14.0", "metrics", "parking_lot", "rand 0.8.5", @@ -7823,7 +7857,7 @@ dependencies = [ "reth-testing-utils", "reth-tracing", "rmp-serde", - "secp256k1", + "secp256k1 0.30.0", "tempfile", "thiserror 2.0.11", "tokio", @@ -7947,12 +7981,11 @@ dependencies = [ "byteorder", "codspeed-criterion-compat", "dashmap 6.1.0", - "derive_more", + "derive_more 2.0.1", "indexmap 2.7.1", "parking_lot", "pprof", "rand 0.8.5", - "rand_xorshift", "reth-mdbx-sys", "smallvec", "tempfile", @@ -8013,11 +8046,11 @@ dependencies = [ "aquamarine", "auto_impl", "codspeed-criterion-compat", - "derive_more", + "derive_more 2.0.1", "discv5", "enr", "futures", - "itertools 0.13.0", + "itertools 0.14.0", "metrics", "parking_lot", "pin-project", @@ -8050,7 +8083,7 @@ dependencies = [ "reth-transaction-pool", "rustc-hash 2.1.1", "schnellru", - "secp256k1", + "secp256k1 0.30.0", "serde", "serial_test", "smallvec", @@ -8070,7 +8103,7 @@ dependencies = [ "alloy-primitives", "alloy-rpc-types-admin", "auto_impl", - "derive_more", + "derive_more 2.0.1", "enr", "futures", "reth-eth-wire-types", @@ -8093,7 +8126,7 @@ dependencies = [ "alloy-eips", "alloy-primitives", "auto_impl", - "derive_more", + "derive_more 2.0.1", "futures", "parking_lot", "reth-consensus", @@ -8115,7 +8148,7 @@ dependencies = [ "alloy-rlp", "enr", "rand 0.8.5", - "secp256k1", + "secp256k1 0.30.0", "serde_json", "serde_with", "thiserror 2.0.11", @@ -8142,7 +8175,7 @@ version = "1.2.0" dependencies = [ "anyhow", "bincode", - "derive_more", + "derive_more 2.0.1", "lz4_flex", "memmap2", "rand 0.8.5", @@ -8233,7 +8266,7 @@ dependencies = [ "reth-tokio-util", "reth-tracing", "reth-transaction-pool", - "secp256k1", + "secp256k1 0.30.0", "tempfile", "tokio", "tokio-stream", @@ -8249,7 +8282,7 @@ dependencies = [ "alloy-primitives", "alloy-rpc-types-engine", "clap", - "derive_more", + "derive_more 2.0.1", "dirs-next", "eyre", "futures", @@ -8279,10 +8312,10 @@ dependencies = [ "reth-storage-errors", "reth-tracing", "reth-transaction-pool", - "secp256k1", + "secp256k1 0.30.0", "serde", "shellexpand", - "strum", + "strum 0.27.1", "thiserror 2.0.11", "tokio", "toml", @@ -8349,7 +8382,7 @@ dependencies = [ "alloy-eips", "alloy-primitives", "alloy-rpc-types-engine", - "derive_more", + "derive_more 2.0.1", "futures", "humantime", "pin-project", @@ -8375,7 +8408,7 @@ dependencies = [ "metrics-exporter-prometheus", "metrics-process", "metrics-util", - "procfs 0.16.0", + "procfs", "reqwest", "reth-metrics", "reth-tasks", @@ -8384,7 +8417,6 @@ dependencies = [ "tokio", "tower 0.4.13", "tracing", - "vergen", ] [[package]] @@ -8448,7 +8480,7 @@ dependencies = [ "alloy-eips", "alloy-genesis", "alloy-primitives", - "derive_more", + "derive_more 2.0.1", "once_cell", "op-alloy-consensus", "op-alloy-rpc-types", @@ -8471,7 +8503,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "clap", - "derive_more", + "derive_more 2.0.1", "eyre", "futures-util", "op-alloy-consensus", @@ -8551,7 +8583,7 @@ dependencies = [ "alloy-genesis", "alloy-op-evm", "alloy-primitives", - "derive_more", + "derive_more 2.0.1", "op-alloy-consensus", "reth-chainspec", "reth-consensus", @@ -8651,7 +8683,7 @@ dependencies = [ "alloy-rlp", "alloy-rpc-types-debug", "alloy-rpc-types-engine", - "derive_more", + "derive_more 2.0.1", "op-alloy-consensus", "op-alloy-rpc-types-engine", "reth-basic-payload-builder", @@ -8692,7 +8724,7 @@ dependencies = [ "alloy-serde", "arbitrary", "bytes", - "derive_more", + "derive_more 2.0.1", "modular-bitfield", "op-alloy-consensus", "proptest", @@ -8704,7 +8736,7 @@ dependencies = [ "revm-context", "revm-optimism", "rstest", - "secp256k1", + "secp256k1 0.30.0", "serde", ] @@ -8719,7 +8751,7 @@ dependencies = [ "alloy-rpc-types-engine", "alloy-rpc-types-eth", "async-trait", - "derive_more", + "derive_more 2.0.1", "jsonrpsee", "jsonrpsee-core", "jsonrpsee-types", @@ -8781,7 +8813,7 @@ dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", "c-kzg", - "derive_more", + "derive_more 2.0.1", "futures-util", "metrics", "op-alloy-consensus", @@ -8912,7 +8944,7 @@ dependencies = [ "bincode", "byteorder", "bytes", - "derive_more", + "derive_more 2.0.1", "k256", "modular-bitfield", "once_cell", @@ -8926,7 +8958,7 @@ dependencies = [ "revm-bytecode", "revm-primitives", "revm-state", - "secp256k1", + "secp256k1 0.30.0", "serde", "serde_json", "serde_with", @@ -8946,7 +8978,7 @@ dependencies = [ "auto_impl", "dashmap 6.1.0", "eyre", - "itertools 0.13.0", + "itertools 0.14.0", "metrics", "notify", "parking_lot", @@ -8979,7 +9011,7 @@ dependencies = [ "revm-database", "revm-database-interface", "revm-state", - "strum", + "strum 0.27.1", "tempfile", "tokio", "tracing", @@ -8993,7 +9025,7 @@ dependencies = [ "alloy-eips", "alloy-primitives", "assert_matches", - "itertools 0.13.0", + "itertools 0.14.0", "metrics", "rayon", "reth-chainspec", @@ -9024,7 +9056,7 @@ dependencies = [ "alloy-primitives", "arbitrary", "assert_matches", - "derive_more", + "derive_more 2.0.1", "modular-bitfield", "proptest", "proptest-arbitrary-interop", @@ -9076,7 +9108,7 @@ dependencies = [ "alloy-signer", "alloy-signer-local", "async-trait", - "derive_more", + "derive_more 2.0.1", "futures", "http", "http-body", @@ -9308,9 +9340,9 @@ dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", "alloy-sol-types", - "derive_more", + "derive_more 2.0.1", "futures", - "itertools 0.13.0", + "itertools 0.14.0", "jsonrpsee-core", "jsonrpsee-types", "metrics", @@ -9372,7 +9404,7 @@ dependencies = [ "reth-errors", "reth-network-api", "serde", - "strum", + "strum 0.27.1", ] [[package]] @@ -9401,7 +9433,7 @@ dependencies = [ "blake3", "codspeed-criterion-compat", "futures-util", - "itertools 0.13.0", + "itertools 0.14.0", "num-traits", "paste", "pprof", @@ -9521,10 +9553,10 @@ version = "1.2.0" dependencies = [ "alloy-primitives", "clap", - "derive_more", + "derive_more 2.0.1", "reth-nippy-jar", "serde", - "strum", + "strum 0.27.1", ] [[package]] @@ -9556,7 +9588,7 @@ dependencies = [ "alloy-eips", "alloy-primitives", "alloy-rlp", - "derive_more", + "derive_more 2.0.1", "reth-primitives-traits", "reth-prune-types", "reth-static-file-types", @@ -9592,7 +9624,7 @@ dependencies = [ "rand 0.8.5", "reth-primitives", "reth-primitives-traits", - "secp256k1", + "secp256k1 0.30.0", ] [[package]] @@ -9676,7 +9708,7 @@ dependencies = [ "alloy-trie", "auto_impl", "codspeed-criterion-compat", - "itertools 0.13.0", + "itertools 0.14.0", "metrics", "proptest", "proptest-arbitrary-interop", @@ -9710,9 +9742,9 @@ dependencies = [ "bincode", "bytes", "codspeed-criterion-compat", - "derive_more", + "derive_more 2.0.1", "hash-db", - "itertools 0.13.0", + "itertools 0.14.0", "nybbles", "plain_hasher", "proptest", @@ -9734,7 +9766,7 @@ dependencies = [ "alloy-consensus", "alloy-primitives", "alloy-rlp", - "derive_more", + "derive_more 2.0.1", "metrics", "proptest", "proptest-arbitrary-interop", @@ -9764,8 +9796,8 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "codspeed-criterion-compat", - "derive_more", - "itertools 0.13.0", + "derive_more 2.0.1", + "itertools 0.14.0", "metrics", "proptest", "proptest-arbitrary-interop", @@ -9792,7 +9824,7 @@ dependencies = [ "arbitrary", "assert_matches", "codspeed-criterion-compat", - "itertools 0.13.0", + "itertools 0.14.0", "pretty_assertions", "proptest", "proptest-arbitrary-interop", @@ -10002,7 +10034,7 @@ dependencies = [ "revm-primitives", "revm-specification", "ripemd", - "secp256k1", + "secp256k1 0.29.1", "sha2 0.10.8", "substrate-bn", ] @@ -10153,21 +10185,21 @@ checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" [[package]] name = "rstest" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2c585be59b6b5dd66a9d2084aa1d8bd52fbdb806eafdeffb52791147862035" +checksum = "03e905296805ab93e13c1ec3a03f4b6c4f35e9498a3d5fa96dc626d22c03cd89" dependencies = [ - "futures", "futures-timer", + "futures-util", "rstest_macros", "rustc_version 0.4.1", ] [[package]] name = "rstest_macros" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "825ea780781b15345a146be27eaefb05085e337e869bff01b4306a4fd4a9ad5a" +checksum = "ef0053bbffce09062bee4bcc499b0fbe7a57b879f1efe088d6d8d4c7adcdef9b" dependencies = [ "cfg-if", "glob", @@ -10477,6 +10509,17 @@ checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ "rand 0.8.5", "secp256k1-sys", +] + +[[package]] +name = "secp256k1" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" +dependencies = [ + "bitcoin_hashes", + "rand 0.8.5", + "secp256k1-sys", "serde", ] @@ -10574,6 +10617,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_combinators" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de5fb30ae2918667d3cee99ef4b112f1f7ca0a6c58fa349d7d9e76035c72f8b" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.217" @@ -10789,7 +10841,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", - "mio 1.0.3", + "mio", "signal-hook", ] @@ -10994,7 +11046,16 @@ version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ - "strum_macros", + "strum_macros 0.26.4", +] + +[[package]] +name = "strum" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +dependencies = [ + "strum_macros 0.27.1", ] [[package]] @@ -11010,6 +11071,19 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "strum_macros" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.98", +] + [[package]] name = "substrate-bn" version = "0.6.0" @@ -11108,9 +11182,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.32.1" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c33cd241af0f2e9e3b5c32163b873b29956890b5342e6745b917ce9d490f4af" +checksum = "4fc858248ea01b66f19d8e8a6d55f41deaf91e9d495246fd01368d99935c6c01" dependencies = [ "core-foundation-sys", "libc", @@ -11147,11 +11221,12 @@ dependencies = [ [[package]] name = "test-fuzz" -version = "6.0.0" +version = "7.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab7a9bb33d134e863862ab9dad2ac7e022ac89707914627f498fe0f29248d9b" +checksum = "13b092bf18815b5fcfadc8b15d4644d5d68b4d761b32ac1192912e3241aa45f7" dependencies = [ "serde", + "serde_combinators", "test-fuzz-internal", "test-fuzz-macro", "test-fuzz-runtime", @@ -11159,25 +11234,24 @@ dependencies = [ [[package]] name = "test-fuzz-internal" -version = "6.0.0" +version = "7.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bef5dd380747bd7b6e636a8032a24aa34fcecaf843e59fc97d299681922e86" +checksum = "f04fc3fa0293849f8762c3e8427cb11a73b8bfc2157f2713029d93df554da052" dependencies = [ "bincode", - "cargo_metadata 0.18.1", + "cargo_metadata 0.19.1", "serde", ] [[package]] name = "test-fuzz-macro" -version = "6.0.0" +version = "7.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7e6b4c7391a38f0f026972ec2200bcfd1ec45533aa266fdae5858d011afc500" +checksum = "fcc398c37df7cf559845f32bcf694b3984e0378887dc2e177775a7a918ee7110" dependencies = [ "darling", "heck", - "itertools 0.13.0", - "once_cell", + "itertools 0.14.0", "prettyplease", "proc-macro2", "quote", @@ -11186,9 +11260,9 @@ dependencies = [ [[package]] name = "test-fuzz-runtime" -version = "6.0.0" +version = "7.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9fbe6fb7481ec6d9bf64ae2c5d49cb1b40f8da624a91031482af7b08168c679" +checksum = "2dede21a17233c03fdb704ea831e4a6b52da877f54e8bc273f74eee47903d446" dependencies = [ "hex", "num-traits", @@ -11380,7 +11454,7 @@ dependencies = [ "backtrace", "bytes", "libc", - "mio 1.0.3", + "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -11688,9 +11762,9 @@ dependencies = [ [[package]] name = "tracy-client" -version = "0.17.6" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73202d787346a5418f8222eddb5a00f29ea47caf3c7d38a8f2f69f8455fa7c7e" +checksum = "d90a2c01305b02b76fdd89ac8608bae27e173c829a35f7d76a345ab5d33836db" dependencies = [ "loom", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index c63166f6cd09..b5106249534a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -502,7 +502,7 @@ bytes = { version = "1.5", default-features = false } cfg-if = "1.0" clap = "4" dashmap = "6.0" -derive_more = { version = "1", default-features = false, features = ["full"] } +derive_more = { version = "2", default-features = false, features = ["full"] } dirs-next = "2.0.0" dyn-clone = "1.0.17" eyre = "0.6" @@ -510,10 +510,10 @@ fdlimit = "0.3.0" generic-array = "0.14" humantime = "2.1" humantime-serde = "1.1" -itertools = { version = "0.13", default-features = false } +itertools = { version = "0.14", default-features = false } linked_hash_set = "0.1" modular-bitfield = "0.11.2" -notify = { version = "6.1.1", default-features = false, features = ["macos_fsevent"] } +notify = { version = "8.0.0", default-features = false, features = ["macos_fsevent"] } nybbles = { version = "0.3.0", default-features = false } once_cell = { version = "1.19", default-features = false, features = ["critical-section"] } parking_lot = "0.12" @@ -528,7 +528,7 @@ serde_with = { version = "3", default-features = false, features = ["macros"] } sha2 = { version = "0.10", default-features = false } shellexpand = "3.0.0" smallvec = "1" -strum = { version = "0.26", default-features = false } +strum = { version = "0.27", default-features = false } syn = "2.0" thiserror = { version = "2.0.0", default-features = false } tracing = "0.1.0" @@ -569,7 +569,7 @@ tower = "0.4" tower-http = "0.6" # p2p -discv5 = "0.8.0" +discv5 = "0.9" if-addrs = "0.13" # rpc @@ -587,9 +587,9 @@ jsonwebtoken = "9" proptest-arbitrary-interop = "0.1.0" # crypto -enr = { version = "0.12.1", default-features = false } +enr = { version = "0.13", default-features = false } k256 = { version = "0.13", default-features = false, features = ["ecdsa"] } -secp256k1 = { version = "0.29", default-features = false, features = ["global-context", "recovery"] } +secp256k1 = { version = "0.30", default-features = false, features = ["global-context", "recovery"] } # for eip-4844 c-kzg = "1.0.0" @@ -607,13 +607,13 @@ proptest-derive = "0.5" serial_test = { default-features = false, version = "3" } similar-asserts = { version = "1.5.0", features = ["serde"] } tempfile = "3.8" -test-fuzz = "6" -rstest = "0.23.0" +test-fuzz = "7" +rstest = "0.24.0" # allocators tikv-jemalloc-ctl = "0.6" tikv-jemallocator = "0.6" -tracy-client = "0.17.3" +tracy-client = "0.18.0" snmalloc-rs = { version = "0.3.7", features = ["build_cc"] } # TODO: When we build for a windows target on an ubuntu runner, crunchy tries to diff --git a/crates/cli/commands/Cargo.toml b/crates/cli/commands/Cargo.toml index 9e6136f489c8..a4fc4dd982b7 100644 --- a/crates/cli/commands/Cargo.toml +++ b/crates/cli/commands/Cargo.toml @@ -68,7 +68,7 @@ serde.workspace = true serde_json.workspace = true tracing.workspace = true backon.workspace = true -secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery"] } +secp256k1 = { workspace = true, features = ["global-context", "std", "recovery"] } # io fdlimit.workspace = true @@ -77,7 +77,7 @@ toml = { workspace = true, features = ["display"] } # tui comfy-table = "7.0" crossterm = "0.28.0" -ratatui = { version = "0.28", default-features = false, features = ["crossterm"] } +ratatui = { version = "0.29", default-features = false, features = ["crossterm"] } # reth test-vectors proptest = { workspace = true, optional = true } diff --git a/crates/net/discv4/Cargo.toml b/crates/net/discv4/Cargo.toml index dfd2c6eb63dd..5d5ec73782f9 100644 --- a/crates/net/discv4/Cargo.toml +++ b/crates/net/discv4/Cargo.toml @@ -22,7 +22,7 @@ reth-network-peers = { workspace = true, features = ["secp256k1"] } alloy-primitives = { workspace = true, features = ["rand"] } alloy-rlp = { workspace = true, features = ["derive"] } discv5.workspace = true -secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery", "serde"] } +secp256k1 = { workspace = true, features = ["global-context", "std", "recovery", "serde"] } enr.workspace = true # async/futures diff --git a/crates/net/discv4/src/proto.rs b/crates/net/discv4/src/proto.rs index 97546f4fe1cb..b9ec6cbfa919 100644 --- a/crates/net/discv4/src/proto.rs +++ b/crates/net/discv4/src/proto.rs @@ -122,7 +122,7 @@ impl Message { // Serialize the signature and append it to the signature bytes let (rec, sig) = signature.serialize_compact(); sig_bytes.extend_from_slice(&sig); - sig_bytes.put_u8(rec.to_i32() as u8); + sig_bytes.put_u8(i32::from(rec) as u8); sig_bytes.unsplit(payload); // Calculate the hash of the signature bytes and append it to the datagram @@ -156,7 +156,7 @@ impl Message { } let signature = &packet[32..96]; - let recovery_id = RecoveryId::from_i32(packet[96] as i32)?; + let recovery_id = RecoveryId::try_from(packet[96] as i32)?; let recoverable_sig = RecoverableSignature::from_compact(signature, recovery_id)?; // recover the public key diff --git a/crates/net/discv5/Cargo.toml b/crates/net/discv5/Cargo.toml index 329f04cb73aa..6c59f422431c 100644 --- a/crates/net/discv5/Cargo.toml +++ b/crates/net/discv5/Cargo.toml @@ -42,4 +42,4 @@ metrics.workspace = true [dev-dependencies] reth-tracing.workspace = true tokio = { workspace = true, features = ["rt-multi-thread"] } -secp256k1 = { workspace = true, features = ["rand-std"] } +secp256k1 = { workspace = true, features = ["std", "rand"] } diff --git a/crates/net/discv5/src/lib.rs b/crates/net/discv5/src/lib.rs index da54d0b52663..267a5f63c3ce 100644 --- a/crates/net/discv5/src/lib.rs +++ b/crates/net/discv5/src/lib.rs @@ -655,8 +655,8 @@ pub async fn lookup( mod test { use super::*; use ::enr::{CombinedKey, EnrKey}; + use rand::thread_rng; use reth_chainspec::MAINNET; - use secp256k1::rand::thread_rng; use tracing::trace; fn discv5_noop() -> Discv5 { @@ -729,16 +729,12 @@ mod test { node_1.with_discv5(|discv5| discv5.send_ping(node_2_enr.clone())).await.unwrap(); // verify node_1:discv5 is connected to node_2:discv5 and vv - let event_2_v5 = stream_2.recv().await.unwrap(); let event_1_v5 = stream_1.recv().await.unwrap(); + assert!(matches!( event_1_v5, discv5::Event::SessionEstablished(node, socket) if node == node_2_enr && socket == node_2_enr.udp4_socket().unwrap().into() )); - assert!(matches!( - event_2_v5, - discv5::Event::SessionEstablished(node, socket) if node == node_1_enr && socket == node_1_enr.udp4_socket().unwrap().into() - )); // verify node_1 is in KBuckets of node_2:discv5 let event_2_v5 = stream_2.recv().await.unwrap(); diff --git a/crates/net/dns/Cargo.toml b/crates/net/dns/Cargo.toml index 0c8d30d0e945..d078d434ad9d 100644 --- a/crates/net/dns/Cargo.toml +++ b/crates/net/dns/Cargo.toml @@ -19,7 +19,7 @@ reth-tokio-util = { workspace = true, features = ["time"] } # ethereum alloy-primitives.workspace = true -secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery", "serde"] } +secp256k1 = { workspace = true, features = ["global-context", "std", "recovery", "serde"] } enr.workspace = true # async/futures @@ -27,7 +27,7 @@ tokio = { workspace = true, features = ["io-util", "net", "time"] } tokio-stream.workspace = true # trust-dns -hickory-resolver = { version = "0.25.0-alpha.4" } +hickory-resolver = { version = "0.25.0-alpha.5" } # misc data-encoding = "2" diff --git a/crates/net/ecies/Cargo.toml b/crates/net/ecies/Cargo.toml index ec34e3e7a323..9880162b9aa5 100644 --- a/crates/net/ecies/Cargo.toml +++ b/crates/net/ecies/Cargo.toml @@ -34,7 +34,7 @@ byteorder.workspace = true rand.workspace = true ctr = "0.9.2" digest = "0.10.5" -secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery"] } +secp256k1 = { workspace = true, features = ["global-context", "std", "recovery", "rand"] } concat-kdf = "0.1.0" sha2.workspace = true sha3 = "0.10.5" diff --git a/crates/net/ecies/src/algorithm.rs b/crates/net/ecies/src/algorithm.rs index 3abc7cbb2671..bd27de3e0876 100644 --- a/crates/net/ecies/src/algorithm.rs +++ b/crates/net/ecies/src/algorithm.rs @@ -421,7 +421,7 @@ impl ECIES { let mut sig_bytes = [0u8; 65]; sig_bytes[..64].copy_from_slice(&sig); - sig_bytes[64] = rec_id.to_i32() as u8; + sig_bytes[64] = i32::from(rec_id) as u8; let id = pk2id(&self.public_key); @@ -479,7 +479,7 @@ impl ECIES { let sigdata = data.get_next::<[u8; 65]>()?.ok_or(ECIESErrorImpl::InvalidAuthData)?; let signature = RecoverableSignature::from_compact( &sigdata[..64], - RecoveryId::from_i32(sigdata[64] as i32)?, + RecoveryId::try_from(sigdata[64] as i32)?, )?; let remote_id = data.get_next()?.ok_or(ECIESErrorImpl::InvalidAuthData)?; self.remote_id = Some(remote_id); diff --git a/crates/net/eth-wire/Cargo.toml b/crates/net/eth-wire/Cargo.toml index 049029b6988d..9a01f4607cf7 100644 --- a/crates/net/eth-wire/Cargo.toml +++ b/crates/net/eth-wire/Cargo.toml @@ -53,7 +53,7 @@ test-fuzz.workspace = true tokio = { workspace = true, features = ["rt", "rt-multi-thread"] } tokio-util = { workspace = true, features = ["io", "codec"] } rand.workspace = true -secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery"] } +secp256k1 = { workspace = true, features = ["global-context", "std", "recovery"] } arbitrary = { workspace = true, features = ["derive"] } proptest.workspace = true diff --git a/crates/net/network/Cargo.toml b/crates/net/network/Cargo.toml index 39bbb9f0e103..be53fbc2cb72 100644 --- a/crates/net/network/Cargo.toml +++ b/crates/net/network/Cargo.toml @@ -65,7 +65,7 @@ rustc-hash.workspace = true thiserror.workspace = true parking_lot.workspace = true rand.workspace = true -secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery"] } +secp256k1 = { workspace = true, features = ["global-context", "std", "recovery"] } derive_more.workspace = true schnellru.workspace = true itertools.workspace = true @@ -96,6 +96,7 @@ alloy-consensus.workspace = true serial_test.workspace = true tempfile.workspace = true url.workspace = true +secp256k1 = { workspace = true, features = ["rand"] } ## Benchmarks pprof = { workspace = true, features = ["criterion", "flamegraph"] } diff --git a/crates/node/builder/Cargo.toml b/crates/node/builder/Cargo.toml index 38f3f0a3ace5..7158a7bc6362 100644 --- a/crates/node/builder/Cargo.toml +++ b/crates/node/builder/Cargo.toml @@ -68,7 +68,7 @@ tokio = { workspace = true, features = ["sync", "macros", "time", "rt-multi-thre tokio-stream.workspace = true ## crypto -secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery"] } +secp256k1 = { workspace = true, features = ["global-context", "std", "recovery"] } ## misc aquamarine.workspace = true diff --git a/crates/node/core/Cargo.toml b/crates/node/core/Cargo.toml index fe488afc3d46..4743a722b63a 100644 --- a/crates/node/core/Cargo.toml +++ b/crates/node/core/Cargo.toml @@ -61,7 +61,7 @@ shellexpand.workspace = true tracing.workspace = true # crypto -secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery"] } +secp256k1 = { workspace = true, features = ["global-context", "std", "recovery"] } # async futures.workspace = true diff --git a/crates/node/metrics/Cargo.toml b/crates/node/metrics/Cargo.toml index 3d79d11db7d7..afb6bf10c46d 100644 --- a/crates/node/metrics/Cargo.toml +++ b/crates/node/metrics/Cargo.toml @@ -29,7 +29,7 @@ eyre.workspace = true tikv-jemalloc-ctl = { workspace = true, optional = true, features = ["stats"] } [target.'cfg(target_os = "linux")'.dependencies] -procfs = "0.16.0" +procfs = "0.17.0" [dev-dependencies] reqwest.workspace = true @@ -40,6 +40,3 @@ workspace = true [features] jemalloc = ["dep:tikv-jemalloc-ctl"] - -[build-dependencies] -vergen = { version = "8.0.0", features = ["build", "cargo", "git", "gitcl"] } diff --git a/crates/optimism/chainspec/src/lib.rs b/crates/optimism/chainspec/src/lib.rs index e90d621d8afd..82c530db9e11 100644 --- a/crates/optimism/chainspec/src/lib.rs +++ b/crates/optimism/chainspec/src/lib.rs @@ -25,7 +25,7 @@ use alloy_genesis::Genesis; use alloy_primitives::{B256, U256}; pub use base::BASE_MAINNET; pub use base_sepolia::BASE_SEPOLIA; -use derive_more::{Constructor, Deref, Display, From, Into}; +use derive_more::{Constructor, Deref, From, Into}; pub use dev::OP_DEV; pub use op::OP_MAINNET; pub use op_sepolia::OP_SEPOLIA; @@ -215,7 +215,7 @@ impl EthChainSpec for OpChainSpec { self.inner.prune_delete_limit() } - fn display_hardforks(&self) -> Box { + fn display_hardforks(&self) -> Box { Box::new(ChainSpec::display_hardforks(self)) } diff --git a/crates/optimism/primitives/src/transaction/signed.rs b/crates/optimism/primitives/src/transaction/signed.rs index e087c6cb5a3a..859c962e521b 100644 --- a/crates/optimism/primitives/src/transaction/signed.rs +++ b/crates/optimism/primitives/src/transaction/signed.rs @@ -17,6 +17,7 @@ use alloy_rlp::Header; use core::{ hash::{Hash, Hasher}, mem, + ops::Deref, }; use derive_more::{AsRef, Deref}; use op_alloy_consensus::{ diff --git a/crates/primitives-traits/src/crypto.rs b/crates/primitives-traits/src/crypto.rs index 0f59b97db4d8..6b022a6cabbd 100644 --- a/crates/primitives-traits/src/crypto.rs +++ b/crates/primitives-traits/src/crypto.rs @@ -81,7 +81,7 @@ mod impl_secp256k1 { msg: &[u8; 32], ) -> Result { let sig = - RecoverableSignature::from_compact(&sig[0..64], RecoveryId::from_i32(sig[64] as i32)?)?; + RecoverableSignature::from_compact(&sig[0..64], RecoveryId::try_from(sig[64] as i32)?)?; let public = SECP256K1.recover_ecdsa(&Message::from_digest(*msg), &sig)?; Ok(public_key_to_address(public)) @@ -97,7 +97,7 @@ mod impl_secp256k1 { let signature = Signature::new( U256::try_from_be_slice(&data[..32]).expect("The slice has at most 32 bytes"), U256::try_from_be_slice(&data[32..64]).expect("The slice has at most 32 bytes"), - rec_id.to_i32() != 0, + i32::from(rec_id) != 0, ); Ok(signature) } diff --git a/crates/storage/codecs/derive/Cargo.toml b/crates/storage/codecs/derive/Cargo.toml index f62587faa938..f27ce7b30cba 100644 --- a/crates/storage/codecs/derive/Cargo.toml +++ b/crates/storage/codecs/derive/Cargo.toml @@ -15,7 +15,7 @@ workspace = true proc-macro = true [dependencies] -convert_case = "0.6.0" +convert_case = "0.7.0" proc-macro2.workspace = true quote.workspace = true syn.workspace = true diff --git a/crates/storage/db/Cargo.toml b/crates/storage/db/Cargo.toml index 35b2b4a2cba6..1762cfab7424 100644 --- a/crates/storage/db/Cargo.toml +++ b/crates/storage/db/Cargo.toml @@ -37,7 +37,7 @@ thiserror.workspace = true tempfile = { workspace = true, optional = true } derive_more.workspace = true rustc-hash = { workspace = true, optional = true } -sysinfo = { version = "0.32", default-features = false, features = ["system"] } +sysinfo = { version = "0.33", default-features = false, features = ["system"] } parking_lot = { workspace = true, optional = true } # arbitrary utils diff --git a/crates/storage/db/src/lockfile.rs b/crates/storage/db/src/lockfile.rs index c44f88790d5f..a1a9946b570d 100644 --- a/crates/storage/db/src/lockfile.rs +++ b/crates/storage/db/src/lockfile.rs @@ -112,7 +112,7 @@ impl ProcessUID { system.refresh_processes_specifics( sysinfo::ProcessesToUpdate::Some(&[pid2]), true, - ProcessRefreshKind::new(), + ProcessRefreshKind::nothing(), ); system.process(pid2).map(|process| Self { pid, start_time: process.start_time() }) } @@ -141,9 +141,11 @@ impl ProcessUID { /// Whether a process with this `pid` and `start_time` exists. fn is_active(&self) -> bool { - System::new_with_specifics(RefreshKind::new().with_processes(ProcessRefreshKind::new())) - .process(self.pid.into()) - .is_some_and(|p| p.start_time() == self.start_time) + System::new_with_specifics( + RefreshKind::nothing().with_processes(ProcessRefreshKind::nothing()), + ) + .process(self.pid.into()) + .is_some_and(|p| p.start_time() == self.start_time) } /// Writes `pid` and `start_time` to a file. diff --git a/crates/storage/libmdbx-rs/Cargo.toml b/crates/storage/libmdbx-rs/Cargo.toml index 7e8626348726..a61b884ae61e 100644 --- a/crates/storage/libmdbx-rs/Cargo.toml +++ b/crates/storage/libmdbx-rs/Cargo.toml @@ -34,7 +34,6 @@ read-tx-timeouts = ["dep:dashmap"] pprof = { workspace = true, features = ["flamegraph", "frame-pointer", "criterion"] } criterion.workspace = true rand.workspace = true -rand_xorshift = "0.3" tempfile.workspace = true [[bench]] diff --git a/crates/storage/libmdbx-rs/benches/transaction.rs b/crates/storage/libmdbx-rs/benches/transaction.rs index eb4b0671b7fa..e230e13f4117 100644 --- a/crates/storage/libmdbx-rs/benches/transaction.rs +++ b/crates/storage/libmdbx-rs/benches/transaction.rs @@ -2,8 +2,7 @@ mod utils; use criterion::{criterion_group, criterion_main, Criterion}; -use rand::{prelude::SliceRandom, SeedableRng}; -use rand_xorshift::XorShiftRng; +use rand::{prelude::SliceRandom, rngs::StdRng, SeedableRng}; use reth_libmdbx::{ffi::*, ObjectLength, WriteFlags}; use std::{hint::black_box, ptr}; use utils::*; @@ -15,7 +14,7 @@ fn bench_get_rand(c: &mut Criterion) { let db = txn.open_db(None).unwrap(); let mut keys: Vec = (0..n).map(get_key).collect(); - keys.shuffle(&mut XorShiftRng::from_seed(Default::default())); + keys.shuffle(&mut StdRng::from_seed(Default::default())); c.bench_function("bench_get_rand", |b| { b.iter(|| { @@ -35,7 +34,7 @@ fn bench_get_rand_raw(c: &mut Criterion) { let db = txn.open_db(None).unwrap(); let mut keys: Vec = (0..n).map(get_key).collect(); - keys.shuffle(&mut XorShiftRng::from_seed(Default::default())); + keys.shuffle(&mut StdRng::from_seed(Default::default())); let dbi = db.dbi(); @@ -71,7 +70,7 @@ fn bench_put_rand(c: &mut Criterion) { let db = txn.commit_and_rebind_open_dbs().unwrap().2.remove(0); let mut items: Vec<(String, String)> = (0..n).map(|n| (get_key(n), get_data(n))).collect(); - items.shuffle(&mut XorShiftRng::from_seed(Default::default())); + items.shuffle(&mut StdRng::from_seed(Default::default())); c.bench_function("bench_put_rand", |b| { b.iter(|| { @@ -88,7 +87,7 @@ fn bench_put_rand_raw(c: &mut Criterion) { let (_dir, env) = setup_bench_db(0); let mut items: Vec<(String, String)> = (0..n).map(|n| (get_key(n), get_data(n))).collect(); - items.shuffle(&mut XorShiftRng::from_seed(Default::default())); + items.shuffle(&mut StdRng::from_seed(Default::default())); let dbi = env.begin_ro_txn().unwrap().open_db(None).unwrap().dbi(); diff --git a/crates/trie/db/src/prefix_set.rs b/crates/trie/db/src/prefix_set.rs index 08ab9cba4001..9d2cf8a28d81 100644 --- a/crates/trie/db/src/prefix_set.rs +++ b/crates/trie/db/src/prefix_set.rs @@ -2,8 +2,10 @@ use alloy_primitives::{ map::{HashMap, HashSet}, BlockNumber, B256, }; -use core::{marker::PhantomData, ops::RangeInclusive}; -use derive_more::Deref; +use core::{ + marker::PhantomData, + ops::{Deref, RangeInclusive}, +}; use reth_db_api::{ cursor::DbCursorRO, models::{AccountBeforeTx, BlockNumberAddress}, diff --git a/examples/bsc-p2p/Cargo.toml b/examples/bsc-p2p/Cargo.toml index d5a7c982da53..4201fde726ab 100644 --- a/examples/bsc-p2p/Cargo.toml +++ b/examples/bsc-p2p/Cargo.toml @@ -16,7 +16,7 @@ reth-network-peers.workspace = true reth-primitives.workspace = true reth-tracing.workspace = true -secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery"] } +secp256k1 = { workspace = true, features = ["global-context", "std", "recovery"] } tokio.workspace = true tokio-stream.workspace = true diff --git a/examples/manual-p2p/Cargo.toml b/examples/manual-p2p/Cargo.toml index b1642f66ca04..eaaa211cd161 100644 --- a/examples/manual-p2p/Cargo.toml +++ b/examples/manual-p2p/Cargo.toml @@ -16,7 +16,7 @@ reth-network-peers.workspace = true alloy-consensus.workspace = true -secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery"] } +secp256k1 = { workspace = true, features = ["global-context", "std", "recovery"] } futures.workspace = true tokio.workspace = true diff --git a/examples/polygon-p2p/Cargo.toml b/examples/polygon-p2p/Cargo.toml index 5daa8149b6d4..d0e856b973ac 100644 --- a/examples/polygon-p2p/Cargo.toml +++ b/examples/polygon-p2p/Cargo.toml @@ -8,7 +8,7 @@ license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery"] } +secp256k1 = { workspace = true, features = ["global-context", "std", "recovery"] } tokio.workspace = true reth-network.workspace = true reth-chainspec.workspace = true From 1ae733a7d11d6ca3f1d838c2595d7f253f4f1fa2 Mon Sep 17 00:00:00 2001 From: Solar Mithril Date: Wed, 19 Feb 2025 13:18:37 +0100 Subject: [PATCH 14/21] Add interop hardfork in all relevant places. (#14582) --- crates/optimism/chainspec/src/lib.rs | 9 +++++++++ crates/optimism/evm/src/config.rs | 7 +++++++ crates/optimism/hardforks/src/hardfork.rs | 11 +++++++++-- crates/optimism/hardforks/src/lib.rs | 6 ++++++ crates/optimism/payload/src/builder.rs | 5 +++++ 5 files changed, 36 insertions(+), 2 deletions(-) diff --git a/crates/optimism/chainspec/src/lib.rs b/crates/optimism/chainspec/src/lib.rs index 82c530db9e11..e96403b5740f 100644 --- a/crates/optimism/chainspec/src/lib.rs +++ b/crates/optimism/chainspec/src/lib.rs @@ -159,6 +159,13 @@ impl OpChainSpecBuilder { self } + /// Enable Interop at genesis + pub fn interop_activated(mut self) -> Self { + self = self.isthmus_activated(); + self.inner = self.inner.with_fork(OpHardfork::Interop, ForkCondition::Timestamp(0)); + self + } + /// Build the resulting [`OpChainSpec`]. /// /// # Panics @@ -329,6 +336,7 @@ impl From for OpChainSpec { (OpHardfork::Granite.boxed(), genesis_info.granite_time), (OpHardfork::Holocene.boxed(), genesis_info.holocene_time), (OpHardfork::Isthmus.boxed(), genesis_info.isthmus_time), + // (OpHardfork::Interop.boxed(), genesis_info.interop_time), ]; let mut time_hardforks = time_hardfork_opts @@ -982,6 +990,7 @@ mod tests { OpHardfork::Granite.boxed(), OpHardfork::Holocene.boxed(), // OpHardfork::Isthmus.boxed(), + // OpHardfork::Interop.boxed(), ]; for (expected, actual) in expected_hardforks.iter().zip(hardforks.iter()) { diff --git a/crates/optimism/evm/src/config.rs b/crates/optimism/evm/src/config.rs index 6375ceb3c5ef..3e380021c41d 100644 --- a/crates/optimism/evm/src/config.rs +++ b/crates/optimism/evm/src/config.rs @@ -17,6 +17,9 @@ pub fn revm_spec_by_timestamp_after_bedrock( chain_spec: impl OpHardforks, timestamp: u64, ) -> OpSpecId { + // if chain_spec.is_interop_active_at_timestamp(timestamp) { + // OpSpecId::INTEROP + // } else if chain_spec.is_isthmus_active_at_timestamp(timestamp) { OpSpecId::ISTHMUS } else if chain_spec.is_holocene_active_at_timestamp(timestamp) { @@ -49,6 +52,10 @@ mod tests { let cs = ChainSpecBuilder::mainnet().chain(reth_chainspec::Chain::from_id(10)).into(); f(cs).build() } + // assert_eq!( + // revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.interop_activated()), 0), + // OpSpecId::INTEROP + // ); assert_eq!( revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.isthmus_activated()), 0), OpSpecId::ISTHMUS diff --git a/crates/optimism/hardforks/src/hardfork.rs b/crates/optimism/hardforks/src/hardfork.rs index 313fd67dde6f..5afade45094c 100644 --- a/crates/optimism/hardforks/src/hardfork.rs +++ b/crates/optimism/hardforks/src/hardfork.rs @@ -35,6 +35,8 @@ hardfork!( Holocene, /// Isthmus: Isthmus, + /// TODO: add interop hardfork overview when available + Interop, } ); @@ -162,6 +164,7 @@ impl OpHardfork { Self::Granite => Some(1723478400), Self::Holocene => Some(1732633200), Self::Isthmus => todo!(), + Self::Interop => todo!(), }, ) } @@ -198,6 +201,7 @@ impl OpHardfork { Self::Granite => Some(1726070401), Self::Holocene => Some(1736445601), Self::Isthmus => todo!(), + Self::Interop => todo!(), }, ) } @@ -378,8 +382,10 @@ mod tests { #[test] fn check_op_hardfork_from_str() { - let hardfork_str = - ["beDrOck", "rEgOlITH", "cAnYoN", "eCoToNe", "FJorD", "GRaNiTe", "hOlOcEnE", "isthMUS"]; + let hardfork_str = [ + "beDrOck", "rEgOlITH", "cAnYoN", "eCoToNe", "FJorD", "GRaNiTe", "hOlOcEnE", "isthMUS", + "inTerOP", + ]; let expected_hardforks = [ OpHardfork::Bedrock, OpHardfork::Regolith, @@ -389,6 +395,7 @@ mod tests { OpHardfork::Granite, OpHardfork::Holocene, OpHardfork::Isthmus, + OpHardfork::Interop, ]; let hardforks: Vec = diff --git a/crates/optimism/hardforks/src/lib.rs b/crates/optimism/hardforks/src/lib.rs index fbe77aa20a7a..3379116830b8 100644 --- a/crates/optimism/hardforks/src/lib.rs +++ b/crates/optimism/hardforks/src/lib.rs @@ -69,4 +69,10 @@ pub trait OpHardforks: EthereumHardforks { fn is_isthmus_active_at_timestamp(&self, timestamp: u64) -> bool { self.op_fork_activation(OpHardfork::Isthmus).active_at_timestamp(timestamp) } + + /// Returns `true` if [`Interop`](OpHardfork::Interop) is active at given block + /// timestamp. + fn is_interop_active_at_timestamp(&self, timestamp: u64) -> bool { + self.op_fork_activation(OpHardfork::Interop).active_at_timestamp(timestamp) + } } diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index 34ff1f7152c3..46bf3a55c3f6 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -793,6 +793,11 @@ where self.chain_spec.is_isthmus_active_at_timestamp(self.attributes().timestamp()) } + /// Returns true if interop is active for the payload. + pub fn is_interop_active(&self) -> bool { + self.chain_spec.is_interop_active_at_timestamp(self.attributes().timestamp()) + } + /// Returns true if the fees are higher than the previous payload. pub fn is_better_payload(&self, total_fees: U256) -> bool { is_better_payload(self.best_payload.as_ref(), total_fees) From 4f454c91d649e2435bd5992f6c55e6097fe6175d Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Wed, 19 Feb 2025 17:10:50 +0400 Subject: [PATCH 15/21] refactor: `BlockExecutionStrategy` API (#14480) --- Cargo.lock | 5 +- .../engine/invalid-block-hooks/src/witness.rs | 7 +- crates/engine/tree/src/tree/mod.rs | 2 +- crates/engine/util/src/reorg.rs | 2 +- crates/ethereum/evm/Cargo.toml | 7 +- crates/ethereum/evm/src/execute.rs | 185 ++++++------- crates/ethereum/evm/src/lib.rs | 15 +- crates/ethereum/payload/src/lib.rs | 2 +- crates/evm/Cargo.toml | 5 +- crates/evm/execution-types/src/execute.rs | 2 +- crates/evm/src/execute.rs | 252 +++++++----------- crates/evm/src/lib.rs | 12 +- crates/evm/src/system_calls/mod.rs | 13 +- crates/evm/src/test_utils.rs | 18 +- crates/optimism/evm/src/execute.rs | 196 ++++++-------- crates/optimism/evm/src/lib.rs | 15 +- crates/optimism/payload/src/builder.rs | 4 +- crates/optimism/rpc/src/eth/pending_block.rs | 12 +- crates/rpc/rpc-eth-api/src/helpers/call.rs | 23 +- .../rpc-eth-api/src/helpers/pending_block.rs | 13 +- crates/rpc/rpc-eth-api/src/helpers/trace.rs | 10 +- crates/rpc/rpc-eth-types/src/simulate.rs | 10 +- crates/rpc/rpc/src/debug.rs | 16 +- crates/rpc/rpc/src/eth/bundle.rs | 2 +- .../rpc/rpc/src/eth/helpers/pending_block.rs | 13 +- crates/rpc/rpc/src/eth/sim_bundle.rs | 21 +- crates/rpc/rpc/src/trace.rs | 2 +- .../custom-beacon-withdrawals/src/main.rs | 91 +++---- examples/custom-evm/src/main.rs | 10 +- examples/stateful-precompile/src/main.rs | 11 +- 30 files changed, 422 insertions(+), 554 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 93cec435ccdb..4b0cb1c71237 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7744,12 +7744,12 @@ dependencies = [ "alloy-evm", "alloy-primitives", "auto_impl", + "derive_more 2.0.1", "futures-util", "metrics", "metrics-util", "parking_lot", "reth-chainspec", - "reth-consensus", "reth-consensus-common", "reth-ethereum-forks", "reth-ethereum-primitives", @@ -7774,9 +7774,8 @@ dependencies = [ "alloy-genesis", "alloy-primitives", "alloy-sol-types", + "derive_more 2.0.1", "reth-chainspec", - "reth-consensus", - "reth-ethereum-consensus", "reth-ethereum-forks", "reth-evm", "reth-execution-types", diff --git a/crates/engine/invalid-block-hooks/src/witness.rs b/crates/engine/invalid-block-hooks/src/witness.rs index 8257baca3465..e6cc6b98a4db 100644 --- a/crates/engine/invalid-block-hooks/src/witness.rs +++ b/crates/engine/invalid-block-hooks/src/witness.rs @@ -8,7 +8,6 @@ use reth_evm::{ state_change::post_block_balance_increments, system_calls::SystemCaller, ConfigureEvmFor, Evm, }; use reth_primitives::{NodePrimitives, RecoveredBlock, SealedHeader}; -use reth_primitives_traits::{BlockBody, SignedTransaction}; use reth_provider::{BlockExecutionOutput, ChainSpecProvider, StateProviderFactory}; use reth_revm::{ database::StateProviderDatabase, @@ -85,10 +84,8 @@ where // Re-execute all of the transactions in the block to load all touched accounts into // the cache DB. - for tx in block.body().transactions() { - let signer = - tx.recover_signer().map_err(|_| eyre::eyre!("failed to recover sender"))?; - evm.transact_commit(self.evm_config.tx_env(tx, signer))?; + for tx in block.transactions_recovered() { + evm.transact_commit(self.evm_config.tx_env(tx))?; } drop(evm); diff --git a/crates/engine/tree/src/tree/mod.rs b/crates/engine/tree/src/tree/mod.rs index 912daa72b7bb..ca5b262d9d44 100644 --- a/crates/engine/tree/src/tree/mod.rs +++ b/crates/engine/tree/src/tree/mod.rs @@ -2775,7 +2775,7 @@ where let mut evm = evm_config.evm_with_env(state_provider, evm_env); // create the tx env and reset nonce - let tx_env = evm_config.tx_env(&tx, tx.signer()); + let tx_env = evm_config.tx_env(&tx); // exit early if execution is done if cancel_execution.is_cancelled() { diff --git a/crates/engine/util/src/reorg.rs b/crates/engine/util/src/reorg.rs index b79da3f6c42f..a5e9e291b8f2 100644 --- a/crates/engine/util/src/reorg.rs +++ b/crates/engine/util/src/reorg.rs @@ -312,7 +312,7 @@ where // Configure the environment for the block. let tx_recovered = tx.try_clone_into_recovered().map_err(|_| ProviderError::SenderRecoveryError)?; - let tx_env = evm_config.tx_env(&tx_recovered, tx_recovered.signer()); + let tx_env = evm_config.tx_env(tx_recovered); let exec_result = match evm.transact(tx_env) { Ok(result) => result, Err(err) if err.is_invalid_tx_err() => { diff --git a/crates/ethereum/evm/Cargo.toml b/crates/ethereum/evm/Cargo.toml index d456b69e5b45..2926f18d3753 100644 --- a/crates/ethereum/evm/Cargo.toml +++ b/crates/ethereum/evm/Cargo.toml @@ -12,13 +12,12 @@ workspace = true [dependencies] # Reth +reth-execution-types.workspace = true reth-chainspec.workspace = true reth-ethereum-forks.workspace = true reth-revm.workspace = true reth-evm.workspace = true reth-primitives.workspace = true -reth-ethereum-consensus.workspace = true -reth-consensus.workspace = true # Ethereum reth-primitives-traits.workspace = true @@ -30,6 +29,8 @@ alloy-evm.workspace = true alloy-sol-types.workspace = true alloy-consensus.workspace = true +derive_more.workspace = true + [dev-dependencies] reth-testing-utils.workspace = true reth-evm = { workspace = true, features = ["test-utils"] } @@ -43,7 +44,6 @@ alloy-genesis.workspace = true [features] default = ["std"] std = [ - "reth-consensus/std", "reth-primitives/std", "reth-revm/std", "alloy-consensus/std", @@ -58,4 +58,5 @@ std = [ "alloy-evm/std", "reth-execution-types/std", "reth-evm/std", + "derive_more/std", ] diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index f4427dd4a005..efb3e0db1931 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -8,19 +8,20 @@ use alloc::{boxed::Box, sync::Arc, vec::Vec}; use alloy_consensus::{BlockHeader, Transaction}; use alloy_eips::{eip6110, eip7685::Requests}; use reth_chainspec::{ChainSpec, EthereumHardfork, EthereumHardforks, MAINNET}; -use reth_consensus::ConsensusError; -use reth_ethereum_consensus::validate_block_post_execution; use reth_evm::{ execute::{ balance_increment_state, BasicBlockExecutorProvider, BlockExecutionError, - BlockExecutionStrategy, BlockExecutionStrategyFactory, BlockValidationError, ExecuteOutput, + BlockExecutionStrategy, BlockExecutionStrategyFactory, BlockValidationError, }, state_change::post_block_balance_increments, system_calls::{OnStateHook, StateChangePostBlockSource, StateChangeSource, SystemCaller}, - ConfigureEvm, Database, Evm, + ConfigureEvm, ConfigureEvmEnv, Database, Evm, }; -use reth_primitives::{EthPrimitives, Receipt, RecoveredBlock}; -use reth_primitives_traits::{BlockBody, SignedTransaction}; +use reth_execution_types::BlockExecutionResult; +use reth_primitives::{ + EthPrimitives, Receipt, Recovered, RecoveredBlock, SealedBlock, TransactionSigned, +}; +use reth_primitives_traits::NodePrimitives; use reth_revm::{context_interface::result::ResultAndState, db::State, DatabaseCommit}; /// Factory for [`EthExecutionStrategy`]. @@ -46,7 +47,7 @@ impl EthExecutionStrategyFactory { impl EthExecutionStrategyFactory { /// Creates a new executor strategy factory. - pub const fn new(chain_spec: Arc, evm_config: EvmConfig) -> Self { + pub fn new(chain_spec: Arc, evm_config: EvmConfig) -> Self { Self { chain_spec, evm_config } } } @@ -65,113 +66,108 @@ where { type Primitives = EthPrimitives; - type Strategy = EthExecutionStrategy; - - fn create_strategy(&self, db: DB) -> Self::Strategy + fn create_strategy<'a, DB>( + &'a mut self, + db: &'a mut State, + block: &'a RecoveredBlock<::Block>, + ) -> impl BlockExecutionStrategy + 'a where DB: Database, { - let state = - State::builder().with_database(db).with_bundle_update().without_state_clear().build(); - EthExecutionStrategy::new(state, self.chain_spec.clone(), self.evm_config.clone()) + let evm = self.evm_config.evm_for_block(db, block.header()); + EthExecutionStrategy::new(evm, block.sealed_block(), self) } } /// Block execution strategy for Ethereum. -#[allow(missing_debug_implementations)] -pub struct EthExecutionStrategy -where - EvmConfig: Clone, -{ - /// The chainspec - chain_spec: Arc, - /// How to create an EVM. - evm_config: EvmConfig, - /// Current state for block execution. - state: State, +#[derive(Debug, derive_more::Deref)] +pub struct EthExecutionStrategy<'a, Evm, EvmConfig> { + /// Reference to the parent factory providing access to [`ChainSpec`]. + #[deref] + factory: &'a EthExecutionStrategyFactory, + + /// Block being executed. + block: &'a SealedBlock, + /// The EVM used by strategy. + evm: Evm, + /// Receipts of executed transactions. + receipts: Vec, /// Utility to call system smart contracts. - system_caller: SystemCaller>, + system_caller: SystemCaller<&'a ChainSpec>, } -impl EthExecutionStrategy -where - EvmConfig: Clone, -{ +impl<'a, Evm, EvmConfig> EthExecutionStrategy<'a, Evm, EvmConfig> { /// Creates a new [`EthExecutionStrategy`] - pub fn new(state: State, chain_spec: Arc, evm_config: EvmConfig) -> Self { - let system_caller = SystemCaller::new(chain_spec.clone()); - Self { state, chain_spec, evm_config, system_caller } + pub fn new( + evm: Evm, + block: &'a SealedBlock, + factory: &'a EthExecutionStrategyFactory, + ) -> Self { + Self { + evm, + factory, + block, + receipts: Vec::new(), + system_caller: SystemCaller::new(&factory.chain_spec), + } } } -impl BlockExecutionStrategy for EthExecutionStrategy +impl<'db, DB, E, EvmConfig> BlockExecutionStrategy for EthExecutionStrategy<'_, E, EvmConfig> where - DB: Database, - EvmConfig: ConfigureEvm< - Header = alloy_consensus::Header, - Transaction = reth_primitives::TransactionSigned, - >, + DB: Database + 'db, + E: Evm, Tx = EvmConfig::TxEnv>, + EvmConfig: ConfigureEvmEnv, { - type DB = DB; type Error = BlockExecutionError; type Primitives = EthPrimitives; - fn apply_pre_execution_changes( - &mut self, - block: &RecoveredBlock, - ) -> Result<(), Self::Error> { + fn apply_pre_execution_changes(&mut self) -> Result<(), Self::Error> { // Set state clear flag if the block is after the Spurious Dragon hardfork. - let state_clear_flag = self.chain_spec.is_spurious_dragon_active_at_block(block.number()); - self.state.set_state_clear_flag(state_clear_flag); - - let mut evm = self.evm_config.evm_for_block(&mut self.state, block.header()); - - self.system_caller.apply_pre_execution_changes(block.header(), &mut evm)?; + let state_clear_flag = + self.chain_spec.is_spurious_dragon_active_at_block(self.block.number()); + self.evm.db_mut().set_state_clear_flag(state_clear_flag); + self.system_caller.apply_pre_execution_changes(self.block.header(), &mut self.evm)?; Ok(()) } - fn execute_transactions( + fn execute_transactions<'a>( &mut self, - block: &RecoveredBlock, - ) -> Result, Self::Error> { - let mut evm = self.evm_config.evm_for_block(&mut self.state, block.header()); - + transactions: impl IntoIterator>, + ) -> Result<(), Self::Error> { let mut cumulative_gas_used = 0; - let mut receipts = Vec::with_capacity(block.body().transaction_count()); - for (tx_index, (sender, transaction)) in block.transactions_with_sender().enumerate() { + for (tx_index, tx) in transactions.into_iter().enumerate() { // The sum of the transaction's gas limit, Tg, and the gas utilized in this block prior, // must be no greater than the block's gasLimit. - let block_available_gas = block.gas_limit() - cumulative_gas_used; - if transaction.gas_limit() > block_available_gas { + let block_available_gas = self.block.gas_limit() - cumulative_gas_used; + if tx.gas_limit() > block_available_gas { return Err(BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas { - transaction_gas_limit: transaction.gas_limit(), + transaction_gas_limit: tx.gas_limit(), block_available_gas, } .into()) } - let tx_env = self.evm_config.tx_env(transaction, *sender); + let tx_env = self.evm_config.tx_env(tx.clone()); + let hash = tx.hash(); // Execute transaction. - let result_and_state = evm.transact(tx_env).map_err(move |err| { + let result_and_state = self.evm.transact(tx_env).map_err(move |err| { // Ensure hash is calculated for error log, if not already done - BlockValidationError::EVM { - hash: transaction.recalculate_hash(), - error: Box::new(err), - } + BlockValidationError::EVM { hash: *hash, error: Box::new(err) } })?; self.system_caller .on_state(StateChangeSource::Transaction(tx_index), &result_and_state.state); let ResultAndState { result, state } = result_and_state; - evm.db_mut().commit(state); + self.evm.db_mut().commit(state); // append gas used cumulative_gas_used += result.gas_used(); // Push transaction changeset and calculate header bloom filter for receipt. - receipts.push(Receipt { - tx_type: transaction.tx_type(), + self.receipts.push(Receipt { + tx_type: tx.tx_type(), // Success flag was added in `EIP-658: Embedding transaction status code in // receipts`. success: result.is_success(), @@ -179,20 +175,16 @@ where logs: result.into_logs(), }); } - Ok(ExecuteOutput { receipts, gas_used: cumulative_gas_used }) + Ok(()) } fn apply_post_execution_changes( - &mut self, - block: &RecoveredBlock, - receipts: &[Receipt], - ) -> Result { - let mut evm = self.evm_config.evm_for_block(&mut self.state, block.header()); - - let requests = if self.chain_spec.is_prague_active_at_timestamp(block.timestamp) { + mut self, + ) -> Result, Self::Error> { + let requests = if self.chain_spec.is_prague_active_at_timestamp(self.block.timestamp) { // Collect all EIP-6110 deposits let deposit_requests = - crate::eip6110::parse_deposits_from_receipts(&self.chain_spec, receipts)?; + crate::eip6110::parse_deposits_from_receipts(&self.chain_spec, &self.receipts)?; let mut requests = Requests::default(); @@ -200,20 +192,20 @@ where requests.push_request_with_type(eip6110::DEPOSIT_REQUEST_TYPE, deposit_requests); } - requests.extend(self.system_caller.apply_post_execution_changes(&mut evm)?); + requests.extend(self.system_caller.apply_post_execution_changes(&mut self.evm)?); requests } else { Requests::default() }; - drop(evm); - let mut balance_increments = post_block_balance_increments(&self.chain_spec, block); + let mut balance_increments = post_block_balance_increments(&self.chain_spec, self.block); // Irregular state change at Ethereum DAO hardfork - if self.chain_spec.fork(EthereumHardfork::Dao).transitions_at_block(block.number()) { + if self.chain_spec.fork(EthereumHardfork::Dao).transitions_at_block(self.block.number()) { // drain balances from hardcoded addresses. let drained_balance: u128 = self - .state + .evm + .db_mut() .drain_balances(DAO_HARDFORK_ACCOUNTS) .map_err(|_| BlockValidationError::IncrementBalanceFailed)? .into_iter() @@ -223,43 +215,24 @@ where *balance_increments.entry(DAO_HARDFORK_BENEFICIARY).or_default() += drained_balance; } // increment balances - self.state + self.evm + .db_mut() .increment_balances(balance_increments.clone()) .map_err(|_| BlockValidationError::IncrementBalanceFailed)?; // call state hook with changes due to balance increments. - let balance_state = balance_increment_state(&balance_increments, &mut self.state)?; + let balance_state = balance_increment_state(&balance_increments, self.evm.db_mut())?; self.system_caller.on_state( StateChangeSource::PostBlock(StateChangePostBlockSource::BalanceIncrements), &balance_state, ); - Ok(requests) - } - - fn state_ref(&self) -> &State { - &self.state - } - - fn state_mut(&mut self) -> &mut State { - &mut self.state - } - - fn into_state(self) -> State { - self.state + let gas_used = self.receipts.last().map(|r| r.cumulative_gas_used).unwrap_or_default(); + Ok(BlockExecutionResult { receipts: self.receipts, requests, gas_used }) } fn with_state_hook(&mut self, hook: Option>) { self.system_caller.with_state_hook(hook); } - - fn validate_block_post_execution( - &self, - block: &RecoveredBlock, - receipts: &[Receipt], - requests: &Requests, - ) -> Result<(), ConsensusError> { - validate_block_post_execution(block, &self.chain_spec.clone(), receipts, requests) - } } /// Helper type with backwards compatible methods to obtain Ethereum executor diff --git a/crates/ethereum/evm/src/lib.rs b/crates/ethereum/evm/src/lib.rs index 33c8a8ee2a62..3b7c3244d282 100644 --- a/crates/ethereum/evm/src/lib.rs +++ b/crates/ethereum/evm/src/lib.rs @@ -17,11 +17,11 @@ extern crate alloc; -use alloc::sync::Arc; -use alloy_consensus::{BlockHeader, Header}; +use alloc::{borrow::Borrow, sync::Arc}; +use alloy_consensus::{transaction::Recovered, BlockHeader, Header}; pub use alloy_evm::EthEvm; use alloy_evm::EthEvmFactory; -use alloy_primitives::{Address, U256}; +use alloy_primitives::U256; use core::{convert::Infallible, fmt::Debug}; use reth_chainspec::{ChainSpec, EthChainSpec, MAINNET}; use reth_evm::{ConfigureEvm, ConfigureEvmEnv, EvmEnv, NextBlockEnvAttributes}; @@ -77,9 +77,14 @@ impl ConfigureEvmEnv for EthEvmConfig { type TxEnv = TxEnv; type Spec = SpecId; - fn tx_env(&self, transaction: &TransactionSigned, sender: Address) -> Self::TxEnv { + fn tx_env>( + &self, + transaction: impl Borrow>, + ) -> Self::TxEnv { + let transaction = transaction.borrow(); + let mut tx_env = TxEnv::default(); - transaction.fill_tx_env(&mut tx_env, sender); + transaction.tx().borrow().fill_tx_env(&mut tx_env, transaction.signer()); tx_env } diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index d659012d54f7..60b022ba6c54 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -279,7 +279,7 @@ where } // Configure the environment for the tx. - let tx_env = evm_config.tx_env(tx.tx(), tx.signer()); + let tx_env = evm_config.tx_env(&tx); let ResultAndState { result, state } = match evm.transact(tx_env) { Ok(res) => res, diff --git a/crates/evm/Cargo.toml b/crates/evm/Cargo.toml index 032d92e02fe9..f5a52da5a816 100644 --- a/crates/evm/Cargo.toml +++ b/crates/evm/Cargo.toml @@ -13,7 +13,6 @@ workspace = true [dependencies] # reth reth-chainspec.workspace = true -reth-consensus.workspace = true reth-consensus-common.workspace = true reth-execution-errors.workspace = true reth-execution-types.workspace = true @@ -34,6 +33,7 @@ alloy-evm.workspace = true alloy-consensus.workspace = true auto_impl.workspace = true +derive_more.workspace = true futures-util.workspace = true metrics = { workspace = true, optional = true } parking_lot = { workspace = true, optional = true } @@ -47,7 +47,6 @@ metrics-util = { workspace = true, features = ["debugging"] } [features] default = ["std"] std = [ - "reth-consensus/std", "reth-primitives/std", "reth-primitives-traits/std", "alloy-eips/std", @@ -65,6 +64,7 @@ std = [ "reth-execution-types/std", "reth-storage-errors/std", "futures-util/std", + "derive_more/std", ] metrics = [ "std", @@ -74,7 +74,6 @@ metrics = [ test-utils = [ "dep:parking_lot", "reth-chainspec/test-utils", - "reth-consensus/test-utils", "reth-ethereum-primitives/test-utils", "reth-primitives/test-utils", "reth-primitives-traits/test-utils", diff --git a/crates/evm/execution-types/src/execute.rs b/crates/evm/execution-types/src/execute.rs index eadb68aa89ec..0f4da96e5bca 100644 --- a/crates/evm/execution-types/src/execute.rs +++ b/crates/evm/execution-types/src/execute.rs @@ -3,7 +3,7 @@ use alloy_eips::eip7685::Requests; use revm_database::BundleState; /// The result of executing a block. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct BlockExecutionResult { /// All the receipts of the transactions in the block. pub receipts: Vec, diff --git a/crates/evm/src/execute.rs b/crates/evm/src/execute.rs index 1a75bad5a10a..40d7a5892505 100644 --- a/crates/evm/src/execute.rs +++ b/crates/evm/src/execute.rs @@ -2,22 +2,19 @@ use alloy_consensus::BlockHeader; // Re-export execution types -pub use reth_execution_errors::{ - BlockExecutionError, BlockValidationError, InternalBlockExecutionError, -}; -use reth_execution_types::BlockExecutionResult; -pub use reth_execution_types::{BlockExecutionOutput, ExecutionOutcome}; -pub use reth_storage_errors::provider::ProviderError; - use crate::{system_calls::OnStateHook, Database}; use alloc::{boxed::Box, vec::Vec}; -use alloy_eips::eip7685::Requests; use alloy_primitives::{ map::{DefaultHashBuilder, HashMap}, Address, }; -use reth_consensus::ConsensusError; -use reth_primitives::{NodePrimitives, Receipt, RecoveredBlock}; +pub use reth_execution_errors::{ + BlockExecutionError, BlockValidationError, InternalBlockExecutionError, +}; +use reth_execution_types::BlockExecutionResult; +pub use reth_execution_types::{BlockExecutionOutput, ExecutionOutcome}; +use reth_primitives::{NodePrimitives, Receipt, Recovered, RecoveredBlock}; +pub use reth_storage_errors::provider::ProviderError; use revm::state::{Account, AccountStatus, EvmState}; use revm_database::{states::bundle_state::BundleRetention, State}; @@ -167,9 +164,6 @@ pub struct ExecuteOutput { /// Defines the strategy for executing a single block. pub trait BlockExecutionStrategy { - /// Database this strategy operates on. - type DB: revm::Database; - /// Primitive types used by the strategy. type Primitives: NodePrimitives; @@ -177,45 +171,23 @@ pub trait BlockExecutionStrategy { type Error: core::error::Error; /// Applies any necessary changes before executing the block's transactions. - fn apply_pre_execution_changes( - &mut self, - block: &RecoveredBlock<::Block>, - ) -> Result<(), Self::Error>; + fn apply_pre_execution_changes(&mut self) -> Result<(), Self::Error>; /// Executes all transactions in the block. - fn execute_transactions( + fn execute_transactions<'a>( &mut self, - block: &RecoveredBlock<::Block>, - ) -> Result::Receipt>, Self::Error>; + transactions: impl IntoIterator< + Item = Recovered<&'a ::SignedTx>, + >, + ) -> Result<(), Self::Error>; /// Applies any necessary changes after executing the block's transactions. fn apply_post_execution_changes( - &mut self, - block: &RecoveredBlock<::Block>, - receipts: &[::Receipt], - ) -> Result; - - /// Returns a reference to the current state. - fn state_ref(&self) -> &State; - - /// Returns a mutable reference to the current state. - fn state_mut(&mut self) -> &mut State; - - /// Consumes the strategy and returns inner [`State`]. - fn into_state(self) -> State; + self, + ) -> Result::Receipt>, Self::Error>; /// Sets a hook to be called after each state change during execution. - fn with_state_hook(&mut self, _hook: Option>) {} - - /// Validate a block with regard to execution results. - fn validate_block_post_execution( - &self, - _block: &RecoveredBlock<::Block>, - _receipts: &[::Receipt], - _requests: &Requests, - ) -> Result<(), ConsensusError> { - Ok(()) - } + fn with_state_hook(&mut self, hook: Option>); } /// A strategy factory that can create block execution strategies. @@ -223,15 +195,12 @@ pub trait BlockExecutionStrategyFactory: Send + Sync + Clone + Unpin + 'static { /// Primitive types used by the strategy. type Primitives: NodePrimitives; - /// Associated strategy type. - type Strategy: BlockExecutionStrategy< - DB = DB, - Primitives = Self::Primitives, - Error = BlockExecutionError, - >; - - /// Creates a strategy using the give database. - fn create_strategy(&self, db: DB) -> Self::Strategy + /// Creates a strategy using the given database. + fn create_strategy<'a, DB>( + &'a mut self, + db: &'a mut State, + block: &'a RecoveredBlock<::Block>, + ) -> impl BlockExecutionStrategy + 'a where DB: Database; } @@ -264,74 +233,85 @@ where { type Primitives = F::Primitives; - type Executor = BasicBlockExecutor>; + type Executor = BasicBlockExecutor; fn executor(&self, db: DB) -> Self::Executor where DB: Database, { - let strategy = self.strategy_factory.create_strategy(db); - BasicBlockExecutor::new(strategy) + BasicBlockExecutor::new(self.strategy_factory.clone(), db) } } /// A generic block executor that uses a [`BlockExecutionStrategy`] to /// execute blocks. #[allow(missing_debug_implementations, dead_code)] -pub struct BasicBlockExecutor { +pub struct BasicBlockExecutor { /// Block execution strategy. - pub(crate) strategy: S, + pub(crate) strategy_factory: F, + /// Database. + pub(crate) db: State, } -impl BasicBlockExecutor { +impl BasicBlockExecutor { /// Creates a new `BasicBlockExecutor` with the given strategy. - pub const fn new(strategy: S) -> Self { - Self { strategy } + pub fn new(strategy_factory: F, db: DB) -> Self { + let db = + State::builder().with_database(db).with_bundle_update().without_state_clear().build(); + Self { strategy_factory, db } } } -impl Executor for BasicBlockExecutor +impl Executor for BasicBlockExecutor where - S: BlockExecutionStrategy, + F: BlockExecutionStrategyFactory, DB: Database, { - type Primitives = S::Primitives; - type Error = S::Error; + type Primitives = F::Primitives; + type Error = BlockExecutionError; fn execute_one( &mut self, block: &RecoveredBlock<::Block>, ) -> Result::Receipt>, Self::Error> { - self.strategy.apply_pre_execution_changes(block)?; - let ExecuteOutput { receipts, gas_used } = self.strategy.execute_transactions(block)?; - let requests = self.strategy.apply_post_execution_changes(block, &receipts)?; - self.strategy.state_mut().merge_transitions(BundleRetention::Reverts); + let mut strategy = self.strategy_factory.create_strategy(&mut self.db, block); + + strategy.apply_pre_execution_changes()?; + strategy.execute_transactions(block.transactions_recovered())?; + let result = strategy.apply_post_execution_changes()?; + + self.db.merge_transitions(BundleRetention::Reverts); - Ok(BlockExecutionResult { receipts, requests, gas_used }) + Ok(result) } - fn execute_one_with_state_hook( + fn execute_one_with_state_hook( &mut self, block: &RecoveredBlock<::Block>, - state_hook: F, + state_hook: H, ) -> Result::Receipt>, Self::Error> where - F: OnStateHook + 'static, + H: OnStateHook + 'static, { - self.strategy.with_state_hook(Some(Box::new(state_hook))); - let result = self.execute_one(block); - self.strategy.with_state_hook(None); + let mut strategy = self.strategy_factory.create_strategy(&mut self.db, block); + strategy.with_state_hook(Some(Box::new(state_hook))); + + strategy.apply_pre_execution_changes()?; + strategy.execute_transactions(block.transactions_recovered())?; + let result = strategy.apply_post_execution_changes()?; - result + self.db.merge_transitions(BundleRetention::Reverts); + + Ok(result) } fn into_state(self) -> State { - self.strategy.into_state() + self.db } fn size_hint(&self) -> usize { - self.strategy.state_ref().bundle_state.size_hint() + self.db.bundle_state.size_hint() } } @@ -374,17 +354,14 @@ where #[cfg(test)] mod tests { use super::*; - use alloy_primitives::U256; + use alloy_consensus::constants::KECCAK_EMPTY; + use alloy_eips::eip7685::Requests; + use alloy_primitives::{address, bytes, U256}; use core::marker::PhantomData; - use reth_chainspec::{ChainSpec, MAINNET}; + use reth_ethereum_primitives::TransactionSigned; use reth_primitives::EthPrimitives; - use revm::{ - database_interface::EmptyDBTyped, - primitives::{address, bytes, KECCAK_EMPTY}, - state::AccountInfo, - }; - use revm_database::CacheDB; - use std::sync::Arc; + use revm::state::AccountInfo; + use revm_database::{CacheDB, EmptyDBTyped}; #[derive(Clone, Default)] struct TestExecutorProvider; @@ -435,94 +412,55 @@ mod tests { } } - struct TestExecutorStrategy { - // chain spec and evm config here only to illustrate how the strategy - // factory can use them in a real use case. - _chain_spec: Arc, - _evm_config: EvmConfig, - state: State, - execute_transactions_result: ExecuteOutput, - apply_post_execution_changes_result: Requests, + struct TestExecutorStrategy { + result: BlockExecutionResult, } #[derive(Clone)] struct TestExecutorStrategyFactory { - execute_transactions_result: ExecuteOutput, - apply_post_execution_changes_result: Requests, + result: BlockExecutionResult, } impl BlockExecutionStrategyFactory for TestExecutorStrategyFactory { type Primitives = EthPrimitives; - type Strategy = TestExecutorStrategy; - fn create_strategy(&self, db: DB) -> Self::Strategy + fn create_strategy<'a, DB>( + &'a mut self, + _db: &'a mut State, + _block: &'a RecoveredBlock<::Block>, + ) -> impl BlockExecutionStrategy + 'a where DB: Database, { - let state = State::builder() - .with_database(db) - .with_bundle_update() - .without_state_clear() - .build(); - - TestExecutorStrategy { - _chain_spec: MAINNET.clone(), - _evm_config: TestEvmConfig {}, - execute_transactions_result: self.execute_transactions_result.clone(), - apply_post_execution_changes_result: self - .apply_post_execution_changes_result - .clone(), - state, - } + TestExecutorStrategy { result: self.result.clone() } } } - impl BlockExecutionStrategy for TestExecutorStrategy - where - DB: Database, - { - type DB = DB; + impl BlockExecutionStrategy for TestExecutorStrategy { type Primitives = EthPrimitives; type Error = BlockExecutionError; - fn apply_pre_execution_changes( - &mut self, - _block: &RecoveredBlock, - ) -> Result<(), Self::Error> { + fn apply_pre_execution_changes(&mut self) -> Result<(), Self::Error> { Ok(()) } - fn execute_transactions( + fn execute_transactions<'a>( &mut self, - _block: &RecoveredBlock, - ) -> Result, Self::Error> { - Ok(self.execute_transactions_result.clone()) + _transactions: impl IntoIterator>, + ) -> Result<(), Self::Error> { + Ok(()) } fn apply_post_execution_changes( - &mut self, - _block: &RecoveredBlock, - _receipts: &[Receipt], - ) -> Result { - Ok(self.apply_post_execution_changes_result.clone()) - } - - fn state_ref(&self) -> &State { - &self.state - } - - fn state_mut(&mut self) -> &mut State { - &mut self.state + self, + ) -> Result::Receipt>, Self::Error> + { + Ok(self.result) } - fn into_state(self) -> State { - self.state - } + fn with_state_hook(&mut self, _hook: Option>) {} } - #[derive(Clone)] - struct TestEvmConfig {} - #[test] fn test_provider() { let provider = TestExecutorProvider; @@ -533,19 +471,13 @@ mod tests { #[test] fn test_strategy() { - let expected_gas_used = 10; - let expected_receipts = vec![Receipt::default()]; - let expected_execute_transactions_result = ExecuteOutput:: { - receipts: expected_receipts.clone(), - gas_used: expected_gas_used, + let expected_result = BlockExecutionResult { + receipts: vec![Receipt::default()], + gas_used: 10, + requests: Requests::new(vec![bytes!("deadbeef")]), }; - let expected_apply_post_execution_changes_result = Requests::new(vec![bytes!("deadbeef")]); - let strategy_factory = TestExecutorStrategyFactory { - execute_transactions_result: expected_execute_transactions_result, - apply_post_execution_changes_result: expected_apply_post_execution_changes_result - .clone(), - }; + let strategy_factory = TestExecutorStrategyFactory { result: expected_result.clone() }; let provider = BasicBlockExecutorProvider::new(strategy_factory); let db = CacheDB::>::default(); let executor = provider.executor(db); @@ -553,9 +485,7 @@ mod tests { assert!(result.is_ok()); let block_execution_output = result.unwrap(); - assert_eq!(block_execution_output.gas_used, expected_gas_used); - assert_eq!(block_execution_output.receipts, expected_receipts); - assert_eq!(block_execution_output.requests, expected_apply_post_execution_changes_result); + assert_eq!(block_execution_output.result, expected_result); } fn setup_state_with_account( diff --git a/crates/evm/src/lib.rs b/crates/evm/src/lib.rs index 5bb93218bc64..1c5f27f77d81 100644 --- a/crates/evm/src/lib.rs +++ b/crates/evm/src/lib.rs @@ -17,6 +17,7 @@ extern crate alloc; +use alloc::borrow::Borrow; use alloy_consensus::transaction::Recovered; use alloy_eips::eip2930::AccessList; pub use alloy_evm::evm::EvmFactory; @@ -182,13 +183,10 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static { type Spec: Debug + Copy + Send + Sync + 'static; /// Returns a [`TxEnv`] from a transaction and [`Address`]. - fn tx_env(&self, transaction: &Self::Transaction, signer: Address) -> Self::TxEnv; - - /// Returns a [`TxEnv`] from a [`Recovered`] transaction. - fn tx_env_from_recovered(&self, tx: Recovered<&Self::Transaction>) -> Self::TxEnv { - let (tx, address) = tx.into_parts(); - self.tx_env(tx, address) - } + fn tx_env>( + &self, + transaction: impl Borrow>, + ) -> Self::TxEnv; /// Creates a new [`EvmEnv`] for the given header. fn evm_env(&self, header: &Self::Header) -> EvmEnv; diff --git a/crates/evm/src/system_calls/mod.rs b/crates/evm/src/system_calls/mod.rs index 53f194740c28..802dd8f5e861 100644 --- a/crates/evm/src/system_calls/mod.rs +++ b/crates/evm/src/system_calls/mod.rs @@ -77,10 +77,11 @@ impl OnStateHook for NoopHook { /// An ephemeral helper type for executing system calls. /// /// This can be used to chain system transaction calls. -#[allow(missing_debug_implementations)] +#[derive(derive_more::Debug)] pub struct SystemCaller { chain_spec: ChainSpec, /// Optional hook to be called after each state change. + #[debug(skip)] hook: Option>, } @@ -149,7 +150,7 @@ where eip2935::transact_blockhashes_contract_call(&self.chain_spec, parent_block_hash, evm)?; if let Some(res) = result_and_state { - if let Some(ref mut hook) = self.hook { + if let Some(hook) = &mut self.hook { hook.on_state( StateChangeSource::PreBlock(StateChangePreBlockSource::BlockHashesContract), &res.state, @@ -174,7 +175,7 @@ where )?; if let Some(res) = result_and_state { - if let Some(ref mut hook) = self.hook { + if let Some(hook) = &mut self.hook { hook.on_state( StateChangeSource::PreBlock(StateChangePreBlockSource::BeaconRootContract), &res.state, @@ -193,7 +194,7 @@ where ) -> Result { let result_and_state = eip7002::transact_withdrawal_requests_contract_call(evm)?; - if let Some(ref mut hook) = self.hook { + if let Some(ref mut hook) = &mut self.hook { hook.on_state( StateChangeSource::PostBlock( StateChangePostBlockSource::WithdrawalRequestsContract, @@ -213,7 +214,7 @@ where ) -> Result { let result_and_state = eip7251::transact_consolidation_requests_contract_call(evm)?; - if let Some(ref mut hook) = self.hook { + if let Some(ref mut hook) = &mut self.hook { hook.on_state( StateChangeSource::PostBlock( StateChangePostBlockSource::ConsolidationRequestsContract, @@ -228,7 +229,7 @@ where /// Delegate to stored `OnStateHook`, noop if hook is `None`. pub fn on_state(&mut self, source: StateChangeSource, state: &EvmState) { - if let Some(ref mut hook) = &mut self.hook { + if let Some(hook) = &mut self.hook { hook.on_state(source, state); } } diff --git a/crates/evm/src/test_utils.rs b/crates/evm/src/test_utils.rs index cb9645988cf5..c7546ac53228 100644 --- a/crates/evm/src/test_utils.rs +++ b/crates/evm/src/test_utils.rs @@ -1,10 +1,7 @@ //! Helpers for testing. use crate::{ - execute::{ - BasicBlockExecutor, BlockExecutionOutput, BlockExecutionStrategy, BlockExecutorProvider, - Executor, - }, + execute::{BasicBlockExecutor, BlockExecutionOutput, BlockExecutorProvider, Executor}, system_calls::OnStateHook, Database, }; @@ -125,23 +122,20 @@ impl Executor for MockExecutorProvider { } } -impl BasicBlockExecutor -where - S: BlockExecutionStrategy, -{ +impl BasicBlockExecutor { /// Provides safe read access to the state pub fn with_state(&self, f: F) -> R where - F: FnOnce(&State) -> R, + F: FnOnce(&State) -> R, { - f(self.strategy.state_ref()) + f(&self.db) } /// Provides safe write access to the state pub fn with_state_mut(&mut self, f: F) -> R where - F: FnOnce(&mut State) -> R, + F: FnOnce(&mut State) -> R, { - f(self.strategy.state_mut()) + f(&mut self.db) } } diff --git a/crates/optimism/evm/src/execute.rs b/crates/optimism/evm/src/execute.rs index 6e0d948559e3..f038fe619143 100644 --- a/crates/optimism/evm/src/execute.rs +++ b/crates/optimism/evm/src/execute.rs @@ -5,24 +5,24 @@ use crate::{ OpReceiptBuilder, ReceiptBuilderCtx, }; use alloc::{boxed::Box, sync::Arc, vec::Vec}; -use alloy_consensus::{BlockHeader, Eip658Value, Receipt, Transaction as _}; -use alloy_eips::eip7685::Requests; +use alloy_consensus::{ + transaction::Recovered, BlockHeader, Eip658Value, Receipt, Transaction as _, TxReceipt, +}; use op_alloy_consensus::OpDepositReceipt; -use reth_consensus::ConsensusError; use reth_evm::{ execute::{ balance_increment_state, BasicBlockExecutorProvider, BlockExecutionError, - BlockExecutionStrategy, BlockExecutionStrategyFactory, BlockValidationError, ExecuteOutput, + BlockExecutionStrategy, BlockExecutionStrategyFactory, BlockValidationError, }, state_change::post_block_balance_increments, system_calls::{OnStateHook, StateChangePostBlockSource, StateChangeSource, SystemCaller}, ConfigureEvm, ConfigureEvmFor, Database, Evm, HaltReasonFor, }; +use reth_execution_types::BlockExecutionResult; use reth_optimism_chainspec::OpChainSpec; -use reth_optimism_consensus::validate_block_post_execution; use reth_optimism_forks::OpHardforks; use reth_optimism_primitives::{transaction::signed::OpTransaction, DepositReceipt, OpPrimitives}; -use reth_primitives_traits::{BlockBody, NodePrimitives, RecoveredBlock, SignedTransaction}; +use reth_primitives_traits::{NodePrimitives, RecoveredBlock, SealedBlock, SignedTransaction}; use revm::{context_interface::result::ResultAndState, DatabaseCommit}; use revm_database::State; use tracing::trace; @@ -79,43 +79,38 @@ where EvmConfig: ConfigureEvmFor + Clone + Unpin + Sync + Send + 'static, { type Primitives = N; - type Strategy = OpExecutionStrategy; - fn create_strategy(&self, db: DB) -> Self::Strategy + fn create_strategy<'a, DB>( + &'a mut self, + db: &'a mut State, + block: &'a RecoveredBlock<::Block>, + ) -> impl BlockExecutionStrategy + 'a where DB: Database, { - let state = - State::builder().with_database(db).with_bundle_update().without_state_clear().build(); - OpExecutionStrategy::new( - state, - self.chain_spec.clone(), - self.evm_config.clone(), - self.receipt_builder.clone(), - ) + let evm = self.evm_config.evm_for_block(db, block.header()); + OpExecutionStrategy::new(evm, block.sealed_block(), self) } } /// Block execution strategy for Optimism. -#[allow(missing_debug_implementations)] -pub struct OpExecutionStrategy -where - EvmConfig: ConfigureEvm, -{ - /// The chainspec - chain_spec: Arc, - /// How to create an EVM. - evm_config: EvmConfig, - /// Current state for block execution. - state: State, +#[derive(Debug, derive_more::Deref)] +pub struct OpExecutionStrategy<'a, Evm, N: NodePrimitives, ChainSpec, EvmConfig: ConfigureEvm> { + /// Reference to the parent factory. + #[deref] + factory: &'a OpExecutionStrategyFactory, + + /// Block being executed. + block: &'a SealedBlock, + /// The EVM used by strategy. + evm: Evm, + /// Receipts of executed transactions. + receipts: Vec, /// Utility to call system smart contracts. - system_caller: SystemCaller>, - /// Receipt builder. - receipt_builder: - Arc, Receipt = N::Receipt>>, + system_caller: SystemCaller<&'a ChainSpec>, } -impl OpExecutionStrategy +impl<'a, Evm, N, ChainSpec, EvmConfig> OpExecutionStrategy<'a, Evm, N, ChainSpec, EvmConfig> where N: NodePrimitives, ChainSpec: OpHardforks, @@ -123,73 +118,67 @@ where { /// Creates a new [`OpExecutionStrategy`] pub fn new( - state: State, - chain_spec: Arc, - evm_config: EvmConfig, - receipt_builder: Arc< - dyn OpReceiptBuilder, Receipt = N::Receipt>, - >, + evm: Evm, + block: &'a SealedBlock, + factory: &'a OpExecutionStrategyFactory, ) -> Self { - let system_caller = SystemCaller::new(chain_spec.clone()); - Self { state, chain_spec, evm_config, system_caller, receipt_builder } + Self { + evm, + factory, + block, + receipts: Vec::new(), + system_caller: SystemCaller::new(&factory.chain_spec), + } } } -impl BlockExecutionStrategy - for OpExecutionStrategy +impl<'db, DB, E, N, ChainSpec, EvmConfig> BlockExecutionStrategy + for OpExecutionStrategy<'_, E, N, ChainSpec, EvmConfig> where - DB: Database, + DB: Database + 'db, + E: Evm, Tx = EvmConfig::TxEnv, HaltReason = HaltReasonFor>, N: NodePrimitives, ChainSpec: OpHardforks, EvmConfig: ConfigureEvmFor, { - type DB = DB; type Primitives = N; type Error = BlockExecutionError; - fn apply_pre_execution_changes( - &mut self, - block: &RecoveredBlock, - ) -> Result<(), Self::Error> { + fn apply_pre_execution_changes(&mut self) -> Result<(), Self::Error> { // Set state clear flag if the block is after the Spurious Dragon hardfork. let state_clear_flag = - (*self.chain_spec).is_spurious_dragon_active_at_block(block.number()); - self.state.set_state_clear_flag(state_clear_flag); + (*self.chain_spec).is_spurious_dragon_active_at_block(self.block.number()); + self.evm.db_mut().set_state_clear_flag(state_clear_flag); - let mut evm = self.evm_config.evm_for_block(&mut self.state, block.header()); - - self.system_caller - .apply_beacon_root_contract_call(block.header().parent_beacon_block_root(), &mut evm)?; + self.system_caller.apply_beacon_root_contract_call( + self.block.parent_beacon_block_root(), + &mut self.evm, + )?; // Ensure that the create2deployer is force-deployed at the canyon transition. Optimism // blocks will always have at least a single transaction in them (the L1 info transaction), // so we can safely assume that this will always be triggered upon the transition and that // the above check for empty blocks will never be hit on OP chains. - ensure_create2_deployer(self.chain_spec.clone(), block.header().timestamp(), evm.db_mut()) + ensure_create2_deployer(self.chain_spec.clone(), self.block.timestamp(), self.evm.db_mut()) .map_err(|_| OpBlockExecutionError::ForceCreate2DeployerFail)?; Ok(()) } - fn execute_transactions( + fn execute_transactions<'a>( &mut self, - block: &RecoveredBlock, - ) -> Result, Self::Error> { - let mut evm = self.evm_config.evm_for_block(&mut self.state, block.header()); - - let is_regolith = self.chain_spec.is_regolith_active_at_timestamp(block.timestamp()); + transactions: impl IntoIterator>, + ) -> Result<(), Self::Error> { + let is_regolith = self.chain_spec.is_regolith_active_at_timestamp(self.block.timestamp()); let mut cumulative_gas_used = 0; - let mut receipts = Vec::with_capacity(block.body().transaction_count()); - for (tx_index, (sender, transaction)) in block.transactions_with_sender().enumerate() { + for (tx_index, tx) in transactions.into_iter().enumerate() { // The sum of the transaction’s gas limit, Tg, and the gas utilized in this block prior, // must be no greater than the block’s gasLimit. - let block_available_gas = block.gas_limit() - cumulative_gas_used; - if transaction.gas_limit() > block_available_gas && - (is_regolith || !transaction.is_deposit()) - { + let block_available_gas = self.block.gas_limit() - cumulative_gas_used; + if tx.gas_limit() > block_available_gas && (is_regolith || !tx.is_deposit()) { return Err(BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas { - transaction_gas_limit: transaction.gas_limit(), + transaction_gas_limit: tx.gas_limit(), block_available_gas, } .into()) @@ -200,42 +189,41 @@ where // Note that this *only* needs to be done post-regolith hardfork, as deposit nonces // were not introduced in Bedrock. In addition, regular transactions don't have deposit // nonces, so we don't need to touch the DB for those. - let depositor = (is_regolith && transaction.is_deposit()) + let depositor = (is_regolith && tx.is_deposit()) .then(|| { - evm.db_mut() - .load_cache_account(*sender) + self.evm + .db_mut() + .load_cache_account(tx.signer()) .map(|acc| acc.account_info().unwrap_or_default()) }) .transpose() - .map_err(|_| OpBlockExecutionError::AccountLoadFailed(*sender))?; + .map_err(|_| OpBlockExecutionError::AccountLoadFailed(tx.signer()))?; - let tx_env = self.evm_config.tx_env(transaction, *sender); + let tx_env = self.evm_config.tx_env(&tx); + let hash = tx.tx_hash(); // Execute transaction. - let result_and_state = evm.transact(tx_env).map_err(move |err| { + let result_and_state = self.evm.transact(tx_env).map_err(move |err| { // Ensure hash is calculated for error log, if not already done - BlockValidationError::EVM { - hash: transaction.recalculate_hash(), - error: Box::new(err), - } + BlockValidationError::EVM { hash: *hash, error: Box::new(err) } })?; trace!( target: "evm", - ?transaction, + ?tx, "Executed transaction" ); self.system_caller .on_state(StateChangeSource::Transaction(tx_index), &result_and_state.state); let ResultAndState { result, state } = result_and_state; - evm.db_mut().commit(state); + self.evm.db_mut().commit(state); // append gas used cumulative_gas_used += result.gas_used(); - receipts.push( + self.receipts.push( match self.receipt_builder.build_receipt(ReceiptBuilderCtx { - tx: transaction, + tx: tx.tx(), result, cumulative_gas_used, }) { @@ -257,9 +245,9 @@ where // when set. The state transition process ensures // this is only set for post-Canyon deposit // transactions. - deposit_receipt_version: (transaction.is_deposit() && + deposit_receipt_version: (tx.is_deposit() && self.chain_spec - .is_canyon_active_at_timestamp(block.timestamp())) + .is_canyon_active_at_timestamp(self.block.timestamp())) .then_some(1), }) } @@ -267,53 +255,33 @@ where ); } - Ok(ExecuteOutput { receipts, gas_used: cumulative_gas_used }) + Ok(()) } fn apply_post_execution_changes( - &mut self, - block: &RecoveredBlock, - _receipts: &[N::Receipt], - ) -> Result { - let balance_increments = post_block_balance_increments(&self.chain_spec.clone(), block); + mut self, + ) -> Result, Self::Error> { + let balance_increments = + post_block_balance_increments(&self.chain_spec.clone(), self.block); // increment balances - self.state + self.evm + .db_mut() .increment_balances(balance_increments.clone()) .map_err(|_| BlockValidationError::IncrementBalanceFailed)?; // call state hook with changes due to balance increments. - let balance_state = balance_increment_state(&balance_increments, &mut self.state)?; + let balance_state = balance_increment_state(&balance_increments, self.evm.db_mut())?; self.system_caller.on_state( StateChangeSource::PostBlock(StateChangePostBlockSource::BalanceIncrements), &balance_state, ); - Ok(Requests::default()) - } - - fn state_ref(&self) -> &State { - &self.state - } - - fn state_mut(&mut self) -> &mut State { - &mut self.state - } - - fn into_state(self) -> revm_database::State { - self.state + let gas_used = self.receipts.last().map(|r| r.cumulative_gas_used()).unwrap_or_default(); + Ok(BlockExecutionResult { receipts: self.receipts, requests: Default::default(), gas_used }) } fn with_state_hook(&mut self, hook: Option>) { self.system_caller.with_state_hook(hook); } - - fn validate_block_post_execution( - &self, - block: &RecoveredBlock, - receipts: &[N::Receipt], - _requests: &Requests, - ) -> Result<(), ConsensusError> { - validate_block_post_execution(block.header(), self.chain_spec.clone(), receipts) - } } /// Helper type with backwards compatible methods to obtain executor providers. diff --git a/crates/optimism/evm/src/lib.rs b/crates/optimism/evm/src/lib.rs index 5f5989e61488..1b5730bf624e 100644 --- a/crates/optimism/evm/src/lib.rs +++ b/crates/optimism/evm/src/lib.rs @@ -11,10 +11,10 @@ extern crate alloc; use alloc::sync::Arc; -use alloy_consensus::{BlockHeader, Header}; +use alloy_consensus::{transaction::Recovered, BlockHeader, Header}; use alloy_op_evm::OpEvmFactory; -use alloy_primitives::{Address, U256}; -use core::fmt::Debug; +use alloy_primitives::U256; +use core::{borrow::Borrow, fmt::Debug}; use op_alloy_consensus::EIP1559ParamError; use reth_chainspec::EthChainSpec; use reth_evm::{ConfigureEvm, ConfigureEvmEnv, EvmEnv, NextBlockEnvAttributes}; @@ -74,9 +74,14 @@ impl ConfigureEvmEnv for OpEvmC type TxEnv = OpTransaction; type Spec = OpSpecId; - fn tx_env(&self, transaction: &Self::Transaction, signer: Address) -> Self::TxEnv { + fn tx_env>( + &self, + transaction: impl Borrow>, + ) -> Self::TxEnv { + let transaction = transaction.borrow(); + let mut tx_env = Default::default(); - transaction.fill_tx_env(&mut tx_env, signer); + transaction.tx().borrow().fill_tx_env(&mut tx_env, transaction.signer()); tx_env } diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index 46bf3a55c3f6..c7add53420a6 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -934,7 +934,7 @@ where )) })?; - let tx_env = self.evm_config.tx_env(sequencer_tx.tx(), sequencer_tx.signer()); + let tx_env = self.evm_config.tx_env(&sequencer_tx); let ResultAndState { result, state: _ } = match evm.transact_commit(tx_env) { Ok(res) => res, @@ -1011,7 +1011,7 @@ where } // Configure the environment for the tx. - let tx_env = self.evm_config.tx_env(tx.tx(), tx.signer()); + let tx_env = self.evm_config.tx_env(&tx); let ResultAndState { result, state: _ } = match evm.transact_commit(tx_env) { Ok(res) => res, diff --git a/crates/optimism/rpc/src/eth/pending_block.rs b/crates/optimism/rpc/src/eth/pending_block.rs index 92a318920862..d0f0a875b6c2 100644 --- a/crates/optimism/rpc/src/eth/pending_block.rs +++ b/crates/optimism/rpc/src/eth/pending_block.rs @@ -2,8 +2,8 @@ use crate::OpEthApi; use alloy_consensus::{ - constants::EMPTY_WITHDRAWALS, proofs::calculate_transaction_root, Eip658Value, Header, - Transaction as _, TxReceipt, EMPTY_OMMER_ROOT_HASH, + constants::EMPTY_WITHDRAWALS, proofs::calculate_transaction_root, transaction::Recovered, + Eip658Value, Header, Transaction as _, TxReceipt, EMPTY_OMMER_ROOT_HASH, }; use alloy_eips::{eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE, BlockNumberOrTag}; use alloy_primitives::{B256, U256}; @@ -100,7 +100,7 @@ where block_env: &BlockEnv, parent_hash: B256, state_root: B256, - transactions: Vec>, + transactions: Vec>>, receipts: &[ProviderReceipt], ) -> reth_provider::ProviderBlock { let chain_spec = self.provider().chain_spec(); @@ -144,7 +144,11 @@ where // seal the block reth_primitives::Block { header, - body: BlockBody { transactions, ommers: vec![], withdrawals: None }, + body: BlockBody { + transactions: transactions.into_iter().map(|tx| tx.into_tx()).collect(), + ommers: vec![], + withdrawals: None, + }, } } diff --git a/crates/rpc/rpc-eth-api/src/helpers/call.rs b/crates/rpc/rpc-eth-api/src/helpers/call.rs index 998d53b14c21..db405f2a81f0 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/call.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/call.rs @@ -7,7 +7,7 @@ use crate::{ }; use alloy_consensus::BlockHeader; use alloy_eips::{eip1559::calc_next_block_base_fee, eip2930::AccessListResult}; -use alloy_primitives::{Address, Bytes, B256, U256}; +use alloy_primitives::{Bytes, B256, U256}; use alloy_rpc_types_eth::{ simulate::{SimBlock, SimulatePayload, SimulatedBlock}, state::{EvmOverrides, StateOverride}, @@ -22,6 +22,7 @@ use reth_evm::{ TransactionEnv, }; use reth_node_api::BlockBody; +use reth_primitives::Recovered; use reth_primitives_traits::SignedTransaction; use reth_provider::{BlockIdReader, ChainSpecProvider, ProviderHeader}; use reth_revm::{database::StateProviderDatabase, db::CacheDB, DatabaseRef}; @@ -172,8 +173,6 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA let mut results = Vec::with_capacity(calls.len()); while let Some(call) = calls.next() { - let sender = call.from.unwrap_or_default(); - // Resolve transaction, populate missing fields and enforce calls // correctness. let tx = simulate::resolve_transaction( @@ -185,7 +184,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA this.tx_resp_builder(), )?; - let tx_env = this.evm_config().tx_env(&tx, sender); + let tx_env = this.evm_config().tx_env(&tx); let (res, (_, tx_env)) = { if trace_transfers { @@ -324,9 +323,9 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA if replay_block_txs { // only need to replay the transactions in the block if not all transactions are // to be replayed - let transactions = block.transactions_with_sender().take(num_txs); - for (signer, tx) in transactions { - let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx, *signer); + let transactions = block.transactions_recovered().take(num_txs); + for tx in transactions { + let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx); let (res, _) = this.transact(&mut db, evm_env.clone(), tx_env)?; db.commit(res.state); } @@ -671,12 +670,12 @@ pub trait Call: let this = self.clone(); self.spawn_with_state_at_block(parent_block.into(), move |state| { let mut db = CacheDB::new(StateProviderDatabase::new(state)); - let block_txs = block.transactions_with_sender(); + let block_txs = block.transactions_recovered(); // replay all transactions prior to the targeted transaction this.replay_transactions_until(&mut db, evm_env.clone(), block_txs, *tx.tx_hash())?; - let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx.tx(), tx.signer()); + let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx); let (res, _) = this.transact(&mut db, evm_env, tx_env)?; f(tx_info, res, db) @@ -702,18 +701,18 @@ pub trait Call: ) -> Result where DB: Database + DatabaseCommit, - I: IntoIterator::Transaction)>, + I: IntoIterator::Transaction>>, ::Transaction: SignedTransaction, { let mut evm = self.evm_config().evm_with_env(db, evm_env); let mut index = 0; - for (sender, tx) in transactions { + for tx in transactions { if *tx.tx_hash() == target_tx_hash { // reached the target transaction break } - let tx_env = self.evm_config().tx_env(tx, *sender); + let tx_env = self.evm_config().tx_env(tx); evm.transact_commit(tx_env).map_err(Self::Error::from_evm_err)?; index += 1; } diff --git a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs index 8a62c226b1d8..0b1d67479ca4 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs @@ -3,7 +3,7 @@ use super::SpawnBlocking; use crate::{types::RpcTypes, EthApiTypes, FromEthApiError, FromEvmError, RpcNodeCore}; -use alloy_consensus::{BlockHeader, Transaction}; +use alloy_consensus::{transaction::Recovered, BlockHeader, Transaction}; use alloy_eips::eip4844::MAX_DATA_GAS_PER_BLOCK; use alloy_primitives::B256; use alloy_rpc_types_eth::BlockNumberOrTag; @@ -209,7 +209,7 @@ pub trait LoadPendingBlock: block_env: &BlockEnv, parent_hash: B256, state_root: B256, - transactions: Vec>, + transactions: Vec>>, receipts: &[ProviderReceipt], ) -> ProviderBlock; @@ -219,7 +219,7 @@ pub trait LoadPendingBlock: block_env: &BlockEnv, parent_hash: B256, state_root: B256, - transactions: Vec>, + transactions: Vec>>, results: Vec>>, ) -> (ProviderBlock, Vec>) { let mut cumulative_gas_used = 0; @@ -267,7 +267,6 @@ pub trait LoadPendingBlock: let base_fee = evm_env.block_env.basefee; let mut executed_txs = Vec::new(); - let mut senders = Vec::new(); let mut best_txs = self.pool().best_transactions_with_attributes(BestTransactionsAttributes::new( base_fee, @@ -336,7 +335,7 @@ pub trait LoadPendingBlock: } } - let tx_env = self.evm_config().tx_env(tx.tx(), tx.signer()); + let tx_env = self.evm_config().tx_env(&tx); let ResultAndState { result, state: _ } = match evm.transact_commit(tx_env) { Ok(res) => res, @@ -377,9 +376,7 @@ pub trait LoadPendingBlock: cumulative_gas_used += gas_used; // append transaction to the list of executed transactions - let (tx, sender) = tx.into_parts(); executed_txs.push(tx); - senders.push(sender); results.push(result); } @@ -405,6 +402,8 @@ pub trait LoadPendingBlock: // calculate the state root let state_root = db.database.state_root(hashed_state).map_err(Self::Error::from_eth_err)?; + let senders = executed_txs.iter().map(|tx| tx.signer()).collect(); + let (block, receipts) = self.assemble_block_and_receipts( &evm_env.block_env, parent_hash, diff --git a/crates/rpc/rpc-eth-api/src/helpers/trace.rs b/crates/rpc/rpc-eth-api/src/helpers/trace.rs index 2e72f8b4f932..bdc481cd30b9 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/trace.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/trace.rs @@ -204,14 +204,14 @@ pub trait Trace: let this = self.clone(); self.spawn_with_state_at_block(parent_block.into(), move |state| { let mut db = CacheDB::new(StateProviderDatabase::new(state)); - let block_txs = block.transactions_with_sender(); + let block_txs = block.transactions_recovered(); this.apply_pre_execution_changes(&block, &mut db, &evm_env)?; // replay all transactions prior to the targeted transaction this.replay_transactions_until(&mut db, evm_env.clone(), block_txs, *tx.tx_hash())?; - let tx_env = this.evm_config().tx_env(tx.tx(), tx.signer()); + let tx_env = this.evm_config().tx_env(tx); let (res, _) = this.inspect( StateCacheDbRefMutWrapper(&mut db), evm_env, @@ -339,10 +339,10 @@ pub trait Trace: let mut results = Vec::with_capacity(max_transactions); let mut transactions = block - .transactions_with_sender() + .transactions_recovered() .take(max_transactions) .enumerate() - .map(|(idx, (signer, tx))| { + .map(|(idx, tx)| { let tx_info = TransactionInfo { hash: Some(*tx.tx_hash()), index: Some(idx as u64), @@ -350,7 +350,7 @@ pub trait Trace: block_number: Some(block_number), base_fee: Some(base_fee), }; - let tx_env = this.evm_config().tx_env(tx, *signer); + let tx_env = this.evm_config().tx_env(tx); (tx_info, tx_env) }) .peekable(); diff --git a/crates/rpc/rpc-eth-types/src/simulate.rs b/crates/rpc/rpc-eth-types/src/simulate.rs index ad21f0b3e4f2..d9a6ba06f539 100644 --- a/crates/rpc/rpc-eth-types/src/simulate.rs +++ b/crates/rpc/rpc-eth-types/src/simulate.rs @@ -7,7 +7,7 @@ use alloy_rpc_types_eth::{ Block, BlockTransactionsKind, Header, }; use jsonrpsee_types::ErrorObject; -use reth_primitives::RecoveredBlock; +use reth_primitives::{Recovered, RecoveredBlock}; use reth_primitives_traits::{block::BlockTx, BlockBody as _, SignedTransaction}; use reth_rpc_server_types::result::rpc_err; use reth_rpc_types_compat::{block::from_block, TransactionCompat}; @@ -60,7 +60,7 @@ pub fn resolve_transaction>( chain_id: u64, db: &mut DB, tx_resp_builder: &T, -) -> Result +) -> Result, EthApiError> where EthApiError: From, { @@ -108,7 +108,11 @@ where } } - tx_resp_builder.build_simulate_v1_transaction(tx).map_err(|e| EthApiError::other(e.into())) + let tx = tx_resp_builder + .build_simulate_v1_transaction(tx) + .map_err(|e| EthApiError::other(e.into()))?; + + Ok(Recovered::new_unchecked(tx, from)) } /// Handles outputs of the calls execution and builds a [`SimulatedBlock`]. diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index cdae15763d3f..65f9702f4425 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -109,12 +109,12 @@ where this.eth_api().apply_pre_execution_changes(&block, &mut db, &evm_env)?; - let mut transactions = block.transactions_with_sender().enumerate().peekable(); + let mut transactions = block.transactions_recovered().enumerate().peekable(); let mut inspector = None; - while let Some((index, (signer, tx))) = transactions.next() { + while let Some((index, tx)) = transactions.next() { let tx_hash = *tx.tx_hash(); - let tx_env = this.eth_api().evm_config().tx_env(tx, *signer); + let tx_env = this.eth_api().evm_config().tx_env(tx); let (result, state_changes) = this.trace_transaction( &opts, @@ -229,7 +229,7 @@ where let this = self.clone(); self.eth_api() .spawn_with_state_at_block(state_at, move |state| { - let block_txs = block.transactions_with_sender(); + let block_txs = block.transactions_recovered(); // configure env for the target transaction let tx = transaction.into_recovered(); @@ -246,7 +246,7 @@ where *tx.tx_hash(), )?; - let tx_env = this.eth_api().evm_config().tx_env(tx.tx(), tx.signer()); + let tx_env = this.eth_api().evm_config().tx_env(&tx); this.trace_transaction( &opts, @@ -530,11 +530,11 @@ where if replay_block_txs { // only need to replay the transactions in the block if not all transactions are // to be replayed - let transactions = block.transactions_with_sender().take(num_txs); + let transactions = block.transactions_recovered().take(num_txs); // Execute all transactions until index - for (signer, tx) in transactions { - let tx_env = this.eth_api().evm_config().tx_env(tx, *signer); + for tx in transactions { + let tx_env = this.eth_api().evm_config().tx_env(tx); let (res, _) = this.eth_api().transact(&mut db, evm_env.clone(), tx_env)?; db.commit(res.state); } diff --git a/crates/rpc/rpc/src/eth/bundle.rs b/crates/rpc/rpc/src/eth/bundle.rs index df8de0582e8d..384787f75674 100644 --- a/crates/rpc/rpc/src/eth/bundle.rs +++ b/crates/rpc/rpc/src/eth/bundle.rs @@ -176,7 +176,7 @@ where hasher.update(*tx.tx_hash()); let gas_price = tx.effective_gas_price(basefee); let ResultAndState { result, state } = evm - .transact(eth_api.evm_config().tx_env(&tx, signer)) + .transact(eth_api.evm_config().tx_env(&tx)) .map_err(Eth::Error::from_evm_err)?; let gas_used = result.gas_used(); diff --git a/crates/rpc/rpc/src/eth/helpers/pending_block.rs b/crates/rpc/rpc/src/eth/helpers/pending_block.rs index ae2876ab2321..92d26b95aca5 100644 --- a/crates/rpc/rpc/src/eth/helpers/pending_block.rs +++ b/crates/rpc/rpc/src/eth/helpers/pending_block.rs @@ -1,6 +1,9 @@ //! Support for building a pending block with transactions from local view of mempool. -use alloy_consensus::{constants::EMPTY_WITHDRAWALS, Header, Transaction, EMPTY_OMMER_ROOT_HASH}; +use alloy_consensus::{ + constants::EMPTY_WITHDRAWALS, transaction::Recovered, Header, Transaction, + EMPTY_OMMER_ROOT_HASH, +}; use alloy_eips::{eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE}; use alloy_primitives::U256; use reth_chainspec::{EthChainSpec, EthereumHardforks}; @@ -61,7 +64,7 @@ where block_env: &BlockEnv, parent_hash: revm_primitives::B256, state_root: revm_primitives::B256, - transactions: Vec>, + transactions: Vec>>, receipts: &[ProviderReceipt], ) -> reth_provider::ProviderBlock { let chain_spec = self.provider().chain_spec(); @@ -105,7 +108,11 @@ where // seal the block reth_primitives::Block { header, - body: BlockBody { transactions, ommers: vec![], withdrawals: None }, + body: BlockBody { + transactions: transactions.into_iter().map(|tx| tx.into_tx()).collect(), + ommers: vec![], + withdrawals: None, + }, } } diff --git a/crates/rpc/rpc/src/eth/sim_bundle.rs b/crates/rpc/rpc/src/eth/sim_bundle.rs index 5914b2a970ac..26daf9df4621 100644 --- a/crates/rpc/rpc/src/eth/sim_bundle.rs +++ b/crates/rpc/rpc/src/eth/sim_bundle.rs @@ -10,6 +10,7 @@ use alloy_rpc_types_mev::{ }; use jsonrpsee::core::RpcResult; use reth_evm::{ConfigureEvm, ConfigureEvmEnv, Evm}; +use reth_primitives::Recovered; use reth_provider::ProviderTx; use reth_revm::{database::StateProviderDatabase, db::CacheDB}; use reth_rpc_api::MevSimApiServer; @@ -21,9 +22,8 @@ use reth_rpc_eth_types::{ revm_utils::apply_block_overrides, utils::recover_raw_transaction, EthApiError, }; use reth_tasks::pool::BlockingTaskGuard; -use reth_transaction_pool::{PoolConsensusTx, PoolPooledTx, PoolTransaction, TransactionPool}; +use reth_transaction_pool::{PoolPooledTx, PoolTransaction, TransactionPool}; use revm::{context_interface::result::ResultAndState, DatabaseCommit, DatabaseRef}; -use revm_primitives::Address; use std::{sync::Arc, time::Duration}; use tracing::info; @@ -46,9 +46,7 @@ const SBUNDLE_PAYOUT_MAX_COST: u64 = 30_000; #[derive(Clone, Debug)] pub struct FlattenedBundleItem { /// The signed transaction - pub tx: T, - /// The address that signed the transaction - pub signer: Address, + pub tx: Recovered, /// Whether the transaction is allowed to revert pub can_revert: bool, /// Item-level inclusion constraints @@ -169,10 +167,10 @@ where while idx < body.len() { match &body[idx] { BundleItem::Tx { tx, can_revert } => { - let recovered_tx = recover_raw_transaction::>(tx)?; - let (tx, signer) = recovered_tx.into_parts(); - let tx: PoolConsensusTx = - ::Transaction::pooled_into_consensus(tx); + let tx = recover_raw_transaction::>(tx)?; + let tx = tx.map_transaction( + ::Transaction::pooled_into_consensus, + ); let refund_percent = validity.as_ref().and_then(|v| v.refund.as_ref()).and_then(|refunds| { @@ -186,7 +184,6 @@ where // Create FlattenedBundleItem with current inclusion, validity, and privacy let flattened_item = FlattenedBundleItem { tx, - signer, can_revert: *can_revert, inclusion: inclusion.clone(), validity: validity.clone(), @@ -282,7 +279,7 @@ where } let ResultAndState { result, state } = evm - .transact(eth_api.evm_config().tx_env(&item.tx, item.signer)) + .transact(eth_api.evm_config().tx_env(&item.tx)) .map_err(Eth::Error::from_evm_err)?; if !result.is_success() && !item.can_revert { @@ -330,7 +327,7 @@ where if let Some(refund_percent) = item.refund_percent { // Get refund configurations let refund_configs = item.refund_configs.clone().unwrap_or_else(|| { - vec![RefundConfig { address: item.signer, percent: 100 }] + vec![RefundConfig { address: item.tx.signer(), percent: 100 }] }); // Calculate payout transaction fee diff --git a/crates/rpc/rpc/src/trace.rs b/crates/rpc/rpc/src/trace.rs index a2057fd60b3d..9fc71417ab6c 100644 --- a/crates/rpc/rpc/src/trace.rs +++ b/crates/rpc/rpc/src/trace.rs @@ -113,7 +113,7 @@ where .map_transaction(::Transaction::pooled_into_consensus); let (evm_env, at) = self.eth_api().evm_env_at(block_id.unwrap_or_default()).await?; - let tx_env = self.eth_api().evm_config().tx_env(tx.tx(), tx.signer()); + let tx_env = self.eth_api().evm_config().tx_env(tx); let config = TracingInspectorConfig::from_parity_config(&trace_types); diff --git a/examples/custom-beacon-withdrawals/src/main.rs b/examples/custom-beacon-withdrawals/src/main.rs index c19c34d404e8..b82848e853eb 100644 --- a/examples/custom-beacon-withdrawals/src/main.rs +++ b/examples/custom-beacon-withdrawals/src/main.rs @@ -4,13 +4,14 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] use alloy_consensus::BlockHeader; -use alloy_eips::{eip4895::Withdrawal, eip7685::Requests}; +use alloy_eips::eip4895::Withdrawal; use alloy_sol_macro::sol; use alloy_sol_types::SolCall; use reth::{ api::{ConfigureEvm, NodeTypesWithEngine}, builder::{components::ExecutorBuilder, BuilderContext, FullNodeTypes}, cli::Cli, + providers::BlockExecutionResult, revm::{ db::State, primitives::{address, Address}, @@ -20,14 +21,16 @@ use reth::{ use reth_chainspec::{ChainSpec, EthereumHardforks}; use reth_evm::{ execute::{ - BlockExecutionError, BlockExecutionStrategy, BlockExecutionStrategyFactory, ExecuteOutput, + BlockExecutionError, BlockExecutionStrategy, BlockExecutionStrategyFactory, InternalBlockExecutionError, }, Database, Evm, }; use reth_evm_ethereum::EthEvmConfig; use reth_node_ethereum::{node::EthereumAddOns, BasicBlockExecutorProvider, EthereumNode}; -use reth_primitives::{EthPrimitives, Receipt, RecoveredBlock}; +use reth_primitives::{ + Block, EthPrimitives, Receipt, Recovered, RecoveredBlock, SealedBlock, TransactionSigned, +}; use std::{fmt::Display, sync::Arc}; pub const SYSTEM_ADDRESS: Address = address!("fffffffffffffffffffffffffffffffffffffffe"); @@ -90,86 +93,64 @@ pub struct CustomExecutorStrategyFactory { impl BlockExecutionStrategyFactory for CustomExecutorStrategyFactory { type Primitives = EthPrimitives; - type Strategy = CustomExecutorStrategy; - fn create_strategy(&self, db: DB) -> Self::Strategy + fn create_strategy<'a, DB>( + &'a mut self, + db: &'a mut State, + block: &'a RecoveredBlock, + ) -> impl BlockExecutionStrategy + 'a where DB: Database, { - let state = - State::builder().with_database(db).with_bundle_update().without_state_clear().build(); - CustomExecutorStrategy { - state, - chain_spec: self.chain_spec.clone(), - evm_config: self.evm_config.clone(), - } + let evm = self.evm_config.evm_for_block(db, block.header()); + CustomExecutorStrategy { evm, factory: self, block } } } -pub struct CustomExecutorStrategy -where - DB: Database, -{ - /// The chainspec - chain_spec: Arc, - /// How to create an EVM. - evm_config: EthEvmConfig, - /// Current state for block execution. - state: State, +pub struct CustomExecutorStrategy<'a, Evm> { + /// Reference to the parent factory. + factory: &'a CustomExecutorStrategyFactory, + /// EVM used for execution. + evm: Evm, + /// Block being executed. + block: &'a SealedBlock, } -impl BlockExecutionStrategy for CustomExecutorStrategy +impl<'db, DB, E> BlockExecutionStrategy for CustomExecutorStrategy<'_, E> where - DB: Database, + DB: Database + 'db, + E: Evm>, { - type DB = DB; type Primitives = EthPrimitives; type Error = BlockExecutionError; - fn apply_pre_execution_changes( - &mut self, - block: &RecoveredBlock, - ) -> Result<(), Self::Error> { + fn apply_pre_execution_changes(&mut self) -> Result<(), Self::Error> { // Set state clear flag if the block is after the Spurious Dragon hardfork. let state_clear_flag = - (*self.chain_spec).is_spurious_dragon_active_at_block(block.number()); - self.state.set_state_clear_flag(state_clear_flag); + (*self.factory.chain_spec).is_spurious_dragon_active_at_block(self.block.number()); + self.evm.db_mut().set_state_clear_flag(state_clear_flag); Ok(()) } - fn execute_transactions( + fn execute_transactions<'a>( &mut self, - _block: &RecoveredBlock, - ) -> Result, Self::Error> { - Ok(ExecuteOutput { receipts: vec![], gas_used: 0 }) + _transactions: impl IntoIterator>, + ) -> Result<(), Self::Error> { + Ok(()) } fn apply_post_execution_changes( - &mut self, - block: &RecoveredBlock, - _receipts: &[Receipt], - ) -> Result { - let mut evm = self.evm_config.evm_for_block(&mut self.state, block.header()); - - if let Some(withdrawals) = block.body().withdrawals.as_ref() { - apply_withdrawals_contract_call(withdrawals, &mut evm)?; + mut self, + ) -> Result, Self::Error> { + if let Some(withdrawals) = self.block.body().withdrawals.as_ref() { + apply_withdrawals_contract_call(withdrawals, &mut self.evm)?; } - Ok(Requests::default()) + Ok(Default::default()) } - fn state_ref(&self) -> &State { - &self.state - } - - fn state_mut(&mut self) -> &mut State { - &mut self.state - } - - fn into_state(self) -> reth::revm::db::State { - self.state - } + fn with_state_hook(&mut self, _hook: Option>) {} } sol!( diff --git a/examples/custom-evm/src/main.rs b/examples/custom-evm/src/main.rs index 6aa7551e3bd6..02f93baa45e9 100644 --- a/examples/custom-evm/src/main.rs +++ b/examples/custom-evm/src/main.rs @@ -41,9 +41,10 @@ use reth_node_ethereum::{ node::{EthereumAddOns, EthereumPayloadBuilder}, BasicBlockExecutorProvider, EthExecutionStrategyFactory, EthereumNode, }; -use reth_primitives::{EthPrimitives, TransactionSigned}; +use reth_primitives::{EthPrimitives, Recovered, TransactionSigned}; use reth_tracing::{RethTracer, Tracer}; use std::{ + borrow::Borrow, convert::Infallible, sync::{Arc, OnceLock}, }; @@ -105,8 +106,11 @@ impl ConfigureEvmEnv for MyEvmConfig { type TxEnv = TxEnv; type Spec = SpecId; - fn tx_env(&self, transaction: &Self::Transaction, signer: Address) -> Self::TxEnv { - self.inner.tx_env(transaction, signer) + fn tx_env>( + &self, + transaction: impl Borrow>, + ) -> Self::TxEnv { + self.inner.tx_env(transaction) } fn evm_env(&self, header: &Self::Header) -> EvmEnv { diff --git a/examples/stateful-precompile/src/main.rs b/examples/stateful-precompile/src/main.rs index 6f38d9a3d40b..77b34c3f05e2 100644 --- a/examples/stateful-precompile/src/main.rs +++ b/examples/stateful-precompile/src/main.rs @@ -33,10 +33,10 @@ use reth_node_ethereum::{ evm::EthEvm, node::EthereumAddOns, BasicBlockExecutorProvider, EthEvmConfig, EthExecutionStrategyFactory, EthereumNode, }; -use reth_primitives::{EthPrimitives, TransactionSigned}; +use reth_primitives::{EthPrimitives, Recovered, TransactionSigned}; use reth_tracing::{RethTracer, Tracer}; use schnellru::{ByLength, LruMap}; -use std::{collections::HashMap, convert::Infallible, sync::Arc}; +use std::{borrow::Borrow, collections::HashMap, convert::Infallible, sync::Arc}; /// Type alias for the LRU cache used within the [`PrecompileCache`]. type PrecompileLRUCache = LruMap<(SpecId, Bytes, u64), Result>; @@ -186,8 +186,11 @@ impl ConfigureEvmEnv for MyEvmConfig { type TxEnv = TxEnv; type Spec = SpecId; - fn tx_env(&self, transaction: &Self::Transaction, signer: Address) -> Self::TxEnv { - self.inner.tx_env(transaction, signer) + fn tx_env>( + &self, + transaction: impl Borrow>, + ) -> Self::TxEnv { + self.inner.tx_env(transaction) } fn evm_env(&self, header: &Self::Header) -> EvmEnv { From e51e1097230875182d9735800070e746db7740d9 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Feb 2025 14:12:17 +0100 Subject: [PATCH 16/21] chore(deps): Bump `op-alloy` (#14585) --- Cargo.lock | 24 ++++++++++++------------ Cargo.toml | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b0cb1c71237..e69e29f531c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5602,9 +5602,9 @@ checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "op-alloy-consensus" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc796860410e85a9cd881ee074c3dc0120b90696d82d09348ebb563d4ade67e4" +checksum = "621e69964165285ce750bf7ba961707e26c31df9f0b25652d6219dcee1f7f5b5" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5620,15 +5620,15 @@ dependencies = [ [[package]] name = "op-alloy-flz" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4ab80587d9f98aae42d255c21bd183ae4423a4d7cb320e738d2b2e96d1591b" +checksum = "bbee9e684edfb73081bc22337be374b1b454d5eea87790b61ca95a6564953807" [[package]] name = "op-alloy-network" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f787eb3752a847369a3eefb6cbb3f8bfc9c365a2435116f84ef68d0edfe821" +checksum = "c45f90eaee907df6f1c75d9295c303cfc018fdb3ef91b13b9f46e9922bfb1625" dependencies = [ "alloy-consensus", "alloy-network", @@ -5641,9 +5641,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-jsonrpsee" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a47074c77544a3f6fe062809d0c74b137668a93f788513250577873b2a93b14" +checksum = "409274d1940cdd6806c431157eb2b68b93ec2d019785f625b665d1c72c51d04e" dependencies = [ "alloy-primitives", "jsonrpsee", @@ -5651,9 +5651,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70bef5860f87412848c40a9f71f23923c6d59726aae678251911acdbc7380b2" +checksum = "7a206be9e4aab37bfa352352d63d8dfa9d48d9df1f30478e4a9477865fd88ad6" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5669,9 +5669,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types-engine" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a03ea4f6374aa13524753136eeceee76196acad6b1306399ab8f1856872384" +checksum = "158a8f5cec81cd301a2bdf97474b9918dda6318447619fbdfcf3f5bbc394d6be" dependencies = [ "alloy-consensus", "alloy-eips", diff --git a/Cargo.toml b/Cargo.toml index b5106249534a..f1ecb1a80ba9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -483,12 +483,12 @@ alloy-transport-ws = { version = "0.11.1", default-features = false } # op alloy-op-evm = { version = "0.1", default-features = false } -op-alloy-rpc-types = { version = "0.10.4", default-features = false } -op-alloy-rpc-types-engine = { version = "0.10.4", default-features = false } -op-alloy-network = { version = "0.10.4", default-features = false } -op-alloy-consensus = { version = "0.10.4", default-features = false } -op-alloy-flz = { version = "0.10.4", default-features = false } -op-alloy-rpc-jsonrpsee = { version = "0.10.4", default-features = false } +op-alloy-rpc-types = { version = "0.10.5", default-features = false } +op-alloy-rpc-types-engine = { version = "0.10.5", default-features = false } +op-alloy-network = { version = "0.10.5", default-features = false } +op-alloy-consensus = { version = "0.10.5", default-features = false } +op-alloy-flz = { version = "0.10.5", default-features = false } +op-alloy-rpc-jsonrpsee = { version = "0.10.5", default-features = false } # misc aquamarine = "0.6" From b9c81e4d94032870096f02f7059295ce3ea101b1 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Wed, 19 Feb 2025 18:03:13 +0400 Subject: [PATCH 17/21] feat: `BlockExecutionStrategy::execute_transaction` API (#14586) --- crates/ethereum/evm/src/execute.rs | 79 ++++---- crates/evm/src/execute.rs | 20 +- crates/optimism/evm/src/execute.rs | 172 +++++++++--------- .../custom-beacon-withdrawals/src/main.rs | 4 +- 4 files changed, 138 insertions(+), 137 deletions(-) diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index efb3e0db1931..987c93cc3a53 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -92,6 +92,8 @@ pub struct EthExecutionStrategy<'a, Evm, EvmConfig> { evm: Evm, /// Receipts of executed transactions. receipts: Vec, + /// Total gas used by transactions in this block. + gas_used: u64, /// Utility to call system smart contracts. system_caller: SystemCaller<&'a ChainSpec>, } @@ -108,6 +110,7 @@ impl<'a, Evm, EvmConfig> EthExecutionStrategy<'a, Evm, EvmConfig> { factory, block, receipts: Vec::new(), + gas_used: 0, system_caller: SystemCaller::new(&factory.chain_spec), } } @@ -132,49 +135,47 @@ where Ok(()) } - fn execute_transactions<'a>( + fn execute_transaction( &mut self, - transactions: impl IntoIterator>, + tx: Recovered<&TransactionSigned>, ) -> Result<(), Self::Error> { - let mut cumulative_gas_used = 0; - for (tx_index, tx) in transactions.into_iter().enumerate() { - // The sum of the transaction's gas limit, Tg, and the gas utilized in this block prior, - // must be no greater than the block's gasLimit. - let block_available_gas = self.block.gas_limit() - cumulative_gas_used; - if tx.gas_limit() > block_available_gas { - return Err(BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas { - transaction_gas_limit: tx.gas_limit(), - block_available_gas, - } - .into()) + // The sum of the transaction's gas limit, Tg, and the gas utilized in this block prior, + // must be no greater than the block's gasLimit. + let block_available_gas = self.block.gas_limit() - self.gas_used; + if tx.gas_limit() > block_available_gas { + return Err(BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas { + transaction_gas_limit: tx.gas_limit(), + block_available_gas, } - - let tx_env = self.evm_config.tx_env(tx.clone()); - let hash = tx.hash(); - - // Execute transaction. - let result_and_state = self.evm.transact(tx_env).map_err(move |err| { - // Ensure hash is calculated for error log, if not already done - BlockValidationError::EVM { hash: *hash, error: Box::new(err) } - })?; - self.system_caller - .on_state(StateChangeSource::Transaction(tx_index), &result_and_state.state); - let ResultAndState { result, state } = result_and_state; - self.evm.db_mut().commit(state); - - // append gas used - cumulative_gas_used += result.gas_used(); - - // Push transaction changeset and calculate header bloom filter for receipt. - self.receipts.push(Receipt { - tx_type: tx.tx_type(), - // Success flag was added in `EIP-658: Embedding transaction status code in - // receipts`. - success: result.is_success(), - cumulative_gas_used, - logs: result.into_logs(), - }); + .into()) } + + let tx_env = self.evm_config.tx_env(tx.clone()); + let hash = tx.hash(); + + // Execute transaction. + let result_and_state = self.evm.transact(tx_env).map_err(move |err| { + // Ensure hash is calculated for error log, if not already done + BlockValidationError::EVM { hash: *hash, error: Box::new(err) } + })?; + self.system_caller + .on_state(StateChangeSource::Transaction(self.receipts.len()), &result_and_state.state); + let ResultAndState { result, state } = result_and_state; + self.evm.db_mut().commit(state); + + // append gas used + self.gas_used += result.gas_used(); + + // Push transaction changeset and calculate header bloom filter for receipt. + self.receipts.push(Receipt { + tx_type: tx.tx_type(), + // Success flag was added in `EIP-658: Embedding transaction status code in + // receipts`. + success: result.is_success(), + cumulative_gas_used: self.gas_used, + logs: result.into_logs(), + }); + Ok(()) } diff --git a/crates/evm/src/execute.rs b/crates/evm/src/execute.rs index 40d7a5892505..f0f59a9be2d3 100644 --- a/crates/evm/src/execute.rs +++ b/crates/evm/src/execute.rs @@ -173,12 +173,10 @@ pub trait BlockExecutionStrategy { /// Applies any necessary changes before executing the block's transactions. fn apply_pre_execution_changes(&mut self) -> Result<(), Self::Error>; - /// Executes all transactions in the block. - fn execute_transactions<'a>( + /// Executes a single transaction and applies execution result to internal state. + fn execute_transaction( &mut self, - transactions: impl IntoIterator< - Item = Recovered<&'a ::SignedTx>, - >, + tx: Recovered<&::SignedTx>, ) -> Result<(), Self::Error>; /// Applies any necessary changes after executing the block's transactions. @@ -278,7 +276,9 @@ where let mut strategy = self.strategy_factory.create_strategy(&mut self.db, block); strategy.apply_pre_execution_changes()?; - strategy.execute_transactions(block.transactions_recovered())?; + for tx in block.transactions_recovered() { + strategy.execute_transaction(tx)?; + } let result = strategy.apply_post_execution_changes()?; self.db.merge_transitions(BundleRetention::Reverts); @@ -298,7 +298,9 @@ where strategy.with_state_hook(Some(Box::new(state_hook))); strategy.apply_pre_execution_changes()?; - strategy.execute_transactions(block.transactions_recovered())?; + for tx in block.transactions_recovered() { + strategy.execute_transaction(tx)?; + } let result = strategy.apply_post_execution_changes()?; self.db.merge_transitions(BundleRetention::Reverts); @@ -444,9 +446,9 @@ mod tests { Ok(()) } - fn execute_transactions<'a>( + fn execute_transaction( &mut self, - _transactions: impl IntoIterator>, + _tx: Recovered<&TransactionSigned>, ) -> Result<(), Self::Error> { Ok(()) } diff --git a/crates/optimism/evm/src/execute.rs b/crates/optimism/evm/src/execute.rs index f038fe619143..03e527694bbc 100644 --- a/crates/optimism/evm/src/execute.rs +++ b/crates/optimism/evm/src/execute.rs @@ -106,6 +106,10 @@ pub struct OpExecutionStrategy<'a, Evm, N: NodePrimitives, ChainSpec, EvmConfig: evm: Evm, /// Receipts of executed transactions. receipts: Vec, + /// Total gas used by executed transactions. + gas_used: u64, + /// Whether Regolith hardfork is active. + is_regolith: bool, /// Utility to call system smart contracts. system_caller: SystemCaller<&'a ChainSpec>, } @@ -127,6 +131,8 @@ where factory, block, receipts: Vec::new(), + gas_used: 0, + is_regolith: factory.chain_spec.is_regolith_active_at_timestamp(block.timestamp()), system_caller: SystemCaller::new(&factory.chain_spec), } } @@ -165,96 +171,88 @@ where Ok(()) } - fn execute_transactions<'a>( - &mut self, - transactions: impl IntoIterator>, - ) -> Result<(), Self::Error> { - let is_regolith = self.chain_spec.is_regolith_active_at_timestamp(self.block.timestamp()); - - let mut cumulative_gas_used = 0; - for (tx_index, tx) in transactions.into_iter().enumerate() { - // The sum of the transaction’s gas limit, Tg, and the gas utilized in this block prior, - // must be no greater than the block’s gasLimit. - let block_available_gas = self.block.gas_limit() - cumulative_gas_used; - if tx.gas_limit() > block_available_gas && (is_regolith || !tx.is_deposit()) { - return Err(BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas { - transaction_gas_limit: tx.gas_limit(), - block_available_gas, - } - .into()) + fn execute_transaction(&mut self, tx: Recovered<&N::SignedTx>) -> Result<(), Self::Error> { + // The sum of the transaction’s gas limit, Tg, and the gas utilized in this block prior, + // must be no greater than the block’s gasLimit. + let block_available_gas = self.block.gas_limit() - self.gas_used; + if tx.gas_limit() > block_available_gas && (self.is_regolith || !tx.is_deposit()) { + return Err(BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas { + transaction_gas_limit: tx.gas_limit(), + block_available_gas, } - - // Cache the depositor account prior to the state transition for the deposit nonce. - // - // Note that this *only* needs to be done post-regolith hardfork, as deposit nonces - // were not introduced in Bedrock. In addition, regular transactions don't have deposit - // nonces, so we don't need to touch the DB for those. - let depositor = (is_regolith && tx.is_deposit()) - .then(|| { - self.evm - .db_mut() - .load_cache_account(tx.signer()) - .map(|acc| acc.account_info().unwrap_or_default()) - }) - .transpose() - .map_err(|_| OpBlockExecutionError::AccountLoadFailed(tx.signer()))?; - - let tx_env = self.evm_config.tx_env(&tx); - let hash = tx.tx_hash(); - - // Execute transaction. - let result_and_state = self.evm.transact(tx_env).map_err(move |err| { - // Ensure hash is calculated for error log, if not already done - BlockValidationError::EVM { hash: *hash, error: Box::new(err) } - })?; - - trace!( - target: "evm", - ?tx, - "Executed transaction" - ); - self.system_caller - .on_state(StateChangeSource::Transaction(tx_index), &result_and_state.state); - let ResultAndState { result, state } = result_and_state; - self.evm.db_mut().commit(state); - - // append gas used - cumulative_gas_used += result.gas_used(); - - self.receipts.push( - match self.receipt_builder.build_receipt(ReceiptBuilderCtx { - tx: tx.tx(), - result, - cumulative_gas_used, - }) { - Ok(receipt) => receipt, - Err(ctx) => { - let receipt = Receipt { - // Success flag was added in `EIP-658: Embedding transaction status code - // in receipts`. - status: Eip658Value::Eip658(ctx.result.is_success()), - cumulative_gas_used, - logs: ctx.result.into_logs(), - }; - - self.receipt_builder.build_deposit_receipt(OpDepositReceipt { - inner: receipt, - 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 ensures - // this is only set for post-Canyon deposit - // transactions. - deposit_receipt_version: (tx.is_deposit() && - self.chain_spec - .is_canyon_active_at_timestamp(self.block.timestamp())) - .then_some(1), - }) - } - }, - ); + .into()) } + // Cache the depositor account prior to the state transition for the deposit nonce. + // + // Note that this *only* needs to be done post-regolith hardfork, as deposit nonces + // were not introduced in Bedrock. In addition, regular transactions don't have deposit + // nonces, so we don't need to touch the DB for those. + let depositor = (self.is_regolith && tx.is_deposit()) + .then(|| { + self.evm + .db_mut() + .load_cache_account(tx.signer()) + .map(|acc| acc.account_info().unwrap_or_default()) + }) + .transpose() + .map_err(|_| OpBlockExecutionError::AccountLoadFailed(tx.signer()))?; + + let tx_env = self.evm_config.tx_env(&tx); + let hash = tx.tx_hash(); + + // Execute transaction. + let result_and_state = self.evm.transact(tx_env).map_err(move |err| { + // Ensure hash is calculated for error log, if not already done + BlockValidationError::EVM { hash: *hash, error: Box::new(err) } + })?; + + trace!( + target: "evm", + ?tx, + "Executed transaction" + ); + self.system_caller + .on_state(StateChangeSource::Transaction(self.receipts.len()), &result_and_state.state); + let ResultAndState { result, state } = result_and_state; + self.evm.db_mut().commit(state); + + // append gas used + self.gas_used += result.gas_used(); + + self.receipts.push( + match self.receipt_builder.build_receipt(ReceiptBuilderCtx { + tx: tx.tx(), + result, + cumulative_gas_used: self.gas_used, + }) { + Ok(receipt) => receipt, + Err(ctx) => { + let receipt = Receipt { + // Success flag was added in `EIP-658: Embedding transaction status code + // in receipts`. + status: Eip658Value::Eip658(ctx.result.is_success()), + cumulative_gas_used: self.gas_used, + logs: ctx.result.into_logs(), + }; + + self.receipt_builder.build_deposit_receipt(OpDepositReceipt { + inner: receipt, + 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 ensures + // this is only set for post-Canyon deposit + // transactions. + deposit_receipt_version: (tx.is_deposit() && + self.chain_spec + .is_canyon_active_at_timestamp(self.block.timestamp())) + .then_some(1), + }) + } + }, + ); + Ok(()) } diff --git a/examples/custom-beacon-withdrawals/src/main.rs b/examples/custom-beacon-withdrawals/src/main.rs index b82848e853eb..1c41377e2e35 100644 --- a/examples/custom-beacon-withdrawals/src/main.rs +++ b/examples/custom-beacon-withdrawals/src/main.rs @@ -133,9 +133,9 @@ where Ok(()) } - fn execute_transactions<'a>( + fn execute_transaction( &mut self, - _transactions: impl IntoIterator>, + _tx: Recovered<&TransactionSigned>, ) -> Result<(), Self::Error> { Ok(()) } From f1f353edcc92eb4a81adb9babfc0ab514652237e Mon Sep 17 00:00:00 2001 From: int88 <106391185+int88@users.noreply.github.com> Date: Wed, 19 Feb 2025 22:19:24 +0800 Subject: [PATCH 18/21] integration test of network state change (#14575) --- crates/net/network-types/src/peers/config.rs | 6 +++ crates/net/network/tests/it/connect.rs | 42 ++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/crates/net/network-types/src/peers/config.rs b/crates/net/network-types/src/peers/config.rs index 890679f5d34b..221705c3846b 100644 --- a/crates/net/network-types/src/peers/config.rs +++ b/crates/net/network-types/src/peers/config.rs @@ -197,6 +197,12 @@ impl PeersConfig { self } + /// Configure how long to refill outbound slots + pub const fn with_refill_slots_interval(mut self, interval: Duration) -> Self { + self.refill_slots_interval = interval; + self + } + /// Maximum allowed outbound connections. pub const fn with_max_outbound(mut self, max_outbound: usize) -> Self { self.connection_info.max_outbound = max_outbound; diff --git a/crates/net/network/tests/it/connect.rs b/crates/net/network/tests/it/connect.rs index feac0cc516de..d5a0ed5915af 100644 --- a/crates/net/network/tests/it/connect.rs +++ b/crates/net/network/tests/it/connect.rs @@ -636,6 +636,48 @@ async fn test_trusted_peer_only() { assert_eq!(handle.num_connected_peers(), 2); } +#[tokio::test(flavor = "multi_thread")] +async fn test_network_state_change() { + let net = Testnet::create(1).await; + let secret_key = SecretKey::new(&mut rand::thread_rng()); + let peers_config = + PeersConfig::default().with_refill_slots_interval(Duration::from_millis(500)); + + let config = NetworkConfigBuilder::eth(secret_key) + .listener_port(0) + .disable_discovery() + .peer_config(peers_config) + .build(NoopProvider::default()); + + let network = NetworkManager::new(config).await.unwrap(); + + let handle = network.handle().clone(); + tokio::task::spawn(network); + + let mut handles = net.handles(); + let handle0 = handles.next().unwrap(); + + drop(handles); + let _handle = net.spawn(); + + // Set network state to Hibernate. + handle.set_network_hibernate(); + + handle.add_peer(*handle0.peer_id(), handle0.local_addr()); + + // wait 2 seconds, the number of connections is still 0, because network is Hibernate. + tokio::time::sleep(Duration::from_secs(2)).await; + assert_eq!(handle.num_connected_peers(), 0); + + // Set network state to Active. + handle.set_network_active(); + + // wait 2 seconds, the number of connections should be 1, because network is Active and outbound + // slot should be filled. + tokio::time::sleep(Duration::from_secs(2)).await; + assert_eq!(handle.num_connected_peers(), 1); +} + #[tokio::test(flavor = "multi_thread")] async fn test_exceed_outgoing_connections() { let net = Testnet::create(2).await; From 737f7833e81008e025e3a9dba4cad91fcbe821da Mon Sep 17 00:00:00 2001 From: int88 <106391185+int88@users.noreply.github.com> Date: Wed, 19 Feb 2025 22:21:43 +0800 Subject: [PATCH 19/21] peers.add_and_connect(): try to connect even if the peer has been added (#14581) --- crates/net/network/src/peers.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/crates/net/network/src/peers.rs b/crates/net/network/src/peers.rs index fa2efa593f5c..adc95caa27f8 100644 --- a/crates/net/network/src/peers.rs +++ b/crates/net/network/src/peers.rs @@ -788,7 +788,7 @@ impl PeersManager { self.add_and_connect_kind(peer_id, PeerKind::Basic, addr, fork_id) } - /// Connects a peer and its address with the given kind. + /// Connects a peer and its address with the given kind. /// /// Note: This is invoked on demand via an external command received by the manager pub(crate) fn add_and_connect_kind( @@ -803,6 +803,20 @@ impl PeersManager { } match self.peers.entry(peer_id) { + Entry::Occupied(mut entry) => { + let peer = entry.get_mut(); + peer.kind = kind; + peer.fork_id = fork_id; + peer.addr = addr; + + if peer.state == PeerConnectionState::Idle { + // Try connecting again. + peer.state = PeerConnectionState::PendingOut; + self.connection_info.inc_pending_out(); + self.queued_actions + .push_back(PeerAction::Connect { peer_id, remote_addr: addr.tcp() }); + } + } Entry::Vacant(entry) => { trace!(target: "net::peers", ?peer_id, addr=?addr.tcp(), "connects new node"); let mut peer = Peer::with_kind(addr, kind); @@ -813,7 +827,6 @@ impl PeersManager { self.queued_actions .push_back(PeerAction::Connect { peer_id, remote_addr: addr.tcp() }); } - _ => return, } if kind.is_trusted() { @@ -2791,7 +2804,7 @@ mod tests { } #[tokio::test] - async fn test_add_pending_onnect() { + async fn test_add_pending_connect() { let peer = PeerId::random(); let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008); let mut peers = PeersManager::default(); From 36851cc8d889d13d206896fac04a056c8b163581 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 19 Feb 2025 15:41:08 +0100 Subject: [PATCH 20/21] chore: fix codspeed build (#14588) --- .github/scripts/codspeed-build.sh | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/.github/scripts/codspeed-build.sh b/.github/scripts/codspeed-build.sh index 188ecfb883f7..9976a3314c9f 100755 --- a/.github/scripts/codspeed-build.sh +++ b/.github/scripts/codspeed-build.sh @@ -4,20 +4,11 @@ set -eo pipefail # TODO: Benchmarks run WAY too slow due to excessive amount of iterations. cmd=(cargo codspeed build --profile profiling) -excludes=( - # Unnecessary - --exclude reth-libmdbx - # Build is too slow - --exclude reth-network - # Built separately - --exclude reth-transaction-pool - # TODO: some benchmarks panic: https://github.com/paradigmxyz/reth/actions/runs/12307046814/job/34349955788 - --exclude reth-db - --exclude reth-trie-parallel - --exclude reth-engine-tree +crates=( + -p reth-primitives + -p reth-trie + -p reth-trie-common + -p reth-trie-sparse ) -"${cmd[@]}" --features test-utils --workspace "${excludes[@]}" - -# TODO: Slow benchmarks due to too many iterations -## "${cmd[@]}" -p reth-transaction-pool --features test-utils,arbitrary +"${cmd[@]}" --features test-utils "${crates[@]}" From 465af6e0f37b1f8c7c86a1b377da6fa016184fff Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin <5773434+shekhirin@users.noreply.github.com> Date: Wed, 19 Feb 2025 15:37:19 +0000 Subject: [PATCH 21/21] feat(tree): increase state root task thread pool size (#14455) --- crates/engine/tree/src/tree/mod.rs | 2 +- crates/engine/tree/src/tree/root.rs | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/crates/engine/tree/src/tree/mod.rs b/crates/engine/tree/src/tree/mod.rs index ca5b262d9d44..f78f3cd2efd6 100644 --- a/crates/engine/tree/src/tree/mod.rs +++ b/crates/engine/tree/src/tree/mod.rs @@ -671,7 +671,7 @@ where ) -> Self { let (incoming_tx, incoming) = std::sync::mpsc::channel(); - let num_threads = root::thread_pool_size(); + let num_threads = root::rayon_thread_pool_size(); let thread_pool = Arc::new( rayon::ThreadPoolBuilder::new() diff --git a/crates/engine/tree/src/tree/root.rs b/crates/engine/tree/src/tree/root.rs index 463c41927b6e..206992f558c0 100644 --- a/crates/engine/tree/src/tree/root.rs +++ b/crates/engine/tree/src/tree/root.rs @@ -42,14 +42,21 @@ use tracing::{debug, error, trace, trace_span}; /// The level below which the sparse trie hashes are calculated in [`update_sparse_trie`]. const SPARSE_TRIE_INCREMENTAL_LEVEL: usize = 2; -/// Determines the size of the thread pool to be used in [`StateRootTask`]. -/// It should be at least three, one for multiproof calculations plus two to be -/// used internally in [`StateRootTask`]. +/// Determines the size of the rayon thread pool to be used in [`StateRootTask`]. +/// +/// The value is determined as `max(NUM_THREADS - 2, 3)`: +/// - It should leave at least 2 threads to the rest of the system to be used in: +/// - Engine +/// - State Root Task spawned in [`StateRootTask::spawn`] +/// - It should heave at least 3 threads to be used in: +/// - Sparse Trie spawned in [`run_sparse_trie`] +/// - Multiproof computation spawned in [`MultiproofManager::spawn_multiproof`] +/// - Storage root computation spawned in [`ParallelProof::multiproof`] /// /// NOTE: this value can be greater than the available cores in the host, it /// represents the maximum number of threads that can be handled by the pool. -pub(crate) fn thread_pool_size() -> usize { - std::thread::available_parallelism().map_or(3, |num| (num.get() / 2).max(3)) +pub(crate) fn rayon_thread_pool_size() -> usize { + std::thread::available_parallelism().map_or(3, |num| (num.get().saturating_sub(2).max(3))) } /// Determines if the host has enough parallelism to run the state root task. @@ -535,7 +542,7 @@ where fetched_proof_targets: Default::default(), proof_sequencer: ProofSequencer::new(), thread_pool: thread_pool.clone(), - multiproof_manager: MultiproofManager::new(thread_pool, thread_pool_size()), + multiproof_manager: MultiproofManager::new(thread_pool, rayon_thread_pool_size()), metrics: StateRootTaskMetrics::default(), } } @@ -1286,7 +1293,7 @@ mod tests { + Clone + 'static, { - let num_threads = thread_pool_size(); + let num_threads = rayon_thread_pool_size(); let thread_pool = rayon::ThreadPoolBuilder::new() .num_threads(num_threads) @@ -1361,7 +1368,7 @@ mod tests { prefix_sets: Arc::new(input.prefix_sets), }; - let num_threads = thread_pool_size(); + let num_threads = rayon_thread_pool_size(); let state_root_task_pool = rayon::ThreadPoolBuilder::new() .num_threads(num_threads)