Chore/nym api commands (#4225)
* created run and init commands for nym-api + nasty mnemonic workaround * removed dead code * cargo fmt + clippy * fixed key loader * made announce address optional and removed the nonobvious fallback value * clippy * removed contract addresses from config template * fixed conflicting arguments macro * post-rebasing fixes: applied client macro to balance method
This commit is contained in:
committed by
GitHub
parent
496870b5f6
commit
78610c7e28
@@ -73,7 +73,7 @@ where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let path = path.as_ref();
|
||||
log::debug!("trying to save config file to {}", path.display());
|
||||
log::info!("saving config file to {}", path.display());
|
||||
|
||||
if let Some(parent) = path.parent() {
|
||||
create_dir_all(parent)?;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::var_names;
|
||||
use crate::{DenomDetails, ValidatorDetails};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub const NETWORK_NAME: &str = "mainnet";
|
||||
|
||||
@@ -60,6 +61,12 @@ pub fn read_var_if_not_default(var: &str) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_parsed_var_if_not_default<T: FromStr>(var: &str) -> Option<Result<T, T::Err>> {
|
||||
read_var_if_not_default(var)
|
||||
.as_deref()
|
||||
.map(FromStr::from_str)
|
||||
}
|
||||
|
||||
pub fn export_to_env() {
|
||||
set_var_to_default(var_names::CONFIGURED, "true");
|
||||
set_var_to_default(var_names::NETWORK_NAME, NETWORK_NAME);
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
use crate::coconut::error::Result;
|
||||
use crate::nyxd;
|
||||
use nym_coconut_dkg_common::types::EpochId;
|
||||
use crate::support::nyxd::ClientInner;
|
||||
use nym_coconut_dkg_common::types::{Epoch, EpochId};
|
||||
use nym_coconut_interface::VerificationKey;
|
||||
use nym_credentials::coconut::utils::obtain_aggregate_verification_key;
|
||||
use nym_validator_client::coconut::all_coconut_api_clients;
|
||||
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
||||
use nym_validator_client::DirectSigningHttpRpcNyxdClient;
|
||||
use std::cmp::min;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
@@ -40,9 +40,7 @@ impl CachedEpoch {
|
||||
self.valid_until > OffsetDateTime::now_utc()
|
||||
}
|
||||
|
||||
async fn update(&mut self, client: &DirectSigningHttpRpcNyxdClient) -> Result<()> {
|
||||
let epoch = client.get_current_epoch().await?;
|
||||
|
||||
async fn update(&mut self, epoch: Epoch) -> Result<()> {
|
||||
let now = OffsetDateTime::now_utc();
|
||||
let state_end =
|
||||
OffsetDateTime::from_unix_timestamp(epoch.finish_timestamp.seconds() as i64).unwrap();
|
||||
@@ -84,8 +82,13 @@ impl APICommunicationChannel for QueryCommunicationChannel {
|
||||
// update cache
|
||||
drop(guard);
|
||||
let mut guard = self.cached_epoch.write().await;
|
||||
let client = self.nyxd_client.0.read().await;
|
||||
guard.update(&client).await?;
|
||||
|
||||
let epoch = match self.nyxd_client.read().await.deref() {
|
||||
ClientInner::Query(client) => client.get_current_epoch().await?,
|
||||
ClientInner::Signing(client) => client.get_current_epoch().await?,
|
||||
};
|
||||
|
||||
guard.update(epoch).await?;
|
||||
|
||||
return Ok(guard.current_epoch_id);
|
||||
}
|
||||
@@ -96,8 +99,11 @@ impl APICommunicationChannel for QueryCommunicationChannel {
|
||||
}
|
||||
|
||||
let mut guard = self.epoch_keys.write().await;
|
||||
let client = self.nyxd_client.0.read().await;
|
||||
let coconut_api_clients = all_coconut_api_clients(client.deref(), epoch_id).await?;
|
||||
let coconut_api_clients = match self.nyxd_client.read().await.deref() {
|
||||
ClientInner::Query(client) => all_coconut_api_clients(client, epoch_id).await?,
|
||||
ClientInner::Signing(client) => all_coconut_api_clients(client, epoch_id).await?,
|
||||
};
|
||||
|
||||
let vk = obtain_aggregate_verification_key(&coconut_api_clients).await?;
|
||||
|
||||
guard.insert(epoch_id, vk.clone());
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::coconut::dkg::{
|
||||
use crate::coconut::keypair::KeyPair as CoconutKeyPair;
|
||||
use crate::nyxd;
|
||||
use crate::support::config;
|
||||
use anyhow::Result;
|
||||
use anyhow::{bail, Result};
|
||||
use nym_coconut_dkg_common::types::EpochState;
|
||||
use nym_dkg::bte::keys::KeyPair as DkgKeyPair;
|
||||
use nym_task::{TaskClient, TaskManager};
|
||||
@@ -53,6 +53,10 @@ impl<R: RngCore + CryptoRng + Clone> DkgController<R> {
|
||||
coconut_keypair: CoconutKeyPair,
|
||||
rng: R,
|
||||
) -> Result<Self> {
|
||||
let Some(announce_address) = &config.announce_address else {
|
||||
bail!("can't start a DKG controller without specifying an announce address!")
|
||||
};
|
||||
|
||||
let dkg_keypair = nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new(
|
||||
&config.storage_paths.decryption_key_path,
|
||||
&config.storage_paths.public_key_with_proof_path,
|
||||
@@ -76,7 +80,7 @@ impl<R: RngCore + CryptoRng + Clone> DkgController<R> {
|
||||
state: State::new(
|
||||
config.storage_paths.dkg_persistent_state_path.clone(),
|
||||
persistent_state,
|
||||
config.announce_address.clone(),
|
||||
announce_address.clone(),
|
||||
dkg_keypair,
|
||||
coconut_keypair,
|
||||
),
|
||||
|
||||
+6
-17
@@ -9,7 +9,7 @@ use crate::network::models::NetworkDetails;
|
||||
use crate::node_describe_cache::DescribedNodes;
|
||||
use crate::node_status_api::uptime_updater::HistoricalUptimeUpdater;
|
||||
use crate::support::caching::cache::SharedCache;
|
||||
use crate::support::cli::{self, Commands};
|
||||
use crate::support::cli;
|
||||
use crate::support::config::Config;
|
||||
use crate::support::storage;
|
||||
use crate::support::storage::NymApiStorage;
|
||||
@@ -21,11 +21,11 @@ use clap::Parser;
|
||||
use coconut::dkg::controller::DkgController;
|
||||
use node_status_api::NodeStatusCache;
|
||||
use nym_bin_common::logging::setup_logging;
|
||||
use nym_config::defaults::NymNetworkDetails;
|
||||
use nym_contract_cache::cache::NymContractCache;
|
||||
use nym_sphinx::receiver::SphinxMessageReceiver;
|
||||
use nym_task::TaskManager;
|
||||
use rand::rngs::OsRng;
|
||||
use std::error::Error;
|
||||
use support::{http, nyxd};
|
||||
|
||||
mod circulating_supply_api;
|
||||
@@ -46,7 +46,7 @@ struct ShutdownHandles {
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
async fn main() -> Result<(), anyhow::Error> {
|
||||
println!("Starting nym api...");
|
||||
|
||||
cfg_if::cfg_if! {if #[cfg(feature = "console-subscriber")] {
|
||||
@@ -59,24 +59,13 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
trace!("{:#?}", args);
|
||||
|
||||
setup_env(args.config_env_file.as_ref());
|
||||
|
||||
let command = args.command.unwrap_or(Commands::Run(Box::new(args.run)));
|
||||
|
||||
match command {
|
||||
Commands::BuildInfo(m) => {
|
||||
cli::build_info::execute(m);
|
||||
Ok(())
|
||||
}
|
||||
Commands::Run(m) => cli::run::execute(*m).await,
|
||||
}
|
||||
args.execute().await
|
||||
}
|
||||
|
||||
async fn start_nym_api_tasks(
|
||||
config: Config,
|
||||
) -> Result<ShutdownHandles, Box<dyn Error + Send + Sync>> {
|
||||
async fn start_nym_api_tasks(config: Config) -> anyhow::Result<ShutdownHandles> {
|
||||
let nyxd_client = nyxd::Client::new(&config);
|
||||
let connected_nyxd = config.get_nyxd_url();
|
||||
let nym_network_details = config.get_network_details();
|
||||
let nym_network_details = NymNetworkDetails::new_from_env();
|
||||
let network_details = NetworkDetails::new(connected_nyxd.to_string(), nym_network_details);
|
||||
|
||||
let coconut_keypair = coconut::keypair::KeyPair::new();
|
||||
|
||||
+38
-28
@@ -47,44 +47,52 @@ impl NymContractCacheRefresher {
|
||||
}
|
||||
|
||||
async fn get_nym_contracts_info(&self) -> Result<CachedContractsInfo> {
|
||||
use crate::query_guard;
|
||||
|
||||
let mut updated = HashMap::new();
|
||||
|
||||
let client_guard = self.nyxd_client.read().await;
|
||||
|
||||
let mixnet = client_guard.mixnet_contract_address();
|
||||
let vesting = client_guard.vesting_contract_address();
|
||||
let name_service = client_guard.name_service_contract_address();
|
||||
let service_provider = client_guard.service_provider_contract_address();
|
||||
let coconut_bandwidth = client_guard.coconut_bandwidth_contract_address();
|
||||
let coconut_dkg = client_guard.dkg_contract_address();
|
||||
let group = client_guard.group_contract_address();
|
||||
let multisig = client_guard.multisig_contract_address();
|
||||
let mixnet = query_guard!(client_guard, mixnet_contract_address());
|
||||
let vesting = query_guard!(client_guard, vesting_contract_address());
|
||||
let name_service = query_guard!(client_guard, name_service_contract_address());
|
||||
let service_provider = query_guard!(client_guard, service_provider_contract_address());
|
||||
let coconut_bandwidth = query_guard!(client_guard, coconut_bandwidth_contract_address());
|
||||
let coconut_dkg = query_guard!(client_guard, dkg_contract_address());
|
||||
let group = query_guard!(client_guard, group_contract_address());
|
||||
let multisig = query_guard!(client_guard, multisig_contract_address());
|
||||
|
||||
// get cw2 versions
|
||||
let mixnet_cw2_future = client_guard.get_mixnet_contract_cw2_version();
|
||||
let vesting_cw2_future = client_guard.get_vesting_contract_cw2_version();
|
||||
let service_provider_cw2_future = client_guard.get_name_service_contract_cw2_version();
|
||||
let name_service_cw2_future = client_guard.get_name_service_contract_cw2_version();
|
||||
let mixnet_cw2_future = query_guard!(client_guard, get_mixnet_contract_cw2_version());
|
||||
let vesting_cw2_future = query_guard!(client_guard, get_vesting_contract_cw2_version());
|
||||
let service_provider_cw2_future =
|
||||
query_guard!(client_guard, get_name_service_contract_cw2_version());
|
||||
let name_service_cw2_future =
|
||||
query_guard!(client_guard, get_name_service_contract_cw2_version());
|
||||
|
||||
// group and multisig contract save that information in their storage but don't expose it via queries
|
||||
// so a temporary workaround...
|
||||
let multisig_cw2 = if let Some(multisig_contract) = multisig {
|
||||
client_guard
|
||||
.query_contract_raw(multisig_contract, b"contract_info".to_vec())
|
||||
.await
|
||||
.map(|r| serde_json::from_slice(&r).ok())
|
||||
.ok()
|
||||
.flatten()
|
||||
query_guard!(
|
||||
client_guard,
|
||||
query_contract_raw(multisig_contract, b"contract_info".to_vec())
|
||||
.await
|
||||
.map(|r| serde_json::from_slice(&r).ok())
|
||||
.ok()
|
||||
.flatten()
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let group_cw2 = if let Some(group_contract) = group {
|
||||
client_guard
|
||||
.query_contract_raw(group_contract, b"contract_info".to_vec())
|
||||
.await
|
||||
.map(|r| serde_json::from_slice(&r).ok())
|
||||
.ok()
|
||||
.flatten()
|
||||
query_guard!(
|
||||
client_guard,
|
||||
query_contract_raw(group_contract, b"contract_info".to_vec())
|
||||
.await
|
||||
.map(|r| serde_json::from_slice(&r).ok())
|
||||
.ok()
|
||||
.flatten()
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -98,10 +106,12 @@ impl NymContractCacheRefresher {
|
||||
.await;
|
||||
|
||||
// get detailed build info
|
||||
let mixnet_detailed_future = client_guard.get_mixnet_contract_version();
|
||||
let vesting_detailed_future = client_guard.get_vesting_contract_version();
|
||||
let service_provider_detailed_future = client_guard.get_sp_contract_version();
|
||||
let name_service_detailed_future = client_guard.get_name_service_contract_version();
|
||||
let mixnet_detailed_future = query_guard!(client_guard, get_mixnet_contract_version());
|
||||
let vesting_detailed_future = query_guard!(client_guard, get_vesting_contract_version());
|
||||
let service_provider_detailed_future =
|
||||
query_guard!(client_guard, get_sp_contract_version());
|
||||
let name_service_detailed_future =
|
||||
query_guard!(client_guard, get_name_service_contract_version());
|
||||
|
||||
let mut build_info = join_all(vec![
|
||||
mixnet_detailed_future,
|
||||
|
||||
@@ -10,6 +10,7 @@ pub(crate) struct Args {
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
pub(crate) fn execute(args: Args) {
|
||||
println!("{}", args.output.format(&bin_info_owned!()))
|
||||
pub(crate) fn execute(args: Args) -> anyhow::Result<()> {
|
||||
println!("{}", args.output.format(&bin_info_owned!()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::support::config::default_config_filepath;
|
||||
use crate::support::config::helpers::initialise_new;
|
||||
use anyhow::bail;
|
||||
|
||||
#[derive(clap::Args, Debug)]
|
||||
pub(crate) struct Args {
|
||||
/// Id of the nym-api we want to initialise. if unspecified, a default value will be used.
|
||||
/// default: "default"
|
||||
#[clap(long, default_value = "default")]
|
||||
pub(crate) id: String,
|
||||
|
||||
/// Specifies whether network monitoring is enabled on this API
|
||||
/// default: false
|
||||
#[clap(short = 'm', long)]
|
||||
pub(crate) enable_monitor: bool,
|
||||
|
||||
/// Specifies whether network rewarding is enabled on this API
|
||||
/// default: false
|
||||
#[clap(short = 'r', long, requires = "enable_monitor", requires = "mnemonic")]
|
||||
pub(crate) enable_rewarding: bool,
|
||||
|
||||
/// Endpoint to nyxd instance used for contract information.
|
||||
/// default: http://localhost:26657
|
||||
#[clap(long)]
|
||||
pub(crate) nyxd_validator: Option<url::Url>,
|
||||
|
||||
/// Mnemonic of the network monitor used for sending rewarding and zk-nyms transactions
|
||||
/// default: None
|
||||
#[clap(long)]
|
||||
pub(crate) mnemonic: Option<bip39::Mnemonic>,
|
||||
|
||||
/// Flag to indicate whether credential signer authority is enabled on this API
|
||||
/// default: false
|
||||
#[clap(
|
||||
long,
|
||||
requires = "mnemonic",
|
||||
requires = "announce_address",
|
||||
alias = "enable_coconut"
|
||||
)]
|
||||
pub(crate) enable_zk_nym: bool,
|
||||
|
||||
/// Announced address that is going to be put in the DKG contract where zk-nym clients will connect
|
||||
/// to obtain their credentials
|
||||
/// default: None
|
||||
#[clap(long)]
|
||||
pub(crate) announce_address: Option<url::Url>,
|
||||
|
||||
/// Set this nym api to work in a enabled credentials that would attempt to use gateway with the bandwidth credential requirement
|
||||
#[clap(long, requires = "enable_monitor")]
|
||||
pub(crate) monitor_credentials_mode: bool,
|
||||
// #[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
// output: OutputFormat,
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> anyhow::Result<()> {
|
||||
eprintln!("initialising nym-api...");
|
||||
|
||||
// let output = args.output;
|
||||
|
||||
let config_path = default_config_filepath(&args.id);
|
||||
if config_path.exists() {
|
||||
// don't bother with attempting to override some of the data and preserving the rest of it
|
||||
// if the config exists.
|
||||
// this situation should never occur under normal circumstances, so it's up to the user to deal with it
|
||||
bail!("there already exists a configuration file at '{}'. If you intend to replace it, you need to manually remove it first. Make sure to make backup of any keys and datastores first.", config_path.display())
|
||||
}
|
||||
|
||||
let config = initialise_new(&args.id)?;
|
||||
// args take precedence over env
|
||||
config
|
||||
.override_with_env()
|
||||
.override_with_args(args)
|
||||
.try_save()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
+19
-110
@@ -1,31 +1,22 @@
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use super::config::Config;
|
||||
use crate::support::config::default_config_filepath;
|
||||
use crate::support::config::helpers::{initialise_new, try_load_current_config};
|
||||
use ::nym_config::defaults::var_names::{MIXNET_CONTRACT_ADDRESS, VESTING_CONTRACT_ADDRESS};
|
||||
use anyhow::{bail, Result};
|
||||
use anyhow::Result;
|
||||
use clap::{Parser, Subcommand};
|
||||
use lazy_static::lazy_static;
|
||||
use nym_bin_common::bin_info;
|
||||
use nym_config::defaults::var_names::NYXD;
|
||||
use nym_config::OptionalSet;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
pub(crate) mod build_info;
|
||||
pub(crate) mod init;
|
||||
pub(crate) mod run;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PRETTY_BUILD_INFORMATION: String = bin_info!().pretty_print();
|
||||
}
|
||||
|
||||
// Helper for passing LONG_VERSION to clap
|
||||
fn pretty_build_info_static() -> &'static str {
|
||||
&PRETTY_BUILD_INFORMATION
|
||||
static PRETTY_BUILD_INFORMATION: OnceLock<String> = OnceLock::new();
|
||||
PRETTY_BUILD_INFORMATION.get_or_init(|| bin_info!().pretty_print())
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(args_conflicts_with_subcommands = true)]
|
||||
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
|
||||
pub(crate) struct Cli {
|
||||
/// Path pointing to an env file that configures the Nym API.
|
||||
@@ -33,109 +24,27 @@ pub(crate) struct Cli {
|
||||
pub(crate) config_env_file: Option<std::path::PathBuf>,
|
||||
|
||||
#[clap(subcommand)]
|
||||
pub(crate) command: Option<Commands>,
|
||||
pub(crate) command: Commands,
|
||||
}
|
||||
|
||||
// this shouldn't really be here, but we don't want to break backwards compat
|
||||
#[clap(flatten)]
|
||||
pub(crate) run: run::Args,
|
||||
impl Cli {
|
||||
pub(crate) async fn execute(self) -> Result<(), anyhow::Error> {
|
||||
match self.command {
|
||||
Commands::Init(args) => init::execute(args).await,
|
||||
Commands::Run(args) => run::execute(args).await,
|
||||
Commands::BuildInfo(args) => build_info::execute(args),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub(crate) enum Commands {
|
||||
/// Initialise a Nym Api instance with persistent config.toml file.
|
||||
Init(init::Args),
|
||||
|
||||
/// Run the Nym Api with provided configuration optionally overriding set parameters
|
||||
Run(Box<run::Args>),
|
||||
Run(run::Args),
|
||||
|
||||
/// Show build information of this binary
|
||||
BuildInfo(build_info::Args),
|
||||
}
|
||||
|
||||
pub(crate) fn override_config(config: Config, args: run::Args) -> Config {
|
||||
config
|
||||
.with_optional_env(
|
||||
Config::with_custom_nyxd_validator,
|
||||
args.nyxd_validator,
|
||||
NYXD,
|
||||
)
|
||||
.with_optional_env(
|
||||
Config::with_custom_mixnet_contract,
|
||||
args.mixnet_contract,
|
||||
MIXNET_CONTRACT_ADDRESS,
|
||||
)
|
||||
.with_optional_env(
|
||||
Config::with_custom_vesting_contract,
|
||||
args.vesting_contract,
|
||||
VESTING_CONTRACT_ADDRESS,
|
||||
)
|
||||
.with_optional(Config::with_mnemonic, args.mnemonic)
|
||||
.with_optional(
|
||||
Config::with_minimum_interval_monitor_threshold,
|
||||
args.monitor_threshold,
|
||||
)
|
||||
.with_optional(
|
||||
Config::with_min_mixnode_reliability,
|
||||
args.min_mixnode_reliability,
|
||||
)
|
||||
.with_optional(
|
||||
Config::with_min_gateway_reliability,
|
||||
args.min_gateway_reliability,
|
||||
)
|
||||
.with_optional(Config::with_network_monitor_enabled, args.enable_monitor)
|
||||
.with_optional(Config::with_rewarding_enabled, args.enable_rewarding)
|
||||
.with_optional(Config::with_ephemera_enabled, args.enable_ephemera)
|
||||
.with_optional(
|
||||
Config::with_disabled_credentials_mode,
|
||||
args.enabled_credentials_mode.map(|b| !b),
|
||||
)
|
||||
.with_optional(Config::with_announce_address, args.announce_address)
|
||||
.with_optional(Config::with_coconut_signer_enabled, args.enable_coconut)
|
||||
.with_optional(Config::with_ephemera_ip, args.ephemera_args.ephemera_ip)
|
||||
.with_optional(
|
||||
Config::with_ephemera_protocol_port,
|
||||
args.ephemera_args.ephemera_protocol_port,
|
||||
)
|
||||
.with_optional(
|
||||
Config::with_ephemera_websocket_port,
|
||||
args.ephemera_args.ephemera_websocket_port,
|
||||
)
|
||||
.with_optional(
|
||||
Config::with_ephemera_http_api_port,
|
||||
args.ephemera_args.ephemera_http_api_port,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn build_config(args: run::Args) -> Result<Config> {
|
||||
let id = match &args.id {
|
||||
Some(id) => id.clone(),
|
||||
None => {
|
||||
error!("--id argument must be provided to run nym-api");
|
||||
bail!("--id argument must be provided to run nym-api")
|
||||
}
|
||||
};
|
||||
|
||||
// try to load config from the file, if it doesn't exist, use default values
|
||||
let config = match try_load_current_config(&id) {
|
||||
Ok(cfg) => cfg,
|
||||
Err(err) => {
|
||||
let config_path = default_config_filepath(&id);
|
||||
warn!(
|
||||
"Could not load the configuration file from {}: {err}. Either the file did not exist or was malformed. Using the default values instead",
|
||||
config_path.display()
|
||||
);
|
||||
|
||||
initialise_new(&id)?
|
||||
}
|
||||
};
|
||||
|
||||
let mut config = override_config(config, args);
|
||||
// since we have no proper `init`, we have to do id check here:
|
||||
let made_new_keys = config
|
||||
.base
|
||||
.storage_paths
|
||||
.generate_identity_if_missing(&config.base.id)?;
|
||||
|
||||
if made_new_keys {
|
||||
config.save_to_default_location()?
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
@@ -2,114 +2,68 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::start_nym_api_tasks;
|
||||
use crate::support::cli::build_config;
|
||||
use nym_validator_client::nyxd;
|
||||
use std::error::Error;
|
||||
|
||||
// explicitly defined custom parser (as opposed to just using
|
||||
// #[arg(value_parser = clap::value_parser!(u8).range(0..100))]
|
||||
// for better error message
|
||||
fn threshold_in_range(s: &str) -> Result<u8, String> {
|
||||
let threshold: usize = s
|
||||
.parse()
|
||||
.map_err(|_| format!("`{s}` isn't a valid threshold number"))?;
|
||||
if threshold > 100 {
|
||||
Err(format!("{threshold} is not within the range 0-100"))
|
||||
} else {
|
||||
Ok(threshold as u8)
|
||||
}
|
||||
}
|
||||
use crate::support::config::helpers::try_load_current_config;
|
||||
use anyhow::bail;
|
||||
|
||||
#[derive(clap::Args, Debug)]
|
||||
pub(crate) struct Args {
|
||||
/// Id of the nym-api we want to run
|
||||
#[clap(long)]
|
||||
// ugh. we had to make it optional in case somebody wanted to run `build-info`
|
||||
pub(crate) id: Option<String>,
|
||||
/// Id of the nym-api we want to run.if unspecified, a default value will be used.
|
||||
/// default: "default"
|
||||
#[clap(long, default_value = "default")]
|
||||
pub(crate) id: String,
|
||||
|
||||
/// Specifies whether network monitoring is enabled on this API
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(short = 'm', long)]
|
||||
pub(crate) enable_monitor: Option<bool>,
|
||||
|
||||
/// Specifies whether network rewarding is enabled on this API
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(short = 'r', long, requires = "enable_monitor", requires = "mnemonic")]
|
||||
pub(crate) enable_rewarding: Option<bool>,
|
||||
|
||||
/// Specifies whether ephemera is used to aggregate monitor data on this API
|
||||
#[clap(short = 'e', long, requires = "enable_monitor")]
|
||||
pub(crate) enable_ephemera: Option<bool>,
|
||||
|
||||
/// Endpoint to nyxd instance from which the monitor will grab nodes to test
|
||||
/// Endpoint to nyxd instance used for contract information.
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(long)]
|
||||
pub(crate) nyxd_validator: Option<url::Url>,
|
||||
|
||||
/// Address of the mixnet contract managing the network
|
||||
#[clap(long)]
|
||||
pub(crate) mixnet_contract: Option<nyxd::AccountId>,
|
||||
|
||||
/// Address of the vesting contract holding locked tokens
|
||||
#[clap(long)]
|
||||
pub(crate) vesting_contract: Option<nyxd::AccountId>,
|
||||
|
||||
/// Mnemonic of the network monitor used for rewarding operators
|
||||
// even though we're currently converting the mnemonic to string (and then back to the concrete type)
|
||||
// at least we're getting immediate validation when passing the arguments
|
||||
/// Mnemonic of the network monitor used for sending rewarding and zk-nyms transactions
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(long)]
|
||||
pub(crate) mnemonic: Option<bip39::Mnemonic>,
|
||||
|
||||
/// Specifies whether a config file based on provided arguments should be saved to a file
|
||||
#[clap(short = 'w', long)]
|
||||
pub(crate) save_config: bool,
|
||||
|
||||
/// Specifies the minimum percentage of monitor test run data present in order to distribute rewards for given interval.
|
||||
#[clap(long, value_parser = threshold_in_range)]
|
||||
pub(crate) monitor_threshold: Option<u8>,
|
||||
|
||||
/// Mixnodes with reliability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.
|
||||
#[clap(long, value_parser = threshold_in_range)]
|
||||
pub(crate) min_mixnode_reliability: Option<u8>,
|
||||
|
||||
/// Gateways with reliability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.
|
||||
#[clap(long, value_parser = threshold_in_range)]
|
||||
pub(crate) min_gateway_reliability: Option<u8>,
|
||||
|
||||
/// Set this nym api to work in a enabled credentials that would attempt to use gateway with the bandwidth credential requirement
|
||||
#[clap(long)]
|
||||
pub(crate) enabled_credentials_mode: Option<bool>,
|
||||
|
||||
/// Announced address where coconut clients will connect.
|
||||
#[clap(long, hide = true)]
|
||||
pub(crate) announce_address: Option<url::Url>,
|
||||
|
||||
/// Flag to indicate whether coconut signer authority is enabled on this API
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(
|
||||
long,
|
||||
requires = "mnemonic",
|
||||
requires = "announce_address",
|
||||
hide = true
|
||||
alias = "enable_coconut"
|
||||
)]
|
||||
pub(crate) enable_coconut: Option<bool>,
|
||||
pub(crate) enable_zk_nym: Option<bool>,
|
||||
|
||||
/// Ephemera configuration arguments.
|
||||
#[command(flatten)]
|
||||
pub(crate) ephemera_args: ephemera::cli::init::Cmd,
|
||||
/// Announced address that is going to be put in the DKG contract where zk-nym clients will connect
|
||||
/// to obtain their credentials
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(long)]
|
||||
pub(crate) announce_address: Option<url::Url>,
|
||||
|
||||
/// Set this nym api to work in a enabled credentials that would attempt to use gateway with the bandwidth credential requirement
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(long)]
|
||||
pub(crate) monitor_credentials_mode: Option<bool>,
|
||||
// /// Ephemera configuration arguments.
|
||||
// #[command(flatten)]
|
||||
// pub(crate) ephemera_args: ephemera::cli::init::Cmd,
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
let save_to_file = args.save_config;
|
||||
let config = build_config(args)?;
|
||||
pub(crate) async fn execute(args: Args) -> anyhow::Result<()> {
|
||||
// args take precedence over env
|
||||
let config = try_load_current_config(&args.id)?
|
||||
.override_with_env()
|
||||
.override_with_args(args);
|
||||
|
||||
// if we just wanted to write data to the config, exit, don't start any tasks
|
||||
if save_to_file {
|
||||
info!("Saving the configuration to a file");
|
||||
config.save_to_default_location()?;
|
||||
config
|
||||
.get_ephemera_args()
|
||||
.cmd
|
||||
.clone()
|
||||
.execute(Some(&config.get_id()));
|
||||
return Ok(());
|
||||
}
|
||||
config.validate()?;
|
||||
|
||||
let shutdown_handlers = start_nym_api_tasks(config).await?;
|
||||
|
||||
@@ -120,5 +74,10 @@ pub(crate) async fn execute(args: Args) -> Result<(), Box<dyn Error + Send + Syn
|
||||
log::info!("Stopping nym API");
|
||||
shutdown_handlers.rocket_handle.notify();
|
||||
|
||||
res
|
||||
if let Err(err) = res {
|
||||
// that's a nasty workaround, but anyhow errors are generally nicer, especially on exit
|
||||
bail!("{err}")
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,42 +1,26 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::support::config::old_config_v1_1_21::ConfigV1_1_21;
|
||||
use crate::support::config::old_config_v1_1_27::ConfigV1_1_27;
|
||||
use crate::support::config::{default_config_directory, default_data_directory, Config};
|
||||
use anyhow::Result;
|
||||
use crate::support::config;
|
||||
use crate::support::config::{
|
||||
default_config_directory, default_data_directory, upgrade_helpers, Config,
|
||||
};
|
||||
use anyhow::{Context, Result};
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use rand_07::rngs::OsRng;
|
||||
use std::{fs, io};
|
||||
|
||||
fn try_upgrade_v1_1_21_config(id: &str) -> Result<()> {
|
||||
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
|
||||
fn init_identity_keys(config: &config::NymApiPaths) -> Result<()> {
|
||||
let keypaths = nym_pemstore::KeyPairPath::new(
|
||||
&config.private_identity_key_file,
|
||||
&config.public_identity_key_file,
|
||||
);
|
||||
|
||||
// explicitly load it as v1.1.21 (which is incompatible with the current, i.e. 1.1.22+)
|
||||
let Ok(old_config) = ConfigV1_1_21::load_from_file(id) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(());
|
||||
};
|
||||
info!("It seems the nym-api is using <= v1.1.21 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated: Config = old_config.into();
|
||||
Ok(updated.save_to_default_location()?)
|
||||
}
|
||||
|
||||
fn try_upgrade_v1_1_27_config(id: &str) -> Result<()> {
|
||||
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
|
||||
|
||||
// explicitly load it as v1.1.27 (which is incompatible with the current, i.e. 1.1.28+)
|
||||
let Ok(old_config) = ConfigV1_1_27::load_from_file(id) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(());
|
||||
};
|
||||
info!("It seems the nym-api is using <= v1.1.27 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated: Config = old_config.into();
|
||||
Ok(updated.save_to_default_location()?)
|
||||
let mut rng = OsRng;
|
||||
let keypair = identity::KeyPair::new(&mut rng);
|
||||
nym_pemstore::store_keypair(&keypair, &keypaths)
|
||||
.context("failed to store identity keys of the nym api")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init_paths(id: &str) -> io::Result<()> {
|
||||
@@ -46,14 +30,21 @@ fn init_paths(id: &str) -> io::Result<()> {
|
||||
|
||||
pub(crate) fn initialise_new(id: &str) -> Result<Config> {
|
||||
let config = Config::new(id);
|
||||
|
||||
// create base storage paths
|
||||
init_paths(id)?;
|
||||
|
||||
// create identity keys
|
||||
init_identity_keys(&config.base.storage_paths)?;
|
||||
|
||||
// create DKG BTE keys
|
||||
crate::coconut::dkg::controller::init_keypair(&config.coconut_signer)?;
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub(crate) fn try_load_current_config(id: &str) -> Result<Config> {
|
||||
try_upgrade_v1_1_21_config(id)?;
|
||||
try_upgrade_v1_1_27_config(id)?;
|
||||
|
||||
Ok(Config::read_from_default_path(id)?)
|
||||
upgrade_helpers::try_upgrade_config(id)?;
|
||||
Config::read_from_default_path(id).context(
|
||||
"failed to load config.toml from the default path - are you sure you run `init` before?",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,13 +4,16 @@
|
||||
use crate::support::config::persistence::{
|
||||
CoconutSignerPaths, NetworkMonitorPaths, NodeStatusAPIPaths, NymApiPaths,
|
||||
};
|
||||
use crate::support::config::r#override::OverrideConfig;
|
||||
use crate::support::config::template::CONFIG_TEMPLATE;
|
||||
use nym_config::defaults::{mainnet, NymNetworkDetails};
|
||||
use anyhow::bail;
|
||||
use nym_config::defaults::mainnet::read_parsed_var_if_not_default;
|
||||
use nym_config::defaults::var_names::{CONFIGURED, NYXD};
|
||||
use nym_config::serde_helpers::de_maybe_stringified;
|
||||
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, DEFAULT_NYM_APIS_DIR, NYM_DIR,
|
||||
};
|
||||
use nym_validator_client::nyxd;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
@@ -19,14 +22,13 @@ use url::Url;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
pub(crate) mod helpers;
|
||||
pub(crate) mod old_config_v1_1_21;
|
||||
pub(crate) mod old_config_v1_1_27;
|
||||
|
||||
mod r#override;
|
||||
mod persistence;
|
||||
mod template;
|
||||
mod upgrade_helpers;
|
||||
|
||||
pub const DEFAULT_LOCAL_VALIDATOR: &str = "http://localhost:26657";
|
||||
pub const DEFAULT_NYM_API_PORT: u16 = 8080;
|
||||
|
||||
pub const DEFAULT_DKG_CONTRACT_POLLING_RATE: Duration = Duration::from_secs(10);
|
||||
|
||||
@@ -86,6 +88,10 @@ pub fn default_data_directory<P: AsRef<Path>>(id: P) -> PathBuf {
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct Config {
|
||||
// additional metadata holding on-disk location of this config file
|
||||
#[serde(skip)]
|
||||
pub(crate) save_path: Option<PathBuf>,
|
||||
|
||||
pub base: Base,
|
||||
|
||||
// TODO: perhaps introduce separate 'path finder' field for all the paths and directories like we have with other configs
|
||||
@@ -104,16 +110,6 @@ pub struct Config {
|
||||
pub ephemera: Ephemera,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Config> for NymNetworkDetails {
|
||||
fn from(value: &'a Config) -> Self {
|
||||
// we get the current environmental details and then overwrite whatever is appropriate with
|
||||
// the values from the config
|
||||
NymNetworkDetails::new_from_env()
|
||||
.with_mixnet_contract(Some(value.get_mixnet_contract_address().as_ref()))
|
||||
.with_vesting_contract(Some(value.get_vesting_contract_address().as_ref()))
|
||||
}
|
||||
}
|
||||
|
||||
impl NymConfigTemplate for Config {
|
||||
fn template(&self) -> &'static str {
|
||||
CONFIG_TEMPLATE
|
||||
@@ -123,6 +119,7 @@ impl NymConfigTemplate for Config {
|
||||
impl Config {
|
||||
pub fn new<S: AsRef<str>>(id: S) -> Self {
|
||||
Config {
|
||||
save_path: None,
|
||||
base: Base::new_default(id.as_ref()),
|
||||
network_monitor: NetworkMonitor::new_default(id.as_ref()),
|
||||
node_status_api: NodeStatusAPI::new_default(id.as_ref()),
|
||||
@@ -134,12 +131,78 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> anyhow::Result<()> {
|
||||
let can_sign = self.base.mnemonic.is_some();
|
||||
|
||||
if !can_sign && self.rewarding.enabled {
|
||||
bail!("can't enable rewarding without providing a mnemonic")
|
||||
}
|
||||
|
||||
if !can_sign && self.coconut_signer.enabled {
|
||||
bail!("can't enable coconut signer without providing a mnemonic")
|
||||
}
|
||||
|
||||
if !can_sign && self.ephemera.enabled {
|
||||
bail!("can't enable ephemera without providing a mnemonic")
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn override_with_args<O: Into<OverrideConfig>>(mut self, args: O) -> Self {
|
||||
let args = args.into();
|
||||
|
||||
if let Some(enabled_monitor) = args.enable_monitor {
|
||||
self.network_monitor.enabled = enabled_monitor;
|
||||
}
|
||||
if let Some(enable_rewarding) = args.enable_rewarding {
|
||||
self.rewarding.enabled = enable_rewarding;
|
||||
}
|
||||
if let Some(nyxd_upstream) = args.nyxd_validator {
|
||||
self.base.local_validator = nyxd_upstream;
|
||||
}
|
||||
if let Some(mnemonic) = args.mnemonic {
|
||||
self.base.mnemonic = Some(mnemonic)
|
||||
}
|
||||
if let Some(enable_zk_nym) = args.enable_zk_nym {
|
||||
self.coconut_signer.enabled = enable_zk_nym
|
||||
}
|
||||
if let Some(announce_address) = args.announce_address {
|
||||
self.coconut_signer.announce_address = Some(announce_address)
|
||||
}
|
||||
if let Some(monitor_credentials_mode) = args.monitor_credentials_mode {
|
||||
self.network_monitor.debug.disabled_credentials_mode = !monitor_credentials_mode
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn override_with_env(mut self) -> Self {
|
||||
if std::env::var(CONFIGURED).is_ok() {
|
||||
// currently the only value that can be overridden is 'nyxd'
|
||||
if let Some(Ok(custom_nyxd)) = read_parsed_var_if_not_default(NYXD) {
|
||||
self.base.local_validator = custom_nyxd
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
// simple wrapper that reads config file and assigns path location
|
||||
fn read_from_path<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||
let path = path.as_ref();
|
||||
let mut loaded: Config = read_config_from_toml_file(path)?;
|
||||
loaded.save_path = Some(path.to_path_buf());
|
||||
debug!("loaded config file from {}", path.display());
|
||||
Ok(loaded)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||
read_config_from_toml_file(path)
|
||||
Self::read_from_path(path)
|
||||
}
|
||||
|
||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||
Self::read_from_toml_file(default_config_filepath(id))
|
||||
Self::read_from_path(default_config_filepath(id))
|
||||
}
|
||||
|
||||
pub fn default_location(&self) -> PathBuf {
|
||||
@@ -151,93 +214,13 @@ impl Config {
|
||||
save_formatted_config_to_file(self, config_save_location)
|
||||
}
|
||||
|
||||
pub fn get_network_details(&self) -> NymNetworkDetails {
|
||||
self.into()
|
||||
}
|
||||
|
||||
pub fn with_network_monitor_enabled(mut self, enabled: bool) -> Self {
|
||||
self.network_monitor.enabled = enabled;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_disabled_credentials_mode(mut self, disabled_credentials_mode: bool) -> Self {
|
||||
self.network_monitor.debug.disabled_credentials_mode = disabled_credentials_mode;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_rewarding_enabled(mut self, enabled: bool) -> Self {
|
||||
self.rewarding.enabled = enabled;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_coconut_signer_enabled(mut self, enabled: bool) -> Self {
|
||||
self.coconut_signer.enabled = enabled;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_ephemera_enabled(mut self, enabled: bool) -> Self {
|
||||
self.ephemera.enabled = enabled;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_custom_nyxd_validator(mut self, validator: Url) -> Self {
|
||||
self.base.local_validator = validator;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_announce_address(mut self, announce_address: Url) -> Self {
|
||||
self.coconut_signer.announce_address = announce_address;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_custom_mixnet_contract(mut self, mixnet_contract: nyxd::AccountId) -> Self {
|
||||
self.base.mixnet_contract_address = mixnet_contract;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_custom_vesting_contract(mut self, vesting_contract: nyxd::AccountId) -> Self {
|
||||
self.base.vesting_contract_address = vesting_contract;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_mnemonic(mut self, mnemonic: bip39::Mnemonic) -> Self {
|
||||
self.base.mnemonic = mnemonic;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_minimum_interval_monitor_threshold(mut self, threshold: u8) -> Self {
|
||||
self.rewarding.debug.minimum_interval_monitor_threshold = threshold;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_min_mixnode_reliability(mut self, min_mixnode_reliability: u8) -> Self {
|
||||
self.network_monitor.debug.min_mixnode_reliability = min_mixnode_reliability;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_min_gateway_reliability(mut self, min_gateway_reliability: u8) -> Self {
|
||||
self.network_monitor.debug.min_gateway_reliability = min_gateway_reliability;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_ephemera_ip(mut self, ip: String) -> Self {
|
||||
self.ephemera.args.cmd.ephemera_ip = Some(ip);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_ephemera_protocol_port(mut self, port: u16) -> Self {
|
||||
self.ephemera.args.cmd.ephemera_protocol_port = Some(port);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_ephemera_websocket_port(mut self, port: u16) -> Self {
|
||||
self.ephemera.args.cmd.ephemera_websocket_port = Some(port);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_ephemera_http_api_port(mut self, port: u16) -> Self {
|
||||
self.ephemera.args.cmd.ephemera_http_api_port = Some(port);
|
||||
self
|
||||
pub fn try_save(&self) -> io::Result<()> {
|
||||
if let Some(save_location) = &self.save_path {
|
||||
save_formatted_config_to_file(self, save_location)
|
||||
} else {
|
||||
debug!("config file save location is unknown. falling back to the default");
|
||||
self.save_to_default_location()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> String {
|
||||
@@ -248,16 +231,8 @@ impl Config {
|
||||
self.base.local_validator.clone()
|
||||
}
|
||||
|
||||
pub fn get_mixnet_contract_address(&self) -> nyxd::AccountId {
|
||||
self.base.mixnet_contract_address.clone()
|
||||
}
|
||||
|
||||
pub fn get_vesting_contract_address(&self) -> nyxd::AccountId {
|
||||
self.base.vesting_contract_address.clone()
|
||||
}
|
||||
|
||||
pub fn get_mnemonic(&self) -> bip39::Mnemonic {
|
||||
self.base.mnemonic.clone()
|
||||
pub fn get_mnemonic(&self) -> Option<&bip39::Mnemonic> {
|
||||
self.base.mnemonic.as_ref()
|
||||
}
|
||||
|
||||
pub fn get_ephemera_args(&self) -> &crate::ephemera::Args {
|
||||
@@ -278,23 +253,13 @@ pub struct Base {
|
||||
#[zeroize(skip)]
|
||||
pub local_validator: Url,
|
||||
|
||||
/// Address of the validator contract managing the network
|
||||
#[zeroize(skip)]
|
||||
pub mixnet_contract_address: nyxd::AccountId,
|
||||
|
||||
/// Address of the vesting contract holding locked tokens
|
||||
#[zeroize(skip)]
|
||||
pub vesting_contract_address: nyxd::AccountId,
|
||||
|
||||
/// Mnemonic used for rewarding and/or multisig operations
|
||||
// TODO: similarly to the note in gateway, this should get moved to a separate file
|
||||
mnemonic: bip39::Mnemonic,
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
mnemonic: Option<bip39::Mnemonic>,
|
||||
|
||||
/// Storage paths to the common nym-api files
|
||||
#[zeroize(skip)]
|
||||
// ideally we wouldn't be using default here, but I really really don't want to be writing
|
||||
// another big config migration
|
||||
#[serde(default)]
|
||||
pub storage_paths: NymApiPaths,
|
||||
}
|
||||
|
||||
@@ -310,10 +275,7 @@ impl Base {
|
||||
storage_paths: NymApiPaths::new_default(&id),
|
||||
id,
|
||||
local_validator: default_validator,
|
||||
mixnet_contract_address: mainnet::MIXNET_CONTRACT_ADDRESS.parse().unwrap(),
|
||||
vesting_contract_address: mainnet::VESTING_CONTRACT_ADDRESS.parse().unwrap(),
|
||||
// this this doesn't make any sense since you really have a mnemonic beforehand...
|
||||
mnemonic: bip39::Mnemonic::generate(24).unwrap(),
|
||||
mnemonic: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -561,7 +523,8 @@ pub struct CoconutSigner {
|
||||
/// Specifies whether rewarding service is enabled in this process.
|
||||
pub enabled: bool,
|
||||
|
||||
pub announce_address: Url,
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
pub announce_address: Option<Url>,
|
||||
|
||||
pub storage_paths: CoconutSignerPaths,
|
||||
|
||||
@@ -571,17 +534,9 @@ pub struct CoconutSigner {
|
||||
|
||||
impl CoconutSigner {
|
||||
pub fn new_default<P: AsRef<Path>>(id: P) -> Self {
|
||||
let default_validator: Url = DEFAULT_LOCAL_VALIDATOR
|
||||
.parse()
|
||||
.expect("default local validator is malformed!");
|
||||
let mut default_announce_address = default_validator;
|
||||
default_announce_address
|
||||
.set_port(Some(DEFAULT_NYM_API_PORT))
|
||||
.expect("default local validator is malformed!");
|
||||
|
||||
CoconutSigner {
|
||||
enabled: false,
|
||||
announce_address: default_announce_address,
|
||||
announce_address: None,
|
||||
storage_paths: CoconutSignerPaths::new_default(id),
|
||||
debug: Default::default(),
|
||||
}
|
||||
|
||||
@@ -1,374 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::support::config::persistence::{
|
||||
CoconutSignerPaths, NetworkMonitorPaths, NodeStatusAPIPaths,
|
||||
};
|
||||
use crate::support::config::{
|
||||
Base, CirculatingSupplyCacher, CirculatingSupplyCacherDebug, CoconutSigner, CoconutSignerDebug,
|
||||
Config, NetworkMonitor, NetworkMonitorDebug, NodeStatusAPI, NodeStatusAPIDebug, Rewarding,
|
||||
RewardingDebug, TopologyCacher, TopologyCacherDebug,
|
||||
};
|
||||
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
|
||||
use nym_validator_client::nyxd;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
const DEFAULT_NYM_API_PORT: u16 = 8080;
|
||||
const MIXNET_CONTRACT_ADDRESS: &str =
|
||||
"n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr";
|
||||
const VESTING_CONTRACT_ADDRESS: &str =
|
||||
"n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw";
|
||||
|
||||
const DEFAULT_LOCAL_VALIDATOR: &str = "http://localhost:26657";
|
||||
|
||||
const DEFAULT_DKG_CONTRACT_POLLING_RATE: Duration = Duration::from_secs(10);
|
||||
|
||||
const DEFAULT_GATEWAY_SENDING_RATE: usize = 200;
|
||||
const DEFAULT_MAX_CONCURRENT_GATEWAY_CLIENTS: usize = 50;
|
||||
const DEFAULT_PACKET_DELIVERY_TIMEOUT: Duration = Duration::from_secs(20);
|
||||
const DEFAULT_MONITOR_RUN_INTERVAL: Duration = Duration::from_secs(15 * 60);
|
||||
const DEFAULT_GATEWAY_PING_INTERVAL: Duration = Duration::from_secs(60);
|
||||
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
|
||||
// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the
|
||||
// bandwidth bridging protocol, we can come back to a smaller timeout value
|
||||
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
|
||||
// This timeout value should be big enough to accommodate an initial bandwidth acquirement
|
||||
const DEFAULT_GATEWAY_CONNECTION_TIMEOUT: Duration = Duration::from_secs(2 * 60);
|
||||
|
||||
const DEFAULT_TEST_ROUTES: usize = 3;
|
||||
const DEFAULT_MINIMUM_TEST_ROUTES: usize = 1;
|
||||
const DEFAULT_ROUTE_TEST_PACKETS: usize = 1000;
|
||||
const DEFAULT_PER_NODE_TEST_PACKETS: usize = 3;
|
||||
|
||||
const DEFAULT_TOPOLOGY_CACHE_INTERVAL: Duration = Duration::from_secs(30);
|
||||
const DEFAULT_NODE_STATUS_CACHE_INTERVAL: Duration = Duration::from_secs(120);
|
||||
const DEFAULT_CIRCULATING_SUPPLY_CACHE_INTERVAL: Duration = Duration::from_secs(3600);
|
||||
const DEFAULT_MONITOR_THRESHOLD: u8 = 60;
|
||||
const DEFAULT_MIN_MIXNODE_RELIABILITY: u8 = 50;
|
||||
const DEFAULT_MIN_GATEWAY_RELIABILITY: u8 = 20;
|
||||
|
||||
#[derive(Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV1_1_21 {
|
||||
#[serde(default)]
|
||||
base: BaseV1_1_21,
|
||||
|
||||
#[serde(default)]
|
||||
network_monitor: NetworkMonitorV1_1_21,
|
||||
|
||||
#[serde(default)]
|
||||
node_status_api: NodeStatusAPIV1_1_21,
|
||||
|
||||
#[serde(default)]
|
||||
topology_cacher: TopologyCacherV1_1_21,
|
||||
|
||||
#[serde(default)]
|
||||
circulating_supply_cacher: CirculatingSupplyCacherV1_1_21,
|
||||
|
||||
#[serde(default)]
|
||||
rewarding: RewardingV1_1_21,
|
||||
|
||||
#[serde(default)]
|
||||
coconut_signer: CoconutSignerV1_1_21,
|
||||
}
|
||||
|
||||
impl From<ConfigV1_1_21> for Config {
|
||||
fn from(value: ConfigV1_1_21) -> Self {
|
||||
// this value was never properly saved (probably a bug)
|
||||
// so explicitly set it to the default
|
||||
|
||||
let dkg_persistent_state_path =
|
||||
CoconutSignerV1_1_21::default_dkg_persistent_state_path(&value.base.id);
|
||||
|
||||
Config {
|
||||
base: Base {
|
||||
id: value.base.id,
|
||||
local_validator: value.base.local_validator,
|
||||
mixnet_contract_address: value.base.mixnet_contract_address,
|
||||
vesting_contract_address: value.base.vesting_contract_address,
|
||||
mnemonic: value.base.mnemonic,
|
||||
storage_paths: Default::default(),
|
||||
},
|
||||
network_monitor: NetworkMonitor {
|
||||
enabled: value.network_monitor.enabled,
|
||||
storage_paths: NetworkMonitorPaths {
|
||||
credentials_database_path: value.network_monitor.credentials_database_path,
|
||||
},
|
||||
debug: NetworkMonitorDebug {
|
||||
min_mixnode_reliability: value.network_monitor.min_mixnode_reliability,
|
||||
min_gateway_reliability: value.network_monitor.min_gateway_reliability,
|
||||
disabled_credentials_mode: value.network_monitor.disabled_credentials_mode,
|
||||
run_interval: value.network_monitor.run_interval,
|
||||
gateway_ping_interval: value.network_monitor.gateway_ping_interval,
|
||||
gateway_sending_rate: value.network_monitor.gateway_sending_rate,
|
||||
max_concurrent_gateway_clients: value
|
||||
.network_monitor
|
||||
.max_concurrent_gateway_clients,
|
||||
gateway_response_timeout: value.network_monitor.gateway_response_timeout,
|
||||
gateway_connection_timeout: value.network_monitor.gateway_connection_timeout,
|
||||
packet_delivery_timeout: value.network_monitor.packet_delivery_timeout,
|
||||
test_routes: value.network_monitor.test_routes,
|
||||
minimum_test_routes: value.network_monitor.minimum_test_routes,
|
||||
route_test_packets: value.network_monitor.route_test_packets,
|
||||
per_node_test_packets: value.network_monitor.per_node_test_packets,
|
||||
},
|
||||
},
|
||||
node_status_api: NodeStatusAPI {
|
||||
storage_paths: NodeStatusAPIPaths {
|
||||
database_path: value.node_status_api.database_path,
|
||||
},
|
||||
debug: NodeStatusAPIDebug {
|
||||
caching_interval: value.node_status_api.caching_interval,
|
||||
},
|
||||
},
|
||||
topology_cacher: TopologyCacher {
|
||||
debug: TopologyCacherDebug {
|
||||
caching_interval: value.topology_cacher.caching_interval,
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
circulating_supply_cacher: CirculatingSupplyCacher {
|
||||
enabled: value.circulating_supply_cacher.enabled,
|
||||
debug: CirculatingSupplyCacherDebug {
|
||||
caching_interval: value.circulating_supply_cacher.caching_interval,
|
||||
},
|
||||
},
|
||||
rewarding: Rewarding {
|
||||
enabled: value.rewarding.enabled,
|
||||
debug: RewardingDebug {
|
||||
minimum_interval_monitor_threshold: value
|
||||
.rewarding
|
||||
.minimum_interval_monitor_threshold,
|
||||
},
|
||||
},
|
||||
coconut_signer: CoconutSigner {
|
||||
enabled: value.coconut_signer.enabled,
|
||||
announce_address: value.base.announce_address,
|
||||
storage_paths: CoconutSignerPaths {
|
||||
dkg_persistent_state_path,
|
||||
verification_key_path: value.coconut_signer.verification_key_path,
|
||||
secret_key_path: value.coconut_signer.secret_key_path,
|
||||
decryption_key_path: value.coconut_signer.decryption_key_path,
|
||||
public_key_with_proof_path: value.coconut_signer.public_key_with_proof_path,
|
||||
},
|
||||
debug: CoconutSignerDebug {
|
||||
dkg_contract_polling_rate: value.coconut_signer.dkg_contract_polling_rate,
|
||||
},
|
||||
},
|
||||
ephemera: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MigrationNymConfig for ConfigV1_1_21 {
|
||||
fn default_root_directory() -> PathBuf {
|
||||
dirs::home_dir()
|
||||
.expect("Failed to evaluate $HOME value")
|
||||
.join(".nym")
|
||||
.join("nym-api")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct BaseV1_1_21 {
|
||||
/// ID specifies the human readable ID of this particular nym-api.
|
||||
id: String,
|
||||
|
||||
local_validator: Url,
|
||||
|
||||
/// Address announced to the directory server for the clients to connect to.
|
||||
// It is useful, say, in NAT scenarios or wanting to more easily update actual IP address
|
||||
// later on by using name resolvable with a DNS query, such as `nymtech.net`.
|
||||
announce_address: Url,
|
||||
|
||||
/// Address of the validator contract managing the network
|
||||
mixnet_contract_address: nyxd::AccountId,
|
||||
|
||||
/// Address of the vesting contract holding locked tokens
|
||||
vesting_contract_address: nyxd::AccountId,
|
||||
|
||||
/// Mnemonic used for rewarding and/or multisig operations
|
||||
mnemonic: bip39::Mnemonic,
|
||||
}
|
||||
|
||||
impl Default for BaseV1_1_21 {
|
||||
fn default() -> Self {
|
||||
let default_validator: Url = DEFAULT_LOCAL_VALIDATOR
|
||||
.parse()
|
||||
.expect("default local validator is malformed!");
|
||||
let mut default_announce_address = default_validator.clone();
|
||||
default_announce_address
|
||||
.set_port(Some(DEFAULT_NYM_API_PORT))
|
||||
.expect("default local validator is malformed!");
|
||||
|
||||
BaseV1_1_21 {
|
||||
id: String::default(),
|
||||
local_validator: default_validator,
|
||||
announce_address: default_announce_address,
|
||||
mixnet_contract_address: MIXNET_CONTRACT_ADDRESS.parse().unwrap(),
|
||||
vesting_contract_address: VESTING_CONTRACT_ADDRESS.parse().unwrap(),
|
||||
mnemonic: bip39::Mnemonic::generate(24).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NetworkMonitorV1_1_21 {
|
||||
min_mixnode_reliability: u8, // defaults to 50
|
||||
min_gateway_reliability: u8, // defaults to 20
|
||||
enabled: bool,
|
||||
#[serde(default)]
|
||||
disabled_credentials_mode: bool,
|
||||
#[serde(with = "humantime_serde")]
|
||||
run_interval: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
gateway_ping_interval: Duration,
|
||||
gateway_sending_rate: usize,
|
||||
max_concurrent_gateway_clients: usize,
|
||||
#[serde(with = "humantime_serde")]
|
||||
gateway_response_timeout: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
gateway_connection_timeout: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
packet_delivery_timeout: Duration,
|
||||
credentials_database_path: PathBuf,
|
||||
test_routes: usize,
|
||||
minimum_test_routes: usize,
|
||||
route_test_packets: usize,
|
||||
per_node_test_packets: usize,
|
||||
}
|
||||
|
||||
impl Default for NetworkMonitorV1_1_21 {
|
||||
fn default() -> Self {
|
||||
NetworkMonitorV1_1_21 {
|
||||
min_mixnode_reliability: DEFAULT_MIN_MIXNODE_RELIABILITY,
|
||||
min_gateway_reliability: DEFAULT_MIN_GATEWAY_RELIABILITY,
|
||||
enabled: false,
|
||||
disabled_credentials_mode: true,
|
||||
run_interval: DEFAULT_MONITOR_RUN_INTERVAL,
|
||||
gateway_ping_interval: DEFAULT_GATEWAY_PING_INTERVAL,
|
||||
gateway_sending_rate: DEFAULT_GATEWAY_SENDING_RATE,
|
||||
max_concurrent_gateway_clients: DEFAULT_MAX_CONCURRENT_GATEWAY_CLIENTS,
|
||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
gateway_connection_timeout: DEFAULT_GATEWAY_CONNECTION_TIMEOUT,
|
||||
packet_delivery_timeout: DEFAULT_PACKET_DELIVERY_TIMEOUT,
|
||||
credentials_database_path: Default::default(),
|
||||
test_routes: DEFAULT_TEST_ROUTES,
|
||||
minimum_test_routes: DEFAULT_MINIMUM_TEST_ROUTES,
|
||||
route_test_packets: DEFAULT_ROUTE_TEST_PACKETS,
|
||||
per_node_test_packets: DEFAULT_PER_NODE_TEST_PACKETS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NodeStatusAPIV1_1_21 {
|
||||
database_path: PathBuf,
|
||||
#[serde(with = "humantime_serde")]
|
||||
caching_interval: Duration,
|
||||
}
|
||||
|
||||
impl Default for NodeStatusAPIV1_1_21 {
|
||||
fn default() -> Self {
|
||||
NodeStatusAPIV1_1_21 {
|
||||
database_path: Default::default(),
|
||||
caching_interval: DEFAULT_NODE_STATUS_CACHE_INTERVAL,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct TopologyCacherV1_1_21 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
caching_interval: Duration,
|
||||
}
|
||||
|
||||
impl Default for TopologyCacherV1_1_21 {
|
||||
fn default() -> Self {
|
||||
TopologyCacherV1_1_21 {
|
||||
caching_interval: DEFAULT_TOPOLOGY_CACHE_INTERVAL,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CirculatingSupplyCacherV1_1_21 {
|
||||
enabled: bool,
|
||||
|
||||
#[serde(with = "humantime_serde")]
|
||||
caching_interval: Duration,
|
||||
}
|
||||
|
||||
impl Default for CirculatingSupplyCacherV1_1_21 {
|
||||
fn default() -> Self {
|
||||
CirculatingSupplyCacherV1_1_21 {
|
||||
enabled: true,
|
||||
caching_interval: DEFAULT_CIRCULATING_SUPPLY_CACHE_INTERVAL,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct RewardingV1_1_21 {
|
||||
enabled: bool,
|
||||
minimum_interval_monitor_threshold: u8,
|
||||
}
|
||||
|
||||
impl Default for RewardingV1_1_21 {
|
||||
fn default() -> Self {
|
||||
RewardingV1_1_21 {
|
||||
enabled: false,
|
||||
minimum_interval_monitor_threshold: DEFAULT_MONITOR_THRESHOLD,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CoconutSignerV1_1_21 {
|
||||
enabled: bool,
|
||||
dkg_persistent_state_path: PathBuf,
|
||||
verification_key_path: PathBuf,
|
||||
secret_key_path: PathBuf,
|
||||
decryption_key_path: PathBuf,
|
||||
public_key_with_proof_path: PathBuf,
|
||||
dkg_contract_polling_rate: Duration,
|
||||
}
|
||||
|
||||
impl CoconutSignerV1_1_21 {
|
||||
pub const DKG_PERSISTENT_STATE_FILE: &'static str = "dkg_persistent_state.json";
|
||||
|
||||
fn default_dkg_persistent_state_path(id: &str) -> PathBuf {
|
||||
ConfigV1_1_21::default_data_directory(id).join(Self::DKG_PERSISTENT_STATE_FILE)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CoconutSignerV1_1_21 {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
enabled: Default::default(),
|
||||
dkg_persistent_state_path: Default::default(),
|
||||
verification_key_path: Default::default(),
|
||||
secret_key_path: Default::default(),
|
||||
decryption_key_path: Default::default(),
|
||||
public_key_with_proof_path: Default::default(),
|
||||
dkg_contract_polling_rate: DEFAULT_DKG_CONTRACT_POLLING_RATE,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,269 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::support::config::persistence::{
|
||||
CoconutSignerPaths, NetworkMonitorPaths, NodeStatusAPIPaths,
|
||||
};
|
||||
use crate::support::config::{
|
||||
Base, CirculatingSupplyCacher, CoconutSigner, CoconutSignerDebug, Config, Ephemera,
|
||||
NetworkMonitor, NetworkMonitorDebug, NodeStatusAPI, NodeStatusAPIDebug, Rewarding,
|
||||
TopologyCacher,
|
||||
};
|
||||
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
|
||||
use nym_validator_client::nyxd;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
use url::Url;
|
||||
|
||||
const DEFAULT_NYM_API_PORT: u16 = 8080;
|
||||
const MIXNET_CONTRACT_ADDRESS: &str =
|
||||
"n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr";
|
||||
const VESTING_CONTRACT_ADDRESS: &str =
|
||||
"n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw";
|
||||
|
||||
const DEFAULT_LOCAL_VALIDATOR: &str = "http://localhost:26657";
|
||||
|
||||
#[derive(Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV1_1_27 {
|
||||
#[serde(default)]
|
||||
base: BaseV1_1_27,
|
||||
|
||||
#[serde(default)]
|
||||
network_monitor: NetworkMonitorV1_1_27,
|
||||
|
||||
#[serde(default)]
|
||||
node_status_api: NodeStatusAPIV1_1_27,
|
||||
|
||||
#[serde(default)]
|
||||
topology_cacher: TopologyCacher,
|
||||
|
||||
#[serde(default)]
|
||||
circulating_supply_cacher: CirculatingSupplyCacher,
|
||||
|
||||
#[serde(default)]
|
||||
rewarding: Rewarding,
|
||||
|
||||
#[serde(default)]
|
||||
coconut_signer: CoconutSignerV1_1_27,
|
||||
}
|
||||
|
||||
impl From<ConfigV1_1_27> for Config {
|
||||
fn from(value: ConfigV1_1_27) -> Self {
|
||||
// this value was never properly saved (probably a bug)
|
||||
// so explicitly set it to the default
|
||||
|
||||
Config {
|
||||
base: Base {
|
||||
id: value.base.id.clone(),
|
||||
local_validator: value.base.local_validator,
|
||||
mixnet_contract_address: value.base.mixnet_contract_address,
|
||||
vesting_contract_address: value.base.vesting_contract_address,
|
||||
mnemonic: value.base.mnemonic,
|
||||
storage_paths: Default::default(),
|
||||
},
|
||||
network_monitor: NetworkMonitor {
|
||||
enabled: value.network_monitor.enabled,
|
||||
storage_paths: NetworkMonitorPaths {
|
||||
credentials_database_path: value
|
||||
.network_monitor
|
||||
.storage_paths
|
||||
.credentials_database_path,
|
||||
},
|
||||
debug: NetworkMonitorDebug {
|
||||
min_mixnode_reliability: value.network_monitor.debug.min_mixnode_reliability,
|
||||
min_gateway_reliability: value.network_monitor.debug.min_gateway_reliability,
|
||||
disabled_credentials_mode: value
|
||||
.network_monitor
|
||||
.debug
|
||||
.disabled_credentials_mode,
|
||||
run_interval: value.network_monitor.debug.run_interval,
|
||||
gateway_ping_interval: value.network_monitor.debug.gateway_ping_interval,
|
||||
gateway_sending_rate: value.network_monitor.debug.gateway_sending_rate,
|
||||
max_concurrent_gateway_clients: value
|
||||
.network_monitor
|
||||
.debug
|
||||
.max_concurrent_gateway_clients,
|
||||
gateway_response_timeout: value.network_monitor.debug.gateway_response_timeout,
|
||||
gateway_connection_timeout: value
|
||||
.network_monitor
|
||||
.debug
|
||||
.gateway_connection_timeout,
|
||||
packet_delivery_timeout: value.network_monitor.debug.packet_delivery_timeout,
|
||||
test_routes: value.network_monitor.debug.test_routes,
|
||||
minimum_test_routes: value.network_monitor.debug.minimum_test_routes,
|
||||
route_test_packets: value.network_monitor.debug.route_test_packets,
|
||||
per_node_test_packets: value.network_monitor.debug.per_node_test_packets,
|
||||
},
|
||||
},
|
||||
node_status_api: NodeStatusAPI {
|
||||
storage_paths: NodeStatusAPIPaths {
|
||||
database_path: value.node_status_api.storage_paths.database_path,
|
||||
},
|
||||
debug: NodeStatusAPIDebug {
|
||||
caching_interval: value.node_status_api.debug.caching_interval,
|
||||
},
|
||||
},
|
||||
topology_cacher: value.topology_cacher,
|
||||
circulating_supply_cacher: value.circulating_supply_cacher,
|
||||
rewarding: value.rewarding,
|
||||
coconut_signer: CoconutSigner {
|
||||
enabled: value.coconut_signer.enabled,
|
||||
announce_address: value.base.announce_address,
|
||||
storage_paths: CoconutSignerPaths {
|
||||
dkg_persistent_state_path: value
|
||||
.coconut_signer
|
||||
.storage_paths
|
||||
.dkg_persistent_state_path,
|
||||
verification_key_path: value.coconut_signer.storage_paths.verification_key_path,
|
||||
secret_key_path: value.coconut_signer.storage_paths.secret_key_path,
|
||||
decryption_key_path: value.coconut_signer.storage_paths.decryption_key_path,
|
||||
public_key_with_proof_path: value
|
||||
.coconut_signer
|
||||
.storage_paths
|
||||
.public_key_with_proof_path,
|
||||
},
|
||||
debug: CoconutSignerDebug {
|
||||
dkg_contract_polling_rate: value.coconut_signer.debug.dkg_contract_polling_rate,
|
||||
},
|
||||
},
|
||||
ephemera: Ephemera::new_default(&value.base.id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MigrationNymConfig for ConfigV1_1_27 {
|
||||
fn default_root_directory() -> PathBuf {
|
||||
dirs::home_dir()
|
||||
.expect("Failed to evaluate $HOME value")
|
||||
.join(".nym")
|
||||
.join("nym-api")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct BaseV1_1_27 {
|
||||
/// ID specifies the human readable ID of this particular nym-api.
|
||||
id: String,
|
||||
|
||||
local_validator: Url,
|
||||
|
||||
/// Address announced to the directory server for the clients to connect to.
|
||||
// It is useful, say, in NAT scenarios or wanting to more easily update actual IP address
|
||||
// later on by using name resolvable with a DNS query, such as `nymtech.net`.
|
||||
announce_address: Url,
|
||||
|
||||
/// Address of the validator contract managing the network
|
||||
mixnet_contract_address: nyxd::AccountId,
|
||||
|
||||
/// Address of the vesting contract holding locked tokens
|
||||
vesting_contract_address: nyxd::AccountId,
|
||||
|
||||
/// Mnemonic used for rewarding and/or multisig operations
|
||||
mnemonic: bip39::Mnemonic,
|
||||
}
|
||||
|
||||
impl Default for BaseV1_1_27 {
|
||||
fn default() -> Self {
|
||||
let default_validator: Url = DEFAULT_LOCAL_VALIDATOR
|
||||
.parse()
|
||||
.expect("default local validator is malformed!");
|
||||
let mut default_announce_address = default_validator.clone();
|
||||
default_announce_address
|
||||
.set_port(Some(DEFAULT_NYM_API_PORT))
|
||||
.expect("default local validator is malformed!");
|
||||
|
||||
BaseV1_1_27 {
|
||||
id: String::default(),
|
||||
local_validator: default_validator,
|
||||
announce_address: default_announce_address,
|
||||
mixnet_contract_address: MIXNET_CONTRACT_ADDRESS.parse().unwrap(),
|
||||
vesting_contract_address: VESTING_CONTRACT_ADDRESS.parse().unwrap(),
|
||||
mnemonic: bip39::Mnemonic::generate(24).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NetworkMonitorV1_1_27 {
|
||||
/// Specifies whether network monitoring service is enabled in this process.
|
||||
pub enabled: bool,
|
||||
|
||||
pub storage_paths: NetworkMonitorPaths,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: NetworkMonitorDebug,
|
||||
}
|
||||
|
||||
impl Default for NetworkMonitorV1_1_27 {
|
||||
fn default() -> Self {
|
||||
NetworkMonitorV1_1_27 {
|
||||
enabled: false,
|
||||
storage_paths: NetworkMonitorPaths {
|
||||
credentials_database_path: Default::default(),
|
||||
},
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NodeStatusAPIV1_1_27 {
|
||||
// pub enabled: bool,
|
||||
pub storage_paths: NodeStatusAPIPaths,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: NodeStatusAPIDebug,
|
||||
}
|
||||
|
||||
impl Default for NodeStatusAPIV1_1_27 {
|
||||
fn default() -> Self {
|
||||
NodeStatusAPIV1_1_27 {
|
||||
storage_paths: NodeStatusAPIPaths {
|
||||
database_path: Default::default(),
|
||||
},
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CoconutSignerV1_1_27 {
|
||||
/// Specifies whether rewarding service is enabled in this process.
|
||||
pub enabled: bool,
|
||||
|
||||
pub announce_address: Url,
|
||||
|
||||
pub storage_paths: CoconutSignerPaths,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: CoconutSignerDebug,
|
||||
}
|
||||
|
||||
impl Default for CoconutSignerV1_1_27 {
|
||||
fn default() -> Self {
|
||||
let announce_address: Url = DEFAULT_LOCAL_VALIDATOR
|
||||
.parse()
|
||||
.expect("default local validator is malformed!");
|
||||
CoconutSignerV1_1_27 {
|
||||
enabled: Default::default(),
|
||||
announce_address,
|
||||
storage_paths: CoconutSignerPaths {
|
||||
dkg_persistent_state_path: Default::default(),
|
||||
verification_key_path: Default::default(),
|
||||
secret_key_path: Default::default(),
|
||||
decryption_key_path: Default::default(),
|
||||
public_key_with_proof_path: Default::default(),
|
||||
},
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::support::cli::{init, run};
|
||||
|
||||
// Configuration that can be overridden.
|
||||
pub(crate) struct OverrideConfig {
|
||||
/// Specifies whether network monitoring is enabled on this API
|
||||
pub(crate) enable_monitor: Option<bool>,
|
||||
|
||||
/// Specifies whether network rewarding is enabled on this API
|
||||
pub(crate) enable_rewarding: Option<bool>,
|
||||
|
||||
/// Endpoint to nyxd instance used for contract information.
|
||||
pub(crate) nyxd_validator: Option<url::Url>,
|
||||
|
||||
/// Mnemonic of the network monitor used for sending rewarding and zk-nyms transactions
|
||||
pub(crate) mnemonic: Option<bip39::Mnemonic>,
|
||||
|
||||
/// Flag to indicate whether coconut signer authority is enabled on this API
|
||||
pub(crate) enable_zk_nym: Option<bool>,
|
||||
|
||||
/// Announced address that is going to be put in the DKG contract where zk-nym clients will connect
|
||||
/// to obtain their credentials
|
||||
pub(crate) announce_address: Option<url::Url>,
|
||||
|
||||
/// Set this nym api to work in a enabled credentials that would attempt to use gateway with the bandwidth credential requirement
|
||||
pub(crate) monitor_credentials_mode: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<init::Args> for OverrideConfig {
|
||||
fn from(args: init::Args) -> Self {
|
||||
OverrideConfig {
|
||||
enable_monitor: Some(args.enable_monitor),
|
||||
enable_rewarding: Some(args.enable_rewarding),
|
||||
nyxd_validator: args.nyxd_validator,
|
||||
mnemonic: args.mnemonic,
|
||||
enable_zk_nym: Some(args.enable_zk_nym),
|
||||
announce_address: args.announce_address,
|
||||
monitor_credentials_mode: Some(args.monitor_credentials_mode),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<run::Args> for OverrideConfig {
|
||||
fn from(args: run::Args) -> Self {
|
||||
OverrideConfig {
|
||||
enable_monitor: args.enable_monitor,
|
||||
enable_rewarding: args.enable_rewarding,
|
||||
nyxd_validator: args.nyxd_validator,
|
||||
mnemonic: args.mnemonic,
|
||||
enable_zk_nym: args.enable_zk_nym,
|
||||
announce_address: args.announce_address,
|
||||
monitor_credentials_mode: args.monitor_credentials_mode,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,8 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::support::config::default_data_directory;
|
||||
use anyhow::{anyhow, Context};
|
||||
use nym_config::serde_helpers::de_maybe_stringified;
|
||||
use anyhow::Context;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use rand_07::rngs::OsRng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@@ -111,12 +109,10 @@ impl CoconutSignerPaths {
|
||||
#[serde(default)]
|
||||
pub struct NymApiPaths {
|
||||
/// Path to file containing private identity key of the nym-api.
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
pub private_identity_key_file: Option<PathBuf>,
|
||||
pub private_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing public identity key of the nym-api.
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
pub public_identity_key_file: Option<PathBuf>,
|
||||
pub public_identity_key_file: PathBuf,
|
||||
}
|
||||
|
||||
impl NymApiPaths {
|
||||
@@ -124,48 +120,19 @@ impl NymApiPaths {
|
||||
let data_dir = default_data_directory(id);
|
||||
|
||||
NymApiPaths {
|
||||
private_identity_key_file: Some(data_dir.join(DEFAULT_PRIVATE_IDENTITY_KEY_FILENAME)),
|
||||
public_identity_key_file: Some(data_dir.join(DEFAULT_PUBLIC_IDENTITY_KEY_FILENAME)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_identity_if_missing<P: AsRef<Path>>(&mut self, id: P) -> anyhow::Result<bool> {
|
||||
if self.private_identity_key_file.is_none() {
|
||||
log::warn!("identity key paths are not set - going to generate a fresh pair!");
|
||||
|
||||
let data_dir = default_data_directory(id);
|
||||
self.private_identity_key_file =
|
||||
Some(data_dir.join(DEFAULT_PRIVATE_IDENTITY_KEY_FILENAME));
|
||||
self.public_identity_key_file =
|
||||
Some(data_dir.join(DEFAULT_PUBLIC_IDENTITY_KEY_FILENAME));
|
||||
|
||||
let keypaths = nym_pemstore::KeyPairPath::new(
|
||||
self.private_identity_key_file.as_ref().unwrap(),
|
||||
self.public_identity_key_file.as_ref().unwrap(),
|
||||
);
|
||||
|
||||
let mut rng = OsRng;
|
||||
let keypair = identity::KeyPair::new(&mut rng);
|
||||
|
||||
nym_pemstore::store_keypair(&keypair, &keypaths)
|
||||
.context("failed to store identity keys of the nym api")?;
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
private_identity_key_file: data_dir.join(DEFAULT_PRIVATE_IDENTITY_KEY_FILENAME),
|
||||
public_identity_key_file: data_dir.join(DEFAULT_PUBLIC_IDENTITY_KEY_FILENAME),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_identity(&self) -> anyhow::Result<identity::KeyPair> {
|
||||
// if somebody has set their private key but removed public key, the panic is totally on them.
|
||||
let keypaths = nym_pemstore::KeyPairPath::new(
|
||||
self.private_identity_key_file
|
||||
.as_ref()
|
||||
.ok_or(anyhow!("private key path is not specified"))?,
|
||||
self.public_identity_key_file
|
||||
.as_ref()
|
||||
.ok_or(anyhow!("public key path is not specified"))?,
|
||||
&self.private_identity_key_file,
|
||||
&self.public_identity_key_file,
|
||||
);
|
||||
|
||||
nym_pemstore::load_keypair(&keypaths).context("failed to load identity keys of the nym api")
|
||||
nym_pemstore::load_keypair(&keypaths).context(format!(
|
||||
"failed to load identity keys of the nym api. paths: {keypaths:?}"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,21 +15,15 @@ id = '{{ base.id }}'
|
||||
# Validator server to which the API will be getting information about the network.
|
||||
local_validator = '{{ base.local_validator }}'
|
||||
|
||||
# Address of the validator contract managing the network.
|
||||
mixnet_contract_address = '{{ base.mixnet_contract_address }}'
|
||||
|
||||
# Address of the vesting contract holding locked tokens
|
||||
vesting_contract_address = '{{ base.vesting_contract_address }}'
|
||||
|
||||
# Mnemonic used for rewarding and validator interaction
|
||||
mnemonic = '{{ base.mnemonic }}'
|
||||
|
||||
[base.storage_paths]
|
||||
# Path to file containing private identity key of the nym-api.
|
||||
keys.private_identity_key_file = '{{ base.storage_paths.private_identity_key_file }}'
|
||||
private_identity_key_file = '{{ base.storage_paths.private_identity_key_file }}'
|
||||
|
||||
# Path to file containing public identity key of the nym-api.
|
||||
keys.public_identity_key_file = '{{ base.storage_paths.public_identity_key_file }}'
|
||||
public_identity_key_file = '{{ base.storage_paths.public_identity_key_file }}'
|
||||
|
||||
##### network monitor config options #####
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
pub(crate) fn try_upgrade_config(_id: &str) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
+166
-150
@@ -16,7 +16,7 @@ use nym_coconut_dkg_common::{
|
||||
types::{EncodedBTEPublicKeyWithProof, Epoch, EpochId},
|
||||
verification_key::{ContractVKShare, VerificationKeyShare},
|
||||
};
|
||||
use nym_config::defaults::ChainDetails;
|
||||
use nym_config::defaults::{ChainDetails, NymNetworkDetails};
|
||||
use nym_contracts_common::dealings::ContractSafeBytes;
|
||||
use nym_ephemera_common::msg::QueryMsg as EphemeraQueryMsg;
|
||||
use nym_ephemera_common::types::JsonPeerInfo;
|
||||
@@ -46,77 +46,122 @@ use nym_validator_client::nyxd::{
|
||||
hash::{Hash, SHA256_HASH_SIZE},
|
||||
AccountId, Coin, TendermintTime,
|
||||
};
|
||||
use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient};
|
||||
use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient, QueryHttpRpcNyxdClient};
|
||||
use nym_vesting_contract_common::AccountVestingCoins;
|
||||
use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::{RwLock, RwLockReadGuard};
|
||||
|
||||
pub(crate) struct Client(pub(crate) Arc<RwLock<DirectSigningHttpRpcNyxdClient>>);
|
||||
#[macro_export]
|
||||
macro_rules! query_guard {
|
||||
($guard:expr, $($op:tt)*) => {{
|
||||
match &*$guard {
|
||||
$crate::support::nyxd::ClientInner::Signing(client) => client.$($op)*,
|
||||
$crate::support::nyxd::ClientInner::Query(client) => client.$($op)*,
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
impl Clone for Client {
|
||||
fn clone(&self) -> Self {
|
||||
Client(Arc::clone(&self.0))
|
||||
}
|
||||
macro_rules! nyxd_query {
|
||||
($self:expr, $($op:tt)*) => {{
|
||||
let guard = $self.inner.read().await;
|
||||
match &*guard {
|
||||
$crate::support::nyxd::ClientInner::Signing(client) => client.$($op)*,
|
||||
$crate::support::nyxd::ClientInner::Query(client) => client.$($op)*,
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! nyxd_signing_shared {
|
||||
($self:expr, $($op:tt)*) => {{
|
||||
let guard = $self.inner.read().await;
|
||||
match &*guard {
|
||||
$crate::support::nyxd::ClientInner::Signing(client) => client.$($op)*,
|
||||
$crate::support::nyxd::ClientInner::Query(_) => panic!("attempted to use a signing method on a query client"),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! nyxd_signing {
|
||||
($self:expr, $($op:tt)*) => {{
|
||||
let guard = $self.inner.write().await;
|
||||
match &*guard {
|
||||
$crate::support::nyxd::ClientInner::Signing(client) => client.$($op)*,
|
||||
$crate::support::nyxd::ClientInner::Query(_) => panic!("attempted to use a signing method on a query client"),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct Client {
|
||||
inner: Arc<RwLock<ClientInner>>,
|
||||
}
|
||||
|
||||
pub enum ClientInner {
|
||||
Signing(DirectSigningHttpRpcNyxdClient),
|
||||
Query(QueryHttpRpcNyxdClient),
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub(crate) fn new(config: &Config) -> Self {
|
||||
let details = config.get_network_details();
|
||||
let details = NymNetworkDetails::new_from_env();
|
||||
let nyxd_url = config.get_nyxd_url();
|
||||
|
||||
let client_config = nyxd::Config::try_from_nym_network_details(&details)
|
||||
.expect("failed to construct valid validator client config with the provided network");
|
||||
|
||||
let mnemonic = config.get_mnemonic();
|
||||
let inner = if let Some(mnemonic) = config.get_mnemonic() {
|
||||
ClientInner::Signing(
|
||||
DirectSigningHttpRpcNyxdClient::connect_with_mnemonic(
|
||||
client_config,
|
||||
nyxd_url.as_str(),
|
||||
mnemonic.clone(),
|
||||
)
|
||||
.expect("Failed to connect to nyxd!"),
|
||||
)
|
||||
} else {
|
||||
ClientInner::Query(
|
||||
QueryHttpRpcNyxdClient::connect(client_config, nyxd_url.as_str())
|
||||
.expect("Failed to connect to nyxd!"),
|
||||
)
|
||||
};
|
||||
|
||||
let inner = DirectSigningHttpRpcNyxdClient::connect_with_mnemonic(
|
||||
client_config,
|
||||
nyxd_url.as_str(),
|
||||
mnemonic,
|
||||
)
|
||||
.expect("Failed to connect to nyxd!");
|
||||
|
||||
Client(Arc::new(RwLock::new(inner)))
|
||||
Client {
|
||||
inner: Arc::new(RwLock::new(inner)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn read(&self) -> RwLockReadGuard<'_, DirectSigningHttpRpcNyxdClient> {
|
||||
self.0.read().await
|
||||
pub(crate) async fn read(&self) -> RwLockReadGuard<'_, ClientInner> {
|
||||
self.inner.read().await
|
||||
}
|
||||
|
||||
pub(crate) async fn client_address(&self) -> AccountId {
|
||||
self.0.read().await.address()
|
||||
nyxd_signing_shared!(self, address())
|
||||
}
|
||||
|
||||
pub(crate) async fn balance<S: Into<String>>(&self, denom: S) -> Result<Coin, NyxdError> {
|
||||
let guard = self.0.read().await;
|
||||
let address = self.client_address().await;
|
||||
let denom = denom.into();
|
||||
let address = guard.address();
|
||||
match self
|
||||
.0
|
||||
.read()
|
||||
.await
|
||||
.get_balance(&address, denom.clone())
|
||||
.await?
|
||||
{
|
||||
let balance = nyxd_query!(self, get_balance(&address, denom.clone()).await?);
|
||||
|
||||
match balance {
|
||||
None => Ok(Coin::new(0, denom)),
|
||||
Some(coin) => Ok(coin),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn chain_details(&self) -> ChainDetails {
|
||||
self.0.read().await.current_chain_details().clone()
|
||||
nyxd_query!(self, current_chain_details().clone())
|
||||
}
|
||||
|
||||
pub(crate) async fn get_rewarding_validator_address(&self) -> Result<AccountId, NyxdError> {
|
||||
let cosmwasm_addr = self
|
||||
.0
|
||||
.read()
|
||||
.await
|
||||
.get_mixnet_contract_state()
|
||||
.await?
|
||||
.rewarding_validator_address
|
||||
.into_string();
|
||||
let cosmwasm_addr = nyxd_query!(
|
||||
self,
|
||||
get_mixnet_contract_state()
|
||||
.await?
|
||||
.rewarding_validator_address
|
||||
.into_string()
|
||||
);
|
||||
|
||||
// this should never fail otherwise it implies either
|
||||
// 1) our mixnet contract state is invalid
|
||||
@@ -132,7 +177,7 @@ impl Client {
|
||||
// a helper function for the future to obtain the current block timestamp
|
||||
#[allow(dead_code)]
|
||||
pub(crate) async fn current_block_timestamp(&self) -> Result<TendermintTime, NyxdError> {
|
||||
let time = self.0.read().await.get_current_block_timestamp().await?;
|
||||
let time = nyxd_query!(self, get_current_block_timestamp().await?);
|
||||
|
||||
Ok(time)
|
||||
}
|
||||
@@ -148,7 +193,7 @@ impl Client {
|
||||
&self,
|
||||
height: u32,
|
||||
) -> Result<Option<[u8; SHA256_HASH_SIZE]>, NyxdError> {
|
||||
let hash = match self.0.read().await.get_block_hash(height).await? {
|
||||
let hash = match nyxd_query!(self, get_block_hash(height).await?) {
|
||||
Hash::Sha256(hash) => Some(hash),
|
||||
Hash::None => None,
|
||||
};
|
||||
@@ -157,44 +202,46 @@ impl Client {
|
||||
}
|
||||
|
||||
pub(crate) async fn get_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NyxdError> {
|
||||
self.0.read().await.get_all_mixnodes_detailed().await
|
||||
nyxd_query!(self, get_all_mixnodes_detailed().await)
|
||||
}
|
||||
|
||||
pub(crate) async fn get_gateways(&self) -> Result<Vec<GatewayBond>, NyxdError> {
|
||||
self.0.read().await.get_all_gateways().await
|
||||
nyxd_query!(self, get_all_gateways().await)
|
||||
}
|
||||
|
||||
pub(crate) async fn get_current_interval(&self) -> Result<CurrentIntervalResponse, NyxdError> {
|
||||
self.0.read().await.get_current_interval_details().await
|
||||
nyxd_query!(self, get_current_interval_details().await)
|
||||
}
|
||||
|
||||
pub(crate) async fn get_current_epoch_status(&self) -> Result<EpochStatus, NyxdError> {
|
||||
self.0.read().await.get_current_epoch_status().await
|
||||
nyxd_query!(self, get_current_epoch_status().await)
|
||||
}
|
||||
|
||||
pub(crate) async fn get_current_rewarding_parameters(
|
||||
&self,
|
||||
) -> Result<RewardingParams, NyxdError> {
|
||||
self.0.read().await.get_rewarding_parameters().await
|
||||
nyxd_query!(self, get_rewarding_parameters().await)
|
||||
}
|
||||
|
||||
pub(crate) async fn get_rewarded_set_mixnodes(
|
||||
&self,
|
||||
) -> Result<Vec<(MixId, RewardedSetNodeStatus)>, NyxdError> {
|
||||
self.0.read().await.get_all_rewarded_set_mixnodes().await
|
||||
nyxd_query!(self, get_all_rewarded_set_mixnodes().await)
|
||||
}
|
||||
|
||||
pub(crate) async fn get_current_vesting_account_storage_key(&self) -> Result<u32, NyxdError> {
|
||||
let guard = self.0.read().await;
|
||||
let guard = self.inner.read().await;
|
||||
|
||||
// the expect is fine as we always construct the client with the vesting contract explicitly set
|
||||
let vesting_contract = guard
|
||||
.vesting_contract_address()
|
||||
.expect("vesting contract address is not available");
|
||||
let vesting_contract = query_guard!(
|
||||
guard,
|
||||
vesting_contract_address().expect("vesting contract address is not available")
|
||||
);
|
||||
// TODO: I don't like the usage of the hardcoded value here
|
||||
let res = guard
|
||||
.query_contract_raw(vesting_contract, b"key".to_vec())
|
||||
.await?;
|
||||
let res = query_guard!(
|
||||
guard,
|
||||
query_contract_raw(vesting_contract, b"key".to_vec()).await?
|
||||
);
|
||||
if res.is_empty() {
|
||||
return Ok(0);
|
||||
}
|
||||
@@ -205,22 +252,22 @@ impl Client {
|
||||
pub(crate) async fn get_all_vesting_coins(
|
||||
&self,
|
||||
) -> Result<Vec<AccountVestingCoins>, NyxdError> {
|
||||
self.0.read().await.get_all_accounts_vesting_coins().await
|
||||
nyxd_query!(self, get_all_accounts_vesting_coins().await)
|
||||
}
|
||||
|
||||
pub(crate) async fn get_all_family_members(
|
||||
&self,
|
||||
) -> Result<Vec<(IdentityKey, FamilyHead)>, NyxdError> {
|
||||
self.0.read().await.get_all_family_members().await
|
||||
nyxd_query!(self, get_all_family_members().await)
|
||||
}
|
||||
|
||||
pub(crate) async fn get_pending_events_count(&self) -> Result<u32, NyxdError> {
|
||||
let pending = self.0.read().await.get_number_of_pending_events().await?;
|
||||
let pending = nyxd_query!(self, get_number_of_pending_events().await?);
|
||||
Ok(pending.epoch_events + pending.interval_events)
|
||||
}
|
||||
|
||||
pub(crate) async fn begin_epoch_transition(&self) -> Result<(), NyxdError> {
|
||||
self.0.write().await.begin_epoch_transition(None).await?;
|
||||
nyxd_signing!(self, begin_epoch_transition(None).await?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -247,26 +294,29 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
// "technically" we don't need a write access to the client,
|
||||
// but we REALLY don't want to accidentally send any transactions while we're sending rewarding messages
|
||||
// as that would have messed up sequence numbers
|
||||
let guard = self.0.write().await;
|
||||
|
||||
// the expect is fine as we always construct the client with the mixnet contract explicitly set
|
||||
let mixnet_contract = guard
|
||||
.mixnet_contract_address()
|
||||
.expect("mixnet contract address is not available");
|
||||
let mixnet_contract = nyxd_query!(
|
||||
self,
|
||||
mixnet_contract_address()
|
||||
.expect("mixnet contract address is not available")
|
||||
.clone()
|
||||
);
|
||||
|
||||
let msgs = generate_reward_messages(nodes);
|
||||
|
||||
guard
|
||||
.execute_multiple(
|
||||
mixnet_contract,
|
||||
// "technically" we don't need a write access to the client,
|
||||
// but we REALLY don't want to accidentally send any transactions while we're sending rewarding messages
|
||||
// as that would have messed up sequence numbers
|
||||
nyxd_signing!(
|
||||
self,
|
||||
execute_multiple(
|
||||
&mixnet_contract,
|
||||
msgs,
|
||||
Default::default(),
|
||||
format!("rewarding {} mixnodes", nodes.len()),
|
||||
)
|
||||
.await?;
|
||||
.await?
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -275,20 +325,15 @@ impl Client {
|
||||
new_rewarded_set: Vec<LayerAssignment>,
|
||||
expected_active_set_size: u32,
|
||||
) -> Result<(), NyxdError> {
|
||||
self.0
|
||||
.write()
|
||||
.await
|
||||
.advance_current_epoch(new_rewarded_set, expected_active_set_size, None)
|
||||
.await?;
|
||||
nyxd_signing!(
|
||||
self,
|
||||
advance_current_epoch(new_rewarded_set, expected_active_set_size, None).await?
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn reconcile_epoch_events(&self, limit: Option<u32>) -> Result<(), NyxdError> {
|
||||
self.0
|
||||
.write()
|
||||
.await
|
||||
.reconcile_epoch_events(limit, None)
|
||||
.await?;
|
||||
nyxd_signing!(self, reconcile_epoch_events(limit, None).await?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -300,7 +345,7 @@ impl crate::coconut::client::Client for Client {
|
||||
}
|
||||
|
||||
async fn get_tx(&self, tx_hash: Hash) -> crate::coconut::error::Result<nyxd::TxResponse> {
|
||||
self.0.read().await.get_tx(tx_hash).await.map_err(|source| {
|
||||
nyxd_query!(self, get_tx(tx_hash).await).map_err(|source| {
|
||||
CoconutError::TxRetrievalFailure {
|
||||
tx_hash: tx_hash.to_string(),
|
||||
source,
|
||||
@@ -312,78 +357,69 @@ impl crate::coconut::client::Client for Client {
|
||||
&self,
|
||||
proposal_id: u64,
|
||||
) -> crate::coconut::error::Result<ProposalResponse> {
|
||||
Ok(self.0.read().await.query_proposal(proposal_id).await?)
|
||||
Ok(nyxd_query!(self, query_proposal(proposal_id).await?))
|
||||
}
|
||||
|
||||
async fn list_proposals(&self) -> crate::coconut::error::Result<Vec<ProposalResponse>> {
|
||||
Ok(self.0.read().await.get_all_proposals().await?)
|
||||
Ok(nyxd_query!(self, get_all_proposals().await?))
|
||||
}
|
||||
|
||||
async fn get_spent_credential(
|
||||
&self,
|
||||
blinded_serial_number: String,
|
||||
) -> crate::coconut::error::Result<SpendCredentialResponse> {
|
||||
Ok(self
|
||||
.0
|
||||
.read()
|
||||
.await
|
||||
.get_spent_credential(blinded_serial_number)
|
||||
.await?)
|
||||
Ok(nyxd_query!(
|
||||
self,
|
||||
get_spent_credential(blinded_serial_number).await?
|
||||
))
|
||||
}
|
||||
|
||||
async fn get_current_epoch(&self) -> crate::coconut::error::Result<Epoch> {
|
||||
Ok(self.0.read().await.get_current_epoch().await?)
|
||||
Ok(nyxd_query!(self, get_current_epoch().await?))
|
||||
}
|
||||
|
||||
async fn group_member(&self, addr: String) -> crate::coconut::error::Result<MemberResponse> {
|
||||
Ok(self.0.read().await.member(addr, None).await?)
|
||||
Ok(nyxd_query!(self, member(addr, None).await?))
|
||||
}
|
||||
|
||||
async fn get_current_epoch_threshold(
|
||||
&self,
|
||||
) -> crate::coconut::error::Result<Option<nym_dkg::Threshold>> {
|
||||
Ok(self.0.read().await.get_current_epoch_threshold().await?)
|
||||
Ok(nyxd_query!(self, get_current_epoch_threshold().await?))
|
||||
}
|
||||
|
||||
async fn get_initial_dealers(
|
||||
&self,
|
||||
) -> crate::coconut::error::Result<Option<InitialReplacementData>> {
|
||||
Ok(self.0.read().await.get_initial_dealers().await?)
|
||||
Ok(nyxd_query!(self, get_initial_dealers().await?))
|
||||
}
|
||||
|
||||
async fn get_self_registered_dealer_details(
|
||||
&self,
|
||||
) -> crate::coconut::error::Result<DealerDetailsResponse> {
|
||||
let self_address = &self.address().await;
|
||||
Ok(self.0.read().await.get_dealer_details(self_address).await?)
|
||||
Ok(nyxd_query!(self, get_dealer_details(self_address).await?))
|
||||
}
|
||||
|
||||
async fn get_current_dealers(&self) -> crate::coconut::error::Result<Vec<DealerDetails>> {
|
||||
Ok(self.0.read().await.get_all_current_dealers().await?)
|
||||
Ok(nyxd_query!(self, get_all_current_dealers().await?))
|
||||
}
|
||||
|
||||
async fn get_dealings(
|
||||
&self,
|
||||
idx: usize,
|
||||
) -> crate::coconut::error::Result<Vec<ContractDealing>> {
|
||||
Ok(self
|
||||
.0
|
||||
.read()
|
||||
.await
|
||||
.get_all_epoch_dealings(idx as u64)
|
||||
.await?)
|
||||
Ok(nyxd_query!(self, get_all_epoch_dealings(idx as u64).await?))
|
||||
}
|
||||
|
||||
async fn get_verification_key_shares(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
) -> crate::coconut::error::Result<Vec<ContractVKShare>> {
|
||||
Ok(self
|
||||
.0
|
||||
.read()
|
||||
.await
|
||||
.get_all_verification_key_shares(epoch_id)
|
||||
.await?)
|
||||
Ok(nyxd_query!(
|
||||
self,
|
||||
get_all_verification_key_shares(epoch_id).await?
|
||||
))
|
||||
}
|
||||
|
||||
async fn vote_proposal(
|
||||
@@ -392,25 +428,17 @@ impl crate::coconut::client::Client for Client {
|
||||
vote_yes: bool,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<(), CoconutError> {
|
||||
self.0
|
||||
.write()
|
||||
.await
|
||||
.vote_proposal(proposal_id, vote_yes, fee)
|
||||
.await?;
|
||||
nyxd_signing!(self, vote_proposal(proposal_id, vote_yes, fee).await?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn execute_proposal(&self, proposal_id: u64) -> crate::coconut::error::Result<()> {
|
||||
self.0
|
||||
.write()
|
||||
.await
|
||||
.execute_proposal(proposal_id, None)
|
||||
.await?;
|
||||
nyxd_signing!(self, execute_proposal(proposal_id, None).await?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn advance_epoch_state(&self) -> crate::coconut::error::Result<()> {
|
||||
self.0.write().await.advance_dkg_epoch_state(None).await?;
|
||||
nyxd_signing!(self, advance_dkg_epoch_state(None).await?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -420,12 +448,10 @@ impl crate::coconut::client::Client for Client {
|
||||
announce_address: String,
|
||||
resharing: bool,
|
||||
) -> Result<ExecuteResult, CoconutError> {
|
||||
Ok(self
|
||||
.0
|
||||
.write()
|
||||
.await
|
||||
.register_dealer(bte_key, announce_address, resharing, None)
|
||||
.await?)
|
||||
Ok(nyxd_signing!(
|
||||
self,
|
||||
register_dealer(bte_key, announce_address, resharing, None).await?
|
||||
))
|
||||
}
|
||||
|
||||
async fn submit_dealing(
|
||||
@@ -433,12 +459,10 @@ impl crate::coconut::client::Client for Client {
|
||||
dealing_bytes: ContractSafeBytes,
|
||||
resharing: bool,
|
||||
) -> Result<ExecuteResult, CoconutError> {
|
||||
Ok(self
|
||||
.0
|
||||
.write()
|
||||
.await
|
||||
.submit_dealing_bytes(dealing_bytes, resharing, None)
|
||||
.await?)
|
||||
Ok(nyxd_signing!(
|
||||
self,
|
||||
submit_dealing_bytes(dealing_bytes, resharing, None).await?
|
||||
))
|
||||
}
|
||||
|
||||
async fn submit_verification_key_share(
|
||||
@@ -446,31 +470,27 @@ impl crate::coconut::client::Client for Client {
|
||||
share: VerificationKeyShare,
|
||||
resharing: bool,
|
||||
) -> crate::coconut::error::Result<ExecuteResult> {
|
||||
Ok(self
|
||||
.0
|
||||
.write()
|
||||
.await
|
||||
.submit_verification_key_share(share, resharing, None)
|
||||
.await?)
|
||||
Ok(nyxd_signing!(
|
||||
self,
|
||||
submit_verification_key_share(share, resharing, None).await?
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl crate::ephemera::client::Client for Client {
|
||||
async fn get_ephemera_peers(&self) -> crate::ephemera::error::Result<Vec<JsonPeerInfo>> {
|
||||
Ok(self.0.read().await.get_all_ephemera_peers().await?)
|
||||
Ok(nyxd_query!(self, get_all_ephemera_peers().await?))
|
||||
}
|
||||
|
||||
async fn register_ephemera_peer(
|
||||
&self,
|
||||
peer_info: JsonPeerInfo,
|
||||
) -> crate::ephemera::error::Result<ExecuteResult> {
|
||||
Ok(self
|
||||
.0
|
||||
.write()
|
||||
.await
|
||||
.register_as_peer(peer_info, None)
|
||||
.await?)
|
||||
Ok(nyxd_signing!(
|
||||
self,
|
||||
register_as_peer(peer_info, None).await?
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,7 +500,7 @@ impl DkgQueryClient for Client {
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.0.read().await.query_dkg_contract(query).await
|
||||
nyxd_query!(self, query_dkg_contract(query).await)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,7 +513,7 @@ impl EphemeraQueryClient for Client {
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.0.read().await.query_ephemera_contract(query).await
|
||||
nyxd_query!(self, query_ephemera_contract(query).await)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,11 +526,7 @@ impl SpDirectoryQueryClient for Client {
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.0
|
||||
.read()
|
||||
.await
|
||||
.query_service_provider_contract(query)
|
||||
.await
|
||||
nyxd_query!(self, query_service_provider_contract(query).await)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,6 +539,6 @@ impl NameServiceQueryClient for Client {
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
{
|
||||
self.0.read().await.query_name_service_contract(query).await
|
||||
nyxd_query!(self, query_name_service_contract(query).await)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user