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:
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
|
Reference in New Issue
Block a user