Feature/node state endpoint (#1013)

* Introduced route to check mixnode's status (active/standby/inactive/not_found)

* Restored default validator API caching interval to a more sane value

* Changed status route
This commit is contained in:
Jędrzej Stuczyński
2022-01-07 11:57:38 +00:00
committed by GitHub
parent 30e93c33bb
commit 62fa2ae5e4
3 changed files with 72 additions and 3 deletions
+54 -1
View File
@@ -4,7 +4,9 @@
use crate::nymd_client::Client;
use anyhow::Result;
use config::defaults::VALIDATOR_API_VERSION;
use mixnet_contract::{ContractStateParams, GatewayBond, MixNodeBond, RewardingIntervalResponse};
use mixnet_contract::{
ContractStateParams, GatewayBond, IdentityKey, MixNodeBond, RewardingIntervalResponse,
};
use rand::prelude::SliceRandom;
use rand_chacha::rand_core::SeedableRng;
use rand_chacha::ChaCha20Rng;
@@ -20,6 +22,15 @@ use validator_client::nymd::CosmWasmClient;
pub(crate) mod routes;
#[derive(Clone, Copy, Debug, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum MixnodeStatus {
Active, // in both the active set and the rewarded set
Standby, // only in the rewarded set
Inactive, // in neither the rewarded set nor the active set, but is bonded
NotFound, // doesn't even exist in the bonded set
}
pub struct ValidatorCacheRefresher<C> {
nymd_client: Client<C>,
cache: ValidatorCache,
@@ -157,6 +168,7 @@ impl ValidatorCache {
routes::get_gateways,
routes::get_active_mixnodes,
routes::get_rewarded_mixnodes,
routes::get_mixnode_status,
],
)
})
@@ -305,6 +317,47 @@ impl ValidatorCache {
}
}
pub async fn mixnode_status(&self, identity: IdentityKey) -> MixnodeStatus {
// it might not be the most optimal to possibly iterate the entire vector to find (or not)
// the relevant value. However, the vectors are relatively small (< 10_000 elements) and
// the implementation for active/rewarded sets might change soon so there's no point in premature optimisation
// with HashSets
let rewarded_mixnodes = &self.inner.rewarded_mixnodes.read().await.value;
let active_set_size = self
.inner
.current_mixnode_active_set_size
.load(Ordering::SeqCst) as usize;
// see if node is in the top active_set_size of rewarded nodes, i.e. it's active
if rewarded_mixnodes
.iter()
.take(active_set_size)
.any(|mix| mix.mix_node.identity_key == identity)
{
MixnodeStatus::Active
// see if it's in the bottom part of the rewarded set, i.e. it's in standby
} else if rewarded_mixnodes
.iter()
.skip(active_set_size)
.any(|mix| mix.mix_node.identity_key == identity)
{
MixnodeStatus::Standby
// if it's not in the rewarded set see if its bonded at all
} else if self
.inner
.mixnodes
.read()
.await
.value
.iter()
.any(|mix| mix.mix_node.identity_key == identity)
{
MixnodeStatus::Inactive
} else {
MixnodeStatus::NotFound
}
}
pub fn initialised(&self) -> bool {
self.inner.initialised.load(Ordering::Relaxed)
}
+17 -1
View File
@@ -1,10 +1,11 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::cache::ValidatorCache;
use crate::cache::{MixnodeStatus, ValidatorCache};
use mixnet_contract::{GatewayBond, MixNodeBond};
use rocket::serde::json::Json;
use rocket::State;
use serde::Serialize;
#[get("/mixnodes")]
pub(crate) async fn get_mixnodes(cache: &State<ValidatorCache>) -> Json<Vec<MixNodeBond>> {
@@ -25,3 +26,18 @@ pub(crate) async fn get_rewarded_mixnodes(cache: &State<ValidatorCache>) -> Json
pub(crate) async fn get_active_mixnodes(cache: &State<ValidatorCache>) -> Json<Vec<MixNodeBond>> {
Json(cache.active_mixnodes().await.value)
}
#[derive(Serialize)]
pub(crate) struct MixnodeStatusResponse {
status: MixnodeStatus,
}
#[get("/mixnode/<identity>/status")]
pub(crate) async fn get_mixnode_status(
cache: &State<ValidatorCache>,
identity: String,
) -> Json<MixnodeStatusResponse> {
Json(MixnodeStatusResponse {
status: cache.mixnode_status(identity).await,
})
}
+1 -1
View File
@@ -36,7 +36,7 @@ const DEFAULT_MINIMUM_TEST_ROUTES: usize = 1;
const DEFAULT_ROUTE_TEST_PACKETS: usize = 1000;
const DEFAULT_PER_NODE_TEST_PACKETS: usize = 3;
const DEFAULT_CACHE_INTERVAL: Duration = Duration::from_secs(5);
const DEFAULT_CACHE_INTERVAL: Duration = Duration::from_secs(30);
const DEFAULT_MONITOR_THRESHOLD: u8 = 60;
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]