more granual configs
This commit is contained in:
committed by
Jon Häggblad
parent
5c864cb055
commit
162ff71814
@@ -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
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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(())
|
||||
|
||||
Reference in New Issue
Block a user