Skip to content

Commit

Permalink
smoothing some rough edges
Browse files Browse the repository at this point in the history
  • Loading branch information
jstuczyn committed Dec 18, 2023
1 parent fd2a430 commit 7370164
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 80 deletions.
2 changes: 1 addition & 1 deletion nym-validator-rewarder/migrations/01_initial.sql
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ CREATE TABLE epoch_credential_issuance
rewarding_epoch_id INTEGER NOT NULL PRIMARY KEY REFERENCES rewarding_epoch (id),
starting_dkg_epoch INTEGER NOT NULL,
ending_dkg_epoch INTEGER NOT NULL,
total_issued_credentials INTEGER NOT NULL,
total_issued_partial_credentials INTEGER NOT NULL,
budget TEXT NOT NULL
);

Expand Down
5 changes: 1 addition & 4 deletions nym-validator-rewarder/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,14 @@ pub struct ConfigOverridableArgs {
#[clap(long)]
pub disable_block_signing_rewarding: bool,

#[clap(long)]
pub disable_block_scraper: bool,

#[clap(long)]
pub disable_credential_issuance_rewarding: bool,

#[clap(long)]
pub credential_monitor_run_interval: Option<humantime::Duration>,

#[clap(long)]
pub credential_monitor_min_validation: Option<u32>,
pub credential_monitor_min_validation: Option<usize>,

#[clap(long)]
pub credential_monitor_sampling_rate: Option<f64>,
Expand Down
16 changes: 3 additions & 13 deletions nym-validator-rewarder/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const DEFAULT_MIX_REWARDING_DENOM: &str = "unym";

const DEFAULT_EPOCH_DURATION: Duration = Duration::from_secs(60 * 60);
const DEFAULT_MONITOR_RUN_INTERVAL: Duration = Duration::from_secs(10 * 60);
const DEFAULT_MONITOR_MIN_VALIDATE: u32 = 10;
const DEFAULT_MONITOR_MIN_VALIDATE: usize = 10;
const DEFAULT_MONITOR_SAMPLING_RATE: f64 = 0.10;

/// Get default path to rewarder's config directory.
Expand Down Expand Up @@ -100,10 +100,7 @@ impl Config {
rewarding: Rewarding::default(),
block_signing: Default::default(),
issuance_monitor: IssuanceMonitor::default(),
nyxd_scraper: NyxdScraper {
enabled: true,
websocket_url,
},
nyxd_scraper: NyxdScraper { websocket_url },
base: Base {
upstream_nyxd: nyxd_url,
mnemonic,
Expand All @@ -121,10 +118,6 @@ impl Config {
}

pub fn ensure_is_valid(&self) -> Result<(), NymRewarderError> {
if self.block_signing.enabled && !self.nyxd_scraper.enabled {
return Err(NymRewarderError::BlockSigningRewardWithoutScraper);
}

self.rewarding.ratios.ensure_is_valid()?;
Ok(())
}
Expand Down Expand Up @@ -240,9 +233,6 @@ impl RewardingRatios {

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct NyxdScraper {
/// Specifies whether the chain scraper is enabled.
pub enabled: bool,

/// Url to the websocket endpoint of a validator, for example `wss://rpc.nymtech.net/websocket`
pub websocket_url: Url,
// TODO: debug with everything that's currently hardcoded in the scraper
Expand Down Expand Up @@ -270,7 +260,7 @@ pub struct IssuanceMonitor {

/// Defines the minimum number of credentials the monitor will validate
/// regardless of the sampling rate
pub min_validate_per_issuer: u32,
pub min_validate_per_issuer: usize,

/// The sampling rate of the issued credentials
pub sampling_rate: f64,
Expand Down
4 changes: 0 additions & 4 deletions nym-validator-rewarder/src/config/override.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ impl ConfigOverride for ConfigOverridableArgs {
config.block_signing.enabled = false
}

if self.disable_block_scraper {
config.nyxd_scraper.enabled = false
}

if self.disable_credential_issuance_rewarding {
config.issuance_monitor.enabled = false
}
Expand Down
3 changes: 0 additions & 3 deletions nym-validator-rewarder/src/config/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ min_validate_per_issuer = {{ issuance_monitor.min_validate_per_issuer }}
sampling_rate = {{ issuance_monitor.sampling_rate }}
[nyxd_scraper]
# Specifies whether the chain scraper is enabled.
enabled = {{ nyxd_scraper.enabled }}
# Url to the websocket endpoint of a validator, for example `wss://rpc.nymtech.net/websocket`
websocket_url = '{{ nyxd_scraper.websocket_url }}'
"#;
3 changes: 0 additions & 3 deletions nym-validator-rewarder/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,6 @@ pub enum NymRewarderError {
on_chain: String,
},

#[error("can't enable block signing rewarding without the block scraper")]
BlockSigningRewardWithoutScraper,

#[error("the current rewarder balance is insufficient to start the process. The epoch budget is: {} while we currently have {}. (the minimum is set to {})", .0.epoch_budget, .0.balance, .0.minimum)]
InsufficientRewarderBalance(Box<InsufficientBalance>),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use nym_credentials::coconut::bandwidth::BandwidthVoucher;
use nym_task::TaskClient;
use nym_validator_client::nym_api::{IssuedCredential, IssuedCredentialBody, NymApiClientExt};
use nym_validator_client::nyxd::Hash;
use std::cmp::max;
use std::collections::HashMap;
use std::sync::OnceLock;
use tokio::time::interval;
Expand Down Expand Up @@ -205,11 +206,14 @@ impl CredentialIssuanceMonitor {
let credential_range: Vec<_> = (first_id..first_id + total_issued).collect();
let issued = credential_range.len();

let sampled = if issued <= self.config.min_validate_per_issuer as usize {
let sampled = if issued <= self.config.min_validate_per_issuer {
credential_range
} else {
let mut rng = thread_rng();
let sample_size = (issued as f64 * self.config.sampling_rate) as usize;
let sample_size = max(
self.config.min_validate_per_issuer,
(issued as f64 * self.config.sampling_rate) as usize,
);
credential_range
.choose_multiple(&mut rng, sample_size)
.copied()
Expand All @@ -225,6 +229,7 @@ impl CredentialIssuanceMonitor {
epoch_id: EpochId,
issuer: CredentialIssuer,
) -> Result<RawOperatorResult, NymRewarderError> {
info!("checking the issuer's credentials...");
debug!("checking the issuer's credentials...");

let api_client = api_client(&issuer)?;
Expand Down Expand Up @@ -284,6 +289,7 @@ impl CredentialIssuanceMonitor {
}

async fn check_issuers(&mut self) -> Result<(), NymRewarderError> {
info!("checking credential issuers");
let epoch = self.nyxd_client.dkg_epoch().await?;
let issuers = self
.nyxd_client
Expand Down
17 changes: 7 additions & 10 deletions nym-validator-rewarder/src/rewarder/credential_issuance/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,23 +157,21 @@ pub(crate) struct MonitoringResultsInner {

impl From<MonitoringResultsInner> for CredentialIssuanceResults {
fn from(value: MonitoringResultsInner) -> Self {
// approximation!
// get the maximum number of issued credentials of all apis
// (we sum values if they cross dkg epochs)
let total_issued = value
.operators
.values()
.map(|o| {
o.per_epoch
let operator_issued: u32 = o
.per_epoch
.values()
.map(|e| e.issued_since_monitor_started)
.sum()
.sum();
operator_issued
})
.max()
.unwrap_or_default();
.sum();

CredentialIssuanceResults {
total_issued,
total_issued_partial_credentials: total_issued,
dkg_epochs: value.dkg_epochs,
api_runners: value
.operators
Expand Down Expand Up @@ -296,8 +294,7 @@ impl OperatorIssuing {
}

pub struct CredentialIssuanceResults {
// note: this is an approximation!
pub total_issued: u32,
pub total_issued_partial_credentials: u32,
pub dkg_epochs: Vec<u32>,
pub api_runners: Vec<OperatorIssuing>,
}
Expand Down
59 changes: 27 additions & 32 deletions nym-validator-rewarder/src/rewarder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ use nym_task::TaskManager;
use nym_validator_client::nyxd::{AccountId, Coin, Hash};
use nyxd_scraper::NyxdScraper;
use std::ops::Add;
use std::time::Duration;
use time::OffsetDateTime;
use tokio::pin;
use tokio::time::{interval_at, Instant};
use tracing::{error, info, instrument};
Expand Down Expand Up @@ -43,26 +41,28 @@ impl EpochRewards {
let mut amounts = Vec::new();

if let Some(signing) = &self.signing {
let mut signing_amounts = signing.rewarding_amounts(&self.signing_budget);
amounts.append(&mut signing_amounts);
for signing_amount in signing.rewarding_amounts(&self.signing_budget) {
if signing_amount.1[0].amount != 0 {
amounts.push(signing_amount)
}
}
}

if let Some(credentials) = &self.credentials {
let mut credentials_amounts = credentials.rewarding_amounts(&self.credentials_budget);
amounts.append(&mut credentials_amounts);
for credential_amount in credentials.rewarding_amounts(&self.credentials_budget) {
if credential_amount.1[0].amount != 0 {
amounts.push(credential_amount)
}
}
}

amounts
}
}

pub fn total_spent(&self) -> Coin {
let amount = self
.amounts()
.into_iter()
.map(|(_, amount)| amount[0].amount)
.sum();
Coin::new(amount, &self.total_budget.denom)
}
pub fn total_spent(amounts: &[(AccountId, Vec<Coin>)], denom: &str) -> Coin {
let amount = amounts.iter().map(|(_, amount)| amount[0].amount).sum();
Coin::new(amount, denom)
}

pub struct Rewarder {
Expand All @@ -77,12 +77,6 @@ pub struct Rewarder {

impl Rewarder {
pub async fn new(config: Config) -> Result<Self, NymRewarderError> {
let nyxd_scraper = if config.nyxd_scraper.enabled {
Some(NyxdScraper::new(config.scraper_config()).await?)
} else {
None
};

let nyxd_client = NyxdClient::new(&config)?;
let storage = RewarderStorage::init(&config.storage_paths.reward_history).await?;
let current_epoch = if let Some(last_epoch) = storage.load_last_rewarding_epoch().await? {
Expand All @@ -92,11 +86,10 @@ impl Rewarder {
};

let epoch_signing = if config.block_signing.enabled {
// safety: our config has been validated at load time to ensure that if block signing is enabled,
// so is the scraper
let nyxd_scraper = NyxdScraper::new(config.scraper_config()).await?;

Some(EpochSigning {
#[allow(clippy::unwrap_used)]
nyxd_scraper: nyxd_scraper.unwrap(),
nyxd_scraper,
nyxd_client: nyxd_client.clone(),
})
} else {
Expand Down Expand Up @@ -198,10 +191,12 @@ impl Rewarder {
})
}

#[instrument(skip(self))]
async fn send_rewards(
&self,
amounts: Vec<(AccountId, Vec<Coin>)>,
) -> Result<Hash, NymRewarderError> {
info!("sending rewards");
self.nyxd_client
.send_rewards(self.current_epoch, amounts)
.await
Expand All @@ -218,10 +213,16 @@ impl Rewarder {
}
};

let rewarding_result = self.send_rewards(rewards.amounts()).await;
let rewarding_amounts = rewards.amounts();
let total_spent = total_spent(
&rewarding_amounts,
&self.config.rewarding.epoch_budget.denom,
);

let rewarding_result = self.send_rewards(rewarding_amounts).await;
if let Err(err) = self
.storage
.save_rewarding_information(rewards, rewarding_result)
.save_rewarding_information(rewards, total_spent, rewarding_result)
.await
{
error!("failed to persist rewarding information: {err}")
Expand Down Expand Up @@ -249,12 +250,6 @@ impl Rewarder {
epoch_signing.nyxd_scraper.wait_for_startup_sync().await;
}

// rewarding epochs last from :00 to :00
// \/\/\/\/\/\/\/ TEMP TESTING!!!
self.current_epoch.end_time = OffsetDateTime::now_utc();
self.current_epoch.start_time = self.current_epoch.end_time - Duration::from_secs(60 * 60);
// ^^^^^^^^^^^ TEMP TESTING!!!

let until_end = self.current_epoch.until_end();

info!(
Expand Down
6 changes: 3 additions & 3 deletions nym-validator-rewarder/src/rewarder/storage/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl StorageManager {
epoch: i64,
starting_dkg_epoch: u32,
ending_dkg_epoch: u32,
total_issued_credentials: u32,
total_issued_partial_credentials: u32,
budget: String,
) -> Result<(), sqlx::Error> {
sqlx::query!(
Expand All @@ -122,15 +122,15 @@ impl StorageManager {
rewarding_epoch_id,
starting_dkg_epoch,
ending_dkg_epoch,
total_issued_credentials,
total_issued_partial_credentials,
budget
)
VALUES (?, ?, ?, ?, ?)
"#,
epoch,
starting_dkg_epoch,
ending_dkg_epoch,
total_issued_credentials,
total_issued_partial_credentials,
budget,
)
.execute(&self.connection_pool)
Expand Down
11 changes: 6 additions & 5 deletions nym-validator-rewarder/src/rewarder/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::error::NymRewarderError;
use crate::rewarder::epoch::Epoch;
use crate::rewarder::storage::manager::StorageManager;
use crate::rewarder::EpochRewards;
use nym_validator_client::nyxd::Hash;
use nym_validator_client::nyxd::{Coin, Hash};
use sqlx::ConnectOptions;
use std::fmt::Debug;
use std::path::Path;
Expand Down Expand Up @@ -58,6 +58,7 @@ impl RewarderStorage {
pub(crate) async fn save_rewarding_information(
&self,
reward: EpochRewards,
total_spent: Coin,
rewarding_tx: Result<Hash, NymRewarderError>,
) -> Result<(), NymRewarderError> {
info!("persisting reward details");
Expand All @@ -72,7 +73,7 @@ impl RewarderStorage {
.insert_rewarding_epoch(
reward.epoch,
reward.total_budget.to_string(),
reward.total_spent().to_string(),
total_spent.to_string(),
reward_tx,
reward_err,
)
Expand Down Expand Up @@ -118,13 +119,13 @@ impl RewarderStorage {
let dkg_epoch_start = reward
.credentials
.as_ref()
.map(|c| *c.dkg_epochs.first().unwrap())
.and_then(|c| c.dkg_epochs.first().copied())
.unwrap_or_default();
#[allow(clippy::unwrap_used)]
let dkg_epoch_end = reward
.credentials
.as_ref()
.map(|c| *c.dkg_epochs.last().unwrap())
.and_then(|c| c.dkg_epochs.last().copied())
.unwrap_or_default();

self.manager
Expand All @@ -135,7 +136,7 @@ impl RewarderStorage {
reward
.credentials
.as_ref()
.map(|c| c.total_issued)
.map(|c| c.total_issued_partial_credentials)
.unwrap_or_default(),
reward.credentials_budget.to_string(),
)
Expand Down

0 comments on commit 7370164

Please sign in to comment.