Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/additional directory fixes #4973

Merged
merged 11 commits into from
Oct 16, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,23 @@ impl GeoAwareTopologyProvider {
}

async fn get_topology(&self) -> Option<NymTopology> {
let mixnodes = match self.validator_client.get_basic_mixnodes(None).await {
let mixnodes = match self
.validator_client
.get_basic_active_mixing_assigned_nodes(Some(self.client_version.clone()))
.await
{
Err(err) => {
error!("failed to get network mixnodes - {err}");
return None;
}
Ok(mixes) => mixes,
};

let gateways = match self.validator_client.get_basic_gateways(None).await {
let gateways = match self
.validator_client
.get_all_basic_entry_assigned_nodes(Some(self.client_version.clone()))
.await
{
Err(err) => {
error!("failed to get network gateways - {err}");
return None;
Expand Down Expand Up @@ -185,8 +193,7 @@ impl GeoAwareTopologyProvider {
.filter(|m| filtered_mixnode_ids.contains(&m.node_id))
.collect::<Vec<_>>();

let topology = nym_topology_from_basic_info(&mixnodes, &gateways)
.filter_system_version(&self.client_version);
let topology = nym_topology_from_basic_info(&mixnodes, &gateways);

// TODO: return real error type
check_layer_integrity(topology.clone()).ok()?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl NymApiTopologyProvider {
async fn get_current_compatible_topology(&mut self) -> Option<NymTopology> {
let mixnodes = match self
.validator_client
.get_basic_mixnodes(Some(self.client_version.clone()))
.get_basic_active_mixing_assigned_nodes(Some(self.client_version.clone()))
.await
{
Err(err) => {
Expand All @@ -110,7 +110,7 @@ impl NymApiTopologyProvider {

let gateways = match self
.validator_client
.get_basic_gateways(Some(self.client_version.clone()))
.get_all_basic_entry_assigned_nodes(Some(self.client_version.clone()))
.await
{
Err(err) => {
Expand All @@ -134,7 +134,6 @@ impl NymApiTopologyProvider {
g.performance.round_to_integer() >= self.config.min_gateway_performance
}),
);

if let Err(err) = self.check_layer_distribution(&topology) {
warn!("The current filtered active topology has extremely skewed layer distribution. It cannot be used: {err}");
self.use_next_nym_api();
Expand Down
21 changes: 7 additions & 14 deletions common/client-core/src/init/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use futures::{SinkExt, StreamExt};
use log::{debug, info, trace, warn};
use nym_crypto::asymmetric::identity;
use nym_gateway_client::GatewayClient;
use nym_topology::{filter::VersionFilterable, gateway, mix};
use nym_topology::{gateway, mix};
use nym_validator_client::client::IdentityKeyRef;
use nym_validator_client::UserAgent;
use rand::{seq::SliceRandom, Rng};
Expand Down Expand Up @@ -94,25 +94,20 @@ pub async fn current_gateways<R: Rng>(

log::debug!("Fetching list of gateways from: {nym_api}");

let gateways = client.get_basic_gateways(None).await?;
let gateways = client.get_all_basic_entry_assigned_nodes(None).await?;
log::debug!("Found {} gateways", gateways.len());
log::trace!("Gateways: {:#?}", gateways);

let valid_gateways = gateways
.iter()
.filter_map(|gateway| gateway.try_into().ok())
.collect::<Vec<gateway::LegacyNode>>();
log::debug!("Ater checking validity: {}", valid_gateways.len());
log::debug!("After checking validity: {}", valid_gateways.len());
log::trace!("Valid gateways: {:#?}", valid_gateways);

// we were always filtering by version so I'm not removing that 'feature'
let filtered_gateways = valid_gateways.filter_by_version(env!("CARGO_PKG_VERSION"));
log::debug!("After filtering for version: {}", filtered_gateways.len());
log::trace!("Filtered gateways: {:#?}", filtered_gateways);
log::info!("nym-api reports {} valid gateways", valid_gateways.len());

log::info!("nym-api reports {} valid gateways", filtered_gateways.len());

Ok(filtered_gateways)
Ok(valid_gateways)
}

pub async fn current_mixnodes<R: Rng>(
Expand All @@ -126,15 +121,13 @@ pub async fn current_mixnodes<R: Rng>(

log::trace!("Fetching list of mixnodes from: {nym_api}");

let mixnodes = client.get_basic_mixnodes(None).await?;
let mixnodes = client.get_basic_active_mixing_assigned_nodes(None).await?;
let valid_mixnodes = mixnodes
.iter()
.filter_map(|mixnode| mixnode.try_into().ok())
.collect::<Vec<mix::LegacyNode>>();

// we were always filtering by version so I'm not removing that 'feature'
let filtered_mixnodes = valid_mixnodes.filter_by_version(env!("CARGO_PKG_VERSION"));
Ok(filtered_mixnodes)
Ok(valid_mixnodes)
}

#[cfg(not(target_arch = "wasm32"))]
Expand Down
66 changes: 66 additions & 0 deletions common/client-libs/validator-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ impl NymApiClient {
self.nym_api.change_base_url(new_endpoint);
}

#[deprecated(note = "use get_basic_active_mixing_assigned_nodes instead")]
pub async fn get_basic_mixnodes(
&self,
semver_compatibility: Option<String>,
Expand All @@ -294,6 +295,7 @@ impl NymApiClient {
.nodes)
}

#[deprecated(note = "use get_all_basic_entry_assigned_nodes instead")]
pub async fn get_basic_gateways(
&self,
semver_compatibility: Option<String>,
Expand All @@ -305,6 +307,70 @@ impl NymApiClient {
.nodes)
}

/// retrieve basic information for nodes are capable of operating as an entry gateway
/// this includes legacy gateways and nym-nodes
pub async fn get_all_basic_entry_assigned_nodes(
&self,
semver_compatibility: Option<String>,
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
let mut page = 0;
let mut nodes = Vec::new();

loop {
let mut res = self
.nym_api
.get_all_basic_entry_assigned_nodes(
semver_compatibility.clone(),
false,
Some(page),
None,
)
.await?;

nodes.append(&mut res.nodes.data);
if nodes.len() < res.nodes.pagination.total {
page += 1
} else {
break;
}
}

Ok(nodes)
}

/// retrieve basic information for nodes that got assigned 'mixing' node in this epoch
/// this includes legacy mixnodes and nym-nodes
pub async fn get_basic_active_mixing_assigned_nodes(
&self,
semver_compatibility: Option<String>,
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
let mut page = 0;
let mut nodes = Vec::new();

loop {
let mut res = self
.nym_api
.get_basic_active_mixing_assigned_nodes(
semver_compatibility.clone(),
false,
Some(page),
None,
)
.await?;

nodes.append(&mut res.nodes.data);
if nodes.len() < res.nodes.pagination.total {
page += 1
} else {
break;
}
}

Ok(nodes)
}

pub async fn get_cached_active_mixnodes(
&self,
) -> Result<Vec<MixNodeDetails>, ValidatorClientError> {
Expand Down
83 changes: 83 additions & 0 deletions common/client-libs/validator-client/src/nym_api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use nym_api_requests::ecash::VerificationKeyResponse;
use nym_api_requests::models::{
AnnotationResponse, LegacyDescribedMixNode, NodePerformanceResponse,
};
use nym_api_requests::nym_nodes::PaginatedCachedNodesResponse;
pub use nym_api_requests::{
ecash::{
models::{
Expand Down Expand Up @@ -164,6 +165,88 @@ pub trait NymApiClientExt: ApiClient {
.await
}

/// retrieve basic information for nodes are capable of operating as an entry gateway
/// this includes legacy gateways and nym-nodes
async fn get_all_basic_entry_assigned_nodes(
&self,
semver_compatibility: Option<String>,
no_legacy: bool,
page: Option<u32>,
per_page: Option<u32>,
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
let mut params = Vec::new();

if let Some(arg) = &semver_compatibility {
params.push(("semver_compatibility", arg.clone()))
}

if no_legacy {
params.push(("no_legacy", "true".to_string()))
}

if let Some(page) = page {
params.push(("page", page.to_string()))
}

if let Some(per_page) = per_page {
params.push(("per_page", per_page.to_string()))
}

self.get_json(
&[
routes::API_VERSION,
"unstable",
"nym-nodes",
"skimmed",
"entry-gateways",
"all",
],
&params,
)
.await
}

/// retrieve basic information for nodes that got assigned 'mixing' node in this epoch
/// this includes legacy mixnodes and nym-nodes
async fn get_basic_active_mixing_assigned_nodes(
&self,
semver_compatibility: Option<String>,
no_legacy: bool,
page: Option<u32>,
per_page: Option<u32>,
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
let mut params = Vec::new();

if let Some(arg) = &semver_compatibility {
params.push(("semver_compatibility", arg.clone()))
}

if no_legacy {
params.push(("no_legacy", "true".to_string()))
}

if let Some(page) = page {
params.push(("page", page.to_string()))
}

if let Some(per_page) = per_page {
params.push(("per_page", per_page.to_string()))
}

self.get_json(
&[
routes::API_VERSION,
"unstable",
"nym-nodes",
"skimmed",
"mixnodes",
"active",
],
&params,
)
.await
}

async fn get_active_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
self.get_json(
&[routes::API_VERSION, routes::MIXNODES, routes::ACTIVE],
Expand Down
1 change: 1 addition & 0 deletions common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -830,4 +830,5 @@ pub enum QueryMsg {
#[cw_serde]
pub struct MigrateMsg {
pub vesting_contract_address: Option<String>,
pub unsafe_skip_state_updates: Option<bool>,
}
6 changes: 4 additions & 2 deletions common/wasm/client-core/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ pub async fn current_network_topology_async(
};

let api_client = NymApiClient::new(url);
let mixnodes = api_client.get_basic_mixnodes(None).await?;
let gateways = api_client.get_basic_gateways(None).await?;
let mixnodes = api_client
.get_basic_active_mixing_assigned_nodes(None)
.await?;
let gateways = api_client.get_all_basic_entry_assigned_nodes(None).await?;

Ok(NymTopology::from_basic(&mixnodes, &gateways).into())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ pub fn instantiate_contracts(
mixnet_contract_address.clone(),
&nym_mixnet_contract_common::MigrateMsg {
vesting_contract_address: Some(vesting_contract_address.to_string()),
unsafe_skip_state_updates: None,
},
mixnet_code_id,
)
Expand Down
6 changes: 6 additions & 0 deletions contracts/mixnet/schema/nym-mixnet-contract.json
Original file line number Diff line number Diff line change
Expand Up @@ -3212,6 +3212,12 @@
"title": "MigrateMsg",
"type": "object",
"properties": {
"unsafe_skip_state_updates": {
"type": [
"boolean",
"null"
]
},
"vesting_contract_address": {
"type": [
"string",
Expand Down
6 changes: 6 additions & 0 deletions contracts/mixnet/schema/raw/migrate.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
"title": "MigrateMsg",
"type": "object",
"properties": {
"unsafe_skip_state_updates": {
"type": [
"boolean",
"null"
]
},
"vesting_contract_address": {
"type": [
"string",
Expand Down
12 changes: 8 additions & 4 deletions contracts/mixnet/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,11 +576,15 @@ pub fn migrate(
set_build_information!(deps.storage)?;
cw2::ensure_from_older_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

// remove all family-related things
crate::queued_migrations::families_purge(deps.branch())?;
let skip_state_updates = msg.unsafe_skip_state_updates.unwrap_or(false);

// prepare the ground for using nym-nodes rather than standalone mixnodes/gateways
migrate_to_nym_nodes_usage(deps.branch(), &msg)?;
if !skip_state_updates {
// remove all family-related things
crate::queued_migrations::families_purge(deps.branch())?;

// prepare the ground for using nym-nodes rather than standalone mixnodes/gateways
migrate_to_nym_nodes_usage(deps.branch(), &msg)?;
}

// due to circular dependency on contract addresses (i.e. mixnet contract requiring vesting contract address
// and vesting contract requiring the mixnet contract address), if we ever want to deploy any new fresh
Expand Down
4 changes: 3 additions & 1 deletion nym-api/src/node_describe_cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use std::collections::HashMap;
use std::net::SocketAddr;
use std::time::Duration;
use thiserror::Error;
use tracing::{debug, error};
use tracing::{debug, error, info};

mod query_helpers;

Expand Down Expand Up @@ -389,6 +389,8 @@ impl CacheItemProvider for NodeDescriptionProvider {
.collect::<HashMap<_, _>>()
.await;

info!("refreshed self described data for {} nodes", nodes.len());

Ok(DescribedNodes { nodes })
}
}
Expand Down
Loading
Loading