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
@@ -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
@@ -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,
@@ -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,
@@ -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(
@@ -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,
@@ -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,
@@ -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,
@@ -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(),
@@ -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,
}
@@ -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(),
@@ -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()
}
}
@@ -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())
}

@@ -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
@@ -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
@@ -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();
2 changes: 1 addition & 1 deletion common/clients/provider-client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
@@ -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
@@ -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 {
@@ -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();
23 changes: 10 additions & 13 deletions common/healthcheck/src/result.rs
Original file line number Diff line number Diff line change
@@ -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()
@@ -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())) {
@@ -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())) {
@@ -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,
@@ -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 {
7 changes: 4 additions & 3 deletions common/healthcheck/src/score.rs
Original file line number Diff line number Diff line change
@@ -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

@@ -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),
@@ -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),
3 changes: 2 additions & 1 deletion common/topology/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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