Files
nym/validator-api/src/cache/mod.rs
T
Jędrzej Stuczyński 020cad897d Feature/rust rewarding (#750)
* Calculating gas fees

* Ability to set custom fees

* Added extra test

* Removed commented code

* Moved all msg types to common contract crate

* Temporarily disabling get_tx method

* Finishing up nymd client API

* Comment fix

* Remaining fee values

* Some cleanup

* Removed needless borrow

* Fixed imports in contract tests

* Moved error types around

* New ValidatorClient

* Experiment with new type of defaults

* Removed dead module

* Dealt with unwrap

* Migrated mixnode to use new validator client

* Migrated gateway to use new validator client

* Mixnode and gateway adjustments

* More exported defaults

* Clients using new validator client

* Fixed mixnode upgrade

* Moved default values to a new crate

* Changed behaviour of validator client features

* Migrated basic functions of validator api

* Updated config + fixed startup

* Fixed wasm client build

* Integration with the explorer api

* Removed tokio dev dependency

* Needless borrow

* Fixex wasm client build

* Fixed tauri client build

* Needless borrows

* New tables for rewarding

* Updated cosmos-sdk version

* Removed reward-specific node status routes

* New rewarding-specific config entries

* Additional network defaults

* Initial periodic rewards from validator api

* Replaced print with log

* Filtering nodes with uptime > 0

* Additional failure logging statements

* Fixed operation ordering

* Adjusted next rewarding epoch determination

* Modified rewarding behaviour to keep track of rewarding in progress

* Improved error message on config load failure

* Additional log statement

* Adjusted rewarding gas limit calculation

* Made naming slightly more consistent

* Fixed incorrect parentheses placement

* Fixed fee calculation

* Cargo fmt

* Removed failed merge artifacts

* Introduced comment for any future reward modification

* typos

* Helper functions for the future

* Making @mfahampshire 's life easier

* Redesigned epoch + rewarding skipped epochs (if possible)

* Removed old merge artifacts

* Naming consistency

* Constraining arguments

* Removed unnecessary if branch

* Ignore monitor check for current epoch

* Additional checks for current epoch data

* Monitor threshold check

* cargo fmt

* Fixed post-merge issues in transactions.rs
2021-09-24 15:49:21 +01:00

164 lines
4.5 KiB
Rust

// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nymd_client::Client;
use anyhow::Result;
use config::defaults::VALIDATOR_API_VERSION;
use mixnet_contract::{GatewayBond, MixNodeBond};
use rocket::fairing::AdHoc;
use serde::Serialize;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use tokio::sync::RwLock;
use tokio::time;
use validator_client::nymd::CosmWasmClient;
pub(crate) mod routes;
pub struct ValidatorCacheRefresher<C> {
nymd_client: Client<C>,
cache: ValidatorCache,
caching_interval: Duration,
}
#[derive(Clone)]
pub struct ValidatorCache {
inner: Arc<ValidatorCacheInner>,
}
struct ValidatorCacheInner {
initialised: AtomicBool,
mixnodes: RwLock<Cache<Vec<MixNodeBond>>>,
gateways: RwLock<Cache<Vec<GatewayBond>>>,
}
#[derive(Default, Serialize, Clone)]
pub struct Cache<T> {
value: T,
as_at: u64,
}
impl<T: Clone> Cache<T> {
fn set(&mut self, value: T) {
self.value = value;
self.as_at = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
}
pub fn into_inner(self) -> T {
self.value
}
}
impl<C> ValidatorCacheRefresher<C> {
pub(crate) fn new(
nymd_client: Client<C>,
caching_interval: Duration,
cache: ValidatorCache,
) -> Self {
ValidatorCacheRefresher {
nymd_client,
cache,
caching_interval,
}
}
async fn refresh_cache(&self) -> Result<()>
where
C: CosmWasmClient + Sync,
{
let (mixnodes, gateways) = tokio::try_join!(
self.nymd_client.get_mixnodes(),
self.nymd_client.get_gateways()
)?;
info!(
"Updating validator cache. There are {} mixnodes and {} gateways",
mixnodes.len(),
gateways.len()
);
self.cache.update_cache(mixnodes, gateways).await;
Ok(())
}
pub(crate) async fn run(&self)
where
C: CosmWasmClient + Sync,
{
let mut interval = time::interval(self.caching_interval);
loop {
interval.tick().await;
if let Err(err) = self.refresh_cache().await {
error!("Failed to refresh validator cache - {}", err);
} else {
// relaxed memory ordering is fine here. worst case scenario network monitor
// will just have to wait for an additional backoff to see the change.
// And so this will not really incur any performance penalties by setting it every loop iteration
self.cache.inner.initialised.store(true, Ordering::Relaxed)
}
}
}
}
impl ValidatorCache {
fn new() -> Self {
ValidatorCache {
inner: Arc::new(ValidatorCacheInner::new()),
}
}
pub fn stage() -> AdHoc {
AdHoc::on_ignite("Validator Cache Stage", |rocket| async {
rocket.manage(Self::new()).mount(
// this format! is so ugly...
format!("/{}", VALIDATOR_API_VERSION),
routes![routes::get_mixnodes, routes::get_gateways],
)
})
}
async fn update_cache(&self, mixnodes: Vec<MixNodeBond>, gateways: Vec<GatewayBond>) {
self.inner.mixnodes.write().await.set(mixnodes);
self.inner.gateways.write().await.set(gateways);
}
pub async fn mixnodes(&self) -> Cache<Vec<MixNodeBond>> {
self.inner.mixnodes.read().await.clone()
}
pub async fn gateways(&self) -> Cache<Vec<GatewayBond>> {
self.inner.gateways.read().await.clone()
}
pub fn initialised(&self) -> bool {
self.inner.initialised.load(Ordering::Relaxed)
}
pub(crate) async fn wait_for_initial_values(&self) {
let initialisation_backoff = Duration::from_secs(5);
loop {
if self.initialised() {
break;
} else {
debug!("Validator cache hasn't been initialised yet - waiting for {:?} before trying again", initialisation_backoff);
tokio::time::sleep(initialisation_backoff).await;
}
}
}
}
impl ValidatorCacheInner {
fn new() -> Self {
ValidatorCacheInner {
initialised: AtomicBool::new(false),
mixnodes: RwLock::new(Cache::default()),
gateways: RwLock::new(Cache::default()),
}
}
}