From 44116e49074b398a652671bf829267fa53738fbd Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Wed, 22 Jan 2020 16:17:35 +0000 Subject: [PATCH 1/2] common: adding a version-checker crate --- Cargo.lock | 8 +++++ common/version-checker/.gitignore | 3 ++ common/version-checker/Cargo.toml | 10 ++++++ common/version-checker/src/lib.rs | 51 +++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+) create mode 100644 common/version-checker/.gitignore create mode 100644 common/version-checker/Cargo.toml create mode 100644 common/version-checker/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 66d9693e547..5aec0f39d01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2422,6 +2422,7 @@ dependencies = [ "rand 0.7.2", "serde", "sphinx", + "version-checker", ] [[package]] @@ -2557,6 +2558,13 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +[[package]] +name = "version-checker" +version = "0.1.0" +dependencies = [ + "semver", +] + [[package]] name = "version_check" version = "0.1.5" diff --git a/common/version-checker/.gitignore b/common/version-checker/.gitignore new file mode 100644 index 00000000000..693699042b1 --- /dev/null +++ b/common/version-checker/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock diff --git a/common/version-checker/Cargo.toml b/common/version-checker/Cargo.toml new file mode 100644 index 00000000000..80c97fb3499 --- /dev/null +++ b/common/version-checker/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "version-checker" +version = "0.1.0" +authors = ["Dave Hrycyszyn "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +semver = "0.9.0" \ No newline at end of file diff --git a/common/version-checker/src/lib.rs b/common/version-checker/src/lib.rs new file mode 100644 index 00000000000..d6ae38d19ec --- /dev/null +++ b/common/version-checker/src/lib.rs @@ -0,0 +1,51 @@ +use semver::Version; +use semver::VersionReq; + +/// Checks whether given `version` is compatible with a given semantic +/// version requirement `req` according to major-minor semver rules. +/// The semantic version requirement can be passed as a full, concrete version +/// number, because that's what we'll have in our Cargo.toml files (e.g. 0.3.2). +/// The patch number in the requirement will be dropped and replaced with a wildcard (0.3.*) as all minor versions should be compatible with each other. +pub fn is_compatible(version: &str, req: &str) -> bool { + let version = Version::parse(version).unwrap(); + let tmp = Version::parse(req).unwrap(); + let wildcard = format!("{}.{}.*", tmp.major, tmp.minor).to_string(); + let semver_requirement = VersionReq::parse(&wildcard).unwrap(); + + semver_requirement.matches(&version) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn version_0_3_0_is_compatible_with_requirement_0_3_x() { + assert!(is_compatible("0.3.0", "0.3.2")); + } + + #[test] + fn version_0_3_1_is_compatible_with_minimum_requirement_0_3_x() { + assert!(is_compatible("0.3.1", "0.3.2")); + } + + #[test] + fn version_0_3_2_is_compatible_with_minimum_requirement_0_3_x() { + assert!(is_compatible("0.3.2", "0.3.0")); + } + + #[test] + fn version_0_2_0_is_not_compatible_with_requirement_0_3_x() { + assert!(!is_compatible("0.2.0", "0.3.2")); + } + + #[test] + fn version_0_4_0_is_not_compatible_with_requirement_0_3_x() { + assert!(!is_compatible("0.4.0", "0.3.2")); + } + + #[test] + fn version_1_3_2_is_not_compatible_with_requirement_0_3_x() { + assert!(!is_compatible("1.3.2", "0.3.2")); + } +} From 65f5683b12050f4b99f678f34c51acf38ad4fc78 Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Wed, 22 Jan 2020 16:18:00 +0000 Subject: [PATCH 2/2] topology: checking for compatible semver between nodes and clients --- common/topology/Cargo.toml | 1 + common/topology/src/lib.rs | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/common/topology/Cargo.toml b/common/topology/Cargo.toml index 628672da6ee..70153485865 100644 --- a/common/topology/Cargo.toml +++ b/common/topology/Cargo.toml @@ -16,6 +16,7 @@ serde = { version = "1.0.104", features = ["derive"] } ## internal addressing = {path = "../addressing"} +version-checker = {path = "../version-checker" } ## will be moved to proper dependencies once released sphinx = { git = "https://github.com/nymtech/sphinx", rev="1d8cefcb6a0cb8e87d00d89eb1ccf2839e92aa1f" } diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index dd29508ef27..8fadc5c2ab6 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -6,6 +6,7 @@ use sphinx::route::{Node as SphinxNode, NodeAddressBytes}; use std::cmp::max; use std::collections::HashMap; use std::net::SocketAddr; +use version_checker; #[derive(Debug, Clone)] pub struct MixNode { @@ -167,27 +168,33 @@ pub trait NymTopology: Sized { fn filter_node_versions( &self, - mix_version: &str, - provider_version: &str, - coco_version: &str, + expected_mix_version: &str, + expected_provider_version: &str, + expected_coco_version: &str, ) -> Self { let filtered_mixes = self .get_mix_nodes() .iter() + .filter(|mix_node| { + version_checker::is_compatible(&mix_node.version, expected_mix_version) + }) .cloned() - .filter(|mix_node| mix_node.version == mix_version) .collect(); let filtered_providers = self .get_mix_provider_nodes() .iter() + .filter(|provider_node| { + version_checker::is_compatible(&provider_node.version, expected_provider_version) + }) .cloned() - .filter(|provider_node| provider_node.version == provider_version) .collect(); let filtered_coco_nodes = self .get_coco_nodes() .iter() + .filter(|coco_node| { + version_checker::is_compatible(&coco_node.version, expected_coco_version) + }) .cloned() - .filter(|coco_node| coco_node.version == coco_version) .collect(); Self::new_from_nodes(filtered_mixes, filtered_providers, filtered_coco_nodes)