Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b9339b8f0c | |||
| 43a7360399 | |||
| 5f9f7f0fac | |||
| df0e2fe489 | |||
| bc33cc4c8d | |||
| a31597aca9 | |||
| 378229b04e | |||
| fec196c097 | |||
| d6b3d7fc0a | |||
| ac273480f8 |
@@ -44,8 +44,10 @@ jobs:
|
||||
echo "Tag is empty"
|
||||
exit 1
|
||||
fi
|
||||
# first, list all tags for logging purposes
|
||||
curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq
|
||||
exists=$(curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq --arg tag $TAG '.tags | contains([$tag])' )
|
||||
# check if there's a matching tag
|
||||
exists=$(curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq -r --arg tag "$TAG" 'any(.tags[]; . == $tag)' )
|
||||
if [[ $exists = "true" ]]; then
|
||||
echo "Version '$TAG' defined in Cargo.toml ALREADY EXISTS as tag in harbor repo"
|
||||
exit 1
|
||||
@@ -53,5 +55,5 @@ jobs:
|
||||
echo "Version '$TAG' doesn't exist on the remote"
|
||||
else
|
||||
echo "Unknown output '$exists'"
|
||||
exit 1
|
||||
exit 2
|
||||
fi
|
||||
|
||||
@@ -44,8 +44,10 @@ jobs:
|
||||
echo "Tag is empty"
|
||||
exit 1
|
||||
fi
|
||||
# first, list all tags for logging purposes
|
||||
curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq
|
||||
exists=$(curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq --arg tag $TAG '.tags | contains([$tag])' )
|
||||
# check if there's a matching tag
|
||||
exists=$(curl -su ${{ secrets.HARBOR_ROBOT_USERNAME }}:${{ secrets.HARBOR_ROBOT_SECRET }} "$registry/v2/$repo_name/tags/list" | jq -r --arg tag "$TAG" 'any(.tags[]; . == $tag)' )
|
||||
if [[ $exists = "true" ]]; then
|
||||
echo "Version '$TAG' defined in Cargo.toml ALREADY EXISTS as tag in harbor repo"
|
||||
exit 1
|
||||
@@ -53,5 +55,5 @@ jobs:
|
||||
echo "Version '$TAG' doesn't exist on the remote"
|
||||
else
|
||||
echo "Unknown output '$exists'"
|
||||
exit 1
|
||||
exit 2
|
||||
fi
|
||||
|
||||
Generated
+8
-8
@@ -4795,7 +4795,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "nym-api"
|
||||
version = "1.1.61"
|
||||
version = "1.1.60"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -5084,7 +5084,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-cli"
|
||||
version = "1.1.58"
|
||||
version = "1.1.57"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.22.1",
|
||||
@@ -5166,7 +5166,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-client"
|
||||
version = "1.1.58"
|
||||
version = "1.1.57"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"clap",
|
||||
@@ -6438,7 +6438,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-requester"
|
||||
version = "1.1.59"
|
||||
version = "1.1.58"
|
||||
dependencies = [
|
||||
"addr",
|
||||
"anyhow",
|
||||
@@ -6488,7 +6488,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-node"
|
||||
version = "1.14.0"
|
||||
version = "1.13.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
@@ -6649,7 +6649,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-node-status-api"
|
||||
version = "3.0.0"
|
||||
version = "3.1.0"
|
||||
dependencies = [
|
||||
"ammonia",
|
||||
"anyhow",
|
||||
@@ -7012,7 +7012,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.58"
|
||||
version = "1.1.57"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"clap",
|
||||
@@ -7968,7 +7968,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nymvisor"
|
||||
version = "0.1.23"
|
||||
version = "0.1.22"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.58"
|
||||
version = "1.1.57"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.58"
|
||||
version = "1.1.57"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
|
||||
@@ -124,7 +124,7 @@ impl NymApiTopologyProvider {
|
||||
// TODO: we really should be getting ACTIVE gateways only
|
||||
let gateways_fut = self
|
||||
.validator_client
|
||||
.get_all_basic_entry_assigned_nodes_with_metadata();
|
||||
.get_all_basic_entry_assigned_nodes_v2();
|
||||
|
||||
let (rewarded_set, mixnodes_res, gateways_res) =
|
||||
futures::try_join!(rewarded_set_fut, mixnodes_fut, gateways_fut)
|
||||
|
||||
@@ -107,10 +107,7 @@ pub async fn gateways_for_init<R: Rng>(
|
||||
|
||||
log::debug!("Fetching list of gateways from: {nym_api}");
|
||||
|
||||
let gateways = client
|
||||
.get_all_basic_entry_assigned_nodes_with_metadata()
|
||||
.await?
|
||||
.nodes;
|
||||
let gateways = client.get_all_basic_entry_assigned_nodes_v2().await?.nodes;
|
||||
info!("nym api reports {} gateways", gateways.len());
|
||||
|
||||
log::trace!("Gateways: {:#?}", gateways);
|
||||
|
||||
@@ -33,7 +33,6 @@ where
|
||||
self.backend.load_surb_storage().await
|
||||
}
|
||||
|
||||
// this will have to get enabled after merging develop
|
||||
pub async fn flush_on_shutdown(
|
||||
mut self,
|
||||
mem_state: CombinedReplyStorage,
|
||||
@@ -50,7 +49,6 @@ where
|
||||
shutdown.recv().await;
|
||||
|
||||
info!("PersistentReplyStorage is flushing all reply-related data to underlying storage");
|
||||
info!("you MUST NOT forcefully shutdown now or you risk data corruption!");
|
||||
if let Err(err) = self.backend.flush_surb_storage(&mem_state).await {
|
||||
error!("failed to flush our reply-related data to the persistent storage: {err}")
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,6 @@ pub struct Config {
|
||||
pub maximum_reconnection_backoff: Duration,
|
||||
pub initial_connection_timeout: Duration,
|
||||
pub maximum_connection_buffer_size: usize,
|
||||
pub use_legacy_packet_encoding: bool,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@@ -37,14 +36,12 @@ impl Config {
|
||||
maximum_reconnection_backoff: Duration,
|
||||
initial_connection_timeout: Duration,
|
||||
maximum_connection_buffer_size: usize,
|
||||
use_legacy_packet_encoding: bool,
|
||||
) -> Self {
|
||||
Config {
|
||||
initial_reconnection_backoff,
|
||||
maximum_reconnection_backoff,
|
||||
initial_connection_timeout,
|
||||
maximum_connection_buffer_size,
|
||||
use_legacy_packet_encoding,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -270,12 +267,7 @@ impl SendWithoutResponse for Client {
|
||||
fn send_without_response(&self, packet: MixPacket) -> io::Result<()> {
|
||||
let address = packet.next_hop_address();
|
||||
trace!("Sending packet to {address}");
|
||||
|
||||
// TODO: optimisation for the future: rather than constantly using legacy encoding,
|
||||
// once we're addressing by node_id (and thus have full node info here),
|
||||
// we could simply infer supported encoding based on their version
|
||||
let framed_packet =
|
||||
FramedNymPacket::from_mix_packet(packet, self.config.use_legacy_packet_encoding);
|
||||
let framed_packet = FramedNymPacket::from(packet);
|
||||
|
||||
let Some(sender) = self.active_connections.get_mut(&address) else {
|
||||
// there was never a connection to begin with
|
||||
@@ -336,7 +328,6 @@ mod tests {
|
||||
maximum_reconnection_backoff: Duration::from_millis(300_000),
|
||||
initial_connection_timeout: Duration::from_millis(1_500),
|
||||
maximum_connection_buffer_size: 128,
|
||||
use_legacy_packet_encoding: false,
|
||||
},
|
||||
NoiseConfig::new(
|
||||
Arc::new(x25519::KeyPair::new(&mut rng)),
|
||||
|
||||
@@ -471,12 +471,12 @@ impl NymApiClient {
|
||||
pub async fn get_all_basic_entry_assigned_nodes(
|
||||
&self,
|
||||
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
|
||||
self.get_all_basic_entry_assigned_nodes_with_metadata()
|
||||
self.get_all_basic_entry_assigned_nodes_v2()
|
||||
.await
|
||||
.map(|res| res.nodes)
|
||||
}
|
||||
|
||||
pub async fn get_all_basic_entry_assigned_nodes_with_metadata(
|
||||
pub async fn get_all_basic_entry_assigned_nodes_v2(
|
||||
&self,
|
||||
) -> Result<SkimmedNodesWithMetadata, ValidatorClientError> {
|
||||
collect_paged_skimmed_v2!(self, get_basic_entry_assigned_nodes_v2)
|
||||
|
||||
@@ -389,6 +389,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
routes::NYM_NODES_ROUTES,
|
||||
"skimmed",
|
||||
"entry-gateways",
|
||||
"all",
|
||||
],
|
||||
¶ms,
|
||||
)
|
||||
|
||||
@@ -54,8 +54,8 @@ impl PersistentStorage {
|
||||
/// * `database_path`: path to the database.
|
||||
pub async fn init<P: AsRef<Path>>(database_path: P) -> Result<Self, StorageError> {
|
||||
debug!(
|
||||
"Attempting to connect to database {:?}",
|
||||
database_path.as_ref().as_os_str()
|
||||
"Attempting to connect to database {}",
|
||||
database_path.as_ref().display()
|
||||
);
|
||||
|
||||
let opts = sqlx::sqlite::SqliteConnectOptions::new()
|
||||
|
||||
@@ -33,8 +33,8 @@ impl PersistentStatsStorage {
|
||||
/// * `database_path`: path to the database.
|
||||
pub async fn init<P: AsRef<Path> + Send>(database_path: P) -> Result<Self, StatsStorageError> {
|
||||
debug!(
|
||||
"Attempting to connect to database {:?}",
|
||||
database_path.as_ref().as_os_str()
|
||||
"Attempting to connect to database {}",
|
||||
database_path.as_ref().display()
|
||||
);
|
||||
|
||||
// TODO: we can inject here more stuff based on our gateway global config
|
||||
|
||||
@@ -82,8 +82,8 @@ impl GatewayStorage {
|
||||
message_retrieval_limit: i64,
|
||||
) -> Result<Self, GatewayStorageError> {
|
||||
debug!(
|
||||
"Attempting to connect to database {:?}",
|
||||
database_path.as_ref().as_os_str()
|
||||
"Attempting to connect to database {}",
|
||||
database_path.as_ref().display()
|
||||
);
|
||||
|
||||
// TODO: we can inject here more stuff based on our gateway global config
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#[cfg(feature = "network")]
|
||||
use crate::{DenomDetails, ValidatorDetails};
|
||||
use crate::{ApiUrlConst, DenomDetails, ValidatorDetails};
|
||||
|
||||
pub const NETWORK_NAME: &str = "mainnet";
|
||||
|
||||
@@ -29,10 +29,36 @@ pub const COCONUT_DKG_CONTRACT_ADDRESS: &str =
|
||||
pub const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy";
|
||||
|
||||
pub const NYXD_URL: &str = "https://rpc.nymtech.net";
|
||||
pub const NYM_API: &str = "https://validator.nymtech.net/api/";
|
||||
pub const NYXD_WS: &str = "wss://rpc.nymtech.net/websocket";
|
||||
pub const EXPLORER_API: &str = "https://explorer.nymtech.net/api/";
|
||||
pub const NYM_API: &str = "https://validator.nymtech.net/api/";
|
||||
#[cfg(feature = "network")]
|
||||
pub const NYM_APIS: &[ApiUrlConst] = &[
|
||||
ApiUrlConst {
|
||||
url: NYM_API,
|
||||
front_hosts: None,
|
||||
},
|
||||
ApiUrlConst {
|
||||
url: "https://nym-fronntdoor.vercel.app/api/",
|
||||
front_hosts: Some(&["vercel.app", "vercel.com"]),
|
||||
},
|
||||
ApiUrlConst {
|
||||
url: "https://nym-frontdoor.global.ssl.fastly.net/api/",
|
||||
front_hosts: Some(&["yelp.global.ssl.fastly.net"]),
|
||||
},
|
||||
];
|
||||
pub const NYM_VPN_API: &str = "https://nymvpn.com/api/";
|
||||
#[cfg(feature = "network")]
|
||||
pub const NYM_VPN_APIS: &[ApiUrlConst] = &[
|
||||
ApiUrlConst {
|
||||
url: NYM_VPN_API,
|
||||
front_hosts: Some(&["vercel.app", "vercel.com"]),
|
||||
},
|
||||
ApiUrlConst {
|
||||
url: "https://nymvpn-frontdoor.global.ssl.fastly.net/api/",
|
||||
front_hosts: Some(&["yelp.global.ssl.fastly.net"]),
|
||||
},
|
||||
];
|
||||
|
||||
// I'm making clippy mad on purpose, because that url HAS TO be updated and deployed before merging
|
||||
pub const EXIT_POLICY_URL: &str =
|
||||
|
||||
@@ -37,6 +37,37 @@ pub struct NymNetworkDetails {
|
||||
pub contracts: NymContracts,
|
||||
pub explorer_api: Option<String>,
|
||||
pub nym_vpn_api_url: Option<String>,
|
||||
pub nym_api_urls: Option<Vec<ApiUrl>>,
|
||||
pub nym_vpn_api_urls: Option<Vec<ApiUrl>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, JsonSchema)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
pub struct ApiUrl {
|
||||
/// Expects a string formatted Url
|
||||
///
|
||||
/// see https://docs.rs/url/latest/url/struct.Url.html
|
||||
pub url: String,
|
||||
/// Optional alternative equivalent hostnames. Each entry must parse as valid Host
|
||||
///
|
||||
/// see https://docs.rs/url/latest/url/enum.Host.html
|
||||
pub front_hosts: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
pub struct ApiUrlConst<'a> {
|
||||
pub url: &'a str,
|
||||
pub front_hosts: Option<&'a [&'a str]>,
|
||||
}
|
||||
|
||||
impl From<ApiUrlConst<'_>> for ApiUrl {
|
||||
fn from(value: ApiUrlConst) -> Self {
|
||||
ApiUrl {
|
||||
url: value.url.to_string(),
|
||||
front_hosts: value
|
||||
.front_hosts
|
||||
.map(|slice| slice.iter().map(|s| s.to_string()).collect()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// by default we assume the same defaults as mainnet, i.e. same prefixes and denoms
|
||||
@@ -67,6 +98,8 @@ impl NymNetworkDetails {
|
||||
contracts: Default::default(),
|
||||
explorer_api: Default::default(),
|
||||
nym_vpn_api_url: Default::default(),
|
||||
nym_api_urls: Default::default(),
|
||||
nym_vpn_api_urls: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +187,8 @@ impl NymNetworkDetails {
|
||||
},
|
||||
explorer_api: parse_optional_str(mainnet::EXPLORER_API),
|
||||
nym_vpn_api_url: parse_optional_str(mainnet::NYM_VPN_API),
|
||||
nym_api_urls: None,
|
||||
nym_vpn_api_urls: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -131,8 +131,7 @@ impl NoiseConfig {
|
||||
}
|
||||
|
||||
// Only for phased update
|
||||
//SW This can lead to some troubles if two nodes share the same IP and one support Noise but not the other.
|
||||
// This in only for the progressive update though and there is no workaround
|
||||
//SW This can lead to some troubles if two nodes shares the same IP and one support Noise but not the other. This in only for the progressive update though and there is no workaround
|
||||
pub(crate) fn get_noise_support(&self, ip_addr: IpAddr) -> Option<NoiseVersion> {
|
||||
let plain_ip_support = self.network.support.inner.load().get(&ip_addr).copied();
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@ use bytes::{BufMut, BytesMut};
|
||||
use nym_sphinx_forwarding::packet::MixPacket;
|
||||
use nym_sphinx_params::key_rotation::SphinxKeyRotation;
|
||||
use nym_sphinx_params::packet_sizes::PacketSize;
|
||||
use nym_sphinx_params::packet_version::{
|
||||
PacketVersion, CURRENT_PACKET_VERSION, LEGACY_PACKET_VERSION,
|
||||
};
|
||||
use nym_sphinx_params::packet_version::{PacketVersion, CURRENT_PACKET_VERSION};
|
||||
use nym_sphinx_params::PacketType;
|
||||
use nym_sphinx_types::NymPacket;
|
||||
|
||||
@@ -21,25 +19,26 @@ pub struct FramedNymPacket {
|
||||
pub(crate) packet: NymPacket,
|
||||
}
|
||||
|
||||
impl From<MixPacket> for FramedNymPacket {
|
||||
fn from(packet: MixPacket) -> Self {
|
||||
let typ = packet.packet_type();
|
||||
let rot = packet.key_rotation();
|
||||
FramedNymPacket::new(packet.into_packet(), typ, rot)
|
||||
}
|
||||
}
|
||||
|
||||
impl FramedNymPacket {
|
||||
pub fn new(
|
||||
packet: NymPacket,
|
||||
packet_type: PacketType,
|
||||
key_rotation: SphinxKeyRotation,
|
||||
use_legacy_packet_encoding: bool,
|
||||
) -> Self {
|
||||
// If this fails somebody is using the library in a super incorrect way, because they
|
||||
// already managed to somehow create a sphinx packet
|
||||
let packet_size = PacketSize::get_type(packet.len()).unwrap();
|
||||
|
||||
let packet_version = if use_legacy_packet_encoding {
|
||||
LEGACY_PACKET_VERSION
|
||||
} else {
|
||||
PacketVersion::new()
|
||||
};
|
||||
|
||||
let header = Header {
|
||||
packet_version,
|
||||
packet_version: PacketVersion::new(),
|
||||
packet_size,
|
||||
key_rotation,
|
||||
packet_type,
|
||||
@@ -48,12 +47,6 @@ impl FramedNymPacket {
|
||||
FramedNymPacket { header, packet }
|
||||
}
|
||||
|
||||
pub fn from_mix_packet(packet: MixPacket, use_legacy_packet_encoding: bool) -> Self {
|
||||
let typ = packet.packet_type();
|
||||
let rot = packet.key_rotation();
|
||||
FramedNymPacket::new(packet.into_packet(), typ, rot, use_legacy_packet_encoding)
|
||||
}
|
||||
|
||||
pub fn header(&self) -> Header {
|
||||
self.header
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use thiserror::Error;
|
||||
// - packet_version (starting with v1.1.0)
|
||||
// - packet_size indicator
|
||||
// - packet_type
|
||||
// - sphinx key rotation (starting with v1.13.0 - the Dolcelatte release)
|
||||
// - sphinx key rotation (starting with v1.12.0/v1.13.0 - either Cheddar or Dolcelatte release)
|
||||
|
||||
// it also just so happens that the only valid values for packet_size indicator include values 1-6
|
||||
// therefore if we receive byte `7` (or larger than that) we'll know we received a versioned packet,
|
||||
@@ -22,9 +22,6 @@ pub const CURRENT_PACKET_VERSION_NUMBER: u8 = KEY_ROTATION_VERSION_NUMBER;
|
||||
pub const CURRENT_PACKET_VERSION: PacketVersion =
|
||||
PacketVersion::unchecked(CURRENT_PACKET_VERSION_NUMBER);
|
||||
|
||||
pub const LEGACY_PACKET_VERSION: PacketVersion =
|
||||
PacketVersion::unchecked(INITIAL_PACKET_VERSION_NUMBER);
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct PacketVersion(u8);
|
||||
|
||||
|
||||
@@ -79,9 +79,7 @@ pub async fn current_network_topology_async(
|
||||
let metadata = mixnodes_res.metadata;
|
||||
let mixnodes = mixnodes_res.nodes;
|
||||
|
||||
let gateways_res = api_client
|
||||
.get_all_basic_entry_assigned_nodes_with_metadata()
|
||||
.await?;
|
||||
let gateways_res = api_client.get_all_basic_entry_assigned_nodes_v2().await?;
|
||||
if gateways_res.metadata != metadata {
|
||||
console_warn!("inconsistent nodes metadata between mixnodes and gateways calls! {metadata:?} and {:?}", gateways_res.metadata);
|
||||
return Err(WasmCoreError::UnavailableNetworkTopology);
|
||||
|
||||
@@ -1 +1 @@
|
||||
Friday, June 6th 2025, 09:33:10 UTC
|
||||
Thursday, June 12th 2025, 11:03:30 UTC
|
||||
|
||||
@@ -47,6 +47,53 @@ This page displays a full list of all the changes during our release cycle from
|
||||
|
||||
<VarInfo />
|
||||
|
||||
## `v2025.11-cheddar`
|
||||
|
||||
- [Release Binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2025.11-cheddar)
|
||||
- [`nym-node`](nodes/nym-node.mdx) version `1.13.0`
|
||||
|
||||
```sh
|
||||
nym-node
|
||||
Binary Name: nym-node
|
||||
Build Timestamp: 2025-06-10T09:41:31.291089877Z
|
||||
Build Version: 1.13.0
|
||||
Commit SHA: ef220882d4bcf0a8a703ea62f9273e017c9ebb51
|
||||
Commit Date: 2025-06-10T11:39:20.000000000+02:00
|
||||
Commit Branch: HEAD
|
||||
rustc Version: 1.86.0
|
||||
rustc Channel: stable
|
||||
cargo Profile: release
|
||||
```
|
||||
### Operators Updates & Tools
|
||||
|
||||
- **Nym Improvement Proposals**: NIPs are being introduced, allowing us to propose changes to the Nym network and ecosystem, and decentralise governance
|
||||
- **NIP1** will outline the governance process: Its draft will be published soon for discussion
|
||||
- **NIP2** will be about reducing the stake saturation point variable, which would make reward distribution across the network more equitable
|
||||
- **Join the Operator AMA next Tuesday** for an in-depth overview of what this all means (feat Nym Chief Scientist Claudia Diaz)
|
||||
- Keep an eye on our channels for information about how to participate in the upcoming voting (no need for forum registration, we are building something new!)
|
||||
|
||||
### Features
|
||||
|
||||
- [Track wireguard credential retries](https://github.com/nymtech/nym/pull/5783)
|
||||
|
||||
- [Swap a decode into a `fromrow` to please future `postgres` feature](https://github.com/nymtech/nym/pull/5785): This PR change a sqlx derive from `Decode` to `FromRow` because a future PR will bring the `postgres` feature and it doesn't like that `Decode` there
|
||||
|
||||
- [Fix contains ticketbook function that always returned true](https://github.com/nymtech/nym/pull/5787)
|
||||
|
||||
- [QoL: `RequestPath` trait for `http-api-client`](https://github.com/nymtech/nym/pull/5788): Those `PathSegments` in `ApiClient` weren't very user-friendly. Instead we've defined a `RequestPath` trait that allows you to also pass a good old `&str` or `String` and internally it does exactly the same sanitization as before. `PathSegments` are also fully supported to not break any existing compatibility.
|
||||
|
||||
- [Nym Statistics API](https://github.com/nymtech/nym/pull/5800):
|
||||
- Types for `nym-vpn-client`: It introduces `VpnClientStatsReport` which will be used by nym vpn clients to report statistics. Those types are in the monorepo because they're used by the `num-statistics-API`
|
||||
- Nym Statistics API: Basically a `REST API` with a `postgres` backend. In this first iteration, it only accepts `VpnClientStatsReport` and stores them in its database. It optionally connects to the Nym API to confirm reports are coming from the network and attach country code to them if it's the case (exit node country code).
|
||||
|
||||
- [Resolve 1.87 clippy warnings](https://github.com/nymtech/nym/pull/5802)
|
||||
|
||||
- [Adjusted wallet storybook mocks to fix the build](https://github.com/nymtech/nym/pull/5804)
|
||||
|
||||
- [Set cached storage counters to 0](https://github.com/nymtech/nym/pull/5812)
|
||||
|
||||
- [No autoremoval of peers](https://github.com/nymtech/nym/pull/5831)
|
||||
|
||||
## `v2025.10-brie`
|
||||
|
||||
- [Release Binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2025.10-brie)
|
||||
|
||||
@@ -18,12 +18,12 @@ This documentation page provides a guide on how to set up and run a [NYM NODE](.
|
||||
## Current version
|
||||
|
||||
```sh
|
||||
nym-node
|
||||
ym-node
|
||||
Binary Name: nym-node
|
||||
Build Timestamp: 2025-05-27T10:13:18.511075453Z
|
||||
Build Version: 1.12.0
|
||||
Commit SHA: 1c6db86259d08d80e8bcfbc4fcc71ccb147fcfd0
|
||||
Commit Date: 2025-05-27T12:11:13.000000000+02:00
|
||||
Build Timestamp: 2025-06-10T09:41:31.291089877Z
|
||||
Build Version: 1.13.0
|
||||
Commit SHA: ef220882d4bcf0a8a703ea62f9273e017c9ebb51
|
||||
Commit Date: 2025-06-10T11:39:20.000000000+02:00
|
||||
Commit Branch: HEAD
|
||||
rustc Version: 1.86.0
|
||||
rustc Channel: stable
|
||||
|
||||
@@ -419,13 +419,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
return Ok(INITIAL_PROTOCOL_VERSION);
|
||||
};
|
||||
|
||||
// #####
|
||||
// On backwards compat:
|
||||
// Currently it is the case that gateways will understand all previous protocol versions
|
||||
// and will downgrade accordingly, but this will now always be the case.
|
||||
// For example, once we remove downgrade on legacy auth, anything below version 4 will be rejected
|
||||
// #####
|
||||
|
||||
// a v2 gateway will understand v1 requests, but v1 client will not understand v2 responses
|
||||
if client_protocol_version == 1 {
|
||||
return Ok(1);
|
||||
@@ -441,11 +434,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
return Ok(3);
|
||||
}
|
||||
|
||||
// a v5 gateway will understand v4 requests (key-rotation)
|
||||
if client_protocol_version == 4 {
|
||||
return Ok(4);
|
||||
}
|
||||
|
||||
// we can't handle clients with higher protocol than ours
|
||||
// (perhaps we could try to negotiate downgrade on our end? sounds like a nice future improvement)
|
||||
if client_protocol_version <= CURRENT_PROTOCOL_VERSION {
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
[package]
|
||||
name = "nym-api"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.61"
|
||||
version = "1.1.60"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
rust-version.workspace = true
|
||||
|
||||
@@ -90,8 +90,8 @@ impl KeyRotationController {
|
||||
async fn handle_contract_cache_update(&mut self) {
|
||||
let updated = self.get_contract_data().await;
|
||||
|
||||
debug!(
|
||||
"current key rotation: {}",
|
||||
info!(
|
||||
"current rotation: {}",
|
||||
updated
|
||||
.key_rotation_state
|
||||
.key_rotation_id(updated.interval.current_epoch_absolute_id())
|
||||
|
||||
@@ -101,7 +101,7 @@ pub(crate) async fn mixnodes_basic_active(
|
||||
tag = "Unstable Nym Nodes",
|
||||
get,
|
||||
params(NodesParams),
|
||||
path = "/entry-gateways",
|
||||
path = "/entry-gateways/all",
|
||||
context_path = "/v2/unstable/nym-nodes/skimmed",
|
||||
responses(
|
||||
(status = 200, content(
|
||||
@@ -124,7 +124,7 @@ pub(crate) async fn entry_gateways_basic_all(
|
||||
tag = "Unstable Nym Nodes",
|
||||
get,
|
||||
params(NodesParams),
|
||||
path = "/exit-gateways",
|
||||
path = "/exit-gateways/all",
|
||||
context_path = "/v2/unstable/nym-nodes/skimmed",
|
||||
responses(
|
||||
(status = 200, content(
|
||||
|
||||
@@ -21,7 +21,7 @@ export NODE_STATUS_AGENT_SERVER_ADDRESS="http://127.0.0.1"
|
||||
export NODE_STATUS_AGENT_SERVER_PORT="8000"
|
||||
export NODE_STATUS_AGENT_PROBE_PATH="$crate_root/nym-gateway-probe"
|
||||
export NODE_STATUS_AGENT_AUTH_KEY="BjyC9SsHAZUzPRkQR4sPTvVrp4GgaquTh5YfSJksvvWT"
|
||||
export NODE_STATUS_AGENT_PROBE_EXTRA_ARGS="netstack-download-timeout-sec=30,netstack-num-ping=2,netstack-send-timeout-sec=1,netstack-recv-timeout-sec=1,mnemonic=${{ secrets.CANARY_PROBE_MNEMONIC }}"
|
||||
export NODE_STATUS_AGENT_PROBE_EXTRA_ARGS="netstack-download-timeout-sec=30,netstack-num-ping=2,netstack-send-timeout-sec=1,netstack-recv-timeout-sec=1"
|
||||
|
||||
workers=${1:-1}
|
||||
echo "Running $workers workers in parallel"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-node-status-api"
|
||||
version = "3.0.0"
|
||||
version = "3.1.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
@@ -28,7 +28,7 @@ moka = { workspace = true, features = ["future"] }
|
||||
# Nym API: revert after Cheddar is out
|
||||
nym-contracts-common = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" }
|
||||
nym-mixnet-contract-common = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" }
|
||||
nym-bin-common = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" }
|
||||
nym-bin-common = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar", features = ["openapi"]}
|
||||
nym-node-status-client = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" }
|
||||
nym-crypto = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" }
|
||||
nym-http-api-client = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" }
|
||||
|
||||
@@ -14,6 +14,7 @@ pub(crate) mod metrics;
|
||||
pub(crate) mod mixnodes;
|
||||
pub(crate) mod nym_nodes;
|
||||
pub(crate) mod services;
|
||||
pub(crate) mod status;
|
||||
pub(crate) mod summary;
|
||||
pub(crate) mod testruns;
|
||||
|
||||
@@ -39,7 +40,8 @@ impl RouterBuilder {
|
||||
.nest("/mixnodes", mixnodes::routes())
|
||||
.nest("/services", services::routes())
|
||||
.nest("/summary", summary::routes())
|
||||
.nest("/metrics", metrics::routes()),
|
||||
.nest("/metrics", metrics::routes())
|
||||
.nest("/status", status::routes()),
|
||||
)
|
||||
.nest(
|
||||
"/explorer/v3",
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
use axum::{extract::State, Json, Router};
|
||||
use nym_validator_client::models::BinaryBuildInformationOwned;
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::http::{
|
||||
error::HttpResult,
|
||||
state::{AppState, HealthInfo},
|
||||
};
|
||||
|
||||
pub(crate) fn routes() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/build_information", axum::routing::get(build_information))
|
||||
.route("/health", axum::routing::get(health))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
tag = "Status",
|
||||
get,
|
||||
path = "/build_information",
|
||||
context_path = "/v2/status",
|
||||
responses(
|
||||
(status = 200, body = BinaryBuildInformationOwned)
|
||||
)
|
||||
)]
|
||||
#[instrument(level = tracing::Level::INFO, skip_all)]
|
||||
async fn build_information(
|
||||
State(state): State<AppState>,
|
||||
) -> HttpResult<Json<BinaryBuildInformationOwned>> {
|
||||
let build_info = state.build_information().to_owned();
|
||||
|
||||
Ok(Json(build_info))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
tag = "Status",
|
||||
get,
|
||||
path = "/health",
|
||||
context_path = "/v2/status",
|
||||
responses(
|
||||
(status = 200, body = HealthInfo)
|
||||
)
|
||||
)]
|
||||
#[instrument(level = tracing::Level::INFO, skip_all)]
|
||||
async fn health(State(state): State<AppState>) -> HttpResult<Json<HealthInfo>> {
|
||||
Ok(Json(state.health()))
|
||||
}
|
||||
@@ -1,15 +1,20 @@
|
||||
use cosmwasm_std::Decimal;
|
||||
use itertools::Itertools;
|
||||
use moka::{future::Cache, Entry};
|
||||
use nym_bin_common::bin_info_owned;
|
||||
use nym_contracts_common::NaiveFloat;
|
||||
use nym_crypto::asymmetric::ed25519::PublicKey;
|
||||
use nym_mixnet_contract_common::NodeId;
|
||||
use nym_validator_client::nym_api::SkimmedNode;
|
||||
use semver::Version;
|
||||
use serde::Serialize;
|
||||
use std::{collections::HashMap, sync::Arc, time::Duration};
|
||||
use time::UtcDateTime;
|
||||
use tokio::sync::RwLock;
|
||||
use tracing::{error, instrument, warn};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use super::models::SessionStats;
|
||||
use crate::{
|
||||
db::{queries, DbPool},
|
||||
http::models::{
|
||||
@@ -18,7 +23,7 @@ use crate::{
|
||||
monitor::{DelegationsCache, NodeGeoCache},
|
||||
};
|
||||
|
||||
use super::models::SessionStats;
|
||||
pub(crate) use nym_validator_client::models::BinaryBuildInformationOwned;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct AppState {
|
||||
@@ -28,6 +33,7 @@ pub(crate) struct AppState {
|
||||
agent_max_count: i64,
|
||||
node_geocache: NodeGeoCache,
|
||||
node_delegations: Arc<RwLock<DelegationsCache>>,
|
||||
bin_info: BinaryInfo,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
@@ -46,6 +52,7 @@ impl AppState {
|
||||
agent_max_count,
|
||||
node_geocache,
|
||||
node_delegations,
|
||||
bin_info: BinaryInfo::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +85,15 @@ impl AppState {
|
||||
.await
|
||||
.delegations_owned(node_id)
|
||||
}
|
||||
|
||||
pub(crate) fn health(&self) -> HealthInfo {
|
||||
let uptime = (UtcDateTime::now() - self.bin_info.startup_time).whole_seconds();
|
||||
HealthInfo { uptime }
|
||||
}
|
||||
|
||||
pub(crate) fn build_information(&self) -> &BinaryBuildInformationOwned {
|
||||
&self.bin_info.build_info
|
||||
}
|
||||
}
|
||||
|
||||
static GATEWAYS_LIST_KEY: &str = "gateways";
|
||||
@@ -631,3 +647,23 @@ async fn aggregate_node_info_from_db(
|
||||
|
||||
Ok(parsed_nym_nodes)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct BinaryInfo {
|
||||
startup_time: UtcDateTime,
|
||||
build_info: BinaryBuildInformationOwned,
|
||||
}
|
||||
|
||||
impl BinaryInfo {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
startup_time: UtcDateTime::now(),
|
||||
build_info: bin_info_owned!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub(crate) struct HealthInfo {
|
||||
uptime: i64,
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-node"
|
||||
version = "1.14.0"
|
||||
version = "1.13.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
@@ -580,13 +580,6 @@ pub struct MixnetDebug {
|
||||
/// Maximum number of packets that can be stored waiting to get sent to a particular connection.
|
||||
pub maximum_connection_buffer_size: usize,
|
||||
|
||||
/// Specify whether any framed packets between nodes should use the legacy format (v7)
|
||||
/// as opposed to the current (v8) one.
|
||||
/// The legacy format has to be used until sufficient number of nodes on the network has upgraded and understand the new variant.
|
||||
/// This will allow for optimisations to indicate which [sphinx] key is meant to be used when
|
||||
/// processing received packets.
|
||||
pub use_legacy_packet_encoding: bool,
|
||||
|
||||
/// Specifies whether this node should **NOT** use noise protocol in the connections (currently not implemented)
|
||||
pub unsafe_disable_noise: bool,
|
||||
}
|
||||
@@ -772,8 +765,6 @@ impl Default for MixnetDebug {
|
||||
packet_forwarding_maximum_backoff: Self::DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF,
|
||||
initial_connection_timeout: Self::DEFAULT_INITIAL_CONNECTION_TIMEOUT,
|
||||
maximum_connection_buffer_size: Self::DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE,
|
||||
// TODO: update this in few releases...
|
||||
use_legacy_packet_encoding: true,
|
||||
unsafe_disable_noise: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1417,7 +1417,6 @@ pub async fn try_upgrade_config_v9<P: AsRef<Path>>(
|
||||
initial_connection_timeout: old_cfg.mixnet.debug.initial_connection_timeout,
|
||||
maximum_connection_buffer_size: old_cfg.mixnet.debug.maximum_connection_buffer_size,
|
||||
unsafe_disable_noise: old_cfg.mixnet.debug.unsafe_disable_noise,
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
storage_paths: NymNodePaths {
|
||||
|
||||
@@ -1057,7 +1057,6 @@ impl NymNode {
|
||||
self.config.mixnet.debug.packet_forwarding_maximum_backoff,
|
||||
self.config.mixnet.debug.initial_connection_timeout,
|
||||
self.config.mixnet.debug.maximum_connection_buffer_size,
|
||||
self.config.mixnet.debug.use_legacy_packet_encoding,
|
||||
);
|
||||
let mixnet_client = nym_mixnet_client::Client::new(
|
||||
mixnet_client_config,
|
||||
|
||||
@@ -270,7 +270,6 @@ impl ThroughputTestingClient {
|
||||
forward_packet,
|
||||
Default::default(),
|
||||
self.key_rotation,
|
||||
false,
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
@@ -55,5 +55,7 @@ pub(crate) fn network_details() -> nym_network_defaults::NymNetworkDetails {
|
||||
},
|
||||
explorer_api: parse_optional_str(EXPLORER_API),
|
||||
nym_vpn_api_url: None,
|
||||
nym_vpn_api_urls: None,
|
||||
nym_api_urls: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { LoadingModal } from 'src/components/Modals/LoadingModal';
|
||||
import { Results } from 'src/components/TestNode/Results';
|
||||
import { ErrorModal } from 'src/components/Modals/ErrorModal';
|
||||
import { PrintResults } from 'src/components/TestNode/PrintResults';
|
||||
import { MAINNET_VALIDATOR_URL } from 'src/constants';
|
||||
import { MAINNET_VALIDATOR_URL, QA_VALIDATOR_URL } from 'src/constants';
|
||||
import { TestStatus } from 'src/components/TestNode/types';
|
||||
import { isMixnode } from 'src/types';
|
||||
|
||||
@@ -63,7 +63,7 @@ export const NodeTestPage = () => {
|
||||
const loadNodeTestClient = useCallback(async () => {
|
||||
try {
|
||||
const nodeTesterId = new Date().toISOString(); // make a new tester id for each session
|
||||
const validator = network === 'MAINNET' ? MAINNET_VALIDATOR_URL : 'https://rpc.nymtech.net/api/';
|
||||
const validator = network === 'MAINNET' ? MAINNET_VALIDATOR_URL : QA_VALIDATOR_URL;
|
||||
const client = await createNodeTesterClient();
|
||||
await client.tester.init(validator, nodeTesterId);
|
||||
setNodeTestClient(client);
|
||||
|
||||
@@ -48,7 +48,7 @@ impl MyTopologyProvider {
|
||||
|
||||
let gateways = self
|
||||
.validator_client
|
||||
.get_all_basic_entry_assigned_nodes_with_metadata()
|
||||
.get_all_basic_entry_assigned_nodes_v2()
|
||||
.await
|
||||
.unwrap()
|
||||
.nodes;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[package]
|
||||
name = "nym-network-requester"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.59"
|
||||
version = "1.1.58"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version = "1.70"
|
||||
|
||||
@@ -443,7 +443,7 @@ impl NetworkManager {
|
||||
));
|
||||
let id = ctx.nym_node_id(mixnode);
|
||||
cmds.push(format!(
|
||||
"{bin_canon_display} -c {env_canon_display} run --id {id} --local --unsafe-disable-noise"
|
||||
"{bin_canon_display} -c {env_canon_display} run --id {id} --local"
|
||||
));
|
||||
}
|
||||
|
||||
@@ -454,7 +454,7 @@ impl NetworkManager {
|
||||
));
|
||||
let id = ctx.nym_node_id(gateway);
|
||||
cmds.push(format!(
|
||||
"{bin_canon_display} -c {env_canon_display} run --id {id} --local --unsafe-disable-noise"
|
||||
"{bin_canon_display} -c {env_canon_display} run --id {id} --local"
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,8 @@ impl<'a> From<&'a LoadedNetwork> for nym_config::defaults::NymNetworkDetails {
|
||||
contracts,
|
||||
explorer_api: None,
|
||||
nym_vpn_api_url: None,
|
||||
nym_vpn_api_urls: None,
|
||||
nym_api_urls: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ impl InitCtx {
|
||||
contracts: Default::default(),
|
||||
explorer_api: None,
|
||||
nym_vpn_api_url: None,
|
||||
nym_vpn_api_urls: None,
|
||||
nym_api_urls: None,
|
||||
};
|
||||
Ok(Config::try_from_nym_network_details(&network_details)?)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-cli"
|
||||
version = "1.1.58"
|
||||
version = "1.1.57"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nymvisor"
|
||||
version = "0.1.23"
|
||||
version = "0.1.22"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
Reference in New Issue
Block a user