Feature/config from env (#1463)

* Clients use env

* Explorer api uses env

* Mainnet and qa env files

* Set CONFIGURED on the mainnet defaulting

* Gateway uses env

* Mixnode uses env

* Wallet error simplification

* Network requester takes only mainnet client address

* Validator api uses env

* Mixnet contract uses denom from instantiate

* Vesting contract uses denom from instantiate

* More contract test refactoring

* Coconut bandwidth contract uses denom from instantiate

* Bandwidth claim contract uses denom from instantiate and remove from Cargos

* More remove from Cargos and one missed DEFAULT_NETWORK

* Refactor some other missed places

* Minor fixes

* Test and clippy fixes

* Update CHANGELOG
This commit is contained in:
Bogdan-Ștefan Neacşu
2022-07-20 13:16:37 +03:00
committed by GitHub
parent c485934b06
commit 9ca3f69aa8
99 changed files with 900 additions and 617 deletions
+7 -3
View File
@@ -19,7 +19,7 @@ use coconut_bandwidth_contract_common::spend_credential::{
use coconut_interface::{
Attribute, BlindSignRequest, BlindedSignature, KeyPair, Parameters, VerificationKey,
};
use config::defaults::{MIX_DENOM, VALIDATOR_API_VERSION};
use config::defaults::VALIDATOR_API_VERSION;
use credentials::coconut::params::{
ValidatorApiCredentialEncryptionAlgorithm, ValidatorApiCredentialHkdfAlgorithm,
};
@@ -45,6 +45,7 @@ use self::comm::APICommunicationChannel;
pub struct State {
client: Arc<dyn LocalClient + Send + Sync>,
mix_denom: String,
key_pair: KeyPair,
comm_channel: Arc<dyn APICommunicationChannel + Send + Sync>,
storage: ValidatorApiStorage,
@@ -54,6 +55,7 @@ pub struct State {
impl State {
pub(crate) fn new<C, D>(
client: C,
mix_denom: String,
key_pair: KeyPair,
comm_channel: D,
storage: ValidatorApiStorage,
@@ -67,6 +69,7 @@ impl State {
let rng = Arc::new(Mutex::new(OsRng));
Self {
client,
mix_denom,
key_pair,
comm_channel,
storage,
@@ -160,6 +163,7 @@ impl InternalSignRequest {
pub fn stage<C, D>(
client: C,
mix_denom: String,
key_pair: KeyPair,
comm_channel: D,
storage: ValidatorApiStorage,
@@ -168,7 +172,7 @@ impl InternalSignRequest {
C: LocalClient + Send + Sync + 'static,
D: APICommunicationChannel + Send + Sync + 'static,
{
let state = State::new(client, key_pair, comm_channel, storage);
let state = State::new(client, mix_denom, key_pair, comm_channel, storage);
AdHoc::on_ignite("Internal Sign Request Stage", |rocket| async {
rocket.manage(state).mount(
// this format! is so ugly...
@@ -306,7 +310,7 @@ pub async fn verify_bandwidth_credential(
vote_yes &= Coin::from(proposed_release_funds)
== Coin::new(
verify_credential_body.credential().voucher_value() as u128,
MIX_DENOM.base,
state.mix_denom.clone(),
);
// Vote yes or no on the proposal based on the verification result
+27 -14
View File
@@ -11,7 +11,7 @@ use coconut_bandwidth_contract_common::spend_credential::{
SpendCredential, SpendCredentialResponse,
};
use coconut_interface::{hash_to_scalar, Credential, VerificationKey};
use config::defaults::{DEFAULT_NETWORK, MIX_DENOM, VOUCHER_INFO};
use config::defaults::VOUCHER_INFO;
use cosmwasm_std::{to_binary, Addr, CosmosMsg, Decimal, WasmMsg};
use credentials::coconut::bandwidth::BandwidthVoucher;
use credentials::coconut::params::{
@@ -47,6 +47,9 @@ use std::collections::HashMap;
use std::str::FromStr;
use std::sync::{Arc, RwLock};
const TEST_COIN_DENOM: &str = "unym";
const TEST_REWARDING_VALIDATOR_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
#[derive(Clone, Debug)]
struct DummyClient {
validator_address: AccountId,
@@ -178,7 +181,7 @@ async fn check_signer_verif_key(key_pair: KeyPair) {
db_dir.push(&verification_key.to_bs58()[..8]);
let storage = ValidatorApiStorage::init(db_dir).await.unwrap();
let nymd_client = DummyClient::new(
AccountId::from_str(DEFAULT_NETWORK.rewarding_validator_address()).unwrap(),
AccountId::from_str(TEST_REWARDING_VALIDATOR_ADDRESS).unwrap(),
&Arc::new(RwLock::new(HashMap::new())),
&Arc::new(RwLock::new(HashMap::new())),
&Arc::new(RwLock::new(HashMap::new())),
@@ -187,6 +190,7 @@ async fn check_signer_verif_key(key_pair: KeyPair) {
let rocket = rocket::build().attach(InternalSignRequest::stage(
nymd_client,
TEST_COIN_DENOM.to_string(),
key_pair,
comm_channel,
storage,
@@ -271,7 +275,7 @@ async fn signed_before() {
.unwrap()
.insert(tx_hash.to_string(), tx_entry.clone());
let nymd_client = DummyClient::new(
AccountId::from_str(DEFAULT_NETWORK.rewarding_validator_address()).unwrap(),
AccountId::from_str(TEST_REWARDING_VALIDATOR_ADDRESS).unwrap(),
&tx_db,
&Arc::new(RwLock::new(HashMap::new())),
&Arc::new(RwLock::new(HashMap::new())),
@@ -280,6 +284,7 @@ async fn signed_before() {
let rocket = rocket::build().attach(InternalSignRequest::stage(
nymd_client,
TEST_COIN_DENOM.to_string(),
key_pair,
comm_channel,
storage.clone(),
@@ -335,7 +340,7 @@ async fn signed_before() {
#[tokio::test]
async fn state_functions() {
let nymd_client = DummyClient::new(
AccountId::from_str(DEFAULT_NETWORK.rewarding_validator_address()).unwrap(),
AccountId::from_str(TEST_REWARDING_VALIDATOR_ADDRESS).unwrap(),
&Arc::new(RwLock::new(HashMap::new())),
&Arc::new(RwLock::new(HashMap::new())),
&Arc::new(RwLock::new(HashMap::new())),
@@ -346,7 +351,13 @@ async fn state_functions() {
db_dir.push(&key_pair.verification_key().to_bs58()[..8]);
let storage = ValidatorApiStorage::init(db_dir).await.unwrap();
let comm_channel = DummyCommunicationChannel::new(key_pair.verification_key());
let state = State::new(nymd_client, key_pair, comm_channel, storage.clone());
let state = State::new(
nymd_client,
TEST_COIN_DENOM.to_string(),
key_pair,
comm_channel,
storage.clone(),
);
let tx_hash = String::from("6B27412050B823E58BB38447D7870BBC8CBE3C51C905BEA89D459ACCDA80A00E");
assert!(state.signed_before(&tx_hash).await.unwrap().is_none());
@@ -504,7 +515,7 @@ async fn blind_sign_correct() {
.unwrap()
.insert(tx_hash.to_string(), tx_entry.clone());
let nymd_client = DummyClient::new(
AccountId::from_str(DEFAULT_NETWORK.rewarding_validator_address()).unwrap(),
AccountId::from_str(TEST_REWARDING_VALIDATOR_ADDRESS).unwrap(),
&tx_db,
&Arc::new(RwLock::new(HashMap::new())),
&Arc::new(RwLock::new(HashMap::new())),
@@ -513,6 +524,7 @@ async fn blind_sign_correct() {
let rocket = rocket::build().attach(InternalSignRequest::stage(
nymd_client,
TEST_COIN_DENOM.to_string(),
key_pair,
comm_channel,
storage.clone(),
@@ -582,7 +594,7 @@ async fn signature_test() {
db_dir.push(&key_pair.verification_key().to_bs58()[..8]);
let storage = ValidatorApiStorage::init(db_dir).await.unwrap();
let nymd_client = DummyClient::new(
AccountId::from_str(DEFAULT_NETWORK.rewarding_validator_address()).unwrap(),
AccountId::from_str(TEST_REWARDING_VALIDATOR_ADDRESS).unwrap(),
&Arc::new(RwLock::new(HashMap::new())),
&Arc::new(RwLock::new(HashMap::new())),
&Arc::new(RwLock::new(HashMap::new())),
@@ -591,6 +603,7 @@ async fn signature_test() {
let rocket = rocket::build().attach(InternalSignRequest::stage(
nymd_client,
TEST_COIN_DENOM.to_string(),
key_pair,
comm_channel,
storage.clone(),
@@ -645,8 +658,7 @@ async fn signature_test() {
#[tokio::test]
async fn get_cosmos_address() {
let validator_address =
AccountId::from_str(DEFAULT_NETWORK.rewarding_validator_address()).unwrap();
let validator_address = AccountId::from_str(TEST_REWARDING_VALIDATOR_ADDRESS).unwrap();
let nymd_client = DummyClient::new(
validator_address.clone(),
&Arc::new(RwLock::new(HashMap::new())),
@@ -662,6 +674,7 @@ async fn get_cosmos_address() {
let comm_channel = DummyCommunicationChannel::new(key_pair.verification_key());
let rocket = rocket::build().attach(InternalSignRequest::stage(
nymd_client,
TEST_COIN_DENOM.to_string(),
key_pair,
comm_channel,
storage.clone(),
@@ -687,8 +700,7 @@ async fn get_cosmos_address() {
#[tokio::test]
async fn verification_of_bandwidth_credential() {
// Setup variables
let validator_address =
AccountId::from_str(DEFAULT_NETWORK.rewarding_validator_address()).unwrap();
let validator_address = AccountId::from_str(TEST_REWARDING_VALIDATOR_ADDRESS).unwrap();
let proposal_db = Arc::new(RwLock::new(HashMap::new()));
let spent_credential_db = Arc::new(RwLock::new(HashMap::new()));
let nymd_client = DummyClient::new(
@@ -713,6 +725,7 @@ async fn verification_of_bandwidth_credential() {
let comm_channel = DummyCommunicationChannel::new(key_pair.verification_key());
let rocket = rocket::build().attach(InternalSignRequest::stage(
nymd_client.clone(),
TEST_COIN_DENOM.to_string(),
key_pair,
comm_channel.clone(),
storage1.clone(),
@@ -806,7 +819,7 @@ async fn verification_of_bandwidth_credential() {
);
// Test the endpoint without any credential recorded in the Coconut Bandwidth Contract
let funds = Coin::new(voucher_value as u128, MIX_DENOM.base);
let funds = Coin::new(voucher_value as u128, TEST_COIN_DENOM);
let msg = coconut_bandwidth_contract_common::msg::ExecuteMsg::ReleaseFunds {
funds: funds.clone().into(),
};
@@ -901,7 +914,7 @@ async fn verification_of_bandwidth_credential() {
// Test the endpoint with a proposal that has a different value for the funds to be released
// then what's in the credential
let funds = Coin::new((voucher_value + 10) as u128, MIX_DENOM.base);
let funds = Coin::new((voucher_value + 10) as u128, TEST_COIN_DENOM);
let msg = coconut_bandwidth_contract_common::msg::ExecuteMsg::ReleaseFunds {
funds: funds.clone().into(),
};
@@ -939,7 +952,7 @@ async fn verification_of_bandwidth_credential() {
);
// Test the endpoint with every dependency met
let funds = Coin::new(voucher_value as u128, MIX_DENOM.base);
let funds = Coin::new(voucher_value as u128, TEST_COIN_DENOM);
let msg = coconut_bandwidth_contract_common::msg::ExecuteMsg::ReleaseFunds {
funds: funds.clone().into(),
};
+2 -15
View File
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
use crate::config::template::config_template;
use config::defaults::DEFAULT_NETWORK;
use config::NymConfig;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
@@ -108,9 +107,7 @@ impl Default for Base {
local_validator: DEFAULT_LOCAL_VALIDATOR
.parse()
.expect("default local validator is malformed!"),
mixnet_contract_address: DEFAULT_NETWORK
.mixnet_contract_address()
.expect("mixnet contract address is unavailable"),
mixnet_contract_address: String::default(),
mnemonic: "exact antique hybrid width raise anchor puzzle degree fee quit long crack net vague hip despair write put useless civil mechanic broom music day".to_string(),
}
}
@@ -279,7 +276,7 @@ impl Default for Rewarding {
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
#[derive(Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default)]
pub struct CoconutSigner {
/// Specifies whether rewarding service is enabled in this process.
@@ -294,16 +291,6 @@ pub struct CoconutSigner {
all_validator_apis: Vec<Url>,
}
impl Default for CoconutSigner {
fn default() -> Self {
CoconutSigner {
enabled: false,
keypair_path: PathBuf::default(),
all_validator_apis: config::defaults::default_api_endpoints(),
}
}
}
impl Config {
pub fn new() -> Self {
Config::default()
+29 -7
View File
@@ -10,7 +10,10 @@ use crate::network_monitor::NetworkMonitorBuilder;
use crate::node_status_api::uptime_updater::HistoricalUptimeUpdater;
use crate::nymd_client::Client;
use crate::storage::ValidatorApiStorage;
use ::config::defaults::DEFAULT_NETWORK;
use ::config::defaults::setup_env;
#[cfg(feature = "coconut")]
use ::config::defaults::var_names::API_VALIDATOR;
use ::config::defaults::var_names::{CONFIGURED, MIXNET_CONTRACT_ADDRESS, MIX_DENOM};
use ::config::NymConfig;
use anyhow::Result;
use clap::{crate_version, App, Arg, ArgMatches};
@@ -23,6 +26,8 @@ use rocket::{Ignite, Rocket};
use rocket_cors::{AllowedHeaders, AllowedOrigins, Cors};
use rocket_okapi::mount_endpoints_and_merged_docs;
use rocket_okapi::swagger_ui::make_swagger_ui;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;
use std::time::Duration;
use std::{fs, process};
@@ -50,6 +55,7 @@ mod swagger;
mod coconut;
const ID: &str = "id";
const CONFIG_ENV_FILE: &str = "config-env-file";
const MONITORING_ENABLED: &str = "enable-monitor";
const REWARDING_ENABLED: &str = "enable-rewarding";
const MIXNET_CONTRACT_ARG: &str = "mixnet-contract";
@@ -98,7 +104,6 @@ fn long_version() -> String {
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
@@ -115,9 +120,7 @@ fn long_version() -> String {
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE"),
"Network:",
DEFAULT_NETWORK
env!("VERGEN_CARGO_PROFILE")
)
}
@@ -127,6 +130,12 @@ fn parse_args<'a>() -> ArgMatches<'a> {
.version(crate_version!())
.long_version(&*build_details)
.author("Nymtech")
.arg(
Arg::with_name(CONFIG_ENV_FILE)
.help("Path pointing to an env file that configures the validator API")
.long(CONFIG_ENV_FILE)
.takes_value(true)
)
.arg(
Arg::with_name(ID)
.help("Id of the validator-api we want to run")
@@ -273,6 +282,9 @@ fn override_config(mut config: Config, matches: &ArgMatches<'_>) -> Config {
#[cfg(feature = "coconut")]
if let Some(raw_validators) = matches.value_of(API_VALIDATORS_ARG) {
config = config.with_custom_validator_apis(parse_validators(raw_validators));
} else if std::env::var(CONFIGURED).is_ok() {
let raw_validators = std::env::var(API_VALIDATOR).expect("api validator not set");
config = config.with_custom_validator_apis(parse_validators(&raw_validators))
}
if let Some(raw_validator) = matches.value_of(NYMD_VALIDATOR_ARG) {
@@ -288,6 +300,10 @@ fn override_config(mut config: Config, matches: &ArgMatches<'_>) -> Config {
if let Some(mixnet_contract) = matches.value_of(MIXNET_CONTRACT_ARG) {
config = config.with_custom_mixnet_contract(mixnet_contract)
} else if std::env::var(CONFIGURED).is_ok() {
let mixnet_contract =
std::env::var(MIXNET_CONTRACT_ADDRESS).expect("mixnet contract not set");
config = config.with_custom_mixnet_contract(mixnet_contract)
}
if let Some(mnemonic) = matches.value_of(MNEMONIC_ARG) {
@@ -413,6 +429,7 @@ fn expected_monitor_test_runs(config: &Config, interval_length: Duration) -> usi
async fn setup_rocket(
config: &Config,
_mix_denom: String,
liftoff_notify: Arc<Notify>,
_nymd_client: Client<SigningNymdClient>,
) -> Result<Rocket<Ignite>> {
@@ -452,6 +469,7 @@ async fn setup_rocket(
let keypair = KeyPair::try_from_bs58(keypair_bs58)?;
rocket.attach(InternalSignRequest::stage(
_nymd_client,
_mix_denom,
keypair,
QueryCommunicationChannel::new(config.get_all_validator_api_endpoints()),
storage.clone().unwrap(),
@@ -524,6 +542,7 @@ async fn run_validator_api(matches: ArgMatches<'static>) -> Result<()> {
if matches.is_present(WRITE_CONFIG_ARG) {
return Ok(());
}
let mix_denom = std::env::var(MIX_DENOM).expect("mix denom not set");
let signing_nymd_client = Client::new_signing(&config);
@@ -532,6 +551,7 @@ async fn run_validator_api(matches: ArgMatches<'static>) -> Result<()> {
// let's build our rocket!
let rocket = setup_rocket(
&config,
mix_denom,
Arc::clone(&liftoff_notify),
signing_nymd_client.clone(),
)
@@ -605,8 +625,6 @@ async fn run_validator_api(matches: ArgMatches<'static>) -> Result<()> {
async fn main() -> Result<()> {
println!("Starting validator api...");
let _ = dotenv::dotenv();
cfg_if::cfg_if! {if #[cfg(feature = "console-subscriber")] {
// instriment tokio console subscriber needs RUSTFLAGS="--cfg tokio_unstable" at build time
console_subscriber::init();
@@ -614,5 +632,9 @@ async fn main() -> Result<()> {
setup_logging();
let args = parse_args();
let config_env_file = args
.value_of(CONFIG_ENV_FILE)
.map(|s| PathBuf::from_str(s).expect("invalid env config file"));
setup_env(config_env_file);
run_validator_api(args).await
}
+7 -10
View File
@@ -11,7 +11,7 @@ use std::time::Duration;
use tokio::sync::RwLock;
use tokio::time::sleep;
use config::defaults::{DEFAULT_NETWORK, DEFAULT_VALIDATOR_API_PORT};
use config::defaults::{NymNetworkDetails, DEFAULT_VALIDATOR_API_PORT};
use mixnet_contract_common::{
reward_params::EpochRewardParams, ContractStateParams, Delegation, ExecuteMsg, GatewayBond,
IdentityKey, Interval, MixNodeBond, MixnodeRewardingStatusResponse, RewardedSetNodeStatus,
@@ -51,17 +51,16 @@ impl Client<QueryNymdClient> {
.parse()
.unwrap();
let nymd_url = config.get_nymd_validator_url();
let network = DEFAULT_NETWORK;
let details = network
.details()
let details = NymNetworkDetails::new_from_env()
.with_mixnet_contract(Some(config.get_mixnet_contract_address()));
let client_config = validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct valid validator client config with the provided network")
.with_urls(nymd_url, api_url);
let inner = validator_client::Client::new_query(client_config, network)
.expect("Failed to connect to nymd!");
let inner =
validator_client::Client::new_query(client_config).expect("Failed to connect to nymd!");
Client(Arc::new(RwLock::new(inner)))
}
@@ -76,9 +75,7 @@ impl Client<SigningNymdClient> {
.unwrap();
let nymd_url = config.get_nymd_validator_url();
let network = DEFAULT_NETWORK;
let details = network
.details()
let details = NymNetworkDetails::new_from_env()
.with_mixnet_contract(Some(config.get_mixnet_contract_address()));
let client_config = validator_client::Config::try_from_nym_network_details(&details)
@@ -90,7 +87,7 @@ impl Client<SigningNymdClient> {
.parse()
.expect("the mnemonic is invalid!");
let inner = validator_client::Client::new_signing(client_config, network, mnemonic)
let inner = validator_client::Client::new_signing(client_config, mnemonic)
.expect("Failed to connect to nymd!");
Client(Arc::new(RwLock::new(inner)))