a21a01cf1a
* start node families topic branch * start node families topic branch * initialise node families contract * define contract storage * registering new family in storage * accepting family invitation * add_pending_invitation * revoke_pending_invitation * remove_family_member * reject_pending_invitation * disband_family * added unit tests for the storage methods * added restriction on uniquness of family names * update rustc version for node families contract common * clippy * basic queries by id * query_families_paged * change family membership storage and expose query for all members of a family * queries for pending invitations * queries for past invitations * queries for past data per node * queries for past family members * query_past_members_for_node_paged * queries for family by name and by owner * fixup family name normalisation * fixed incorrect lower bound for queries for past data * implement contract and storage initialisation * stubbing tx messages that are to be exposed by the contract * handler for updating config * removed partial fee return * wip: create family * move mixnet contract interaction traits to shared location * store original family name alongside the normalised variant * prevent family creation if owner has a node in another family * try_disband_family * try_invite_to_family + shared helpers * try_revoke_family_invitation * accept_family_invitation * stub method for node unbonding * try_reject_family_invitation * unit tests for family name normalisation * try_leave_family * try_kick_from_family * fix outdated comments and add paid fee event attribute * feat: NMv3: leave family upon node unbonding * NF contract handling of unbonding * lints * init node families contract when creating performance contract tester * clippy * avoid self-dep in the contract dev deps * introduced client traits for interacting with the node families contract * add node families contract to cache refresher * added query for all node family members (globally) and started scaffolding nym-api caches * docs and cache -> api conversion * calculating average node age based on individual timestamps * wire up node families cache * http stubs * filled in the implementation * route tests + extracting shared code * review fixes * feat: expose family information for all dvpn gateway endpoints within NS API * expose family information for explorer v3 route * clippy * review comments and optimise db family update * feat: Node Families: expose stake information inside DVpnGateway * chore: update lock files after rebase * chore: sort workspace members * explicitly require providing node families contract address for mixnet contract migration * fix missing node families contract address env export * dont swallow cache overwrite failures in fixture * pin network-defaults rustc version due to contracts dep * further version pinning * chore: update mixnet contract schema
182 lines
6.6 KiB
Rust
182 lines
6.6 KiB
Rust
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
use clap::Parser;
|
|
use cosmwasm_std::Decimal;
|
|
use log::{debug, info};
|
|
use nym_mixnet_contract_common::reward_params::RewardedSetParams;
|
|
use nym_mixnet_contract_common::{
|
|
InitialRewardingParams, InstantiateMsg, OperatingCostRange, Percent, ProfitMarginRange,
|
|
};
|
|
use nym_network_defaults::mainnet::MIX_DENOM;
|
|
use nym_network_defaults::TOTAL_SUPPLY;
|
|
use nym_validator_client::nyxd::{AccountId, Coin};
|
|
use std::str::FromStr;
|
|
use std::time::Duration;
|
|
|
|
pub fn default_maximum_operating_cost() -> Coin {
|
|
Coin::new(TOTAL_SUPPLY, MIX_DENOM.base)
|
|
}
|
|
|
|
pub fn default_minimum_operating_cost() -> Coin {
|
|
Coin::new(0, MIX_DENOM.base)
|
|
}
|
|
|
|
#[derive(Debug, Parser)]
|
|
pub struct Args {
|
|
#[clap(long)]
|
|
pub rewarding_validator_address: Option<AccountId>,
|
|
|
|
#[clap(long)]
|
|
pub vesting_contract_address: Option<AccountId>,
|
|
|
|
#[clap(long)]
|
|
pub node_families_contract_address: Option<AccountId>,
|
|
|
|
#[clap(long)]
|
|
pub rewarding_denom: Option<String>,
|
|
|
|
#[clap(long)]
|
|
pub current_nym_node_version: String,
|
|
|
|
#[clap(long, default_value_t = 720)]
|
|
pub epochs_in_interval: u32,
|
|
|
|
#[clap(long, default_value_t = 60*60)]
|
|
pub epoch_duration: u64,
|
|
|
|
#[clap(long, default_value_t = 244_817_525_850_285)]
|
|
pub initial_reward_pool: u128,
|
|
|
|
#[clap(long, default_value_t = 100_000_000_000_000)]
|
|
pub initial_staking_supply: u128,
|
|
|
|
#[clap(long, default_value_t = 50)]
|
|
pub staking_supply_scale_factor: u64,
|
|
|
|
#[clap(long, default_value_t = 30)]
|
|
pub sybil_resistance: u64,
|
|
|
|
#[clap(long, default_value_t = 10)]
|
|
pub active_set_work_factor: u32,
|
|
|
|
#[clap(long, default_value_t = 2)]
|
|
pub interval_pool_emission: u64,
|
|
|
|
#[clap(long, default_value_t = 50)]
|
|
pub(crate) entry_gateways: u32,
|
|
|
|
#[clap(long, default_value_t = 70)]
|
|
pub(crate) exit_gateways: u32,
|
|
|
|
#[clap(long, default_value_t = 120)]
|
|
pub(crate) mixnodes: u32,
|
|
|
|
#[clap(long, default_value_t = 0)]
|
|
pub(crate) standby: u32,
|
|
|
|
#[clap(long, default_value_t = Percent::zero())]
|
|
pub minimum_profit_margin_percent: Percent,
|
|
|
|
#[clap(long, default_value_t = Percent::hundred())]
|
|
pub maximum_profit_margin_percent: Percent,
|
|
|
|
#[clap(long, default_value_t = default_minimum_operating_cost())]
|
|
pub minimum_interval_operating_cost: Coin,
|
|
|
|
#[clap(long, default_value_t = default_maximum_operating_cost())]
|
|
pub maximum_interval_operating_cost: Coin,
|
|
}
|
|
|
|
pub async fn generate(args: Args) {
|
|
info!("Starting to generate mixnet contract instantiate msg");
|
|
|
|
debug!("Received arguments: {args:?}");
|
|
|
|
let initial_rewarding_params = InitialRewardingParams {
|
|
initial_reward_pool: Decimal::from_atomics(args.initial_reward_pool, 0)
|
|
.expect("initial_rewarding_pool can't be converted to Decimal"),
|
|
initial_staking_supply: Decimal::from_atomics(args.initial_staking_supply, 0)
|
|
.expect("initial_staking_supply can't be converted to Decimal"),
|
|
staking_supply_scale_factor: Percent::from_percentage_value(
|
|
args.staking_supply_scale_factor,
|
|
)
|
|
.unwrap(),
|
|
sybil_resistance: Percent::from_percentage_value(args.sybil_resistance)
|
|
.expect("sybil_resistance can't be converted to Percent"),
|
|
active_set_work_factor: Decimal::from_atomics(args.active_set_work_factor, 0)
|
|
.expect("active_set_work_factor can't be converted to Decimal"),
|
|
interval_pool_emission: Percent::from_percentage_value(args.interval_pool_emission)
|
|
.expect("interval_pool_emission can't be converted to Percent"),
|
|
|
|
rewarded_set_params: RewardedSetParams {
|
|
entry_gateways: args.entry_gateways,
|
|
exit_gateways: args.exit_gateways,
|
|
mixnodes: args.mixnodes,
|
|
standby: args.standby,
|
|
},
|
|
};
|
|
|
|
debug!("initial_rewarding_params: {initial_rewarding_params:?}");
|
|
|
|
let rewarding_validator_address = args.rewarding_validator_address.unwrap_or_else(|| {
|
|
let address = std::env::var(nym_network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
|
|
.expect("Rewarding validator address has to be set");
|
|
AccountId::from_str(address.as_str())
|
|
.expect("Failed converting rewarding validator address to AccountId")
|
|
});
|
|
|
|
let vesting_contract_address = args.vesting_contract_address.unwrap_or_else(|| {
|
|
let address = std::env::var(nym_network_defaults::var_names::VESTING_CONTRACT_ADDRESS)
|
|
.expect("Vesting contract address has to be set");
|
|
AccountId::from_str(address.as_str())
|
|
.expect("Failed converting vesting contract address to AccountId")
|
|
});
|
|
|
|
let node_families_contract_address = args.node_families_contract_address.unwrap_or_else(|| {
|
|
let address =
|
|
std::env::var(nym_network_defaults::var_names::NODE_FAMILIES_CONTRACT_ADDRESS)
|
|
.expect("node families contract address has to be set");
|
|
AccountId::from_str(address.as_str())
|
|
.expect("Failed converting node families contract address to AccountId")
|
|
});
|
|
|
|
let rewarding_denom = args.rewarding_denom.unwrap_or_else(|| {
|
|
std::env::var(nym_network_defaults::var_names::MIX_DENOM)
|
|
.expect("Rewarding (mix) denom has to be set")
|
|
});
|
|
|
|
if args.minimum_interval_operating_cost.denom != args.maximum_interval_operating_cost.denom {
|
|
panic!("different denoms for operating cost bounds")
|
|
}
|
|
|
|
let instantiate_msg = InstantiateMsg {
|
|
rewarding_validator_address: rewarding_validator_address.to_string(),
|
|
vesting_contract_address: vesting_contract_address.to_string(),
|
|
node_families_contract_address: node_families_contract_address.to_string(),
|
|
rewarding_denom,
|
|
epochs_in_interval: args.epochs_in_interval,
|
|
epoch_duration: Duration::from_secs(args.epoch_duration),
|
|
initial_rewarding_params,
|
|
current_nym_node_version: args.current_nym_node_version,
|
|
version_score_weights: Default::default(),
|
|
version_score_params: Default::default(),
|
|
profit_margin: ProfitMarginRange {
|
|
minimum: args.minimum_profit_margin_percent,
|
|
maximum: args.maximum_profit_margin_percent,
|
|
},
|
|
interval_operating_cost: OperatingCostRange {
|
|
minimum: args.minimum_interval_operating_cost.amount.into(),
|
|
maximum: args.maximum_interval_operating_cost.amount.into(),
|
|
},
|
|
key_validity_in_epochs: None,
|
|
};
|
|
|
|
debug!("instantiate_msg: {instantiate_msg:?}");
|
|
|
|
let res =
|
|
serde_json::to_string(&instantiate_msg).expect("failed to convert instantiate msg to json");
|
|
|
|
println!("{res}")
|
|
}
|