Merge pull request #105 from nymtech/feature/health_checker_with_existing_keys

Feature/health checker with existing keys
This commit is contained in:
Dave Hrycyszyn
2020-01-27 17:17:48 +00:00
committed by GitHub
14 changed files with 218 additions and 87 deletions
Generated
+4
View File
@@ -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",
+1 -1
View File
@@ -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)
+3
View File
@@ -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" }
+17 -4
View File
@@ -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()
}
+2
View File
@@ -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"] }
+25 -3
View File
@@ -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();
+30 -16
View File
@@ -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
+21 -5
View File
@@ -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 {
+38 -16
View File
@@ -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(),
));
}
+52 -28
View File
@@ -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),
+2 -5
View File
@@ -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,
+2 -5
View File
@@ -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,
+1
View File
@@ -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]
+20 -4
View File
@@ -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),
}
}