From 5c753c07946042e217f7e8a209f0cce6a4b67b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 23 Jan 2024 13:53:31 +0000 Subject: [PATCH 1/8] added new whitelist entries to the config --- nym-validator-rewarder/src/config/mod.rs | 20 +++++++++++++++---- nym-validator-rewarder/src/config/template.rs | 14 ++++++++++++- nym-validator-rewarder/src/rewarder/mod.rs | 2 +- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/nym-validator-rewarder/src/config/mod.rs b/nym-validator-rewarder/src/config/mod.rs index 9003d32ceb..5460afa095 100644 --- a/nym-validator-rewarder/src/config/mod.rs +++ b/nym-validator-rewarder/src/config/mod.rs @@ -9,7 +9,7 @@ use nym_config::{ must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, }; -use nym_validator_client::nyxd::Coin; +use nym_validator_client::nyxd::{AccountId, Coin}; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DisplayFromStr}; use std::io; @@ -238,19 +238,26 @@ pub struct NyxdScraper { // TODO: debug with everything that's currently hardcoded in the scraper } -#[derive(Debug, Clone, Deserialize, Serialize, Copy)] +#[derive(Debug, Clone, Deserialize, Serialize)] pub struct BlockSigning { /// Specifies whether credential issuance for block signing is enabled. pub enabled: bool, + + /// List of validators that will receive rewards for block signing. + /// If not on the list, the validator will be treated as if it had 0 voting power. + pub whitelist: Vec, } impl Default for BlockSigning { fn default() -> Self { - BlockSigning { enabled: true } + BlockSigning { + enabled: true, + whitelist: vec![], + } } } -#[derive(Debug, Clone, Deserialize, Serialize, Copy)] +#[derive(Debug, Clone, Deserialize, Serialize)] pub struct IssuanceMonitor { /// Specifies whether credential issuance monitoring (and associated rewards) are enabled. pub enabled: bool, @@ -264,6 +271,10 @@ pub struct IssuanceMonitor { /// The sampling rate of the issued credentials pub sampling_rate: f64, + + /// List of validators that will receive rewards for credential issuance. + /// If not on the list, the validator will be treated as if it hadn't issued a single credential. + pub whitelist: Vec, } impl Default for IssuanceMonitor { @@ -273,6 +284,7 @@ impl Default for IssuanceMonitor { run_interval: DEFAULT_MONITOR_RUN_INTERVAL, min_validate_per_issuer: DEFAULT_MONITOR_MIN_VALIDATE, sampling_rate: DEFAULT_MONITOR_SAMPLING_RATE, + whitelist: vec![], } } } diff --git a/nym-validator-rewarder/src/config/template.rs b/nym-validator-rewarder/src/config/template.rs index 17ba1f9649..89ad6ecea4 100644 --- a/nym-validator-rewarder/src/config/template.rs +++ b/nym-validator-rewarder/src/config/template.rs @@ -40,7 +40,13 @@ credential_verification = {{ rewarding.ratios.credential_verification }} [block_signing] # Specifies whether credential issuance for block signing is enabled. enabled = {{ block_signing.enabled }} - + +# List of validators that will receive rewards for block signing. +# If not on the list, the validator will be treated as if it had 0 voting power. +whitelist = [ + # needs to be manually populated +] + [issuance_monitor] # Specifies whether credential issuance monitoring (and associated rewards) are enabled. @@ -54,6 +60,12 @@ min_validate_per_issuer = {{ issuance_monitor.min_validate_per_issuer }} # The sampling rate of the issued credentials sampling_rate = {{ issuance_monitor.sampling_rate }} + +# List of validators that will receive rewards for credential issuance. +# If not on the list, the validator will be treated as if it hadn't issued a single credential. +whitelist = [ + # needs to be manually populated +] [nyxd_scraper] # Url to the websocket endpoint of a validator, for example `wss://rpc.nymtech.net/websocket` diff --git a/nym-validator-rewarder/src/rewarder/mod.rs b/nym-validator-rewarder/src/rewarder/mod.rs index f58b3ce63f..da937d0fc1 100644 --- a/nym-validator-rewarder/src/rewarder/mod.rs +++ b/nym-validator-rewarder/src/rewarder/mod.rs @@ -239,7 +239,7 @@ impl Rewarder { if let Some(ref credential_issuance) = self.credential_issuance { credential_issuance.start_monitor( - self.config.issuance_monitor, + self.config.issuance_monitor.clone(), self.nyxd_client.clone(), task_manager.subscribe(), ); From f6c24412c0df54898cf845275b685aeb3ee38a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 23 Jan 2024 13:54:19 +0000 Subject: [PATCH 2/8] checking for empty whitelists --- nym-validator-rewarder/src/error.rs | 6 ++++++ nym-validator-rewarder/src/rewarder/mod.rs | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/nym-validator-rewarder/src/error.rs b/nym-validator-rewarder/src/error.rs index b6dae63537..cf4dd033b0 100644 --- a/nym-validator-rewarder/src/error.rs +++ b/nym-validator-rewarder/src/error.rs @@ -156,6 +156,12 @@ pub enum NymRewarderError { #[error("the scraper websocket endpoint hasn't been provided")] UnavailableWebsocketUrl, + + #[error("block signing rewarding is enabled, but the validator whitelist is empty")] + EmptyBlockSigningWhitelist, + + #[error("credential issuance rewarding is enabled, but the validator whitelist is empty")] + EmptyCredentialIssuanceWhitelist, } #[derive(Debug)] diff --git a/nym-validator-rewarder/src/rewarder/mod.rs b/nym-validator-rewarder/src/rewarder/mod.rs index da937d0fc1..16ed92bf8b 100644 --- a/nym-validator-rewarder/src/rewarder/mod.rs +++ b/nym-validator-rewarder/src/rewarder/mod.rs @@ -86,6 +86,10 @@ impl Rewarder { }; let epoch_signing = if config.block_signing.enabled { + if config.block_signing.whitelist.is_empty() { + return Err(NymRewarderError::EmptyBlockSigningWhitelist); + } + let nyxd_scraper = NyxdScraper::new(config.scraper_config()).await?; Some(EpochSigning { @@ -97,6 +101,10 @@ impl Rewarder { }; let credential_issuance = if config.issuance_monitor.enabled { + if config.block_signing.whitelist.is_empty() { + return Err(NymRewarderError::EmptyCredentialIssuanceWhitelist); + } + Some(CredentialIssuance::new(current_epoch, &nyxd_client).await?) } else { None From 387933a975a5ca30c1585971780d2729b3bc2d47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 23 Jan 2024 14:41:15 +0000 Subject: [PATCH 3/8] using whitelisting information for rewarding --- .../migrations/01_initial.sql | 10 +++++--- nym-validator-rewarder/src/config/template.rs | 5 ++-- .../src/rewarder/block_signing/mod.rs | 24 +++++++++++++++--- .../src/rewarder/block_signing/types.rs | 10 +++++++- .../src/rewarder/credential_issuance/mod.rs | 5 +++- .../rewarder/credential_issuance/monitor.rs | 4 +++ .../src/rewarder/credential_issuance/types.rs | 25 ++++++++++++++++--- nym-validator-rewarder/src/rewarder/mod.rs | 23 ++++++++++------- .../src/rewarder/storage/manager.rs | 10 ++++++-- .../src/rewarder/storage/mod.rs | 2 ++ 10 files changed, 91 insertions(+), 27 deletions(-) diff --git a/nym-validator-rewarder/migrations/01_initial.sql b/nym-validator-rewarder/migrations/01_initial.sql index b7b7b9f22f..2dbfb40e35 100644 --- a/nym-validator-rewarder/migrations/01_initial.sql +++ b/nym-validator-rewarder/migrations/01_initial.sql @@ -27,6 +27,7 @@ CREATE TABLE block_signing_reward rewarding_epoch_id INTEGER NOT NULL REFERENCES rewarding_epoch (id), validator_consensus_address TEXT NOT NULL, operator_account TEXT NOT NULL, + whitelisted BOOLEAN NOT NULL, amount TEXT NOT NULL, voting_power BIGINT NOT NULL, voting_power_share TEXT NOT NULL, @@ -38,11 +39,11 @@ CREATE TABLE block_signing_reward 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, + 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_partial_credentials INTEGER NOT NULL, - budget TEXT NOT NULL + budget TEXT NOT NULL ); CREATE TABLE malformed_credential @@ -56,6 +57,7 @@ CREATE TABLE credential_issuance_reward rewarding_epoch_id INTEGER NOT NULL REFERENCES rewarding_epoch (id), operator_account TEXT NOT NULL, amount TEXT NOT NULL, + whitelisted BOOLEAN NOT NULL, api_endpoint TEXT NOT NULL, issued_partial_credentials INTEGER NOT NULL, issued_credentials_share TEXT NOT NULL, diff --git a/nym-validator-rewarder/src/config/template.rs b/nym-validator-rewarder/src/config/template.rs index 89ad6ecea4..89eb22b933 100644 --- a/nym-validator-rewarder/src/config/template.rs +++ b/nym-validator-rewarder/src/config/template.rs @@ -44,7 +44,8 @@ enabled = {{ block_signing.enabled }} # List of validators that will receive rewards for block signing. # If not on the list, the validator will be treated as if it had 0 voting power. whitelist = [ - # needs to be manually populated + # needs to be manually populated; expects nvalcons1... addresses. + # you can get them from, for example, `/cosmos/base/tendermint/v1beta1/validatorsets/latest` endpoint ] @@ -64,7 +65,7 @@ sampling_rate = {{ issuance_monitor.sampling_rate }} # List of validators that will receive rewards for credential issuance. # If not on the list, the validator will be treated as if it hadn't issued a single credential. whitelist = [ - # needs to be manually populated + # needs to be manually populated; expects n1... addresses ] [nyxd_scraper] diff --git a/nym-validator-rewarder/src/rewarder/block_signing/mod.rs b/nym-validator-rewarder/src/rewarder/block_signing/mod.rs index 4fcc75bc66..b87c6efaef 100644 --- a/nym-validator-rewarder/src/rewarder/block_signing/mod.rs +++ b/nym-validator-rewarder/src/rewarder/block_signing/mod.rs @@ -6,18 +6,19 @@ use crate::rewarder::block_signing::types::{EpochSigningResults, RawValidatorRes use crate::rewarder::epoch::Epoch; use crate::rewarder::nyxd_client::NyxdClient; use nym_validator_client::nyxd::module_traits::staking; -use nym_validator_client::nyxd::PageRequest; +use nym_validator_client::nyxd::{AccountId, PageRequest}; use nyxd_scraper::NyxdScraper; use std::cmp::min; use std::collections::HashMap; use std::ops::Range; -use tracing::info; +use tracing::{debug, info, warn}; pub(crate) mod types; pub struct EpochSigning { pub(crate) nyxd_client: NyxdClient, pub(crate) nyxd_scraper: NyxdScraper, + pub(crate) whitelist: Vec, } impl EpochSigning { @@ -116,14 +117,29 @@ impl EpochSigning { else { continue; }; - total_vp += vp; + + let cons_address = &validator.consensus_address; + // if this validator is NOT whitelisted, do not increase the total VP + let whitelisted = if let Ok(parsed) = cons_address.parse() { + if self.whitelist.contains(&parsed) { + debug!("{cons_address} is on the whitelist"); + total_vp += vp; + true + } else { + warn!("{cons_address} is not a valid consensus address"); + false + } + } else { + debug!("{cons_address} is not on the whitelist"); + false + }; let signed = self .nyxd_scraper .storage .get_signed_between_times(&validator.consensus_address, epoch_start, epoch_end) .await?; - signed_in_epoch.insert(validator, RawValidatorResult::new(signed, vp)); + signed_in_epoch.insert(validator, RawValidatorResult::new(signed, vp, whitelisted)); } let total = self diff --git a/nym-validator-rewarder/src/rewarder/block_signing/types.rs b/nym-validator-rewarder/src/rewarder/block_signing/types.rs index bd28b2f49d..3a814b0d04 100644 --- a/nym-validator-rewarder/src/rewarder/block_signing/types.rs +++ b/nym-validator-rewarder/src/rewarder/block_signing/types.rs @@ -15,6 +15,7 @@ pub struct ValidatorSigning { pub validator: models::Validator, pub staking_details: staking::Validator, pub operator_account: AccountId, + pub whitelisted: bool, pub voting_power_at_epoch_start: i64, pub voting_power_ratio: Decimal, @@ -33,6 +34,10 @@ impl ValidatorSigning { } pub fn reward_amount(&self, signing_budget: &Coin) -> Coin { + if !self.whitelisted { + return Coin::new(0, &signing_budget.denom); + } + let amount = Uint128::new(signing_budget.amount) * self.ratio_signed * self.voting_power_ratio; @@ -51,13 +56,15 @@ pub struct EpochSigningResults { pub struct RawValidatorResult { pub signed_blocks: i32, pub voting_power: i64, + pub whitelisted: bool, } impl RawValidatorResult { - pub fn new(signed_blocks: i32, voting_power: i64) -> Self { + pub fn new(signed_blocks: i32, voting_power: i64, whitelisted: bool) -> Self { Self { signed_blocks, voting_power, + whitelisted, } } } @@ -110,6 +117,7 @@ impl EpochSigningResults { validator, staking_details, operator_account, + whitelisted: raw_results.whitelisted, voting_power_at_epoch_start: raw_results.voting_power, voting_power_ratio, signed_blocks: raw_results.signed_blocks, diff --git a/nym-validator-rewarder/src/rewarder/credential_issuance/mod.rs b/nym-validator-rewarder/src/rewarder/credential_issuance/mod.rs index 5807a60dec..7102ac2e69 100644 --- a/nym-validator-rewarder/src/rewarder/credential_issuance/mod.rs +++ b/nym-validator-rewarder/src/rewarder/credential_issuance/mod.rs @@ -8,6 +8,7 @@ use crate::rewarder::credential_issuance::types::{CredentialIssuanceResults, Mon use crate::rewarder::epoch::Epoch; use crate::rewarder::nyxd_client::NyxdClient; use nym_task::TaskClient; +use nym_validator_client::nyxd::AccountId; use tracing::info; mod monitor; @@ -21,9 +22,11 @@ impl CredentialIssuance { pub(crate) async fn new( epoch: Epoch, nyxd_client: &NyxdClient, + whitelist: &[AccountId], ) -> Result { Ok(CredentialIssuance { - monitoring_results: MonitoringResults::new_initial(epoch, nyxd_client).await?, + monitoring_results: MonitoringResults::new_initial(epoch, nyxd_client, whitelist) + .await?, }) } diff --git a/nym-validator-rewarder/src/rewarder/credential_issuance/monitor.rs b/nym-validator-rewarder/src/rewarder/credential_issuance/monitor.rs index 884a63b9fe..96bdef6aae 100644 --- a/nym-validator-rewarder/src/rewarder/credential_issuance/monitor.rs +++ b/nym-validator-rewarder/src/rewarder/credential_issuance/monitor.rs @@ -235,12 +235,15 @@ impl CredentialIssuanceMonitor { let api_client = api_client(&issuer)?; let epoch_credentials = api_client.epoch_credentials(epoch_id).await?; + let whitelisted = self.config.whitelist.contains(&issuer.operator_account); + let Some(first_id) = epoch_credentials.first_epoch_credential_id else { // no point in doing anything more - if they haven't issued anything, there's nothing to verify debug!("no credentials issued this epoch",); return Ok(RawOperatorResult::new_empty( issuer.operator_account, issuer.api_runner, + whitelisted, )); }; trace!("issued credentials: {epoch_credentials:?}"); @@ -283,6 +286,7 @@ impl CredentialIssuanceMonitor { Ok(RawOperatorResult { operator_account: issuer.operator_account, api_runner: issuer.api_runner, + whitelisted, issued_credentials: epoch_credentials.total_issued, validated_credentials: sampled, }) diff --git a/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs b/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs index e6f76a10ae..f701f4bc42 100644 --- a/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs +++ b/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs @@ -25,6 +25,7 @@ impl MonitoringResults { pub(crate) async fn new_initial( initial_epoch: Epoch, nyxd_client: &NyxdClient, + whitelist: &[AccountId], ) -> Result { let epoch = nyxd_client.dkg_epoch().await?; let issuers = nyxd_client.get_credential_issuers(epoch.epoch_id).await?; @@ -36,6 +37,7 @@ impl MonitoringResults { let mut raw_issuer = RawOperatorIssuing { api_runner: issuer.api_runner.clone(), runner_account: issuer.operator_account.clone(), + whitelisted: whitelist.contains(&issuer.operator_account), per_epoch: Default::default(), }; @@ -132,6 +134,7 @@ impl MonitoringResults { RawOperatorIssuing { api_runner: result.api_runner.clone(), runner_account: result.runner_account.clone(), + whitelisted: result.whitelisted, per_epoch: kept_epoch, }, ); @@ -187,6 +190,7 @@ impl From for CredentialIssuanceResults { issued_credentials: runner.issued_credentials(), validated_credentials: runner.validated_credentials(), api_runner: runner.api_runner, + whitelisted: runner.whitelisted, runner_account: runner.runner_account, } }) @@ -212,6 +216,7 @@ impl MonitoringResultsInner { pub(crate) struct RawOperatorResult { pub(crate) operator_account: AccountId, pub(crate) api_runner: String, + pub(crate) whitelisted: bool, // how many credentials the operator claims to have issued in **TOTAL** in this **DKG** epoch pub(crate) issued_credentials: u32, @@ -219,10 +224,15 @@ pub(crate) struct RawOperatorResult { } impl RawOperatorResult { - pub(crate) fn new_empty(operator_account: AccountId, api_runner: String) -> RawOperatorResult { + pub(crate) fn new_empty( + operator_account: AccountId, + api_runner: String, + whitelisted: bool, + ) -> RawOperatorResult { RawOperatorResult { operator_account, api_runner, + whitelisted, issued_credentials: 0, validated_credentials: Default::default(), } @@ -232,6 +242,7 @@ impl RawOperatorResult { pub struct RawOperatorIssuing { pub api_runner: String, pub runner_account: AccountId, + pub whitelisted: bool, pub per_epoch: HashMap, } @@ -243,6 +254,7 @@ impl RawOperatorIssuing { RawOperatorIssuing { api_runner: raw_result.api_runner, runner_account: raw_result.operator_account, + whitelisted: raw_result.whitelisted, per_epoch, } } @@ -278,6 +290,7 @@ impl IssuedEpochCredentials { pub struct OperatorIssuing { pub api_runner: String, + pub whitelisted: bool, pub runner_account: AccountId, pub issued_ratio: Decimal, @@ -286,10 +299,14 @@ pub struct OperatorIssuing { } impl OperatorIssuing { - pub fn reward_amount(&self, signing_budget: &Coin) -> Coin { - let amount = Uint128::new(signing_budget.amount) * self.issued_ratio; + pub fn reward_amount(&self, issuance_budget: &Coin) -> Coin { + if !self.whitelisted { + return Coin::new(0, &issuance_budget.denom); + } - Coin::new(amount.u128(), &signing_budget.denom) + let amount = Uint128::new(issuance_budget.amount) * self.issued_ratio; + + Coin::new(amount.u128(), &issuance_budget.denom) } } diff --git a/nym-validator-rewarder/src/rewarder/mod.rs b/nym-validator-rewarder/src/rewarder/mod.rs index 16ed92bf8b..f586167c09 100644 --- a/nym-validator-rewarder/src/rewarder/mod.rs +++ b/nym-validator-rewarder/src/rewarder/mod.rs @@ -41,17 +41,19 @@ impl EpochRewards { let mut amounts = Vec::new(); if let Some(signing) = &self.signing { - for signing_amount in signing.rewarding_amounts(&self.signing_budget) { - if signing_amount.1[0].amount != 0 { - amounts.push(signing_amount) + for (account, signing_amount) in signing.rewarding_amounts(&self.signing_budget) { + if signing_amount[0].amount != 0 { + amounts.push((account, signing_amount)) } } } if let Some(credentials) = &self.credentials { - for credential_amount in credentials.rewarding_amounts(&self.credentials_budget) { - if credential_amount.1[0].amount != 0 { - amounts.push(credential_amount) + for (account, credential_amount) in + credentials.rewarding_amounts(&self.credentials_budget) + { + if credential_amount[0].amount != 0 { + amounts.push((account, credential_amount)) } } } @@ -86,7 +88,8 @@ impl Rewarder { }; let epoch_signing = if config.block_signing.enabled { - if config.block_signing.whitelist.is_empty() { + let whitelist = config.block_signing.whitelist.clone(); + if whitelist.is_empty() { return Err(NymRewarderError::EmptyBlockSigningWhitelist); } @@ -95,17 +98,19 @@ impl Rewarder { Some(EpochSigning { nyxd_scraper, nyxd_client: nyxd_client.clone(), + whitelist, }) } else { None }; let credential_issuance = if config.issuance_monitor.enabled { - if config.block_signing.whitelist.is_empty() { + let whitelist = &config.issuance_monitor.whitelist; + if whitelist.is_empty() { return Err(NymRewarderError::EmptyCredentialIssuanceWhitelist); } - Some(CredentialIssuance::new(current_epoch, &nyxd_client).await?) + Some(CredentialIssuance::new(current_epoch, &nyxd_client, whitelist).await?) } else { None }; diff --git a/nym-validator-rewarder/src/rewarder/storage/manager.rs b/nym-validator-rewarder/src/rewarder/storage/manager.rs index 5d5ab191f8..b8f84bbd18 100644 --- a/nym-validator-rewarder/src/rewarder/storage/manager.rs +++ b/nym-validator-rewarder/src/rewarder/storage/manager.rs @@ -74,6 +74,7 @@ impl StorageManager { epoch: i64, consensus_address: String, operator_account: String, + whitelisted: bool, amount: String, voting_power: i64, voting_power_share: String, @@ -86,16 +87,18 @@ impl StorageManager { rewarding_epoch_id, validator_consensus_address, operator_account, + whitelisted, amount, voting_power, voting_power_share, signed_blocks, signed_blocks_percent - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) "#, epoch, consensus_address, operator_account, + whitelisted, amount, voting_power, voting_power_share, @@ -144,6 +147,7 @@ impl StorageManager { &self, epoch: i64, operator_account: String, + whitelisted: bool, amount: String, api_endpoint: String, issued_partial_credentials: u32, @@ -155,15 +159,17 @@ impl StorageManager { INSERT INTO credential_issuance_reward ( rewarding_epoch_id, operator_account, + whitelisted, amount, api_endpoint, issued_partial_credentials, issued_credentials_share, validated_issued_credentials - ) VALUES (?, ?, ?, ?, ?, ?, ?) + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) "#, epoch, operator_account, + whitelisted, amount, api_endpoint, issued_partial_credentials, diff --git a/nym-validator-rewarder/src/rewarder/storage/mod.rs b/nym-validator-rewarder/src/rewarder/storage/mod.rs index aada9ef5dd..0c35fb0400 100644 --- a/nym-validator-rewarder/src/rewarder/storage/mod.rs +++ b/nym-validator-rewarder/src/rewarder/storage/mod.rs @@ -104,6 +104,7 @@ impl RewarderStorage { epoch_id, validator.validator.consensus_address, validator.operator_account.to_string(), + validator.whitelisted, reward_amount, validator.voting_power_at_epoch_start, validator.voting_power_ratio.to_string(), @@ -152,6 +153,7 @@ impl RewarderStorage { .insert_rewarding_epoch_credential_issuance_reward( epoch_id, api_runner.runner_account.to_string(), + api_runner.whitelisted, reward_amount, api_runner.api_runner, api_runner.issued_credentials, From 6cacc53e5a25c0c2913fad683e84c31a90df1737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 23 Jan 2024 14:43:46 +0000 Subject: [PATCH 4/8] resolved old todo --- nym-validator-rewarder/src/config/mod.rs | 2 +- nym-validator-rewarder/src/error.rs | 3 ++- nym-validator-rewarder/src/main.rs | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/nym-validator-rewarder/src/config/mod.rs b/nym-validator-rewarder/src/config/mod.rs index 5460afa095..bf83f15407 100644 --- a/nym-validator-rewarder/src/config/mod.rs +++ b/nym-validator-rewarder/src/config/mod.rs @@ -225,7 +225,7 @@ impl Default for RewardingRatios { impl RewardingRatios { pub fn ensure_is_valid(&self) -> Result<(), NymRewarderError> { if self.block_signing + self.credential_verification + self.credential_issuance != 1.0 { - todo!() + return Err(NymRewarderError::InvalidRewardingRatios { ratios: *self }); } Ok(()) } diff --git a/nym-validator-rewarder/src/error.rs b/nym-validator-rewarder/src/error.rs index cf4dd033b0..3d00f0324d 100644 --- a/nym-validator-rewarder/src/error.rs +++ b/nym-validator-rewarder/src/error.rs @@ -1,6 +1,7 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only +use crate::config::RewardingRatios; use nym_coconut::CoconutError; use nym_validator_client::nym_api::error::NymAPIError; use nym_validator_client::nyxd::error::NyxdError; @@ -50,7 +51,7 @@ pub enum NymRewarderError { NyxdFailure(#[from] NyxdError), #[error("the provided rewarding ratios don't add up to 1. ratios: {ratios:?}")] - InvalidRewardingRatios { ratios: Vec }, + InvalidRewardingRatios { ratios: RewardingRatios }, #[error("chain scraping failure: {source}")] ScraperFailure { diff --git a/nym-validator-rewarder/src/main.rs b/nym-validator-rewarder/src/main.rs index fb03008a9a..eb513124d1 100644 --- a/nym-validator-rewarder/src/main.rs +++ b/nym-validator-rewarder/src/main.rs @@ -1,8 +1,10 @@ -// Copyright 2023 - Nym Technologies SA +// Copyright 2023-2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only #![warn(clippy::expect_used)] #![warn(clippy::unwrap_used)] +#![warn(clippy::todo)] +#![warn(clippy::dbg_macro)] use crate::cli::Cli; use clap::{crate_name, crate_version, Parser}; From 3ad6a31e1f6273b69f83619cd8ff4cb957c8d5a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 23 Jan 2024 14:52:38 +0000 Subject: [PATCH 5/8] don't increment total issued credentials from not whitelisted nodes --- .../src/rewarder/credential_issuance/types.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs b/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs index f701f4bc42..135788ff23 100644 --- a/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs +++ b/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs @@ -160,18 +160,20 @@ pub(crate) struct MonitoringResultsInner { impl From for CredentialIssuanceResults { fn from(value: MonitoringResultsInner) -> Self { - let total_issued = value - .operators - .values() - .map(|o| { - let operator_issued: u32 = o + let mut total_issued = 0; + + for operator in value.operators.values() { + // if this validator is NOT whitelisted, do not increase the total VP + if operator.whitelisted { + let operator_issued: u32 = operator .per_epoch .values() .map(|e| e.issued_since_monitor_started) .sum(); - operator_issued - }) - .sum(); + + total_issued += operator_issued + } + } CredentialIssuanceResults { total_issued_partial_credentials: total_issued, From 4ac25aef4d6ebed4e43e144219b45d710f082c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 23 Jan 2024 14:54:41 +0000 Subject: [PATCH 6/8] setting 0 ratios for not whitelisted runners --- nym-validator-rewarder/src/rewarder/block_signing/types.rs | 6 +++++- .../src/rewarder/credential_issuance/types.rs | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/nym-validator-rewarder/src/rewarder/block_signing/types.rs b/nym-validator-rewarder/src/rewarder/block_signing/types.rs index 3a814b0d04..f66cae9624 100644 --- a/nym-validator-rewarder/src/rewarder/block_signing/types.rs +++ b/nym-validator-rewarder/src/rewarder/block_signing/types.rs @@ -100,7 +100,11 @@ impl EpochSigningResults { let vp: u64 = raw_results.voting_power.try_into().unwrap_or_default(); let signed: u64 = raw_results.signed_blocks.try_into().unwrap_or_default(); - let voting_power_ratio = Decimal::from_ratio(vp, total_vp_u64); + let voting_power_ratio = if raw_results.whitelisted { + Decimal::from_ratio(vp, total_vp_u64) + } else { + Decimal::zero() + }; debug_assert!(signed <= blocks_u64); let ratio_signed = Decimal::from_ratio(signed, blocks_u64); diff --git a/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs b/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs index 135788ff23..aac01166ff 100644 --- a/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs +++ b/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs @@ -163,7 +163,7 @@ impl From for CredentialIssuanceResults { let mut total_issued = 0; for operator in value.operators.values() { - // if this validator is NOT whitelisted, do not increase the total VP + // if this validator is NOT whitelisted, do not increase the total issued credentials if operator.whitelisted { let operator_issued: u32 = operator .per_epoch @@ -182,7 +182,7 @@ impl From for CredentialIssuanceResults { .operators .into_values() .map(|runner| { - let issued_ratio = if total_issued == 0 { + let issued_ratio = if total_issued == 0 || !runner.whitelisted { Decimal::zero() } else { Decimal::from_ratio(runner.issued_credentials(), total_issued) From f32ea17de59bd0d3f12fd80aff4560e21e1e3faa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 23 Jan 2024 15:05:53 +0000 Subject: [PATCH 7/8] disabled credential issuance by default --- nym-validator-rewarder/src/config/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nym-validator-rewarder/src/config/mod.rs b/nym-validator-rewarder/src/config/mod.rs index bf83f15407..49571394ad 100644 --- a/nym-validator-rewarder/src/config/mod.rs +++ b/nym-validator-rewarder/src/config/mod.rs @@ -280,7 +280,7 @@ pub struct IssuanceMonitor { impl Default for IssuanceMonitor { fn default() -> Self { IssuanceMonitor { - enabled: true, + enabled: false, run_interval: DEFAULT_MONITOR_RUN_INTERVAL, min_validate_per_issuer: DEFAULT_MONITOR_MIN_VALIDATE, sampling_rate: DEFAULT_MONITOR_SAMPLING_RATE, From c8f38ae785a34692c50afe5efdc3ea3248852be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 23 Jan 2024 15:10:53 +0000 Subject: [PATCH 8/8] added whitelisting information in logs --- nym-validator-rewarder/src/rewarder/block_signing/types.rs | 5 +++-- .../src/rewarder/credential_issuance/types.rs | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/nym-validator-rewarder/src/rewarder/block_signing/types.rs b/nym-validator-rewarder/src/rewarder/block_signing/types.rs index f66cae9624..8cf31a5ba5 100644 --- a/nym-validator-rewarder/src/rewarder/block_signing/types.rs +++ b/nym-validator-rewarder/src/rewarder/block_signing/types.rs @@ -141,10 +141,11 @@ impl EpochSigningResults { .iter() .inspect(|v| { info!( - "validator {} will receive {} at address {} for block signing work", + "validator {} will receive {} at address {} for block signing work (whitelisted: {})", v.moniker(), v.reward_amount(budget), - v.operator_account + v.operator_account, + v.whitelisted ); }) .map(|v| (v.operator_account.clone(), vec![v.reward_amount(budget)])) diff --git a/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs b/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs index aac01166ff..4b84870f70 100644 --- a/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs +++ b/nym-validator-rewarder/src/rewarder/credential_issuance/types.rs @@ -324,10 +324,11 @@ impl CredentialIssuanceResults { .iter() .inspect(|a| { info!( - "operator {} will receive {} at address {} for credential issuance work", + "operator {} will receive {} at address {} for credential issuance work (whitelisted: {})", a.api_runner, a.reward_amount(budget), a.runner_account, + a.whitelisted ); }) .map(|v| (v.runner_account.clone(), vec![v.reward_amount(budget)]))