diff --git a/bin/ethlambda/src/cli.rs b/bin/ethlambda/src/cli.rs index 848a2446..c0427248 100644 --- a/bin/ethlambda/src/cli.rs +++ b/bin/ethlambda/src/cli.rs @@ -50,17 +50,8 @@ pub(crate) struct CliOptions { /// over to the next URL. Startup only aborts if every URL fails. #[arg(long, value_delimiter = ',')] pub(crate) checkpoint_sync_url: Vec, - /// Whether this node acts as a committee aggregator. - /// - /// Seeds the initial value of the live aggregator flag shared by the - /// blockchain actor and the admin API. The flag can be toggled at - /// runtime via `POST /lean/v0/admin/aggregator`. Runtime toggles do - /// NOT persist across restarts and do NOT update gossip subnet - /// subscriptions, which are frozen at startup — standby aggregators - /// should boot with this flag enabled to establish subscriptions, then - /// use the admin endpoint to rotate duties (hot-standby model). - #[arg(long, default_value = "false")] - pub(crate) is_aggregator: bool, + #[command(flatten)] + pub(crate) aggregator: AggregatorOpts, /// Number of attestation committees (subnets) per slot. /// /// If unset, falls back to `config.attestation_committee_count` from @@ -68,10 +59,6 @@ pub(crate) struct CliOptions { /// field is also absent. #[arg(long, value_parser = clap::value_parser!(u64).range(1..))] pub(crate) attestation_committee_count: Option, - /// Subnet IDs this aggregator should subscribe to (comma-separated). - /// Requires --is-aggregator. Defaults to the subnets of the node's validators. - #[arg(long, value_delimiter = ',', requires = "is_aggregator")] - pub(crate) aggregate_subnet_ids: Option>, /// Directory for RocksDB storage #[arg(long, default_value = "./data")] pub(crate) data_dir: PathBuf, @@ -85,3 +72,26 @@ pub(crate) struct CliOptions { #[arg(long, default_value = "false")] pub(crate) disable_duty_sync_gate: bool, } + +/// Aggregator-related flags, grouped so the committee-aggregation knobs live +/// together. Flattened into [`CliOptions`], so the flags stay top-level on the +/// command line (`--is-aggregator`, `--aggregate-subnet-ids`) and the +/// `requires` cross-reference still resolves within the parent command. +#[derive(Debug, clap::Args)] +pub(crate) struct AggregatorOpts { + /// Whether this node acts as a committee aggregator. + /// + /// Seeds the initial value of the live aggregator flag shared by the + /// blockchain actor and the admin API. The flag can be toggled at + /// runtime via `POST /lean/v0/admin/aggregator`. Runtime toggles do + /// NOT persist across restarts and do NOT update gossip subnet + /// subscriptions, which are frozen at startup — standby aggregators + /// should boot with this flag enabled to establish subscriptions, then + /// use the admin endpoint to rotate duties (hot-standby model). + #[arg(long, default_value = "false")] + pub(crate) is_aggregator: bool, + /// Subnet IDs this aggregator should subscribe to (comma-separated). + /// Requires --is-aggregator. Defaults to the subnets of the node's validators. + #[arg(long, value_delimiter = ',', requires = "is_aggregator")] + pub(crate) aggregate_subnet_ids: Option>, +} diff --git a/bin/ethlambda/src/main.rs b/bin/ethlambda/src/main.rs index d85b3e8d..6b4f0835 100644 --- a/bin/ethlambda/src/main.rs +++ b/bin/ethlambda/src/main.rs @@ -207,7 +207,7 @@ async fn main() -> eyre::Result<()> { // Shared, runtime-mutable aggregator flag. Seeded from the CLI and // threaded into both the blockchain actor (which reads on every tick) // and the API server (which exposes GET/POST admin endpoints). - let aggregator = AggregatorController::new(options.is_aggregator); + let aggregator = AggregatorController::new(options.aggregator.is_aggregator); let blockchain = BlockChain::spawn( store.clone(), @@ -228,8 +228,8 @@ async fn main() -> eyre::Result<()> { listening_socket: p2p_socket, validator_ids, attestation_committee_count, - is_aggregator: options.is_aggregator, - aggregate_subnet_ids: options.aggregate_subnet_ids, + is_aggregator: options.aggregator.is_aggregator, + aggregate_subnet_ids: options.aggregator.aggregate_subnet_ids, }) .wrap_err("failed to build swarm")?;