diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 5ac4342aec..bbec8527ad 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -105,7 +105,9 @@ pub enum CliCommand { LargestAccounts { filter: Option, }, - LeaderSchedule, + LeaderSchedule { + epoch: Option, + }, LiveSlots, Logs { filter: RpcTransactionLogsFilter, @@ -571,10 +573,7 @@ pub fn parse_command( ("supply", Some(matches)) => parse_supply(matches), ("total-supply", Some(matches)) => parse_total_supply(matches), ("transaction-count", Some(matches)) => parse_get_transaction_count(matches), - ("leader-schedule", Some(_matches)) => Ok(CliCommandInfo { - command: CliCommand::LeaderSchedule, - signers: vec![], - }), + ("leader-schedule", Some(matches)) => parse_leader_schedule(matches), ("ping", Some(matches)) => parse_cluster_ping(matches, default_signer, wallet_manager), ("live-slots", Some(_matches)) => Ok(CliCommandInfo { command: CliCommand::LiveSlots, @@ -1166,7 +1165,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult { CliCommand::Inflation(inflation_subcommand) => { process_inflation_subcommand(&rpc_client, config, inflation_subcommand) } - CliCommand::LeaderSchedule => process_leader_schedule(&rpc_client), + CliCommand::LeaderSchedule { epoch } => process_leader_schedule(&rpc_client, *epoch), CliCommand::LiveSlots => process_live_slots(&config), CliCommand::Logs { filter } => process_logs(&config, filter), CliCommand::Ping { diff --git a/cli/src/cluster_query.rs b/cli/src/cluster_query.rs index 226d132a5b..3ac5c8de1f 100644 --- a/cli/src/cluster_query.rs +++ b/cli/src/cluster_query.rs @@ -132,7 +132,17 @@ impl ClusterQuerySubCommands for App<'_, '_> { .help("Slot number of the block to query") ) ) - .subcommand(SubCommand::with_name("leader-schedule").about("Display leader schedule")) + .subcommand(SubCommand::with_name("leader-schedule") + .about("Display leader schedule") + .arg( + Arg::with_name("epoch") + .long("epoch") + .takes_value(true) + .value_name("EPOCH") + .validator(is_epoch) + .help("Epoch to show leader schedule for. (default: current)") + ) + ) .subcommand( SubCommand::with_name("epoch-info") .about("Get information about the current epoch") @@ -713,9 +723,23 @@ pub fn process_first_available_block(rpc_client: &RpcClient) -> ProcessResult { Ok(format!("{}", first_available_block)) } -pub fn process_leader_schedule(rpc_client: &RpcClient) -> ProcessResult { +pub fn parse_leader_schedule(matches: &ArgMatches<'_>) -> Result { + let epoch = value_of(matches, "epoch"); + Ok(CliCommandInfo { + command: CliCommand::LeaderSchedule { epoch }, + signers: vec![], + }) +} + +pub fn process_leader_schedule(rpc_client: &RpcClient, epoch: Option) -> ProcessResult { let epoch_info = rpc_client.get_epoch_info()?; - let first_slot_in_epoch = epoch_info.absolute_slot - epoch_info.slot_index; + let epoch = epoch.unwrap_or(epoch_info.epoch); + if epoch > epoch_info.epoch { + return Err(format!("Epoch {} is in the future", epoch).into()); + } + + let epoch_schedule = rpc_client.get_epoch_schedule()?; + let first_slot_in_epoch = epoch_schedule.get_first_slot_in_epoch(epoch); let leader_schedule = rpc_client.get_leader_schedule(Some(first_slot_in_epoch))?; if leader_schedule.is_none() {