From 2521f75c18d113d08aebaf811724f5eeb3de6028 Mon Sep 17 00:00:00 2001 From: Michael Vines Date: Mon, 11 May 2020 15:02:01 -0700 Subject: [PATCH] Advertise node software version in gossip (#9981) * Advertise node version in gossip * Remove solana_clap_utils::version! macro --- Cargo.lock | 29 ++++++++++++++ Cargo.toml | 1 + archiver/Cargo.toml | 2 +- archiver/src/main.rs | 4 +- bench-exchange/Cargo.toml | 1 + bench-exchange/src/main.rs | 2 +- bench-streamer/Cargo.toml | 1 + bench-streamer/src/main.rs | 2 +- bench-tps/Cargo.toml | 1 + bench-tps/src/main.rs | 2 +- clap-utils/src/lib.rs | 19 ---------- cli/Cargo.toml | 1 + cli/src/main.rs | 2 +- core/Cargo.toml | 1 + core/src/cluster_info.rs | 37 +++++++++++++----- core/src/crds_value.rs | 52 ++++++++++++++++++++++++-- core/src/rpc.rs | 4 +- core/tests/client.rs | 2 +- dos/Cargo.toml | 1 + dos/src/main.rs | 2 +- faucet/Cargo.toml | 4 +- faucet/src/bin/faucet.rs | 2 +- genesis/Cargo.toml | 2 +- genesis/src/main.rs | 2 +- gossip/Cargo.toml | 4 +- gossip/src/main.rs | 2 +- install/Cargo.toml | 1 + install/src/lib.rs | 4 +- keygen/Cargo.toml | 1 + keygen/src/keygen.rs | 2 +- ledger-tool/Cargo.toml | 1 + ledger-tool/src/main.rs | 2 +- log-analyzer/Cargo.toml | 1 + log-analyzer/src/main.rs | 2 +- net-utils/Cargo.toml | 1 + net-utils/src/bin/ip_address.rs | 2 +- net-utils/src/bin/ip_address_server.rs | 2 +- stake-monitor/Cargo.toml | 1 + stake-monitor/src/main.rs | 2 +- sys-tuner/Cargo.toml | 1 + sys-tuner/src/main.rs | 2 +- validator/Cargo.toml | 1 + validator/src/main.rs | 4 +- version/.gitignore | 2 + version/Cargo.toml | 20 ++++++++++ version/src/lib.rs | 49 ++++++++++++++++++++++++ vote-signer/Cargo.toml | 1 + vote-signer/src/bin/main.rs | 2 +- watchtower/Cargo.toml | 1 + watchtower/src/main.rs | 2 +- 50 files changed, 223 insertions(+), 66 deletions(-) create mode 100644 version/.gitignore create mode 100644 version/Cargo.toml create mode 100644 version/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 94ddf07b0c..b2829294b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3700,6 +3700,7 @@ dependencies = [ "solana-metrics", "solana-net-utils", "solana-sdk", + "solana-version", ] [[package]] @@ -3790,6 +3791,7 @@ dependencies = [ "solana-net-utils", "solana-runtime", "solana-sdk", + "solana-version", ] [[package]] @@ -3801,6 +3803,7 @@ dependencies = [ "solana-logger", "solana-net-utils", "solana-streamer", + "solana-version", ] [[package]] @@ -3829,6 +3832,7 @@ dependencies = [ "solana-net-utils", "solana-runtime", "solana-sdk", + "solana-version", ] [[package]] @@ -3966,6 +3970,7 @@ dependencies = [ "solana-stake-program", "solana-storage-program", "solana-transaction-status", + "solana-version", "solana-vote-program", "solana-vote-signer", "tempfile", @@ -4081,6 +4086,7 @@ dependencies = [ "solana-streamer", "solana-sys-tuner", "solana-transaction-status", + "solana-version", "solana-vote-program", "solana-vote-signer", "systemstat", @@ -4131,6 +4137,7 @@ dependencies = [ "solana-net-utils", "solana-runtime", "solana-sdk", + "solana-version", ] [[package]] @@ -4187,6 +4194,7 @@ dependencies = [ "solana-logger", "solana-metrics", "solana-sdk", + "solana-version", "tokio 0.1.22", "tokio-codec", ] @@ -4208,6 +4216,7 @@ dependencies = [ "solana-sdk", "solana-stake-program", "solana-storage-program", + "solana-version", "solana-vote-program", "tempfile", ] @@ -4237,6 +4246,7 @@ dependencies = [ "solana-logger", "solana-net-utils", "solana-sdk", + "solana-version", ] [[package]] @@ -4264,6 +4274,7 @@ dependencies = [ "solana-config-program", "solana-logger", "solana-sdk", + "solana-version", "tar", "tempdir", "url 2.1.1", @@ -4283,6 +4294,7 @@ dependencies = [ "solana-cli-config", "solana-remote-wallet", "solana-sdk", + "solana-version", "tiny-bip39", ] @@ -4353,6 +4365,7 @@ dependencies = [ "solana-sdk", "solana-stake-program", "solana-transaction-status", + "solana-version", "solana-vote-program", "tempfile", ] @@ -4410,6 +4423,7 @@ dependencies = [ "serde_json", "solana-clap-utils", "solana-logger", + "solana-version", ] [[package]] @@ -4512,6 +4526,7 @@ dependencies = [ "socket2", "solana-clap-utils", "solana-logger", + "solana-version", "tokio 0.1.22", "tokio-codec", ] @@ -4742,6 +4757,7 @@ dependencies = [ "solana-sdk", "solana-stake-program", "solana-transaction-status", + "solana-version", "tempfile", ] @@ -4804,6 +4820,7 @@ dependencies = [ "nix", "solana-clap-utils", "solana-logger", + "solana-version", "sysctl", "unix_socket2", "users", @@ -4852,10 +4869,20 @@ dependencies = [ "solana-perf", "solana-runtime", "solana-sdk", + "solana-version", "solana-vote-program", "solana-vote-signer", ] +[[package]] +name = "solana-version" +version = "1.2.0" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk", +] + [[package]] name = "solana-vest-program" version = "1.2.0" @@ -4900,6 +4927,7 @@ dependencies = [ "solana-clap-utils", "solana-metrics", "solana-sdk", + "solana-version", ] [[package]] @@ -4919,6 +4947,7 @@ dependencies = [ "solana-metrics", "solana-sdk", "solana-transaction-status", + "solana-version", "solana-vote-program", ] diff --git a/Cargo.toml b/Cargo.toml index e11a159e16..ee3147b4a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ members = [ "transaction-status", "upload-perf", "net-utils", + "version", "vote-signer", "cli", "rayon-threadlimit", diff --git a/archiver/Cargo.toml b/archiver/Cargo.toml index cb4b7efea7..6f253f0218 100644 --- a/archiver/Cargo.toml +++ b/archiver/Cargo.toml @@ -17,7 +17,7 @@ solana-metrics = { path = "../metrics", version = "1.2.0" } solana-archiver-lib = { path = "../archiver-lib", version = "1.2.0" } solana-net-utils = { path = "../net-utils", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } - +solana-version = { path = "../version", version = "1.2.0" } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/archiver/src/main.rs b/archiver/src/main.rs index e1d06c34ce..e12ba5eea1 100644 --- a/archiver/src/main.rs +++ b/archiver/src/main.rs @@ -24,7 +24,7 @@ fn main() { let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .arg( Arg::with_name("identity_keypair") .short("i") @@ -105,7 +105,7 @@ fn main() { println!( "{} version {} (branch={}, commit={})", style(crate_name!()).bold(), - solana_clap_utils::version!(), + solana_version::version!(), option_env!("CI_BRANCH").unwrap_or("unknown"), option_env!("CI_COMMIT").unwrap_or("unknown") ); diff --git a/bench-exchange/Cargo.toml b/bench-exchange/Cargo.toml index 8cfbc5f29c..ba0a5cb274 100644 --- a/bench-exchange/Cargo.toml +++ b/bench-exchange/Cargo.toml @@ -29,6 +29,7 @@ solana-metrics = { path = "../metrics", version = "1.2.0" } solana-net-utils = { path = "../net-utils", version = "1.2.0" } solana-runtime = { path = "../runtime", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } [dev-dependencies] solana-local-cluster = { path = "../local-cluster", version = "1.2.0" } diff --git a/bench-exchange/src/main.rs b/bench-exchange/src/main.rs index 640133501d..f87fd1a139 100644 --- a/bench-exchange/src/main.rs +++ b/bench-exchange/src/main.rs @@ -11,7 +11,7 @@ fn main() { solana_logger::setup(); solana_metrics::set_panic_hook("bench-exchange"); - let matches = cli::build_args(solana_clap_utils::version!()).get_matches(); + let matches = cli::build_args(solana_version::version!()).get_matches(); let cli_config = cli::extract_args(&matches); let cli::Config { diff --git a/bench-streamer/Cargo.toml b/bench-streamer/Cargo.toml index 5663ca6554..f0ec178f42 100644 --- a/bench-streamer/Cargo.toml +++ b/bench-streamer/Cargo.toml @@ -13,6 +13,7 @@ solana-clap-utils = { path = "../clap-utils", version = "1.2.0" } solana-streamer = { path = "../streamer", version = "1.2.0" } solana-logger = { path = "../logger", version = "1.2.0" } solana-net-utils = { path = "../net-utils", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/bench-streamer/src/main.rs b/bench-streamer/src/main.rs index 708e14d6fd..d3c776721d 100644 --- a/bench-streamer/src/main.rs +++ b/bench-streamer/src/main.rs @@ -52,7 +52,7 @@ fn main() -> Result<()> { let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .arg( Arg::with_name("num-recv-sockets") .long("num-recv-sockets") diff --git a/bench-tps/Cargo.toml b/bench-tps/Cargo.toml index 53e4dd288d..ba750e7a61 100644 --- a/bench-tps/Cargo.toml +++ b/bench-tps/Cargo.toml @@ -27,6 +27,7 @@ solana-net-utils = { path = "../net-utils", version = "1.2.0" } solana-runtime = { path = "../runtime", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } solana-move-loader-program = { path = "../programs/move_loader", version = "1.2.0", optional = true } +solana-version = { path = "../version", version = "1.2.0" } [dev-dependencies] serial_test = "0.4.0" diff --git a/bench-tps/src/main.rs b/bench-tps/src/main.rs index dfefa22847..48fb5a95f6 100644 --- a/bench-tps/src/main.rs +++ b/bench-tps/src/main.rs @@ -15,7 +15,7 @@ fn main() { solana_logger::setup_with_default("solana=info"); solana_metrics::set_panic_hook("bench-tps"); - let matches = cli::build_args(solana_clap_utils::version!()).get_matches(); + let matches = cli::build_args(solana_version::version!()).get_matches(); let cli_config = cli::extract_args(&matches); let cli::Config { diff --git a/clap-utils/src/lib.rs b/clap-utils/src/lib.rs index d24beb73e4..ab51ffa627 100644 --- a/clap-utils/src/lib.rs +++ b/clap-utils/src/lib.rs @@ -1,24 +1,5 @@ use thiserror::Error; -#[macro_export] -macro_rules! version { - () => { - &*format!( - "{}{}", - env!("CARGO_PKG_VERSION"), - if option_env!("CI_TAG").unwrap_or("").is_empty() { - format!( - " [channel={} commit={}]", - option_env!("CHANNEL").unwrap_or("unknown"), - option_env!("CI_COMMIT").unwrap_or("unknown"), - ) - } else { - "".to_string() - }, - ) - }; -} - pub struct ArgConstant<'a> { pub long: &'a str, pub name: &'a str, diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 0f81312d4d..880b894e6e 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -41,6 +41,7 @@ solana-sdk = { path = "../sdk", version = "1.2.0" } solana-stake-program = { path = "../programs/stake", version = "1.2.0" } solana-storage-program = { path = "../programs/storage", version = "1.2.0" } solana-transaction-status = { path = "../transaction-status", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } solana-vote-program = { path = "../programs/vote", version = "1.2.0" } solana-vote-signer = { path = "../vote-signer", version = "1.2.0" } thiserror = "1.0.15" diff --git a/cli/src/main.rs b/cli/src/main.rs index 0001847957..f68d6c2370 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -156,7 +156,7 @@ fn main() -> Result<(), Box> { let matches = app( crate_name!(), crate_description!(), - solana_clap_utils::version!(), + solana_version::version!(), ) .arg({ let arg = Arg::with_name("config_file") diff --git a/core/Cargo.toml b/core/Cargo.toml index d984ffad82..72a0c85ec0 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -61,6 +61,7 @@ solana-sdk = { path = "../sdk", version = "1.2.0" } solana-stake-program = { path = "../programs/stake", version = "1.2.0" } solana-storage-program = { path = "../programs/storage", version = "1.2.0" } solana-streamer = { path = "../streamer", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } solana-vote-program = { path = "../programs/vote", version = "1.2.0" } solana-vote-signer = { path = "../vote-signer", version = "1.2.0" } solana-sys-tuner = { path = "../sys-tuner", version = "1.2.0" } diff --git a/core/src/cluster_info.rs b/core/src/cluster_info.rs index 20ca23881d..e86a1615c0 100644 --- a/core/src/cluster_info.rs +++ b/core/src/cluster_info.rs @@ -18,8 +18,8 @@ use crate::{ crds_gossip_error::CrdsGossipError, crds_gossip_pull::{CrdsFilter, CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS}, crds_value::{ - self, CrdsData, CrdsValue, CrdsValueLabel, EpochSlotsIndex, LowestSlot, SnapshotHash, Vote, - MAX_WALLCLOCK, + self, CrdsData, CrdsValue, CrdsValueLabel, EpochSlotsIndex, LowestSlot, SnapshotHash, + Version, Vote, MAX_WALLCLOCK, }, epoch_slots::EpochSlots, result::{Error, Result}, @@ -378,6 +378,7 @@ impl ClusterInfo { archivers += 1; } + let node_version = self.get_node_version(&node.id); if my_shred_version != 0 && (node.shred_version != 0 && node.shred_version != my_shred_version) { different_shred_nodes += 1; None @@ -393,10 +394,9 @@ impl ClusterInfo { "none".to_string() } } - let ip_addr = node.gossip.ip(); Some(format!( - "{:15} {:2}| {:5} | {:44} | {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {}\n", + "{:15} {:2}| {:5} | {:44} |{:^15}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {}\n", if ContactInfo::is_valid_address(&node.gossip) { ip_addr.to_string() } else { @@ -405,6 +405,11 @@ impl ClusterInfo { if node.id == my_pubkey { "me" } else { "" }.to_string(), now.saturating_sub(last_updated), node.id.to_string(), + if let Some(node_version) = node_version { + node_version.to_string() + } else { + "-".to_string() + }, addr_to_string(&ip_addr, &node.gossip), addr_to_string(&ip_addr, &node.tpu), addr_to_string(&ip_addr, &node.tpu_forwards), @@ -412,7 +417,6 @@ impl ClusterInfo { addr_to_string(&ip_addr, &node.tvu_forwards), addr_to_string(&ip_addr, &node.repair), addr_to_string(&ip_addr, &node.serve_repair), - addr_to_string(&ip_addr, &node.storage_addr), addr_to_string(&ip_addr, &node.rpc), addr_to_string(&ip_addr, &node.rpc_pubsub), node.shred_version, @@ -423,9 +427,9 @@ impl ClusterInfo { format!( "IP Address |Age(ms)| Node identifier \ - |Gossip| TPU |TPUfwd| TVU |TVUfwd|Repair|ServeR|Storag| RPC |PubSub|ShredVer\n\ - ------------------+-------+----------------------------------------------+\ - ------+------+------+------+------+------+------+------+------+------+--------\n\ + | Version |Gossip| TPU |TPUfwd| TVU |TVUfwd|Repair|ServeR| RPC |PubSub|ShredVer\n\ + ------------------+-------+----------------------------------------------+---------------+\ + ------+------+------+------+------+------+------+------+------+--------\n\ {}\ Nodes: {}{}{}{}", nodes.join(""), @@ -440,7 +444,7 @@ impl ClusterInfo { } else { "".to_string() }, - if spy_nodes > 0 { + if different_shred_nodes > 0 { format!( "\nNodes with different shred version: {}", different_shred_nodes @@ -703,6 +707,18 @@ impl ClusterInfo { (vec, max) } + pub fn get_node_version(&self, pubkey: &Pubkey) -> Option { + self.gossip + .read() + .unwrap() + .crds + .table + .get(&CrdsValueLabel::Version(*pubkey)) + .map(|x| x.value.version()) + .flatten() + .map(|version| version.version.clone()) + } + /// all validators that have a valid rpc port regardless of `shred_version`. pub fn all_rpc_peers(&self) -> Vec { self.gossip @@ -1313,6 +1329,9 @@ impl ClusterInfo { let mut last_contact_info_trace = timestamp(); let mut adopt_shred_version = obj.my_shred_version() == 0; let recycler = PacketsRecycler::default(); + + let message = CrdsData::Version(Version::new(obj.id())); + obj.push_message(CrdsValue::new_signed(message, &obj.keypair)); loop { let start = timestamp(); thread_mem_usage::datapoint("solana-gossip"); diff --git a/core/src/crds_value.rs b/core/src/crds_value.rs index 5265c1c99a..26878d06f7 100644 --- a/core/src/crds_value.rs +++ b/core/src/crds_value.rs @@ -75,6 +75,7 @@ pub enum CrdsData { SnapshotHashes(SnapshotHash), AccountsHashes(SnapshotHash), EpochSlots(EpochSlotsIndex, EpochSlots), + Version(Version), } impl Sanitize for CrdsData { @@ -101,6 +102,7 @@ impl Sanitize for CrdsData { } val.sanitize() } + CrdsData::Version(version) => version.sanitize(), } } } @@ -206,6 +208,33 @@ impl Vote { } } +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +pub struct Version { + pub from: Pubkey, + pub wallclock: u64, + pub version: solana_version::Version, +} + +impl Sanitize for Version { + fn sanitize(&self) -> Result<(), SanitizeError> { + if self.wallclock >= MAX_WALLCLOCK { + return Err(SanitizeError::ValueOutOfBounds); + } + self.from.sanitize()?; + self.version.sanitize() + } +} + +impl Version { + pub fn new(from: Pubkey) -> Self { + Self { + from, + wallclock: timestamp(), + version: solana_version::Version::default(), + } + } +} + /// Type of the replicated value /// These are labels for values in a record that is associated with `Pubkey` #[derive(PartialEq, Hash, Eq, Clone, Debug)] @@ -216,6 +245,7 @@ pub enum CrdsValueLabel { SnapshotHashes(Pubkey), EpochSlots(EpochSlotsIndex, Pubkey), AccountsHashes(Pubkey), + Version(Pubkey), } impl fmt::Display for CrdsValueLabel { @@ -227,6 +257,7 @@ impl fmt::Display for CrdsValueLabel { CrdsValueLabel::SnapshotHashes(_) => write!(f, "SnapshotHash({})", self.pubkey()), CrdsValueLabel::EpochSlots(ix, _) => write!(f, "EpochSlots({}, {})", ix, self.pubkey()), CrdsValueLabel::AccountsHashes(_) => write!(f, "AccountsHashes({})", self.pubkey()), + CrdsValueLabel::Version(_) => write!(f, "Version({})", self.pubkey()), } } } @@ -240,6 +271,7 @@ impl CrdsValueLabel { CrdsValueLabel::SnapshotHashes(p) => *p, CrdsValueLabel::EpochSlots(_, p) => *p, CrdsValueLabel::AccountsHashes(p) => *p, + CrdsValueLabel::Version(p) => *p, } } } @@ -257,7 +289,7 @@ impl CrdsValue { value.sign(keypair); value } - /// Totally unsecure unverfiable wallclock of the node that generated this message + /// Totally unsecure unverifiable wallclock of the node that generated this message /// Latest wallclock is always picked. /// This is used to time out push messages. pub fn wallclock(&self) -> u64 { @@ -268,6 +300,7 @@ impl CrdsValue { CrdsData::SnapshotHashes(hash) => hash.wallclock, CrdsData::AccountsHashes(hash) => hash.wallclock, CrdsData::EpochSlots(_, p) => p.wallclock, + CrdsData::Version(version) => version.wallclock, } } pub fn pubkey(&self) -> Pubkey { @@ -278,6 +311,7 @@ impl CrdsValue { CrdsData::SnapshotHashes(hash) => hash.from, CrdsData::AccountsHashes(hash) => hash.from, CrdsData::EpochSlots(_, p) => p.from, + CrdsData::Version(version) => version.from, } } pub fn label(&self) -> CrdsValueLabel { @@ -288,6 +322,7 @@ impl CrdsValue { CrdsData::SnapshotHashes(_) => CrdsValueLabel::SnapshotHashes(self.pubkey()), CrdsData::AccountsHashes(_) => CrdsValueLabel::AccountsHashes(self.pubkey()), CrdsData::EpochSlots(ix, _) => CrdsValueLabel::EpochSlots(*ix, self.pubkey()), + CrdsData::Version(_) => CrdsValueLabel::Version(self.pubkey()), } } pub fn contact_info(&self) -> Option<&ContactInfo> { @@ -338,6 +373,13 @@ impl CrdsValue { } } + pub fn version(&self) -> Option<&Version> { + match &self.data { + CrdsData::Version(version) => Some(version), + _ => None, + } + } + /// Return all the possible labels for a record identified by Pubkey. pub fn record_labels(key: &Pubkey) -> Vec { let mut labels = vec![ @@ -345,6 +387,7 @@ impl CrdsValue { CrdsValueLabel::LowestSlot(*key), CrdsValueLabel::SnapshotHashes(*key), CrdsValueLabel::AccountsHashes(*key), + CrdsValueLabel::Version(*key), ]; labels.extend((0..MAX_VOTES).map(|ix| CrdsValueLabel::Vote(ix, *key))); labels.extend((0..MAX_EPOCH_SLOTS).map(|ix| CrdsValueLabel::EpochSlots(ix, *key))); @@ -395,7 +438,7 @@ mod test { #[test] fn test_labels() { - let mut hits = [false; 4 + MAX_VOTES as usize + MAX_EPOCH_SLOTS as usize]; + let mut hits = [false; 5 + MAX_VOTES as usize + MAX_EPOCH_SLOTS as usize]; // this method should cover all the possible labels for v in &CrdsValue::record_labels(&Pubkey::default()) { match v { @@ -403,9 +446,10 @@ mod test { CrdsValueLabel::LowestSlot(_) => hits[1] = true, CrdsValueLabel::SnapshotHashes(_) => hits[2] = true, CrdsValueLabel::AccountsHashes(_) => hits[3] = true, - CrdsValueLabel::Vote(ix, _) => hits[*ix as usize + 4] = true, + CrdsValueLabel::Version(_) => hits[4] = true, + CrdsValueLabel::Vote(ix, _) => hits[*ix as usize + 5] = true, CrdsValueLabel::EpochSlots(ix, _) => { - hits[*ix as usize + MAX_VOTES as usize + 4] = true + hits[*ix as usize + MAX_VOTES as usize + 5] = true } } } diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 7e144fbb99..495d82b431 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -1465,7 +1465,7 @@ impl RpcSol for RpcSolImpl { fn get_version(&self, _: Self::Metadata) -> Result { Ok(RpcVersionInfo { - solana_core: solana_clap_utils::version!().to_string(), + solana_core: solana_version::Version::default().to_string(), }) } @@ -2628,7 +2628,7 @@ pub mod tests { let expected = json!({ "jsonrpc": "2.0", "result": { - "solana-core": solana_clap_utils::version!().to_string() + "solana-core": solana_version::version!().to_string() }, "id": 1 }); diff --git a/core/tests/client.rs b/core/tests/client.rs index 0c5755ee85..71be8443cb 100644 --- a/core/tests/client.rs +++ b/core/tests/client.rs @@ -46,7 +46,7 @@ fn test_rpc_client() { assert_eq!( client.get_version().unwrap().solana_core, - solana_clap_utils::version!() + solana_version::version!() ); assert!(client.get_account(&bob_pubkey).is_err()); diff --git a/dos/Cargo.toml b/dos/Cargo.toml index 08a606be81..37b4b6bf73 100644 --- a/dos/Cargo.toml +++ b/dos/Cargo.toml @@ -19,6 +19,7 @@ solana-logger = { path = "../logger", version = "1.2.0" } solana-net-utils = { path = "../net-utils", version = "1.2.0" } solana-runtime = { path = "../runtime", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/dos/src/main.rs b/dos/src/main.rs index 9576c06f5c..ef60415acc 100644 --- a/dos/src/main.rs +++ b/dos/src/main.rs @@ -94,7 +94,7 @@ fn main() { solana_logger::setup_with_default("solana=info"); let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .arg( Arg::with_name("entrypoint") .long("entrypoint") diff --git a/faucet/Cargo.toml b/faucet/Cargo.toml index 03d614c325..91263e73e0 100644 --- a/faucet/Cargo.toml +++ b/faucet/Cargo.toml @@ -8,9 +8,6 @@ license = "Apache-2.0" homepage = "https://solana.com/" edition = "2018" - - - [dependencies] bincode = "1.2.1" byteorder = "1.3.4" @@ -23,6 +20,7 @@ solana-clap-utils = { path = "../clap-utils", version = "1.2.0" } solana-logger = { path = "../logger", version = "1.2.0" } solana-metrics = { path = "../metrics", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } tokio = "0.1" tokio-codec = "0.1" diff --git a/faucet/src/bin/faucet.rs b/faucet/src/bin/faucet.rs index 4975c633e4..6bb1150aae 100644 --- a/faucet/src/bin/faucet.rs +++ b/faucet/src/bin/faucet.rs @@ -16,7 +16,7 @@ fn main() -> Result<(), Box> { solana_metrics::set_panic_hook("faucet"); let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .arg( Arg::with_name("keypair") .short("k") diff --git a/genesis/Cargo.toml b/genesis/Cargo.toml index 1f163f3ddb..3e9c36c9a6 100644 --- a/genesis/Cargo.toml +++ b/genesis/Cargo.toml @@ -23,13 +23,13 @@ solana-sdk = { path = "../sdk", version = "1.2.0" } solana-stake-program = { path = "../programs/stake", version = "1.2.0" } solana-storage-program = { path = "../programs/storage", version = "1.2.0" } solana-vote-program = { path = "../programs/vote", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } tempfile = "3.1.0" [[bin]] name = "solana-genesis" path = "src/main.rs" - [lib] name = "solana_genesis" diff --git a/genesis/src/main.rs b/genesis/src/main.rs index 8da1b8a85e..8523d177a8 100644 --- a/genesis/src/main.rs +++ b/genesis/src/main.rs @@ -128,7 +128,7 @@ fn main() -> Result<(), Box> { let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .arg( Arg::with_name("creation_time") .long("creation-time") diff --git a/gossip/Cargo.toml b/gossip/Cargo.toml index 3db274bd7b..48b317904e 100644 --- a/gossip/Cargo.toml +++ b/gossip/Cargo.toml @@ -16,9 +16,7 @@ solana-client = { path = "../client", version = "1.2.0" } solana-logger = { path = "../logger", version = "1.2.0" } solana-net-utils = { path = "../net-utils", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } - - - +solana-version = { path = "../version", version = "1.2.0" } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/gossip/src/main.rs b/gossip/src/main.rs index ebd2f9778f..a640841d97 100644 --- a/gossip/src/main.rs +++ b/gossip/src/main.rs @@ -17,7 +17,7 @@ fn main() -> Result<(), Box> { let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .setting(AppSettings::SubcommandRequiredElseHelp) .subcommand( SubCommand::with_name("rpc-url") diff --git a/install/Cargo.toml b/install/Cargo.toml index b06ec4816c..c44efa1c1e 100644 --- a/install/Cargo.toml +++ b/install/Cargo.toml @@ -29,6 +29,7 @@ solana-client = { path = "../client", version = "1.2.0" } solana-config-program = { path = "../programs/config", version = "1.2.0" } solana-logger = { path = "../logger", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } semver = "0.9.0" tar = "0.4.26" tempdir = "0.3.7" diff --git a/install/src/lib.rs b/install/src/lib.rs index 7e9c0dbb6e..298676ba2e 100644 --- a/install/src/lib.rs +++ b/install/src/lib.rs @@ -84,7 +84,7 @@ pub fn main() -> Result<(), String> { let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .setting(AppSettings::SubcommandRequiredElseHelp) .arg({ let arg = Arg::with_name("config_file") @@ -268,7 +268,7 @@ pub fn main_init() -> Result<(), String> { let matches = App::new("solana-install-init") .about("initializes a new installation") - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .arg({ let arg = Arg::with_name("config_file") .short("c") diff --git a/keygen/Cargo.toml b/keygen/Cargo.toml index 5536f2def5..46ee81a9cc 100644 --- a/keygen/Cargo.toml +++ b/keygen/Cargo.toml @@ -17,6 +17,7 @@ solana-clap-utils = { path = "../clap-utils", version = "1.2.0" } solana-cli-config = { path = "../cli-config", version = "1.2.0" } solana-remote-wallet = { path = "../remote-wallet", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } tiny-bip39 = "0.7.0" [[bin]] diff --git a/keygen/src/keygen.rs b/keygen/src/keygen.rs index 20e41f287f..65c13457f0 100644 --- a/keygen/src/keygen.rs +++ b/keygen/src/keygen.rs @@ -208,7 +208,7 @@ fn grind_parse_args( fn main() -> Result<(), Box> { let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .setting(AppSettings::SubcommandRequiredElseHelp) .arg({ let arg = Arg::with_name("config_file") diff --git a/ledger-tool/Cargo.toml b/ledger-tool/Cargo.toml index a0197cd4a6..8a08c78826 100644 --- a/ledger-tool/Cargo.toml +++ b/ledger-tool/Cargo.toml @@ -22,6 +22,7 @@ solana-runtime = { path = "../runtime", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } solana-stake-program = { path = "../programs/stake", version = "1.2.0" } solana-transaction-status = { path = "../transaction-status", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } solana-vote-program = { path = "../programs/vote", version = "1.2.0" } tempfile = "3.1.0" diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index f1f2a1b2ec..025ad0c0af 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -631,7 +631,7 @@ fn main() { let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .arg( Arg::with_name("ledger_path") .short("l") diff --git a/log-analyzer/Cargo.toml b/log-analyzer/Cargo.toml index 9454cd4aa7..958dcd9c26 100644 --- a/log-analyzer/Cargo.toml +++ b/log-analyzer/Cargo.toml @@ -16,6 +16,7 @@ serde = "1.0.110" serde_json = "1.0.53" solana-clap-utils = { path = "../clap-utils", version = "1.2.0" } solana-logger = { path = "../logger", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } [[bin]] name = "solana-log-analyzer" diff --git a/log-analyzer/src/main.rs b/log-analyzer/src/main.rs index 1eb123cfe2..11b3542d47 100644 --- a/log-analyzer/src/main.rs +++ b/log-analyzer/src/main.rs @@ -200,7 +200,7 @@ fn main() { let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .subcommand( SubCommand::with_name("iftop") .about("Process iftop log file") diff --git a/net-utils/Cargo.toml b/net-utils/Cargo.toml index f520845662..d50b6626d0 100644 --- a/net-utils/Cargo.toml +++ b/net-utils/Cargo.toml @@ -20,6 +20,7 @@ serde_derive = "1.0.103" socket2 = "0.3.12" solana-clap-utils = { path = "../clap-utils", version = "1.2.0" } solana-logger = { path = "../logger", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } tokio = "0.1" tokio-codec = "0.1" diff --git a/net-utils/src/bin/ip_address.rs b/net-utils/src/bin/ip_address.rs index bbb86c09c7..e4545f72bb 100644 --- a/net-utils/src/bin/ip_address.rs +++ b/net-utils/src/bin/ip_address.rs @@ -3,7 +3,7 @@ use clap::{App, Arg}; fn main() { solana_logger::setup(); let matches = App::new("solana-ip-address") - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .arg( Arg::with_name("host_port") .index(1) diff --git a/net-utils/src/bin/ip_address_server.rs b/net-utils/src/bin/ip_address_server.rs index 4780ca915c..d1b2e60d32 100644 --- a/net-utils/src/bin/ip_address_server.rs +++ b/net-utils/src/bin/ip_address_server.rs @@ -4,7 +4,7 @@ use std::net::{SocketAddr, TcpListener}; fn main() { solana_logger::setup(); let matches = App::new("solana-ip-address-server") - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .arg( Arg::with_name("port") .index(1) diff --git a/stake-monitor/Cargo.toml b/stake-monitor/Cargo.toml index bd65ed9747..f068576d8a 100644 --- a/stake-monitor/Cargo.toml +++ b/stake-monitor/Cargo.toml @@ -22,6 +22,7 @@ solana-metrics = { path = "../metrics", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } solana-stake-program = { path = "../programs/stake", version = "1.2.0" } solana-transaction-status = { path = "../transaction-status", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } [dev-dependencies] serial_test = "0.4.0" diff --git a/stake-monitor/src/main.rs b/stake-monitor/src/main.rs index 29873bb7ac..c0eaeae6fc 100644 --- a/stake-monitor/src/main.rs +++ b/stake-monitor/src/main.rs @@ -119,7 +119,7 @@ fn main() { let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .setting(AppSettings::SubcommandRequiredElseHelp) .arg( Arg::with_name("data_file") diff --git a/sys-tuner/Cargo.toml b/sys-tuner/Cargo.toml index 623e6d0e57..a7e05cda05 100644 --- a/sys-tuner/Cargo.toml +++ b/sys-tuner/Cargo.toml @@ -15,6 +15,7 @@ log = "0.4.8" libc = "0.2.69" solana-clap-utils = { path = "../clap-utils", version = "1.2.0" } solana-logger = { path = "../logger", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } [target."cfg(unix)".dependencies] unix_socket2 = "0.5.4" diff --git a/sys-tuner/src/main.rs b/sys-tuner/src/main.rs index 0b920b92e8..aa00bd7cdb 100644 --- a/sys-tuner/src/main.rs +++ b/sys-tuner/src/main.rs @@ -101,7 +101,7 @@ fn main() { solana_logger::setup(); let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .arg( Arg::with_name("user") .long("user") diff --git a/validator/Cargo.toml b/validator/Cargo.toml index e3eec9ceae..8ea7c1fdb8 100644 --- a/validator/Cargo.toml +++ b/validator/Cargo.toml @@ -27,6 +27,7 @@ solana-metrics = { path = "../metrics", version = "1.2.0" } solana-net-utils = { path = "../net-utils", version = "1.2.0" } solana-runtime = { path = "../runtime", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } solana-vote-program = { path = "../programs/vote", version = "1.2.0" } solana-vote-signer = { path = "../vote-signer", version = "1.2.0" } diff --git a/validator/src/main.rs b/validator/src/main.rs index edf69de7a6..dd9aec8e92 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -472,7 +472,7 @@ pub fn main() { let default_genesis_archive_unpacked_size = &MAX_GENESIS_ARCHIVE_UNPACKED_SIZE.to_string(); let matches = App::new(crate_name!()).about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .arg( Arg::with_name(SKIP_SEED_PHRASE_VALIDATION_ARG.name) .long(SKIP_SEED_PHRASE_VALIDATION_ARG.long) @@ -1017,7 +1017,7 @@ pub fn main() { env::set_var("RUST_BACKTRACE", "1") } - info!("{} {}", crate_name!(), solana_clap_utils::version!()); + info!("{} {}", crate_name!(), solana_version::version!()); info!("Starting validator with: {:#?}", std::env::args_os()); solana_metrics::set_host_id(identity_keypair.pubkey().to_string()); diff --git a/version/.gitignore b/version/.gitignore new file mode 100644 index 0000000000..5404b132db --- /dev/null +++ b/version/.gitignore @@ -0,0 +1,2 @@ +/target/ +/farf/ diff --git a/version/Cargo.toml b/version/Cargo.toml new file mode 100644 index 0000000000..8e0186426d --- /dev/null +++ b/version/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "solana-version" +version = "1.2.0" +description = "Solana Version" +authors = ["Solana Maintainers "] +repository = "https://github.com/solana-labs/solana" +license = "Apache-2.0" +homepage = "https://solana.com/" +edition = "2018" + +[dependencies] +serde = "1.0.110" +serde_derive = "1.0.103" +solana-sdk = { path = "../sdk", version = "1.2.0" } + +[lib] +name = "solana_version" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/version/src/lib.rs b/version/src/lib.rs new file mode 100644 index 0000000000..b94683d89c --- /dev/null +++ b/version/src/lib.rs @@ -0,0 +1,49 @@ +extern crate serde_derive; +use serde_derive::{Deserialize, Serialize}; +use solana_sdk::sanitize::Sanitize; +use std::fmt; + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +pub struct Version { + major: u16, + minor: u16, + patch: u16, + commit: Option, // first 4 bytes of the sha1 commit hash +} + +impl Default for Version { + fn default() -> Self { + Self { + major: env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap(), + minor: env!("CARGO_PKG_VERSION_MINOR").parse().unwrap(), + patch: env!("CARGO_PKG_VERSION_PATCH").parse().unwrap(), + commit: option_env!("CI_COMMIT") + .map(|sha1| u32::from_str_radix(&sha1[..8], 16).unwrap()), + } + } +} + +impl fmt::Display for Version { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}.{}.{} {}", + self.major, + self.minor, + self.patch, + match self.commit { + None => "devbuild".to_string(), + Some(commit) => format!("{:08x}", commit), + } + ) + } +} + +impl Sanitize for Version {} + +#[macro_export] +macro_rules! version { + () => { + &*format!("{}", $crate::Version::default()) + }; +} diff --git a/vote-signer/Cargo.toml b/vote-signer/Cargo.toml index 66dae7610e..b1824d2fbb 100644 --- a/vote-signer/Cargo.toml +++ b/vote-signer/Cargo.toml @@ -18,6 +18,7 @@ serde_json = "1.0.53" solana-clap-utils = { path = "../clap-utils", version = "1.2.0" } solana-metrics = { path = "../metrics", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } [lib] crate-type = ["lib"] diff --git a/vote-signer/src/bin/main.rs b/vote-signer/src/bin/main.rs index 678935e815..0a010fa69a 100644 --- a/vote-signer/src/bin/main.rs +++ b/vote-signer/src/bin/main.rs @@ -11,7 +11,7 @@ fn main() -> Result<(), Box> { let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .arg( Arg::with_name("port") .long("port") diff --git a/watchtower/Cargo.toml b/watchtower/Cargo.toml index 76765846ee..6b9e8157c2 100644 --- a/watchtower/Cargo.toml +++ b/watchtower/Cargo.toml @@ -22,6 +22,7 @@ solana-logger = { path = "../logger", version = "1.2.0" } solana-metrics = { path = "../metrics", version = "1.2.0" } solana-sdk = { path = "../sdk", version = "1.2.0" } solana-transaction-status = { path = "../transaction-status", version = "1.2.0" } +solana-version = { path = "../version", version = "1.2.0" } solana-vote-program = { path = "../programs/vote", version = "1.2.0" } [[bin]] diff --git a/watchtower/src/main.rs b/watchtower/src/main.rs index cd87ac721c..499f23da26 100644 --- a/watchtower/src/main.rs +++ b/watchtower/src/main.rs @@ -38,7 +38,7 @@ struct Config { fn get_config() -> Config { let matches = App::new(crate_name!()) .about(crate_description!()) - .version(solana_clap_utils::version!()) + .version(solana_version::version!()) .after_help("ADDITIONAL HELP: To receive a Slack, Discord and/or Telegram notification on sanity failure, define environment variables before running `solana-watchtower`: