diff --git a/Cargo.lock b/Cargo.lock index c8698b7997..01e4ebfe21 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4480,6 +4480,7 @@ dependencies = [ "num-traits", "pretty-hex", "reqwest", + "semver 1.0.4", "serde", "serde_derive", "serde_json", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 37398595b1..8fd0e15546 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -22,6 +22,7 @@ humantime = "2.0.1" num-traits = "0.2" pretty-hex = "0.2.1" reqwest = { version = "0.11.6", default-features = false, features = ["blocking", "rustls-tls", "json"] } +semver = "1.0.4" serde = "1.0.130" serde_derive = "1.0.103" serde_json = "1.0.68" diff --git a/cli/src/feature.rs b/cli/src/feature.rs index e742a2ed73..ea8a7565cc 100644 --- a/cli/src/feature.rs +++ b/cli/src/feature.rs @@ -18,7 +18,11 @@ use solana_sdk::{ pubkey::Pubkey, transaction::Transaction, }; -use std::{collections::HashMap, fmt, sync::Arc}; +use std::{ + collections::{HashMap, HashSet}, + fmt, + sync::Arc, +}; #[derive(Copy, Clone, Debug, PartialEq)] pub enum ForceActivation { @@ -226,6 +230,7 @@ pub fn process_feature_subcommand( struct WorkingFeatureSetStatsEntry { stake: u64, rpc_nodes_count: u32, + software_versions: HashSet>, } type WorkingFeatureSetStats = HashMap; @@ -233,6 +238,7 @@ type WorkingFeatureSetStats = HashMap; struct FeatureSetStatsEntry { stake_percent: f64, rpc_nodes_percent: f32, + software_versions: Vec>, } type FeatureSetStats = HashMap; @@ -246,6 +252,9 @@ fn feature_set_stats(rpc_client: &RpcClient) -> Result>(); @@ -269,10 +278,12 @@ fn feature_set_stats(rpc_client: &RpcClient) -> Result Result>(); + software_versions.sort(); if stake_percent >= 0.001 || rpc_nodes_percent >= 0.001 { Some(( feature_set, FeatureSetStatsEntry { stake_percent, rpc_nodes_percent, + software_versions, }, )) } else { @@ -323,6 +338,7 @@ fn feature_activation_allowed(rpc_client: &RpcClient, quiet: bool) -> Result= 95., *rpc_nodes_percent >= 95.), ) .unwrap_or((false, false)); @@ -355,10 +371,12 @@ fn feature_activation_allowed(rpc_client: &RpcClient, quiet: bool) -> Result Result Result>(); + if has_unknown { + software_versions.push("unknown".to_string()); + } + let software_versions = software_versions.join(", "); + max_software_versions_len = max_software_versions_len.max(software_versions.len()); + max_feature_set_len = max_feature_set_len.max(feature_set.len()); max_stake_percent_len = max_stake_percent_len.max(stake_percent.len()); max_rpc_percent_len = max_rpc_percent_len.max(rpc_percent.len()); - stats_output.push((feature_set, stake_percent, rpc_percent, me)); + stats_output.push(( + software_versions, + feature_set, + stake_percent, + rpc_percent, + me, + )); } println!( "{}", style(format!( - "{1:<0$} {3:<2$} {5:<4$}", + "{1:<0$} {3:<2$} {5:<4$} {7:<6$}", + max_software_versions_len, + software_versions_title, max_feature_set_len, feature_set_title, max_stake_percent_len, @@ -398,9 +442,11 @@ fn feature_activation_allowed(rpc_client: &RpcClient, quiet: bool) -> Result0$} {3:>2$} {5:>4$} {6}", + "{1:<0$} {3:>2$} {5:>4$} {7:>6$} {8}", + max_software_versions_len, + software_versions, max_feature_set_len, feature_set, max_stake_percent_len,