cli: Add version information to solana gossip and solana validators (#10652)

* Add validator version to `solana gossip`

* Add validator version to `solana validators`

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
Michael Vines
2020-06-17 16:04:13 -07:00
committed by GitHub
parent a5f82c995e
commit c151e783ca
2 changed files with 78 additions and 10 deletions

View File

@ -255,6 +255,13 @@ pub struct CliValidators {
pub total_deliquent_stake: u64, pub total_deliquent_stake: u64,
pub current_validators: Vec<CliValidator>, pub current_validators: Vec<CliValidator>,
pub delinquent_validators: Vec<CliValidator>, pub delinquent_validators: Vec<CliValidator>,
pub stake_by_version: BTreeMap<
String, /*version*/
(
usize, /*num validators*/
u64, /*total_active_stake*/
),
>,
#[serde(skip_serializing)] #[serde(skip_serializing)]
pub use_lamports_unit: bool, pub use_lamports_unit: bool,
} }
@ -278,7 +285,7 @@ impl fmt::Display for CliValidators {
writeln!( writeln!(
f, f,
"{} {:<44} {:<44} {:>9}% {:>8} {:>10} {:>10} {}", "{} {:<44} {:<44} {:>3}% {:>8} {:>10} {:>10} {:>17} {}",
if delinquent { if delinquent {
WARNING.to_string() WARNING.to_string()
} else { } else {
@ -290,6 +297,7 @@ impl fmt::Display for CliValidators {
non_zero_or_dash(validator.last_vote), non_zero_or_dash(validator.last_vote),
non_zero_or_dash(validator.root_slot), non_zero_or_dash(validator.root_slot),
validator.credits, validator.credits,
validator.version,
if validator.activated_stake > 0 { if validator.activated_stake > 0 {
format!( format!(
"{} ({:.2}%)", "{} ({:.2}%)",
@ -330,18 +338,32 @@ impl fmt::Display for CliValidators {
), ),
)?; )?;
} }
writeln!(f)?;
writeln!(f, "{}", style("Active Stake By Version:").bold())?;
for (version, (num_validators, total_active_stake)) in self.stake_by_version.iter() {
writeln!(
f,
"{} x {} = {:0.2}%",
version,
num_validators,
100. * *total_active_stake as f64 / self.total_active_stake as f64
)?;
}
writeln!(f)?; writeln!(f)?;
writeln!( writeln!(
f, f,
"{}", "{}",
style(format!( style(format!(
" {:<44} {:<44} {} {} {} {:>10} {}", " {:<44} {:<38} {} {} {} {:>10} {:>17} {}",
"Identity Pubkey", "Identity Pubkey",
"Vote Account Pubkey", "Vote Account Pubkey",
"Commission", "Commission",
"Last Vote", "Last Vote",
"Root Block", "Root Block",
"Credits", "Credits",
"Version",
"Active Stake", "Active Stake",
)) ))
.bold() .bold()
@ -378,10 +400,11 @@ pub struct CliValidator {
pub root_slot: u64, pub root_slot: u64,
pub credits: u64, pub credits: u64,
pub activated_stake: u64, pub activated_stake: u64,
pub version: String,
} }
impl CliValidator { impl CliValidator {
pub fn new(vote_account: &RpcVoteAccountInfo, current_epoch: Epoch) -> Self { pub fn new(vote_account: &RpcVoteAccountInfo, current_epoch: Epoch, version: String) -> Self {
Self { Self {
identity_pubkey: vote_account.node_pubkey.to_string(), identity_pubkey: vote_account.node_pubkey.to_string(),
vote_account_pubkey: vote_account.vote_pubkey.to_string(), vote_account_pubkey: vote_account.vote_pubkey.to_string(),
@ -400,6 +423,7 @@ impl CliValidator {
}) })
.unwrap_or(0), .unwrap_or(0),
activated_stake: vote_account.activated_stake, activated_stake: vote_account.activated_stake,
version,
} }
} }
} }

View File

@ -33,7 +33,7 @@ use solana_sdk::{
transaction::Transaction, transaction::Transaction,
}; };
use std::{ use std::{
collections::{HashMap, VecDeque}, collections::{BTreeMap, HashMap, VecDeque},
net::SocketAddr, net::SocketAddr,
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
@ -1094,10 +1094,10 @@ pub fn process_show_gossip(rpc_client: &RpcClient) -> ProcessResult {
} }
let s: Vec<_> = cluster_nodes let s: Vec<_> = cluster_nodes
.iter() .into_iter()
.map(|node| { .map(|node| {
format!( format!(
"{:15} | {:44} | {:6} | {:5} | {:5}", "{:15} | {:44} | {:6} | {:5} | {:5} | {}",
node.gossip node.gossip
.map(|addr| addr.ip().to_string()) .map(|addr| addr.ip().to_string())
.unwrap_or_else(|| "none".to_string()), .unwrap_or_else(|| "none".to_string()),
@ -1105,15 +1105,16 @@ pub fn process_show_gossip(rpc_client: &RpcClient) -> ProcessResult {
format_port(node.gossip), format_port(node.gossip),
format_port(node.tpu), format_port(node.tpu),
format_port(node.rpc), format_port(node.rpc),
node.version.unwrap_or_else(|| "unknown".to_string()),
) )
}) })
.collect(); .collect();
Ok(format!( Ok(format!(
"IP Address | Node identifier \ "IP Address | Node identifier \
| Gossip | TPU | RPC\n\ | Gossip | TPU | RPC | Version\n\
----------------+----------------------------------------------+\ ----------------+----------------------------------------------+\
--------+-------+-------\n\ --------+-------+-------+----------------\n\
{}\n\ {}\n\
Nodes: {}", Nodes: {}",
s.join("\n"), s.join("\n"),
@ -1196,6 +1197,18 @@ pub fn process_show_validators(
) -> ProcessResult { ) -> ProcessResult {
let epoch_info = rpc_client.get_epoch_info_with_commitment(config.commitment)?; let epoch_info = rpc_client.get_epoch_info_with_commitment(config.commitment)?;
let vote_accounts = rpc_client.get_vote_accounts_with_commitment(config.commitment)?; let vote_accounts = rpc_client.get_vote_accounts_with_commitment(config.commitment)?;
let mut node_version = HashMap::new();
let unknown_version = "unknown".to_string();
for contact_info in rpc_client.get_cluster_nodes()? {
node_version.insert(
contact_info.pubkey,
contact_info
.version
.unwrap_or_else(|| unknown_version.clone()),
);
}
let total_active_stake = vote_accounts let total_active_stake = vote_accounts
.current .current
.iter() .iter()
@ -1214,21 +1227,52 @@ pub fn process_show_validators(
current.sort_by(|a, b| b.activated_stake.cmp(&a.activated_stake)); current.sort_by(|a, b| b.activated_stake.cmp(&a.activated_stake));
let current_validators: Vec<CliValidator> = current let current_validators: Vec<CliValidator> = current
.iter() .iter()
.map(|vote_account| CliValidator::new(vote_account, epoch_info.epoch)) .map(|vote_account| {
CliValidator::new(
vote_account,
epoch_info.epoch,
node_version
.get(&vote_account.node_pubkey)
.unwrap_or(&unknown_version)
.clone(),
)
})
.collect(); .collect();
let mut delinquent = vote_accounts.delinquent; let mut delinquent = vote_accounts.delinquent;
delinquent.sort_by(|a, b| b.activated_stake.cmp(&a.activated_stake)); delinquent.sort_by(|a, b| b.activated_stake.cmp(&a.activated_stake));
let delinquent_validators: Vec<CliValidator> = delinquent let delinquent_validators: Vec<CliValidator> = delinquent
.iter() .iter()
.map(|vote_account| CliValidator::new(vote_account, epoch_info.epoch)) .map(|vote_account| {
CliValidator::new(
vote_account,
epoch_info.epoch,
node_version
.get(&vote_account.node_pubkey)
.unwrap_or(&unknown_version)
.clone(),
)
})
.collect(); .collect();
let mut stake_by_version: BTreeMap<_, (usize, u64)> = BTreeMap::new();
for validator in current_validators
.iter()
.chain(delinquent_validators.iter())
{
let mut entry = stake_by_version
.entry(validator.version.clone())
.or_default();
entry.0 += 1;
entry.1 += validator.activated_stake;
}
let cli_validators = CliValidators { let cli_validators = CliValidators {
total_active_stake, total_active_stake,
total_current_stake, total_current_stake,
total_deliquent_stake, total_deliquent_stake,
current_validators, current_validators,
delinquent_validators, delinquent_validators,
stake_by_version,
use_lamports_unit, use_lamports_unit,
}; };
Ok(config.output_format.formatted_string(&cli_validators)) Ok(config.output_format.formatted_string(&cli_validators))