Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9767f72
removed all on_behalf mixnet contract methods
jstuczyn May 24, 2024
701012a
ensure no pending proxy events when migrating
jstuczyn May 24, 2024
c4f7a1e
implemented migration into non-vesting mixnodes/delegations
jstuczyn Jul 12, 2024
9179f1c
exposed migration commands to nym-cli + clippy
jstuczyn Jul 12, 2024
f57fe79
updated contract schema
jstuczyn Jul 12, 2024
952ed9b
fixed wallet vesting-related tests
jstuczyn Jul 12, 2024
70db1ad
fixed vesting contract tests
jstuczyn Jul 12, 2024
03ffb25
introduced the concept of allowed profit margin ranges
jstuczyn Jul 17, 2024
8704c21
normalise node's profit margin during rewarding
jstuczyn Jul 17, 2024
c2ab47a
profit margin range validation
jstuczyn Jul 18, 2024
9d0fd68
introducing allowed range of operator interval operating cost
jstuczyn Jul 18, 2024
82f161f
added associated [hacky] wallet types
jstuczyn Jul 18, 2024
66979df
update contract schema
jstuczyn Jul 18, 2024
b484f47
fix nym-cli
jstuczyn Jul 18, 2024
7b80203
missing test fixture
jstuczyn Jul 18, 2024
61ddeea
fixed post-rebasing imports
jstuczyn Jul 18, 2024
4ee445c
cargo fmt
jstuczyn Jul 18, 2024
7d35102
Fix dependency issue
mmsinclair Jul 18, 2024
b76802e
exposed tauri operations for vesting migrations
jstuczyn Jul 18, 2024
61fcd4a
Dialog and mock for migrating vesting contract delegations
mmsinclair Jul 18, 2024
444c787
Add kind prop to vesting contract migration modal
mmsinclair Jul 18, 2024
96b33bf
Regenerate TS types
mmsinclair Jul 18, 2024
10d6f20
wip: add profit margin and cost params into validation from mixnet co…
mmsinclair Jul 18, 2024
f19c934
finish migrate vested bonded node work
fmtabbara Jul 25, 2024
31ea3f9
update bonding oc and pm validation
fmtabbara Jul 25, 2024
ecee6ca
chore: cargo fmt
jstuczyn Jul 26, 2024
d1de751
fix ci
fmtabbara Jul 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,24 @@ pub trait MixnetSigningClient {
.await
}

async fn migrate_vested_mixnode(&self, fee: Option<Fee>) -> Result<ExecuteResult, NyxdError> {
self.execute_mixnet_contract(fee, MixnetExecuteMsg::MigrateVestedMixNode {}, vec![])
.await
}

async fn migrate_vested_delegation(
&self,
mix_id: MixId,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
self.execute_mixnet_contract(
fee,
MixnetExecuteMsg::MigrateVestedDelegation { mix_id },
vec![],
)
.await
}

#[cfg(feature = "contract-testing")]
async fn testing_resolve_all_pending_events(
&self,
Expand Down Expand Up @@ -928,6 +946,12 @@ mod tests {
MixnetExecuteMsg::WithdrawDelegatorRewardOnBehalf { mix_id, owner } => client
.withdraw_delegator_reward_on_behalf(owner.parse().unwrap(), mix_id, None)
.ignore(),
MixnetExecuteMsg::MigrateVestedMixNode { .. } => {
client.migrate_vested_mixnode(None).ignore()
}
MixnetExecuteMsg::MigrateVestedDelegation { mix_id } => {
client.migrate_vested_delegation(mix_id, None).ignore()
}

#[cfg(feature = "contract-testing")]
MixnetExecuteMsg::TestingResolveAllPendingEvents { .. } => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ where
mod tests {
use super::*;
use crate::nyxd::contract_traits::tests::{mock_coin, IgnoreValue};
use nym_vesting_contract_common::ExecuteMsg;

// it's enough that this compiles and clippy is happy about it
#[allow(dead_code)]
Expand Down Expand Up @@ -560,6 +561,9 @@ mod tests {
VestingExecuteMsg::UpdateLockedPledgeCap { address, cap } => client
.update_locked_pledge_cap(address.parse().unwrap(), cap, None)
.ignore(),
// those will never be manually called by clients
ExecuteMsg::TrackMigratedMixnode { .. } => "explicitly_ignored".ignore(),
ExecuteMsg::TrackMigratedDelegation { .. } => "explicitly_ignored".ignore(),
};
}
}
45 changes: 40 additions & 5 deletions common/commands/src/validator/cosmwasm/generators/mixnet.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
// Copyright 2022 - Nym Technologies SA <[email protected]>
// Copyright 2022-2024 - Nym Technologies SA <[email protected]>
// SPDX-License-Identifier: Apache-2.0

use clap::Parser;
use log::{debug, info};

use cosmwasm_std::Decimal;
use nym_mixnet_contract_common::{InitialRewardingParams, InstantiateMsg, Percent};
use nym_validator_client::nyxd::AccountId;
use log::{debug, info};
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)]
Expand Down Expand Up @@ -50,6 +61,18 @@ pub struct Args {

#[clap(long, default_value_t = 240)]
pub active_set_size: 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) {
Expand Down Expand Up @@ -97,13 +120,25 @@ pub async fn generate(args: Args) {
.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(),
rewarding_denom,
epochs_in_interval: args.epochs_in_interval,
epoch_duration: Duration::from_secs(args.epoch_duration),
initial_rewarding_params,
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(),
},
};

