Feature/wasm topology duplication (#265)

* Removed constructor from NymTopology trait + split directory_client

* Removed bunch of duplicate wasm topology code

* Post-merge changes
This commit is contained in:
Jędrzej Stuczyński
2020-06-16 12:12:19 +01:00
committed by GitHub
parent b57a548350
commit fcfe463efa
28 changed files with 212 additions and 528 deletions
Generated
+10 -2
View File
@@ -634,6 +634,7 @@ dependencies = [
name = "directory-client"
version = "0.1.0"
dependencies = [
"directory-client-models",
"futures 0.3.4",
"log 0.4.8",
"mockito",
@@ -641,6 +642,13 @@ dependencies = [
"reqwest 0.10.4",
"serde",
"tokio 0.2.16",
]
[[package]]
name = "directory-client-models"
version = "0.1.0"
dependencies = [
"serde",
"topology",
]
@@ -1761,10 +1769,11 @@ dependencies = [
[[package]]
name = "nym-client-wasm"
version = "0.7.4"
version = "0.7.5"
dependencies = [
"console_error_panic_hook",
"crypto",
"directory-client-models",
"log 0.4.8",
"nymsphinx",
"rand 0.7.3",
@@ -3271,7 +3280,6 @@ name = "topology"
version = "0.1.0"
dependencies = [
"bs58",
"futures 0.3.4",
"itertools",
"log 0.4.8",
"nymsphinx-addressing",
+1
View File
@@ -8,6 +8,7 @@ members = [
"clients/native",
"clients/webassembly",
"common/client-libs/directory-client",
"common/client-libs/directory-client/models",
"common/client-libs/gateway-client",
"common/client-libs/mixnet-client",
"common/client-libs/validator-client",
+4 -6
View File
@@ -25,7 +25,6 @@ use crate::client::topology_control::{
use crate::config::{Config, SocketType};
use crate::websocket;
use crypto::identity::MixIdentityKeyPair;
use directory_client::presence;
use futures::channel::mpsc;
use gateway_client::{
AcknowledgementReceiver, AcknowledgementSender, GatewayClient, MixnetMessageReceiver,
@@ -221,16 +220,16 @@ impl NymClient {
// future responsible for periodically polling directory server and updating
// the current global view of topology
fn start_topology_refresher<T: 'static + NymTopology>(
fn start_topology_refresher(
&mut self,
topology_accessor: TopologyAccessor<T>,
topology_accessor: TopologyAccessor<directory_client::Topology>,
) {
let topology_refresher_config = TopologyRefresherConfig::new(
self.config.get_directory_server(),
self.config.get_topology_refresh_rate(),
);
let mut topology_refresher =
TopologyRefresher::new(topology_refresher_config, topology_accessor);
TopologyRefresher::new_directory_client(topology_refresher_config, topology_accessor);
// before returning, block entire runtime to refresh the current network view so that any
// components depending on topology would see a non-empty view
info!(
@@ -354,9 +353,8 @@ impl NymClient {
// channels responsible for controlling ack messages
let (ack_sender, ack_receiver) = mpsc::unbounded();
let shared_topology_accessor = TopologyAccessor::<directory_client::Topology>::new();
// TODO: when we switch to our graph topology, we need to remember to change 'presence::Topology' type
let shared_topology_accessor = TopologyAccessor::<presence::Topology>::new();
// the components are started in very specific order. Unless you know what you are doing,
// do not change that.
self.start_topology_refresher(shared_topology_accessor.clone());
+19 -12
View File
@@ -13,6 +13,7 @@
// limitations under the License.
use crate::built_info;
use directory_client::DirectoryClient;
use log::*;
use nymsphinx::addressing::clients::Recipient;
use std::ops::Deref;
@@ -167,34 +168,40 @@ impl TopologyRefresherConfig {
}
pub(crate) struct TopologyRefresher<T: NymTopology> {
directory_server: String,
directory_client: directory_client::Client,
topology_accessor: TopologyAccessor<T>,
refresh_rate: Duration,
}
impl<T: 'static + NymTopology> TopologyRefresher<T> {
pub(crate) fn new(
// TODO: consider (or maybe not) restoring generic TopologyRefresher<T>
impl TopologyRefresher<directory_client::Topology> {
pub(crate) fn new_directory_client(
cfg: TopologyRefresherConfig,
topology_accessor: TopologyAccessor<T>,
topology_accessor: TopologyAccessor<directory_client::Topology>,
) -> Self {
let directory_client_config = directory_client::Config::new(cfg.directory_server);
let directory_client = directory_client::Client::new(directory_client_config);
TopologyRefresher {
directory_server: cfg.directory_server,
directory_client,
topology_accessor,
refresh_rate: cfg.refresh_rate,
}
}
async fn get_current_compatible_topology(&self) -> T {
// note: this call makes it necessary that `T::new()`does *not* have 'static lifetime
let full_topology = T::new(self.directory_server.clone()).await;
// just filter by version and assume the validators will remove all bad behaving
// nodes with the staking
full_topology.filter_system_version(built_info::PKG_VERSION)
async fn get_current_compatible_topology(&self) -> Option<directory_client::Topology> {
match self.directory_client.get_topology().await {
Err(err) => {
error!("failed to get network topology! - {:?}", err);
None
}
Ok(topology) => Some(topology.filter_system_version(built_info::PKG_VERSION)),
}
}
pub(crate) async fn refresh(&mut self) {
trace!("Refreshing the topology");
let new_topology = Some(self.get_current_compatible_topology().await);
let new_topology = self.get_current_compatible_topology().await;
self.topology_accessor
.update_global_topology(new_topology)
+5 -3
View File
@@ -18,7 +18,7 @@ use crate::config::persistence::pathfinder::ClientPathfinder;
use clap::{App, Arg, ArgMatches};
use config::NymConfig;
use crypto::identity::MixIdentityKeyPair;
use directory_client::presence::Topology;
use directory_client::DirectoryClient;
use gateway_client::GatewayClient;
use gateway_requests::AuthToken;
use nymsphinx::DestinationAddressBytes;
@@ -90,8 +90,10 @@ async fn choose_gateway(
directory_server: String,
our_address: DestinationAddressBytes,
) -> (String, AuthToken) {
// TODO: once we change to graph topology this here will need to be updated!
let topology = Topology::new(directory_server.clone()).await;
let directory_client_config = directory_client::Config::new(directory_server.clone());
let directory_client = directory_client::Client::new(directory_client_config);
let topology = directory_client.get_topology().await.unwrap();
let version_filtered_topology = topology.filter_system_version(built_info::PKG_VERSION);
// don't care about health of the networks as mixes can go up and down any time,
// but DO care about gateways
+1
View File
@@ -26,6 +26,7 @@ rand = "0.7.2"
crypto = { path = "../../common/crypto" }
nymsphinx = { path = "../../common/nymsphinx" }
topology = { path = "../../common/topology" }
directory-client-models = { path = "../../common/client-libs/directory-client/models" }
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
+22 -6
View File
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crypto::identity::MixIdentityPublicKey;
use models::Topology;
use models::topology::Topology;
use nymsphinx::addressing::nodes::NymNodeRoutingAddress;
use nymsphinx::Node as SphinxNode;
use nymsphinx::{delays, Destination, NodeAddressBytes, SphinxPacket};
@@ -28,6 +28,7 @@ mod utils;
pub use models::keys::keygen;
use nymsphinx::addressing::clients::Recipient;
use topology::NymTopology;
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
@@ -198,8 +199,8 @@ mod building_a_topology_from_json {
#[test]
#[should_panic]
fn panics_when_there_are_no_mixnodes() {
let mut topology: Topology = serde_json::from_str(topology_fixture()).unwrap();
topology.mix_nodes = vec![];
let mut topology = Topology::new(topology_fixture());
topology.set_mixnodes(vec![]);
let json = serde_json::to_string(&topology).unwrap();
sphinx_route_to(
&json,
@@ -213,9 +214,9 @@ mod building_a_topology_from_json {
#[test]
#[should_panic]
fn panics_when_there_are_not_enough_mixnodes() {
let mut topology: Topology = serde_json::from_str(topology_fixture()).unwrap();
let node = topology.mix_nodes.first().unwrap().clone();
topology.mix_nodes = vec![node]; // 1 mixnode isn't enough. Panic!
let mut topology = Topology::new(topology_fixture());
let node = topology.get_current_raw_mixnodes().first().unwrap().clone();
topology.set_mixnodes(vec![node]); // 1 mixnode isn't enough. Panic!
let json = serde_json::to_string(&topology).unwrap();
sphinx_route_to(
&json,
@@ -226,6 +227,7 @@ mod building_a_topology_from_json {
);
}
// JS: why is this an "offline-test" feature? It makes no network requests?
#[test]
#[cfg_attr(feature = "offline-test", ignore)]
fn test_works_on_happy_json() {
@@ -238,6 +240,20 @@ mod building_a_topology_from_json {
);
assert_eq!(4, route.len());
}
#[test]
fn test_works_on_happy_json_when_serialized() {
let topology = Topology::new(topology_fixture());
let json = serde_json::to_string(&topology).unwrap();
let route = sphinx_route_to(
&json,
&NodeAddressBytes::try_from_base58_string(
"7vhgER4Gz789QHNTSu4apMpTcpTuUaRiLxJnbz1g2HFh",
)
.unwrap(),
);
assert_eq!(4, route.len());
}
}
#[cfg(test)]
+14
View File
@@ -1,3 +1,17 @@
// Copyright 2020 Nym Technologies SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crypto::identity::MixIdentityKeyPair;
use serde::{Deserialize, Serialize};
use std::convert::{TryFrom, TryInto};
+1 -172
View File
@@ -12,176 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use nymsphinx::Node as SphinxNode;
use nymsphinx::NodeAddressBytes;
use rand::seq::IteratorRandom;
use serde::{Deserialize, Serialize};
use std::cmp::max;
use std::collections::HashMap;
use std::convert::TryInto;
use topology::{gateway, mix, provider};
pub mod coconodes;
pub mod gateways;
pub mod keys;
pub mod mixnodes;
pub mod providers;
// JS: can we just get rid of this? It's mostly just copied (and un-updated) code from NymTopology trait
// Topology shows us the current state of the overall Nym network
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Topology {
pub coco_nodes: Vec<coconodes::CocoPresence>,
pub mix_nodes: Vec<mixnodes::MixNodePresence>,
pub mix_provider_nodes: Vec<providers::MixProviderPresence>,
pub gateway_nodes: Vec<gateways::GatewayPresence>,
}
impl Topology {
pub fn new(json: &str) -> Self {
if json.is_empty() {
panic!("empty json passed");
}
serde_json::from_str(json).unwrap()
}
fn make_layered_topology(&self) -> Result<HashMap<u64, Vec<mix::Node>>, NymTopologyError> {
let mut layered_topology: HashMap<u64, Vec<mix::Node>> = HashMap::new();
let mut highest_layer = 0;
for mix in self.mix_nodes() {
// we need to have extra space for provider
if mix.layer > nymsphinx::MAX_PATH_LENGTH as u64 {
return Err(NymTopologyError::InvalidMixLayerError);
}
highest_layer = max(highest_layer, mix.layer);
let layer_nodes = layered_topology.entry(mix.layer).or_insert_with(Vec::new);
layer_nodes.push(mix);
}
// verify the topology - make sure there are no gaps and there is at least one node per layer
let mut missing_layers = Vec::new();
for layer in 1..=highest_layer {
if !layered_topology.contains_key(&layer) {
missing_layers.push(layer);
}
if layered_topology[&layer].is_empty() {
missing_layers.push(layer);
}
}
if !missing_layers.is_empty() {
return Err(NymTopologyError::MissingLayerError(missing_layers));
}
Ok(layered_topology)
}
// Tries to get a route through the mix network
fn random_mix_route(&self) -> Result<Vec<SphinxNode>, NymTopologyError> {
let mut layered_topology = self.make_layered_topology()?;
let num_layers = layered_topology.len();
let route = (1..=num_layers as u64)
// unwrap is safe for 'remove' as it it failed, it implied the entry never existed
// in the map in the first place which would contradict what we've just done
.map(|layer| layered_topology.remove(&layer).unwrap()) // for each layer
.map(|nodes| nodes.into_iter().choose(&mut rand::thread_rng()).unwrap()) // choose random node
.map(|random_node| random_node.into()) // and convert it into sphinx specific node format
.collect();
Ok(route)
}
// Sets up a route to a specific gateway
pub fn random_route_to_gateway(
&self,
gateway_address: &NodeAddressBytes,
) -> Result<Vec<SphinxNode>, NymTopologyError> {
let b58_address = gateway_address.to_base58_string();
let gateway_node = self
.gateways()
.iter()
.cloned()
.find(|gateway| gateway.pub_key == b58_address.clone())
.ok_or_else(|| NymTopologyError::InvalidMixLayerError)?;
Ok(self
.random_mix_route()?
.into_iter()
.chain(std::iter::once(gateway_node.into()))
.collect())
}
pub fn mix_nodes(&self) -> Vec<mix::Node> {
self.mix_nodes
.iter()
.filter_map(|x| x.clone().try_into().ok())
.collect()
}
// it's intesting how compiler knows this function is unused even though it's public
// but it will be removed once our topology is refactored and the concept of "provider"
// goes away.
#[allow(dead_code)]
pub fn providers(&self) -> Vec<provider::Node> {
self.mix_provider_nodes
.iter()
.map(|x| x.clone().into())
.collect()
}
pub fn gateways(&self) -> Vec<gateway::Node> {
self.gateway_nodes
.iter()
.map(|x| x.clone().into())
.collect()
}
}
#[derive(Debug)]
pub enum NymTopologyError {
InvalidMixLayerError,
MissingLayerError(Vec<u64>),
}
#[cfg(test)]
mod converting_mixnode_presence_into_topology_mixnode {
use super::*;
#[test]
fn it_returns_error_on_unresolvable_hostname() {
let unresolvable_hostname = "foomp.foomp.foomp:1234";
let mix_presence = mixnodes::MixNodePresence {
location: "".to_string(),
host: unresolvable_hostname.to_string(),
pub_key: "".to_string(),
layer: 0,
last_seen: 0,
version: "".to_string(),
};
let _result: Result<mix::Node, std::io::Error> = mix_presence.try_into();
// assert!(result.is_err()) // This fails only for me. Why?
// ¯\_(ツ)_/¯ - works on my machine (and travis)
}
#[test]
#[cfg_attr(feature = "offline-test", ignore)]
fn it_returns_resolved_ip_on_resolvable_hostname() {
let resolvable_hostname = "nymtech.net:1234";
let mix_presence = mixnodes::MixNodePresence {
location: "".to_string(),
host: resolvable_hostname.to_string(),
pub_key: "".to_string(),
layer: 0,
last_seen: 0,
version: "".to_string(),
};
let result: Result<topology::mix::Node, std::io::Error> = mix_presence.try_into();
assert!(result.is_ok())
}
}
pub mod topology;
@@ -0,0 +1,90 @@
// Copyright 2020 Nym Technologies SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use serde::Serializer;
use topology::{coco, gateway, mix, provider, NymTopology};
#[derive(Clone, Debug)]
pub struct Topology {
inner: directory_client_models::presence::Topology,
}
impl serde::Serialize for Topology {
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where
S: Serializer,
{
self.inner.serialize(serializer)
}
}
impl Topology {
pub fn new(json: &str) -> Self {
if json.is_empty() {
panic!("empty json passed");
}
Topology {
inner: serde_json::from_str(json).unwrap(),
}
}
#[cfg(test)]
pub(crate) fn set_mixnodes(
&mut self,
mix_nodes: Vec<directory_client_models::presence::mixnodes::MixNodePresence>,
) {
self.inner.mix_nodes = mix_nodes
}
#[cfg(test)]
pub(crate) fn get_current_raw_mixnodes(
&self,
) -> Vec<directory_client_models::presence::mixnodes::MixNodePresence> {
self.inner.mix_nodes.clone()
}
}
impl NymTopology for Topology {
fn new_from_nodes(
mix_nodes: Vec<mix::Node>,
mix_provider_nodes: Vec<provider::Node>,
coco_nodes: Vec<coco::Node>,
gateway_nodes: Vec<gateway::Node>,
) -> Self {
Topology {
inner: directory_client_models::presence::Topology::new_from_nodes(
mix_nodes,
mix_provider_nodes,
coco_nodes,
gateway_nodes,
),
}
}
fn mix_nodes(&self) -> Vec<mix::Node> {
self.inner.mix_nodes()
}
fn providers(&self) -> Vec<provider::Node> {
self.inner.providers()
}
fn gateways(&self) -> Vec<gateway::Node> {
self.inner.gateways()
}
fn coco_nodes(&self) -> Vec<topology::coco::Node> {
self.inner.coco_nodes()
}
}
@@ -13,11 +13,11 @@ offline-test = []
log = "0.4"
futures = "0.3"
pretty_env_logger = "0.3"
reqwest = { version = "0.10", features = ["json"] }
serde = { version = "1.0.104", features = ["derive"] }
reqwest = { version = "0.10", features = ["json"] }
## internal
topology = {path = "../../topology"}
directory-client-models = { path = "models" }
[dev-dependencies]
mockito = "0.23.0"
@@ -0,0 +1,12 @@
[package]
name = "directory-client-models"
version = "0.1.0"
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { version = "1.0.104", features = ["derive"] }
topology = { path = "../../../topology" }
@@ -0,0 +1,16 @@
// Copyright 2020 Nym Technologies SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub mod metrics;
pub mod presence;
@@ -13,12 +13,10 @@
// limitations under the License.
use super::{coconodes, gateways, mixnodes, providers};
use crate::{Client, Config, DirectoryClient};
use futures::future::BoxFuture;
use log::*;
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
use topology::{coco, gateway, mix, provider, NymTopology};
// Topology shows us the current state of the overall Nym network
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
@@ -30,24 +28,6 @@ pub struct Topology {
}
impl NymTopology for Topology {
// TODO: this will need some changes to not imply having to make an HTTP request in constructor
// TODO2: and also be reworked/removed with the topology re-work
fn new<'a>(directory_server: String) -> BoxFuture<'a, Self> {
debug!("Using directory server: {:?}", directory_server);
let directory_config = Config {
base_url: directory_server,
};
let directory = Client::new(directory_config);
Box::pin({
async move {
directory
.get_topology()
.await
.expect("Failed to retrieve network topology.")
}
})
}
fn new_from_nodes(
mix_nodes: Vec<mix::Node>,
mix_provider_nodes: Vec<provider::Node>,
@@ -20,16 +20,18 @@ use crate::requests::presence_gateways_post::Request as PresenceGatewayPost;
use crate::requests::presence_mixnodes_post::Request as PresenceMixNodesPost;
use crate::requests::presence_providers_post::Request as PresenceProvidersPost;
use crate::requests::presence_topology_get::Request as PresenceTopologyRequest;
use metrics::{MixMetric, PersistedMixMetric};
use presence::{
use directory_client_models::metrics::{MixMetric, PersistedMixMetric};
use directory_client_models::presence::{
coconodes::CocoPresence, gateways::GatewayPresence, mixnodes::MixNodePresence,
providers::MixProviderPresence, Topology,
providers::MixProviderPresence,
};
use requests::{health_check_get::HealthCheckResponse, DirectoryGetRequest, DirectoryPostRequest};
pub mod metrics;
pub mod presence;
pub use directory_client_models::{
metrics,
presence::{self, Topology},
};
pub mod requests;
pub struct Config {
@@ -1,50 +0,0 @@
// Copyright 2020 Nym Technologies SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use serde::{Deserialize, Serialize};
use topology::coco;
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CocoPresence {
pub location: String,
pub host: String,
pub pub_key: String,
pub last_seen: u64,
pub version: String,
}
impl Into<topology::coco::Node> for CocoPresence {
fn into(self) -> topology::coco::Node {
topology::coco::Node {
location: self.location,
host: self.host,
pub_key: self.pub_key,
last_seen: self.last_seen,
version: self.version,
}
}
}
impl From<topology::coco::Node> for CocoPresence {
fn from(cn: coco::Node) -> Self {
CocoPresence {
location: cn.location,
host: cn.host,
pub_key: cn.pub_key,
last_seen: cn.last_seen,
version: cn.version,
}
}
}
@@ -1,86 +0,0 @@
// Copyright 2020 Nym Technologies SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use serde::{Deserialize, Serialize};
use topology::gateway;
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GatewayPresence {
pub location: String,
pub client_listener: String,
pub mixnet_listener: String,
pub pub_key: String,
pub registered_clients: Vec<GatewayClient>,
pub last_seen: u64,
pub version: String,
}
impl Into<topology::gateway::Node> for GatewayPresence {
fn into(self) -> topology::gateway::Node {
topology::gateway::Node {
location: self.location,
client_listener: self.client_listener.parse().unwrap(),
mixnet_listener: self.mixnet_listener.parse().unwrap(),
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,
}
}
}
impl From<topology::gateway::Node> for GatewayPresence {
fn from(mpn: gateway::Node) -> Self {
GatewayPresence {
location: mpn.location,
client_listener: mpn.client_listener.to_string(),
mixnet_listener: mpn.mixnet_listener.to_string(),
pub_key: mpn.pub_key,
registered_clients: mpn
.registered_clients
.into_iter()
.map(|c| c.into())
.collect(),
last_seen: mpn.last_seen,
version: mpn.version,
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GatewayClient {
pub pub_key: String,
}
impl Into<topology::gateway::Client> for GatewayClient {
fn into(self) -> topology::gateway::Client {
topology::gateway::Client {
pub_key: self.pub_key,
}
}
}
impl From<topology::gateway::Client> for GatewayClient {
fn from(mpc: topology::gateway::Client) -> Self {
GatewayClient {
pub_key: mpc.pub_key,
}
}
}
@@ -1,66 +0,0 @@
// Copyright 2020 Nym Technologies SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
use std::io;
use std::net::ToSocketAddrs;
use topology::mix;
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MixNodePresence {
pub location: String,
pub host: String,
pub pub_key: String,
pub layer: u64,
pub last_seen: u64,
pub version: String,
}
impl TryInto<topology::mix::Node> for MixNodePresence {
type Error = io::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(
io::ErrorKind::Other,
"no valid socket address",
));
}
Ok(topology::mix::Node {
location: self.location,
host: resolved_hostname.unwrap(),
pub_key: self.pub_key,
layer: self.layer,
last_seen: self.last_seen,
version: self.version,
})
}
}
impl From<topology::mix::Node> for MixNodePresence {
fn from(mn: mix::Node) -> Self {
MixNodePresence {
location: mn.location,
host: mn.host.to_string(),
pub_key: mn.pub_key,
layer: mn.layer,
last_seen: mn.last_seen,
version: mn.version,
}
}
}
@@ -1,86 +0,0 @@
// Copyright 2020 Nym Technologies SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use serde::{Deserialize, Serialize};
use topology::provider;
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MixProviderPresence {
pub location: String,
pub client_listener: String,
pub mixnet_listener: String,
pub pub_key: String,
pub registered_clients: Vec<MixProviderClient>,
pub last_seen: u64,
pub version: String,
}
impl Into<topology::provider::Node> for MixProviderPresence {
fn into(self) -> topology::provider::Node {
topology::provider::Node {
location: self.location,
client_listener: self.client_listener.parse().unwrap(),
mixnet_listener: self.mixnet_listener.parse().unwrap(),
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,
}
}
}
impl From<topology::provider::Node> for MixProviderPresence {
fn from(mpn: provider::Node) -> Self {
MixProviderPresence {
location: mpn.location,
client_listener: mpn.client_listener.to_string(),
mixnet_listener: mpn.mixnet_listener.to_string(),
pub_key: mpn.pub_key,
registered_clients: mpn
.registered_clients
.into_iter()
.map(|c| c.into())
.collect(),
last_seen: mpn.last_seen,
version: mpn.version,
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MixProviderClient {
pub pub_key: String,
}
impl Into<topology::provider::Client> for MixProviderClient {
fn into(self) -> topology::provider::Client {
topology::provider::Client {
pub_key: self.pub_key,
}
}
}
impl From<topology::provider::Client> for MixProviderClient {
fn from(mpc: topology::provider::Client) -> Self {
MixProviderClient {
pub_key: mpc.pub_key,
}
}
}
-1
View File
@@ -9,7 +9,6 @@ edition = "2018"
[dependencies]
bs58 = "0.3.0"
itertools = "0.8.2"
futures = "0.3"
log = "0.4"
pretty_env_logger = "0.3"
rand = "0.7.2"
-5
View File
@@ -13,7 +13,6 @@
// limitations under the License.
use crate::filter::VersionFilterable;
use futures::future::BoxFuture;
use itertools::Itertools;
use nymsphinx_types::{Node as SphinxNode, NodeAddressBytes};
use rand::seq::IteratorRandom;
@@ -29,10 +28,6 @@ pub mod provider;
// TODO: Figure out why 'Clone' was required to have 'TopologyAccessor<T>' working
// even though it only contains an Arc
pub trait NymTopology: Sized + std::fmt::Debug + Send + Sync + Clone {
// this is just a temporary work-around to make current code work without having to
// do major topology rewrites now.
// This will be removed once topology is re-worked
fn new<'a>(directory_server: String) -> BoxFuture<'a, Self>;
fn new_from_nodes(
mix_nodes: Vec<mix::Node>,
mix_provider_nodes: Vec<provider::Node>,
+6 -4
View File
@@ -15,13 +15,12 @@
use crate::config::Config;
use crate::node::packet_processing::PacketProcessor;
use crypto::encryption;
use directory_client::presence::Topology;
use directory_client::DirectoryClient;
use futures::channel::mpsc;
use log::*;
use nymsphinx::SphinxPacket;
use std::net::SocketAddr;
use tokio::runtime::Runtime;
use topology::NymTopology;
mod listener;
mod metrics;
@@ -102,10 +101,13 @@ impl MixNode {
}
fn check_if_same_ip_node_exists(&mut self) -> Option<String> {
// TODO: once we change to graph topology this here will need to be updated!
let directory_client_config =
directory_client::Config::new(self.config.get_presence_directory_server());
let directory_client = directory_client::Client::new(directory_client_config);
let topology = self
.runtime
.block_on(Topology::new(self.config.get_presence_directory_server()));
.block_on(directory_client.get_topology())
.ok()?;
let existing_mixes_presence = topology.mix_nodes;
existing_mixes_presence
.iter()