From aa6f4b4c0eb70c1427342ed83daf535bf32e25bb Mon Sep 17 00:00:00 2001 From: Chris O'Neil Date: Sun, 8 Dec 2024 15:13:20 +0000 Subject: [PATCH] feat: provide new versioning mechanism Implements the versioning scheme that was discussed and agreed. It only uses the version from the `ant-protocol` crate; no keys or other external sources are provided. Only the `MAJOR` and `MINOR` parts of the version are considered. The patch version can advance without being considered. We have discussed changing the version of other crates such that they are synchronised with this protocol version. --- ant-bootstrap/src/config.rs | 4 +- ant-networking/src/driver.rs | 20 ++--- ant-networking/src/event/swarm.rs | 10 +-- ant-node/src/bin/antnode/main.rs | 8 +- ant-protocol/src/version.rs | 125 ++++++++++++++++-------------- autonomi/src/client/mod.rs | 4 +- 6 files changed, 88 insertions(+), 83 deletions(-) diff --git a/ant-bootstrap/src/config.rs b/ant-bootstrap/src/config.rs index 52d85b7dee..86771ed9f8 100644 --- a/ant-bootstrap/src/config.rs +++ b/ant-bootstrap/src/config.rs @@ -7,7 +7,7 @@ // permissions and limitations relating to use of the SAFE Network Software. use crate::error::{Error, Result}; -use ant_protocol::version::{get_key_version_str, get_truncate_version_str}; +use ant_protocol::version::get_protocol_version; use std::{ path::{Path, PathBuf}, time::Duration, @@ -118,7 +118,7 @@ fn default_cache_path() -> Result { std::fs::create_dir_all(&dir)?; - let network_id = format!("{}_{}", get_key_version_str(), get_truncate_version_str()); + let network_id = get_protocol_version(); let path = dir.join(format!("bootstrap_cache_{}.json", network_id)); Ok(path) diff --git a/ant-networking/src/driver.rs b/ant-networking/src/driver.rs index 872e55d26a..15db679e25 100644 --- a/ant-networking/src/driver.rs +++ b/ant-networking/src/driver.rs @@ -35,8 +35,7 @@ use ant_protocol::{ messages::{ChunkProof, Nonce, Request, Response}, storage::{try_deserialize_record, RetryStrategy}, version::{ - get_key_version_str, IDENTIFY_CLIENT_VERSION_STR, IDENTIFY_NODE_VERSION_STR, - IDENTIFY_PROTOCOL_STR, REQ_RESPONSE_VERSION_STR, + get_protocol_version, CLIENT_VERSION, NODE_VERSION, PROTOCOL_VERSION, REQ_RESPONSE_VERSION, }, NetworkAddress, PrettyPrintKBucketKey, PrettyPrintRecordKey, }; @@ -388,7 +387,7 @@ impl NetworkBuilder { check_and_wipe_storage_dir_if_necessary( root_dir.clone(), storage_dir_path.clone(), - get_key_version_str(), + get_protocol_version(), )?; // Configures the disk_store to store records under the provided path and increase the max record size @@ -425,7 +424,7 @@ impl NetworkBuilder { Some(store_cfg), false, ProtocolSupport::Full, - IDENTIFY_NODE_VERSION_STR.to_string(), + NODE_VERSION.to_string(), #[cfg(feature = "upnp")] upnp, )?; @@ -476,7 +475,7 @@ impl NetworkBuilder { None, true, ProtocolSupport::Outbound, - IDENTIFY_CLIENT_VERSION_STR.to_string(), + CLIENT_VERSION.to_string(), #[cfg(feature = "upnp")] false, )?; @@ -557,7 +556,7 @@ impl NetworkBuilder { "The protocol version string that is used to connect to the correct network", Info::new(vec![( "identify_protocol_str".to_string(), - IDENTIFY_PROTOCOL_STR.to_string(), + PROTOCOL_VERSION.to_string(), )]), ); @@ -574,13 +573,10 @@ impl NetworkBuilder { info!( "Building request response with {:?}", - REQ_RESPONSE_VERSION_STR.as_str() + REQ_RESPONSE_VERSION.as_str() ); request_response::cbor::Behaviour::new( - [( - StreamProtocol::new(&REQ_RESPONSE_VERSION_STR), - req_res_protocol, - )], + [(StreamProtocol::new(&REQ_RESPONSE_VERSION), req_res_protocol)], cfg, ) }; @@ -635,7 +631,7 @@ impl NetworkBuilder { let mdns = mdns::tokio::Behaviour::new(mdns_config, peer_id)?; // Identify Behaviour - let identify_protocol_str = IDENTIFY_PROTOCOL_STR.to_string(); + let identify_protocol_str = PROTOCOL_VERSION.to_string(); info!("Building Identify with identify_protocol_str: {identify_protocol_str:?} and identify_version: {identify_version:?}"); let identify = { let mut cfg = diff --git a/ant-networking/src/event/swarm.rs b/ant-networking/src/event/swarm.rs index 84127c43d3..b1afc9089d 100644 --- a/ant-networking/src/event/swarm.rs +++ b/ant-networking/src/event/swarm.rs @@ -10,7 +10,7 @@ use crate::{ event::NodeEvent, multiaddr_get_ip, multiaddr_is_global, multiaddr_strip_p2p, relay_manager::is_a_relayed_peer, target_arch::Instant, NetworkEvent, Result, SwarmDriver, }; -use ant_protocol::version::{IDENTIFY_NODE_VERSION_STR, IDENTIFY_PROTOCOL_STR}; +use ant_protocol::version::{NODE_VERSION, PROTOCOL_VERSION}; #[cfg(feature = "local")] use libp2p::mdns; #[cfg(feature = "open-metrics")] @@ -124,11 +124,11 @@ impl SwarmDriver { } => { debug!(conn_id=%connection_id, %peer_id, ?info, "identify: received info"); - if info.protocol_version != IDENTIFY_PROTOCOL_STR.to_string() { - warn!(?info.protocol_version, "identify: {peer_id:?} does not have the same protocol. Our IDENTIFY_PROTOCOL_STR: {:?}", IDENTIFY_PROTOCOL_STR.as_str()); + if info.protocol_version != PROTOCOL_VERSION.to_string() { + warn!(?info.protocol_version, "identify: {peer_id:?} does not have the same protocol. Our IDENTIFY_PROTOCOL_STR: {:?}", PROTOCOL_VERSION.as_str()); self.send_event(NetworkEvent::PeerWithUnsupportedProtocol { - our_protocol: IDENTIFY_PROTOCOL_STR.to_string(), + our_protocol: PROTOCOL_VERSION.to_string(), their_protocol: info.protocol_version, }); // Block the peer from any further communication. @@ -144,7 +144,7 @@ impl SwarmDriver { } // if client, return. - if info.agent_version != IDENTIFY_NODE_VERSION_STR.to_string() { + if info.agent_version != NODE_VERSION.to_string() { return Ok(()); } diff --git a/ant-node/src/bin/antnode/main.rs b/ant-node/src/bin/antnode/main.rs index 6246206211..c7a9fa778f 100644 --- a/ant-node/src/bin/antnode/main.rs +++ b/ant-node/src/bin/antnode/main.rs @@ -22,7 +22,7 @@ use ant_node::{Marker, NodeBuilder, NodeEvent, NodeEventsReceiver}; use ant_protocol::{ node::get_antnode_root_dir, node_rpc::{NodeCtrl, StopResult}, - version::IDENTIFY_PROTOCOL_STR, + version::PROTOCOL_VERSION, }; use clap::{command, Parser}; use color_eyre::{eyre::eyre, Result}; @@ -223,7 +223,7 @@ fn main() -> Result<()> { ant_build_info::version_string( "Autonomi Node", env!("CARGO_PKG_VERSION"), - Some(&IDENTIFY_PROTOCOL_STR) + Some(&PROTOCOL_VERSION) ) ); return Ok(()); @@ -240,7 +240,7 @@ fn main() -> Result<()> { } if opt.protocol_version { - println!("Network version: {}", *IDENTIFY_PROTOCOL_STR); + println!("Network version: {}", *PROTOCOL_VERSION); return Ok(()); } @@ -279,7 +279,7 @@ fn main() -> Result<()> { ); info!("\n{}\n{}", msg, "=".repeat(msg.len())); - ant_build_info::log_version_info(env!("CARGO_PKG_VERSION"), &IDENTIFY_PROTOCOL_STR); + ant_build_info::log_version_info(env!("CARGO_PKG_VERSION"), &PROTOCOL_VERSION); debug!( "antnode built with git version: {}", ant_build_info::git_info() diff --git a/ant-protocol/src/version.rs b/ant-protocol/src/version.rs index 6606e74be0..40f9b420d2 100644 --- a/ant-protocol/src/version.rs +++ b/ant-protocol/src/version.rs @@ -9,88 +9,97 @@ use lazy_static::lazy_static; lazy_static! { - /// The node version used during Identify Behaviour. - pub static ref IDENTIFY_NODE_VERSION_STR: String = + /// The version used to identify the node + pub static ref NODE_VERSION: String = format!( - "safe/node/{}/{}", - get_truncate_version_str(), - get_key_version_str(), + "ant/node/{}", + get_protocol_version(), ); - /// The client version used during Identify Behaviour. - pub static ref IDENTIFY_CLIENT_VERSION_STR: String = + /// The version used to identify the client + pub static ref CLIENT_VERSION: String = format!( - "safe/client/{}/{}", - get_truncate_version_str(), - get_key_version_str(), + "ant/client/{}", + get_protocol_version(), ); - /// The req/response protocol version - pub static ref REQ_RESPONSE_VERSION_STR: String = + /// The req/response version + pub static ref REQ_RESPONSE_VERSION: String = format!( - "/safe/node/{}/{}", - get_truncate_version_str(), - get_key_version_str(), + "/ant/node/{}", + get_protocol_version(), ); - /// The identify protocol version - pub static ref IDENTIFY_PROTOCOL_STR: String = + /// The current protocol version + pub static ref PROTOCOL_VERSION: String = format!( - "safe/{}/{}", - get_truncate_version_str(), - get_key_version_str(), + "ant/{}", + get_protocol_version(), ); } -// Protocol support shall be downward compatible for patch only version update. -// i.e. versions of `A.B.X` or `A.B.X-alpha.Y` shall be considered as a same protocol of `A.B` -pub fn get_truncate_version_str() -> String { - let version_str = env!("CARGO_PKG_VERSION"); - let parts = version_str.split('.').collect::>(); +pub fn get_protocol_version() -> String { + let version = env!("CARGO_PKG_VERSION"); + let parts = version.split('.').collect::>(); if parts.len() >= 2 { - format!("{}.{}", parts[0], parts[1]) - } else { - panic!("Cannot obtain truncated version str for {version_str:?}: {parts:?}"); + return format!("{}.{}", parts[0], parts[1]); } + panic!("Cannot obtain protocol version from {version:?}: {parts:?}"); } -/// FIXME: Remove this once BEFORE next breaking release and fix this whole file -/// Get the PKs version string. -/// If the public key mis-configed via env variable, -/// it shall result in being rejected to join by the network -pub fn get_key_version_str() -> String { - // let mut f_k_str = FOUNDATION_PK.to_hex(); - // let _ = f_k_str.split_off(6); - // let mut g_k_str = GENESIS_PK.to_hex(); - // let _ = g_k_str.split_off(6); - // let mut n_k_str = NETWORK_ROYALTIES_PK.to_hex(); - // let _ = n_k_str.split_off(6); - // let s = format!("{f_k_str}_{g_k_str}_{n_k_str}"); - // dbg!(&s); - "b20c91_93f735_af451a".to_string() -} #[cfg(test)] mod tests { use super::*; #[test] - fn test_print_version_strings() -> Result<(), Box> { - // Test and print all version strings - println!( - "\nIDENTIFY_CLIENT_VERSION_STR: {}", - *IDENTIFY_CLIENT_VERSION_STR - ); - println!("REQ_RESPONSE_VERSION_STR: {}", *REQ_RESPONSE_VERSION_STR); - println!("IDENTIFY_PROTOCOL_STR: {}", *IDENTIFY_PROTOCOL_STR); + fn test_node_version_format() { + let protocol_ver = get_protocol_version(); + let expected = format!("ant/node/{protocol_ver}"); + assert_eq!(*NODE_VERSION, expected); + } + + #[test] + fn test_client_version_format() { + let protocol_ver = get_protocol_version(); + let expected = format!("ant/client/{protocol_ver}"); + assert_eq!(*CLIENT_VERSION, expected); + } + + #[test] + fn test_req_response_version_format() { + let protocol_ver = get_protocol_version(); + let expected = format!("/ant/node/{protocol_ver}"); + assert_eq!(*REQ_RESPONSE_VERSION, expected); + } - // Test truncated version string - let truncated = get_truncate_version_str(); - println!("\nTruncated version: {truncated}"); + #[test] + fn test_protocol_version_format() { + let protocol_ver = get_protocol_version(); + let expected = format!("ant/{protocol_ver}"); + assert_eq!(*PROTOCOL_VERSION, expected); + } + + #[test] + fn test_get_protocol_version() { + let version = get_protocol_version(); + assert_eq!(version.chars().filter(|&c| c == '.').count(), 1); + + let parts: Vec<&str> = version.split('.').collect(); + assert_eq!(parts.len(), 2); + + assert!(parts[0].parse::().is_ok()); + assert!(parts[1].parse::().is_ok()); + } + + #[test] + fn test_version_consistency() { + let cargo_version = env!("CARGO_PKG_VERSION"); + let protocol_version = get_protocol_version(); - // Test key version string - let key_version = get_key_version_str(); - println!("\nKey version string: {key_version}"); + let cargo_parts: Vec<&str> = cargo_version.split('.').collect(); + let protocol_parts: Vec<&str> = protocol_version.split('.').collect(); - Ok(()) + assert_eq!(cargo_parts[0], protocol_parts[0]); + assert_eq!(cargo_parts[1], protocol_parts[1]); } } diff --git a/autonomi/src/client/mod.rs b/autonomi/src/client/mod.rs index acc62981da..a90fc86536 100644 --- a/autonomi/src/client/mod.rs +++ b/autonomi/src/client/mod.rs @@ -34,7 +34,7 @@ use ant_bootstrap::{BootstrapCacheConfig, BootstrapCacheStore}; pub use ant_evm::Amount; use ant_networking::{interval, multiaddr_is_global, Network, NetworkBuilder, NetworkEvent}; -use ant_protocol::{version::IDENTIFY_PROTOCOL_STR, CLOSE_GROUP_SIZE}; +use ant_protocol::{version::PROTOCOL_VERSION, CLOSE_GROUP_SIZE}; use libp2p::{identity::Keypair, Multiaddr}; use std::{collections::HashSet, sync::Arc, time::Duration}; use tokio::sync::mpsc; @@ -177,7 +177,7 @@ async fn handle_event_receiver( sender .send(Err(ConnectError::TimedOutWithIncompatibleProtocol( protocols, - IDENTIFY_PROTOCOL_STR.to_string(), + PROTOCOL_VERSION.to_string(), ))) .expect("receiver should not close"); } else {