From 090a53868a91d1361636c819c814e575c3aec4e0 Mon Sep 17 00:00:00 2001 From: ibrahimijai Date: Fri, 15 May 2026 13:28:17 +0100 Subject: [PATCH] feat: replace HIVE_LEAN_TEST_DRIVER env var with test-driver subcommand --- bin/ethlambda/src/main.rs | 66 ++++++++++++++++++++++--------- crates/net/rpc/src/test_driver.rs | 35 +--------------- 2 files changed, 50 insertions(+), 51 deletions(-) diff --git a/bin/ethlambda/src/main.rs b/bin/ethlambda/src/main.rs index f6d3ca3e..b71bff7c 100644 --- a/bin/ethlambda/src/main.rs +++ b/bin/ethlambda/src/main.rs @@ -47,7 +47,24 @@ const ASCII_ART: &str = r#" #[derive(Debug, clap::Parser)] #[command(name = "ethlambda", author = "LambdaClass", version = version::CLIENT_VERSION, about = "ethlambda consensus client")] -struct CliOptions { +struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Debug, clap::Subcommand)] +enum Commands { + /// Run the consensus node. + Node(Box), + /// Run in Hive test-driver mode (spec-asset suites only). + /// + /// Skips the consensus/p2p stack and exposes only the + /// `/lean/v0/test_driver/...` endpoints driven by the hive simulator. + TestDriver(TestDriverArgs), +} + +#[derive(Debug, clap::Args)] +struct NodeArgs { /// Path to the chain genesis config (e.g., config.yaml). #[arg(long)] genesis: PathBuf, @@ -111,6 +128,16 @@ struct CliOptions { data_dir: PathBuf, } +#[derive(Debug, clap::Args)] +struct TestDriverArgs { + #[arg(long, default_value = "127.0.0.1")] + http_address: IpAddr, + #[arg(long, default_value = "5052")] + api_port: u16, + #[arg(long, default_value = "5054")] + metrics_port: u16, +} + #[tokio::main] async fn main() -> eyre::Result<()> { let filter = EnvFilter::builder() @@ -119,34 +146,37 @@ async fn main() -> eyre::Result<()> { let subscriber = Registry::default().with(tracing_subscriber::fmt::layer().with_filter(filter)); tracing::subscriber::set_global_default(subscriber).unwrap(); - let options = CliOptions::parse(); + let cli = Cli::parse(); // Initialize metrics ethlambda_blockchain::metrics::init(); ethlambda_blockchain::metrics::set_node_info("ethlambda", version::CLIENT_VERSION); ethlambda_blockchain::metrics::set_node_start_time(); - let rpc_config = RpcConfig { - http_address: options.http_address, - api_port: options.api_port, - metrics_port: options.metrics_port, - }; - println!("{ASCII_ART}"); info!(version = version::CLIENT_VERSION, "Starting ethlambda"); - // Hive lean spec-asset suites boot the client with - // HIVE_LEAN_TEST_DRIVER=1 so it skips the consensus/p2p stack and - // exposes only the `/lean/v0/test_driver/...` endpoints driven by the - // simulator. Detected here before any config / key / genesis loading - // so the driver run doesn't touch --node-key, --custom-network-config-dir, - // or any other consensus prerequisite the hive shim doesn't bother to - // provision. - if ethlambda_rpc::test_driver::test_driver_enabled() { - info!("HIVE_LEAN_TEST_DRIVER detected; booting in test-driver mode"); - return run_test_driver(rpc_config).await; + match cli.command { + Commands::TestDriver(args) => { + let rpc_config = RpcConfig { + http_address: args.http_address, + api_port: args.api_port, + metrics_port: args.metrics_port, + }; + info!("Booting in test-driver mode"); + return run_test_driver(rpc_config).await; + } + Commands::Node(options) => run_node(*options).await, } +} + +async fn run_node(options: NodeArgs) -> eyre::Result<()> { + let rpc_config = RpcConfig { + http_address: options.http_address, + api_port: options.api_port, + metrics_port: options.metrics_port, + }; let node_p2p_key = read_hex_file_bytes(&options.node_key); let p2p_socket = SocketAddr::new(IpAddr::from([0, 0, 0, 0]), options.gossipsub_port); diff --git a/crates/net/rpc/src/test_driver.rs b/crates/net/rpc/src/test_driver.rs index 7bf4033a..e6b0dc6d 100644 --- a/crates/net/rpc/src/test_driver.rs +++ b/crates/net/rpc/src/test_driver.rs @@ -17,8 +17,8 @@ //! store-mutating operations themselves are synchronous, so the write lock is //! never held across `.await`. //! -//! Activated by setting `HIVE_LEAN_TEST_DRIVER=1` in the container env; see -//! [`test_driver_enabled`] and the boot path in `bin/ethlambda/src/main.rs`. +//! Activated via the `test-driver` subcommand; see the boot path in +//! `bin/ethlambda/src/main.rs`. use std::sync::Arc; @@ -51,27 +51,6 @@ use serde::{Deserialize, Serialize}; use tokio::sync::RwLock; use tracing::debug; -/// Environment variable that activates the test driver at boot time. -/// -/// The hive simulator sets this to `"1"` for each spec-asset fixture run; any -/// of `"1"`, `"true"`, or `"yes"` (case-insensitive) enables the driver. -pub const TEST_DRIVER_ENV: &str = "HIVE_LEAN_TEST_DRIVER"; - -/// Whether the supplied env-var value should activate the driver. -fn parse_truthy_env_value(value: &str) -> bool { - matches!( - value.trim().to_ascii_lowercase().as_str(), - "1" | "true" | "yes" - ) -} - -/// Returns true when the binary should boot into test-driver mode. -pub fn test_driver_enabled() -> bool { - std::env::var(TEST_DRIVER_ENV) - .map(|value| parse_truthy_env_value(&value)) - .unwrap_or(false) -} - /// Shared, runtime-replaceable Store backing every test-driver handler. /// /// `fork_choice/init` swaps the contents wholesale; all other handlers either @@ -429,16 +408,6 @@ fn snapshot_store(store: &Store) -> DriverSnapshot { mod tests { use super::*; - #[test] - fn parse_truthy_env_value_accepts_canonical_truthy_strings() { - for value in ["1", "true", "TRUE", " Yes ", "yes\n"] { - assert!(parse_truthy_env_value(value), "{value:?} should be truthy"); - } - for value in ["0", "false", "no", "", " ", "1.0"] { - assert!(!parse_truthy_env_value(value), "{value:?} should be falsy"); - } - } - #[test] fn empty_driver_store_is_usable_as_seed() { let store = empty_driver_store();