Add skip rate to solana validators
(#16939)
(cherry picked from commit d640ac143b
)
Co-authored-by: Michael Vines <mvines@gmail.com>
This commit is contained in:
@ -311,6 +311,7 @@ pub enum CliValidatorsSortOrder {
|
|||||||
Identity,
|
Identity,
|
||||||
LastVote,
|
LastVote,
|
||||||
Root,
|
Root,
|
||||||
|
SkipRate,
|
||||||
Stake,
|
Stake,
|
||||||
VoteAccount,
|
VoteAccount,
|
||||||
}
|
}
|
||||||
@ -360,7 +361,7 @@ impl fmt::Display for CliValidators {
|
|||||||
|
|
||||||
writeln!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
"{} {:<44} {:<44} {:>3}% {:>14} {:>14} {:>13} {:>7} {}",
|
"{} {:<44} {:<44} {:>3}% {:>14} {:>14} {:>7} {:>8} {:>7} {}",
|
||||||
if validator.delinquent {
|
if validator.delinquent {
|
||||||
WARNING.to_string()
|
WARNING.to_string()
|
||||||
} else {
|
} else {
|
||||||
@ -371,6 +372,11 @@ impl fmt::Display for CliValidators {
|
|||||||
validator.commission,
|
validator.commission,
|
||||||
non_zero_or_dash(validator.last_vote, highest_last_vote),
|
non_zero_or_dash(validator.last_vote, highest_last_vote),
|
||||||
non_zero_or_dash(validator.root_slot, highest_root),
|
non_zero_or_dash(validator.root_slot, highest_root),
|
||||||
|
if let Some(skip_rate) = validator.skip_rate {
|
||||||
|
format!("{:.2}%", skip_rate)
|
||||||
|
} else {
|
||||||
|
"- ".to_string()
|
||||||
|
},
|
||||||
validator.epoch_credits,
|
validator.epoch_credits,
|
||||||
validator.version,
|
validator.version,
|
||||||
if validator.activated_stake > 0 {
|
if validator.activated_stake > 0 {
|
||||||
@ -391,14 +397,15 @@ impl fmt::Display for CliValidators {
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
let header = style(format!(
|
let header = style(format!(
|
||||||
"{:padding$} {:<44} {:<38} {} {} {} {:>11} {:^7} {}",
|
"{:padding$} {:<44} {:<38} {} {} {} {} {} {} {}",
|
||||||
" ",
|
" ",
|
||||||
"Identity",
|
"Identity",
|
||||||
"Vote Account",
|
"Vote Account",
|
||||||
"Commission",
|
"Commission",
|
||||||
"Last Vote ",
|
"Last Vote ",
|
||||||
"Root Slot ",
|
"Root Slot ",
|
||||||
"Epoch Credits",
|
"Skip Rate",
|
||||||
|
"Credits",
|
||||||
"Version",
|
"Version",
|
||||||
"Active Stake",
|
"Active Stake",
|
||||||
padding = padding + 1
|
padding = padding + 1
|
||||||
@ -429,6 +436,17 @@ impl fmt::Display for CliValidators {
|
|||||||
CliValidatorsSortOrder::VoteAccount => {
|
CliValidatorsSortOrder::VoteAccount => {
|
||||||
sorted_validators.sort_by(|a, b| a.vote_account_pubkey.cmp(&b.vote_account_pubkey));
|
sorted_validators.sort_by(|a, b| a.vote_account_pubkey.cmp(&b.vote_account_pubkey));
|
||||||
}
|
}
|
||||||
|
CliValidatorsSortOrder::SkipRate => {
|
||||||
|
sorted_validators.sort_by(|a, b| {
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
match (a.skip_rate, b.skip_rate) {
|
||||||
|
(None, None) => Ordering::Equal,
|
||||||
|
(None, Some(_)) => Ordering::Greater,
|
||||||
|
(Some(_), None) => Ordering::Less,
|
||||||
|
(Some(a), Some(b)) => a.partial_cmp(&b).unwrap_or(Ordering::Equal),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
CliValidatorsSortOrder::Stake => {
|
CliValidatorsSortOrder::Stake => {
|
||||||
sorted_validators.sort_by_key(|a| a.activated_stake);
|
sorted_validators.sort_by_key(|a| a.activated_stake);
|
||||||
}
|
}
|
||||||
@ -537,6 +555,7 @@ pub struct CliValidator {
|
|||||||
pub activated_stake: u64,
|
pub activated_stake: u64,
|
||||||
pub version: String,
|
pub version: String,
|
||||||
pub delinquent: bool,
|
pub delinquent: bool,
|
||||||
|
pub skip_rate: Option<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliValidator {
|
impl CliValidator {
|
||||||
@ -544,24 +563,41 @@ impl CliValidator {
|
|||||||
vote_account: &RpcVoteAccountInfo,
|
vote_account: &RpcVoteAccountInfo,
|
||||||
current_epoch: Epoch,
|
current_epoch: Epoch,
|
||||||
version: String,
|
version: String,
|
||||||
|
skip_rate: Option<f64>,
|
||||||
address_labels: &HashMap<String, String>,
|
address_labels: &HashMap<String, String>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::_new(vote_account, current_epoch, version, address_labels, false)
|
Self::_new(
|
||||||
|
vote_account,
|
||||||
|
current_epoch,
|
||||||
|
version,
|
||||||
|
skip_rate,
|
||||||
|
address_labels,
|
||||||
|
false,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_delinquent(
|
pub fn new_delinquent(
|
||||||
vote_account: &RpcVoteAccountInfo,
|
vote_account: &RpcVoteAccountInfo,
|
||||||
current_epoch: Epoch,
|
current_epoch: Epoch,
|
||||||
version: String,
|
version: String,
|
||||||
|
skip_rate: Option<f64>,
|
||||||
address_labels: &HashMap<String, String>,
|
address_labels: &HashMap<String, String>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::_new(vote_account, current_epoch, version, address_labels, true)
|
Self::_new(
|
||||||
|
vote_account,
|
||||||
|
current_epoch,
|
||||||
|
version,
|
||||||
|
skip_rate,
|
||||||
|
address_labels,
|
||||||
|
true,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _new(
|
fn _new(
|
||||||
vote_account: &RpcVoteAccountInfo,
|
vote_account: &RpcVoteAccountInfo,
|
||||||
current_epoch: Epoch,
|
current_epoch: Epoch,
|
||||||
version: String,
|
version: String,
|
||||||
|
skip_rate: Option<f64>,
|
||||||
address_labels: &HashMap<String, String>,
|
address_labels: &HashMap<String, String>,
|
||||||
delinquent: bool,
|
delinquent: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -587,6 +623,7 @@ impl CliValidator {
|
|||||||
activated_stake: vote_account.activated_stake,
|
activated_stake: vote_account.activated_stake,
|
||||||
version,
|
version,
|
||||||
delinquent,
|
delinquent,
|
||||||
|
skip_rate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,6 +376,7 @@ impl ClusterQuerySubCommands for App<'_, '_> {
|
|||||||
"identity",
|
"identity",
|
||||||
"last-vote",
|
"last-vote",
|
||||||
"root",
|
"root",
|
||||||
|
"skip-rate",
|
||||||
"stake",
|
"stake",
|
||||||
"vote-account",
|
"vote-account",
|
||||||
])
|
])
|
||||||
@ -624,6 +625,7 @@ pub fn parse_show_validators(matches: &ArgMatches<'_>) -> Result<CliCommandInfo,
|
|||||||
"identity" => CliValidatorsSortOrder::Identity,
|
"identity" => CliValidatorsSortOrder::Identity,
|
||||||
"last-vote" => CliValidatorsSortOrder::LastVote,
|
"last-vote" => CliValidatorsSortOrder::LastVote,
|
||||||
"root" => CliValidatorsSortOrder::Root,
|
"root" => CliValidatorsSortOrder::Root,
|
||||||
|
"skip-rate" => CliValidatorsSortOrder::SkipRate,
|
||||||
"stake" => CliValidatorsSortOrder::Stake,
|
"stake" => CliValidatorsSortOrder::Stake,
|
||||||
"vote-account" => CliValidatorsSortOrder::VoteAccount,
|
"vote-account" => CliValidatorsSortOrder::VoteAccount,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -1811,9 +1813,32 @@ pub fn process_show_validators(
|
|||||||
validators_reverse_sort: bool,
|
validators_reverse_sort: bool,
|
||||||
number_validators: bool,
|
number_validators: bool,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
|
let progress_bar = new_spinner_progress_bar();
|
||||||
|
progress_bar.set_message("Fetching vote accounts...");
|
||||||
let epoch_info = rpc_client.get_epoch_info()?;
|
let epoch_info = rpc_client.get_epoch_info()?;
|
||||||
let vote_accounts = rpc_client.get_vote_accounts()?;
|
let vote_accounts = rpc_client.get_vote_accounts()?;
|
||||||
|
|
||||||
|
progress_bar.set_message("Fetching block production...");
|
||||||
|
let skip_rate: HashMap<_, _> = rpc_client
|
||||||
|
.get_block_production()
|
||||||
|
.ok()
|
||||||
|
.map(|result| {
|
||||||
|
result
|
||||||
|
.value
|
||||||
|
.by_identity
|
||||||
|
.into_iter()
|
||||||
|
.map(|(identity, (leader_slots, blocks_produced))| {
|
||||||
|
(
|
||||||
|
identity,
|
||||||
|
100. * (leader_slots.saturating_sub(blocks_produced)) as f64
|
||||||
|
/ leader_slots as f64,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
progress_bar.set_message("Fetching version information...");
|
||||||
let mut node_version = HashMap::new();
|
let mut node_version = HashMap::new();
|
||||||
let unknown_version = "unknown".to_string();
|
let unknown_version = "unknown".to_string();
|
||||||
for contact_info in rpc_client.get_cluster_nodes()? {
|
for contact_info in rpc_client.get_cluster_nodes()? {
|
||||||
@ -1825,6 +1850,8 @@ pub fn process_show_validators(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progress_bar.finish_and_clear();
|
||||||
|
|
||||||
let total_active_stake = vote_accounts
|
let total_active_stake = vote_accounts
|
||||||
.current
|
.current
|
||||||
.iter()
|
.iter()
|
||||||
@ -1850,6 +1877,7 @@ pub fn process_show_validators(
|
|||||||
.get(&vote_account.node_pubkey)
|
.get(&vote_account.node_pubkey)
|
||||||
.unwrap_or(&unknown_version)
|
.unwrap_or(&unknown_version)
|
||||||
.clone(),
|
.clone(),
|
||||||
|
skip_rate.get(&vote_account.node_pubkey).cloned(),
|
||||||
&config.address_labels,
|
&config.address_labels,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -1865,6 +1893,7 @@ pub fn process_show_validators(
|
|||||||
.get(&vote_account.node_pubkey)
|
.get(&vote_account.node_pubkey)
|
||||||
.unwrap_or(&unknown_version)
|
.unwrap_or(&unknown_version)
|
||||||
.clone(),
|
.clone(),
|
||||||
|
skip_rate.get(&vote_account.node_pubkey).cloned(),
|
||||||
&config.address_labels,
|
&config.address_labels,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user