diff --git a/.gitignore b/.gitignore index 0a9a3940..8387d8cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ /target .idea/ -testnet/ .vscode/* .nvim.lua +.DS_Store # cargo-fuzz build artifacts + generated corpus / crashes fuzz/target/ diff --git a/CLAUDE.md b/CLAUDE.md index 1a6c36ae..26663dca 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -101,6 +101,7 @@ The `testnet` binary spins up a multi-node network locally — this is the main ```bash ln -s /path/to/seismic-reth ~/.cargo/bin/reth ``` + Alternatively, set the `SRETH_BIN` env var to the path of a specific binary; it takes precedence over PATH. ### Quick start @@ -143,9 +144,9 @@ cd testnet && ./reset.sh ### Config files (`testnet/`) -- `dev.json` — Ethereum genesis with pre-funded test accounts -- `jwt.hex` — Engine API auth token - `node{0-3}/` — per-node keys (`consensus_key.pem`, `node_key.pem`) and data directories +- `bin/` — the `testnet` launcher crate +- `../example_genesis.toml` (repo root) — the genesis the launcher points nodes at ## Binaries @@ -163,7 +164,7 @@ cd testnet && ./reset.sh ## Project Layout ``` -node/ Main binary crate (summit, testnet) +node/ Main binary crate (summit) src/engine.rs Central coordinator — component lifecycle, message routing src/args.rs CLI argument parsing (clap) src/config.rs Channel sizes, timeouts, default paths @@ -171,7 +172,7 @@ node/ Main binary crate (summit, testnet) src/genesis.rs Genesis file utilities (set-validators/digest) src/test_harness/ Shared test harness for e2e tests src/tests/ Integration tests (syncer, checkpointing, execution requests) - src/bin/ Additional binaries (testnet, e2e, bench) + src/bin/ Additional binaries (e2e, bench) application/ Consensus interface — implements Simplex Automaton + Relay traits src/actor.rs Propose, verify, broadcast blocks @@ -203,7 +204,9 @@ types/ Shared types & engine client src/scheme.rs BLS12-381 multisig scheme docs/ Architecture docs, protocol descriptions -testnet/ Local testnet config (4 validators, genesis JSON) +testnet/ Local-network home: per-node keys, reset.sh + bin/ The `testnet` launcher (own crate so the reth spawn + machinery stays out of production builds) ``` ## Architecture diff --git a/Cargo.lock b/Cargo.lock index 08a9b4f0..61d2691a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -245,19 +245,6 @@ dependencies = [ "serde_with", ] -[[package]] -name = "alloy-hardforks" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819a3620fe125e0fff365363315ee5e24c23169173b19747dfd6deba33db8990" -dependencies = [ - "alloy-chains", - "alloy-eip2124", - "alloy-primitives", - "auto_impl", - "dyn-clone", -] - [[package]] name = "alloy-json-abi" version = "1.2.1" @@ -324,27 +311,6 @@ dependencies = [ "serde", ] -[[package]] -name = "alloy-node-bindings" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f70cdf0ba711fb6f1a427fd026e149bd6d64c9da4c020c1c96c69245c4721ac1" -dependencies = [ - "alloy-genesis", - "alloy-hardforks", - "alloy-network", - "alloy-primitives", - "alloy-signer", - "alloy-signer-local", - "k256", - "rand 0.8.5", - "serde_json", - "tempfile", - "thiserror 2.0.12", - "tracing", - "url", -] - [[package]] name = "alloy-primitives" version = "1.2.1" @@ -5959,7 +5925,6 @@ dependencies = [ "alloy-consensus", "alloy-eips", "alloy-network", - "alloy-node-bindings", "alloy-primitives", "alloy-provider", "alloy-rpc-client", @@ -6174,6 +6139,20 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "summit-testnet" +version = "0.0.3-alpha" +dependencies = [ + "clap", + "commonware-runtime", + "console-subscriber", + "futures", + "summit", + "summit-rpc", + "summit-types", + "tracing", +] + [[package]] name = "summit-types" version = "0.0.3-alpha" diff --git a/Cargo.toml b/Cargo.toml index b0fc6603..664555c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = [ "application", "node", "rpc", "types", "finalizer", "orchestrator", "syncer"] +members = [ "application", "node", "rpc", "types", "finalizer", "orchestrator", "syncer", "testnet/bin"] resolver = "3" [workspace.package] @@ -32,7 +32,6 @@ alloy-consensus = "1.0.12" alloy-eips = { version = "1.0.19", features = ["ssz"] } alloy-genesis = "1.0.9" alloy-network = "1.0.9" -alloy-node-bindings = "1.0.9" alloy-rpc-client = { version = "1.0.9", features = [ "hyper", "alloy-transport-http", diff --git a/docs/running-local-network.md b/docs/running-local-network.md index 38663f3a..3dfefd32 100644 --- a/docs/running-local-network.md +++ b/docs/running-local-network.md @@ -4,7 +4,7 @@ Easiest way to run a network locally is to use the testnet bin. This will start ## Prerequisites -1. Make sure you have a `reth` binary installed and in your `PATH`. The testnet bin passes Seismic-specific flags (e.g. `--enclave.endpoint-port`) to the execution client, so a vanilla upstream `reth` will not work - build `seismic-reth`: +1. Make sure you have a `reth` binary installed and in your `PATH` (or point the `SRETH_BIN` env var at a specific binary). The testnet bin passes Seismic-specific flags (e.g. `--seismic.purpose-keys-source`) to the execution client, so a vanilla upstream `reth` will not work - build `seismic-reth`: ```bash git clone https://github.com/SeismicSystems/seismic-reth.git && cd seismic-reth && cargo build --release ``` diff --git a/node/Cargo.toml b/node/Cargo.toml index 3a6e5e44..f2660aae 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -3,10 +3,6 @@ name = "summit" version.workspace = true edition.workspace = true -[[bin]] -name = "testnet" -path = "src/bin/testnet.rs" - [[bin]] name = "stake-and-checkpoint" path = "src/bin/stake_and_checkpoint.rs" @@ -82,7 +78,6 @@ ethereum_ssz.workspace = true jsonrpsee.workspace = true # testnet bin deps -alloy-node-bindings.workspace = true alloy-network = { workspace = true } alloy-primitives.workspace = true alloy-provider = { version = "1.0.30", features = ["reqwest-rustls-tls"] } diff --git a/node/src/bin/observer.rs b/node/src/bin/observer.rs index 875d21eb..0aa76d99 100644 --- a/node/src/bin/observer.rs +++ b/node/src/bin/observer.rs @@ -44,7 +44,7 @@ use summit_types::consensus_state::ConsensusState; use summit_types::ext_private_key::derive_child_public; use summit_types::genesis::Genesis; use summit_types::header::FinalizedHeader; -use summit_types::reth::Reth; +use summit_types::reth::reth_spawner; use summit_types::rpc::CheckpointRes; use summit_types::scheme::MultisigScheme; use tokio::sync::mpsc; @@ -134,20 +134,7 @@ fn main() -> Result<(), Box> { let data_dir = format!("{}/node{}/data/reth_db", args.data_dir, x); fs::create_dir_all(&data_dir).expect("Failed to create data directory"); - let reth_builder = Reth::new() - .instance(x + 1) - .keep_stdout() - .data_dir(data_dir) - .arg("--enclave.mock-server") - .arg("--enclave.endpoint-port") - .arg(format!("1744{x}")) - .arg("--auth-ipc") - .arg("--auth-ipc.path") - .arg(format!("/tmp/reth_engine_api{x}.ipc")) - .arg("--metrics") - .arg(format!("0.0.0.0:{}", 9001 + x)); - - let mut reth = reth_builder.spawn(); + let mut reth = reth_spawner(x, data_dir).spawn(); let stdout = reth.stdout().expect("Failed to get stdout"); let log_dir = args.log_dir.clone(); context.clone().spawn(async move |_| { @@ -247,20 +234,7 @@ fn main() -> Result<(), Box> { .expect("Failed to write observer BLS key"); println!("******* STARTING RETH FOR OBSERVER"); - let observer_reth_builder = Reth::new() - .instance(OBSERVER_SLOT as u16 + 1) - .keep_stdout() - .data_dir(observer_reth_data_dir) - .arg("--enclave.mock-server") - .arg("--enclave.endpoint-port") - .arg(format!("1744{}", OBSERVER_SLOT)) - .arg("--auth-ipc") - .arg("--auth-ipc.path") - .arg(format!("/tmp/reth_engine_api{}.ipc", OBSERVER_SLOT)) - .arg("--metrics") - .arg(format!("0.0.0.0:{}", 9001 + OBSERVER_SLOT)); - - let mut observer_reth = observer_reth_builder.spawn(); + let mut observer_reth = reth_spawner(OBSERVER_SLOT as u16, observer_reth_data_dir).spawn(); let observer_stdout = observer_reth.stdout().expect("Failed to get observer stdout"); let log_dir = args.log_dir.clone(); context.clone().spawn(async move |_| { diff --git a/node/src/bin/protocol_params.rs b/node/src/bin/protocol_params.rs index 0c071dbb..080c1e0c 100644 --- a/node/src/bin/protocol_params.rs +++ b/node/src/bin/protocol_params.rs @@ -31,7 +31,7 @@ use std::{ use summit::args::{RunFlags, run_node_local}; use summit_rpc::SummitApiClient; use summit_types::genesis::Genesis; -use summit_types::reth::Reth; +use summit_types::reth::reth_spawner; use tokio::sync::mpsc; use tracing::Level; @@ -113,21 +113,7 @@ fn main() -> Result<(), Box> { fs::create_dir_all(&data_dir).expect("Failed to create data directory"); // Build and spawn reth instance - let reth_builder = Reth::new() - .instance(x + 1) - .keep_stdout() - // .genesis(serde_json::from_str(&genesis_str).expect("invalid genesis")) - .data_dir(data_dir) - .arg("--enclave.mock-server") - .arg("--enclave.endpoint-port") - .arg(format!("1744{x}")) - .arg("--auth-ipc") - .arg("--auth-ipc.path") - .arg(format!("/tmp/reth_engine_api{x}.ipc")) - .arg("--metrics") - .arg(format!("0.0.0.0:{}", 9001 + x)); - - let mut reth = reth_builder.spawn(); + let mut reth = reth_spawner(x, data_dir).spawn(); // Get stdout handle let stdout = reth.stdout().expect("Failed to get stdout"); diff --git a/node/src/bin/stake_and_checkpoint.rs b/node/src/bin/stake_and_checkpoint.rs index c1cd74e2..9312c1d9 100644 --- a/node/src/bin/stake_and_checkpoint.rs +++ b/node/src/bin/stake_and_checkpoint.rs @@ -38,7 +38,7 @@ use summit_types::consensus_state::ConsensusState; use summit_types::deposit_signature_domain; use summit_types::execution_request::DepositRequest; use summit_types::genesis::Genesis; -use summit_types::reth::Reth; +use summit_types::reth::reth_spawner; use tokio::sync::mpsc; use tracing::Level; @@ -130,21 +130,7 @@ fn main() -> Result<(), Box> { fs::create_dir_all(&data_dir).expect("Failed to create data directory"); // Build and spawn reth instance - let reth_builder = Reth::new() - .instance(x + 1) - .keep_stdout() - // .genesis(serde_json::from_str(&genesis_str).expect("invalid genesis")) - .data_dir(data_dir) - .arg("--enclave.mock-server") - .arg("--enclave.endpoint-port") - .arg(format!("1744{x}")) - .arg("--auth-ipc") - .arg("--auth-ipc.path") - .arg(format!("/tmp/reth_engine_api{x}.ipc")) - .arg("--metrics") - .arg(format!("0.0.0.0:{}", 9001 + x)); - - let mut reth = reth_builder.spawn(); + let mut reth = reth_spawner(x, data_dir).spawn(); // Get stdout handle let stdout = reth.stdout().expect("Failed to get stdout"); @@ -403,20 +389,7 @@ fn main() -> Result<(), Box> { .expect("Failed to copy static_files directory"); // Restart nodeß's reth instance - //let reth_builder = Reth::new() - // .instance((source_node + 1) as u16) - // .keep_stdout() - // // .genesis(serde_json::from_str(&genesis_str).expect("invalid genesis")) - // .data_dir(source_data_dir.clone()) - // .arg("--enclave.mock-server") - // .arg("--enclave.endpoint-port") - // .arg(format!("1744{source_node}")) - // .arg("--auth-ipc") - // .arg("--auth-ipc.path") - // .arg(format!("/tmp/reth_engine_api{source_node}.ipc")) - // .arg("--metrics") - // .arg(format!("0.0.0.0:{}", 9001 + source_node)); - //let reth = reth_builder.spawn(); + //let reth = reth_spawner(source_node as u16, source_data_dir.clone()).spawn(); //handles.push_front(reth); // Restart node0's consensus engine in a new runtime/thread @@ -455,20 +428,7 @@ fn main() -> Result<(), Box> { //node_runtimes.insert(source_node, NodeRuntime { thread, stop_tx }); // Start node4's reth instance - let reth_builder = Reth::new() - .instance(x + 1) - .keep_stdout() - .data_dir(data_dir) - .arg("--enclave.mock-server") - .arg("--enclave.endpoint-port") - .arg(format!("1744{x}")) - .arg("--auth-ipc") - .arg("--auth-ipc.path") - .arg(format!("/tmp/reth_engine_api{x}.ipc")) - .arg("--metrics") - .arg(format!("0.0.0.0:{}", 9001 + x)); - - let mut reth = reth_builder.spawn(); + let mut reth = reth_spawner(x, data_dir).spawn(); let stdout = reth.stdout().expect("Failed to get stdout"); diff --git a/node/src/bin/stake_and_join_with_outdated_ckpt.rs b/node/src/bin/stake_and_join_with_outdated_ckpt.rs index 4decf3bc..3b78cc7d 100644 --- a/node/src/bin/stake_and_join_with_outdated_ckpt.rs +++ b/node/src/bin/stake_and_join_with_outdated_ckpt.rs @@ -39,7 +39,7 @@ use summit_types::deposit_signature_domain; use summit_types::execution_request::DepositRequest; use summit_types::execution_request::compute_deposit_data_root; use summit_types::genesis::Genesis; -use summit_types::reth::Reth; +use summit_types::reth::reth_spawner; use tokio::sync::mpsc; use tracing::Level; @@ -133,21 +133,7 @@ fn main() -> Result<(), Box> { fs::create_dir_all(&data_dir).expect("Failed to create data directory"); // Build and spawn reth instance - let reth_builder = Reth::new() - .instance(x + 1) - .keep_stdout() - // .genesis(serde_json::from_str(&genesis_str).expect("invalid genesis")) - .data_dir(data_dir) - .arg("--enclave.mock-server") - .arg("--enclave.endpoint-port") - .arg(format!("1744{x}")) - .arg("--auth-ipc") - .arg("--auth-ipc.path") - .arg(format!("/tmp/reth_engine_api{x}.ipc")) - .arg("--metrics") - .arg(format!("0.0.0.0:{}", 9001 + x)); - - let mut reth = reth_builder.spawn(); + let mut reth = reth_spawner(x, data_dir).spawn(); // Get stdout handle let stdout = reth.stdout().expect("Failed to get stdout"); @@ -425,20 +411,7 @@ fn main() -> Result<(), Box> { .expect("Failed to copy static_files directory"); // Restart nodeß's reth instance - //let reth_builder = Reth::new() - // .instance((source_node + 1) as u16) - // .keep_stdout() - // // .genesis(serde_json::from_str(&genesis_str).expect("invalid genesis")) - // .data_dir(source_data_dir.clone()) - // .arg("--enclave.mock-server") - // .arg("--enclave.endpoint-port") - // .arg(format!("1744{source_node}")) - // .arg("--auth-ipc") - // .arg("--auth-ipc.path") - // .arg(format!("/tmp/reth_engine_api{source_node}.ipc")) - // .arg("--metrics") - // .arg(format!("0.0.0.0:{}", 9001 + source_node)); - //let reth = reth_builder.spawn(); + //let reth = reth_spawner(source_node as u16, source_data_dir.clone()).spawn(); //handles.push_front(reth); // Restart node0's consensus engine in a new runtime/thread @@ -499,20 +472,7 @@ fn main() -> Result<(), Box> { } // Start node4's reth instance - let reth_builder = Reth::new() - .instance(x + 1) - .keep_stdout() - .data_dir(data_dir) - .arg("--enclave.mock-server") - .arg("--enclave.endpoint-port") - .arg(format!("1744{x}")) - .arg("--auth-ipc") - .arg("--auth-ipc.path") - .arg(format!("/tmp/reth_engine_api{x}.ipc")) - .arg("--metrics") - .arg(format!("0.0.0.0:{}", 9001 + x)); - - let mut reth = reth_builder.spawn(); + let mut reth = reth_spawner(x, data_dir).spawn(); let stdout = reth.stdout().expect("Failed to get stdout"); diff --git a/node/src/bin/sync_from_genesis.rs b/node/src/bin/sync_from_genesis.rs index 29b0c122..3dc1894d 100644 --- a/node/src/bin/sync_from_genesis.rs +++ b/node/src/bin/sync_from_genesis.rs @@ -60,7 +60,7 @@ use summit_types::PublicKey; use summit_types::deposit_signature_domain; use summit_types::execution_request::DepositRequest; use summit_types::genesis::Genesis; -use summit_types::reth::Reth; +use summit_types::reth::reth_spawner; use tokio::sync::mpsc; use tracing::Level; @@ -145,21 +145,7 @@ fn main() -> Result<(), Box> { fs::create_dir_all(&data_dir).expect("Failed to create data directory"); // Build and spawn reth instance - let reth_builder = Reth::new() - .instance(x + 1) - .keep_stdout() - // .genesis(serde_json::from_str(&genesis_str).expect("invalid genesis")) - .data_dir(data_dir) - .arg("--enclave.mock-server") - .arg("--enclave.endpoint-port") - .arg(format!("1744{x}")) - .arg("--auth-ipc") - .arg("--auth-ipc.path") - .arg(format!("/tmp/reth_engine_api{x}.ipc")) - .arg("--metrics") - .arg(format!("0.0.0.0:{}", 9001 + x)); - - let mut reth = reth_builder.spawn(); + let mut reth = reth_spawner(x, data_dir).spawn(); // Get stdout handle let stdout = reth.stdout().expect("Failed to get stdout"); @@ -452,20 +438,7 @@ fn main() -> Result<(), Box> { let new_node_data_dir = format!("{}/node{}/data/reth_db", args.data_dir, x); fs::create_dir_all(&new_node_data_dir).expect("Failed to create data directory"); - let reth_builder = Reth::new() - .instance(x + 1) - .keep_stdout() - .data_dir(new_node_data_dir) - .arg("--enclave.mock-server") - .arg("--enclave.endpoint-port") - .arg(format!("1744{x}")) - .arg("--auth-ipc") - .arg("--auth-ipc.path") - .arg(format!("/tmp/reth_engine_api{x}.ipc")) - .arg("--metrics") - .arg(format!("0.0.0.0:{}", 9001 + x)); - - let mut reth = reth_builder.spawn(); + let mut reth = reth_spawner(x, new_node_data_dir).spawn(); let stdout = reth.stdout().expect("Failed to get stdout"); let log_dir = args.log_dir.clone(); diff --git a/node/src/bin/verify_consensus_state_proof.rs b/node/src/bin/verify_consensus_state_proof.rs index d86afd7a..eae58ccc 100644 --- a/node/src/bin/verify_consensus_state_proof.rs +++ b/node/src/bin/verify_consensus_state_proof.rs @@ -19,7 +19,7 @@ use std::{ use summit::args::{RunFlags, run_node_local}; use summit_rpc::{SummitApiClient, SummitProofApiClient}; use summit_types::genesis::Genesis; -use summit_types::reth::Reth; +use summit_types::reth::reth_spawner; use tokio::sync::mpsc; use tracing::Level; @@ -99,20 +99,7 @@ fn main() -> Result<(), Box> { let data_dir = format!("{}/node{}/data/reth_db", args.data_dir, x); fs::create_dir_all(&data_dir).expect("Failed to create data directory"); - let reth_builder = Reth::new() - .instance(x + 1) - .keep_stdout() - .data_dir(data_dir) - .arg("--enclave.mock-server") - .arg("--enclave.endpoint-port") - .arg(format!("1744{x}")) - .arg("--auth-ipc") - .arg("--auth-ipc.path") - .arg(format!("/tmp/reth_engine_api{x}.ipc")) - .arg("--metrics") - .arg(format!("0.0.0.0:{}", 9001 + x)); - - let mut reth = reth_builder.spawn(); + let mut reth = reth_spawner(x, data_dir).spawn(); let stdout = reth.stdout().expect("Failed to get stdout"); let log_dir = args.log_dir.clone(); diff --git a/node/src/bin/withdraw_and_exit.rs b/node/src/bin/withdraw_and_exit.rs index 7d4f280e..9789901d 100644 --- a/node/src/bin/withdraw_and_exit.rs +++ b/node/src/bin/withdraw_and_exit.rs @@ -35,7 +35,7 @@ use summit::engine::VALIDATOR_WITHDRAWAL_NUM_EPOCHS; use summit_rpc::SummitApiClient; use summit_types::PublicKey; use summit_types::genesis::Genesis; -use summit_types::reth::Reth; +use summit_types::reth::reth_spawner; use tokio::sync::mpsc; use tracing::Level; @@ -118,21 +118,7 @@ fn main() -> Result<(), Box> { fs::create_dir_all(&data_dir).expect("Failed to create data directory"); // Build and spawn reth instance - let reth_builder = Reth::new() - .instance(x + 1) - .keep_stdout() - // .genesis(serde_json::from_str(&genesis_str).expect("invalid genesis")) - .data_dir(data_dir) - .arg("--enclave.mock-server") - .arg("--enclave.endpoint-port") - .arg(format!("1744{x}")) - .arg("--auth-ipc") - .arg("--auth-ipc.path") - .arg(format!("/tmp/reth_engine_api{x}.ipc")) - .arg("--metrics") - .arg(format!("0.0.0.0:{}", 9001 + x)); - - let mut reth = reth_builder.spawn(); + let mut reth = reth_spawner(x, data_dir).spawn(); // Get stdout handle let stdout = reth.stdout().expect("Failed to get stdout"); diff --git a/testnet/.gitignore b/testnet/.gitignore new file mode 100644 index 00000000..f7419563 --- /dev/null +++ b/testnet/.gitignore @@ -0,0 +1,5 @@ +# Everything under node*/ is runtime state (reth datadir, consensus store) +# except the checked-in node keys. bin/ is the launcher crate, kept visible. +node*/* +!node*/*.pem +stores/ diff --git a/testnet/bin/Cargo.toml b/testnet/bin/Cargo.toml new file mode 100644 index 00000000..1e68cd52 --- /dev/null +++ b/testnet/bin/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "summit-testnet" +version.workspace = true +edition.workspace = true + +# The `testnet` local-network launcher lives in its own crate so it can +# enable summit-types/e2e (the reth spawn machinery) without that feature +# leaking into default builds of the production `summit` binary. +[[bin]] +name = "testnet" +path = "src/main.rs" + +[dependencies] +summit = { path = "../../node" } +summit-rpc.workspace = true +summit-types = { workspace = true, features = ["e2e"] } + +clap.workspace = true +commonware-runtime.workspace = true +console-subscriber = { workspace = true, optional = true } +futures.workspace = true +tracing.workspace = true + +[features] +bench = ["summit/bench"] +tokio-console = ["console-subscriber", "summit/tokio-console"] diff --git a/node/src/bin/testnet.rs b/testnet/bin/src/main.rs similarity index 91% rename from node/src/bin/testnet.rs rename to testnet/bin/src/main.rs index 8b4b1e18..b8c728ab 100644 --- a/node/src/bin/testnet.rs +++ b/testnet/bin/src/main.rs @@ -15,11 +15,11 @@ use std::{ path::PathBuf, }; -use alloy_node_bindings::Reth; use clap::Parser; use commonware_runtime::{Metrics as _, Runner as _, Spawner as _, tokio}; use futures::future::try_join_all; use summit::args::{RunFlags, run_node_local}; +use summit_types::reth::reth_spawner; #[derive(Parser, Debug)] struct Args { @@ -81,21 +81,7 @@ fn main() -> Result<(), Box> { // Start Reth println!("******* STARTING RETH FOR NODE {x}"); // Build and spawn reth instance - let reth_builder = Reth::new() - .instance(x + 1) - .keep_stdout() - // .genesis(serde_json::from_str(&genesis_str).expect("invalid genesis")) - .data_dir(format!("testnet/node{x}/data/reth_db")) - .arg("--enclave.mock-server") - .arg("--enclave.endpoint-port") - .arg(format!("1744{x}")) - .arg("--auth-ipc") - .arg("--auth-ipc.path") - .arg(format!("/tmp/reth_engine_api{x}.ipc")) - .arg("--metrics") - .arg(format!("0.0.0.0:{}", 9001 + x)); - - let mut reth = reth_builder.spawn(); + let mut reth = reth_spawner(x, format!("testnet/node{x}/data/reth_db")).spawn(); // Get stdout handle let stdout = reth.stdout().expect("Failed to get stdout"); diff --git a/testnet/node0/data/.gitkeep b/testnet/node0/data/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/testnet/node1/data/.gitkeep b/testnet/node1/data/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/testnet/node2/data/.gitkeep b/testnet/node2/data/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/testnet/node3/data/.gitkeep b/testnet/node3/data/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/types/src/reth.rs b/types/src/reth.rs index a4304c28..e83fd554 100644 --- a/types/src/reth.rs +++ b/types/src/reth.rs @@ -6,7 +6,7 @@ use rand::Rng; use std::{ borrow::Cow, ffi::OsString, - fs::create_dir, + fs::create_dir_all, io::{BufRead, BufReader}, net::SocketAddr, path::PathBuf, @@ -24,6 +24,32 @@ const API: &str = "eth,net,web3,txpool,trace,rpc,reth,ots,admin,debug"; /// The reth command const RETH: &str = "reth"; +/// Env var naming the seismic-reth binary to spawn. When unset, `reth` is +/// resolved from `$PATH`. Lets CI and local runs pin a specific build. +pub const SRETH_BIN_ENV: &str = "SRETH_BIN"; + +/// Returns a [`Reth`] builder for local-network node `slot`, carrying the +/// flags every local-network binary needs: built-in purpose keys (local +/// networks run no key custodian), the per-slot Engine API IPC socket, and +/// a per-slot metrics port. Callers chain any further flags on the +/// returned builder. +pub fn reth_spawner(slot: u16, data_dir: impl Into) -> Reth { + let reth = match std::env::var_os(SRETH_BIN_ENV) { + Some(bin) => Reth::at(bin), + None => Reth::new(), + }; + reth.instance(slot + 1) + .keep_stdout() + .data_dir(data_dir) + .arg("--seismic.purpose-keys-source") + .arg("built-in") + .arg("--auth-ipc") + .arg("--auth-ipc.path") + .arg(format!("/tmp/reth_engine_api{slot}.ipc")) + .arg("--metrics") + .arg(format!("0.0.0.0:{}", 9001 + slot)) +} + /// The default HTTP port for Reth. const DEFAULT_HTTP_PORT: u16 = 8545; @@ -531,9 +557,9 @@ impl Reth { if let Some(data_dir) = &self.data_dir { cmd.arg("--datadir").arg(data_dir); - // create the directory if it doesn't exist + // create the directory (and any missing parents) if it doesn't exist if !data_dir.exists() { - create_dir(data_dir).map_err(NodeError::CreateDirError)?; + create_dir_all(data_dir).map_err(NodeError::CreateDirError)?; } }