debug!("instantiate_msg: {:?}", instantiate_msg);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2024 - Nym Technologies SA <[email protected]>
// SPDX-License-Identifier: Apache-2.0

use crate::context::SigningClient;
use clap::Parser;
use log::info;
use nym_mixnet_contract_common::MixId;
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, MixnetSigningClient};

#[derive(Debug, Parser)]
pub struct Args {
#[clap(long)]
pub mix_id: Option<MixId>,

#[clap(long)]
pub identity_key: Option<String>,
}

pub async fn migrate_vested_delegation(args: Args, client: SigningClient) {
let mix_id = match args.mix_id {
Some(mix_id) => mix_id,
None => {
let identity_key = args
.identity_key
.expect("either mix_id or mix_identity has to be specified");
let node_details = client
.get_mixnode_details_by_identity(identity_key)
.await
.expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist");
node_details.mix_id()
}
};

let res = client
.migrate_vested_delegation(mix_id, None)
.await
.expect("failed to migrate delegation!");

info!("migration result: {:?}", res)
}
3 changes: 3 additions & 0 deletions common/commands/src/validator/mixnet/delegators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod rewards;

pub mod delegate_to_mixnode;
pub mod delegate_to_multiple_mixnodes;
pub mod migrate_vested_delegation;
pub mod query_for_delegations;
pub mod undelegate_from_mixnode;
pub mod vesting_delegate_to_mixnode;
Expand Down Expand Up @@ -35,4 +36,6 @@ pub enum MixnetDelegatorsCommands {
DelegateVesting(vesting_delegate_to_mixnode::Args),
/// Undelegate from a mixnode (when originally using locked tokens)
UndelegateVesting(vesting_undelegate_from_mixnode::Args),
/// Migrate the delegation to use liquid tokens
MigrateVestedDelegation(migrate_vested_delegation::Args),
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ async fn print_delegation_events(events: Vec<PendingEpochEvent>, client: &Signin
mix_id,
amount,
proxy,
..
} => {
if owner.as_str() == client.nyxd.address().as_ref() {
table.add_row(vec![
Expand All @@ -111,6 +112,7 @@ async fn print_delegation_events(events: Vec<PendingEpochEvent>, client: &Signin
owner,
mix_id,
proxy,
..
} => {
if owner.as_str() == client.nyxd.address().as_ref() {
table.add_row(vec![
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use cosmwasm_std::Coin;
use nym_bin_common::output_format::OutputFormat;
use nym_mixnet_contract_common::construct_gateway_bonding_sign_payload;
use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT};
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, NymContractsProvider};
use nym_validator_client::nyxd::contract_traits::MixnetQueryClient;

#[derive(Debug, Parser)]
pub struct Args {
Expand Down Expand Up @@ -39,10 +39,6 @@ pub struct Args {
)]
pub amount: u128,

/// Indicates whether the gateway is going to get bonded via a vesting account
#[arg(long)]
pub with_vesting_account: bool,

#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
Expand Down Expand Up @@ -74,15 +70,8 @@ pub async fn create_payload(args: Args, client: SigningClient) {
};

let address = account_id_to_cw_addr(&client.address());
let proxy = if args.with_vesting_account {
Some(account_id_to_cw_addr(
client.vesting_contract_address().unwrap(),
))
} else {
None
};

let payload = construct_gateway_bonding_sign_payload(nonce, address, proxy, coin, gateway);
let payload = construct_gateway_bonding_sign_payload(nonce, address, coin, gateway);
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
println!("{}", args.output.format(&wrapper))
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,21 @@ use crate::context::SigningClient;
use clap::Parser;
use log::info;
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
use nym_validator_client::nyxd::contract_traits::VestingSigningClient;

#[derive(Debug, Parser)]
pub struct Args {
/// Label that is going to be used for creating the family
#[arg(long)]
pub family_label: String,

/// Indicates whether the family is going to get created via a vesting account
#[arg(long)]
pub with_vesting_account: bool,
}

pub async fn create_family(args: Args, client: SigningClient) {
info!("Create family");

let res = if args.with_vesting_account {
client
.vesting_create_family(args.family_label, None)
.await
.expect("failed to create family with vesting account")
} else {
client
.create_family(args.family_label, None)
.await
.expect("failed to create family")
};
let res = client
.create_family(args.family_label, None)
.await
.expect("failed to create family");

info!("Family creation result: {:?}", res);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,22 @@
// SPDX-License-Identifier: Apache-2.0

use crate::context::QueryClient;
use crate::utils::{account_id_to_cw_addr, DataWrapper};
use crate::utils::DataWrapper;
use clap::Parser;
use cosmrs::AccountId;
use log::info;
use nym_bin_common::output_format::OutputFormat;
use nym_crypto::asymmetric::identity;
use nym_mixnet_contract_common::construct_family_join_permit;
use nym_mixnet_contract_common::families::FamilyHead;
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, NymContractsProvider};
use nym_validator_client::nyxd::contract_traits::MixnetQueryClient;

#[derive(Debug, Parser)]
pub struct Args {
/// Account address (i.e. owner of the family head) which will be used for issuing the permit
#[arg(long)]
pub address: AccountId,

/// Indicates whether the member joining the family is going to use the vesting account for joining.
#[arg(long)]
pub with_vesting_account: bool,

// might as well validate the value when parsing the arguments
/// Identity of the member for whom we're issuing the permit
#[arg(long)]
Expand Down Expand Up @@ -68,18 +64,9 @@ pub async fn create_family_join_permit_sign_payload(args: Args, client: QueryCli
}
};

// let address = account_id_to_cw_addr(&args.address);
let proxy = if args.with_vesting_account {
Some(account_id_to_cw_addr(
client.vesting_contract_address().unwrap(),
))
} else {
None
};

let head = FamilyHead::new(mixnode.bond_information.identity());

let payload = construct_family_join_permit(nonce, head, proxy, args.member.to_base58_string());
let payload = construct_family_join_permit(nonce, head, args.member.to_base58_string());
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
println!("{}", args.output.format(&wrapper))
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,13 @@ use nym_contracts_common::signing::MessageSignature;
use nym_crypto::asymmetric::identity;
use nym_mixnet_contract_common::families::FamilyHead;
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
use nym_validator_client::nyxd::contract_traits::VestingSigningClient;

#[derive(Debug, Parser)]
pub struct Args {
/// The head of the family that we intend to join
#[arg(long)]
pub family_head: identity::PublicKey,

/// Indicates whether the member joining the family is going to do so via the vesting contract
#[arg(long)]
pub with_vesting_account: bool,

/// Permission, as provided by the family head, for joining the family
#[arg(long)]
pub join_permit: MessageSignature,
Expand All @@ -30,17 +25,10 @@ pub async fn join_family(args: Args, client: SigningClient) {

let family_head = FamilyHead::new(args.family_head.to_base58_string());

let res = if args.with_vesting_account {
client
.vesting_join_family(args.join_permit, family_head, None)
.await
.expect("failed to join family with vesting account")
} else {
client
.join_family(args.join_permit, family_head, None)
.await
.expect("failed to join family")
};
let res = client
.join_family(args.join_permit, family_head, None)
.await
.expect("failed to join family");

info!("Family join result: {:?}", res);
}
Loading