Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0877b6edae | |||
| 4c2967a733 | |||
| 2b80e5d1c9 | |||
| 4e7ff53214 | |||
| 9ec36e49b7 |
Generated
+19
@@ -505,6 +505,22 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chitchat"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fec1bff4fabc59f0b7408478183a796ab0a9bcb0534bb413f3cf66f44ce2aca1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.23"
|
||||
@@ -2911,6 +2927,7 @@ name = "mixnode-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"chitchat",
|
||||
"futures",
|
||||
"humantime-serde",
|
||||
"log",
|
||||
@@ -2926,6 +2943,7 @@ dependencies = [
|
||||
"nym-task",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
@@ -3491,6 +3509,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"atty",
|
||||
"bs58",
|
||||
"chitchat",
|
||||
"clap 4.1.4",
|
||||
"colored",
|
||||
"cupid",
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
/target
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
||||
@@ -9,6 +9,7 @@ use crate::nyxd::{Fee, NyxdClient, SigningCosmWasmClient};
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_mixnet_contract_common::gateway::GatewayConfigUpdate;
|
||||
use nym_mixnet_contract_common::mixnode::{MixNodeConfigUpdate, MixNodeCostParams};
|
||||
use nym_mixnet_contract_common::reward_params::{IntervalRewardingParamsUpdate, Performance};
|
||||
use nym_mixnet_contract_common::{
|
||||
@@ -498,6 +499,36 @@ pub trait MixnetSigningClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn update_gateway_config(
|
||||
&self,
|
||||
new_config: GatewayConfigUpdate,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::UpdateGatewayConfig { new_config },
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn update_gateway_config_on_behalf(
|
||||
&self,
|
||||
owner: AccountId,
|
||||
new_config: GatewayConfigUpdate,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(
|
||||
fee,
|
||||
MixnetExecuteMsg::UpdateGatewayConfigOnBehalf {
|
||||
new_config,
|
||||
owner: owner.to_string(),
|
||||
},
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
// delegation-related:
|
||||
|
||||
async fn delegate_to_mixnode(
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::{Coin, Fee, NyxdClient};
|
||||
use async_trait::async_trait;
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_mixnet_contract_common::gateway::GatewayConfigUpdate;
|
||||
use nym_mixnet_contract_common::mixnode::{MixNodeConfigUpdate, MixNodeCostParams};
|
||||
use nym_mixnet_contract_common::{Gateway, MixId, MixNode};
|
||||
use nym_vesting_contract_common::messages::{
|
||||
@@ -35,6 +36,12 @@ pub trait VestingSigningClient {
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError>;
|
||||
|
||||
async fn vesting_update_gateway_config(
|
||||
&self,
|
||||
new_config: GatewayConfigUpdate,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError>;
|
||||
|
||||
async fn update_mixnet_address(
|
||||
&self,
|
||||
address: &str,
|
||||
@@ -185,6 +192,19 @@ impl<C: SigningCosmWasmClient + Sync + Send + Clone> VestingSigningClient for Ny
|
||||
.await
|
||||
}
|
||||
|
||||
async fn vesting_update_gateway_config(
|
||||
&self,
|
||||
new_config: GatewayConfigUpdate,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_vesting_contract(
|
||||
fee,
|
||||
VestingExecuteMsg::UpdateGatewayConfig { new_config },
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn update_mixnet_address(
|
||||
&self,
|
||||
address: &str,
|
||||
|
||||
@@ -5,6 +5,7 @@ use clap::{Args, Subcommand};
|
||||
|
||||
pub mod bond_gateway;
|
||||
pub mod gateway_bonding_sign_payload;
|
||||
pub mod settings;
|
||||
pub mod unbond_gateway;
|
||||
pub mod vesting_bond_gateway;
|
||||
pub mod vesting_unbond_gateway;
|
||||
@@ -18,6 +19,8 @@ pub struct MixnetOperatorsGateway {
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum MixnetOperatorsGatewayCommands {
|
||||
/// Manage your gateway settings stored in the directory
|
||||
Settings(settings::MixnetOperatorsGatewaySettings),
|
||||
/// Bond to a gateway
|
||||
Bond(bond_gateway::Args),
|
||||
/// Unbond from a gateway
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::{Args, Subcommand};
|
||||
|
||||
pub mod update_config;
|
||||
pub mod vesting_update_config;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
pub struct MixnetOperatorsGatewaySettings {
|
||||
#[clap(subcommand)]
|
||||
pub command: MixnetOperatorsGatewaySettingsCommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum MixnetOperatorsGatewaySettingsCommands {
|
||||
/// Update gateway configuration
|
||||
UpdateConfig(update_config::Args),
|
||||
/// Update gateway configuration for a gateway bonded with locked tokens
|
||||
VestingUpdateConfig(vesting_update_config::Args),
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::GatewayConfigUpdate;
|
||||
use validator_client::nyxd::traits::{MixnetQueryClient, MixnetSigningClient};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub host: Option<String>,
|
||||
|
||||
#[clap(long)]
|
||||
pub mix_port: Option<u16>,
|
||||
|
||||
#[clap(long)]
|
||||
pub clients_port: Option<u16>,
|
||||
|
||||
#[clap(long)]
|
||||
pub location: Option<String>,
|
||||
|
||||
#[clap(long)]
|
||||
pub version: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn update_config(args: Args, client: SigningClient) {
|
||||
info!("Update gateway config!");
|
||||
|
||||
let current_details = match client
|
||||
.get_owned_gateway(client.address())
|
||||
.await
|
||||
.expect("failed to query the chain for gateway details")
|
||||
.gateway
|
||||
{
|
||||
Some(details) => details,
|
||||
None => {
|
||||
log::warn!("this operator does not own a gateway to update");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let update = GatewayConfigUpdate {
|
||||
host: args.host.unwrap_or(current_details.gateway.host),
|
||||
mix_port: args.mix_port.unwrap_or(current_details.gateway.mix_port),
|
||||
clients_port: args
|
||||
.clients_port
|
||||
.unwrap_or(current_details.gateway.clients_port),
|
||||
location: args.location.unwrap_or(current_details.gateway.location),
|
||||
version: args.version.unwrap_or(current_details.gateway.version),
|
||||
};
|
||||
|
||||
let res = client
|
||||
.update_gateway_config(update, None)
|
||||
.await
|
||||
.expect("updating gateway config");
|
||||
|
||||
info!("gateway config updated: {:?}", res)
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::SigningClient;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use nym_mixnet_contract_common::GatewayConfigUpdate;
|
||||
use validator_client::nyxd::traits::MixnetQueryClient;
|
||||
use validator_client::nyxd::VestingSigningClient;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[clap(long)]
|
||||
pub host: Option<String>,
|
||||
|
||||
#[clap(long)]
|
||||
pub mix_port: Option<u16>,
|
||||
|
||||
#[clap(long)]
|
||||
pub clients_port: Option<u16>,
|
||||
|
||||
#[clap(long)]
|
||||
pub location: Option<String>,
|
||||
|
||||
#[clap(long)]
|
||||
pub version: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn vesting_update_config(client: SigningClient, args: Args) {
|
||||
info!("Update vesting gateway config!");
|
||||
|
||||
let current_details = match client
|
||||
.get_owned_gateway(client.address())
|
||||
.await
|
||||
.expect("failed to query the chain for gateway details")
|
||||
.gateway
|
||||
{
|
||||
Some(details) => details,
|
||||
None => {
|
||||
log::warn!("this operator does not own a gateway to update");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let update = GatewayConfigUpdate {
|
||||
host: args.host.unwrap_or(current_details.gateway.host),
|
||||
mix_port: args.mix_port.unwrap_or(current_details.gateway.mix_port),
|
||||
clients_port: args
|
||||
.clients_port
|
||||
.unwrap_or(current_details.gateway.clients_port),
|
||||
location: args.location.unwrap_or(current_details.gateway.location),
|
||||
version: args.version.unwrap_or(current_details.gateway.version),
|
||||
};
|
||||
|
||||
let res = client
|
||||
.vesting_update_gateway_config(update, None)
|
||||
.await
|
||||
.expect("updating vesting gateway config");
|
||||
|
||||
info!("gateway config updated: {:?}", res)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::gateway::GatewayConfigUpdate;
|
||||
use crate::mixnode::{MixNodeConfigUpdate, MixNodeCostParams};
|
||||
use crate::reward_params::{IntervalRewardParams, IntervalRewardingParamsUpdate};
|
||||
use crate::rewarding::RewardDistribution;
|
||||
@@ -42,6 +43,7 @@ pub enum MixnetEventType {
|
||||
ReconcilePendingEvents,
|
||||
PendingIntervalConfigUpdate,
|
||||
IntervalConfigUpdate,
|
||||
GatewayConfigUpdate,
|
||||
}
|
||||
|
||||
impl From<MixnetEventType> for String {
|
||||
@@ -86,6 +88,7 @@ impl ToString for MixnetEventType {
|
||||
MixnetEventType::PendingIntervalConfigUpdate => "pending_interval_config_update",
|
||||
MixnetEventType::IntervalConfigUpdate => "interval_config_update",
|
||||
MixnetEventType::DelegationOnUnbonding => "delegation_on_unbonding_node",
|
||||
MixnetEventType::GatewayConfigUpdate => "gateway_config_update",
|
||||
};
|
||||
|
||||
format!("{EVENT_VERSION_PREFIX}{event_name}")
|
||||
@@ -122,6 +125,7 @@ pub const OLD_REWARDING_VALIDATOR_ADDRESS_KEY: &str = "old_rewarding_validator_a
|
||||
pub const NEW_REWARDING_VALIDATOR_ADDRESS_KEY: &str = "new_rewarding_validator_address";
|
||||
|
||||
pub const UPDATED_MIXNODE_CONFIG_KEY: &str = "updated_mixnode_config";
|
||||
pub const UPDATED_GATEWAY_CONFIG_KEY: &str = "updated_gateway_config";
|
||||
pub const UPDATED_MIXNODE_COST_PARAMS_KEY: &str = "updated_mixnode_cost_params";
|
||||
|
||||
// rewarding
|
||||
@@ -382,6 +386,17 @@ pub fn new_mixnode_config_update_event(
|
||||
.add_attribute(UPDATED_MIXNODE_CONFIG_KEY, update.to_inline_json())
|
||||
}
|
||||
|
||||
pub fn new_gateway_config_update_event(
|
||||
owner: &Addr,
|
||||
proxy: &Option<Addr>,
|
||||
update: &GatewayConfigUpdate,
|
||||
) -> Event {
|
||||
Event::new(MixnetEventType::GatewayConfigUpdate)
|
||||
.add_attribute(OWNER_KEY, owner)
|
||||
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
|
||||
.add_attribute(UPDATED_GATEWAY_CONFIG_KEY, update.to_inline_json())
|
||||
}
|
||||
|
||||
pub fn new_mixnode_pending_cost_params_update_event(
|
||||
mix_id: MixId,
|
||||
owner: &Addr,
|
||||
|
||||
@@ -112,6 +112,26 @@ impl Display for GatewayBond {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/GatewayConfigUpdate.ts")
|
||||
)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
|
||||
pub struct GatewayConfigUpdate {
|
||||
pub host: String,
|
||||
pub mix_port: u16,
|
||||
pub clients_port: u16,
|
||||
pub location: String,
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
impl GatewayConfigUpdate {
|
||||
pub fn to_inline_json(&self) -> String {
|
||||
serde_json::to_string(self).unwrap_or_else(|_| "serialisation failure".into())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
|
||||
pub struct PagedGatewayResponse {
|
||||
pub nodes: Vec<GatewayBond>,
|
||||
|
||||
@@ -27,7 +27,8 @@ pub use delegation::{
|
||||
PagedMixNodeDelegationsResponse,
|
||||
};
|
||||
pub use gateway::{
|
||||
Gateway, GatewayBond, GatewayBondResponse, GatewayOwnershipResponse, PagedGatewayResponse,
|
||||
Gateway, GatewayBond, GatewayBondResponse, GatewayConfigUpdate, GatewayOwnershipResponse,
|
||||
PagedGatewayResponse,
|
||||
};
|
||||
pub use interval::{
|
||||
CurrentIntervalResponse, EpochState, EpochStatus, Interval, NumberOfPendingEventsResponse,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::delegation::OwnerProxySubKey;
|
||||
use crate::error::MixnetContractError;
|
||||
use crate::gateway::GatewayConfigUpdate;
|
||||
use crate::helpers::IntoBaseDecimal;
|
||||
use crate::mixnode::{MixNodeConfigUpdate, MixNodeCostParams};
|
||||
use crate::reward_params::{
|
||||
@@ -199,6 +200,13 @@ pub enum ExecuteMsg {
|
||||
UnbondGatewayOnBehalf {
|
||||
owner: String,
|
||||
},
|
||||
UpdateGatewayConfig {
|
||||
new_config: GatewayConfigUpdate,
|
||||
},
|
||||
UpdateGatewayConfigOnBehalf {
|
||||
new_config: GatewayConfigUpdate,
|
||||
owner: String,
|
||||
},
|
||||
|
||||
// delegation-related:
|
||||
DelegateToMixnode {
|
||||
@@ -313,6 +321,10 @@ impl ExecuteMsg {
|
||||
}
|
||||
ExecuteMsg::UnbondGateway { .. } => "unbonding gateway".into(),
|
||||
ExecuteMsg::UnbondGatewayOnBehalf { .. } => "unbonding gateway on behalf".into(),
|
||||
ExecuteMsg::UpdateGatewayConfig { .. } => "updating gateway configuration".into(),
|
||||
ExecuteMsg::UpdateGatewayConfigOnBehalf { .. } => {
|
||||
"updating gateway configuration on behalf".into()
|
||||
}
|
||||
ExecuteMsg::DelegateToMixnode { mix_id } => format!("delegating to mixnode {mix_id}"),
|
||||
ExecuteMsg::DelegateToMixnodeOnBehalf { mix_id, .. } => {
|
||||
format!("delegating to mixnode {mix_id} on behalf")
|
||||
|
||||
@@ -17,6 +17,7 @@ pub const VESTING_MIXNODE_BONDING_EVENT_TYPE: &str = "vesting_mixnode_bonding";
|
||||
pub const VESTING_PLEDGE_MORE_EVENT_TYPE: &str = "vesting_pledge_more";
|
||||
pub const VESTING_MIXNODE_UNBONDING_EVENT_TYPE: &str = "vesting_mixnode_unbonding";
|
||||
pub const VESTING_UPDATE_MIXNODE_CONFIG_EVENT_TYPE: &str = "vesting_update_mixnode_config";
|
||||
pub const VESTING_UPDATE_GATEWAY_CONFIG_EVENT_TYPE: &str = "vesting_update_gateway_config";
|
||||
pub const VESTING_UPDATE_MIXNODE_COST_PARAMS_EVENT_TYPE: &str =
|
||||
"vesting_update_mixnode_cost_params";
|
||||
|
||||
@@ -121,6 +122,10 @@ pub fn new_vesting_update_mixnode_config_event() -> Event {
|
||||
Event::new(VESTING_UPDATE_MIXNODE_CONFIG_EVENT_TYPE)
|
||||
}
|
||||
|
||||
pub fn new_vesting_update_gateway_config_event() -> Event {
|
||||
Event::new(VESTING_UPDATE_GATEWAY_CONFIG_EVENT_TYPE)
|
||||
}
|
||||
|
||||
pub fn new_vesting_update_mixnode_cost_params_event() -> Event {
|
||||
Event::new(VESTING_UPDATE_MIXNODE_COST_PARAMS_EVENT_TYPE)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use contracts_common::signing::MessageSignature;
|
||||
use cosmwasm_std::{Coin, Timestamp};
|
||||
use mixnet_contract_common::{
|
||||
gateway::GatewayConfigUpdate,
|
||||
mixnode::{MixNodeConfigUpdate, MixNodeCostParams},
|
||||
Gateway, IdentityKey, MixId, MixNode,
|
||||
};
|
||||
@@ -140,6 +141,9 @@ pub enum ExecuteMsg {
|
||||
owner: String,
|
||||
amount: Coin,
|
||||
},
|
||||
UpdateGatewayConfig {
|
||||
new_config: GatewayConfigUpdate,
|
||||
},
|
||||
TransferOwnership {
|
||||
to_address: String,
|
||||
},
|
||||
@@ -179,6 +183,7 @@ impl ExecuteMsg {
|
||||
ExecuteMsg::BondGateway { .. } => "VestingExecuteMsg::BondGateway",
|
||||
ExecuteMsg::UnbondGateway { .. } => "VestingExecuteMsg::UnbondGateway",
|
||||
ExecuteMsg::TrackUnbondGateway { .. } => "VestingExecuteMsg::TrackUnbondGateway",
|
||||
ExecuteMsg::UpdateGatewayConfig { .. } => "VestingExecuteMsg::UpdateGatewayConfig",
|
||||
ExecuteMsg::TransferOwnership { .. } => "VestingExecuteMsg::TransferOwnership",
|
||||
ExecuteMsg::UpdateStakingAddress { .. } => "VestingExecuteMsg::UpdateStakingAddress",
|
||||
ExecuteMsg::UpdateLockedPledgeCap { .. } => "VestingExecuteMsg::UpdateLockedPledgeCap",
|
||||
|
||||
@@ -13,12 +13,20 @@ humantime-serde = "1.0"
|
||||
log = { workspace = true }
|
||||
rand = "0.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tokio = { version = "1.24.1", features = ["time", "macros", "rt", "net", "io-util"] }
|
||||
tokio = { version = "1.24.1", features = [
|
||||
"time",
|
||||
"macros",
|
||||
"rt",
|
||||
"net",
|
||||
"io-util",
|
||||
] }
|
||||
tokio-util = { version = "0.7.4", features = ["codec"] }
|
||||
url = "2.2"
|
||||
thiserror = "1.0.37"
|
||||
chitchat = "0.5"
|
||||
serde_json = "1"
|
||||
|
||||
nym-crypto = { path = "../crypto" }
|
||||
nym-crypto = { path = "../crypto" }
|
||||
nym-network-defaults = { path = "../network-defaults" }
|
||||
nym-sphinx-acknowledgements = { path = "../nymsphinx/acknowledgements" }
|
||||
nym-sphinx-addressing = { path = "../nymsphinx/addressing" }
|
||||
@@ -27,5 +35,7 @@ nym-sphinx-framing = { path = "../nymsphinx/framing" }
|
||||
nym-sphinx-params = { path = "../nymsphinx/params" }
|
||||
nym-sphinx-types = { path = "../nymsphinx/types" }
|
||||
nym-task = { path = "../task" }
|
||||
validator-client = { path = "../client-libs/validator-client", features = ["nyxd-client"]}
|
||||
validator-client = { path = "../client-libs/validator-client", features = [
|
||||
"nyxd-client",
|
||||
] }
|
||||
nym-bin-common = { path = "../bin-common" }
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::verloc::listener::PacketListener;
|
||||
use crate::verloc::sender::{PacketSender, TestedNode};
|
||||
use chitchat::Chitchat;
|
||||
use futures::stream::FuturesUnordered;
|
||||
use futures::StreamExt;
|
||||
use log::*;
|
||||
@@ -16,6 +17,7 @@ use std::net::SocketAddr;
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::task::JoinHandle;
|
||||
use tokio::time::sleep;
|
||||
use url::Url;
|
||||
@@ -293,7 +295,7 @@ impl VerlocMeasurer {
|
||||
MeasurementOutcome::Done
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) {
|
||||
pub async fn run(&mut self, chitchat_handle: Arc<Mutex<Chitchat>>) {
|
||||
self.start_listening();
|
||||
|
||||
while !self.shutdown_listener.is_shutdown() {
|
||||
@@ -345,6 +347,17 @@ impl VerlocMeasurer {
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut chitchat_guard = chitchat_handle.lock().await;
|
||||
let cc_state = chitchat_guard.self_node_state();
|
||||
let tested_nodes_cc = tested_nodes
|
||||
.iter()
|
||||
.map(|node| node.identity.to_string())
|
||||
.collect::<Vec<String>>();
|
||||
cc_state.set(
|
||||
"tested_nodes",
|
||||
serde_json::to_value(tested_nodes_cc).expect("Could not serialize"),
|
||||
);
|
||||
|
||||
// on start of each run remove old results
|
||||
self.results.reset_results(tested_nodes.len()).await;
|
||||
|
||||
|
||||
@@ -377,6 +377,7 @@ pub const DEFAULT_CLIENT_LISTENING_PORT: u16 = 9000;
|
||||
// 'MIXNODE'
|
||||
pub const DEFAULT_VERLOC_LISTENING_PORT: u16 = 1790;
|
||||
pub const DEFAULT_HTTP_API_LISTENING_PORT: u16 = 8000;
|
||||
pub const DEFAULT_GOSSIP_PORT: u16 = 10000;
|
||||
|
||||
// 'CLIENT'
|
||||
pub const DEFAULT_WEBSOCKET_LISTENING_PORT: u16 = 1977;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Cargo.lock
|
||||
@@ -318,6 +318,14 @@ pub fn execute(
|
||||
ExecuteMsg::UnbondGatewayOnBehalf { owner } => {
|
||||
crate::gateways::transactions::try_remove_gateway_on_behalf(deps, info, owner)
|
||||
}
|
||||
ExecuteMsg::UpdateGatewayConfig { new_config } => {
|
||||
crate::gateways::transactions::try_update_gateway_config(deps, info, new_config)
|
||||
}
|
||||
ExecuteMsg::UpdateGatewayConfigOnBehalf { new_config, owner } => {
|
||||
crate::gateways::transactions::try_update_gateway_config_on_behalf(
|
||||
deps, info, new_config, owner,
|
||||
)
|
||||
}
|
||||
|
||||
// delegation-related:
|
||||
ExecuteMsg::DelegateToMixnode { mix_id } => {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::storage;
|
||||
use cosmwasm_std::{Addr, Storage};
|
||||
use mixnet_contract_common::{error::MixnetContractError, GatewayBond};
|
||||
|
||||
pub(crate) fn must_get_gateway_bond_by_owner(
|
||||
store: &dyn Storage,
|
||||
owner: &Addr,
|
||||
) -> Result<GatewayBond, MixnetContractError> {
|
||||
Ok(storage::gateways()
|
||||
.idx
|
||||
.owner
|
||||
.item(store, owner.clone())?
|
||||
.ok_or(MixnetContractError::NoAssociatedGatewayBond {
|
||||
owner: owner.clone(),
|
||||
})?
|
||||
.1)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod helpers;
|
||||
pub mod queries;
|
||||
pub mod signature_helpers;
|
||||
pub mod storage;
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::helpers::must_get_gateway_bond_by_owner;
|
||||
use super::storage;
|
||||
use crate::gateways::signature_helpers::verify_gateway_bonding_signature;
|
||||
use crate::mixnet_contract_settings::storage as mixnet_params_storage;
|
||||
use crate::signing::storage as signing_storage;
|
||||
use crate::support::helpers::{
|
||||
ensure_no_existing_bond, ensure_sent_by_vesting_contract, validate_pledge,
|
||||
ensure_no_existing_bond, ensure_proxy_match, ensure_sent_by_vesting_contract, validate_pledge,
|
||||
};
|
||||
use cosmwasm_std::{wasm_execute, Addr, BankMsg, Coin, DepsMut, Env, MessageInfo, Response};
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
use mixnet_contract_common::events::{new_gateway_bonding_event, new_gateway_unbonding_event};
|
||||
use mixnet_contract_common::events::{
|
||||
new_gateway_bonding_event, new_gateway_config_update_event, new_gateway_unbonding_event,
|
||||
};
|
||||
use mixnet_contract_common::gateway::GatewayConfigUpdate;
|
||||
use mixnet_contract_common::{Gateway, GatewayBond};
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use vesting_contract_common::messages::ExecuteMsg as VestingContractExecuteMsg;
|
||||
@@ -189,6 +193,56 @@ pub(crate) fn _try_remove_gateway(
|
||||
)))
|
||||
}
|
||||
|
||||
pub(crate) fn try_update_gateway_config(
|
||||
deps: DepsMut<'_>,
|
||||
info: MessageInfo,
|
||||
new_config: GatewayConfigUpdate,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
let owner = info.sender;
|
||||
_try_update_gateway_config(deps, new_config, owner, None)
|
||||
}
|
||||
|
||||
pub(crate) fn try_update_gateway_config_on_behalf(
|
||||
deps: DepsMut,
|
||||
info: MessageInfo,
|
||||
new_config: GatewayConfigUpdate,
|
||||
owner: String,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
ensure_sent_by_vesting_contract(&info, deps.storage)?;
|
||||
|
||||
let owner = deps.api.addr_validate(&owner)?;
|
||||
let proxy = info.sender;
|
||||
_try_update_gateway_config(deps, new_config, owner, Some(proxy))
|
||||
}
|
||||
|
||||
pub(crate) fn _try_update_gateway_config(
|
||||
deps: DepsMut,
|
||||
new_config: GatewayConfigUpdate,
|
||||
owner: Addr,
|
||||
proxy: Option<Addr>,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
let existing_bond = must_get_gateway_bond_by_owner(deps.storage, &owner)?;
|
||||
ensure_proxy_match(&proxy, &existing_bond.proxy)?;
|
||||
|
||||
let cfg_update_event = new_gateway_config_update_event(&owner, &proxy, &new_config);
|
||||
|
||||
let mut updated_bond = existing_bond.clone();
|
||||
updated_bond.gateway.host = new_config.host;
|
||||
updated_bond.gateway.mix_port = new_config.mix_port;
|
||||
updated_bond.gateway.clients_port = new_config.clients_port;
|
||||
updated_bond.gateway.location = new_config.location;
|
||||
updated_bond.gateway.version = new_config.version;
|
||||
|
||||
storage::gateways().replace(
|
||||
deps.storage,
|
||||
existing_bond.identity(),
|
||||
Some(&updated_bond),
|
||||
Some(&existing_bond),
|
||||
)?;
|
||||
|
||||
Ok(Response::new().add_event(cfg_update_event))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
@@ -196,6 +250,7 @@ pub mod tests {
|
||||
use crate::gateways::queries;
|
||||
use crate::gateways::transactions::{
|
||||
try_add_gateway, try_add_gateway_on_behalf, try_remove_gateway_on_behalf,
|
||||
try_update_gateway_config, try_update_gateway_config_on_behalf,
|
||||
};
|
||||
use crate::interval::pending_events;
|
||||
use crate::mixnet_contract_settings::storage::minimum_gateway_pledge;
|
||||
@@ -207,6 +262,7 @@ pub mod tests {
|
||||
use cosmwasm_std::{Addr, BankMsg, Response, Uint128};
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
use mixnet_contract_common::events::new_gateway_unbonding_event;
|
||||
use mixnet_contract_common::gateway::GatewayConfigUpdate;
|
||||
use mixnet_contract_common::ExecuteMsg;
|
||||
|
||||
#[test]
|
||||
@@ -485,4 +541,94 @@ pub mod tests {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_gateway_config() {
|
||||
let mut test = TestSetup::new();
|
||||
|
||||
let owner = "alice";
|
||||
let info = mock_info(owner, &[]);
|
||||
let update = GatewayConfigUpdate {
|
||||
host: "1.1.1.1:1234".to_string(),
|
||||
mix_port: 1234,
|
||||
clients_port: 1235,
|
||||
location: "home".to_string(),
|
||||
version: "v1.2.3".to_string(),
|
||||
};
|
||||
|
||||
// try updating a non existing gateway bond
|
||||
let res = try_update_gateway_config(test.deps_mut(), info.clone(), update.clone());
|
||||
assert_eq!(
|
||||
res,
|
||||
Err(MixnetContractError::NoAssociatedGatewayBond {
|
||||
owner: Addr::unchecked(owner)
|
||||
})
|
||||
);
|
||||
|
||||
test.add_dummy_gateway(owner, None);
|
||||
let vesting_contract = test.vesting_contract();
|
||||
|
||||
// attempted to remove on behalf with invalid proxy (current is `None`)
|
||||
let res = try_update_gateway_config_on_behalf(
|
||||
test.deps_mut(),
|
||||
mock_info(vesting_contract.as_ref(), &[]),
|
||||
update.clone(),
|
||||
owner.to_string(),
|
||||
);
|
||||
assert_eq!(
|
||||
res,
|
||||
Err(MixnetContractError::ProxyMismatch {
|
||||
existing: "None".to_string(),
|
||||
incoming: vesting_contract.into_string()
|
||||
})
|
||||
);
|
||||
|
||||
// "normal" update succeeds
|
||||
let res = try_update_gateway_config(test.deps_mut(), info, update.clone());
|
||||
assert!(res.is_ok());
|
||||
|
||||
// and the config has actually been updated
|
||||
let bond =
|
||||
must_get_gateway_bond_by_owner(test.deps().storage, &Addr::unchecked(owner)).unwrap();
|
||||
assert_eq!(bond.gateway.host, update.host);
|
||||
assert_eq!(bond.gateway.mix_port, update.mix_port);
|
||||
assert_eq!(bond.gateway.clients_port, update.clients_port);
|
||||
assert_eq!(bond.gateway.location, update.location);
|
||||
assert_eq!(bond.gateway.version, update.version);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn updating_gateway_config_with_illegal_proxy() {
|
||||
let mut test = TestSetup::new();
|
||||
|
||||
let illegal_proxy = Addr::unchecked("not-vesting-contract");
|
||||
let vesting_contract = test.vesting_contract();
|
||||
|
||||
let owner = "alice";
|
||||
|
||||
test.add_dummy_gateway_with_illegal_proxy(owner, None, illegal_proxy.clone());
|
||||
let update = GatewayConfigUpdate {
|
||||
host: "1.1.1.1:1234".to_string(),
|
||||
mix_port: 1234,
|
||||
clients_port: 1235,
|
||||
location: "at home".to_string(),
|
||||
version: "v1.2.3".to_string(),
|
||||
};
|
||||
|
||||
let res = try_update_gateway_config_on_behalf(
|
||||
test.deps_mut(),
|
||||
mock_info(illegal_proxy.as_ref(), &[]),
|
||||
update,
|
||||
owner.to_string(),
|
||||
)
|
||||
.unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
res,
|
||||
MixnetContractError::SenderIsNotVestingContract {
|
||||
received: illegal_proxy,
|
||||
vesting_contract
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ pub(crate) fn try_update_mixnode_config(
|
||||
}
|
||||
|
||||
pub(crate) fn try_update_mixnode_config_on_behalf(
|
||||
deps: DepsMut,
|
||||
deps: DepsMut<'_>,
|
||||
info: MessageInfo,
|
||||
new_config: MixNodeConfigUpdate,
|
||||
owner: String,
|
||||
@@ -308,7 +308,7 @@ pub(crate) fn try_update_mixnode_config_on_behalf(
|
||||
}
|
||||
|
||||
pub(crate) fn _try_update_mixnode_config(
|
||||
deps: DepsMut,
|
||||
deps: DepsMut<'_>,
|
||||
new_config: MixNodeConfigUpdate,
|
||||
owner: Addr,
|
||||
proxy: Option<Addr>,
|
||||
|
||||
@@ -20,7 +20,7 @@ pub mod test_helpers {
|
||||
perform_pending_epoch_actions, perform_pending_interval_actions, try_begin_epoch_transition,
|
||||
};
|
||||
use crate::interval::{pending_events, storage as interval_storage};
|
||||
use crate::mixnet_contract_settings::storage as mixnet_params_storage;
|
||||
use crate::mixnet_contract_settings::storage::{self as mixnet_params_storage};
|
||||
use crate::mixnet_contract_settings::storage::{
|
||||
minimum_gateway_pledge, minimum_mixnode_pledge, rewarding_denom,
|
||||
rewarding_validator_address,
|
||||
|
||||
@@ -14,6 +14,7 @@ use cosmwasm_std::{
|
||||
QueryResponse, Response, StdError, StdResult, Timestamp, Uint128,
|
||||
};
|
||||
use cw_storage_plus::Bound;
|
||||
use mixnet_contract_common::gateway::GatewayConfigUpdate;
|
||||
use mixnet_contract_common::mixnode::{MixNodeConfigUpdate, MixNodeCostParams};
|
||||
use mixnet_contract_common::{Gateway, MixId, MixNode};
|
||||
use semver::Version;
|
||||
@@ -219,6 +220,9 @@ pub fn execute(
|
||||
ExecuteMsg::TrackUnbondGateway { owner, amount } => {
|
||||
try_track_unbond_gateway(&owner, amount, info, deps)
|
||||
}
|
||||
ExecuteMsg::UpdateGatewayConfig { new_config } => {
|
||||
try_update_gateway_config(new_config, info, deps)
|
||||
}
|
||||
ExecuteMsg::TransferOwnership { to_address } => {
|
||||
try_transfer_ownership(to_address, info, deps)
|
||||
}
|
||||
@@ -300,6 +304,15 @@ pub fn try_update_mixnode_config(
|
||||
account.try_update_mixnode_config(new_config, deps.storage)
|
||||
}
|
||||
|
||||
pub fn try_update_gateway_config(
|
||||
new_config: GatewayConfigUpdate,
|
||||
info: MessageInfo,
|
||||
deps: DepsMut,
|
||||
) -> Result<Response, ContractError> {
|
||||
let account = account_from_address(info.sender.as_str(), deps.storage, deps.api)?;
|
||||
account.try_update_gateway_config(new_config, deps.storage)
|
||||
}
|
||||
|
||||
pub fn try_update_mixnode_cost_params(
|
||||
new_costs: MixNodeCostParams,
|
||||
info: MessageInfo,
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::errors::ContractError;
|
||||
use contracts_common::signing::MessageSignature;
|
||||
use cosmwasm_std::{Coin, Env, Response, Storage};
|
||||
use mixnet_contract_common::{
|
||||
gateway::GatewayConfigUpdate,
|
||||
mixnode::{MixNodeConfigUpdate, MixNodeCostParams},
|
||||
Gateway, MixNode,
|
||||
};
|
||||
@@ -64,4 +65,10 @@ pub trait GatewayBondingAccount {
|
||||
amount: Coin,
|
||||
storage: &mut dyn Storage,
|
||||
) -> Result<(), ContractError>;
|
||||
|
||||
fn try_update_gateway_config(
|
||||
&self,
|
||||
new_config: GatewayConfigUpdate,
|
||||
storage: &mut dyn Storage,
|
||||
) -> Result<Response, ContractError>;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,12 @@ use crate::storage::MIXNET_CONTRACT_ADDRESS;
|
||||
use crate::traits::GatewayBondingAccount;
|
||||
use contracts_common::signing::MessageSignature;
|
||||
use cosmwasm_std::{wasm_execute, Coin, Env, Response, Storage, Uint128};
|
||||
use mixnet_contract_common::{ExecuteMsg as MixnetExecuteMsg, Gateway};
|
||||
use mixnet_contract_common::{
|
||||
gateway::GatewayConfigUpdate, ExecuteMsg as MixnetExecuteMsg, Gateway,
|
||||
};
|
||||
use vesting_contract_common::events::{
|
||||
new_vesting_gateway_bonding_event, new_vesting_gateway_unbonding_event,
|
||||
new_vesting_update_gateway_config_event,
|
||||
};
|
||||
|
||||
use super::Account;
|
||||
@@ -78,4 +81,22 @@ impl GatewayBondingAccount for Account {
|
||||
self.remove_gateway_pledge(storage)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_update_gateway_config(
|
||||
&self,
|
||||
new_config: GatewayConfigUpdate,
|
||||
storage: &mut dyn Storage,
|
||||
) -> Result<Response, ContractError> {
|
||||
let msg = MixnetExecuteMsg::UpdateGatewayConfigOnBehalf {
|
||||
new_config,
|
||||
owner: self.owner_address().into_string(),
|
||||
};
|
||||
|
||||
let update_gateway_config_msg =
|
||||
wasm_execute(MIXNET_CONTRACT_ADDRESS.load(storage)?, &msg, vec![])?;
|
||||
|
||||
Ok(Response::new()
|
||||
.add_message(update_gateway_config_msg)
|
||||
.add_event(new_vesting_update_gateway_config_event()))
|
||||
}
|
||||
}
|
||||
|
||||
+21
-13
@@ -29,32 +29,40 @@ log = { workspace = true }
|
||||
pretty_env_logger = "0.4.0"
|
||||
rand = "0.7.3"
|
||||
rocket = { version = "0.5.0-rc.2", features = ["json"] }
|
||||
serde = { version="1.0", features = ["derive"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
sysinfo = "0.27.7"
|
||||
tokio = { version="1.21.2", features = ["rt-multi-thread", "net", "signal"] }
|
||||
tokio-util = { version="0.7.3", features = ["codec"] }
|
||||
tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] }
|
||||
tokio-util = { version = "0.7.3", features = ["codec"] }
|
||||
toml = "0.5.8"
|
||||
url = { version = "2.2", features = ["serde"] }
|
||||
atty = "0.2"
|
||||
|
||||
## internal
|
||||
nym-config = { path="../common/config" }
|
||||
nym-crypto = { path="../common/crypto" }
|
||||
nym-config = { path = "../common/config" }
|
||||
nym-crypto = { path = "../common/crypto" }
|
||||
nym-contracts-common = { path = "../common/cosmwasm-smart-contracts/contracts-common" }
|
||||
mixnet-client = { path="../common/client-libs/mixnet-client" }
|
||||
mixnode-common = { path="../common/mixnode-common" }
|
||||
nym-nonexhaustive-delayqueue = { path="../common/nonexhaustive-delayqueue" }
|
||||
nym-sphinx = { path="../common/nymsphinx" }
|
||||
mixnet-client = { path = "../common/client-libs/mixnet-client" }
|
||||
mixnode-common = { path = "../common/mixnode-common" }
|
||||
nym-nonexhaustive-delayqueue = { path = "../common/nonexhaustive-delayqueue" }
|
||||
nym-sphinx = { path = "../common/nymsphinx" }
|
||||
nym-pemstore = { path = "../common/pemstore", version = "0.2.0" }
|
||||
nym-task = { path = "../common/task" }
|
||||
nym-types = { path = "../common/types" }
|
||||
nym-topology = { path="../common/topology" }
|
||||
validator-client = { path="../common/client-libs/validator-client" }
|
||||
nym-bin-common = { path="../common/bin-common" }
|
||||
nym-topology = { path = "../common/topology" }
|
||||
validator-client = { path = "../common/client-libs/validator-client" }
|
||||
nym-bin-common = { path = "../common/bin-common" }
|
||||
|
||||
# chichat
|
||||
chitchat = "0.5"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version="1.21.2", features = ["rt-multi-thread", "net", "signal", "test-util"] }
|
||||
tokio = { version = "1.21.2", features = [
|
||||
"rt-multi-thread",
|
||||
"net",
|
||||
"signal",
|
||||
"test-util",
|
||||
] }
|
||||
|
||||
nym-sphinx-types = { path = "../common/nymsphinx/types" }
|
||||
nym-sphinx-params = { path = "../common/nymsphinx/params" }
|
||||
|
||||
@@ -109,5 +109,5 @@ pub(crate) async fn execute(args: &Run, output: OutputFormat) {
|
||||
Select the correct version and install it to your machine. You will need to provide the following: \n ");
|
||||
mixnode.print_node_details(output);
|
||||
|
||||
mixnode.run().await
|
||||
mixnode.run().await.expect("Could not run mixnode")
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
use crate::config::template::config_template;
|
||||
use nym_config::defaults::mainnet::NYM_API;
|
||||
use nym_config::defaults::{
|
||||
DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT,
|
||||
DEFAULT_GOSSIP_PORT, DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT,
|
||||
DEFAULT_VERLOC_LISTENING_PORT,
|
||||
};
|
||||
use nym_config::NymConfig;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
@@ -258,6 +259,10 @@ impl Config {
|
||||
self.mixnode.http_api_port
|
||||
}
|
||||
|
||||
pub fn get_gossip_port(&self) -> u16 {
|
||||
self.mixnode.gossip_port
|
||||
}
|
||||
|
||||
pub fn get_packet_forwarding_initial_backoff(&self) -> Duration {
|
||||
self.debug.packet_forwarding_initial_backoff
|
||||
}
|
||||
@@ -348,6 +353,10 @@ struct MixNode {
|
||||
#[serde(default = "default_http_api_port")]
|
||||
http_api_port: u16,
|
||||
|
||||
/// Port used for the gossip protocol
|
||||
#[serde(default = "default_http_api_port")]
|
||||
gossip_port: u16,
|
||||
|
||||
/// Path to file containing private identity key.
|
||||
#[serde(default = "missing_string_value")]
|
||||
private_identity_key_file: PathBuf,
|
||||
@@ -402,6 +411,7 @@ impl Default for MixNode {
|
||||
mix_port: DEFAULT_MIX_LISTENING_PORT,
|
||||
verloc_port: DEFAULT_VERLOC_LISTENING_PORT,
|
||||
http_api_port: DEFAULT_HTTP_API_LISTENING_PORT,
|
||||
gossip_port: DEFAULT_GOSSIP_PORT,
|
||||
private_identity_key_file: Default::default(),
|
||||
public_identity_key_file: Default::default(),
|
||||
private_sphinx_key_file: Default::default(),
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use chitchat::{Chitchat, ClusterStateSnapshot, NodeId};
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::State;
|
||||
use serde::Serialize;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct ClusterState {
|
||||
cluster_id: String,
|
||||
cluster_state: ClusterStateSnapshot,
|
||||
live_nodes: Vec<NodeId>,
|
||||
dead_nodes: Vec<NodeId>,
|
||||
}
|
||||
|
||||
/// Returns a description of the node and why someone might want to delegate stake to it.
|
||||
#[get("/state")]
|
||||
pub(crate) async fn state(chitchat: &State<Arc<Mutex<Chitchat>>>) -> Json<ClusterState> {
|
||||
let chitchat_guard = chitchat.lock().await;
|
||||
let cluster_state = ClusterState {
|
||||
cluster_id: chitchat_guard.cluster_id().to_string(),
|
||||
cluster_state: chitchat_guard.state_snapshot(),
|
||||
live_nodes: chitchat_guard.live_nodes().cloned().collect::<Vec<_>>(),
|
||||
dead_nodes: chitchat_guard.dead_nodes().cloned().collect::<Vec<_>>(),
|
||||
};
|
||||
Json(cluster_state)
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
pub(crate) mod description;
|
||||
pub(crate) mod gossip;
|
||||
pub(crate) mod hardware;
|
||||
pub(crate) mod stats;
|
||||
pub(crate) mod verloc;
|
||||
|
||||
+67
-12
@@ -5,6 +5,7 @@ use crate::config::persistence::pathfinder::MixNodePathfinder;
|
||||
use crate::config::Config;
|
||||
use crate::node::http::{
|
||||
description::description,
|
||||
gossip,
|
||||
hardware::hardware,
|
||||
not_found,
|
||||
stats::stats,
|
||||
@@ -17,6 +18,10 @@ use crate::node::node_description::NodeDescription;
|
||||
use crate::node::node_statistics::SharedNodeStats;
|
||||
use crate::node::packet_delayforwarder::{DelayForwarder, PacketDelayForwardSender};
|
||||
use crate::OutputFormat;
|
||||
use chitchat::transport::UdpTransport;
|
||||
use chitchat::{
|
||||
spawn_chitchat, Chitchat, ChitchatConfig, ChitchatHandle, FailureDetectorConfig, NodeId,
|
||||
};
|
||||
use log::{error, info, warn};
|
||||
use mixnode_common::verloc::{self, AtomicVerlocResult, VerlocMeasurer};
|
||||
use nym_bin_common::version_checker::parse_version;
|
||||
@@ -28,6 +33,8 @@ use rand::thread_rng;
|
||||
use std::net::SocketAddr;
|
||||
use std::process;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
mod http;
|
||||
mod listener;
|
||||
@@ -110,6 +117,7 @@ impl MixNode {
|
||||
&self,
|
||||
atomic_verloc_result: AtomicVerlocResult,
|
||||
node_stats_pointer: SharedNodeStats,
|
||||
chitchat: Arc<Mutex<Chitchat>>,
|
||||
) {
|
||||
info!("Starting HTTP API on http://localhost:8000");
|
||||
|
||||
@@ -125,11 +133,15 @@ impl MixNode {
|
||||
tokio::spawn(async move {
|
||||
rocket::build()
|
||||
.configure(config)
|
||||
.mount("/", routes![verlocRoute, description, stats, hardware])
|
||||
.mount(
|
||||
"/",
|
||||
routes![verlocRoute, description, stats, hardware, gossip::state],
|
||||
)
|
||||
.register("/", catchers![not_found])
|
||||
.manage(verloc_state)
|
||||
.manage(descriptor)
|
||||
.manage(node_stats_pointer)
|
||||
.manage(chitchat)
|
||||
.launch()
|
||||
.await
|
||||
});
|
||||
@@ -199,7 +211,11 @@ impl MixNode {
|
||||
packet_sender
|
||||
}
|
||||
|
||||
fn start_verloc_measurements(&self, shutdown: TaskClient) -> AtomicVerlocResult {
|
||||
fn start_verloc_measurements(
|
||||
&self,
|
||||
chitchat: Arc<Mutex<Chitchat>>,
|
||||
shutdown: TaskClient,
|
||||
) -> AtomicVerlocResult {
|
||||
info!("Starting the round-trip-time measurer...");
|
||||
|
||||
// this is a sanity check to make sure we didn't mess up with the minimum version at some point
|
||||
@@ -235,7 +251,7 @@ impl MixNode {
|
||||
let mut verloc_measurer =
|
||||
VerlocMeasurer::new(config, Arc::clone(&self.identity_keypair), shutdown);
|
||||
let atomic_verloc_results = verloc_measurer.get_verloc_results_pointer();
|
||||
tokio::spawn(async move { verloc_measurer.run().await });
|
||||
tokio::spawn(async move { verloc_measurer.run(chitchat).await });
|
||||
atomic_verloc_results
|
||||
}
|
||||
|
||||
@@ -277,18 +293,53 @@ impl MixNode {
|
||||
log::info!("Stopping nym mixnode");
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) {
|
||||
fn gossip_node_id(&self) -> NodeId {
|
||||
NodeId::new(
|
||||
self.identity_keypair.public_key().to_string(),
|
||||
(
|
||||
self.config.get_listening_address(),
|
||||
self.config.get_gossip_port(),
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
fn gossip_config(&self) -> ChitchatConfig {
|
||||
ChitchatConfig {
|
||||
node_id: self.gossip_node_id(),
|
||||
cluster_id: "hive_mind".to_string(),
|
||||
gossip_interval: Duration::from_millis(500),
|
||||
listen_addr: (
|
||||
self.config.get_listening_address(),
|
||||
self.config.get_gossip_port(),
|
||||
)
|
||||
.into(),
|
||||
// We'd probably wanna get this from the nym_api, or have a few known good nodes, the ones we run probably
|
||||
seed_nodes: vec![],
|
||||
failure_detector_config: FailureDetectorConfig::default(),
|
||||
is_ready_predicate: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn init_chitchat(&self) -> Result<ChitchatHandle, String> {
|
||||
let chitchat_handler = spawn_chitchat(self.gossip_config(), Vec::new(), &UdpTransport)
|
||||
.await
|
||||
.map_err(|_| "Could not spawn chitchat")?;
|
||||
|
||||
Ok(chitchat_handler)
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) -> Result<(), String> {
|
||||
info!("Starting nym mixnode");
|
||||
|
||||
if let Some(duplicate_node_key) = self.check_if_same_ip_node_exists().await {
|
||||
if duplicate_node_key == self.identity_keypair.public_key().to_base58_string() {
|
||||
warn!("You seem to have bonded your mixnode before starting it - that's highly unrecommended as in the future it might result in slashing");
|
||||
} else {
|
||||
log::error!(
|
||||
"Our announce-host is identical to an existing node's announce-host! (its key is {:?})",
|
||||
duplicate_node_key
|
||||
);
|
||||
return;
|
||||
let err = format!("Our announce-host is identical to an existing node's announce-host! (its key is {:?})",
|
||||
duplicate_node_key);
|
||||
log::error!("{err}");
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,14 +354,18 @@ impl MixNode {
|
||||
delay_forwarding_channel,
|
||||
shutdown.subscribe(),
|
||||
);
|
||||
let atomic_verloc_results = self.start_verloc_measurements(shutdown.subscribe());
|
||||
let chitchat_handler = self.init_chitchat().await?;
|
||||
let chitchat = chitchat_handler.chitchat();
|
||||
let atomic_verloc_results =
|
||||
self.start_verloc_measurements(chitchat.clone(), shutdown.subscribe());
|
||||
|
||||
// Rocket handles shutdown on it's own, but its shutdown handling should be incorporated
|
||||
// with that of the rest of the tasks.
|
||||
// Currently it's runtime is forcefully terminated once the mixnode exits.
|
||||
self.start_http_api(atomic_verloc_results, node_stats_pointer);
|
||||
self.start_http_api(atomic_verloc_results, node_stats_pointer, chitchat);
|
||||
|
||||
info!("Finished nym mixnode startup procedure - it should now be able to receive mix traffic!");
|
||||
self.wait_for_interrupt(shutdown).await
|
||||
self.wait_for_interrupt(shutdown).await;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ fn main() {
|
||||
mixnet::bond::unbond_mixnode,
|
||||
mixnet::bond::update_mixnode_cost_params,
|
||||
mixnet::bond::update_mixnode_config,
|
||||
mixnet::bond::update_gateway_config,
|
||||
mixnet::bond::get_number_of_mixnode_delegators,
|
||||
mixnet::bond::get_mix_node_description,
|
||||
mixnet::bond::get_mixnode_avg_uptime,
|
||||
|
||||
@@ -8,6 +8,7 @@ use crate::operations::helpers::{
|
||||
use crate::state::WalletState;
|
||||
use crate::{nyxd_client, Gateway, MixNode};
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_mixnet_contract_common::gateway::GatewayConfigUpdate;
|
||||
use nym_mixnet_contract_common::{MixId, MixNodeConfigUpdate};
|
||||
use nym_types::currency::DecCoin;
|
||||
use nym_types::gateway::GatewayBond;
|
||||
@@ -227,6 +228,31 @@ pub async fn update_mixnode_config(
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn update_gateway_config(
|
||||
update: GatewayConfigUpdate,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
log::info!(
|
||||
">>> Update gateway config: update = {}, fee {:?}",
|
||||
update.to_inline_json(),
|
||||
fee,
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nyxd
|
||||
.update_gateway_config(update, fee)
|
||||
.await?;
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_mixnode_avg_uptime(
|
||||
state: tauri::State<'_, WalletState>,
|
||||
|
||||
@@ -5,8 +5,9 @@ use nym_api_requests::models::{
|
||||
};
|
||||
use nym_mixnet_contract_common::rewarding::RewardEstimate;
|
||||
use nym_mixnet_contract_common::{
|
||||
Interval as ContractInterval, IntervalRewardParams, IntervalRewardingParamsUpdate, MixNode,
|
||||
MixNodeConfigUpdate, RewardedSetNodeStatus, RewardingParams, UnbondedMixnode,
|
||||
GatewayConfigUpdate, Interval as ContractInterval, IntervalRewardParams,
|
||||
IntervalRewardingParamsUpdate, MixNode, MixNodeConfigUpdate, RewardedSetNodeStatus,
|
||||
RewardingParams, UnbondedMixnode,
|
||||
};
|
||||
use nym_types::account::{Account, AccountEntry, AccountWithMnemonic, Balance};
|
||||
use nym_types::currency::{CurrencyDenom, DecCoin};
|
||||
@@ -90,6 +91,7 @@ fn main() {
|
||||
do_export!(Gas);
|
||||
do_export!(GasInfo);
|
||||
do_export!(Gateway);
|
||||
do_export!(GatewayConfigUpdate);
|
||||
do_export!(GatewayBond);
|
||||
do_export!(CurrencyDenom);
|
||||
do_export!(DecCoin);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export interface GatewayConfigUpdate {
|
||||
host: string;
|
||||
mix_port: number;
|
||||
clients_port: number;
|
||||
location: string;
|
||||
version: string;
|
||||
}
|
||||
Reference in New Issue
Block a user