diff --git a/client/directory_client/src/presence.rs b/client/directory_client/src/presence.rs index 5aa9cfe8de..112c9db3e9 100644 --- a/client/directory_client/src/presence.rs +++ b/client/directory_client/src/presence.rs @@ -34,7 +34,7 @@ pub struct MixNodePresence { impl Into for MixNodePresence { fn into(self) -> topology::MixNode { topology::MixNode { - host: self.host, + host: self.host.parse().unwrap(), pub_key: self.pub_key, layer: self.layer, last_seen: self.last_seen, @@ -46,7 +46,8 @@ impl Into for MixNodePresence { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct MixProviderPresence { - pub host: String, + pub client_listener: String, + pub mixnet_listener: String, pub pub_key: String, pub registered_clients: Vec, pub last_seen: u64, @@ -56,9 +57,14 @@ pub struct MixProviderPresence { impl Into for MixProviderPresence { fn into(self) -> topology::MixProviderNode { topology::MixProviderNode { - host: self.host, + 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(), + registered_clients: self + .registered_clients + .into_iter() + .map(|c| c.into()) + .collect(), last_seen: self.last_seen, version: self.version, } @@ -108,7 +114,10 @@ impl NymTopology for Topology { } fn get_mix_provider_nodes(&self) -> Vec { - self.mix_provider_nodes.iter().map(|x| x.clone().into()).collect() + self.mix_provider_nodes + .iter() + .map(|x| x.clone().into()) + .collect() } fn get_coco_nodes(&self) -> Vec { diff --git a/client/provider_client/src/lib.rs b/client/provider_client/src/lib.rs index e95c318e22..cb273b414c 100644 --- a/client/provider_client/src/lib.rs +++ b/client/provider_client/src/lib.rs @@ -51,13 +51,8 @@ impl ProviderClient { our_address: DestinationAddressBytes, auth_token: Option, ) -> Self { - // DH temporary: the provider's client port is not in the topology, but we can't change that - // right now without messing up the existing Go mixnet. So I'm going to hardcode this - // for the moment until the Go mixnet goes away. - let provider_socket = SocketAddr::new(provider_network_address.ip(), 9000); - ProviderClient { - provider_network_address: provider_socket, + provider_network_address, our_address, auth_token, } diff --git a/client/src/clients/mod.rs b/client/src/clients/mod.rs index f466e6875c..a8f0789c5b 100644 --- a/client/src/clients/mod.rs +++ b/client/src/clients/mod.rs @@ -225,16 +225,17 @@ impl NymClient { let topology = Topology::new(self.directory.clone()); // this is temporary and assumes there exists only a single provider. - let provider_address: SocketAddr = topology + let provider_client_listener_address: SocketAddr = topology .get_mix_provider_nodes() .first() .unwrap() - .host - .parse() - .unwrap(); + .client_listener; - let mut provider_client = - provider_client::ProviderClient::new(provider_address, self.address, self.auth_token); + let mut provider_client = provider_client::ProviderClient::new( + provider_client_listener_address, + self.address, + self.auth_token, + ); // registration rt.block_on(async { diff --git a/client/src/utils/sphinx.rs b/client/src/utils/sphinx.rs index 98df4b9976..e329e81ba5 100644 --- a/client/src/utils/sphinx.rs +++ b/client/src/utils/sphinx.rs @@ -1,7 +1,6 @@ use crate::utils::bytes; use addressing; use curve25519_dalek::montgomery::MontgomeryPoint; -use directory_client::presence::Topology; use sphinx::route::{Destination, DestinationAddressBytes, Node, SURBIdentifier}; use sphinx::SphinxPacket; use std::net::SocketAddr; @@ -9,36 +8,39 @@ use topology::NymTopology; pub const LOOP_COVER_MESSAGE_PAYLOAD: &[u8] = b"The cake is a lie!"; -pub fn loop_cover_message( +pub fn loop_cover_message( our_address: DestinationAddressBytes, surb_id: SURBIdentifier, - topology: &Topology, + topology: &T, ) -> (SocketAddr, SphinxPacket) { let destination = Destination::new(our_address, surb_id); encapsulate_message(destination, LOOP_COVER_MESSAGE_PAYLOAD.to_vec(), topology) } -pub fn encapsulate_message( +pub fn encapsulate_message( recipient: Destination, message: Vec, - topology: &Topology, + topology: &T, ) -> (SocketAddr, SphinxPacket) { let mixes_route = topology.route_from(); - let first_provider = topology.mix_provider_nodes.first().unwrap(); + let providers = topology.get_mix_provider_nodes(); + let first_provider = providers.first().unwrap(); let decoded_key_bytes = base64::decode_config(&first_provider.pub_key, base64::URL_SAFE).unwrap(); let key_bytes = bytes::zero_pad_to_32(decoded_key_bytes); let key = MontgomeryPoint(key_bytes); let provider = Node::new( - addressing::encoded_bytes_from_socket_address(first_provider.host.clone().parse().unwrap()), + addressing::encoded_bytes_from_socket_address(first_provider.mixnet_listener.clone()), key, ); let route = [mixes_route, vec![provider]].concat(); - let delays = sphinx::header::delays::generate(route.len()); + // Set average packet dealy to an arbitrary but at least not super-slow value for testing. + let average_delay = 0.1; + let delays = sphinx::header::delays::generate(route.len(), average_delay); // build the packet let packet = sphinx::SphinxPacket::new(message, &route[..], &recipient, &delays).unwrap(); diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index 5f6f15516c..4d87a001ea 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -3,10 +3,11 @@ use curve25519_dalek::montgomery::MontgomeryPoint; use rand::seq::SliceRandom; use sphinx::route::Node as SphinxNode; use std::collections::HashMap; +use std::net::SocketAddr; #[derive(Debug)] pub struct MixNode { - pub host: String, + pub host: SocketAddr, pub pub_key: String, pub layer: u64, pub last_seen: u64, @@ -20,7 +21,8 @@ pub struct MixProviderClient { #[derive(Debug)] pub struct MixProviderNode { - pub host: String, + pub client_listener: SocketAddr, + pub mixnet_listener: SocketAddr, pub pub_key: String, pub registered_clients: Vec, pub last_seen: u64, @@ -57,9 +59,7 @@ pub trait NymTopology { route .iter() .map(|mix| { - let address_bytes = addressing::encoded_bytes_from_socket_address( - mix.host.clone().parse().unwrap(), - ); + let address_bytes = addressing::encoded_bytes_from_socket_address(mix.host.clone()); let decoded_key_bytes = base64::decode_config(&mix.pub_key, base64::URL_SAFE).unwrap(); let mut key_bytes = [0; 32]; diff --git a/scripts/run_local_network.sh b/scripts/run_local_network.sh new file mode 100755 index 0000000000..0bc1b91fc1 --- /dev/null +++ b/scripts/run_local_network.sh @@ -0,0 +1,56 @@ +#// Copyright 2020 The Nym Mixnet Authors +#// +#// 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. + +#!/bin/bash + +echo "Killing old testnet processes..." + +killall nym-mixnode +killall nym-sfw-provider + +echo "Press CTRL-C to stop." + +cargo build + +MAX_LAYERS=3 +NUMMIXES=${1:-3} # Set $NUMMIXES to default of 3, but allow the user to set other values if desired + +for (( j=0; j<$NUMMIXES; j++ )) + +# Note: to disable logging (or direct it to another output) modify the constant on top of mixnode or provider; +# Will make it later either configurable by flags or config file. +do + let layer=j%MAX_LAYERS+1 + $PWD/target/debug/nym-mixnode run --port $((9980+$j)) --host "localhost" --layer $layer --directory http://localhost:8080 & + sleep 1 +done + +sleep 1 +$PWD/target/debug/nym-sfw-provider run --clientHost "localhost" --mixHost "localhost" --mixPort 9997 --clientPort 9998 --directory http://localhost:8080 + +# trap call ctrl_c() +trap ctrl_c SIGINT SIGTERM SIGTSTP +function ctrl_c() { + echo "** Trapped SIGINT, SIGTERM and SIGTSTP" + for (( j=0; j<$NUMMIXES; j++ )); + do + kill_port $((9980+$j)) + done +} + +function kill_port() { + PID=$(lsof -t -i:$1) + echo "$PID" + kill -TERM $PID || kill -KILL $PID +} diff --git a/sfw-provider/src/provider/mod.rs b/sfw-provider/src/provider/mod.rs index 4ab12fddb3..23b460e753 100644 --- a/sfw-provider/src/provider/mod.rs +++ b/sfw-provider/src/provider/mod.rs @@ -290,6 +290,7 @@ impl ServiceProvider { let presence_notifier = presence::Notifier::new( self.directory_server, + self.client_network_address.clone(), self.mix_network_address.clone(), self.public_key, thread_shareable_ledger.clone(), diff --git a/sfw-provider/src/provider/presence.rs b/sfw-provider/src/provider/presence.rs index 982c1d15cf..96fda76ba7 100644 --- a/sfw-provider/src/provider/presence.rs +++ b/sfw-provider/src/provider/presence.rs @@ -11,14 +11,16 @@ use std::time::Duration; pub struct Notifier { pub net_client: directory_client::Client, client_ledger: Arc>, - host: String, + client_listener: String, + mixnet_listener: String, pub_key: String, } impl Notifier { pub fn new( directory_server_address: String, - host: SocketAddr, + client_listener: SocketAddr, + mixnet_listener: SocketAddr, pub_key: MontgomeryPoint, client_ledger: Arc>, ) -> Notifier { @@ -29,7 +31,8 @@ impl Notifier { Notifier { net_client, - host: host.to_string(), + client_listener: client_listener.to_string(), + mixnet_listener: mixnet_listener.to_string(), pub_key: Config::public_key_string(pub_key), client_ledger, } @@ -39,7 +42,8 @@ impl Notifier { let unlocked_ledger = self.client_ledger.lock().await; MixProviderPresence { - host: self.host.clone(), + client_listener: self.client_listener.clone(), + mixnet_listener: self.mixnet_listener.clone(), pub_key: self.pub_key.clone(), registered_clients: unlocked_ledger.current_clients(), last_seen: 0,