Further topology cleanup by defining NymTopology trait

This commit is contained in:
Jedrzej Stuczynski
2020-01-08 12:55:40 +00:00
parent 1292cdb145
commit db67744b19
8 changed files with 152 additions and 55 deletions
Generated
+1 -1
View File
@@ -449,6 +449,7 @@ version = "0.1.0"
dependencies = [
"reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"topology 0.1.0",
]
[[package]]
@@ -2056,7 +2057,6 @@ dependencies = [
"addressing 0.1.0",
"base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"directory_client 0.1.0",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
+4 -1
View File
@@ -8,4 +8,7 @@ edition = "2018"
[dependencies]
reqwest = "0.9.22"
serde = { version = "1.0.104", features = ["derive"] }
serde = { version = "1.0.104", features = ["derive"] }
## internal
topology = {path = "../../common/topology"}
+75 -1
View File
@@ -1,11 +1,24 @@
use crate::requests::presence_topology_get::PresenceTopologyGetRequester;
use crate::{Client, Config, DirectoryClient};
use serde::{Deserialize, Serialize};
use topology::NymTopology;
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CocoPresence {
pub host: String,
pub pub_key: String,
pub last_seen: i64,
pub last_seen: u64,
}
impl Into<topology::CocoNode> for CocoPresence {
fn into(self) -> topology::CocoNode {
topology::CocoNode {
host: self.host,
pub_key: self.pub_key,
last_seen: self.last_seen,
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
@@ -18,21 +31,54 @@ pub struct MixNodePresence {
pub version: String,
}
impl Into<topology::MixNode> for MixNodePresence {
fn into(self) -> topology::MixNode {
topology::MixNode {
host: self.host,
pub_key: self.pub_key,
layer: self.layer,
last_seen: self.last_seen,
version: self.version,
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MixProviderPresence {
pub host: String,
pub pub_key: String,
pub registered_clients: Vec<MixProviderClient>,
pub last_seen: u64,
pub version: String,
}
impl Into<topology::MixProviderNode> for MixProviderPresence {
fn into(self) -> topology::MixProviderNode {
topology::MixProviderNode {
host: self.host,
pub_key: self.pub_key,
registered_clients: self.registered_clients.into_iter().map(|c| c.into()).collect(),
last_seen: self.last_seen,
version: self.version,
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MixProviderClient {
pub pub_key: String,
}
impl Into<topology::MixProviderClient> for MixProviderClient {
fn into(self) -> topology::MixProviderClient {
topology::MixProviderClient {
pub_key: self.pub_key,
}
}
}
// Topology shows us the current state of the overall Nym network
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
@@ -41,3 +87,31 @@ pub struct Topology {
pub mix_nodes: Vec<MixNodePresence>,
pub mix_provider_nodes: Vec<MixProviderPresence>,
}
impl NymTopology for Topology {
fn new(directory_server: String) -> Self {
println!("Using directory server: {:?}", directory_server);
let directory_config = Config {
base_url: directory_server,
};
let directory = Client::new(directory_config);
let topology = directory
.presence_topology
.get()
.expect("Failed to retrieve network topology.");
topology
}
fn get_mix_nodes(&self) -> Vec<topology::MixNode> {
self.mix_nodes.iter().map(|x| x.clone().into()).collect()
}
fn get_mix_provider_nodes(&self) -> Vec<topology::MixProviderNode> {
self.mix_provider_nodes.iter().map(|x| x.clone().into()).collect()
}
fn get_coco_nodes(&self) -> Vec<topology::CocoNode> {
self.coco_nodes.iter().map(|x| x.clone().into()).collect()
}
}
+3 -3
View File
@@ -14,7 +14,7 @@ use std::net::SocketAddr;
use std::sync::Arc;
use std::time::Duration;
use tokio::runtime::Runtime;
use topology::get_topology;
use topology::NymTopology;
const LOOP_COVER_AVERAGE_DELAY: f64 = 0.5;
// seconds
@@ -223,10 +223,10 @@ impl NymClient {
println!("Starting nym client");
let mut rt = Runtime::new()?;
let topology = get_topology(self.directory.clone());
let topology = Topology::new(self.directory.clone());
// this is temporary and assumes there exists only a single provider.
let provider_address: SocketAddr = topology
.mix_provider_nodes
.get_mix_provider_nodes()
.first()
.unwrap()
.host
+2 -1
View File
@@ -5,6 +5,7 @@ use directory_client::presence::Topology;
use sphinx::route::{Destination, DestinationAddressBytes, Node, SURBIdentifier};
use sphinx::SphinxPacket;
use std::net::SocketAddr;
use topology::NymTopology;
pub const LOOP_COVER_MESSAGE_PAYLOAD: &[u8] = b"The cake is a lie!";
@@ -23,7 +24,7 @@ pub fn encapsulate_message(
message: Vec<u8>,
topology: &Topology,
) -> (SocketAddr, SphinxPacket) {
let mixes_route = topology::route_from(&topology);
let mixes_route = topology.route_from();
let first_provider = topology.mix_provider_nodes.first().unwrap();
let decoded_key_bytes =
base64::decode_config(&first_provider.pub_key, base64::URL_SAFE).unwrap();
-1
View File
@@ -15,7 +15,6 @@ serde = { version = "1.0.104", features = ["derive"] }
## internal
addressing = {path = "../addressing"}
directory_client = { path = "../../client/directory_client" }
## will be moved to proper dependencies once released
sphinx = { path = "../../../sphinx" }
+66 -47
View File
@@ -1,56 +1,75 @@
use addressing;
use curve25519_dalek::montgomery::MontgomeryPoint;
use directory_client::presence::{MixNodePresence, Topology};
use directory_client::requests::presence_topology_get::PresenceTopologyGetRequester;
use directory_client::DirectoryClient;
use rand::seq::SliceRandom;
use sphinx::route::Node as SphinxNode;
use std::collections::HashMap;
pub fn get_topology(directory_server: String) -> Topology {
println!("Using directory server: {:?}", directory_server);
let directory_config = directory_client::Config {
base_url: directory_server,
};
let directory = directory_client::Client::new(directory_config);
let topology = directory
.presence_topology
.get()
.expect("Failed to retrieve network topology.");
topology
#[derive(Debug)]
pub struct MixNode {
pub host: String,
pub pub_key: String,
pub layer: u64,
pub last_seen: u64,
pub version: String,
}
pub fn route_from(topology: &Topology) -> Vec<SphinxNode> {
let mut layered_topology: HashMap<u64, Vec<MixNodePresence>> = HashMap::new();
let mixes = topology.mix_nodes.iter();
for mix in mixes {
let layer_nodes = layered_topology.entry(mix.layer).or_insert(Vec::new());
layer_nodes.push(mix.clone());
}
let num_layers = layered_topology.len() as u64;
let mut route = vec![];
for x in 1..=num_layers {
let nodes = &layered_topology[&x];
let the_node = nodes.choose(&mut rand::thread_rng()).unwrap();
route.push(the_node);
}
route
.iter()
.map(|mix| {
let address_bytes =
addressing::encoded_bytes_from_socket_address(mix.host.clone().parse().unwrap());
let decoded_key_bytes = base64::decode_config(&mix.pub_key, base64::URL_SAFE).unwrap();
let mut key_bytes = [0; 32];
key_bytes.copy_from_slice(&decoded_key_bytes[..]);
let key = MontgomeryPoint(key_bytes);
SphinxNode {
address: address_bytes,
pub_key: key,
}
})
.collect()
#[derive(Debug)]
pub struct MixProviderClient {
pub pub_key: String,
}
#[derive(Debug)]
pub struct MixProviderNode {
pub host: String,
pub pub_key: String,
pub registered_clients: Vec<MixProviderClient>,
pub last_seen: u64,
pub version: String,
}
#[derive(Debug)]
pub struct CocoNode {
pub host: String,
pub pub_key: String,
pub last_seen: u64,
}
pub trait NymTopology {
fn new(directory_server: String) -> Self;
fn get_mix_nodes(&self) -> Vec<MixNode>;
fn get_mix_provider_nodes(&self) -> Vec<MixProviderNode>;
fn get_coco_nodes(&self) -> Vec<CocoNode>;
fn route_from(&self) -> Vec<SphinxNode> {
let mut layered_topology: HashMap<u64, Vec<MixNode>> = HashMap::new();
for mix in self.get_mix_nodes() {
let layer_nodes = layered_topology.entry(mix.layer).or_insert(Vec::new());
layer_nodes.push(mix);
}
// TODO: assertion that num_layers is a sane number
let num_layers = layered_topology.len() as u64;
let route: Vec<_> = (1..=num_layers)
.map(|layer| &layered_topology[&layer]) // for each layer
.map(|nodes| nodes.choose(&mut rand::thread_rng()).unwrap()) // choose random node
.collect();
route
.iter()
.map(|mix| {
let address_bytes = addressing::encoded_bytes_from_socket_address(
mix.host.clone().parse().unwrap(),
);
let decoded_key_bytes =
base64::decode_config(&mix.pub_key, base64::URL_SAFE).unwrap();
let mut key_bytes = [0; 32];
key_bytes.copy_from_slice(&decoded_key_bytes[..]);
let key = MontgomeryPoint(key_bytes);
SphinxNode {
address: address_bytes,
pub_key: key,
}
})
.collect()
}
}
+1
View File
@@ -42,6 +42,7 @@ impl Notifier {
host: self.host.clone(),
pub_key: self.pub_key.clone(),
registered_clients: unlocked_ledger.current_clients(),
last_seen: 0,
version: env!("CARGO_PKG_VERSION").to_string(),
}
}