Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

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

131 changes: 4 additions & 127 deletions bin/ev-reth/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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<
<<Self::BuiltPayload as reth_ethereum::node::api::BuiltPayload>::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<N> = RpcAddOns<N, EthereumEthApiBuilder, EvolveEngineValidatorBuilder>;

impl<N> Node<N> for EvolveNode
where
N: FullNodeTypes<Types = Self>,
{
type ComponentsBuilder = ComponentsBuilder<
N,
EthereumPoolBuilder,
BasicPayloadServiceBuilder<EvolvePayloadBuilderBuilder>,
EthereumNetworkBuilder,
EvolveExecutorBuilder,
EvolveConsensusBuilder,
>;
type AddOns = EvolveNodeAddOns<NodeAdapter<N>>;

fn components_builder(&self) -> Self::ComponentsBuilder {
ComponentsBuilder::default()
.node_types::<N>()
.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 ===");

Expand All @@ -172,12 +51,10 @@ fn main() {
}

if let Err(err) = Cli::<EthereumChainSpecParser, EvolveArgs>::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 ===");
|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();
Expand Down
3 changes: 3 additions & 0 deletions crates/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions crates/node/src/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use clap::Args;

/// Evolve CLI arguments (currently empty; reserved for future toggles).
#[derive(Debug, Clone, Default, Args)]
pub struct EvolveArgs {}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<Bytes>>,
/// Optional gas limit for the payload
/// Optional gas limit for the payload.
#[serde(rename = "gasLimit")]
pub gas_limit: Option<u64>,
}
Expand All @@ -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<TransactionSigned>,
/// Gas limit for the payload
/// Gas limit for the payload.
pub gas_limit: Option<u64>,
}

Expand All @@ -62,7 +62,7 @@ impl PayloadBuilderAttributes for EvolveEnginePayloadBuilderAttributes {
) -> Result<Self, Self::Error> {
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()
Expand Down
5 changes: 4 additions & 1 deletion bin/ev-reth/src/error.rs → crates/node/src/error.rs
Original file line number Diff line number Diff line change
@@ -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),
}
7 changes: 4 additions & 3 deletions bin/ev-reth/src/executor.rs → crates/node/src/executor.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand All @@ -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<ChainSpec, EvEvmFactory<EthEvmFactory>>;

/// Builds the EV-aware EVM configuration by wrapping the default config with the EV handler.
pub fn build_evm_config<Node>(ctx: &BuilderContext<Node>) -> eyre::Result<EvolveEvmConfig>
where
Node: FullNodeTypes<Types = crate::EvolveNode>,
Node: FullNodeTypes<Types = EvolveNode>,
ChainSpec: Hardforks + EthExecutorSpec + EthereumHardforks,
{
let chain_spec = ctx.chain_spec();
Expand Down Expand Up @@ -51,7 +52,7 @@ pub struct EvolveExecutorBuilder;

impl<Node> RethExecutorBuilder<Node> for EvolveExecutorBuilder
where
Node: FullNodeTypes<Types = crate::EvolveNode>,
Node: FullNodeTypes<Types = EvolveNode>,
ChainSpec: Hardforks + EthExecutorSpec + EthereumHardforks,
{
type EVM = EvolveEvmConfig;
Expand Down
25 changes: 23 additions & 2 deletions crates/node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, EvolveEngineTypes, EvolveNode, EvolveNodeAddOns};
pub use payload_service::{EvolveEnginePayloadBuilder, EvolvePayloadBuilderBuilder};
pub use validator::{EvolveEngineValidator, EvolveEngineValidatorBuilder};
Loading