more granual configs

This commit is contained in:
Jędrzej Stuczyński
2023-12-18 14:05:02 +00:00
committed by Jon Häggblad
parent 5c864cb055
commit 162ff71814
7 changed files with 175 additions and 82 deletions
+1
View File
@@ -24,4 +24,5 @@ SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS=n1ps5yutd7sufwg058qd7ac7ldnlazsvmhzq
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0"
EXPLORER_API=https://sandbox-explorer.nymtech.net/api
NYXD="https://rpc.sandbox.nymtech.net"
NYXD_WS="wss://rpc.sandbox.nymtech.net/websocket"
NYM_API="https://sandbox-nym-api1.nymtech.net/api"
@@ -40,7 +40,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,
ending_dkg_epoch INTEGER NOT NULL,
total_issued_credentials INTEGER NOT NULL,
budget TEXT NOT NULL
);
+30 -12
View File
@@ -11,7 +11,7 @@ use nym_config::{
};
use nym_network_defaults::NymNetworkDetails;
use nym_validator_client::nyxd;
use nym_validator_client::nyxd::{AccountId, Coin};
use nym_validator_client::nyxd::Coin;
use serde::{Deserialize, Serialize};
use std::io;
use std::path::{Path, PathBuf};
@@ -69,6 +69,9 @@ pub struct Config {
#[zeroize(skip)]
pub rewarding: Rewarding,
#[zeroize(skip)]
pub block_signing: BlockSigning,
#[zeroize(skip)]
pub issuance_monitor: IssuanceMonitor,
@@ -95,8 +98,10 @@ impl Config {
Config {
save_path: None,
rewarding: Rewarding::default(),
block_signing: Default::default(),
issuance_monitor: IssuanceMonitor::default(),
nyxd_scraper: NyxdScraper {
enabled: true,
websocket_url: network.endpoints[0]
.websocket_url()
.expect("TODO: hardcoded websocket url is not available"),
@@ -123,17 +128,11 @@ impl Config {
.expect("failed to create nyxd client config")
}
pub fn dkg_contract_address(&self) -> AccountId {
// TEMP
NymNetworkDetails::new_from_env()
.contracts
.coconut_dkg_contract_address
.expect("missing contract address")
.parse()
.expect("invalid contract address")
}
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(())
}
@@ -192,7 +191,7 @@ pub struct Base {
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Rewarding {
///
/// Specifies total budget for the epoch
pub epoch_budget: Coin,
#[serde(with = "humantime_serde")]
@@ -250,13 +249,31 @@ 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
}
#[derive(Debug, Clone, Deserialize, Serialize, Copy)]
pub struct BlockSigning {
/// Specifies whether credential issuance for block signing is enabled.
pub enabled: bool,
}
impl Default for BlockSigning {
fn default() -> Self {
BlockSigning { enabled: true }
}
}
#[derive(Debug, Clone, Deserialize, Serialize, Copy)]
pub struct IssuanceMonitor {
/// Specifies whether credential issuance monitoring (and associated rewards) are enabled.
pub enabled: bool,
#[serde(with = "humantime_serde")]
pub run_interval: Duration,
@@ -271,6 +288,7 @@ pub struct IssuanceMonitor {
impl Default for IssuanceMonitor {
fn default() -> Self {
IssuanceMonitor {
enabled: true,
run_interval: DEFAULT_MONITOR_RUN_INTERVAL,
min_validate_per_issuer: DEFAULT_MONITOR_MIN_VALIDATE,
sampling_rate: DEFAULT_MONITOR_SAMPLING_RATE,
+3
View File
@@ -150,4 +150,7 @@ pub enum NymRewarderError {
request: Option<String>,
on_chain: String,
},
#[error("can't enable block signing rewarding without the block scraper")]
BlockSigningRewardWithoutScraper,
}
+3
View File
@@ -1,6 +1,9 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
#![warn(clippy::expect_used)]
#![warn(clippy::unwrap_used)]
use crate::cli::Cli;
use clap::{crate_name, crate_version, Parser};
use nym_bin_common::logging::{maybe_print_banner, setup_tracing_logger};
+77 -33
View File
@@ -30,8 +30,8 @@ mod tasks;
pub struct EpochRewards {
pub epoch: Epoch,
pub signing: EpochSigningResults,
pub credentials: CredentialIssuanceResults,
pub signing: Option<EpochSigningResults>,
pub credentials: Option<CredentialIssuanceResults>,
pub total_budget: Coin,
pub signing_budget: Coin,
@@ -40,11 +40,17 @@ pub struct EpochRewards {
impl EpochRewards {
pub fn amounts(&self) -> Vec<(AccountId, Vec<Coin>)> {
let signing = self.signing.rewarding_amounts(&self.signing_budget);
let mut credentials = self.credentials.rewarding_amounts(&self.credentials_budget);
let mut amounts = Vec::new();
let mut amounts = signing;
amounts.append(&mut credentials);
if let Some(signing) = &self.signing {
let mut signing_amounts = signing.rewarding_amounts(&self.signing_budget);
amounts.append(&mut signing_amounts);
}
if let Some(credentials) = &self.credentials {
let mut credentials_amounts = credentials.rewarding_amounts(&self.credentials_budget);
amounts.append(&mut credentials_amounts);
}
amounts
}
@@ -65,13 +71,18 @@ pub struct Rewarder {
storage: RewarderStorage,
nyxd_client: NyxdClient,
epoch_signing: EpochSigning,
credential_issuance: CredentialIssuance,
epoch_signing: Option<EpochSigning>,
credential_issuance: Option<CredentialIssuance>,
}
impl Rewarder {
pub async fn new(config: Config) -> Result<Self, NymRewarderError> {
let nyxd_scraper = NyxdScraper::new(config.scraper_config()).await?;
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? {
@@ -80,13 +91,28 @@ impl Rewarder {
Epoch::first(config.rewarding.epoch_duration)?
};
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
Some(EpochSigning {
#[allow(clippy::unwrap_used)]
nyxd_scraper: nyxd_scraper.unwrap(),
nyxd_client: nyxd_client.clone(),
})
} else {
None
};
let credential_issuance = if config.issuance_monitor.enabled {
Some(CredentialIssuance::new(current_epoch, &nyxd_client).await?)
} else {
None
};
Ok(Rewarder {
current_epoch,
credential_issuance: CredentialIssuance::new(current_epoch, &nyxd_client).await?,
epoch_signing: EpochSigning {
nyxd_scraper,
nyxd_client: nyxd_client.clone(),
},
credential_issuance,
epoch_signing,
nyxd_client,
storage,
config,
@@ -96,21 +122,35 @@ impl Rewarder {
#[instrument(skip(self))]
async fn calculate_block_signing_rewards(
&mut self,
) -> Result<EpochSigningResults, NymRewarderError> {
) -> Result<Option<EpochSigningResults>, NymRewarderError> {
info!("calculating reward shares");
self.epoch_signing
.get_signed_blocks_results(self.current_epoch)
.await
if let Some(epoch_signing) = &mut self.epoch_signing {
Some(
epoch_signing
.get_signed_blocks_results(self.current_epoch)
.await,
)
} else {
None
}
.transpose()
}
#[instrument(skip(self))]
async fn calculate_credential_rewards(
&mut self,
) -> Result<CredentialIssuanceResults, NymRewarderError> {
) -> Result<Option<CredentialIssuanceResults>, NymRewarderError> {
info!("calculating reward shares");
self.credential_issuance
.get_issued_credentials_results(self.current_epoch)
.await
if let Some(credential_issuance) = &mut self.credential_issuance {
Some(
credential_issuance
.get_issued_credentials_results(self.current_epoch)
.await,
)
} else {
None
}
.transpose()
}
async fn determine_epoch_rewards(&mut self) -> Result<EpochRewards, NymRewarderError> {
@@ -180,16 +220,18 @@ impl Rewarder {
// setup shutdowns
let mut task_manager = TaskManager::new(5);
self.credential_issuance.start_monitor(
self.config.issuance_monitor,
self.nyxd_client.clone(),
task_manager.subscribe(),
);
self.epoch_signing.nyxd_scraper.start().await?;
self.epoch_signing
.nyxd_scraper
.wait_for_startup_sync()
.await;
if let Some(ref credential_issuance) = self.credential_issuance {
credential_issuance.start_monitor(
self.config.issuance_monitor,
self.nyxd_client.clone(),
task_manager.subscribe(),
);
}
if let Some(epoch_signing) = &self.epoch_signing {
epoch_signing.nyxd_scraper.start().await?;
epoch_signing.nyxd_scraper.wait_for_startup_sync().await;
}
// rewarding epochs last from :00 to :00
// \/\/\/\/\/\/\/ TEMP TESTING!!!
@@ -225,7 +267,9 @@ impl Rewarder {
}
}
self.epoch_signing.nyxd_scraper.stop().await;
if let Some(epoch_signing) = self.epoch_signing {
epoch_signing.nyxd_scraper.stop().await;
}
Ok(())
}
@@ -81,58 +81,82 @@ impl RewarderStorage {
self.manager
.insert_rewarding_epoch_block_signing(
epoch_id,
reward.signing.total_voting_power_at_epoch_start,
reward.signing.blocks,
reward
.signing
.as_ref()
.map(|s| s.total_voting_power_at_epoch_start)
.unwrap_or_default(),
reward
.signing
.as_ref()
.map(|s| s.blocks)
.unwrap_or_default(),
reward.signing_budget.to_string(),
)
.await?;
for validator in reward.signing.validators {
let reward_amount = validator.reward_amount(&reward.signing_budget).to_string();
self.manager
.insert_rewarding_epoch_block_signing_reward(
epoch_id,
validator.validator.consensus_address,
validator.operator_account.to_string(),
reward_amount,
validator.voting_power_at_epoch_start,
validator.voting_power_ratio.to_string(),
validator.signed_blocks,
validator.ratio_signed.to_string(),
)
.await?;
if let Some(signing) = reward.signing {
for validator in signing.validators {
let reward_amount = validator.reward_amount(&reward.signing_budget).to_string();
self.manager
.insert_rewarding_epoch_block_signing_reward(
epoch_id,
validator.validator.consensus_address,
validator.operator_account.to_string(),
reward_amount,
validator.voting_power_at_epoch_start,
validator.voting_power_ratio.to_string(),
validator.signed_blocks,
validator.ratio_signed.to_string(),
)
.await?;
}
}
// safety: we must have at least a single value here
let dkg_epoch_start = reward.credentials.dkg_epochs.first().unwrap();
let dkg_epoch_end = reward.credentials.dkg_epochs.last().unwrap();
let dkg_epoch_start = reward
.credentials
.as_ref()
.map(|c| *c.dkg_epochs.first().unwrap())
.unwrap_or_default();
let dkg_epoch_end = reward
.credentials
.as_ref()
.map(|c| *c.dkg_epochs.last().unwrap())
.unwrap_or_default();
self.manager
.insert_rewarding_epoch_credential_issuance(
epoch_id,
*dkg_epoch_start,
*dkg_epoch_end,
reward.credentials.total_issued,
dkg_epoch_start,
dkg_epoch_end,
reward
.credentials
.as_ref()
.map(|c| c.total_issued)
.unwrap_or_default(),
reward.credentials_budget.to_string(),
)
.await?;
for api_runner in reward.credentials.api_runners {
let reward_amount = api_runner
.reward_amount(&reward.credentials_budget)
.to_string();
if let Some(credentials) = reward.credentials {
for api_runner in credentials.api_runners {
let reward_amount = api_runner
.reward_amount(&reward.credentials_budget)
.to_string();
self.manager
.insert_rewarding_epoch_credential_issuance_reward(
epoch_id,
api_runner.runner_account.to_string(),
reward_amount,
api_runner.api_runner,
api_runner.issued_credentials,
api_runner.issued_ratio.to_string(),
api_runner.validated_credentials,
)
.await?;
self.manager
.insert_rewarding_epoch_credential_issuance_reward(
epoch_id,
api_runner.runner_account.to_string(),
reward_amount,
api_runner.api_runner,
api_runner.issued_credentials,
api_runner.issued_ratio.to_string(),
api_runner.validated_credentials,
)
.await?;
}
}
Ok(())