From a5be4074e9c22779e4d522a9aa85645592b80bb9 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Thu, 16 Oct 2025 15:49:44 +0200 Subject: [PATCH 1/5] move creation of componenets to node for easier testing --- Cargo.lock | 3 + bin/ev-reth/src/main.rs | 127 +---------------- crates/node/Cargo.toml | 3 + crates/node/src/args.rs | 14 ++ .../ev-reth => crates/node}/src/attributes.rs | 18 +-- {bin/ev-reth => crates/node}/src/error.rs | 5 +- {bin/ev-reth => crates/node}/src/executor.rs | 7 +- crates/node/src/lib.rs | 25 +++- crates/node/src/node.rs | 133 ++++++++++++++++++ .../node/src/payload_service.rs | 64 ++++----- {bin/ev-reth => crates/node}/src/validator.rs | 30 ++-- 11 files changed, 238 insertions(+), 191 deletions(-) create mode 100644 crates/node/src/args.rs rename {bin/ev-reth => crates/node}/src/attributes.rs (89%) rename {bin/ev-reth => crates/node}/src/error.rs (61%) rename {bin/ev-reth => crates/node}/src/executor.rs (92%) create mode 100644 crates/node/src/node.rs rename bin/ev-reth/src/builder.rs => crates/node/src/payload_service.rs (85%) rename {bin/ev-reth => crates/node}/src/validator.rs (87%) diff --git a/Cargo.lock b/Cargo.lock index 7f58edb4..484067fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2811,6 +2811,7 @@ dependencies = [ "alloy-rpc-types", "alloy-rpc-types-engine", "async-trait", + "clap", "ev-common", "ev-revm", "evolve-ev-reth", @@ -2824,6 +2825,8 @@ dependencies = [ "reth-engine-local", "reth-engine-primitives", "reth-errors", + "reth-ethereum", + "reth-ethereum-forks", "reth-ethereum-payload-builder", "reth-ethereum-primitives", "reth-evm", diff --git a/bin/ev-reth/src/main.rs b/bin/ev-reth/src/main.rs index b6d152a5..4071121c 100644 --- a/bin/ev-reth/src/main.rs +++ b/bin/ev-reth/src/main.rs @@ -5,48 +5,16 @@ #![allow(missing_docs, rustdoc::missing_crate_level_docs)] -pub mod attributes; -pub mod builder; -pub mod error; -pub mod executor; -pub mod validator; - -use alloy_rpc_types::engine::{ - ExecutionData, ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, - ExecutionPayloadEnvelopeV4, ExecutionPayloadEnvelopeV5, ExecutionPayloadV1, -}; use clap::Parser; use evolve_ev_reth::{ config::EvolveConfig, - consensus::EvolveConsensusBuilder, rpc::txpool::{EvolveTxpoolApiImpl, EvolveTxpoolApiServer}, }; -use reth_ethereum::{ - chainspec::ChainSpec, - node::{ - api::{EngineTypes, FullNodeTypes, NodeTypes, PayloadTypes}, - builder::{ - components::{BasicPayloadServiceBuilder, ComponentsBuilder}, - rpc::RpcAddOns, - Node, NodeAdapter, - }, - node::{EthereumNetworkBuilder, EthereumPoolBuilder}, - EthereumEthApiBuilder, - }, - primitives::SealedBlock, -}; use reth_ethereum_cli::{chainspec::EthereumChainSpecParser, Cli}; -use reth_payload_builder::EthBuiltPayload; -use serde::{Deserialize, Serialize}; use tracing::info; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; -use crate::{ - attributes::{EvolveEnginePayloadAttributes, EvolveEnginePayloadBuilderAttributes}, - builder::{EvolveArgs, EvolvePayloadBuilderBuilder}, - executor::EvolveExecutorBuilder, - validator::EvolveEngineValidatorBuilder, -}; +use ev_node::{log_startup, EvolveArgs, EvolveNode}; #[global_allocator] static ALLOC: reth_cli_util::allocator::Allocator = reth_cli_util::allocator::new_allocator(); @@ -64,95 +32,6 @@ fn init_otlp_tracing() -> eyre::Result<()> { Ok(()) } -/// Evolve engine types - uses custom payload attributes that support transactions -#[derive(Clone, Debug, Default, Deserialize, Serialize)] -#[non_exhaustive] -pub struct EvolveEngineTypes; - -impl PayloadTypes for EvolveEngineTypes { - type ExecutionData = ExecutionData; - type BuiltPayload = EthBuiltPayload; - type PayloadAttributes = EvolveEnginePayloadAttributes; - type PayloadBuilderAttributes = EvolveEnginePayloadBuilderAttributes; - - fn block_to_payload( - block: SealedBlock< - <::Primitives as reth_ethereum::node::api::NodePrimitives>::Block, - >, - ) -> ExecutionData { - let (payload, sidecar) = - reth_ethereum::rpc::types::engine::ExecutionPayload::from_block_unchecked( - block.hash(), - &block.into_block(), - ); - ExecutionData { payload, sidecar } - } -} - -impl EngineTypes for EvolveEngineTypes { - type ExecutionPayloadEnvelopeV1 = ExecutionPayloadV1; - type ExecutionPayloadEnvelopeV2 = ExecutionPayloadEnvelopeV2; - type ExecutionPayloadEnvelopeV3 = ExecutionPayloadEnvelopeV3; - type ExecutionPayloadEnvelopeV4 = ExecutionPayloadEnvelopeV4; - type ExecutionPayloadEnvelopeV5 = ExecutionPayloadEnvelopeV5; -} - -/// Evolve node type -#[derive(Debug, Clone, Default)] -#[non_exhaustive] -pub struct EvolveNode { - /// Evolve-specific arguments - pub args: EvolveArgs, -} - -impl EvolveNode { - /// Create a new evolve node with the given arguments - pub const fn new(args: EvolveArgs) -> Self { - Self { args } - } -} - -impl NodeTypes for EvolveNode { - type Primitives = reth_ethereum::EthPrimitives; - type ChainSpec = ChainSpec; - type Storage = reth_ethereum::provider::EthStorage; - type Payload = EvolveEngineTypes; -} - -/// Evolve node addons configuring RPC types with custom engine validator -pub type EvolveNodeAddOns = RpcAddOns; - -impl Node for EvolveNode -where - N: FullNodeTypes, -{ - type ComponentsBuilder = ComponentsBuilder< - N, - EthereumPoolBuilder, - BasicPayloadServiceBuilder, - EthereumNetworkBuilder, - EvolveExecutorBuilder, - EvolveConsensusBuilder, - >; - type AddOns = EvolveNodeAddOns>; - - fn components_builder(&self) -> Self::ComponentsBuilder { - ComponentsBuilder::default() - .node_types::() - .pool(EthereumPoolBuilder::default()) - .executor(EvolveExecutorBuilder::default()) - .payload(BasicPayloadServiceBuilder::new( - EvolvePayloadBuilderBuilder::new(&self.args), - )) - .network(EthereumNetworkBuilder::default()) - .consensus(EvolveConsensusBuilder::default()) - } - - fn add_ons(&self) -> Self::AddOns { - EvolveNodeAddOns::default() - } -} - fn main() { info!("=== EV-RETH NODE STARTING ==="); @@ -173,9 +52,7 @@ fn main() { if let Err(err) = Cli::::parse().run( async move |builder, evolve_args| { - info!("=== EV-RETH: Starting with args: {:?} ===", evolve_args); - info!("=== EV-RETH: Evolve node mode enabled ==="); - info!("=== EV-RETH: Using custom payload builder with transaction support ==="); + log_startup(&evolve_args); let handle = builder .node(EvolveNode::new(evolve_args)) .extend_rpc_modules(move |ctx| { diff --git a/crates/node/Cargo.toml b/crates/node/Cargo.toml index e589e791..f2d7813a 100644 --- a/crates/node/Cargo.toml +++ b/crates/node/Cargo.toml @@ -17,6 +17,8 @@ ev-revm = { path = "../ev-revm" } # Reth dependencies reth-node-builder.workspace = true reth-chainspec.workspace = true +reth-ethereum = { workspace = true, features = ["node", "cli", "pool"] } +reth-ethereum-forks.workspace = true reth-ethereum-payload-builder.workspace = true reth-payload-primitives.workspace = true reth-primitives.workspace = true @@ -60,6 +62,7 @@ serde_json.workspace = true thiserror.workspace = true async-trait.workspace = true futures.workspace = true +clap.workspace = true [dev-dependencies] # Test dependencies diff --git a/crates/node/src/args.rs b/crates/node/src/args.rs new file mode 100644 index 00000000..1bd120ce --- /dev/null +++ b/crates/node/src/args.rs @@ -0,0 +1,14 @@ +use clap::Parser; +use serde::{Deserialize, Serialize}; + +/// Evolve-specific command line arguments. +#[derive(Debug, Clone, Parser, PartialEq, Eq, Serialize, Deserialize, Default)] +pub struct EvolveArgs { + /// Enable Evolve mode for the node (enabled by default). + #[arg( + long = "ev-reth.enable", + default_value = "true", + help = "Enable Evolve integration for transaction processing via Engine API" + )] + pub enable_evolve: bool, +} diff --git a/bin/ev-reth/src/attributes.rs b/crates/node/src/attributes.rs similarity index 89% rename from bin/ev-reth/src/attributes.rs rename to crates/node/src/attributes.rs index 9ec33009..2b1d4070 100644 --- a/bin/ev-reth/src/attributes.rs +++ b/crates/node/src/attributes.rs @@ -13,15 +13,15 @@ use serde::{Deserialize, Serialize}; use crate::error::EvolveEngineError; -/// Evolve payload attributes that support passing transactions via Engine API +/// Evolve payload attributes that support passing transactions via Engine API. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct EvolveEnginePayloadAttributes { - /// Standard Ethereum payload attributes + /// Standard Ethereum payload attributes. #[serde(flatten)] pub inner: EthPayloadAttributes, - /// Transactions to be included in the payload (passed via Engine API) + /// Transactions to be included in the payload (passed via Engine API). pub transactions: Option>, - /// Optional gas limit for the payload + /// Optional gas limit for the payload. #[serde(rename = "gasLimit")] pub gas_limit: Option, } @@ -40,14 +40,14 @@ impl PayloadAttributes for EvolveEnginePayloadAttributes { } } -/// Evolve payload builder attributes +/// Evolve payload builder attributes. #[derive(Clone, Debug, PartialEq, Eq)] pub struct EvolveEnginePayloadBuilderAttributes { - /// Ethereum payload builder attributes + /// Ethereum payload builder attributes. pub ethereum_attributes: EthPayloadBuilderAttributes, - /// Decoded transactions from the Engine API + /// Decoded transactions from the Engine API. pub transactions: Vec, - /// Gas limit for the payload + /// Gas limit for the payload. pub gas_limit: Option, } @@ -62,7 +62,7 @@ impl PayloadBuilderAttributes for EvolveEnginePayloadBuilderAttributes { ) -> Result { let ethereum_attributes = EthPayloadBuilderAttributes::new(parent, attributes.inner); - // Decode transactions from bytes if provided + // Decode transactions from bytes if provided. let transactions = attributes .transactions .unwrap_or_default() diff --git a/bin/ev-reth/src/error.rs b/crates/node/src/error.rs similarity index 61% rename from bin/ev-reth/src/error.rs rename to crates/node/src/error.rs index d3bfe205..d1515958 100644 --- a/bin/ev-reth/src/error.rs +++ b/crates/node/src/error.rs @@ -1,13 +1,16 @@ use evolve_ev_reth::PayloadAttributesError; use thiserror::Error; -/// Custom error type used in payload attributes validation +/// Custom error type used in payload attributes validation. #[derive(Debug, Error)] pub enum EvolveEngineError { + /// Provided transaction bytes failed to decode. #[error("Invalid transaction data: {0}")] InvalidTransactionData(String), + /// Requested payload exceeded allowed gas limit. #[error("Gas limit exceeded")] GasLimitExceeded, + /// Underlying evolve payload attribute validation failed. #[error("Evolve payload attributes error: {0}")] PayloadAttributes(#[from] PayloadAttributesError), } diff --git a/bin/ev-reth/src/executor.rs b/crates/node/src/executor.rs similarity index 92% rename from bin/ev-reth/src/executor.rs rename to crates/node/src/executor.rs index 4ac0b734..aedfd546 100644 --- a/bin/ev-reth/src/executor.rs +++ b/crates/node/src/executor.rs @@ -1,7 +1,6 @@ //! Helpers to build the ev-reth executor with EV-specific hooks applied. use alloy_evm::eth::{spec::EthExecutorSpec, EthEvmFactory}; -use ev_node::EvolvePayloadBuilderConfig; use ev_revm::{with_ev_handler, BaseFeeRedirect, EvEvmFactory}; use reth_chainspec::ChainSpec; use reth_ethereum::{ @@ -16,13 +15,15 @@ use reth_ethereum_forks::Hardforks; use reth_node_builder::PayloadBuilderConfig; use tracing::info; +use crate::{config::EvolvePayloadBuilderConfig, EvolveNode}; + /// Type alias for the EV-aware EVM config we install into the node. pub type EvolveEvmConfig = EthEvmConfig>; /// Builds the EV-aware EVM configuration by wrapping the default config with the EV handler. pub fn build_evm_config(ctx: &BuilderContext) -> eyre::Result where - Node: FullNodeTypes, + Node: FullNodeTypes, ChainSpec: Hardforks + EthExecutorSpec + EthereumHardforks, { let chain_spec = ctx.chain_spec(); @@ -51,7 +52,7 @@ pub struct EvolveExecutorBuilder; impl RethExecutorBuilder for EvolveExecutorBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes, ChainSpec: Hardforks + EthExecutorSpec + EthereumHardforks, { type EVM = EvolveEvmConfig; diff --git a/crates/node/src/lib.rs b/crates/node/src/lib.rs index e4863b4d..a835ee3f 100644 --- a/crates/node/src/lib.rs +++ b/crates/node/src/lib.rs @@ -5,11 +5,32 @@ //! - Node configuration //! - RPC interfaces +/// CLI argument handling for evolve-specific options. +pub mod args; +/// Evolve-specific payload attribute wiring. +pub mod attributes; /// Builder module for payload construction and related utilities. pub mod builder; -/// Configuration types and validation for the Evolve payload builder +/// Configuration types and validation for the Evolve payload builder. pub mod config; +/// Shared error types for evolve node wiring. +pub mod error; +/// Executor wiring for EV aware execution. +pub mod executor; +/// Node composition and payload types. +pub mod node; +/// Payload service integration. +pub mod payload_service; +/// Payload validator integration. +pub mod validator; -// Re-export public types +// Re-export public types for convenience. +pub use args::EvolveArgs; +pub use attributes::{EvolveEnginePayloadAttributes, EvolveEnginePayloadBuilderAttributes}; pub use builder::{create_payload_builder_service, EvolvePayloadBuilder}; pub use config::{ConfigError, EvolvePayloadBuilderConfig}; +pub use error::EvolveEngineError; +pub use executor::{build_evm_config, EvolveEvmConfig, EvolveExecutorBuilder}; +pub use node::{log_startup, parse_args, EvolveEngineTypes, EvolveNode, EvolveNodeAddOns}; +pub use payload_service::{EvolveEnginePayloadBuilder, EvolvePayloadBuilderBuilder}; +pub use validator::{EvolveEngineValidator, EvolveEngineValidatorBuilder}; diff --git a/crates/node/src/node.rs b/crates/node/src/node.rs new file mode 100644 index 00000000..87782844 --- /dev/null +++ b/crates/node/src/node.rs @@ -0,0 +1,133 @@ +//! Node wiring for ev-reth, including payload types and component assembly. + +use alloy_rpc_types::engine::{ + ExecutionData, ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, + ExecutionPayloadEnvelopeV4, ExecutionPayloadEnvelopeV5, ExecutionPayloadV1, +}; +use clap::Parser; +use reth_ethereum::{ + chainspec::ChainSpec, + node::{ + api::{EngineTypes, FullNodeTypes, NodeTypes, PayloadTypes}, + builder::{ + components::{BasicPayloadServiceBuilder, ComponentsBuilder}, + rpc::RpcAddOns, + Node, NodeAdapter, + }, + node::{EthereumNetworkBuilder, EthereumPoolBuilder}, + EthereumEthApiBuilder, + }, + primitives::SealedBlock, +}; +use reth_payload_builder::EthBuiltPayload; +use serde::{Deserialize, Serialize}; +use tracing::info; + +use crate::{ + args::EvolveArgs, + attributes::{EvolveEnginePayloadAttributes, EvolveEnginePayloadBuilderAttributes}, + executor::EvolveExecutorBuilder, + payload_service::EvolvePayloadBuilderBuilder, + validator::EvolveEngineValidatorBuilder, +}; + +/// Evolve engine types - uses custom payload attributes that support transactions. +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +#[non_exhaustive] +pub struct EvolveEngineTypes; + +impl PayloadTypes for EvolveEngineTypes { + type ExecutionData = ExecutionData; + type BuiltPayload = EthBuiltPayload; + type PayloadAttributes = EvolveEnginePayloadAttributes; + type PayloadBuilderAttributes = EvolveEnginePayloadBuilderAttributes; + + fn block_to_payload( + block: SealedBlock< + <::Primitives as reth_ethereum::node::api::NodePrimitives>::Block, + >, + ) -> ExecutionData { + let (payload, sidecar) = + reth_ethereum::rpc::types::engine::ExecutionPayload::from_block_unchecked( + block.hash(), + &block.into_block(), + ); + ExecutionData { payload, sidecar } + } +} + +impl EngineTypes for EvolveEngineTypes { + type ExecutionPayloadEnvelopeV1 = ExecutionPayloadV1; + type ExecutionPayloadEnvelopeV2 = ExecutionPayloadEnvelopeV2; + type ExecutionPayloadEnvelopeV3 = ExecutionPayloadEnvelopeV3; + type ExecutionPayloadEnvelopeV4 = ExecutionPayloadEnvelopeV4; + type ExecutionPayloadEnvelopeV5 = ExecutionPayloadEnvelopeV5; +} + +/// Evolve node type. +#[derive(Debug, Clone, Default)] +#[non_exhaustive] +pub struct EvolveNode { + /// Evolve-specific arguments. + pub args: EvolveArgs, +} + +impl EvolveNode { + /// Create a new evolve node with the given arguments. + pub const fn new(args: EvolveArgs) -> Self { + Self { args } + } +} + +impl NodeTypes for EvolveNode { + type Primitives = reth_ethereum::EthPrimitives; + type ChainSpec = ChainSpec; + type Storage = reth_ethereum::provider::EthStorage; + type Payload = EvolveEngineTypes; +} + +/// Evolve node addons configuring RPC types with custom engine validator. +pub type EvolveNodeAddOns = RpcAddOns; + +impl Node for EvolveNode +where + N: FullNodeTypes, +{ + type ComponentsBuilder = ComponentsBuilder< + N, + EthereumPoolBuilder, + BasicPayloadServiceBuilder, + EthereumNetworkBuilder, + EvolveExecutorBuilder, + evolve_ev_reth::consensus::EvolveConsensusBuilder, + >; + type AddOns = EvolveNodeAddOns>; + + fn components_builder(&self) -> Self::ComponentsBuilder { + ComponentsBuilder::default() + .node_types::() + .pool(EthereumPoolBuilder::default()) + .executor(EvolveExecutorBuilder::default()) + .payload(BasicPayloadServiceBuilder::new( + EvolvePayloadBuilderBuilder::new(&self.args), + )) + .network(EthereumNetworkBuilder::default()) + .consensus(evolve_ev_reth::consensus::EvolveConsensusBuilder::default()) + } + + fn add_ons(&self) -> Self::AddOns { + EvolveNodeAddOns::default() + } +} + +/// Helper logging to announce node startup with args. +pub fn log_startup(args: &EvolveArgs) { + info!("=== EV-RETH: Starting with args: {:?} ===", args); + info!("=== EV-RETH: Evolve node mode enabled ==="); + info!("=== EV-RETH: Using custom payload builder with transaction support ==="); +} + +/// Ensure Clap derives are linked when this crate is used without the binary. +pub fn parse_args() -> EvolveArgs { + EvolveArgs::parse() +} diff --git a/bin/ev-reth/src/builder.rs b/crates/node/src/payload_service.rs similarity index 85% rename from bin/ev-reth/src/builder.rs rename to crates/node/src/payload_service.rs index f8a49388..ca19646f 100644 --- a/bin/ev-reth/src/builder.rs +++ b/crates/node/src/payload_service.rs @@ -1,7 +1,8 @@ +use std::sync::Arc; + use alloy_primitives::{Address, U256}; -use clap::Parser; -use ev_node::{EvolvePayloadBuilder, EvolvePayloadBuilderConfig}; use evolve_ev_reth::EvolvePayloadAttributes; +use eyre::WrapErr; use reth_basic_payload_builder::{ BuildArguments, BuildOutcome, HeaderForPayload, MissingPayloadBehaviour, PayloadBuilder, PayloadConfig, @@ -19,28 +20,18 @@ use reth_ethereum::{ use reth_payload_builder::{EthBuiltPayload, PayloadBuilderError}; use reth_provider::HeaderProvider; use reth_revm::cached::CachedReads; -use serde::{Deserialize, Serialize}; -use std::sync::Arc; +use tokio::runtime::Handle; use tracing::info; use crate::{ - attributes::EvolveEnginePayloadBuilderAttributes, executor::EvolveEvmConfig, EvolveEngineTypes, + args::EvolveArgs, attributes::EvolveEnginePayloadBuilderAttributes, + builder::EvolvePayloadBuilder, config::EvolvePayloadBuilderConfig, executor::EvolveEvmConfig, + node::EvolveEngineTypes, }; -use evolve_ev_reth::config::set_current_block_gas_limit; -/// Evolve-specific command line arguments -#[derive(Debug, Clone, Parser, PartialEq, Eq, Serialize, Deserialize, Default)] -pub struct EvolveArgs { - /// Enable Evolve mode for the node (enabled by default) - #[arg( - long = "ev-reth.enable", - default_value = "true", - help = "Enable Evolve integration for transaction processing via Engine API" - )] - pub enable_evolve: bool, -} +use evolve_ev_reth::config::set_current_block_gas_limit; -/// Evolve payload service builder that integrates with the evolve payload builder +/// Evolve payload service builder that integrates with the evolve payload builder. #[derive(Debug, Clone)] #[non_exhaustive] pub struct EvolvePayloadBuilderBuilder { @@ -48,7 +39,7 @@ pub struct EvolvePayloadBuilderBuilder { } impl EvolvePayloadBuilderBuilder { - /// Create a new builder with evolve args + /// Create a new builder with evolve args. pub fn new(_args: &EvolveArgs) -> Self { let config = EvolvePayloadBuilderConfig::new(); info!("Created Evolve payload builder with config: {:?}", config); @@ -62,7 +53,7 @@ impl Default for EvolvePayloadBuilderBuilder { } } -/// The evolve engine payload builder that integrates with the evolve payload builder +/// The evolve engine payload builder that integrates with the evolve payload builder. #[derive(Debug, Clone)] pub struct EvolveEnginePayloadBuilder where @@ -98,7 +89,8 @@ where evm_config: EvolveEvmConfig, ) -> eyre::Result { let chain_spec = ctx.chain_spec(); - let mut config = EvolvePayloadBuilderConfig::from_chain_spec(&chain_spec)?; + let mut config = EvolvePayloadBuilderConfig::from_chain_spec(&chain_spec) + .wrap_err("failed to load evolve config from chain spec")?; if self.config.base_fee_sink.is_some() { config.base_fee_sink = self.config.base_fee_sink; @@ -154,10 +146,10 @@ where attributes.transactions.len() ); - // Convert Engine API attributes to Evolve payload attributes - // If no gas_limit provided, default to the parent header's gas limit (genesis for first block) + // Convert Engine API attributes to Evolve payload attributes. + // If no gas_limit provided, default to the parent header's gas limit (genesis for first block). let effective_gas_limit = attributes.gas_limit.unwrap_or(parent_header.gas_limit); - // Publish effective gas limit for RPC alignment + // Publish effective gas limit for RPC alignment. set_current_block_gas_limit(effective_gas_limit); let mut fee_recipient = attributes.suggested_fee_recipient(); @@ -182,10 +174,10 @@ where parent_header.number + 1, ); - // Build the payload using the evolve payload builder - use spawn_blocking for async work + // Build the payload using the evolve payload builder - use spawn_blocking for async work. let evolve_builder = self.evolve_builder.clone(); let sealed_block = tokio::task::block_in_place(|| { - tokio::runtime::Handle::current().block_on(evolve_builder.build_payload(evolve_attrs)) + Handle::current().block_on(evolve_builder.build_payload(evolve_attrs)) }) .map_err(PayloadBuilderError::other)?; @@ -195,13 +187,13 @@ where sealed_block.gas_used ); - // Convert to EthBuiltPayload + // Convert to EthBuiltPayload. let gas_used = sealed_block.gas_used; let built_payload = EthBuiltPayload::new( - attributes.payload_id(), // Use the proper payload ID from attributes + attributes.payload_id(), // Use the proper payload ID from attributes. Arc::new(sealed_block), - U256::from(gas_used), // Block gas used - None, // No blob sidecar for evolve + U256::from(gas_used), // Block gas used. + None, // No blob sidecar for evolve. ); Ok(BuildOutcome::Better { @@ -221,10 +213,10 @@ where info!("Evolve engine payload builder: building empty payload"); - // Create empty evolve attributes (no transactions) - // If no gas_limit provided, default to the parent header's gas limit (genesis for first block) + // Create empty evolve attributes (no transactions). + // If no gas_limit provided, default to the parent header's gas limit (genesis for first block). let effective_gas_limit = attributes.gas_limit.unwrap_or(parent_header.gas_limit); - // Publish effective gas limit for RPC alignment + // Publish effective gas limit for RPC alignment. set_current_block_gas_limit(effective_gas_limit); let mut fee_recipient = attributes.suggested_fee_recipient(); @@ -249,10 +241,10 @@ where parent_header.number + 1, ); - // Build empty payload - use spawn_blocking for async work + // Build empty payload - use spawn_blocking for async work. let evolve_builder = self.evolve_builder.clone(); let sealed_block = tokio::task::block_in_place(|| { - tokio::runtime::Handle::current().block_on(evolve_builder.build_payload(evolve_attrs)) + Handle::current().block_on(evolve_builder.build_payload(evolve_attrs)) }) .map_err(PayloadBuilderError::other)?; @@ -268,7 +260,7 @@ where /// Determines how to handle a request for a payload that is currently being built. /// /// This will always await the in-progress job, preventing a race with a new build. - /// This is the recommended behavior to prevent redundant payload builds + /// This is the recommended behavior to prevent redundant payload builds. fn on_missing_payload( &self, _args: BuildArguments, diff --git a/bin/ev-reth/src/validator.rs b/crates/node/src/validator.rs similarity index 87% rename from bin/ev-reth/src/validator.rs rename to crates/node/src/validator.rs index e3e048ad..5b1e2853 100644 --- a/bin/ev-reth/src/validator.rs +++ b/crates/node/src/validator.rs @@ -1,7 +1,8 @@ #![allow(missing_docs, rustdoc::missing_crate_level_docs)] -use alloy_rpc_types::engine::ExecutionData; +use std::sync::Arc; +use alloy_rpc_types::engine::ExecutionData; use reth_ethereum::{ chainspec::ChainSpec, node::{ @@ -16,12 +17,11 @@ use reth_ethereum::{ }; use reth_ethereum_payload_builder::EthereumExecutionPayloadValidator; use reth_primitives_traits::{Block as _, RecoveredBlock}; -use std::sync::Arc; use tracing::info; -use crate::{attributes::EvolveEnginePayloadAttributes, EvolveEngineTypes}; +use crate::{attributes::EvolveEnginePayloadAttributes, node::EvolveEngineTypes}; -/// Evolve engine validator that handles custom payload validation +/// Evolve engine validator that handles custom payload validation. #[derive(Debug, Clone)] pub struct EvolveEngineValidator { inner: EthereumExecutionPayloadValidator, @@ -42,7 +42,7 @@ impl EvolveEngineValidator { } } -impl PayloadValidator for EvolveEngineValidator { +impl PayloadValidator for EvolveEngineValidator { type Block = reth_ethereum::Block; fn ensure_well_formed_payload( @@ -51,7 +51,7 @@ impl PayloadValidator for EvolveEngineValidator { ) -> Result, NewPayloadError> { info!("Evolve engine validator: validating payload"); - // Use inner validator but with custom evolve handling + // Use inner validator but with custom evolve handling. match self.inner.ensure_well_formed_payload(payload.clone()) { Ok(sealed_block) => { info!("Evolve engine validator: payload validation succeeded"); @@ -60,20 +60,20 @@ impl PayloadValidator for EvolveEngineValidator { .map_err(|e| NewPayloadError::Other(e.into())) } Err(err) => { - // Log the error for debugging + // Log the error for debugging. tracing::debug!("Evolve payload validation error: {:?}", err); - // Check if this is a block hash mismatch error - bypass it for evolve + // Check if this is a block hash mismatch error - bypass it for evolve. if matches!(err, alloy_rpc_types::engine::PayloadError::BlockHash { .. }) { info!("Evolve engine validator: bypassing block hash mismatch for ev-reth"); - // For evolve, we trust the payload builder - just parse the block without hash validation + // For evolve, we trust the payload builder - just parse the block without hash validation. let ExecutionData { payload, sidecar } = payload; let sealed_block = payload.try_into_block_with_sidecar(&sidecar)?.seal_slow(); sealed_block .try_recover() .map_err(|e| NewPayloadError::Other(e.into())) } else { - // For other errors, re-throw them + // For other errors, re-throw them. Err(NewPayloadError::Eth(err)) } } @@ -82,15 +82,15 @@ impl PayloadValidator for EvolveEngineValidator { fn validate_payload_attributes_against_header( &self, - _attr: &crate::attributes::EvolveEnginePayloadAttributes, + _attr: &EvolveEnginePayloadAttributes, _header: &::Header, ) -> Result<(), InvalidPayloadAttributesError> { - // Skip default timestamp validation for evolve + // Skip default timestamp validation for evolve. Ok(()) } } -impl EngineApiValidator for EvolveEngineValidator { +impl EngineApiValidator for EvolveEngineValidator { fn validate_version_specific_fields( &self, version: EngineApiMessageVersion, @@ -112,7 +112,7 @@ impl EngineApiValidator for EvolveEngineValidator { ), )?; - // Validate evolve-specific attributes + // Validate evolve-specific attributes. if let Some(ref transactions) = attributes.transactions { info!( "Evolve engine validator: validating {} transactions", @@ -124,7 +124,7 @@ impl EngineApiValidator for EvolveEngineValidator { } } -/// Evolve engine validator builder +/// Evolve engine validator builder. #[derive(Debug, Default, Clone, Copy)] #[non_exhaustive] pub struct EvolveEngineValidatorBuilder; From e0712025ea1d4d0c938c6a1dc3b7dfef519a33da Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Thu, 16 Oct 2025 16:01:05 +0200 Subject: [PATCH 2/5] remove dead flag --- crates/node/src/args.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/crates/node/src/args.rs b/crates/node/src/args.rs index 1bd120ce..7caeb34e 100644 --- a/crates/node/src/args.rs +++ b/crates/node/src/args.rs @@ -1,14 +1,5 @@ use clap::Parser; -use serde::{Deserialize, Serialize}; -/// Evolve-specific command line arguments. -#[derive(Debug, Clone, Parser, PartialEq, Eq, Serialize, Deserialize, Default)] -pub struct EvolveArgs { - /// Enable Evolve mode for the node (enabled by default). - #[arg( - long = "ev-reth.enable", - default_value = "true", - help = "Enable Evolve integration for transaction processing via Engine API" - )] - pub enable_evolve: bool, -} +/// Evolve CLI arguments (currently empty; reserved for future toggles). +#[derive(Debug, Clone, Parser, PartialEq, Eq, Default)] +pub struct EvolveArgs {} From d7fe4d32d9fdb99480e3ad2c9caa0f99b765e49c Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Thu, 16 Oct 2025 16:18:12 +0200 Subject: [PATCH 3/5] remove unused pool --- bin/ev-reth/src/main.rs | 12 ++++++------ crates/node/src/args.rs | 4 ++-- crates/node/src/lib.rs | 2 +- crates/node/src/node.rs | 21 +++++---------------- crates/node/src/payload_service.rs | 23 +++++++++-------------- 5 files changed, 23 insertions(+), 39 deletions(-) diff --git a/bin/ev-reth/src/main.rs b/bin/ev-reth/src/main.rs index 4071121c..26e7f3b5 100644 --- a/bin/ev-reth/src/main.rs +++ b/bin/ev-reth/src/main.rs @@ -50,11 +50,11 @@ fn main() { } } - if let Err(err) = Cli::::parse().run( - async move |builder, evolve_args| { - log_startup(&evolve_args); + if let Err(err) = Cli::::parse() + .run(|builder, _evolve_args| async move { + log_startup(); let handle = builder - .node(EvolveNode::new(evolve_args)) + .node(EvolveNode::new()) .extend_rpc_modules(move |ctx| { // Build custom txpool RPC with config + optional CLI/env override let evolve_cfg = EvolveConfig::default(); @@ -70,8 +70,8 @@ fn main() { info!("=== EV-RETH: Node launched successfully with ev-reth payload builder ==="); handle.node_exit_future.await - }, - ) { + }) + { eprintln!("Error: {err:?}"); std::process::exit(1); } diff --git a/crates/node/src/args.rs b/crates/node/src/args.rs index 7caeb34e..65f45a2d 100644 --- a/crates/node/src/args.rs +++ b/crates/node/src/args.rs @@ -1,5 +1,5 @@ -use clap::Parser; +use clap::Args; /// Evolve CLI arguments (currently empty; reserved for future toggles). -#[derive(Debug, Clone, Parser, PartialEq, Eq, Default)] +#[derive(Debug, Clone, Default, Args)] pub struct EvolveArgs {} diff --git a/crates/node/src/lib.rs b/crates/node/src/lib.rs index a835ee3f..8591d284 100644 --- a/crates/node/src/lib.rs +++ b/crates/node/src/lib.rs @@ -31,6 +31,6 @@ pub use builder::{create_payload_builder_service, EvolvePayloadBuilder}; pub use config::{ConfigError, EvolvePayloadBuilderConfig}; pub use error::EvolveEngineError; pub use executor::{build_evm_config, EvolveEvmConfig, EvolveExecutorBuilder}; -pub use node::{log_startup, parse_args, EvolveEngineTypes, EvolveNode, EvolveNodeAddOns}; +pub use node::{log_startup, EvolveEngineTypes, EvolveNode, EvolveNodeAddOns}; pub use payload_service::{EvolveEnginePayloadBuilder, EvolvePayloadBuilderBuilder}; pub use validator::{EvolveEngineValidator, EvolveEngineValidatorBuilder}; diff --git a/crates/node/src/node.rs b/crates/node/src/node.rs index 87782844..6a3cbfb1 100644 --- a/crates/node/src/node.rs +++ b/crates/node/src/node.rs @@ -4,7 +4,6 @@ use alloy_rpc_types::engine::{ ExecutionData, ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4, ExecutionPayloadEnvelopeV5, ExecutionPayloadV1, }; -use clap::Parser; use reth_ethereum::{ chainspec::ChainSpec, node::{ @@ -24,7 +23,6 @@ use serde::{Deserialize, Serialize}; use tracing::info; use crate::{ - args::EvolveArgs, attributes::{EvolveEnginePayloadAttributes, EvolveEnginePayloadBuilderAttributes}, executor::EvolveExecutorBuilder, payload_service::EvolvePayloadBuilderBuilder, @@ -67,15 +65,12 @@ impl EngineTypes for EvolveEngineTypes { /// Evolve node type. #[derive(Debug, Clone, Default)] #[non_exhaustive] -pub struct EvolveNode { - /// Evolve-specific arguments. - pub args: EvolveArgs, -} +pub struct EvolveNode {} impl EvolveNode { /// Create a new evolve node with the given arguments. - pub const fn new(args: EvolveArgs) -> Self { - Self { args } + pub const fn new() -> Self { + Self {} } } @@ -109,7 +104,7 @@ where .pool(EthereumPoolBuilder::default()) .executor(EvolveExecutorBuilder::default()) .payload(BasicPayloadServiceBuilder::new( - EvolvePayloadBuilderBuilder::new(&self.args), + EvolvePayloadBuilderBuilder::new(), )) .network(EthereumNetworkBuilder::default()) .consensus(evolve_ev_reth::consensus::EvolveConsensusBuilder::default()) @@ -121,13 +116,7 @@ where } /// Helper logging to announce node startup with args. -pub fn log_startup(args: &EvolveArgs) { - info!("=== EV-RETH: Starting with args: {:?} ===", args); +pub fn log_startup() { info!("=== EV-RETH: Evolve node mode enabled ==="); info!("=== EV-RETH: Using custom payload builder with transaction support ==="); } - -/// Ensure Clap derives are linked when this crate is used without the binary. -pub fn parse_args() -> EvolveArgs { - EvolveArgs::parse() -} diff --git a/crates/node/src/payload_service.rs b/crates/node/src/payload_service.rs index ca19646f..69979666 100644 --- a/crates/node/src/payload_service.rs +++ b/crates/node/src/payload_service.rs @@ -24,9 +24,8 @@ use tokio::runtime::Handle; use tracing::info; use crate::{ - args::EvolveArgs, attributes::EvolveEnginePayloadBuilderAttributes, - builder::EvolvePayloadBuilder, config::EvolvePayloadBuilderConfig, executor::EvolveEvmConfig, - node::EvolveEngineTypes, + attributes::EvolveEnginePayloadBuilderAttributes, builder::EvolvePayloadBuilder, + config::EvolvePayloadBuilderConfig, executor::EvolveEvmConfig, node::EvolveEngineTypes, }; use evolve_ev_reth::config::set_current_block_gas_limit; @@ -40,7 +39,7 @@ pub struct EvolvePayloadBuilderBuilder { impl EvolvePayloadBuilderBuilder { /// Create a new builder with evolve args. - pub fn new(_args: &EvolveArgs) -> Self { + pub fn new() -> Self { let config = EvolvePayloadBuilderConfig::new(); info!("Created Evolve payload builder with config: {:?}", config); Self { config } @@ -49,21 +48,17 @@ impl EvolvePayloadBuilderBuilder { impl Default for EvolvePayloadBuilderBuilder { fn default() -> Self { - Self::new(&EvolveArgs::default()) + Self::new() } } /// The evolve engine payload builder that integrates with the evolve payload builder. #[derive(Debug, Clone)] -pub struct EvolveEnginePayloadBuilder +pub struct EvolveEnginePayloadBuilder where - Pool: Clone, Client: Clone, { pub(crate) evolve_builder: Arc>, - #[allow(dead_code)] - pub(crate) pool: Pool, - #[allow(dead_code)] pub(crate) config: EvolvePayloadBuilderConfig, } @@ -80,7 +75,7 @@ where + Unpin + 'static, { - type PayloadBuilder = EvolveEnginePayloadBuilder; + type PayloadBuilder = EvolveEnginePayloadBuilder; async fn build_payload_builder( self, @@ -98,6 +93,8 @@ where config.validate()?; + let _ = pool; + let evolve_builder = Arc::new(EvolvePayloadBuilder::new( Arc::new(ctx.provider().clone()), evm_config, @@ -106,13 +103,12 @@ where Ok(EvolveEnginePayloadBuilder { evolve_builder, - pool, config, }) } } -impl PayloadBuilder for EvolveEnginePayloadBuilder +impl PayloadBuilder for EvolveEnginePayloadBuilder where Client: reth_ethereum::provider::StateProviderFactory + ChainSpecProvider @@ -121,7 +117,6 @@ where + Send + Sync + 'static, - Pool: TransactionPool>, { type Attributes = EvolveEnginePayloadBuilderAttributes; type BuiltPayload = EthBuiltPayload; From ebe382de920253b6b8e530340ad785088b0f9dc6 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Thu, 16 Oct 2025 16:25:51 +0200 Subject: [PATCH 4/5] fmt --- bin/ev-reth/src/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/ev-reth/src/main.rs b/bin/ev-reth/src/main.rs index 26e7f3b5..7a264e67 100644 --- a/bin/ev-reth/src/main.rs +++ b/bin/ev-reth/src/main.rs @@ -50,8 +50,8 @@ fn main() { } } - if let Err(err) = Cli::::parse() - .run(|builder, _evolve_args| async move { + if let Err(err) = Cli::::parse().run( + |builder, _evolve_args| async move { log_startup(); let handle = builder .node(EvolveNode::new()) @@ -70,8 +70,8 @@ fn main() { info!("=== EV-RETH: Node launched successfully with ev-reth payload builder ==="); handle.node_exit_future.await - }) - { + }, + ) { eprintln!("Error: {err:?}"); std::process::exit(1); } From 3577e6fa3b097f62d7e67bc8e6db0741462ba4e2 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Thu, 16 Oct 2025 16:29:07 +0200 Subject: [PATCH 5/5] remove unused pool --- crates/node/src/payload_service.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/node/src/payload_service.rs b/crates/node/src/payload_service.rs index 69979666..26e9df44 100644 --- a/crates/node/src/payload_service.rs +++ b/crates/node/src/payload_service.rs @@ -80,7 +80,7 @@ where async fn build_payload_builder( self, ctx: &BuilderContext, - pool: Pool, + _pool: Pool, evm_config: EvolveEvmConfig, ) -> eyre::Result { let chain_spec = ctx.chain_spec(); @@ -93,8 +93,6 @@ where config.validate()?; - let _ = pool; - let evolve_builder = Arc::new(EvolvePayloadBuilder::new( Arc::new(ctx.provider().clone()), evm_config,