validator: WIP on merge conflicts
This commit is contained in:
+38
-7
@@ -1,8 +1,38 @@
|
||||
# Changelog
|
||||
|
||||
## [Unreleased](https://github.com/nymtech/nym/tree/HEAD)
|
||||
## [v0.4.1](https://github.com/nymtech/nym/tree/v0.4.1) (2020-01-29)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.3.3...HEAD)
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.4.0...v0.4.1)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Change healthcheck to run on provided topology rather than pull one itself [\#95](https://github.com/nymtech/nym/issues/95)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Bugfix/healthcheck on provided topology [\#108](https://github.com/nymtech/nym/pull/108) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
## [v0.4.0](https://github.com/nymtech/nym/tree/v0.4.0) (2020-01-28)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.4.0-rc.2...v0.4.0)
|
||||
|
||||
Nym 0.4.0 Platform
|
||||
|
||||
In this release, we're taking a lot more care with version numbers, so that we can ensure upgrade compatibility for mixnodes, providers, clients, and validators more easily.
|
||||
|
||||
This release also integrates a health-checker and network topology refresh into the Nym client, so that the client can intelligently choose paths which route around any non-functional or incompatible nodes.
|
||||
|
||||
## [v0.4.0-rc.2](https://github.com/nymtech/nym/tree/v0.4.0-rc.2) (2020-01-28)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.4.0-rc.1...v0.4.0-rc.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Hotfix/semver compatibility [\#106](https://github.com/nymtech/nym/pull/106) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
## [v0.4.0-rc.1](https://github.com/nymtech/nym/tree/v0.4.0-rc.1) (2020-01-28)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.3.3...v0.4.0-rc.1)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
@@ -64,10 +94,6 @@
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.3.1...v0.3.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Feature/separate presence address [\#59](https://github.com/nymtech/nym/pull/59) ([jstuczyn](https://github.com/jstuczyn))
|
||||
|
||||
## [v0.3.1](https://github.com/nymtech/nym/tree/v0.3.1) (2020-01-16)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/v0.3.0...v0.3.1)
|
||||
@@ -94,6 +120,7 @@
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Feature/separate presence address [\#59](https://github.com/nymtech/nym/pull/59) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- Feature/client topology filtering [\#54](https://github.com/nymtech/nym/pull/54) ([jstuczyn](https://github.com/jstuczyn))
|
||||
- print public key for nym client tools [\#53](https://github.com/nymtech/nym/pull/53) ([mileschet](https://github.com/mileschet))
|
||||
- Showing binding warning on binding to localhost, 0.0.0.0 or 127.0.0.1 [\#52](https://github.com/nymtech/nym/pull/52) ([jstuczyn](https://github.com/jstuczyn))
|
||||
@@ -114,7 +141,11 @@
|
||||
|
||||
## [v0.2.0](https://github.com/nymtech/nym/tree/v0.2.0) (2020-01-07)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/3c64a2facd753f4f2f431e7f888e54842e2bc64e...v0.2.0)
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/0.2.0...v0.2.0)
|
||||
|
||||
## [0.2.0](https://github.com/nymtech/nym/tree/0.2.0) (2020-01-06)
|
||||
|
||||
[Full Changelog](https://github.com/nymtech/nym/compare/0.1.0...0.2.0)
|
||||
|
||||
|
||||
|
||||
|
||||
Generated
+6
-4
@@ -1379,7 +1379,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-client"
|
||||
version = "0.4.0-rc.1"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"addressing",
|
||||
"bs58",
|
||||
@@ -1411,7 +1411,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-mixnode"
|
||||
version = "0.4.0-rc.1"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"addressing",
|
||||
"bs58",
|
||||
@@ -1429,7 +1429,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-sfw-provider"
|
||||
version = "0.4.0-rc.1"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"built",
|
||||
@@ -1453,13 +1453,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-validator"
|
||||
version = "0.4.0-rc.1"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"abci",
|
||||
"built",
|
||||
"byteorder",
|
||||
"clap",
|
||||
"crypto",
|
||||
"directory-client",
|
||||
"dotenv",
|
||||
"futures 0.3.1",
|
||||
"healthcheck",
|
||||
@@ -1469,6 +1470,7 @@ dependencies = [
|
||||
"serde_derive",
|
||||
"tokio 0.2.10",
|
||||
"toml",
|
||||
"topology",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -6,14 +6,13 @@ use bs58;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
use sphinx::route::DestinationAddressBytes;
|
||||
|
||||
pub trait MixnetIdentityKeyPair<Priv, Pub>: Clone
|
||||
where
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
{
|
||||
pub trait MixnetIdentityKeyPair: Clone {
|
||||
type PublicKeyMaterial: MixnetIdentityPublicKey;
|
||||
type PrivateKeyMaterial: MixnetIdentityPrivateKey;
|
||||
|
||||
fn new() -> Self;
|
||||
fn private_key(&self) -> &Priv;
|
||||
fn public_key(&self) -> &Pub;
|
||||
fn private_key(&self) -> &Self::PrivateKeyMaterial;
|
||||
fn public_key(&self) -> &Self::PublicKeyMaterial;
|
||||
fn from_bytes(priv_bytes: &[u8], pub_bytes: &[u8]) -> Self;
|
||||
|
||||
// TODO: signing related methods
|
||||
@@ -56,9 +55,10 @@ pub struct DummyMixIdentityKeyPair {
|
||||
pub public_key: DummyMixIdentityPublicKey,
|
||||
}
|
||||
|
||||
impl MixnetIdentityKeyPair<DummyMixIdentityPrivateKey, DummyMixIdentityPublicKey>
|
||||
for DummyMixIdentityKeyPair
|
||||
{
|
||||
impl MixnetIdentityKeyPair for DummyMixIdentityKeyPair {
|
||||
type PublicKeyMaterial = DummyMixIdentityPublicKey;
|
||||
type PrivateKeyMaterial = DummyMixIdentityPrivateKey;
|
||||
|
||||
fn new() -> Self {
|
||||
let keypair = encryption::x25519::KeyPair::new();
|
||||
DummyMixIdentityKeyPair {
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
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 crypto::identity::MixnetIdentityKeyPair;
|
||||
use log::trace;
|
||||
use std::fmt::{Error, Formatter};
|
||||
use std::marker::PhantomData;
|
||||
use std::time::Duration;
|
||||
use topology::NymTopologyError;
|
||||
use topology::{NymTopology, NymTopologyError};
|
||||
|
||||
pub mod config;
|
||||
mod path_check;
|
||||
@@ -36,58 +33,31 @@ impl From<topology::NymTopologyError> for HealthCheckerError {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HealthChecker<IDPair, Priv, Pub>
|
||||
where
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
{
|
||||
directory_client: directory_client::Client,
|
||||
interval: Duration,
|
||||
pub struct HealthChecker<IDPair: MixnetIdentityKeyPair> {
|
||||
num_test_packets: usize,
|
||||
resolution_timeout: Duration,
|
||||
identity_keypair: IDPair,
|
||||
|
||||
_phantom_private: PhantomData<Priv>,
|
||||
_phantom_public: PhantomData<Pub>,
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
let directory_client_config = directory_client::Config::new(config.directory_server);
|
||||
impl<IDPair: MixnetIdentityKeyPair> HealthChecker<IDPair> {
|
||||
pub fn new(
|
||||
resolution_timeout_f64: f64,
|
||||
num_test_packets: usize,
|
||||
identity_keypair: IDPair,
|
||||
) -> Self {
|
||||
HealthChecker {
|
||||
directory_client: directory_client::Client::new(directory_client_config),
|
||||
interval: Duration::from_secs_f64(config.interval),
|
||||
resolution_timeout: Duration::from_secs_f64(config.resolution_timeout),
|
||||
num_test_packets: config.num_test_packets,
|
||||
resolution_timeout: Duration::from_secs_f64(resolution_timeout_f64),
|
||||
num_test_packets,
|
||||
identity_keypair,
|
||||
|
||||
_phantom_private: PhantomData,
|
||||
_phantom_public: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn do_check(&self) -> Result<HealthCheckResult, HealthCheckerError> {
|
||||
pub async fn do_check<T: NymTopology>(
|
||||
&self,
|
||||
current_topology: &T,
|
||||
) -> Result<HealthCheckResult, HealthCheckerError> {
|
||||
trace!("going to perform a healthcheck!");
|
||||
|
||||
let current_topology = match self.directory_client.presence_topology.get() {
|
||||
Ok(topology) => topology,
|
||||
Err(err) => {
|
||||
error!("failed to obtain topology - {:?}", err);
|
||||
return Err(HealthCheckerError::FailedToObtainTopologyError);
|
||||
}
|
||||
};
|
||||
trace!("current topology: {:?}", current_topology);
|
||||
|
||||
let mut healthcheck_result = HealthCheckResult::calculate(
|
||||
current_topology,
|
||||
self.num_test_packets,
|
||||
@@ -98,20 +68,4 @@ where
|
||||
healthcheck_result.sort_scores();
|
||||
Ok(healthcheck_result)
|
||||
}
|
||||
|
||||
pub async fn run(self) -> Result<(), HealthCheckerError> {
|
||||
debug!(
|
||||
"healthcheck will run every {:?} and will send {} packets to each node",
|
||||
self.interval, self.num_test_packets
|
||||
);
|
||||
|
||||
loop {
|
||||
match self.do_check().await {
|
||||
Ok(health) => info!("current network health: \n{}", health),
|
||||
Err(err) => error!("failed to perform healthcheck - {:?}", err),
|
||||
};
|
||||
|
||||
tokio::time::delay_for(self.interval).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPrivateKey, MixnetIdentityPublicKey};
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPublicKey};
|
||||
use itertools::Itertools;
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use mix_client::MixClient;
|
||||
@@ -27,16 +27,11 @@ pub(crate) struct PathChecker {
|
||||
}
|
||||
|
||||
impl PathChecker {
|
||||
pub(crate) async fn new<IDPair, Priv, Pub>(
|
||||
pub(crate) async fn new<IDPair: MixnetIdentityKeyPair>(
|
||||
providers: Vec<provider::Node>,
|
||||
identity_keys: &IDPair,
|
||||
check_id: [u8; 16],
|
||||
) -> Self
|
||||
where
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
{
|
||||
) -> Self {
|
||||
let mut provider_clients = HashMap::new();
|
||||
|
||||
let address = identity_keys.public_key().derive_address();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::path_check::{PathChecker, PathStatus};
|
||||
use crate::score::NodeScore;
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPrivateKey, MixnetIdentityPublicKey};
|
||||
use crypto::identity::MixnetIdentityKeyPair;
|
||||
use log::{debug, error, info, warn};
|
||||
use rand_os::rand_core::RngCore;
|
||||
use sphinx::route::NodeAddressBytes;
|
||||
@@ -27,7 +27,7 @@ impl HealthCheckResult {
|
||||
self.0.sort();
|
||||
}
|
||||
|
||||
fn zero_score<T: NymTopology>(topology: T) -> Self {
|
||||
fn zero_score<T: NymTopology>(topology: &T) -> Self {
|
||||
warn!("The network is unhealthy, could not send any packets - returning zero score!");
|
||||
let mixes = topology.mix_nodes();
|
||||
let providers = topology.providers();
|
||||
@@ -102,17 +102,15 @@ impl HealthCheckResult {
|
||||
id
|
||||
}
|
||||
|
||||
pub async fn calculate<T, IDPair, Priv, Pub>(
|
||||
topology: T,
|
||||
pub async fn calculate<T, IDPair>(
|
||||
topology: &T,
|
||||
iterations: usize,
|
||||
resolution_timeout: Duration,
|
||||
identity_keys: &IDPair,
|
||||
) -> Self
|
||||
where
|
||||
T: NymTopology,
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
IDPair: MixnetIdentityKeyPair,
|
||||
{
|
||||
// currently healthchecker supports only up to 255 iterations - if we somehow
|
||||
// find we need more, it's relatively easy change
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use crate::pathfinder::PathFinder;
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPrivateKey, MixnetIdentityPublicKey};
|
||||
use crypto::PemStorable;
|
||||
use pem::{encode, parse, Pem};
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
@@ -25,12 +27,7 @@ impl PemStore {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_identity<IDPair, Priv, Pub>(&self) -> io::Result<IDPair>
|
||||
where
|
||||
IDPair: crypto::identity::MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: crypto::identity::MixnetIdentityPrivateKey,
|
||||
Pub: crypto::identity::MixnetIdentityPublicKey,
|
||||
{
|
||||
pub fn read_identity<IDPair: MixnetIdentityKeyPair>(&self) -> io::Result<IDPair> {
|
||||
let private_pem = self.read_pem_file(self.private_mix_key.clone())?;
|
||||
let public_pem = self.read_pem_file(self.public_mix_key.clone())?;
|
||||
|
||||
@@ -62,12 +59,10 @@ impl PemStore {
|
||||
// This should be refactored and made more generic for when we have other kinds of
|
||||
// KeyPairs that we want to persist (e.g. validator keypairs, or keys for
|
||||
// signing vs encryption). However, for the moment, it does the job.
|
||||
pub fn write_identity<IDPair, Priv, Pub>(&self, key_pair: IDPair) -> io::Result<()>
|
||||
where
|
||||
IDPair: crypto::identity::MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: crypto::identity::MixnetIdentityPrivateKey,
|
||||
Pub: crypto::identity::MixnetIdentityPublicKey,
|
||||
{
|
||||
pub fn write_identity<IDPair: MixnetIdentityKeyPair>(
|
||||
&self,
|
||||
key_pair: IDPair,
|
||||
) -> io::Result<()> {
|
||||
std::fs::create_dir_all(self.config_dir.clone())?;
|
||||
|
||||
let private_key = key_pair.private_key();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use semver::Version;
|
||||
use semver::VersionReq;
|
||||
|
||||
/// Checks whether given `version` is compatible with a given semantic version requirement `req`
|
||||
/// according to major-minor semver rules. The semantic version requirement can be passed as a full,
|
||||
@@ -7,18 +6,16 @@ use semver::VersionReq;
|
||||
/// The patch number in the requirement gets dropped and replaced with a wildcard (0.3.*) as all
|
||||
/// minor versions should be compatible with each other.
|
||||
pub fn is_minor_version_compatible(version: &str, req: &str) -> bool {
|
||||
let version = match Version::parse(version) {
|
||||
let expected_version = match Version::parse(version) {
|
||||
Ok(v) => v,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let tmp = match Version::parse(req) {
|
||||
let req_version = match Version::parse(req) {
|
||||
Ok(v) => v,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let wildcard = format!("{}.{}.*", tmp.major, tmp.minor).to_string();
|
||||
let semver_requirement = VersionReq::parse(&wildcard).expect("panicked on semver requirement parsing. This should never happen as inputs should already have been sanitized.");
|
||||
|
||||
semver_requirement.matches(&version)
|
||||
expected_version.major == req_version.major && expected_version.minor == req_version.minor
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -55,6 +52,11 @@ mod tests {
|
||||
assert!(!is_minor_version_compatible("1.3.2", "0.3.2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_0_4_0_rc_1_is_compatible_with_version_0_4_0_rc_1() {
|
||||
assert!(is_minor_version_compatible("0.4.0-rc.1", "0.4.0-rc.1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_false_on_foo_version() {
|
||||
assert!(!is_minor_version_compatible("foo", "0.3.2"));
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
build = "build.rs"
|
||||
name = "nym-mixnode"
|
||||
version = "0.4.0-rc.1"
|
||||
version = "0.4.1"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2018"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
build = "build.rs"
|
||||
name = "nym-client"
|
||||
version = "0.4.0-rc.1"
|
||||
version = "0.4.1"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2018"
|
||||
|
||||
|
||||
@@ -3,14 +3,13 @@ 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 crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPublicKey};
|
||||
use directory_client::presence::Topology;
|
||||
use futures::channel::mpsc;
|
||||
use futures::join;
|
||||
use log::*;
|
||||
use sfw_provider_requests::AuthToken;
|
||||
use sphinx::route::Destination;
|
||||
use std::marker::PhantomData;
|
||||
use std::net::SocketAddr;
|
||||
use tokio::runtime::Runtime;
|
||||
use topology::NymTopology;
|
||||
@@ -37,11 +36,9 @@ pub enum SocketType {
|
||||
None,
|
||||
}
|
||||
|
||||
pub struct NymClient<IDPair, Priv, Pub>
|
||||
pub struct NymClient<IDPair>
|
||||
where
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub> + Send + Sync,
|
||||
Priv: MixnetIdentityPrivateKey + Send + Sync,
|
||||
Pub: MixnetIdentityPublicKey + Send + Sync,
|
||||
IDPair: MixnetIdentityKeyPair + Send + Sync,
|
||||
{
|
||||
keypair: IDPair,
|
||||
|
||||
@@ -53,19 +50,14 @@ where
|
||||
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<IDPair: 'static, Priv: 'static, Pub: 'static> NymClient<IDPair, Priv, Pub>
|
||||
impl<IDPair> NymClient<IDPair>
|
||||
where
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub> + Send + Sync,
|
||||
Priv: MixnetIdentityPrivateKey + Send + Sync,
|
||||
Pub: MixnetIdentityPublicKey + Send + Sync,
|
||||
IDPair: 'static + MixnetIdentityKeyPair + Send + Sync,
|
||||
{
|
||||
pub fn new(
|
||||
keypair: IDPair,
|
||||
@@ -84,8 +76,6 @@ where
|
||||
directory,
|
||||
auth_token,
|
||||
socket_type,
|
||||
_phantom_private: PhantomData,
|
||||
_phantom_public: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +119,7 @@ where
|
||||
|
||||
// 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(
|
||||
rt.block_on(topology_control::TopologyControl::<Topology, _>::new(
|
||||
self.directory.clone(),
|
||||
TOPOLOGY_REFRESH_RATE,
|
||||
healthcheck_keys,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::built_info;
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPrivateKey, MixnetIdentityPublicKey};
|
||||
use crypto::identity::MixnetIdentityKeyPair;
|
||||
use healthcheck::HealthChecker;
|
||||
use log::{error, info, trace, warn};
|
||||
use std::sync::Arc;
|
||||
@@ -12,16 +12,14 @@ 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, IDPair, Priv, Pub>
|
||||
pub(crate) struct TopologyControl<T, IDPair>
|
||||
where
|
||||
T: NymTopology,
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
IDPair: MixnetIdentityKeyPair,
|
||||
{
|
||||
directory_server: String,
|
||||
inner: Arc<FRwLock<Inner<T>>>,
|
||||
health_checker: HealthChecker<IDPair, Priv, Pub>,
|
||||
health_checker: HealthChecker<IDPair>,
|
||||
refresh_rate: f64,
|
||||
}
|
||||
|
||||
@@ -31,29 +29,18 @@ enum TopologyError {
|
||||
NoValidPathsError,
|
||||
}
|
||||
|
||||
impl<T, IDPair, Priv, Pub> TopologyControl<T, IDPair, Priv, Pub>
|
||||
impl<T, IDPair> TopologyControl<T, IDPair>
|
||||
where
|
||||
T: NymTopology,
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
IDPair: MixnetIdentityKeyPair,
|
||||
{
|
||||
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 health_checker = healthcheck::HealthChecker::new(5.0, 2, identity_keypair);
|
||||
|
||||
let mut topology_control = TopologyControl {
|
||||
directory_server,
|
||||
@@ -79,8 +66,16 @@ where
|
||||
|
||||
async fn get_current_compatible_topology(&self) -> Result<T, TopologyError> {
|
||||
let full_topology = T::new(self.directory_server.clone());
|
||||
let version_filtered_topology = full_topology.filter_node_versions(
|
||||
built_info::PKG_VERSION,
|
||||
built_info::PKG_VERSION,
|
||||
built_info::PKG_VERSION,
|
||||
);
|
||||
|
||||
let healthcheck_result = self.health_checker.do_check().await;
|
||||
let healthcheck_result = self
|
||||
.health_checker
|
||||
.do_check(&version_filtered_topology)
|
||||
.await;
|
||||
let healthcheck_scores = match healthcheck_result {
|
||||
Err(err) => {
|
||||
error!("Error while performing the healthcheck: {:?}", err);
|
||||
@@ -89,21 +84,15 @@ where
|
||||
Ok(scores) => scores,
|
||||
};
|
||||
|
||||
let healthy_topology =
|
||||
healthcheck_scores.filter_topology_by_score(&full_topology, NODE_HEALTH_THRESHOLD);
|
||||
|
||||
let versioned_healthy_topology = healthy_topology.filter_node_versions(
|
||||
built_info::PKG_VERSION,
|
||||
built_info::PKG_VERSION,
|
||||
built_info::PKG_VERSION,
|
||||
);
|
||||
let healthy_topology = healthcheck_scores
|
||||
.filter_topology_by_score(&version_filtered_topology, NODE_HEALTH_THRESHOLD);
|
||||
|
||||
// make sure you can still send a packet through the network:
|
||||
if !versioned_healthy_topology.can_construct_path_through() {
|
||||
if !healthy_topology.can_construct_path_through() {
|
||||
return Err(TopologyError::NoValidPathsError);
|
||||
}
|
||||
|
||||
Ok(versioned_healthy_topology)
|
||||
Ok(healthy_topology)
|
||||
}
|
||||
|
||||
pub(crate) fn get_inner_ref(&self) -> Arc<FRwLock<Inner<T>>> {
|
||||
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
# set CHANGELOG_GITHUB_TOKEN in your .bashrc file
|
||||
github_changelog_generator -u nymtech -p nym --exclude-tags 0.1.0 --token "$CHANGELOG_GITHUB_TOKEN"
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
build = "build.rs"
|
||||
name = "nym-sfw-provider"
|
||||
version = "0.4.0-rc.1"
|
||||
version = "0.4.1"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2018"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
build = "build.rs"
|
||||
name = "nym-validator"
|
||||
version = "0.4.0-rc.1"
|
||||
version = "0.4.1"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
edition = "2018"
|
||||
|
||||
@@ -23,7 +23,9 @@ toml = "0.5.5"
|
||||
|
||||
## internal
|
||||
crypto = {path = "../common/crypto"}
|
||||
directory-client = { path = "../common/clients/directory-client" }
|
||||
healthcheck = {path = "../common/healthcheck" }
|
||||
topology = {path = "../common/topology"}
|
||||
|
||||
[build-dependencies]
|
||||
built = "0.3.2"
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::process;
|
||||
use toml;
|
||||
|
||||
mod network;
|
||||
mod services;
|
||||
mod validator;
|
||||
|
||||
fn main() {
|
||||
|
||||
@@ -21,8 +21,8 @@ impl Abci {
|
||||
Abci { count: 0 }
|
||||
}
|
||||
|
||||
pub async fn run(self) {
|
||||
abci::run_local(self);
|
||||
pub fn run(self) {
|
||||
tokio::spawn(async { abci::run_local(self) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
use crypto::identity::MixnetIdentityKeyPair;
|
||||
use healthcheck::HealthChecker;
|
||||
use log::*;
|
||||
use std::time::Duration;
|
||||
use topology::NymTopology;
|
||||
|
||||
pub struct HealthCheckRunner<T: MixnetIdentityKeyPair> {
|
||||
directory_server: String,
|
||||
health_checker: HealthChecker<T>,
|
||||
interval: f64,
|
||||
}
|
||||
|
||||
impl<T: MixnetIdentityKeyPair + Send + Sync + 'static> HealthCheckRunner<T> {
|
||||
pub fn new(
|
||||
directory_server: String,
|
||||
interval: f64,
|
||||
health_checker: HealthChecker<T>,
|
||||
) -> HealthCheckRunner<T> {
|
||||
HealthCheckRunner {
|
||||
directory_server,
|
||||
health_checker,
|
||||
interval,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(self) {
|
||||
tokio::spawn(async move {
|
||||
let healthcheck_interval = Duration::from_secs_f64(self.interval);
|
||||
debug!("healthcheck will run every {:?}", healthcheck_interval);
|
||||
loop {
|
||||
let full_topology =
|
||||
directory_client::presence::Topology::new(self.directory_server.clone());
|
||||
let version_filtered_topology = full_topology.filter_node_versions(
|
||||
crate::built_info::PKG_VERSION,
|
||||
crate::built_info::PKG_VERSION,
|
||||
crate::built_info::PKG_VERSION,
|
||||
);
|
||||
match self
|
||||
.health_checker
|
||||
.do_check(&version_filtered_topology)
|
||||
.await
|
||||
{
|
||||
Ok(health) => info!("current network health: \n{}", health),
|
||||
Err(err) => error!("failed to perform healthcheck - {:?}", err),
|
||||
};
|
||||
tokio::time::delay_for(healthcheck_interval).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod health_check_runner;
|
||||
@@ -0,0 +1 @@
|
||||
pub mod mixmining;
|
||||
+23
-23
@@ -1,8 +1,6 @@
|
||||
use crate::network::tendermint;
|
||||
use crypto::identity::{
|
||||
DummyMixIdentityKeyPair, DummyMixIdentityPrivateKey, DummyMixIdentityPublicKey,
|
||||
MixnetIdentityKeyPair, MixnetIdentityPrivateKey, MixnetIdentityPublicKey,
|
||||
};
|
||||
use crate::services::mixmining::health_check_runner;
|
||||
use crypto::identity::{DummyMixIdentityKeyPair, MixnetIdentityKeyPair};
|
||||
use healthcheck::HealthChecker;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
@@ -15,39 +13,41 @@ pub struct Config {
|
||||
}
|
||||
|
||||
// allow for a generic validator
|
||||
pub struct Validator<IDPair, Priv, Pub>
|
||||
where
|
||||
IDPair: MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
{
|
||||
tendermint_abci: tendermint::Abci,
|
||||
health_check: HealthChecker<IDPair, Priv, Pub>,
|
||||
pub struct Validator<IDPair: MixnetIdentityKeyPair> {
|
||||
config: Config,
|
||||
#[allow(dead_code)]
|
||||
identity_keypair: IDPair,
|
||||
health_check_runner: health_check_runner::HealthCheckRunner<IDPair>,
|
||||
tendermint_abci: tendermint::Abci,
|
||||
}
|
||||
|
||||
// but for time being, since it's a dummy one, have it use dummy keys
|
||||
impl Validator<DummyMixIdentityKeyPair, DummyMixIdentityPrivateKey, DummyMixIdentityPublicKey> {
|
||||
impl Validator<DummyMixIdentityKeyPair> {
|
||||
pub fn new(config: Config) -> Self {
|
||||
let dummy_keypair = DummyMixIdentityKeyPair::new();
|
||||
let hc = HealthChecker::new(
|
||||
config.health_check.resolution_timeout,
|
||||
config.health_check.num_test_packets,
|
||||
dummy_keypair.clone(),
|
||||
);
|
||||
|
||||
let health_check_runner = health_check_runner::HealthCheckRunner::new(
|
||||
config.health_check.directory_server.clone(),
|
||||
config.health_check.interval,
|
||||
hc,
|
||||
);
|
||||
|
||||
Validator {
|
||||
tendermint_abci: tendermint::Abci::new(),
|
||||
health_check: HealthChecker::new(config.health_check, dummy_keypair.clone()),
|
||||
identity_keypair: dummy_keypair,
|
||||
health_check_runner,
|
||||
config,
|
||||
tendermint_abci: tendermint::Abci::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(self) {
|
||||
let mut rt = Runtime::new().unwrap();
|
||||
|
||||
let abci_future = self.tendermint_abci.run();
|
||||
let health_check_future = self.health_check.run();
|
||||
|
||||
rt.spawn(abci_future);
|
||||
|
||||
let health_check_res = rt.block_on(health_check_future);
|
||||
assert!(health_check_res.is_ok()); // panic if health checker failed
|
||||
rt.spawn(self.health_check_runner.run());
|
||||
rt.block_on(self.tendermint_abci.run());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user