Merge pull request #105 from nymtech/feature/health_checker_with_existing_keys
Feature/health checker with existing keys
This commit is contained in:
Generated
+4
@@ -472,6 +472,7 @@ dependencies = [
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
"rand_os",
|
||||
"sphinx",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -859,6 +860,8 @@ dependencies = [
|
||||
"mix-client",
|
||||
"pretty_env_logger",
|
||||
"provider-client",
|
||||
"rand 0.7.3",
|
||||
"rand_os",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"sfw-provider-requests",
|
||||
@@ -1418,6 +1421,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"built",
|
||||
"clap",
|
||||
"crypto",
|
||||
"dotenv",
|
||||
"futures 0.3.1",
|
||||
"healthcheck",
|
||||
|
||||
@@ -75,7 +75,7 @@ impl ProviderClient {
|
||||
let mut response = Vec::new();
|
||||
socket.read_to_end(&mut response).await?;
|
||||
if let Err(e) = socket.shutdown(Shutdown::Read) {
|
||||
warn!("failed to close read part of the socket; err = {:?}", e)
|
||||
debug!("failed to close read part of the socket; err = {:?}. It was probably already closed by the provider", e)
|
||||
}
|
||||
|
||||
Ok(response)
|
||||
|
||||
@@ -13,3 +13,6 @@ log = "0.4"
|
||||
pretty_env_logger = "0.3"
|
||||
rand = "0.7.2"
|
||||
rand_os = "0.1"
|
||||
|
||||
## will be moved to proper dependencies once released
|
||||
sphinx = { git = "https://github.com/nymtech/sphinx", rev="8424f4b0933b4a7f64ae828b2edefc5ba43a9e79" }
|
||||
@@ -4,8 +4,9 @@ use crate::encryption::{
|
||||
use crate::{encryption, PemStorable};
|
||||
use bs58;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
use sphinx::route::DestinationAddressBytes;
|
||||
|
||||
pub trait MixnetIdentityKeyPair<Priv, Pub>
|
||||
pub trait MixnetIdentityKeyPair<Priv, Pub>: Clone
|
||||
where
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
@@ -19,16 +20,20 @@ where
|
||||
}
|
||||
|
||||
pub trait MixnetIdentityPublicKey:
|
||||
Sized + PemStorable + for<'a> From<&'a <Self as MixnetIdentityPublicKey>::PrivateKeyMaterial>
|
||||
Sized
|
||||
+ PemStorable
|
||||
+ Clone
|
||||
+ for<'a> From<&'a <Self as MixnetIdentityPublicKey>::PrivateKeyMaterial>
|
||||
{
|
||||
// we need to couple public and private keys together
|
||||
type PrivateKeyMaterial: MixnetIdentityPrivateKey<PublicKeyMaterial = Self>;
|
||||
|
||||
fn derive_address(&self) -> DestinationAddressBytes;
|
||||
fn to_bytes(&self) -> Vec<u8>;
|
||||
fn from_bytes(b: &[u8]) -> Self;
|
||||
}
|
||||
|
||||
pub trait MixnetIdentityPrivateKey: Sized + PemStorable {
|
||||
pub trait MixnetIdentityPrivateKey: Sized + PemStorable + Clone {
|
||||
// we need to couple public and private keys together
|
||||
type PublicKeyMaterial: MixnetIdentityPublicKey<PrivateKeyMaterial = Self>;
|
||||
|
||||
@@ -45,7 +50,7 @@ pub trait MixnetIdentityPrivateKey: Sized + PemStorable {
|
||||
|
||||
// for time being define a dummy identity using x25519 encryption keys (as we've done so far)
|
||||
// and replace it with proper keys, like ed25519 later on
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DummyMixIdentityKeyPair {
|
||||
pub private_key: DummyMixIdentityPrivateKey,
|
||||
pub public_key: DummyMixIdentityPublicKey,
|
||||
@@ -84,6 +89,14 @@ pub struct DummyMixIdentityPublicKey(encryption::x25519::PublicKey);
|
||||
impl MixnetIdentityPublicKey for DummyMixIdentityPublicKey {
|
||||
type PrivateKeyMaterial = DummyMixIdentityPrivateKey;
|
||||
|
||||
fn derive_address(&self) -> DestinationAddressBytes {
|
||||
let mut temporary_address = [0u8; 32];
|
||||
let public_key_bytes = self.to_bytes();
|
||||
temporary_address.copy_from_slice(&public_key_bytes[..]);
|
||||
|
||||
temporary_address
|
||||
}
|
||||
|
||||
fn to_bytes(&self) -> Vec<u8> {
|
||||
self.0.to_bytes()
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ futures = "0.3.1"
|
||||
itertools = "0.8.2"
|
||||
log = "0.4.8"
|
||||
pretty_env_logger = "0.3"
|
||||
rand_os = "0.1"
|
||||
rand = "0.7.2"
|
||||
serde = "1.0.104"
|
||||
serde_derive = "1.0.104"
|
||||
tokio = { version = "0.2", features = ["full"] }
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use crate::result::HealthCheckResult;
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPrivateKey, MixnetIdentityPublicKey};
|
||||
use directory_client::requests::presence_topology_get::PresenceTopologyGetRequester;
|
||||
use directory_client::DirectoryClient;
|
||||
use log::{debug, error, info, trace};
|
||||
use std::fmt::{Error, Formatter};
|
||||
use std::marker::PhantomData;
|
||||
use std::time::Duration;
|
||||
use topology::NymTopologyError;
|
||||
|
||||
@@ -34,15 +36,29 @@ impl From<topology::NymTopologyError> for HealthCheckerError {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HealthChecker {
|
||||
pub struct HealthChecker<IDPair, Priv, Pub>
|
||||
where
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
{
|
||||
directory_client: directory_client::Client,
|
||||
interval: Duration,
|
||||
num_test_packets: usize,
|
||||
resolution_timeout: Duration,
|
||||
identity_keypair: IDPair,
|
||||
|
||||
_phantom_private: PhantomData<Priv>,
|
||||
_phantom_public: PhantomData<Pub>,
|
||||
}
|
||||
|
||||
impl HealthChecker {
|
||||
pub fn new(config: config::HealthCheck) -> Self {
|
||||
impl<IDPair, Priv, Pub> HealthChecker<IDPair, Priv, Pub>
|
||||
where
|
||||
IDPair: crypto::identity::MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: crypto::identity::MixnetIdentityPrivateKey,
|
||||
Pub: crypto::identity::MixnetIdentityPublicKey,
|
||||
{
|
||||
pub fn new(config: config::HealthCheck, identity_keypair: IDPair) -> Self {
|
||||
debug!(
|
||||
"healthcheck will be using the following directory server: {:?}",
|
||||
config.directory_server
|
||||
@@ -53,11 +69,16 @@ impl HealthChecker {
|
||||
interval: Duration::from_secs_f64(config.interval),
|
||||
resolution_timeout: Duration::from_secs_f64(config.resolution_timeout),
|
||||
num_test_packets: config.num_test_packets,
|
||||
identity_keypair,
|
||||
|
||||
_phantom_private: PhantomData,
|
||||
_phantom_public: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn do_check(&self) -> Result<HealthCheckResult, HealthCheckerError> {
|
||||
trace!("going to perform a healthcheck!");
|
||||
|
||||
let current_topology = match self.directory_client.presence_topology.get() {
|
||||
Ok(topology) => topology,
|
||||
Err(err) => {
|
||||
@@ -71,6 +92,7 @@ impl HealthChecker {
|
||||
current_topology,
|
||||
self.num_test_packets,
|
||||
self.resolution_timeout,
|
||||
&self.identity_keypair,
|
||||
)
|
||||
.await;
|
||||
healthcheck_result.sort_scores();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crypto::identity::{DummyMixIdentityKeyPair, MixnetIdentityKeyPair, MixnetIdentityPublicKey};
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPrivateKey, MixnetIdentityPublicKey};
|
||||
use itertools::Itertools;
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use mix_client::MixClient;
|
||||
use provider_client::ProviderClient;
|
||||
use provider_client::{ProviderClient, ProviderClientError};
|
||||
use sphinx::header::delays::Delay;
|
||||
use sphinx::route::{Destination, Node as SphinxNode};
|
||||
use std::collections::HashMap;
|
||||
@@ -23,28 +23,36 @@ pub(crate) struct PathChecker {
|
||||
layer_one_clients: HashMap<[u8; 32], Option<MixClient>>,
|
||||
paths_status: HashMap<Vec<u8>, PathStatus>,
|
||||
our_destination: Destination,
|
||||
check_id: [u8; 16],
|
||||
}
|
||||
|
||||
impl PathChecker {
|
||||
pub(crate) async fn new(
|
||||
pub(crate) async fn new<IDPair, Priv, Pub>(
|
||||
providers: Vec<provider::Node>,
|
||||
ephemeral_keys: DummyMixIdentityKeyPair,
|
||||
) -> Self {
|
||||
identity_keys: &IDPair,
|
||||
check_id: [u8; 16],
|
||||
) -> Self
|
||||
where
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
{
|
||||
let mut provider_clients = HashMap::new();
|
||||
|
||||
let mut temporary_address = [0u8; 32];
|
||||
let public_key_bytes = ephemeral_keys.public_key().to_bytes();
|
||||
temporary_address.copy_from_slice(&public_key_bytes[..]);
|
||||
let address = identity_keys.public_key().derive_address();
|
||||
|
||||
for provider in providers {
|
||||
let mut provider_client =
|
||||
ProviderClient::new(provider.client_listener, temporary_address, None);
|
||||
let mut provider_client = ProviderClient::new(provider.client_listener, address, None);
|
||||
let insertion_result = match provider_client.register().await {
|
||||
Ok(token) => {
|
||||
debug!("registered at provider {}", provider.pub_key);
|
||||
provider_client.update_token(token);
|
||||
provider_clients.insert(provider.get_pub_key_bytes(), Some(provider_client))
|
||||
}
|
||||
Err(ProviderClientError::ClientAlreadyRegisteredError) => {
|
||||
info!("We were already registered");
|
||||
provider_clients.insert(provider.get_pub_key_bytes(), Some(provider_client))
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"failed to register at provider {} - {:?}",
|
||||
@@ -62,15 +70,19 @@ impl PathChecker {
|
||||
PathChecker {
|
||||
provider_clients,
|
||||
layer_one_clients: HashMap::new(),
|
||||
our_destination: Destination::new(temporary_address, Default::default()),
|
||||
our_destination: Destination::new(address, Default::default()),
|
||||
paths_status: HashMap::new(),
|
||||
check_id,
|
||||
}
|
||||
}
|
||||
|
||||
// iteration is used to distinguish packets sent through the same path (as the healthcheck
|
||||
// may try to send say 10 packets through given path)
|
||||
fn unique_path_key(path: &Vec<SphinxNode>, iteration: u8) -> Vec<u8> {
|
||||
std::iter::once(iteration)
|
||||
fn unique_path_key(path: &Vec<SphinxNode>, check_id: [u8; 16], iteration: u8) -> Vec<u8> {
|
||||
check_id
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain(std::iter::once(iteration))
|
||||
.chain(
|
||||
path.iter()
|
||||
.map(|node| node.pub_key.to_bytes().to_vec())
|
||||
@@ -80,10 +92,10 @@ impl PathChecker {
|
||||
}
|
||||
|
||||
pub(crate) fn path_key_to_node_keys(path_key: Vec<u8>) -> Vec<[u8; 32]> {
|
||||
assert_eq!(path_key.len() % 32, 1);
|
||||
assert_eq!(path_key.len() % 32, 17);
|
||||
path_key
|
||||
.into_iter()
|
||||
.skip(1) // remove first byte as it represents the iteration number which we do not care about now
|
||||
.skip(16 + 1) // remove 16 + 1 bytes as it represents check_id and the iteration number which we do not care about now
|
||||
.chunks(32)
|
||||
.into_iter()
|
||||
.map(|key_chunk| {
|
||||
@@ -135,6 +147,8 @@ impl PathChecker {
|
||||
if msg == sfw_provider_requests::DUMMY_MESSAGE_CONTENT {
|
||||
// finish iterating the loop as the messages might not be ordered
|
||||
should_stop = true;
|
||||
} else if msg[..16] != self.check_id {
|
||||
warn!("received response from previous healthcheck")
|
||||
} else {
|
||||
provider_messages.push(msg);
|
||||
}
|
||||
@@ -171,7 +185,7 @@ impl PathChecker {
|
||||
}
|
||||
|
||||
debug!("Checking path: {:?} ({})", path, iteration);
|
||||
let path_identifier = PathChecker::unique_path_key(path, iteration);
|
||||
let path_identifier = PathChecker::unique_path_key(path, self.check_id, iteration);
|
||||
|
||||
// check if there is even any point in sending the packet
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::path_check::{PathChecker, PathStatus};
|
||||
use crate::score::NodeScore;
|
||||
use crypto::identity::{DummyMixIdentityKeyPair, MixnetIdentityKeyPair};
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPrivateKey, MixnetIdentityPublicKey};
|
||||
use log::{debug, error, info, warn};
|
||||
use rand_os::rand_core::RngCore;
|
||||
use sphinx::route::NodeAddressBytes;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Error, Formatter};
|
||||
@@ -94,15 +95,31 @@ impl HealthCheckResult {
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn calculate<T: NymTopology>(
|
||||
fn generate_check_id() -> [u8; 16] {
|
||||
let mut id = [0u8; 16];
|
||||
let mut rng = rand_os::OsRng::new().unwrap();
|
||||
rng.fill_bytes(&mut id);
|
||||
id
|
||||
}
|
||||
|
||||
pub async fn calculate<T, IDPair, Priv, Pub>(
|
||||
topology: T,
|
||||
iterations: usize,
|
||||
resolution_timeout: Duration,
|
||||
) -> Self {
|
||||
identity_keys: &IDPair,
|
||||
) -> Self
|
||||
where
|
||||
T: NymTopology,
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
{
|
||||
// currently healthchecker supports only up to 255 iterations - if we somehow
|
||||
// find we need more, it's relatively easy change
|
||||
assert!(iterations <= 255);
|
||||
|
||||
let check_id = Self::generate_check_id();
|
||||
|
||||
let all_paths = match topology.all_paths() {
|
||||
Ok(paths) => paths,
|
||||
Err(_) => return Self::zero_score(topology),
|
||||
@@ -118,10 +135,9 @@ impl HealthCheckResult {
|
||||
score_map.insert(node.get_pub_key_bytes(), NodeScore::from_provider(node));
|
||||
});
|
||||
|
||||
let ephemeral_keys = DummyMixIdentityKeyPair::new();
|
||||
let providers = topology.providers();
|
||||
|
||||
let mut path_checker = PathChecker::new(providers, ephemeral_keys).await;
|
||||
let mut path_checker = PathChecker::new(providers, identity_keys, check_id).await;
|
||||
for i in 0..iterations {
|
||||
debug!("running healthcheck iteration {} / {}", i + 1, iterations);
|
||||
for path in &all_paths {
|
||||
|
||||
@@ -3,12 +3,14 @@ use crate::client::received_buffer::ReceivedMessagesBuffer;
|
||||
use crate::client::topology_control::TopologyInnerRef;
|
||||
use crate::sockets::tcp;
|
||||
use crate::sockets::ws;
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPrivateKey, MixnetIdentityPublicKey};
|
||||
use directory_client::presence::Topology;
|
||||
use futures::channel::mpsc;
|
||||
use futures::join;
|
||||
use log::*;
|
||||
use sfw_provider_requests::AuthToken;
|
||||
use sphinx::route::{Destination, DestinationAddressBytes};
|
||||
use sphinx::route::Destination;
|
||||
use std::marker::PhantomData;
|
||||
use std::net::SocketAddr;
|
||||
use tokio::runtime::Runtime;
|
||||
use topology::NymTopology;
|
||||
@@ -35,9 +37,13 @@ pub enum SocketType {
|
||||
None,
|
||||
}
|
||||
|
||||
pub struct NymClient {
|
||||
// to be replaced by something else I guess
|
||||
address: DestinationAddressBytes,
|
||||
pub struct NymClient<IDPair, Priv, Pub>
|
||||
where
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub> + Send + Sync,
|
||||
Priv: MixnetIdentityPrivateKey + Send + Sync,
|
||||
Pub: MixnetIdentityPublicKey + Send + Sync,
|
||||
{
|
||||
keypair: IDPair,
|
||||
|
||||
// to be used by "send" function or socket, etc
|
||||
pub input_tx: mpsc::UnboundedSender<InputMessage>,
|
||||
@@ -47,14 +53,22 @@ pub struct NymClient {
|
||||
directory: String,
|
||||
auth_token: Option<AuthToken>,
|
||||
socket_type: SocketType,
|
||||
|
||||
_phantom_private: PhantomData<Priv>,
|
||||
_phantom_public: PhantomData<Pub>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InputMessage(pub Destination, pub Vec<u8>);
|
||||
|
||||
impl NymClient {
|
||||
impl<IDPair: 'static, Priv: 'static, Pub: 'static> NymClient<IDPair, Priv, Pub>
|
||||
where
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub> + Send + Sync,
|
||||
Priv: MixnetIdentityPrivateKey + Send + Sync,
|
||||
Pub: MixnetIdentityPublicKey + Send + Sync,
|
||||
{
|
||||
pub fn new(
|
||||
address: DestinationAddressBytes,
|
||||
keypair: IDPair,
|
||||
socket_listening_address: SocketAddr,
|
||||
directory: String,
|
||||
auth_token: Option<AuthToken>,
|
||||
@@ -63,13 +77,15 @@ impl NymClient {
|
||||
let (input_tx, input_rx) = mpsc::unbounded::<InputMessage>();
|
||||
|
||||
NymClient {
|
||||
address,
|
||||
keypair,
|
||||
input_tx,
|
||||
input_rx,
|
||||
socket_listening_address,
|
||||
directory,
|
||||
auth_token,
|
||||
socket_type,
|
||||
_phantom_private: PhantomData,
|
||||
_phantom_public: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,11 +122,18 @@ impl NymClient {
|
||||
let (received_messages_buffer_output_tx, received_messages_buffer_output_rx) =
|
||||
mpsc::unbounded();
|
||||
|
||||
let self_address = self.keypair.public_key().derive_address();
|
||||
|
||||
// generate same type of keys we have as our identity
|
||||
let healthcheck_keys = IDPair::new();
|
||||
|
||||
// TODO: when we switch to our graph topology, we need to remember to change 'Topology' type
|
||||
let topology_controller = rt.block_on(topology_control::TopologyControl::<Topology>::new(
|
||||
self.directory.clone(),
|
||||
TOPOLOGY_REFRESH_RATE,
|
||||
));
|
||||
let topology_controller =
|
||||
rt.block_on(topology_control::TopologyControl::<Topology, _, _, _>::new(
|
||||
self.directory.clone(),
|
||||
TOPOLOGY_REFRESH_RATE,
|
||||
healthcheck_keys,
|
||||
));
|
||||
|
||||
let provider_client_listener_address =
|
||||
rt.block_on(self.get_provider_socket_address(topology_controller.get_inner_ref()));
|
||||
@@ -118,7 +141,7 @@ impl NymClient {
|
||||
let mut provider_poller = provider_poller::ProviderPoller::new(
|
||||
poller_input_tx,
|
||||
provider_client_listener_address,
|
||||
self.address,
|
||||
self_address,
|
||||
self.auth_token,
|
||||
);
|
||||
|
||||
@@ -144,12 +167,11 @@ impl NymClient {
|
||||
let loop_cover_traffic_future =
|
||||
rt.spawn(cover_traffic_stream::start_loop_cover_traffic_stream(
|
||||
mix_tx.clone(),
|
||||
Destination::new(self.address, Default::default()),
|
||||
Destination::new(self_address, Default::default()),
|
||||
topology_controller.get_inner_ref(),
|
||||
));
|
||||
|
||||
// cloning arguments required by OutQueueControl; required due to move
|
||||
let self_address = self.address;
|
||||
let input_rx = self.input_rx;
|
||||
let topology_ref = topology_controller.get_inner_ref();
|
||||
|
||||
@@ -180,7 +202,7 @@ impl NymClient {
|
||||
self.socket_listening_address,
|
||||
self.input_tx,
|
||||
received_messages_buffer_output_tx,
|
||||
self.address,
|
||||
self_address,
|
||||
topology_controller.get_inner_ref(),
|
||||
));
|
||||
}
|
||||
@@ -189,7 +211,7 @@ impl NymClient {
|
||||
self.socket_listening_address,
|
||||
self.input_tx,
|
||||
received_messages_buffer_output_tx,
|
||||
self.address,
|
||||
self_address,
|
||||
topology_controller.get_inner_ref(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use crate::built_info;
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPrivateKey, MixnetIdentityPublicKey};
|
||||
use healthcheck::HealthChecker;
|
||||
use log::{error, info, trace, warn};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
@@ -10,10 +12,17 @@ const NODE_HEALTH_THRESHOLD: f64 = 0.0;
|
||||
// auxiliary type for ease of use
|
||||
pub type TopologyInnerRef<T> = Arc<FRwLock<Inner<T>>>;
|
||||
|
||||
pub(crate) struct TopologyControl<T: NymTopology> {
|
||||
pub(crate) struct TopologyControl<T, IDPair, Priv, Pub>
|
||||
where
|
||||
T: NymTopology,
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
{
|
||||
directory_server: String,
|
||||
refresh_rate: f64,
|
||||
inner: Arc<FRwLock<Inner<T>>>,
|
||||
health_checker: HealthChecker<IDPair, Priv, Pub>,
|
||||
refresh_rate: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -22,40 +31,56 @@ enum TopologyError {
|
||||
NoValidPathsError,
|
||||
}
|
||||
|
||||
impl<T: NymTopology> TopologyControl<T> {
|
||||
pub(crate) async fn new(directory_server: String, refresh_rate: f64) -> Self {
|
||||
let initial_topology = match Self::get_current_compatible_topology(directory_server.clone())
|
||||
.await
|
||||
{
|
||||
impl<T, IDPair, Priv, Pub> TopologyControl<T, IDPair, Priv, Pub>
|
||||
where
|
||||
T: NymTopology,
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
{
|
||||
pub(crate) async fn new(
|
||||
directory_server: String,
|
||||
refresh_rate: f64,
|
||||
identity_keypair: IDPair,
|
||||
) -> Self {
|
||||
// topology control run a healthcheck to determine healthy-ish nodes:
|
||||
// this is a temporary solution as the healthcheck will eventually be moved to validators
|
||||
|
||||
let healthcheck_config = healthcheck::config::HealthCheck {
|
||||
directory_server: directory_server.clone(),
|
||||
// those are literally irrelevant when running single check
|
||||
interval: 100000.0,
|
||||
resolution_timeout: 5.0,
|
||||
num_test_packets: 2,
|
||||
};
|
||||
let health_checker = healthcheck::HealthChecker::new(healthcheck_config, identity_keypair);
|
||||
|
||||
let mut topology_control = TopologyControl {
|
||||
directory_server,
|
||||
refresh_rate,
|
||||
inner: Arc::new(FRwLock::new(Inner::new(None))),
|
||||
health_checker,
|
||||
};
|
||||
|
||||
// best effort approach to try to get a valid topology after call to 'new'
|
||||
let initial_topology = match topology_control.get_current_compatible_topology().await {
|
||||
Ok(topology) => Some(topology),
|
||||
Err(err) => {
|
||||
error!("Initial topology is invalid - {:?}. Right now it will be impossible to send any packets through the mixnet!", err);
|
||||
None
|
||||
}
|
||||
};
|
||||
topology_control
|
||||
.update_global_topology(initial_topology)
|
||||
.await;
|
||||
|
||||
TopologyControl {
|
||||
directory_server,
|
||||
refresh_rate,
|
||||
inner: Arc::new(FRwLock::new(Inner::new(initial_topology))),
|
||||
}
|
||||
topology_control
|
||||
}
|
||||
|
||||
async fn get_current_compatible_topology(directory_server: String) -> Result<T, TopologyError> {
|
||||
let full_topology = T::new(directory_server.clone());
|
||||
|
||||
// run a healthcheck to determine healthy-ish nodes:
|
||||
// this is a temporary solution as the healthcheck will eventually be moved to validators
|
||||
let healthcheck_config = healthcheck::config::HealthCheck {
|
||||
directory_server,
|
||||
// those are literally irrelevant when running single check
|
||||
interval: 100000.0,
|
||||
resolution_timeout: 5.0,
|
||||
num_test_packets: 2,
|
||||
};
|
||||
let healthcheck = healthcheck::HealthChecker::new(healthcheck_config);
|
||||
let healthcheck_result = healthcheck.do_check().await;
|
||||
async fn get_current_compatible_topology(&self) -> Result<T, TopologyError> {
|
||||
let full_topology = T::new(self.directory_server.clone());
|
||||
|
||||
let healthcheck_result = self.health_checker.do_check().await;
|
||||
let healthcheck_scores = match healthcheck_result {
|
||||
Err(err) => {
|
||||
error!("Error while performing the healthcheck: {:?}", err);
|
||||
@@ -96,8 +121,7 @@ impl<T: NymTopology> TopologyControl<T> {
|
||||
let delay_duration = Duration::from_secs_f64(self.refresh_rate);
|
||||
loop {
|
||||
trace!("Refreshing the topology");
|
||||
let new_topology_res =
|
||||
Self::get_current_compatible_topology(self.directory_server.clone()).await;
|
||||
let new_topology_res = self.get_current_compatible_topology().await;
|
||||
|
||||
let new_topology = match new_topology_res {
|
||||
Ok(topology) => Some(topology),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::client::{NymClient, SocketType};
|
||||
use crate::config::persistance::pathfinder::ClientPathfinder;
|
||||
use clap::ArgMatches;
|
||||
use crypto::identity::{DummyMixIdentityKeyPair, MixnetIdentityKeyPair, MixnetIdentityPublicKey};
|
||||
use crypto::identity::DummyMixIdentityKeyPair;
|
||||
use pemstore::pemstore::PemStore;
|
||||
use std::net::ToSocketAddrs;
|
||||
|
||||
@@ -34,12 +34,9 @@ pub fn execute(matches: &ArgMatches) {
|
||||
|
||||
println!("Public key: {}", keypair.public_key.to_base58_string());
|
||||
|
||||
let mut temporary_address = [0u8; 32];
|
||||
let public_key_bytes = keypair.public_key().to_bytes();
|
||||
temporary_address.copy_from_slice(&public_key_bytes[..]);
|
||||
let auth_token = None;
|
||||
let client = NymClient::new(
|
||||
temporary_address,
|
||||
keypair,
|
||||
socket_address.clone(),
|
||||
directory_server,
|
||||
auth_token,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::client::{NymClient, SocketType};
|
||||
use crate::config::persistance::pathfinder::ClientPathfinder;
|
||||
use clap::ArgMatches;
|
||||
use crypto::identity::{DummyMixIdentityKeyPair, MixnetIdentityKeyPair, MixnetIdentityPublicKey};
|
||||
use crypto::identity::DummyMixIdentityKeyPair;
|
||||
use pemstore::pemstore::PemStore;
|
||||
use std::net::ToSocketAddrs;
|
||||
|
||||
@@ -35,12 +35,9 @@ pub fn execute(matches: &ArgMatches) {
|
||||
|
||||
println!("Public key: {}", keypair.public_key.to_base58_string());
|
||||
|
||||
let mut temporary_address = [0u8; 32];
|
||||
let public_key_bytes = keypair.public_key().to_bytes();
|
||||
temporary_address.copy_from_slice(&public_key_bytes[..]);
|
||||
let auth_token = None;
|
||||
let client = NymClient::new(
|
||||
temporary_address,
|
||||
keypair,
|
||||
socket_address,
|
||||
directory_server,
|
||||
auth_token,
|
||||
|
||||
@@ -20,6 +20,7 @@ tokio = { version = "0.2", features = ["full"] }
|
||||
toml = "0.5.5"
|
||||
|
||||
## internal
|
||||
crypto = {path = "../common/crypto"}
|
||||
healthcheck = {path = "../common/healthcheck" }
|
||||
|
||||
[build-dependencies]
|
||||
|
||||
@@ -1,20 +1,36 @@
|
||||
use crate::validator::config::Config;
|
||||
use crypto::identity::{
|
||||
DummyMixIdentityKeyPair, DummyMixIdentityPrivateKey, DummyMixIdentityPublicKey,
|
||||
MixnetIdentityKeyPair, MixnetIdentityPrivateKey, MixnetIdentityPublicKey,
|
||||
};
|
||||
use healthcheck::HealthChecker;
|
||||
use log::debug;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
pub mod config;
|
||||
|
||||
pub struct Validator {
|
||||
heath_check: HealthChecker,
|
||||
// allow for a generic validator
|
||||
pub struct Validator<IDPair, Priv, Pub>
|
||||
where
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
{
|
||||
#[allow(dead_code)]
|
||||
identity_keypair: IDPair,
|
||||
heath_check: HealthChecker<IDPair, Priv, Pub>,
|
||||
}
|
||||
|
||||
impl Validator {
|
||||
// but for time being, since it's a dummy one, have it use dummy keys
|
||||
impl Validator<DummyMixIdentityKeyPair, DummyMixIdentityPrivateKey, DummyMixIdentityPublicKey> {
|
||||
pub fn new(config: Config) -> Self {
|
||||
debug!("validator new");
|
||||
|
||||
let dummy_keypair = DummyMixIdentityKeyPair::new();
|
||||
|
||||
Validator {
|
||||
heath_check: HealthChecker::new(config.health_check),
|
||||
identity_keypair: dummy_keypair.clone(),
|
||||
heath_check: HealthChecker::new(config.health_check, dummy_keypair),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user