* clap-utils: Add epoch validator (cherry picked from commita709850ee4
) * CLI: Support displaying past leader schedules (cherry picked from commitbd761e2a52
) Co-authored-by: Trent Nelson <trent@solana.com>
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
use crate::keypair::{parse_keypair_path, KeypairUrl, ASK_KEYWORD};
|
use crate::keypair::{parse_keypair_path, KeypairUrl, ASK_KEYWORD};
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
clock::Slot,
|
clock::{Epoch, Slot},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{read_keypair_file, Signature},
|
signature::{read_keypair_file, Signature},
|
||||||
@ -148,6 +148,13 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_epoch<T>(epoch: T) -> Result<(), String>
|
||||||
|
where
|
||||||
|
T: AsRef<str> + Display,
|
||||||
|
{
|
||||||
|
is_parsable_generic::<Epoch, _>(epoch)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_slot<T>(slot: T) -> Result<(), String>
|
pub fn is_slot<T>(slot: T) -> Result<(), String>
|
||||||
where
|
where
|
||||||
T: AsRef<str> + Display,
|
T: AsRef<str> + Display,
|
||||||
|
@ -118,7 +118,9 @@ pub enum CliCommand {
|
|||||||
LargestAccounts {
|
LargestAccounts {
|
||||||
filter: Option<RpcLargestAccountsFilter>,
|
filter: Option<RpcLargestAccountsFilter>,
|
||||||
},
|
},
|
||||||
LeaderSchedule,
|
LeaderSchedule {
|
||||||
|
epoch: Option<Epoch>,
|
||||||
|
},
|
||||||
LiveSlots,
|
LiveSlots,
|
||||||
Logs {
|
Logs {
|
||||||
filter: RpcTransactionLogsFilter,
|
filter: RpcTransactionLogsFilter,
|
||||||
@ -582,10 +584,7 @@ pub fn parse_command(
|
|||||||
("supply", Some(matches)) => parse_supply(matches),
|
("supply", Some(matches)) => parse_supply(matches),
|
||||||
("total-supply", Some(matches)) => parse_total_supply(matches),
|
("total-supply", Some(matches)) => parse_total_supply(matches),
|
||||||
("transaction-count", Some(matches)) => parse_get_transaction_count(matches),
|
("transaction-count", Some(matches)) => parse_get_transaction_count(matches),
|
||||||
("leader-schedule", Some(_matches)) => Ok(CliCommandInfo {
|
("leader-schedule", Some(matches)) => parse_leader_schedule(matches),
|
||||||
command: CliCommand::LeaderSchedule,
|
|
||||||
signers: vec![],
|
|
||||||
}),
|
|
||||||
("ping", Some(matches)) => parse_cluster_ping(matches, default_signer, wallet_manager),
|
("ping", Some(matches)) => parse_cluster_ping(matches, default_signer, wallet_manager),
|
||||||
("live-slots", Some(_matches)) => Ok(CliCommandInfo {
|
("live-slots", Some(_matches)) => Ok(CliCommandInfo {
|
||||||
command: CliCommand::LiveSlots,
|
command: CliCommand::LiveSlots,
|
||||||
@ -1562,7 +1561,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
|||||||
CliCommand::Inflation(inflation_subcommand) => {
|
CliCommand::Inflation(inflation_subcommand) => {
|
||||||
process_inflation_subcommand(&rpc_client, config, 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::LiveSlots => process_live_slots(&config),
|
||||||
CliCommand::Logs { filter } => process_logs(&config, filter),
|
CliCommand::Logs { filter } => process_logs(&config, filter),
|
||||||
CliCommand::Ping {
|
CliCommand::Ping {
|
||||||
|
@ -132,7 +132,17 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
|||||||
.help("Slot number of the block to query")
|
.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(
|
||||||
SubCommand::with_name("epoch-info")
|
SubCommand::with_name("epoch-info")
|
||||||
.about("Get information about the current epoch")
|
.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))
|
Ok(format!("{}", first_available_block))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_leader_schedule(rpc_client: &RpcClient) -> ProcessResult {
|
pub fn parse_leader_schedule(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||||
|
let epoch = value_of(matches, "epoch");
|
||||||
|
Ok(CliCommandInfo {
|
||||||
|
command: CliCommand::LeaderSchedule { epoch },
|
||||||
|
signers: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_leader_schedule(rpc_client: &RpcClient, epoch: Option<Epoch>) -> ProcessResult {
|
||||||
let epoch_info = rpc_client.get_epoch_info()?;
|
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))?;
|
let leader_schedule = rpc_client.get_leader_schedule(Some(first_slot_in_epoch))?;
|
||||||
if leader_schedule.is_none() {
|
if leader_schedule.is_none() {
|
||||||
|
Reference in New Issue
Block a user