Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/version filtering improvements #96

Merged
merged 11 commits into from
Jan 24, 2020
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 32 additions & 29 deletions common/clients/directory-client/src/presence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use std::collections::HashSet;
use std::convert::TryInto;
use std::io;
use std::net::ToSocketAddrs;
use topology::{CocoNode, MixNode, MixProviderNode, NymTopology};
use topology::coco;
use topology::mix;
use topology::provider;
use topology::NymTopology;

// special version of 'PartialEq' that does not care about last_seen field (where applicable)
// or order of elements in vectors
Expand All @@ -23,9 +26,9 @@ pub struct CocoPresence {
pub version: String,
}

impl Into<topology::CocoNode> for CocoPresence {
fn into(self) -> topology::CocoNode {
topology::CocoNode {
impl Into<topology::coco::Node> for CocoPresence {
fn into(self) -> topology::coco::Node {
topology::coco::Node {
host: self.host,
pub_key: self.pub_key,
last_seen: self.last_seen,
Expand All @@ -34,8 +37,8 @@ impl Into<topology::CocoNode> for CocoPresence {
}
}

impl From<topology::CocoNode> for CocoPresence {
fn from(cn: CocoNode) -> Self {
impl From<topology::coco::Node> for CocoPresence {
fn from(cn: coco::Node) -> Self {
CocoPresence {
host: cn.host,
pub_key: cn.pub_key,
Expand All @@ -55,10 +58,10 @@ pub struct MixNodePresence {
pub version: String,
}

impl TryInto<topology::MixNode> for MixNodePresence {
impl TryInto<topology::mix::Node> for MixNodePresence {
type Error = io::Error;

fn try_into(self) -> Result<MixNode, Self::Error> {
fn try_into(self) -> Result<topology::mix::Node, Self::Error> {
let resolved_hostname = self.host.to_socket_addrs()?.next();
if resolved_hostname.is_none() {
return Err(io::Error::new(
Expand All @@ -67,7 +70,7 @@ impl TryInto<topology::MixNode> for MixNodePresence {
));
}

Ok(topology::MixNode {
Ok(topology::mix::Node {
host: resolved_hostname.unwrap(),
pub_key: self.pub_key,
layer: self.layer,
Expand All @@ -77,8 +80,8 @@ impl TryInto<topology::MixNode> for MixNodePresence {
}
}

impl From<topology::MixNode> for MixNodePresence {
fn from(mn: MixNode) -> Self {
impl From<topology::mix::Node> for MixNodePresence {
fn from(mn: mix::Node) -> Self {
MixNodePresence {
host: mn.host.to_string(),
pub_key: mn.pub_key,
Expand Down Expand Up @@ -126,9 +129,9 @@ impl PresenceEq for MixProviderPresence {
}
}

impl Into<topology::MixProviderNode> for MixProviderPresence {
fn into(self) -> topology::MixProviderNode {
topology::MixProviderNode {
impl Into<topology::provider::Node> for MixProviderPresence {
fn into(self) -> topology::provider::Node {
topology::provider::Node {
client_listener: self.client_listener.parse().unwrap(),
mixnet_listener: self.mixnet_listener.parse().unwrap(),
pub_key: self.pub_key,
Expand All @@ -143,8 +146,8 @@ impl Into<topology::MixProviderNode> for MixProviderPresence {
}
}

impl From<topology::MixProviderNode> for MixProviderPresence {
fn from(mpn: MixProviderNode) -> Self {
impl From<topology::provider::Node> for MixProviderPresence {
fn from(mpn: provider::Node) -> Self {
MixProviderPresence {
client_listener: mpn.client_listener.to_string(),
mixnet_listener: mpn.mixnet_listener.to_string(),
Expand All @@ -166,16 +169,16 @@ pub struct MixProviderClient {
pub pub_key: String,
}

impl Into<topology::MixProviderClient> for MixProviderClient {
fn into(self) -> topology::MixProviderClient {
topology::MixProviderClient {
impl Into<topology::provider::Client> for MixProviderClient {
fn into(self) -> topology::provider::Client {
topology::provider::Client {
pub_key: self.pub_key,
}
}
}

impl From<topology::MixProviderClient> for MixProviderClient {
fn from(mpc: topology::MixProviderClient) -> Self {
impl From<topology::provider::Client> for MixProviderClient {
fn from(mpc: topology::provider::Client) -> Self {
MixProviderClient {
pub_key: mpc.pub_key,
}
Expand Down Expand Up @@ -318,9 +321,9 @@ impl NymTopology for Topology {
}

fn new_from_nodes(
mix_nodes: Vec<MixNode>,
mix_provider_nodes: Vec<MixProviderNode>,
coco_nodes: Vec<CocoNode>,
mix_nodes: Vec<mix::Node>,
mix_provider_nodes: Vec<provider::Node>,
coco_nodes: Vec<coco::Node>,
) -> Self {
Topology {
coco_nodes: coco_nodes.into_iter().map(|node| node.into()).collect(),
Expand All @@ -332,21 +335,21 @@ impl NymTopology for Topology {
}
}

fn get_mix_nodes(&self) -> Vec<topology::MixNode> {
fn mix_nodes(&self) -> Vec<mix::Node> {
self.mix_nodes
.iter()
.filter_map(|x| x.clone().try_into().ok())
.collect()
}

fn get_mix_provider_nodes(&self) -> Vec<topology::MixProviderNode> {
fn providers(&self) -> Vec<provider::Node> {
self.mix_provider_nodes
.iter()
.map(|x| x.clone().into())
.collect()
}

fn get_coco_nodes(&self) -> Vec<topology::CocoNode> {
fn coco_nodes(&self) -> Vec<topology::coco::Node> {
self.coco_nodes.iter().map(|x| x.clone().into()).collect()
}
}
Expand All @@ -367,7 +370,7 @@ mod converting_mixnode_presence_into_topology_mixnode {
version: "".to_string(),
};

let result: Result<topology::MixNode, io::Error> = mix_presence.try_into();
let result: Result<mix::Node, io::Error> = mix_presence.try_into();
assert!(result.is_err())
}

Expand All @@ -383,7 +386,7 @@ mod converting_mixnode_presence_into_topology_mixnode {
version: "".to_string(),
};

let result: Result<topology::MixNode, io::Error> = mix_presence.try_into();
let result: Result<topology::mix::Node, io::Error> = mix_presence.try_into();
assert!(result.is_ok())
}
}
3 changes: 2 additions & 1 deletion common/clients/mix-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ addressing = {path = "../../addressing"}
topology = {path = "../../topology"}

## will be moved to proper dependencies once released
sphinx = { git = "https://github.com/nymtech/sphinx", rev="1d8cefcb6a0cb8e87d00d89eb1ccf2839e92aa1f" }
sphinx = { git = "https://github.com/nymtech/sphinx", rev="47c4fbba8272c4aee03cc8165220f33572a96602" }
# sphinx = { path = "../../../../sphinx"}

2 changes: 1 addition & 1 deletion common/clients/mix-client/src/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub fn encapsulate_message<T: NymTopology>(
topology: &T,
average_delay: f64,
) -> (SocketAddr, SphinxPacket) {
let mut providers = topology.get_mix_provider_nodes();
let mut providers = topology.providers();
let provider = providers.pop().unwrap().into();

let route = topology.route_to(provider).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion common/clients/provider-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ tokio = { version = "0.2", features = ["full"] }
sfw-provider-requests = { path = "../../../sfw-provider/sfw-provider-requests" }

## will be moved to proper dependencies once released
sphinx = { git = "https://github.com/nymtech/sphinx", rev="1d8cefcb6a0cb8e87d00d89eb1ccf2839e92aa1f" }
sphinx = { git = "https://github.com/nymtech/sphinx", rev="47c4fbba8272c4aee03cc8165220f33572a96602" }
3 changes: 2 additions & 1 deletion common/healthcheck/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ sfw-provider-requests = { path = "../../sfw-provider/sfw-provider-requests" }
topology = {path = "../topology" }

## will be moved to proper dependencies once released
sphinx = { git = "https://github.com/nymtech/sphinx", rev="1d8cefcb6a0cb8e87d00d89eb1ccf2839e92aa1f" }
sphinx = { git = "https://github.com/nymtech/sphinx", rev="47c4fbba8272c4aee03cc8165220f33572a96602" }
# sphinx = { path = "../../../sphinx"}

[dev-dependencies]
4 changes: 2 additions & 2 deletions common/healthcheck/src/path_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use provider_client::ProviderClient;
use sphinx::header::delays::Delay;
use sphinx::route::{Destination, Node as SphinxNode};
use std::collections::HashMap;
use topology::MixProviderNode;
use topology::provider;

#[derive(Debug, PartialEq, Clone)]
pub enum PathStatus {
Expand All @@ -27,7 +27,7 @@ pub(crate) struct PathChecker {

impl PathChecker {
pub(crate) async fn new(
providers: Vec<MixProviderNode>,
providers: Vec<provider::Node>,
ephemeral_keys: DummyMixIdentityKeyPair,
) -> Self {
let mut provider_clients = HashMap::new();
Expand Down
23 changes: 10 additions & 13 deletions common/healthcheck/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ impl HealthCheckResult {

fn zero_score<T: NymTopology>(topology: T) -> Self {
warn!("The network is unhealthy, could not send any packets - returning zero score!");
let mixes = topology.get_mix_nodes();
let providers = topology.get_mix_provider_nodes();
let mixes = topology.mix_nodes();
let providers = topology.providers();

let health = mixes
.into_iter()
Expand Down Expand Up @@ -58,7 +58,7 @@ impl HealthCheckResult {
score_threshold: f64,
) -> T {
let filtered_mix_nodes = topology
.get_mix_nodes()
.mix_nodes()
.into_iter()
.filter(|node| {
match self.node_score(NodeAddressBytes::from_b64_string(node.pub_key.clone())) {
Expand All @@ -72,7 +72,7 @@ impl HealthCheckResult {
.collect();

let filtered_provider_nodes = topology
.get_mix_provider_nodes()
.providers()
.into_iter()
.filter(|node| {
match self.node_score(NodeAddressBytes::from_b64_string(node.pub_key.clone())) {
Expand All @@ -85,7 +85,7 @@ impl HealthCheckResult {
})
.collect();
// coco nodes remain unchanged as no healthcheck is being run on them or time being
let filtered_coco_nodes = topology.get_coco_nodes();
let filtered_coco_nodes = topology.coco_nodes();

T::new_from_nodes(
filtered_mix_nodes,
Expand All @@ -110,19 +110,16 @@ impl HealthCheckResult {

// create entries for all nodes
let mut score_map = HashMap::new();
topology.get_mix_nodes().into_iter().for_each(|node| {
topology.mix_nodes().into_iter().for_each(|node| {
score_map.insert(node.get_pub_key_bytes(), NodeScore::from_mixnode(node));
});

topology
.get_mix_provider_nodes()
.into_iter()
.for_each(|node| {
score_map.insert(node.get_pub_key_bytes(), NodeScore::from_provider(node));
});
topology.providers().into_iter().for_each(|node| {
score_map.insert(node.get_pub_key_bytes(), NodeScore::from_provider(node));
});

let ephemeral_keys = DummyMixIdentityKeyPair::new();
let providers = topology.get_mix_provider_nodes();
let providers = topology.providers();

let mut path_checker = PathChecker::new(providers, ephemeral_keys).await;
for i in 0..iterations {
Expand Down
7 changes: 4 additions & 3 deletions common/healthcheck/src/score.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use std::cmp::Ordering;
use std::fmt::Error;
use std::fmt::Formatter;
use std::net::SocketAddr;
use topology::{MixNode, MixProviderNode};
use topology::mix;
use topology::provider;

// TODO: should 'nodetype' really be part of healthcheck::score

Expand Down Expand Up @@ -91,7 +92,7 @@ impl PartialEq for NodeScore {
}

impl NodeScore {
pub(crate) fn from_mixnode(node: MixNode) -> Self {
pub(crate) fn from_mixnode(node: mix::Node) -> Self {
NodeScore {
typ: NodeType::Mix,
pub_key: NodeAddressBytes::from_b64_string(node.pub_key),
Expand All @@ -103,7 +104,7 @@ impl NodeScore {
}
}

pub(crate) fn from_provider(node: MixProviderNode) -> Self {
pub(crate) fn from_provider(node: provider::Node) -> Self {
NodeScore {
typ: NodeType::MixProvider,
pub_key: NodeAddressBytes::from_b64_string(node.pub_key),
Expand Down
3 changes: 2 additions & 1 deletion common/topology/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ 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" }
sphinx = { git = "https://github.com/nymtech/sphinx", rev="47c4fbba8272c4aee03cc8165220f33572a96602" }
# sphinx = { path = "../../../sphinx"}
15 changes: 15 additions & 0 deletions common/topology/src/coco.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use crate::filter;

#[derive(Debug, Clone)]
pub struct Node {
pub host: String,
pub pub_key: String,
pub last_seen: u64,
pub version: String,
}

impl filter::Versioned for Node {
fn version(&self) -> String {
self.version.clone()
}
}
18 changes: 18 additions & 0 deletions common/topology/src/filter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
pub trait Versioned: Clone {
fn version(&self) -> String;
}

pub trait VersionFilterable<T> {
fn filter_by_version(&self, expected_version: &str) -> Self;
}

impl<T: Versioned> VersionFilterable<T> for Vec<T> {
fn filter_by_version(&self, expected_version: &str) -> Self {
self.iter()
.filter(|node| {
version_checker::is_minor_version_compatible(&node.version(), expected_version)
})
.cloned()
.collect()
}
}
Loading