Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 45eaad6e1b | |||
| d81c053eb7 | |||
| dc97e84c54 | |||
| 8634fc2bed | |||
| c4a8c7d664 | |||
| d2712749da | |||
| 983521f1db |
@@ -54,7 +54,7 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --lib --manifest-path contracts/Cargo.toml --all-features
|
||||
args: --lib --manifest-path contracts/Cargo.toml
|
||||
|
||||
- name: Check formatting
|
||||
uses: actions-rs/cargo@v1
|
||||
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: arc-linux-latest
|
||||
runs-on: arc-ubuntu-22.04
|
||||
env:
|
||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
||||
defaults:
|
||||
|
||||
@@ -4,50 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2025.18-jarlsberg] (2025-10-14)
|
||||
|
||||
- ns-api: add descriptions to dVPN gateway responses ([#6102])
|
||||
- NS API: use new probe download filesize and milliseconds field ([#6097])
|
||||
- ns-api: use download files size from probes instead of parsing filenames ([#6095])
|
||||
- ns-api: add new fields for probe output for query_metadata and download file size and duration in ms ([#6091])
|
||||
- Bugfix/bloomfilters purge ([#6089])
|
||||
- Hotfix: Update API source in node ping tester script ([#6082])
|
||||
- Get wireguard keypair as arg instead of reading it from disk ([#6078])
|
||||
- Feature: Ping probe all nodes /described nodes from a server ([#6074])
|
||||
- Node Status API: add bridge information to dVPN endpoint ([#6069])
|
||||
- frontdoor typo fix ([#6067])
|
||||
- Feature: Node rewards tracker ([#6064])
|
||||
- [chore] Clippy fix ([#6060])
|
||||
- Registration Client ([#6059])
|
||||
- Bugfix: Nym node CLI download nym-node exception ([#6058])
|
||||
- Feature: Nym node html landing page ([#6053])
|
||||
- feat: DKG contract method for updating announce address ([#6050])
|
||||
- feat: NS ticket faucet ([#6047])
|
||||
- Bridge proto client params in Self-Described ([#6035])
|
||||
- Node Status API: remove sqlite support ([#6004])
|
||||
- Benny/ci contract fix ([#5962])
|
||||
|
||||
[#6102]: https://github.com/nymtech/nym/pull/6102
|
||||
[#6097]: https://github.com/nymtech/nym/pull/6097
|
||||
[#6095]: https://github.com/nymtech/nym/pull/6095
|
||||
[#6091]: https://github.com/nymtech/nym/pull/6091
|
||||
[#6089]: https://github.com/nymtech/nym/pull/6089
|
||||
[#6082]: https://github.com/nymtech/nym/pull/6082
|
||||
[#6078]: https://github.com/nymtech/nym/pull/6078
|
||||
[#6074]: https://github.com/nymtech/nym/pull/6074
|
||||
[#6069]: https://github.com/nymtech/nym/pull/6069
|
||||
[#6067]: https://github.com/nymtech/nym/pull/6067
|
||||
[#6064]: https://github.com/nymtech/nym/pull/6064
|
||||
[#6060]: https://github.com/nymtech/nym/pull/6060
|
||||
[#6059]: https://github.com/nymtech/nym/pull/6059
|
||||
[#6058]: https://github.com/nymtech/nym/pull/6058
|
||||
[#6053]: https://github.com/nymtech/nym/pull/6053
|
||||
[#6050]: https://github.com/nymtech/nym/pull/6050
|
||||
[#6047]: https://github.com/nymtech/nym/pull/6047
|
||||
[#6035]: https://github.com/nymtech/nym/pull/6035
|
||||
[#6004]: https://github.com/nymtech/nym/pull/6004
|
||||
[#5962]: https://github.com/nymtech/nym/pull/5962
|
||||
|
||||
## [2025.17-isabirra] (2025-09-29)
|
||||
|
||||
- Bugfix | Fix the registration handshake ([#6062])
|
||||
|
||||
Generated
+720
-507
File diff suppressed because it is too large
Load Diff
+4
-9
@@ -248,7 +248,7 @@ dashmap = "5.5.3"
|
||||
# We want https://github.com/DefGuard/wireguard-rs/pull/64 , but there's no crates.io release being pushed out anymore
|
||||
defguard_wireguard_rs = { git = "https://github.com/DefGuard/wireguard-rs.git", rev = "v0.4.7" }
|
||||
digest = "0.10.7"
|
||||
dirs = "6.0"
|
||||
dirs = "5.0"
|
||||
doc-comment = "0.3"
|
||||
dotenvy = "0.15.6"
|
||||
dyn-clone = "1.0.19"
|
||||
@@ -300,11 +300,8 @@ nix = "0.27.1"
|
||||
notify = "5.1.0"
|
||||
okapi = "0.7.0"
|
||||
once_cell = "1.21.3"
|
||||
opentelemetry = "0.30.0"
|
||||
opentelemetry-otlp = "0.30.0"
|
||||
opentelemetry-semantic-conventions = "0.30.0"
|
||||
opentelemetry_sdk = "0.30.0"
|
||||
opentelemetry-stdout = "0.30.0"
|
||||
opentelemetry = "0.19.0"
|
||||
opentelemetry-jaeger = "0.18.0"
|
||||
parking_lot = "0.12.3"
|
||||
pem = "0.8"
|
||||
petgraph = "0.6.5"
|
||||
@@ -363,10 +360,8 @@ toml = "0.8.22"
|
||||
tower = "0.5.2"
|
||||
tower-http = "0.5.2"
|
||||
tracing = "0.1.41"
|
||||
tracing-core = "0.1.33"
|
||||
tracing-log = "0.2"
|
||||
tracing-opentelemetry = "0.31.0"
|
||||
tracing-serde = "0.2.0"
|
||||
tracing-opentelemetry = "0.19.0"
|
||||
tracing-subscriber = "0.3.19"
|
||||
tracing-tree = "0.2.2"
|
||||
tracing-indicatif = "0.3.9"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.64"
|
||||
version = "1.1.63"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
@@ -46,6 +46,7 @@ nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = [
|
||||
"output_format",
|
||||
"clap",
|
||||
"basic_tracing",
|
||||
] }
|
||||
nym-client-core = { path = "../../common/client-core", features = [
|
||||
"fs-credentials-storage",
|
||||
@@ -70,11 +71,3 @@ nym-client-websocket-requests = { path = "websocket-requests" }
|
||||
nym-id = { path = "../../common/nym-id" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
otel = [
|
||||
"nym-client-core/otel",
|
||||
"nym-bin-common/otel",
|
||||
"nym-gateway-requests/otel",
|
||||
]
|
||||
@@ -60,7 +60,6 @@ impl SocketClient {
|
||||
let ClientInput {
|
||||
connection_command_sender,
|
||||
input_sender,
|
||||
..
|
||||
} = client_input;
|
||||
|
||||
let ClientOutput {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use std::error::Error;
|
||||
|
||||
use clap::{crate_name, crate_version, Parser};
|
||||
use nym_bin_common::logging::{maybe_print_banner, setup_no_otel_logger};
|
||||
use nym_bin_common::logging::{maybe_print_banner, setup_tracing_logger};
|
||||
use nym_network_defaults::setup_env;
|
||||
|
||||
pub mod client;
|
||||
@@ -20,7 +20,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
if !args.no_banner {
|
||||
maybe_print_banner(crate_name!(), crate_version!());
|
||||
}
|
||||
setup_no_otel_logger().expect("failed to initialize logging");
|
||||
setup_tracing_logger();
|
||||
|
||||
if let Err(err) = commands::execute(args).await {
|
||||
log::error!("{err}");
|
||||
|
||||
@@ -184,14 +184,7 @@ impl Handler {
|
||||
});
|
||||
|
||||
// the ack control is now responsible for chunking, etc.
|
||||
let input_msg = InputMessage::new_regular(
|
||||
recipient,
|
||||
message,
|
||||
lane,
|
||||
self.packet_type,
|
||||
#[cfg(feature = "otel")]
|
||||
None,
|
||||
);
|
||||
let input_msg = InputMessage::new_regular(recipient, message, lane, self.packet_type);
|
||||
if let Err(err) = self.msg_input.send(input_msg).await {
|
||||
if !self.shutdown_token.is_cancelled() {
|
||||
error!("Failed to send message to the input buffer: {err}");
|
||||
@@ -223,15 +216,8 @@ impl Handler {
|
||||
TransmissionLane::ConnectionId(id)
|
||||
});
|
||||
|
||||
let input_msg = InputMessage::new_anonymous(
|
||||
recipient,
|
||||
message,
|
||||
reply_surbs,
|
||||
lane,
|
||||
self.packet_type,
|
||||
#[cfg(feature = "otel")]
|
||||
None,
|
||||
);
|
||||
let input_msg =
|
||||
InputMessage::new_anonymous(recipient, message, reply_surbs, lane, self.packet_type);
|
||||
if let Err(err) = self.msg_input.send(input_msg).await {
|
||||
if !self.shutdown_token.is_cancelled() {
|
||||
error!("Failed to send anonymous message to the input buffer: {err}");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.64"
|
||||
version = "1.1.63"
|
||||
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"
|
||||
@@ -27,6 +27,7 @@ zeroize = { workspace = true }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = [
|
||||
"output_format",
|
||||
"clap",
|
||||
"basic_tracing",
|
||||
] }
|
||||
nym-client-core = { path = "../../common/client-core", features = [
|
||||
"fs-credentials-storage",
|
||||
@@ -53,7 +54,3 @@ nym-validator-client = { path = "../../common/client-libs/validator-client", fea
|
||||
[features]
|
||||
default = []
|
||||
eth = []
|
||||
otel = [
|
||||
"nym-socks5-client-core/otel",
|
||||
"nym-bin-common/otel",
|
||||
]
|
||||
@@ -4,7 +4,7 @@
|
||||
use std::error::Error;
|
||||
|
||||
use clap::{crate_name, crate_version, Parser};
|
||||
use nym_bin_common::logging::{maybe_print_banner, setup_no_otel_logger};
|
||||
use nym_bin_common::logging::{maybe_print_banner, setup_tracing_logger};
|
||||
use nym_network_defaults::setup_env;
|
||||
|
||||
mod commands;
|
||||
@@ -19,7 +19,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
if !args.no_banner {
|
||||
maybe_print_banner(crate_name!(), crate_version!());
|
||||
}
|
||||
setup_no_otel_logger().expect("failed to initialize logging");
|
||||
setup_tracing_logger();
|
||||
|
||||
if let Err(err) = commands::execute(args).await {
|
||||
log::error!("{err}");
|
||||
|
||||
@@ -8,30 +8,24 @@ license = { workspace = true }
|
||||
repository = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
chrono = { workspace = true, optional = true }
|
||||
cfg-if = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive"], optional = true }
|
||||
clap_complete = { workspace = true, optional = true }
|
||||
clap_complete_fig = { workspace = true, optional = true }
|
||||
const-str = { workspace = true }
|
||||
opentelemetry = { workspace = true, optional = true }
|
||||
opentelemetry-otlp = { workspace = true,features=["metrics", "grpc-tonic", "tls",
|
||||
"tls-webpki-roots"], optional = true }
|
||||
opentelemetry-semantic-conventions = { workspace = true, features = ["semconv_experimental"], optional = true }
|
||||
opentelemetry-stdout = { workspace = true, features = ["trace", "metrics"], optional = true }
|
||||
opentelemetry_sdk = { workspace = true, optional = true }
|
||||
rand = { workspace = true, optional = true }
|
||||
log = { workspace = true }
|
||||
schemars = { workspace = true, features = ["preserve_order"], optional = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true, optional = true }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
tracing-core = { workspace = true }
|
||||
|
||||
## tracing
|
||||
tracing-subscriber = { workspace = true, features = ["env-filter"], optional = true }
|
||||
tracing-tree = { workspace = true, optional = true }
|
||||
tracing = { workspace = true, optional = true }
|
||||
opentelemetry-jaeger = { workspace = true, features = ["rt-tokio", "collector_client", "isahc_collector_client"], optional = true }
|
||||
tracing-opentelemetry = { workspace = true, optional = true }
|
||||
tracing-serde = { workspace = true }
|
||||
tracing-subscriber = { workspace = true, features = ["env-filter", "json"] }
|
||||
tracing-tree = { workspace = true }
|
||||
utoipa = { workspace = true, optional = true }
|
||||
opentelemetry = { workspace = true, features = ["rt-tokio"], optional = true }
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
vergen = { workspace = true, features = ["build", "git", "gitcl", "rustc", "cargo"] }
|
||||
@@ -41,17 +35,13 @@ default = []
|
||||
openapi = ["utoipa"]
|
||||
output_format = ["serde_json", "dep:clap"]
|
||||
bin_info_schema = ["schemars"]
|
||||
tokio-console = ["otel"]
|
||||
otel = [
|
||||
"chrono",
|
||||
basic_tracing = ["dep:tracing", "tracing-subscriber"]
|
||||
tracing = [
|
||||
"basic_tracing",
|
||||
"tracing-tree",
|
||||
"opentelemetry-jaeger",
|
||||
"tracing-opentelemetry",
|
||||
"opentelemetry",
|
||||
"opentelemetry-otlp",
|
||||
"opentelemetry-semantic-conventions",
|
||||
"opentelemetry-stdout",
|
||||
"opentelemetry_sdk",
|
||||
"serde_json",
|
||||
"rand",
|
||||
]
|
||||
clap = ["dep:clap", "dep:clap_complete", "dep:clap_complete_fig"]
|
||||
models = []
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
pub mod build_information;
|
||||
pub mod logging;
|
||||
|
||||
#[cfg(feature = "otel")]
|
||||
pub mod opentelemetry;
|
||||
|
||||
#[cfg(feature = "clap")]
|
||||
pub mod completions;
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#[cfg(feature = "otel")]
|
||||
use opentelemetry_otlp::ExporterBuildError;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum TracingError {
|
||||
#[error("tracing logger already initialised")]
|
||||
TracingLoggerAlreadyInitialised,
|
||||
|
||||
#[error("Logging error: {0}")]
|
||||
TracingTryInitError(tracing_subscriber::util::TryInitError),
|
||||
|
||||
#[cfg(feature = "otel")]
|
||||
#[error("{0}")]
|
||||
TracingExporterBuildError(#[from] ExporterBuildError),
|
||||
|
||||
#[error("{0}")]
|
||||
TracingFilterParseError(#[from] tracing_subscriber::filter::ParseError),
|
||||
}
|
||||
@@ -1,12 +1,19 @@
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod error;
|
||||
|
||||
use error::TracingError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::IsTerminal;
|
||||
use tracing_subscriber::{filter::Directive, layer::SubscriberExt, util::SubscriberInitExt};
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use opentelemetry;
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use opentelemetry_jaeger;
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use tracing_opentelemetry;
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use tracing_subscriber;
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use tracing_tree;
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
@@ -15,6 +22,7 @@ pub struct LoggingSettings {
|
||||
}
|
||||
|
||||
// don't call init so that we could attach additional layers
|
||||
#[cfg(feature = "basic_tracing")]
|
||||
pub fn build_tracing_logger() -> impl tracing_subscriber::layer::SubscriberExt {
|
||||
use tracing_subscriber::prelude::*;
|
||||
|
||||
@@ -23,6 +31,7 @@ pub fn build_tracing_logger() -> impl tracing_subscriber::layer::SubscriberExt {
|
||||
.with(default_tracing_env_filter())
|
||||
}
|
||||
|
||||
#[cfg(feature = "basic_tracing")]
|
||||
pub fn default_tracing_env_filter() -> tracing_subscriber::filter::EnvFilter {
|
||||
if ::std::env::var("RUST_LOG").is_ok() {
|
||||
tracing_subscriber::filter::EnvFilter::from_default_env()
|
||||
@@ -34,6 +43,7 @@ pub fn default_tracing_env_filter() -> tracing_subscriber::filter::EnvFilter {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "basic_tracing")]
|
||||
pub fn default_tracing_fmt_layer<S, W>(
|
||||
writer: W,
|
||||
) -> impl tracing_subscriber::Layer<S> + Sync + Send + 'static
|
||||
@@ -53,47 +63,45 @@ where
|
||||
.with_target(false)
|
||||
}
|
||||
|
||||
/// Creates a tracing filter that sets more granular log levels for specific crates.
|
||||
/// This allows for finer control over logging verbosity.
|
||||
pub(crate) fn granual_filtered_env() -> Result<tracing_subscriber::filter::EnvFilter, TracingError>
|
||||
{
|
||||
fn directive_checked(directive: impl Into<String>) -> Result<Directive, TracingError> {
|
||||
directive.into().parse().map_err(From::from)
|
||||
}
|
||||
|
||||
let mut filter = default_tracing_env_filter();
|
||||
|
||||
// these crates are more granularly filtered
|
||||
let filter_crates = ["defguard_wireguard_rs"];
|
||||
for crate_name in filter_crates {
|
||||
filter = filter.add_directive(directive_checked(format!("{crate_name}=warn"))?);
|
||||
}
|
||||
Ok(filter)
|
||||
}
|
||||
|
||||
pub fn setup_no_otel_logger() -> Result<(), TracingError> {
|
||||
// Only set up if not already initialized
|
||||
if tracing::dispatcher::has_been_set() {
|
||||
// It shouldn't be - this is really checking that it is torn down between async command executions
|
||||
return Err(TracingError::TracingLoggerAlreadyInitialised);
|
||||
}
|
||||
|
||||
let registry = tracing_subscriber::registry()
|
||||
.with(default_tracing_fmt_layer(std::io::stderr))
|
||||
.with(granual_filtered_env()?);
|
||||
|
||||
registry
|
||||
.try_init()
|
||||
.map_err(|e| TracingError::TracingTryInitError(e))?;
|
||||
|
||||
Ok(())
|
||||
#[cfg(feature = "basic_tracing")]
|
||||
pub fn setup_tracing_logger() {
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
build_tracing_logger().init()
|
||||
}
|
||||
|
||||
// TODO: This has to be a macro, running it as a function does not work for the file_appender for some reason
|
||||
#[cfg(feature = "tracing")]
|
||||
#[macro_export]
|
||||
macro_rules! setup_tracing {
|
||||
($service_name: expr) => {
|
||||
setup_no_otel_logger()
|
||||
use nym_bin_common::logging::tracing_subscriber::layer::SubscriberExt;
|
||||
use nym_bin_common::logging::tracing_subscriber::util::SubscriberInitExt;
|
||||
|
||||
let registry = nym_bin_common::logging::tracing_subscriber::Registry::default()
|
||||
.with(nym_bin_common::logging::tracing_subscriber::EnvFilter::from_default_env())
|
||||
.with(
|
||||
nym_bin_common::logging::tracing_tree::HierarchicalLayer::new(4)
|
||||
.with_targets(true)
|
||||
.with_bracketed_fields(true),
|
||||
);
|
||||
|
||||
let tracer = nym_bin_common::logging::opentelemetry_jaeger::new_collector_pipeline()
|
||||
.with_endpoint("http://44.199.230.10:14268/api/traces")
|
||||
.with_service_name($service_name)
|
||||
.with_isahc()
|
||||
.with_trace_config(
|
||||
nym_bin_common::logging::opentelemetry::sdk::trace::config().with_sampler(
|
||||
nym_bin_common::logging::opentelemetry::sdk::trace::Sampler::TraceIdRatioBased(
|
||||
0.1,
|
||||
),
|
||||
),
|
||||
)
|
||||
.install_batch(nym_bin_common::logging::opentelemetry::runtime::Tokio)
|
||||
.expect("Could not init tracer");
|
||||
|
||||
let telemetry = nym_bin_common::logging::tracing_opentelemetry::layer().with_tracer(tracer);
|
||||
|
||||
registry.with(telemetry).init();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
use opentelemetry::trace::{SpanId, TraceId};
|
||||
use opentelemetry_sdk::trace::IdGenerator;
|
||||
use rand::RngCore;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Compact13BytesIdGenerator;
|
||||
|
||||
impl IdGenerator for Compact13BytesIdGenerator {
|
||||
fn new_trace_id(&self) -> TraceId {
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut bytes = [0u8; 16];
|
||||
|
||||
// Fill the first 13 bytes with random data
|
||||
rng.fill_bytes(&mut bytes[0..12]);
|
||||
// Set the last 4 bytes to zero
|
||||
bytes[12] = 0;
|
||||
bytes[13] = 0;
|
||||
bytes[14] = 0;
|
||||
bytes[15] = 0;
|
||||
|
||||
TraceId::from_bytes(bytes)
|
||||
}
|
||||
|
||||
fn new_span_id(&self) -> SpanId {
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut bytes = [0u8; 8];
|
||||
rng.fill_bytes(&mut bytes);
|
||||
|
||||
SpanId::from_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compress_trace_id(trace_id: &TraceId) -> [u8; 12] {
|
||||
let bytes = trace_id.to_bytes();
|
||||
|
||||
let mut compressed = [0u8; 12];
|
||||
compressed.copy_from_slice(&bytes[0..12]);
|
||||
|
||||
compressed
|
||||
}
|
||||
|
||||
pub fn decompress_trace_id(compressed: &[u8; 12]) -> [u8; 16] {
|
||||
let mut bytes = [0u8; 16];
|
||||
bytes[0..12].copy_from_slice(compressed);
|
||||
bytes[12..].copy_from_slice(&[0u8; 4]);
|
||||
bytes
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
use opentelemetry::propagation::{Extractor, Injector, TextMapPropagator};
|
||||
use opentelemetry::trace::{SpanContext, TraceContextExt, TraceId};
|
||||
use opentelemetry::{Context, TraceFlags};
|
||||
use opentelemetry_sdk::{propagation::TraceContextPropagator, trace::IdGenerator};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
use tracing::instrument;
|
||||
use tracing_opentelemetry::OpenTelemetrySpanExt;
|
||||
|
||||
/// Make a Carrier for context propagation
|
||||
pub struct ContextCarrier {
|
||||
data: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl ContextCarrier {
|
||||
pub fn new_empty() -> Self {
|
||||
ContextCarrier {
|
||||
data: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_data(data: HashMap<String, String>) -> Self {
|
||||
if data.is_empty() {
|
||||
return ContextCarrier::new_empty();
|
||||
}
|
||||
|
||||
ContextCarrier { data }
|
||||
}
|
||||
|
||||
pub fn new_with_current_context(context: Context) -> Self {
|
||||
let mut carrier = ContextCarrier::new_empty();
|
||||
let propagator = TraceContextPropagator::new();
|
||||
propagator.inject_context(&context, &mut carrier);
|
||||
carrier
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = (&String, &String)> {
|
||||
self.data.iter()
|
||||
}
|
||||
|
||||
pub fn from_map(data: HashMap<String, String>) -> Self {
|
||||
ContextCarrier { data }
|
||||
}
|
||||
|
||||
pub fn into_map(self) -> HashMap<String, String> {
|
||||
self.data
|
||||
}
|
||||
|
||||
pub fn extract_trace_id(&self) -> Option<TraceId> {
|
||||
self.get("traceparent").and_then(|tp| {
|
||||
let parts: Vec<&str> = tp.split('-').collect();
|
||||
if parts.len() == 4 {
|
||||
TraceId::from_hex(parts[1]).ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn extract_trace_id_into_bytes(&self) -> Option<[u8; 16]> {
|
||||
self.extract_trace_id().map(|id| id.to_bytes())
|
||||
}
|
||||
|
||||
pub fn extract_traceparent(&self) -> Option<String> {
|
||||
self.get("traceparent").map(|s| s.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl Injector for ContextCarrier {
|
||||
fn set(&mut self, key: &str, value: String) {
|
||||
self.data.insert(key.to_string(), value);
|
||||
}
|
||||
}
|
||||
|
||||
impl Extractor for ContextCarrier {
|
||||
fn get(&self, key: &str) -> Option<&str> {
|
||||
self.data.get(key).map(|s| s.as_str())
|
||||
}
|
||||
|
||||
fn keys(&self) -> Vec<&str> {
|
||||
self.data.keys().map(|k| k.as_str()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ContextCarrier {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self.data)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ManualContextPropagator {
|
||||
pub root_span: tracing::Span,
|
||||
pub trace_id: TraceId,
|
||||
}
|
||||
|
||||
impl ManualContextPropagator {
|
||||
#[instrument(skip_all, level = "debug")]
|
||||
pub fn new(name: &str, context: HashMap<String, String>) -> Self {
|
||||
let carrier = ContextCarrier::new_with_data(context);
|
||||
let trace_id = match carrier.extract_trace_id() {
|
||||
Some(id) => id,
|
||||
None => Context::current().span().span_context().trace_id(),
|
||||
};
|
||||
|
||||
let root_span_builder = new_span_context_with_id(trace_id.clone());
|
||||
|
||||
let root_span = tracing::info_span!("trace_root", name = %name, trace_id = %trace_id);
|
||||
root_span.set_parent(root_span_builder);
|
||||
|
||||
ManualContextPropagator {
|
||||
root_span,
|
||||
trace_id,
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip_all, level = "debug")]
|
||||
pub fn new_from_tid(name: &str, trace_id: TraceId) -> Self {
|
||||
let root_span_builder = new_span_context_with_id(trace_id.clone());
|
||||
|
||||
let root_span = tracing::info_span!("trace_root", name = %name, trace_id = %trace_id);
|
||||
root_span.set_parent(root_span_builder);
|
||||
|
||||
ManualContextPropagator {
|
||||
root_span,
|
||||
trace_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn root_span(&self) -> &tracing::Span {
|
||||
&self.root_span
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip_all, level = "debug")]
|
||||
pub fn new_span_context_with_id(trace_id: TraceId) -> Context {
|
||||
let id_gen = opentelemetry_sdk::trace::RandomIdGenerator::default();
|
||||
let span_id = id_gen.new_span_id();
|
||||
let span_context = SpanContext::new(
|
||||
trace_id,
|
||||
span_id,
|
||||
TraceFlags::SAMPLED,
|
||||
true,
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
Context::current().with_remote_span_context(span_context)
|
||||
}
|
||||
|
||||
#[instrument(skip_all, level = "debug")]
|
||||
pub fn extract_trace_id_from_tracing_cx() -> TraceId {
|
||||
let cx = tracing::Span::current().context();
|
||||
let binding = cx.span();
|
||||
let trace_id = binding.span_context().trace_id();
|
||||
trace_id
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
pub mod compact_id_generator;
|
||||
pub mod context;
|
||||
mod trace_id_format;
|
||||
|
||||
use tracing::{Level, info};
|
||||
use tracing_subscriber::filter::Directive;
|
||||
use tracing_subscriber::fmt;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
|
||||
use crate::logging::default_tracing_env_filter;
|
||||
use crate::logging::error::TracingError;
|
||||
use crate::opentelemetry::compact_id_generator::Compact13BytesIdGenerator;
|
||||
use opentelemetry::trace::TracerProvider;
|
||||
use opentelemetry::{KeyValue, global};
|
||||
use opentelemetry_otlp::tonic_types::metadata::MetadataMap;
|
||||
use opentelemetry_otlp::tonic_types::transport::ClientTlsConfig;
|
||||
use opentelemetry_otlp::{WithExportConfig, WithTonicConfig};
|
||||
use opentelemetry_sdk::metrics::{MeterProviderBuilder, PeriodicReader, SdkMeterProvider};
|
||||
use opentelemetry_sdk::trace::SdkTracerProvider;
|
||||
use opentelemetry_sdk::{Resource, trace::Sampler};
|
||||
use opentelemetry_semantic_conventions::SCHEMA_URL;
|
||||
use opentelemetry_semantic_conventions::resource::{DEPLOYMENT_ENVIRONMENT_NAME, SERVICE_VERSION};
|
||||
use tracing_opentelemetry::{MetricsLayer, OpenTelemetryLayer};
|
||||
use tracing_subscriber::fmt::format::FmtSpan;
|
||||
|
||||
pub struct TracerProviderGuard(Option<SdkTracerProvider>);
|
||||
|
||||
impl Drop for TracerProviderGuard {
|
||||
fn drop(&mut self) {
|
||||
if let Some(tracer_provider) = self.0.take() {
|
||||
// Ensure all spans are flushed before exit
|
||||
if let Err(e) = tracer_provider.shutdown() {
|
||||
eprintln!("Error shutting down tracer provider: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn granual_filtered_env() -> Result<tracing_subscriber::filter::EnvFilter, TracingError>
|
||||
{
|
||||
fn directive_checked(directive: impl Into<String>) -> Result<Directive, TracingError> {
|
||||
directive.into().parse().map_err(From::from)
|
||||
}
|
||||
|
||||
let mut filter = default_tracing_env_filter();
|
||||
|
||||
// these crates are more granularly filtered
|
||||
let filter_crates = ["defguard_wireguard_rs"];
|
||||
for crate_name in filter_crates {
|
||||
filter = filter.add_directive(directive_checked(format!("{crate_name}=warn"))?);
|
||||
}
|
||||
Ok(filter)
|
||||
}
|
||||
|
||||
pub fn setup_tracing_logger(service_name: String) -> Result<TracerProviderGuard, TracingError> {
|
||||
if tracing::dispatcher::has_been_set() {
|
||||
// It shouldn't be - this is really checking that it is torn down between async command executions
|
||||
return Err(TracingError::TracingLoggerAlreadyInitialised);
|
||||
}
|
||||
|
||||
// define ingestion points
|
||||
let endpoint = std::env::var("SIGNOZ_ENDPOINT").expect("SIGNOZ_ENDPOINT not set");
|
||||
let key = std::env::var("SIGNOZ_INGESTION_KEY").expect("SIGNOZ_INGESTION_KEY not set");
|
||||
let mut metadata = MetadataMap::new();
|
||||
metadata.insert(
|
||||
"signoz-ingestion-key",
|
||||
key.parse().expect("Could not parse signoz ingestion key"),
|
||||
);
|
||||
|
||||
// Build resources
|
||||
let resource = build_resource(&service_name);
|
||||
|
||||
// Initialize tracer and meter providers
|
||||
let tracer_provider = init_tracer_provider(&endpoint, metadata.clone(), resource.clone())?;
|
||||
let meter_provider = init_meter_provider(&endpoint, metadata.clone(), resource.clone())?;
|
||||
|
||||
// Bridge tracing and opentelemetry
|
||||
let tracer = tracer_provider.tracer("otel-subscriber");
|
||||
let fmt_layer = fmt::layer()
|
||||
.json()
|
||||
.with_writer(std::io::stderr)
|
||||
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
|
||||
.with_span_list(false)
|
||||
.with_current_span(true)
|
||||
.event_format(trace_id_format::TraceIdFormat);
|
||||
|
||||
let registry = tracing_subscriber::registry()
|
||||
.with(fmt_layer)
|
||||
.with(granual_filtered_env()?)
|
||||
.with(tracing_subscriber::filter::LevelFilter::from_level(
|
||||
Level::INFO,
|
||||
))
|
||||
.with(MetricsLayer::new(meter_provider.clone()))
|
||||
.with(OpenTelemetryLayer::new(tracer));
|
||||
|
||||
registry
|
||||
.try_init()
|
||||
.map_err(TracingError::TracingTryInitError)?;
|
||||
|
||||
global::set_tracer_provider(tracer_provider.clone());
|
||||
global::set_meter_provider(meter_provider.clone());
|
||||
|
||||
info!("Tracing initialized with service name: {}", service_name);
|
||||
|
||||
Ok(TracerProviderGuard(Some(tracer_provider)))
|
||||
}
|
||||
|
||||
fn build_resource(service_name: &str) -> Resource {
|
||||
Resource::builder()
|
||||
.with_service_name(service_name.to_string())
|
||||
.with_schema_url(
|
||||
[
|
||||
KeyValue::new(SERVICE_VERSION, env!("CARGO_PKG_VERSION")),
|
||||
KeyValue::new(DEPLOYMENT_ENVIRONMENT_NAME, "develop"),
|
||||
],
|
||||
SCHEMA_URL,
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
fn init_tracer_provider(
|
||||
endpoint: &str,
|
||||
metadata: MetadataMap,
|
||||
resource: Resource,
|
||||
) -> Result<SdkTracerProvider, TracingError> {
|
||||
let mut exporter_builder = opentelemetry_otlp::SpanExporter::builder()
|
||||
.with_tonic()
|
||||
.with_metadata(metadata)
|
||||
.with_endpoint(endpoint);
|
||||
|
||||
if endpoint.starts_with("https://") {
|
||||
exporter_builder =
|
||||
exporter_builder.with_tls_config(ClientTlsConfig::new().with_enabled_roots());
|
||||
}
|
||||
|
||||
let exporter = exporter_builder.build()?;
|
||||
|
||||
let tracer = SdkTracerProvider::builder()
|
||||
.with_sampler(Sampler::ParentBased(Box::new(Sampler::TraceIdRatioBased(
|
||||
1.0,
|
||||
))))
|
||||
.with_id_generator(Compact13BytesIdGenerator)
|
||||
.with_resource(resource)
|
||||
.with_batch_exporter(exporter)
|
||||
.build();
|
||||
|
||||
global::set_tracer_provider(tracer.clone());
|
||||
Ok(tracer)
|
||||
}
|
||||
|
||||
fn init_meter_provider(
|
||||
endpoint: &str,
|
||||
metadata: MetadataMap,
|
||||
resource: Resource,
|
||||
) -> Result<SdkMeterProvider, TracingError> {
|
||||
let mut exporter_builder = opentelemetry_otlp::MetricExporter::builder()
|
||||
.with_tonic()
|
||||
.with_metadata(metadata)
|
||||
.with_endpoint(endpoint)
|
||||
.with_temporality(opentelemetry_sdk::metrics::Temporality::default());
|
||||
|
||||
if endpoint.starts_with("https://") {
|
||||
exporter_builder =
|
||||
exporter_builder.with_tls_config(ClientTlsConfig::new().with_enabled_roots());
|
||||
}
|
||||
|
||||
let exporter = exporter_builder.build()?;
|
||||
|
||||
let reader = PeriodicReader::builder(exporter)
|
||||
.with_interval(std::time::Duration::from_secs(30))
|
||||
.build();
|
||||
|
||||
let stdout_reader =
|
||||
PeriodicReader::builder(opentelemetry_stdout::MetricExporter::default()).build();
|
||||
|
||||
let meter_provider = MeterProviderBuilder::default()
|
||||
.with_resource(resource)
|
||||
.with_reader(reader)
|
||||
.with_reader(stdout_reader)
|
||||
.build();
|
||||
|
||||
global::set_meter_provider(meter_provider.clone());
|
||||
|
||||
Ok(meter_provider)
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
use chrono::Utc;
|
||||
use opentelemetry::trace::TraceContextExt;
|
||||
use opentelemetry::{SpanId, TraceId};
|
||||
use serde::ser::{SerializeMap, Serializer as _};
|
||||
use std::io;
|
||||
use tracing::{Event, Subscriber};
|
||||
use tracing_opentelemetry::OpenTelemetrySpanExt;
|
||||
use tracing_serde::AsSerde;
|
||||
use tracing_serde::fields::AsMap;
|
||||
use tracing_subscriber::fmt::format::Writer;
|
||||
use tracing_subscriber::fmt::{FmtContext, FormatEvent, FormatFields};
|
||||
use tracing_subscriber::registry::LookupSpan;
|
||||
|
||||
pub struct WriteAdaptor<'a> {
|
||||
fmt_write: &'a mut dyn std::fmt::Write,
|
||||
}
|
||||
|
||||
impl<'a> WriteAdaptor<'a> {
|
||||
pub fn new(fmt_write: &'a mut dyn std::fmt::Write) -> Self {
|
||||
Self { fmt_write }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> io::Write for WriteAdaptor<'a> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let s =
|
||||
std::str::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
|
||||
self.fmt_write
|
||||
.write_str(s)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||
|
||||
Ok(s.as_bytes().len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TraceIdFormat;
|
||||
|
||||
impl<S, N> FormatEvent<S, N> for TraceIdFormat
|
||||
where
|
||||
S: Subscriber + for<'lookup> LookupSpan<'lookup>,
|
||||
N: for<'writer> FormatFields<'writer> + 'static,
|
||||
{
|
||||
fn format_event(
|
||||
&self,
|
||||
_ctx: &FmtContext<'_, S, N>,
|
||||
mut writer: Writer<'_>,
|
||||
event: &Event<'_>,
|
||||
) -> std::fmt::Result
|
||||
where
|
||||
S: Subscriber + for<'a> LookupSpan<'a>,
|
||||
{
|
||||
let meta = event.metadata();
|
||||
|
||||
let mut visit = || {
|
||||
let mut serializer = serde_json::Serializer::new(WriteAdaptor::new(&mut writer));
|
||||
let mut serializer = serializer.serialize_map(None)?;
|
||||
serializer.serialize_entry("timestamp", &Utc::now().to_rfc3339())?;
|
||||
serializer.serialize_entry("level", &meta.level().as_serde())?;
|
||||
serializer.serialize_entry("fields", &event.field_map())?;
|
||||
serializer.serialize_entry("target", meta.target())?;
|
||||
|
||||
let current_span = tracing::Span::current();
|
||||
let context = current_span.context();
|
||||
let span_ref = context.span();
|
||||
let span_context = span_ref.span_context();
|
||||
|
||||
let trace_id = span_context.trace_id();
|
||||
if trace_id != TraceId::INVALID {
|
||||
serializer.serialize_entry("trace_id", &trace_id.to_string())?;
|
||||
|
||||
let span_id = span_context.span_id();
|
||||
if span_id != SpanId::INVALID {
|
||||
serializer.serialize_entry("span_id", &span_id.to_string())?;
|
||||
}
|
||||
}
|
||||
|
||||
serializer.end()
|
||||
};
|
||||
|
||||
visit().map_err(|_| std::fmt::Error)?;
|
||||
writeln!(writer)
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,6 @@ cli = ["clap", "comfy-table"]
|
||||
fs-credentials-storage = ["nym-credential-storage/persistent-storage"]
|
||||
fs-surb-storage = ["nym-client-core-surb-storage/fs-surb-storage"]
|
||||
fs-gateways-storage = ["nym-client-core-gateways-storage/fs-gateways-storage"]
|
||||
otel = ["nym-sphinx/otel"]
|
||||
wasm = ["nym-gateway-client/wasm"]
|
||||
metrics-server = []
|
||||
|
||||
|
||||
@@ -114,12 +114,13 @@ where
|
||||
})?;
|
||||
hardcoded_topology.entry_capable_nodes().cloned().collect()
|
||||
} else {
|
||||
let mut rng = rand::thread_rng();
|
||||
crate::init::helpers::gateways_for_init(
|
||||
&mut rng,
|
||||
&core.client.nym_api_urls,
|
||||
user_agent,
|
||||
core.debug.topology.minimum_gateway_performance,
|
||||
core.debug.topology.ignore_ingress_epoch_role,
|
||||
None,
|
||||
)
|
||||
.await?
|
||||
};
|
||||
|
||||
@@ -173,12 +173,13 @@ where
|
||||
})?;
|
||||
hardcoded_topology.entry_capable_nodes().cloned().collect()
|
||||
} else {
|
||||
let mut rng = rand::thread_rng();
|
||||
crate::init::helpers::gateways_for_init(
|
||||
&mut rng,
|
||||
&core.client.nym_api_urls,
|
||||
user_agent,
|
||||
core.debug.topology.minimum_gateway_performance,
|
||||
core.debug.topology.ignore_ingress_epoch_role,
|
||||
None,
|
||||
)
|
||||
.await?
|
||||
};
|
||||
|
||||
@@ -7,12 +7,11 @@ use super::statistics_control::StatisticsControl;
|
||||
use crate::client::base_client::storage::helpers::store_client_keys;
|
||||
use crate::client::base_client::storage::MixnetClientStorage;
|
||||
use crate::client::cover_traffic_stream::LoopCoverTrafficStream;
|
||||
use crate::client::event_control::EventControl;
|
||||
use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender};
|
||||
use crate::client::key_manager::persistence::KeyStore;
|
||||
use crate::client::key_manager::ClientKeys;
|
||||
use crate::client::mix_traffic::transceiver::{GatewayReceiver, GatewayTransceiver, RemoteGateway};
|
||||
use crate::client::mix_traffic::{BatchMixMessageSender, MixTrafficController, MixTrafficEvent};
|
||||
use crate::client::mix_traffic::{BatchMixMessageSender, MixTrafficController};
|
||||
use crate::client::real_messages_control;
|
||||
use crate::client::real_messages_control::RealMessagesController;
|
||||
use crate::client::received_buffer::{
|
||||
@@ -67,7 +66,7 @@ use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use time::OffsetDateTime;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
use tracing::instrument;
|
||||
use tracing::*;
|
||||
use url::Url;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
@@ -84,28 +83,10 @@ pub mod non_wasm_helpers;
|
||||
pub mod helpers;
|
||||
pub mod storage;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum MixnetClientEvent {
|
||||
Traffic(MixTrafficEvent),
|
||||
}
|
||||
|
||||
pub type EventReceiver = mpsc::UnboundedReceiver<MixnetClientEvent>;
|
||||
#[derive(Clone)]
|
||||
pub struct EventSender(pub mpsc::UnboundedSender<MixnetClientEvent>);
|
||||
|
||||
impl EventSender {
|
||||
pub fn send(&self, event: MixnetClientEvent) {
|
||||
if let Err(err) = self.0.unbounded_send(event) {
|
||||
tracing::warn!("Failed to send error event. The caller event reader was closed: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ClientInput {
|
||||
pub connection_command_sender: ConnectionCommandSender,
|
||||
pub input_sender: InputMessageSender,
|
||||
pub client_request_sender: ClientRequestSender,
|
||||
}
|
||||
|
||||
impl ClientInput {
|
||||
@@ -122,7 +103,6 @@ pub struct ClientOutput {
|
||||
}
|
||||
|
||||
impl ClientOutput {
|
||||
#[instrument(name = "ClientOutput::register_receiver", skip_all)]
|
||||
pub fn register_receiver(
|
||||
&mut self,
|
||||
) -> Result<mpsc::UnboundedReceiver<Vec<ReconstructedMessage>>, ClientCoreError> {
|
||||
@@ -218,7 +198,6 @@ pub struct BaseClientBuilder<C, S: MixnetClientStorage> {
|
||||
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
||||
shutdown: Option<ShutdownTracker>,
|
||||
event_tx: Option<EventSender>,
|
||||
user_agent: Option<UserAgent>,
|
||||
|
||||
setup_method: GatewaySetup,
|
||||
@@ -247,7 +226,6 @@ where
|
||||
custom_topology_provider: None,
|
||||
custom_gateway_transceiver: None,
|
||||
shutdown: None,
|
||||
event_tx: None,
|
||||
user_agent: None,
|
||||
setup_method: GatewaySetup::MustLoad { gateway_id: None },
|
||||
#[cfg(unix)]
|
||||
@@ -310,12 +288,6 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_event_tx(mut self, event_tx: EventSender) -> Self {
|
||||
self.event_tx = Some(event_tx);
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_user_agent(mut self, user_agent: UserAgent) -> Self {
|
||||
self.user_agent = Some(user_agent);
|
||||
@@ -346,18 +318,6 @@ where
|
||||
details.client_address()
|
||||
}
|
||||
|
||||
fn start_event_control(
|
||||
parent_event_tx: Option<EventSender>,
|
||||
children_event_rx: EventReceiver,
|
||||
shutdown_tracker: &ShutdownTracker,
|
||||
) {
|
||||
let event_control = EventControl::new(parent_event_tx, children_event_rx);
|
||||
shutdown_tracker.try_spawn_named_with_shutdown(
|
||||
async move { event_control.run().await },
|
||||
"EventControl",
|
||||
);
|
||||
}
|
||||
|
||||
// future constantly pumping loop cover traffic at some specified average rate
|
||||
// the pumped traffic goes to the MixTrafficController
|
||||
fn start_cover_traffic_stream(
|
||||
@@ -369,7 +329,7 @@ where
|
||||
stats_tx: ClientStatsSender,
|
||||
shutdown_tracker: &ShutdownTracker,
|
||||
) {
|
||||
tracing::info!("Starting loop cover traffic stream...");
|
||||
info!("Starting loop cover traffic stream...");
|
||||
|
||||
let mut stream = LoopCoverTrafficStream::new(
|
||||
ack_key,
|
||||
@@ -386,7 +346,6 @@ where
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[instrument(skip_all)]
|
||||
fn start_real_traffic_controller(
|
||||
controller_config: real_messages_control::Config,
|
||||
key_rotation_config: KeyRotationConfig,
|
||||
@@ -402,7 +361,7 @@ where
|
||||
stats_tx: ClientStatsSender,
|
||||
shutdown_tracker: &ShutdownTracker,
|
||||
) {
|
||||
tracing::info!("Starting real traffic stream...");
|
||||
info!("Starting real traffic stream...");
|
||||
|
||||
let real_messages_controller = RealMessagesController::new(
|
||||
controller_config,
|
||||
@@ -478,7 +437,6 @@ where
|
||||
|
||||
// buffer controlling all messages fetched from provider
|
||||
// required so that other components would be able to use them (say the websocket)
|
||||
#[instrument(skip_all)]
|
||||
fn start_received_messages_buffer_controller(
|
||||
local_encryption_keypair: Arc<x25519::KeyPair>,
|
||||
query_receiver: ReceivedBufferRequestReceiver,
|
||||
@@ -488,7 +446,7 @@ where
|
||||
metrics_reporter: ClientStatsSender,
|
||||
shutdown_tracker: &ShutdownTracker,
|
||||
) {
|
||||
tracing::info!("Starting received messages buffer controller...");
|
||||
info!("Starting received messages buffer controller...");
|
||||
let controller = ReceivedMessagesBufferController::<SphinxMessageReceiver>::new(
|
||||
local_encryption_keypair,
|
||||
query_receiver,
|
||||
@@ -511,7 +469,6 @@ where
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[instrument(skip_all)]
|
||||
async fn start_gateway_client(
|
||||
config: &Config,
|
||||
initialisation_result: InitialisationResult,
|
||||
@@ -600,7 +557,7 @@ where
|
||||
details_store
|
||||
.upgrade_stored_remote_gateway_key(gateway_client.gateway_identity(), &updated_key)
|
||||
.await.map_err(|err| {
|
||||
tracing::error!("failed to store upgraded gateway key! this connection might be forever broken now: {err}");
|
||||
error!("failed to store upgraded gateway key! this connection might be forever broken now: {err}");
|
||||
ClientCoreError::GatewaysDetailsStoreError { source: Box::new(err) }
|
||||
})?
|
||||
}
|
||||
@@ -618,7 +575,6 @@ where
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[instrument(skip_all)]
|
||||
async fn setup_gateway_transceiver(
|
||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
||||
config: &Config,
|
||||
@@ -698,7 +654,7 @@ where
|
||||
|
||||
if topology_config.disable_refreshing {
|
||||
// if we're not spawning the refresher, don't cause shutdown immediately
|
||||
tracing::info!("The background topology refresher is not going to be started");
|
||||
info!("The background topology refresher is not going to be started");
|
||||
}
|
||||
|
||||
let mut topology_refresher = TopologyRefresher::new(
|
||||
@@ -708,7 +664,7 @@ where
|
||||
);
|
||||
// before returning, block entire runtime to refresh the current network view so that any
|
||||
// components depending on topology would see a non-empty view
|
||||
tracing::info!("Obtaining initial network topology");
|
||||
info!("Obtaining initial network topology");
|
||||
topology_refresher.try_refresh().await;
|
||||
|
||||
if let Err(err) = topology_refresher.ensure_topology_is_routable().await {
|
||||
@@ -734,13 +690,13 @@ where
|
||||
.wait_for_gateway(local_gateway, waiting_timeout)
|
||||
.await
|
||||
{
|
||||
tracing::error!(
|
||||
error!(
|
||||
"the gateway did not come back online within the specified timeout: {err}"
|
||||
);
|
||||
return Err(err.into());
|
||||
}
|
||||
} else {
|
||||
tracing::error!("the gateway we're supposedly connected to does not exist. We'll not be able to send any packets to ourselves: {err}");
|
||||
error!("the gateway we're supposedly connected to does not exist. We'll not be able to send any packets to ourselves: {err}");
|
||||
return Err(err.into());
|
||||
}
|
||||
}
|
||||
@@ -748,7 +704,7 @@ where
|
||||
if !topology_config.disable_refreshing {
|
||||
// don't spawn the refresher if we don't want to be refreshing the topology.
|
||||
// only use the initial values obtained
|
||||
tracing::info!("Starting topology refresher...");
|
||||
info!("Starting topology refresher...");
|
||||
shutdown_tracker.try_spawn_named_with_shutdown(
|
||||
async move { topology_refresher.run().await },
|
||||
"TopologyRefresher",
|
||||
@@ -765,7 +721,7 @@ where
|
||||
input_sender: Sender<InputMessage>,
|
||||
shutdown_tracker: &ShutdownTracker,
|
||||
) -> ClientStatsSender {
|
||||
tracing::info!("Starting statistics control...");
|
||||
info!("Starting statistics control...");
|
||||
StatisticsControl::create_and_start(
|
||||
config.debug.stats_reporting,
|
||||
user_agent
|
||||
@@ -776,21 +732,14 @@ where
|
||||
shutdown_tracker,
|
||||
)
|
||||
}
|
||||
#[instrument(skip_all)]
|
||||
|
||||
fn start_mix_traffic_controller(
|
||||
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
||||
shutdown_tracker: &ShutdownTracker,
|
||||
event_tx: EventSender,
|
||||
) -> (BatchMixMessageSender, ClientRequestSender) {
|
||||
tracing::info!("Starting mix traffic controller...");
|
||||
let mut mix_traffic_controller = MixTrafficController::new(
|
||||
gateway_transceiver,
|
||||
shutdown_tracker.clone_shutdown_token(),
|
||||
event_tx,
|
||||
);
|
||||
|
||||
let mix_tx = mix_traffic_controller.mix_rx();
|
||||
let client_tx = mix_traffic_controller.client_tx();
|
||||
info!("Starting mix traffic controller...");
|
||||
let (mut mix_traffic_controller, mix_tx, client_tx) =
|
||||
MixTrafficController::new(gateway_transceiver, shutdown_tracker.clone_shutdown_token());
|
||||
|
||||
shutdown_tracker.try_spawn_named(
|
||||
async move { mix_traffic_controller.run().await },
|
||||
@@ -854,7 +803,7 @@ where
|
||||
{
|
||||
// if client keys do not exist already, create and persist them
|
||||
if key_store.load_keys().await.is_err() {
|
||||
tracing::info!("could not find valid client keys - a new set will be generated");
|
||||
info!("could not find valid client keys - a new set will be generated");
|
||||
let mut rng = OsRng;
|
||||
let keys = if let Some(derivation_material) = derivation_material {
|
||||
ClientKeys::from_master_key(&mut rng, &derivation_material)
|
||||
@@ -893,7 +842,6 @@ where
|
||||
Ok(client.get_key_rotation_info().await?.into())
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError>
|
||||
where
|
||||
S::ReplyStore: Send + Sync,
|
||||
@@ -902,7 +850,7 @@ where
|
||||
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync + 'static,
|
||||
<S::GatewaysDetailsStore as GatewaysDetailsStore>::StorageError: Sync + Send,
|
||||
{
|
||||
tracing::info!("Starting nym client");
|
||||
info!("Starting nym client");
|
||||
#[cfg(debug_assertions)]
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
@@ -936,9 +884,6 @@ where
|
||||
// channels responsible for controlling real messages
|
||||
let (input_sender, input_receiver) = tokio::sync::mpsc::channel::<InputMessage>(1);
|
||||
|
||||
// channels responsible for event management
|
||||
let (event_sender, event_receiver) = mpsc::unbounded();
|
||||
|
||||
// channels responsible for controlling ack messages
|
||||
let (ack_sender, ack_receiver) = mpsc::unbounded();
|
||||
let shared_topology_accessor =
|
||||
@@ -951,8 +896,6 @@ where
|
||||
None => nym_task::get_sdk_shutdown_tracker()?,
|
||||
};
|
||||
|
||||
Self::start_event_control(self.event_tx, event_receiver, &shutdown_tracker);
|
||||
|
||||
// channels responsible for dealing with reply-related fun
|
||||
let (reply_controller_sender, reply_controller_receiver) =
|
||||
reply_controller::requests::new_control_channels();
|
||||
@@ -1043,7 +986,6 @@ where
|
||||
let (message_sender, client_request_sender) = Self::start_mix_traffic_controller(
|
||||
gateway_transceiver,
|
||||
&shutdown_tracker.child_tracker(),
|
||||
EventSender(event_sender),
|
||||
);
|
||||
|
||||
// Channels that the websocket listener can use to signal downstream to the real traffic
|
||||
@@ -1093,8 +1035,8 @@ where
|
||||
);
|
||||
}
|
||||
|
||||
tracing::debug!("Core client startup finished!");
|
||||
tracing::debug!("The address of this client is: {self_address}");
|
||||
debug!("Core client startup finished!");
|
||||
debug!("The address of this client is: {self_address}");
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
@@ -1110,7 +1052,6 @@ where
|
||||
client_input: ClientInput {
|
||||
connection_command_sender: client_connection_tx,
|
||||
input_sender,
|
||||
client_request_sender,
|
||||
},
|
||||
},
|
||||
client_output: ClientOutputStatus::AwaitingConsumer {
|
||||
@@ -1126,6 +1067,7 @@ where
|
||||
},
|
||||
stats_reporter,
|
||||
shutdown_handle: shutdown_tracker, // The primary tracker for this client
|
||||
client_request_sender,
|
||||
forget_me: self.config.debug.forget_me,
|
||||
remember_me: self.config.debug.remember_me,
|
||||
})
|
||||
@@ -1139,6 +1081,7 @@ pub struct BaseClient {
|
||||
pub client_output: ClientOutputStatus,
|
||||
pub client_state: ClientState,
|
||||
pub stats_reporter: ClientStatsSender,
|
||||
pub client_request_sender: ClientRequestSender,
|
||||
pub shutdown_handle: ShutdownTracker,
|
||||
pub forget_me: ForgetMe,
|
||||
pub remember_me: RememberMe,
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use futures::StreamExt;
|
||||
|
||||
use crate::client::base_client::{EventReceiver, EventSender, MixnetClientEvent};
|
||||
|
||||
/// Launches and manages task events, propagating upwards what is not strictly internal.
|
||||
pub(crate) struct EventControl {
|
||||
parent_event_tx: Option<EventSender>,
|
||||
children_event_rx: EventReceiver,
|
||||
}
|
||||
|
||||
impl EventControl {
|
||||
pub(crate) fn new(
|
||||
parent_event_tx: Option<EventSender>,
|
||||
children_event_rx: EventReceiver,
|
||||
) -> Self {
|
||||
EventControl {
|
||||
parent_event_tx,
|
||||
children_event_rx,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_internal(event: MixnetClientEvent) -> bool {
|
||||
match event {
|
||||
MixnetClientEvent::Traffic(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn run(mut self) {
|
||||
while let Some(event) = self.children_event_rx.next().await {
|
||||
if let Some(parent_event_tx) = &self.parent_event_tx {
|
||||
if !Self::is_internal(event) {
|
||||
parent_event_tx.send(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,6 @@ pub enum InputMessage {
|
||||
data: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
max_retransmissions: Option<u32>,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>,
|
||||
},
|
||||
|
||||
/// Creates a message used for a duplex anonymous communication where the recipient
|
||||
@@ -47,8 +45,6 @@ pub enum InputMessage {
|
||||
reply_surbs: u32,
|
||||
lane: TransmissionLane,
|
||||
max_retransmissions: Option<u32>,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>,
|
||||
},
|
||||
|
||||
/// Attempt to use our internally received and stored `ReplySurb` to send the message back
|
||||
@@ -94,16 +90,12 @@ impl InputMessage {
|
||||
data: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
packet_type: Option<PacketType>,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>,
|
||||
) -> Self {
|
||||
let message = InputMessage::Regular {
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
max_retransmissions: None,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
};
|
||||
if let Some(packet_type) = packet_type {
|
||||
InputMessage::new_wrapper(message, packet_type)
|
||||
@@ -118,8 +110,6 @@ impl InputMessage {
|
||||
reply_surbs: u32,
|
||||
lane: TransmissionLane,
|
||||
packet_type: Option<PacketType>,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>,
|
||||
) -> Self {
|
||||
let message = InputMessage::Anonymous {
|
||||
recipient,
|
||||
@@ -127,8 +117,6 @@ impl InputMessage {
|
||||
reply_surbs,
|
||||
lane,
|
||||
max_retransmissions: None,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
};
|
||||
if let Some(packet_type) = packet_type {
|
||||
InputMessage::new_wrapper(message, packet_type)
|
||||
@@ -197,14 +185,4 @@ impl InputMessage {
|
||||
self.set_max_retransmissions(max_retransmissions);
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(feature = "otel")]
|
||||
pub fn trace_id(&self) -> Option<[u8; 12]> {
|
||||
match self {
|
||||
InputMessage::Regular { trace_id, .. } => *trace_id,
|
||||
InputMessage::Anonymous { trace_id, .. } => *trace_id,
|
||||
InputMessage::Premade { .. } | InputMessage::Reply { .. } => None,
|
||||
InputMessage::MessageWrapper { message, .. } => message.trace_id(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::{
|
||||
base_client::{EventSender, MixnetClientEvent},
|
||||
mix_traffic::transceiver::GatewayTransceiver,
|
||||
};
|
||||
use crate::client::mix_traffic::transceiver::GatewayTransceiver;
|
||||
use nym_gateway_requests::ClientRequest;
|
||||
use nym_sphinx::forwarding::packet::MixPacket;
|
||||
use nym_task::ShutdownToken;
|
||||
@@ -25,33 +22,28 @@ const MAX_FAILURE_COUNT: usize = 100;
|
||||
// that's also disgusting.
|
||||
pub struct Empty;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum MixTrafficEvent {
|
||||
FailedSendingSphinx,
|
||||
}
|
||||
|
||||
pub struct MixTrafficController {
|
||||
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
||||
|
||||
mix_tx: BatchMixMessageSender,
|
||||
mix_rx: BatchMixMessageReceiver,
|
||||
client_rx: ClientRequestReceiver,
|
||||
client_tx: ClientRequestSender,
|
||||
|
||||
// TODO: this is temporary work-around.
|
||||
// in long run `gateway_client` will be moved away from `MixTrafficController` anyway.
|
||||
consecutive_gateway_failure_count: usize,
|
||||
|
||||
shutdown_token: ShutdownToken,
|
||||
event_tx: EventSender,
|
||||
}
|
||||
|
||||
impl MixTrafficController {
|
||||
pub fn new<T>(
|
||||
gateway_transceiver: T,
|
||||
shutdown_token: ShutdownToken,
|
||||
event_tx: EventSender,
|
||||
) -> MixTrafficController
|
||||
) -> (
|
||||
MixTrafficController,
|
||||
BatchMixMessageSender,
|
||||
ClientRequestSender,
|
||||
)
|
||||
where
|
||||
T: GatewayTransceiver + Send + 'static,
|
||||
{
|
||||
@@ -60,32 +52,41 @@ impl MixTrafficController {
|
||||
|
||||
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(8);
|
||||
|
||||
MixTrafficController {
|
||||
gateway_transceiver: Box::new(gateway_transceiver),
|
||||
mix_tx: message_sender,
|
||||
mix_rx: message_receiver,
|
||||
client_rx: client_receiver,
|
||||
client_tx: client_sender,
|
||||
consecutive_gateway_failure_count: 0,
|
||||
shutdown_token,
|
||||
event_tx,
|
||||
}
|
||||
(
|
||||
MixTrafficController {
|
||||
gateway_transceiver: Box::new(gateway_transceiver),
|
||||
mix_rx: message_receiver,
|
||||
client_rx: client_receiver,
|
||||
consecutive_gateway_failure_count: 0,
|
||||
shutdown_token,
|
||||
},
|
||||
message_sender,
|
||||
client_sender,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_dynamic(
|
||||
gateway_transceiver: Box<dyn GatewayTransceiver + Send>,
|
||||
shutdown_token: ShutdownToken,
|
||||
event_tx: EventSender,
|
||||
) -> MixTrafficController {
|
||||
Self::new(gateway_transceiver, shutdown_token, event_tx)
|
||||
}
|
||||
|
||||
pub fn client_tx(&self) -> ClientRequestSender {
|
||||
self.client_tx.clone()
|
||||
}
|
||||
|
||||
pub fn mix_rx(&self) -> BatchMixMessageSender {
|
||||
self.mix_tx.clone()
|
||||
) -> (
|
||||
MixTrafficController,
|
||||
BatchMixMessageSender,
|
||||
ClientRequestSender,
|
||||
) {
|
||||
let (message_sender, message_receiver) =
|
||||
tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE);
|
||||
let (client_sender, client_receiver) = tokio::sync::mpsc::channel(8);
|
||||
(
|
||||
MixTrafficController {
|
||||
gateway_transceiver,
|
||||
mix_rx: message_receiver,
|
||||
client_rx: client_receiver,
|
||||
consecutive_gateway_failure_count: 0,
|
||||
shutdown_token,
|
||||
},
|
||||
message_sender,
|
||||
client_sender,
|
||||
)
|
||||
}
|
||||
|
||||
async fn on_messages(
|
||||
@@ -144,26 +145,34 @@ impl MixTrafficController {
|
||||
trace!("MixTrafficController: Received shutdown");
|
||||
break;
|
||||
}
|
||||
// mix_rx should never error out as we're holding one instance of the sender
|
||||
|
||||
Some(mix_packets) = self.mix_rx.recv() => {
|
||||
if let Err(err) = self.on_messages(mix_packets).await {
|
||||
error!("Failed to send sphinx packet(s) to the gateway: {err}");
|
||||
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
|
||||
// Disconnect from the gateway. If we should try to re-connect
|
||||
// is handled at a higher layer.
|
||||
error!("Failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead");
|
||||
// Do we need to handle the embedded mixnet client case
|
||||
// separately?
|
||||
self.event_tx.send(MixnetClientEvent::Traffic(MixTrafficEvent::FailedSendingSphinx));
|
||||
break;
|
||||
mix_packets = self.mix_rx.recv() => match mix_packets {
|
||||
Some(mix_packets) => {
|
||||
if let Err(err) = self.on_messages(mix_packets).await {
|
||||
error!("Failed to send sphinx packet(s) to the gateway: {err}");
|
||||
if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT {
|
||||
// Disconnect from the gateway. If we should try to re-connect
|
||||
// is handled at a higher layer.
|
||||
error!("Failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead");
|
||||
// Do we need to handle the embedded mixnet client case
|
||||
// separately?
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
trace!("MixTrafficController: Stopping since channel closed");
|
||||
break;
|
||||
}
|
||||
},
|
||||
client_request = self.client_rx.recv() => match client_request {
|
||||
Some(client_request) => {
|
||||
self.on_client_request(client_request).await;
|
||||
},
|
||||
None => {
|
||||
trace!("MixTrafficController, client request channel closed");
|
||||
break
|
||||
}
|
||||
},
|
||||
// client_rx should never error out as we're holding one instance of the sender
|
||||
Some(client_request) = self.client_rx.recv() => {
|
||||
self.on_client_request(client_request).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
debug!("MixTrafficController: Exiting");
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
pub mod base_client;
|
||||
pub mod cover_traffic_stream;
|
||||
pub(crate) mod event_control;
|
||||
pub(crate) mod helpers;
|
||||
pub mod inbound_messages;
|
||||
pub mod key_manager;
|
||||
|
||||
+1
-55
@@ -70,7 +70,6 @@ where
|
||||
.send_reply(recipient_tag, data, lane, max_retransmissions);
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn handle_plain_message(
|
||||
&mut self,
|
||||
recipient: Recipient,
|
||||
@@ -78,27 +77,16 @@ where
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
max_retransmissions: Option<u32>,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>,
|
||||
) {
|
||||
if let Err(err) = self
|
||||
.message_handler
|
||||
.try_send_plain_message(
|
||||
recipient,
|
||||
content,
|
||||
lane,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
)
|
||||
.try_send_plain_message(recipient, content, lane, packet_type, max_retransmissions)
|
||||
.await
|
||||
{
|
||||
warn!("failed to send a plain message - {err}")
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn handle_repliable_message(
|
||||
&mut self,
|
||||
recipient: Recipient,
|
||||
@@ -107,8 +95,6 @@ where
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
max_retransmissions: Option<u32>,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>,
|
||||
) {
|
||||
if let Err(err) = self
|
||||
.message_handler
|
||||
@@ -119,8 +105,6 @@ where
|
||||
lane,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
@@ -129,36 +113,20 @@ where
|
||||
}
|
||||
|
||||
#[allow(clippy::panic)]
|
||||
#[instrument(skip_all)]
|
||||
async fn on_input_message(&mut self, msg: InputMessage) {
|
||||
#[cfg(feature = "otel")]
|
||||
let trace_id = msg.trace_id();
|
||||
#[cfg(feature = "otel")]
|
||||
if let Some(tid) = trace_id {
|
||||
tracing::info!("Processing input message with trace_id: {:?}", tid);
|
||||
}
|
||||
|
||||
match msg {
|
||||
InputMessage::Regular {
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
max_retransmissions,
|
||||
..
|
||||
} => {
|
||||
#[cfg(feature = "otel")]
|
||||
info!(
|
||||
"Handling regular input message with trace_id: {:?}",
|
||||
trace_id
|
||||
);
|
||||
self.handle_plain_message(
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
PacketType::Mix,
|
||||
max_retransmissions,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -168,13 +136,7 @@ where
|
||||
reply_surbs,
|
||||
lane,
|
||||
max_retransmissions,
|
||||
..
|
||||
} => {
|
||||
#[cfg(feature = "otel")]
|
||||
tracing::info!(
|
||||
"Handling anonymous input message with trace_id: {:?}",
|
||||
trace_id
|
||||
);
|
||||
self.handle_repliable_message(
|
||||
recipient,
|
||||
data,
|
||||
@@ -182,8 +144,6 @@ where
|
||||
lane,
|
||||
PacketType::Mix,
|
||||
max_retransmissions,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -193,8 +153,6 @@ where
|
||||
lane,
|
||||
max_retransmissions,
|
||||
} => {
|
||||
#[cfg(feature = "otel")]
|
||||
info!("Handling reply input message with trace_id: {:?}", trace_id);
|
||||
self.handle_reply(recipient_tag, data, lane, max_retransmissions)
|
||||
.await;
|
||||
}
|
||||
@@ -208,21 +166,13 @@ where
|
||||
data,
|
||||
lane,
|
||||
max_retransmissions,
|
||||
..
|
||||
} => {
|
||||
#[cfg(feature = "otel")]
|
||||
tracing::info!(
|
||||
"Handling regular input message with trace_id: {:?}",
|
||||
trace_id
|
||||
);
|
||||
self.handle_plain_message(
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -232,7 +182,6 @@ where
|
||||
reply_surbs,
|
||||
lane,
|
||||
max_retransmissions,
|
||||
..
|
||||
} => {
|
||||
self.handle_repliable_message(
|
||||
recipient,
|
||||
@@ -241,8 +190,6 @@ where
|
||||
lane,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -266,7 +213,6 @@ where
|
||||
};
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn run(&mut self, shutdown_token: ShutdownToken) {
|
||||
debug!("Started InputMessageListener with graceful shutdown support");
|
||||
|
||||
|
||||
+1
-7
@@ -60,13 +60,7 @@ where
|
||||
|
||||
// TODO: Figure out retransmission packet type signaling
|
||||
self.message_handler
|
||||
.try_prepare_single_chunk_for_sending(
|
||||
packet_recipient,
|
||||
chunk_data,
|
||||
packet_type,
|
||||
#[cfg(feature = "otel")]
|
||||
None
|
||||
)
|
||||
.try_prepare_single_chunk_for_sending(packet_recipient, chunk_data, packet_type)
|
||||
.await
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use thiserror::Error;
|
||||
use tracing::{debug, error, info, instrument, trace, warn};
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
|
||||
// TODO: move that error elsewhere since it seems to be contaminating different files
|
||||
#[derive(Debug, Error)]
|
||||
@@ -476,7 +476,6 @@ where
|
||||
self.forward_messages(msgs, lane).await;
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn try_send_plain_message(
|
||||
&mut self,
|
||||
recipient: Recipient,
|
||||
@@ -484,8 +483,6 @@ where
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
max_retransmissions: Option<u32>,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>,
|
||||
) -> Result<(), PreparationError> {
|
||||
let message = NymMessage::new_plain(message);
|
||||
self.try_split_and_send_non_reply_message(
|
||||
@@ -494,13 +491,10 @@ where
|
||||
lane,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn try_split_and_send_non_reply_message(
|
||||
&mut self,
|
||||
message: NymMessage,
|
||||
@@ -508,8 +502,6 @@ where
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
max_retransmissions: Option<u32>,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>,
|
||||
) -> Result<(), PreparationError> {
|
||||
debug!("Sending non-reply message with packet type {packet_type}");
|
||||
// TODO: I really dislike existence of this assertion, it implies code has to be re-organised
|
||||
@@ -542,8 +534,6 @@ where
|
||||
&self.config.ack_key,
|
||||
&recipient,
|
||||
packet_type,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
)?;
|
||||
|
||||
let real_message = RealMessage::new(
|
||||
@@ -595,8 +585,6 @@ where
|
||||
TransmissionLane::AdditionalReplySurbs,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
#[cfg(feature = "otel")]
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -614,8 +602,6 @@ where
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
max_retransmissions: Option<u32>,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>,
|
||||
) -> Result<(), SurbWrappedPreparationError> {
|
||||
debug!("Sending message with reply SURBs with packet type {packet_type}");
|
||||
let sender_tag = self.get_or_create_sender_tag(&recipient);
|
||||
@@ -639,8 +625,6 @@ where
|
||||
lane,
|
||||
packet_type,
|
||||
max_retransmissions,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -655,8 +639,6 @@ where
|
||||
recipient: Recipient,
|
||||
chunk: Fragment,
|
||||
packet_type: PacketType,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>,
|
||||
) -> Result<PreparedFragment, PreparationError> {
|
||||
debug!("Sending single chunk with packet type {packet_type}");
|
||||
let topology_permit = self.topology_access.get_read_permit().await;
|
||||
@@ -668,8 +650,6 @@ where
|
||||
&self.config.ack_key,
|
||||
&recipient,
|
||||
packet_type,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
)?;
|
||||
|
||||
Ok(prepared_fragment)
|
||||
|
||||
@@ -80,8 +80,6 @@ impl StatisticsControl {
|
||||
stats_report.into(),
|
||||
TransmissionLane::General,
|
||||
None,
|
||||
#[cfg(feature = "otel")]
|
||||
None,
|
||||
);
|
||||
if let Err(err) = self.report_tx.send(report_message).await {
|
||||
tracing::error!("Failed to report client stats: {err:?}");
|
||||
|
||||
@@ -45,7 +45,6 @@ type WsConn = JSWebsocket;
|
||||
|
||||
const CONCURRENT_GATEWAYS_MEASURED: usize = 20;
|
||||
const MEASUREMENTS: usize = 3;
|
||||
const DEFAULT_NYM_API_RETRIES: usize = 3;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
const CONN_TIMEOUT: Duration = Duration::from_millis(1500);
|
||||
@@ -133,27 +132,25 @@ impl<'a, G: ConnectableGateway> GatewayWithLatency<'a, G> {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn gateways_for_init(
|
||||
pub async fn gateways_for_init<R: Rng>(
|
||||
rng: &mut R,
|
||||
nym_apis: &[Url],
|
||||
user_agent: Option<UserAgent>,
|
||||
minimum_performance: u8,
|
||||
ignore_epoch_roles: bool,
|
||||
retry_count: Option<usize>,
|
||||
) -> Result<Vec<RoutingNode>, ClientCoreError> {
|
||||
// Build client with ALL URLs for fallback support
|
||||
let nym_api_urls: Vec<nym_http_api_client::Url> = nym_apis
|
||||
.iter()
|
||||
.map(|url| nym_http_api_client::Url::from(url.clone()))
|
||||
.collect();
|
||||
let nym_api = nym_apis
|
||||
.choose(rng)
|
||||
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
||||
|
||||
if nym_api_urls.is_empty() {
|
||||
return Err(ClientCoreError::ListOfNymApisIsEmpty);
|
||||
}
|
||||
|
||||
let retry_count = retry_count.unwrap_or(DEFAULT_NYM_API_RETRIES);
|
||||
let mut builder = nym_http_api_client::ClientBuilder::new_with_urls(nym_api_urls.clone())
|
||||
.with_retries(retry_count)
|
||||
.with_bincode();
|
||||
// Use the unified HTTP client directly with optional user agent
|
||||
let mut builder = nym_http_api_client::Client::builder(nym_api.clone())
|
||||
.map_err(|e| {
|
||||
ClientCoreError::ValidatorClientError(nym_validator_client::ValidatorClientError::from(
|
||||
e,
|
||||
))
|
||||
})?
|
||||
.with_bincode(); // Use bincode for better performance
|
||||
|
||||
if let Some(user_agent) = user_agent {
|
||||
builder = builder.with_user_agent(user_agent);
|
||||
@@ -163,7 +160,7 @@ pub async fn gateways_for_init(
|
||||
ClientCoreError::ValidatorClientError(nym_validator_client::ValidatorClientError::from(e))
|
||||
})?;
|
||||
|
||||
tracing::debug!("Fetching list of gateways from: {:?}", nym_api_urls);
|
||||
tracing::debug!("Fetching list of gateways from: {nym_api}");
|
||||
|
||||
// Use our helper to handle pagination
|
||||
let gateways = get_all_basic_entry_nodes_with_metadata(&client, true)
|
||||
@@ -175,15 +172,17 @@ pub async fn gateways_for_init(
|
||||
|
||||
// filter out gateways below minimum performance and ones that could operate as a mixnode
|
||||
// (we don't want instability)
|
||||
let valid_gateways: Vec<RoutingNode> = gateways
|
||||
let valid_gateways = gateways
|
||||
.iter()
|
||||
.filter(|g| ignore_epoch_roles || !g.supported_roles.mixnode)
|
||||
.filter(|g| g.performance.round_to_integer() >= minimum_performance)
|
||||
.filter_map(|gateway| gateway.try_into().ok())
|
||||
.collect();
|
||||
.collect::<Vec<_>>();
|
||||
tracing::debug!("After checking validity: {}", valid_gateways.len());
|
||||
tracing::trace!("Valid gateways: {valid_gateways:#?}");
|
||||
|
||||
tracing::info!(
|
||||
"Found {} valid gateways after filtering",
|
||||
"and {} after validity and performance filtering",
|
||||
valid_gateways.len()
|
||||
);
|
||||
|
||||
@@ -346,20 +345,13 @@ pub(super) fn get_specified_gateway(
|
||||
must_use_tls: bool,
|
||||
) -> Result<RoutingNode, ClientCoreError> {
|
||||
tracing::debug!("Requesting specified gateway: {gateway_identity}");
|
||||
|
||||
let user_gateway = ed25519::PublicKey::from_base58_string(gateway_identity)
|
||||
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
|
||||
|
||||
let gateway = gateways
|
||||
.iter()
|
||||
.find(|gateway| gateway.identity_key == user_gateway)
|
||||
.ok_or_else(|| {
|
||||
tracing::debug!(
|
||||
"Gateway {gateway_identity} not found in {} available gateways",
|
||||
gateways.len()
|
||||
);
|
||||
ClientCoreError::NoGatewayWithId(gateway_identity.to_string())
|
||||
})?;
|
||||
.ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string()))?;
|
||||
|
||||
let Some(entry_details) = gateway.entry.as_ref() else {
|
||||
return Err(ClientCoreError::UnsupportedEntry {
|
||||
@@ -422,52 +414,3 @@ pub(super) async fn register_with_gateway(
|
||||
authenticated_ephemeral_client: gateway_client,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use url::Url;
|
||||
|
||||
#[test]
|
||||
fn test_single_url_builds_without_retries() {
|
||||
let urls = [Url::parse("https://api.nym.com").unwrap()];
|
||||
|
||||
let nym_api_urls: Vec<nym_http_api_client::Url> = urls
|
||||
.iter()
|
||||
.map(|url| nym_http_api_client::Url::from(url.clone()))
|
||||
.collect();
|
||||
|
||||
assert_eq!(nym_api_urls.len(), 1, "Should have exactly one URL");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_urls_prepared_for_retries() {
|
||||
let urls = vec![
|
||||
Url::parse("https://api1.nym.com").unwrap(),
|
||||
Url::parse("https://api2.nym.com").unwrap(),
|
||||
Url::parse("https://api3.nym.com").unwrap(),
|
||||
];
|
||||
|
||||
let nym_api_urls: Vec<nym_http_api_client::Url> = urls
|
||||
.iter()
|
||||
.map(|url| nym_http_api_client::Url::from(url.clone()))
|
||||
.collect();
|
||||
|
||||
assert_eq!(nym_api_urls.len(), 3, "Should have all three URLs");
|
||||
assert!(
|
||||
nym_api_urls.len() > 1,
|
||||
"Multiple URLs trigger retry behavior"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_url_list_is_detected() {
|
||||
let urls: Vec<Url> = vec![];
|
||||
|
||||
let nym_api_urls: Vec<nym_http_api_client::Url> = urls
|
||||
.iter()
|
||||
.map(|url| nym_http_api_client::Url::from(url.clone()))
|
||||
.collect();
|
||||
|
||||
assert!(nym_api_urls.is_empty(), "Empty list should remain empty");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1043,12 +1043,6 @@ impl<C, St> GatewayClient<C, St> {
|
||||
}
|
||||
|
||||
// Note: this requires prior authentication
|
||||
#[instrument(skip_all,
|
||||
fields(
|
||||
gateway = %self.gateway_identity,
|
||||
gateway_address = %self.gateway_address
|
||||
)
|
||||
)]
|
||||
pub fn start_listening_for_mixnet_messages(&mut self) -> Result<(), GatewayClientError> {
|
||||
if !self.authenticated {
|
||||
return Err(GatewayClientError::NotAuthenticated);
|
||||
|
||||
@@ -267,7 +267,6 @@ impl Client {
|
||||
}
|
||||
|
||||
impl SendWithoutResponse for Client {
|
||||
#[instrument(skip(self, packet))]
|
||||
fn send_without_response(&self, packet: MixPacket) -> io::Result<()> {
|
||||
let address = packet.next_hop_address();
|
||||
trace!("Sending packet to {address}");
|
||||
|
||||
@@ -10,7 +10,7 @@ use cosmrs::tx;
|
||||
use cosmrs::tx::SignDoc;
|
||||
use nym_config::defaults;
|
||||
use thiserror::Error;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
type Secp256k1Keypair = (SigningKey, PublicKey);
|
||||
|
||||
@@ -128,20 +128,9 @@ impl DirectSecp256k1HdWallet {
|
||||
Ok(accounts)
|
||||
}
|
||||
|
||||
pub fn secret(&self) -> &bip39::Mnemonic {
|
||||
&self.secret
|
||||
}
|
||||
|
||||
#[deprecated(
|
||||
note = "use either .secret() for obtaining &bip39::Mnemonic or .mnemonic_string() for Zeroizing wrapper around the String"
|
||||
)]
|
||||
pub fn mnemonic(&self) -> String {
|
||||
self.secret.to_string()
|
||||
}
|
||||
|
||||
pub fn mnemonic_string(&self) -> Zeroizing<String> {
|
||||
Zeroizing::new(self.secret.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
||||
@@ -18,6 +18,6 @@ pub fn create_account(args: Args, prefix: &str) {
|
||||
let wallet = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic);
|
||||
|
||||
// Output address and mnemonics into separate lines for easier parsing
|
||||
println!("{}", wallet.mnemonic_string().as_str());
|
||||
println!("{}", wallet.mnemonic());
|
||||
println!("{}", wallet.try_derive_accounts().unwrap()[0].address());
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ nym-contracts-common = { path = "../cosmwasm-smart-contracts/contracts-common",
|
||||
bs58 = { workspace = true }
|
||||
|
||||
|
||||
lazy_static = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
rand_chacha = { workspace = true }
|
||||
rand_core = { workspace = true }
|
||||
|
||||
@@ -13,9 +13,9 @@ use rand::CryptoRng;
|
||||
use rand_core::RngCore;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Neg;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Ciphertexts {
|
||||
pub rr: [G1Projective; NUM_CHUNKS],
|
||||
pub ss: [G1Projective; NUM_CHUNKS],
|
||||
@@ -164,7 +164,8 @@ impl Ciphertexts {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Zeroize, ZeroizeOnDrop)]
|
||||
#[derive(Zeroize)]
|
||||
#[zeroize(drop)]
|
||||
/// Randomness generated during ciphertext generation that is required for proofs of knowledge.
|
||||
///
|
||||
/// It must be handled with extreme care as its misuse might help malicious parties to recover
|
||||
@@ -398,7 +399,7 @@ pub fn baby_step_giant_step(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::bte::{keygen, setup, BSGS_TABLE};
|
||||
use crate::bte::{keygen, setup, DEFAULT_BSGS_TABLE};
|
||||
use rand_core::SeedableRng;
|
||||
|
||||
fn verify_hazmat_rand(ciphertext: &Ciphertexts, randomness: &HazmatRandomness) {
|
||||
@@ -456,6 +457,8 @@ mod tests {
|
||||
let (decryption_key1, public_key1) = keygen(¶ms, &mut rng);
|
||||
let (decryption_key2, public_key2) = keygen(¶ms, &mut rng);
|
||||
|
||||
let lookup_table = &DEFAULT_BSGS_TABLE;
|
||||
|
||||
for _ in 0..10 {
|
||||
let m1 = Share::random(&mut rng);
|
||||
let m2 = Share::random(&mut rng);
|
||||
@@ -464,12 +467,22 @@ mod tests {
|
||||
let (ciphertext, hazmat) = encrypt_shares(shares, ¶ms, &mut rng);
|
||||
verify_hazmat_rand(&ciphertext, &hazmat);
|
||||
|
||||
let recovered1 =
|
||||
decrypt_share(¶ms, &decryption_key1, 0, &ciphertext, Some(&BSGS_TABLE))
|
||||
.unwrap();
|
||||
let recovered2 =
|
||||
decrypt_share(¶ms, &decryption_key2, 1, &ciphertext, Some(&BSGS_TABLE))
|
||||
.unwrap();
|
||||
let recovered1 = decrypt_share(
|
||||
¶ms,
|
||||
&decryption_key1,
|
||||
0,
|
||||
&ciphertext,
|
||||
Some(lookup_table),
|
||||
)
|
||||
.unwrap();
|
||||
let recovered2 = decrypt_share(
|
||||
¶ms,
|
||||
&decryption_key2,
|
||||
1,
|
||||
&ciphertext,
|
||||
Some(lookup_table),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(m1, recovered1);
|
||||
assert_eq!(m2, recovered2);
|
||||
}
|
||||
@@ -485,6 +498,8 @@ mod tests {
|
||||
let (decryption_key1, public_key1) = keygen(¶ms, &mut rng);
|
||||
let (decryption_key2, public_key2) = keygen(¶ms, &mut rng);
|
||||
|
||||
let lookup_table = &DEFAULT_BSGS_TABLE;
|
||||
|
||||
for _ in 0..10 {
|
||||
let m1 = Share::random(&mut rng);
|
||||
let m2 = Share::random(&mut rng);
|
||||
@@ -493,12 +508,22 @@ mod tests {
|
||||
let (ciphertext, hazmat) = encrypt_shares(shares, ¶ms, &mut rng);
|
||||
verify_hazmat_rand(&ciphertext, &hazmat);
|
||||
|
||||
let recovered1 =
|
||||
decrypt_share(¶ms, &decryption_key1, 0, &ciphertext, Some(&BSGS_TABLE))
|
||||
.unwrap();
|
||||
let recovered2 =
|
||||
decrypt_share(¶ms, &decryption_key2, 1, &ciphertext, Some(&BSGS_TABLE))
|
||||
.unwrap();
|
||||
let recovered1 = decrypt_share(
|
||||
¶ms,
|
||||
&decryption_key1,
|
||||
0,
|
||||
&ciphertext,
|
||||
Some(lookup_table),
|
||||
)
|
||||
.unwrap();
|
||||
let recovered2 = decrypt_share(
|
||||
¶ms,
|
||||
&decryption_key2,
|
||||
1,
|
||||
&ciphertext,
|
||||
Some(lookup_table),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(m1, recovered1);
|
||||
assert_eq!(m2, recovered2);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use group::GroupEncoding;
|
||||
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
|
||||
use rand::CryptoRng;
|
||||
use rand_core::RngCore;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
// produces public key and a decryption key for the root of the tree
|
||||
pub fn keygen(
|
||||
@@ -48,7 +48,7 @@ pub fn keygen(
|
||||
(dk, key_with_proof)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Zeroize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct PublicKey(pub(crate) G1Projective);
|
||||
|
||||
impl PublicKey {
|
||||
@@ -57,7 +57,7 @@ impl PublicKey {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct PublicKeyWithProof {
|
||||
pub(crate) key: PublicKey,
|
||||
pub(crate) proof: ProofOfDiscreteLog,
|
||||
@@ -136,7 +136,8 @@ impl PublicKeyWithProof {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Zeroize, ZeroizeOnDrop)]
|
||||
#[derive(Debug, Zeroize)]
|
||||
#[zeroize(drop)]
|
||||
#[cfg_attr(test, derive(PartialEq, Eq))]
|
||||
pub struct DecryptionKey {
|
||||
// g1^rho
|
||||
@@ -241,7 +242,6 @@ impl DecryptionKey {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Zeroize, ZeroizeOnDrop)]
|
||||
pub struct KeyPair {
|
||||
pub(crate) private_key: DecryptionKey,
|
||||
pub(crate) public_key: PublicKeyWithProof,
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use crate::bte::encryption::BabyStepGiantStepLookup;
|
||||
use crate::utils::hash_g2;
|
||||
use crate::{Chunk, Share};
|
||||
use bls12_381::{G1Affine, G2Affine, G2Prepared, G2Projective, Gt};
|
||||
use group::Curve;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
pub mod encryption;
|
||||
pub mod keys;
|
||||
@@ -18,12 +16,14 @@ pub mod proof_sharing;
|
||||
pub use encryption::{decrypt_share, encrypt_shares, Ciphertexts};
|
||||
pub use keys::{keygen, DecryptionKey, PublicKey, PublicKeyWithProof};
|
||||
|
||||
pub(crate) static PAIRING_BASE: LazyLock<Gt> =
|
||||
LazyLock::new(|| bls12_381::pairing(&G1Affine::generator(), &G2Affine::generator()));
|
||||
pub(crate) static G2_GENERATOR_PREPARED: LazyLock<G2Prepared> =
|
||||
LazyLock::new(|| G2Prepared::from(G2Affine::generator()));
|
||||
pub static BSGS_TABLE: LazyLock<BabyStepGiantStepLookup> =
|
||||
LazyLock::new(BabyStepGiantStepLookup::default);
|
||||
lazy_static! {
|
||||
pub(crate) static ref PAIRING_BASE: Gt =
|
||||
bls12_381::pairing(&G1Affine::generator(), &G2Affine::generator());
|
||||
pub(crate) static ref G2_GENERATOR_PREPARED: G2Prepared =
|
||||
G2Prepared::from(G2Affine::generator());
|
||||
pub(crate) static ref DEFAULT_BSGS_TABLE: encryption::BabyStepGiantStepLookup =
|
||||
encryption::BabyStepGiantStepLookup::default();
|
||||
}
|
||||
|
||||
// Domain tries to follow guidelines specified by:
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
|
||||
|
||||
@@ -12,7 +12,6 @@ use ff::Field;
|
||||
use group::{Group, GroupEncoding};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use rand_core::{RngCore, SeedableRng};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
const CHUNKING_ORACLE_DOMAIN: &[u8] =
|
||||
b"NYM_COCONUT_NIDKG_V01_CS01_SHA-256_CHACHA20_CHUNKING_ORACLE";
|
||||
@@ -68,7 +67,7 @@ impl<'a> Instance<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ProofOfChunking {
|
||||
y0: G1Projective,
|
||||
bb: Vec<G1Projective>,
|
||||
|
||||
@@ -7,14 +7,14 @@ use ff::Field;
|
||||
use group::GroupEncoding;
|
||||
use rand::CryptoRng;
|
||||
use rand_core::RngCore;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
// Domain tries to follow guidelines specified by:
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
|
||||
const DISCRETE_LOG_DOMAIN: &[u8] =
|
||||
b"NYM_COCONUT_NIDKG_V01_CS01_WITH_BLS12381_XMD:SHA-256_SSWU_RO_PROOF_DISCRETE_LOG";
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ProofOfDiscreteLog {
|
||||
pub(crate) rand_commitment: G1Projective,
|
||||
pub(crate) response: Scalar,
|
||||
@@ -52,9 +52,9 @@ impl ProofOfDiscreteLog {
|
||||
let public_bytes = public.to_bytes();
|
||||
let rand_commit_bytes = rand_commit.to_bytes();
|
||||
|
||||
let mut bytes = [0u8; 96];
|
||||
bytes[0..48].copy_from_slice(public_bytes.as_ref());
|
||||
bytes[48..96].copy_from_slice(rand_commit_bytes.as_ref());
|
||||
let mut bytes = Vec::with_capacity(96);
|
||||
bytes.extend_from_slice(public_bytes.as_ref());
|
||||
bytes.extend_from_slice(rand_commit_bytes.as_ref());
|
||||
|
||||
hash_to_scalar(bytes, DISCRETE_LOG_DOMAIN)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ use group::GroupEncoding;
|
||||
use rand::CryptoRng;
|
||||
use rand_core::RngCore;
|
||||
use std::collections::BTreeMap;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
// Domain tries to follow guidelines specified by:
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
|
||||
@@ -78,7 +77,7 @@ impl<'a> Instance<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ProofOfSecretSharing {
|
||||
ff: G1Projective,
|
||||
aa: G2Projective,
|
||||
|
||||
@@ -18,7 +18,7 @@ use rand_core::RngCore;
|
||||
use std::collections::BTreeMap;
|
||||
use zeroize::Zeroize;
|
||||
|
||||
#[derive(Clone, Debug, Zeroize)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq, Eq))]
|
||||
pub struct RecoveredVerificationKeys {
|
||||
pub recovered_master: G2Projective,
|
||||
@@ -83,7 +83,7 @@ impl RecoveredVerificationKeys {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Zeroize)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Dealing {
|
||||
pub public_coefficients: PublicCoefficients,
|
||||
pub ciphertexts: Ciphertexts,
|
||||
|
||||
@@ -9,9 +9,9 @@ use group::GroupEncoding;
|
||||
use rand::CryptoRng;
|
||||
use rand_core::RngCore;
|
||||
use std::ops::{Add, Index, IndexMut};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct PublicCoefficients {
|
||||
pub(crate) coefficients: Vec<G2Projective>,
|
||||
}
|
||||
@@ -111,7 +111,8 @@ impl IndexMut<usize> for PublicCoefficients {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Zeroize)]
|
||||
#[zeroize(drop)]
|
||||
pub struct Polynomial {
|
||||
coefficients: Vec<Scalar>,
|
||||
}
|
||||
|
||||
@@ -6,13 +6,14 @@ use crate::error::DkgError;
|
||||
use crate::interpolation::perform_lagrangian_interpolation_at_origin;
|
||||
use crate::NodeIndex;
|
||||
use bls12_381::Scalar;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
// if this type is changed, one must ensure all values can fit in it
|
||||
pub type Chunk = u16;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)]
|
||||
#[derive(PartialEq, Eq, Debug, Zeroize)]
|
||||
#[cfg_attr(test, derive(Clone))]
|
||||
#[zeroize(drop)]
|
||||
pub struct Share(pub(crate) Scalar);
|
||||
|
||||
pub fn combine_shares(shares: Vec<Share>, node_indices: &[NodeIndex]) -> Result<Scalar, DkgError> {
|
||||
@@ -65,8 +66,9 @@ impl From<Scalar> for Share {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Zeroize, ZeroizeOnDrop)]
|
||||
#[derive(Default, Zeroize)]
|
||||
#[cfg_attr(test, derive(Clone))]
|
||||
#[zeroize(drop)]
|
||||
pub(crate) struct ChunkedShare {
|
||||
pub(crate) chunks: [Chunk; NUM_CHUNKS],
|
||||
}
|
||||
|
||||
@@ -19,11 +19,11 @@ serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
strum = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true, features = ["log"] }
|
||||
time = { workspace = true }
|
||||
subtle = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
nym-bin-common = { path = "../bin-common" }
|
||||
nym-crypto = { path = "../crypto", features = ["aead", "hashing"] }
|
||||
nym-pemstore = { path = "../pemstore" }
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
@@ -34,11 +34,6 @@ nym-task = { path = "../task" }
|
||||
nym-credentials = { path = "../credentials" }
|
||||
nym-credentials-interface = { path = "../credentials-interface" }
|
||||
|
||||
opentelemetry = { workspace = true, features = ["trace"], optional = true }
|
||||
opentelemetry_sdk = { workspace = true, optional = true }
|
||||
tracing-opentelemetry = { workspace = true, optional = true }
|
||||
tracing = { workspace = true, features = ["std", "attributes", "tracing-attributes"] }
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
|
||||
workspace = true
|
||||
features = ["time"]
|
||||
@@ -56,12 +51,3 @@ anyhow = { workspace = true }
|
||||
nym-compact-ecash = { path = "../nym_offline_compact_ecash" } # we need specific imports in tests
|
||||
nym-test-utils = { path = "../test-utils" }
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
otel = [
|
||||
"nym-bin-common/otel",
|
||||
"opentelemetry",
|
||||
"opentelemetry_sdk",
|
||||
"tracing-opentelemetry",
|
||||
]
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
use crate::{AuthenticationFailure, GatewayRequestsError, SharedGatewayKey};
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::iter;
|
||||
use std::time::Duration;
|
||||
use subtle::ConstantTimeEq;
|
||||
@@ -17,9 +16,6 @@ pub struct AuthenticateRequest {
|
||||
pub content: AuthenticateRequestContent,
|
||||
|
||||
pub request_signature: ed25519::Signature,
|
||||
|
||||
#[serde(default)]
|
||||
pub otel_context: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
||||
impl AuthenticateRequest {
|
||||
@@ -27,7 +23,6 @@ impl AuthenticateRequest {
|
||||
protocol_version: u8,
|
||||
shared_key: &SharedGatewayKey,
|
||||
identity_keys: &ed25519::KeyPair,
|
||||
otel_context: Option<HashMap<String, String>>,
|
||||
) -> Result<AuthenticateRequest, GatewayRequestsError> {
|
||||
let content = AuthenticateRequestContent::new(
|
||||
protocol_version,
|
||||
@@ -40,7 +35,6 @@ impl AuthenticateRequest {
|
||||
Ok(AuthenticateRequest {
|
||||
content,
|
||||
request_signature,
|
||||
otel_context,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -8,16 +8,12 @@ use crate::{
|
||||
AUTHENTICATE_V2_PROTOCOL_VERSION, CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION,
|
||||
INITIAL_PROTOCOL_VERSION,
|
||||
};
|
||||
#[cfg(feature = "otel")]
|
||||
use nym_bin_common::opentelemetry::context::ContextCarrier;
|
||||
use nym_credentials_interface::CredentialSpendingData;
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_sphinx::DestinationAddressBytes;
|
||||
use nym_statistics_common::types::SessionType;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use tracing::{instrument, warn};
|
||||
use tungstenite::Message;
|
||||
|
||||
pub mod authenticate;
|
||||
@@ -80,10 +76,6 @@ pub enum ClientControlRequest {
|
||||
address: String,
|
||||
enc_address: String,
|
||||
iv: String,
|
||||
/// this is a trace id that is used in testing and performance verification
|
||||
/// in mainnet, this will always be set to None
|
||||
#[serde(default)]
|
||||
otel_context: Option<HashMap<String, String>>,
|
||||
},
|
||||
|
||||
AuthenticateV2(Box<AuthenticateRequest>),
|
||||
@@ -135,25 +127,14 @@ impl ClientControlRequest {
|
||||
let nonce = shared_key.random_nonce_or_iv();
|
||||
let ciphertext = shared_key.encrypt_naive(address.as_bytes_ref(), Some(&nonce))?;
|
||||
|
||||
#[cfg(feature = "otel")]
|
||||
let context_carrier = {
|
||||
let context = opentelemetry::Context::current();
|
||||
ContextCarrier::new_with_current_context(context).into_map()
|
||||
};
|
||||
|
||||
Ok(ClientControlRequest::Authenticate {
|
||||
protocol_version,
|
||||
address: address.as_base58_string(),
|
||||
enc_address: bs58::encode(&ciphertext).into_string(),
|
||||
iv: bs58::encode(&nonce).into_string(),
|
||||
#[cfg(feature = "otel")]
|
||||
otel_context: Some(context_carrier),
|
||||
#[cfg(not(feature = "otel"))]
|
||||
otel_context: None,
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub fn new_authenticate_v2(
|
||||
shared_key: &SharedGatewayKey,
|
||||
identity_keys: &ed25519::KeyPair,
|
||||
@@ -161,25 +142,8 @@ impl ClientControlRequest {
|
||||
// if we're using v2 authentication, we must announce at least that protocol version
|
||||
let protocol_version = AUTHENTICATE_V2_PROTOCOL_VERSION;
|
||||
|
||||
#[cfg(feature = "otel")]
|
||||
let context_carrier = {
|
||||
use nym_bin_common::opentelemetry::context::extract_trace_id_from_tracing_cx;
|
||||
use tracing_opentelemetry::OpenTelemetrySpanExt;
|
||||
|
||||
let current_span = tracing::Span::current();
|
||||
let otel_context = current_span.context();
|
||||
ContextCarrier::new_with_current_context(otel_context).into_map()
|
||||
};
|
||||
#[cfg(not(feature = "otel"))]
|
||||
let context_carrier: HashMap<String, String> = HashMap::new();
|
||||
|
||||
Ok(ClientControlRequest::AuthenticateV2(Box::new(
|
||||
AuthenticateRequest::new(
|
||||
protocol_version,
|
||||
shared_key,
|
||||
identity_keys,
|
||||
Some(context_carrier),
|
||||
)?,
|
||||
AuthenticateRequest::new(protocol_version, shared_key, identity_keys)?,
|
||||
)))
|
||||
}
|
||||
|
||||
|
||||
@@ -11,11 +11,9 @@ license.workspace = true
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
# TODO: Remove otel from default before release
|
||||
default=["tunneling"]
|
||||
tunneling=[]
|
||||
network-defaults = ["dep:nym-network-defaults"]
|
||||
otel = ["nym-bin-common/otel", "opentelemetry", "opentelemetry_sdk"]
|
||||
debug-inventory = ["nym-http-api-client-macro/debug-inventory"]
|
||||
|
||||
[dependencies]
|
||||
@@ -26,8 +24,6 @@ reqwest = { workspace = true, features = ["json", "gzip", "deflate", "brotli", "
|
||||
http.workspace = true
|
||||
url = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
opentelemetry = { workspace = true, optional = true }
|
||||
opentelemetry_sdk = { workspace = true, optional = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
serde_yaml = { workspace = true}
|
||||
@@ -57,3 +53,4 @@ features = ["tokio"]
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { workspace = true, features = ["rt", "macros"] }
|
||||
|
||||
|
||||
@@ -986,21 +986,6 @@ impl ApiClientCore for Client {
|
||||
|
||||
self.apply_hosts_to_req(&mut req);
|
||||
|
||||
// if opentelemetry is activated add the current trace context to the request
|
||||
#[cfg(feature = "otel")]
|
||||
{
|
||||
use nym_bin_common::opentelemetry::context::ContextCarrier;
|
||||
use opentelemetry::Context;
|
||||
|
||||
let carrier = ContextCarrier::new_with_current_context(Context::current());
|
||||
|
||||
if let Some(traceparent) = carrier.extract_traceparent() {
|
||||
if let Ok(header_value) = HeaderValue::from_str(&traceparent) {
|
||||
req.headers_mut().insert("traceparent", header_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut rb = RequestBuilder::from_parts(self.reqwest_client.clone(), req);
|
||||
|
||||
rb = rb
|
||||
|
||||
@@ -183,11 +183,6 @@ impl Url {
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the underlying URL
|
||||
pub fn inner_url(&self) -> &url::Url {
|
||||
&self.url
|
||||
}
|
||||
|
||||
/// Returns true if the URL has a front domain set
|
||||
pub fn has_front(&self) -> bool {
|
||||
if let Some(fronts) = &self.fronts {
|
||||
@@ -206,11 +201,6 @@ impl Url {
|
||||
.and_then(|url| url.host_str())
|
||||
}
|
||||
|
||||
/// Returns the fronts
|
||||
pub fn fronts(&self) -> Option<&[url::Url]> {
|
||||
self.fronts.as_deref()
|
||||
}
|
||||
|
||||
/// Return the string representation of the host (domain or IP address) for this URL, if any.
|
||||
pub fn host_str(&self) -> Option<&str> {
|
||||
self.url.host_str()
|
||||
|
||||
@@ -18,7 +18,6 @@ bytes = { workspace = true, optional = true }
|
||||
colored = { workspace = true, optional = true }
|
||||
futures = { workspace = true, optional = true }
|
||||
mime = { workspace = true, optional = true }
|
||||
nym-bin-common = { path = "../bin-common" }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
serde_yaml = { workspace = true, optional = true }
|
||||
@@ -50,8 +49,6 @@ middleware = [
|
||||
"zeroize"
|
||||
]
|
||||
|
||||
otel = ["nym-bin-common/otel"]
|
||||
|
||||
utoipa = ["dep:utoipa"]
|
||||
|
||||
[lints]
|
||||
|
||||
@@ -56,16 +56,6 @@ async fn log_request(
|
||||
|
||||
let host = header_map(request.headers().get(HOST), "Unknown Host".to_string());
|
||||
|
||||
// Extract traceparent from headers if it exists
|
||||
#[cfg(feature = "otel")]
|
||||
let traceparent = request
|
||||
.headers()
|
||||
.get("traceparent")
|
||||
.and_then(|h| h.to_str().ok())
|
||||
.map(|s| s.to_string());
|
||||
#[cfg(not(feature = "otel"))]
|
||||
let traceparent: Option<String> = None;
|
||||
|
||||
let start = Instant::now();
|
||||
// run request through all middleware, incl. extractors
|
||||
let res = next.run(request).await;
|
||||
@@ -92,10 +82,10 @@ async fn log_request(
|
||||
|
||||
match level {
|
||||
LogLevel::Debug => debug!(
|
||||
"[{addr} -> {host}] {method} '{uri}': {print_status} {time_taken} {agent_str}: {agent} traceparent: {traceparent:?}",
|
||||
"[{addr} -> {host}] {method} '{uri}': {print_status} {time_taken} {agent_str}: {agent}"
|
||||
),
|
||||
LogLevel::Info => info!(
|
||||
"[{addr} -> {host}] {method} '{uri}': {print_status} {time_taken} {agent_str}: {agent} traceparent: {traceparent:?}"
|
||||
"[{addr} -> {host}] {method} '{uri}': {print_status} {time_taken} {agent_str}: {agent}"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,3 @@ workspace = true
|
||||
## wasm-only dependencies
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-utils]
|
||||
path = "../wasm/utils"
|
||||
|
||||
[ features ]
|
||||
default = []
|
||||
otel = ["nym-sphinx/otel"]
|
||||
@@ -231,8 +231,6 @@ where
|
||||
&address,
|
||||
&address,
|
||||
PacketType::Mix,
|
||||
#[cfg(feature = "otel")]
|
||||
None,
|
||||
)?)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,12 @@ license = { workspace = true }
|
||||
repository = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
sphinx-packet = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
rand_distr = { workspace = true }
|
||||
rand_chacha = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
nym-bin-common = { path = "../bin-common" }
|
||||
nym-sphinx-acknowledgements = { path = "acknowledgements" }
|
||||
nym-sphinx-addressing = { path = "addressing" }
|
||||
nym-sphinx-anonymous-replies = { path = "anonymous-replies" }
|
||||
@@ -57,11 +55,3 @@ outfox = [
|
||||
"nym-sphinx-params/outfox",
|
||||
"nym-sphinx-types/outfox",
|
||||
]
|
||||
|
||||
otel = [
|
||||
"nym-bin-common/otel",
|
||||
"nym-sphinx-acknowledgements/otel",
|
||||
"nym-sphinx-addressing/otel",
|
||||
"nym-sphinx-cover/otel",
|
||||
"nym-sphinx-anonymous-replies/otel",
|
||||
]
|
||||
@@ -24,4 +24,3 @@ nym-topology = { path = "../../topology" }
|
||||
|
||||
[features]
|
||||
serde = ["dep:serde", "generic-array"]
|
||||
otel = ["nym-sphinx-addressing/otel"]
|
||||
|
||||
@@ -61,10 +61,7 @@ impl SurbAck {
|
||||
};
|
||||
|
||||
let delays = nym_sphinx_routing::generate_hop_delays(average_delay, route.len());
|
||||
#[cfg(not(feature = "otel"))]
|
||||
let destination = recipient.as_sphinx_destination();
|
||||
#[cfg(feature = "otel")]
|
||||
let destination = recipient.as_sphinx_destination(None);
|
||||
|
||||
let surb_ack_payload = prepare_identifier(rng, ack_key, marshaled_fragment_id);
|
||||
let packet_size = match packet_type {
|
||||
|
||||
@@ -8,20 +8,14 @@ license = { workspace = true }
|
||||
repository = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
nym-bin-common = { path = "../../bin-common", features = ["opentelemetry"] } # for trace id compression/decompression
|
||||
nym-crypto = { path = "../../crypto", features = ["asymmetric", "sphinx"] } # all addresses are expressed in terms on their crypto keys
|
||||
nym-sphinx-types = { path = "../types", features = ["sphinx"] } # we need to be able to refer to some types defined inside sphinx crate
|
||||
serde = { workspace = true } # implementing serialization/deserialization for some types, like `Recipient`
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = { workspace = true }
|
||||
nym-crypto = { path = "../../crypto", features = ["rand"] }
|
||||
bincode = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
otel = ["nym-bin-common/otel"]
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
@@ -153,28 +153,12 @@ impl Recipient {
|
||||
// TODO: Currently the `DestinationAddress` is equivalent to `ClientIdentity`, but perhaps
|
||||
// it shouldn't be? Maybe it should be (for example) H(`ClientIdentity || ClientEncryptionKey`)
|
||||
// instead? That is an open question.
|
||||
pub fn as_sphinx_destination(
|
||||
&self,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>
|
||||
) -> Destination {
|
||||
#[cfg(feature = "otel")]
|
||||
use nym_bin_common::opentelemetry::compact_id_generator::decompress_trace_id;
|
||||
#[cfg(feature = "otel")]
|
||||
let trace_id_16 = if let Some(trace_id) = trace_id {
|
||||
decompress_trace_id(&trace_id)
|
||||
} else {
|
||||
decompress_trace_id(&[0u8; 12])
|
||||
};
|
||||
|
||||
pub fn as_sphinx_destination(&self) -> Destination {
|
||||
// since the nym mix network differs slightly in design from loopix, we do not care
|
||||
// about "surb_id" field at all and just use the default value.
|
||||
Destination::new(
|
||||
self.client_identity.derive_destination_address(),
|
||||
#[cfg(not(feature = "otel"))]
|
||||
[0u8; 16],
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id_16
|
||||
Default::default(),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,3 @@ workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
rand_chacha = { workspace = true }
|
||||
|
||||
[ features ]
|
||||
default = []
|
||||
otel = ["nym-sphinx-addressing/otel"]
|
||||
@@ -82,9 +82,6 @@ impl ReplySurb {
|
||||
topology.random_route_to_egress(rng, recipient.gateway())?
|
||||
};
|
||||
let delays = nym_sphinx_routing::generate_hop_delays(average_delay, route.len());
|
||||
#[cfg(feature = "otel")]
|
||||
let destination = recipient.as_sphinx_destination(None);
|
||||
#[cfg(not(feature = "otel"))]
|
||||
let destination = recipient.as_sphinx_destination();
|
||||
|
||||
let mut surb_material = SURBMaterial::new(route, delays, destination);
|
||||
|
||||
@@ -20,6 +20,3 @@ nym-sphinx-params = { path = "../params" }
|
||||
nym-sphinx-routing = { path = "../routing" }
|
||||
nym-sphinx-types = { path = "../types" }
|
||||
nym-topology = { path = "../../topology" }
|
||||
|
||||
[features]
|
||||
otel = ["nym-sphinx-addressing/otel"]
|
||||
@@ -125,10 +125,7 @@ where
|
||||
|
||||
let route = topology.random_route_to_egress(rng, full_address.gateway())?;
|
||||
let delays = nym_sphinx_routing::generate_hop_delays(average_packet_delay, route.len());
|
||||
#[cfg(not(feature = "otel"))]
|
||||
let destination = full_address.as_sphinx_destination();
|
||||
#[cfg(feature = "otel")]
|
||||
let destination = full_address.as_sphinx_destination(None);
|
||||
|
||||
let rotation_id = topology.current_key_rotation();
|
||||
let sphinx_key_rotation = SphinxKeyRotation::from(rotation_id);
|
||||
|
||||
@@ -11,10 +11,8 @@ repository = { workspace = true }
|
||||
bytes = { workspace = true }
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
thiserror = { workspace = true }
|
||||
opentelemetry = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
nym-bin-common = { path = "../../bin-common" }
|
||||
nym-sphinx-types = { path = "../types", features = ["sphinx", "outfox"] }
|
||||
nym-sphinx-params = { path = "../params", features = ["sphinx", "outfox"] }
|
||||
nym-sphinx-forwarding = { path = "../forwarding" }
|
||||
@@ -23,7 +21,3 @@ nym-sphinx-acknowledgements = { path = "../acknowledgements" }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
otel = ["nym-bin-common/otel"]
|
||||
@@ -2,11 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::packet::FramedNymPacket;
|
||||
#[cfg(feature = "otel")]
|
||||
use nym_bin_common::opentelemetry::{
|
||||
compact_id_generator::decompress_trace_id, context::ManualContextPropagator,
|
||||
};
|
||||
|
||||
use nym_sphinx_acknowledgements::surb_ack::{SurbAck, SurbAckRecoveryError};
|
||||
use nym_sphinx_addressing::nodes::{NymNodeRoutingAddress, NymNodeRoutingAddressError};
|
||||
use nym_sphinx_forwarding::packet::MixPacket;
|
||||
@@ -19,9 +14,7 @@ use nym_sphinx_types::{
|
||||
};
|
||||
use std::fmt::Display;
|
||||
use thiserror::Error;
|
||||
#[cfg(feature = "otel")]
|
||||
use tracing::warn_span;
|
||||
use tracing::{debug, error, info, instrument, trace, warn};
|
||||
use tracing::{debug, error, info, trace};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MixProcessingResultData {
|
||||
@@ -161,7 +154,6 @@ impl PartiallyUnwrappedPacket {
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub fn finalise_unwrapping(self) -> Result<MixProcessingResult, PacketProcessingError> {
|
||||
let packet_size = self.received_data.packet_size();
|
||||
let packet_type = self.received_data.packet_type();
|
||||
@@ -244,7 +236,6 @@ fn perform_framed_packet_processing(
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
fn wrap_processed_sphinx_packet(
|
||||
packet: nym_sphinx_types::ProcessedPacket,
|
||||
packet_size: PacketSize,
|
||||
@@ -267,38 +258,15 @@ fn wrap_processed_sphinx_packet(
|
||||
// sphinx all together?
|
||||
ProcessedPacketData::FinalHop {
|
||||
destination,
|
||||
#[cfg(feature = "otel")]
|
||||
identifier,
|
||||
#[cfg(not(feature = "otel"))]
|
||||
identifier: _,
|
||||
identifier: _,
|
||||
payload,
|
||||
} => {
|
||||
// if we have a trace id in the destination, we log it for easier correlation later on
|
||||
#[cfg(feature = "otel")]
|
||||
let span = match identifier[0..12].try_into().map(|b: [u8; 12]| b) {
|
||||
Ok(trace_bytes) if !trace_bytes.iter().all(|b| *b == 0) => {
|
||||
let full_trace_id_bytes = decompress_trace_id(&trace_bytes);
|
||||
let full_trace_id =
|
||||
opentelemetry::trace::TraceId::from_bytes(full_trace_id_bytes);
|
||||
let context_propagator =
|
||||
ManualContextPropagator::new_from_tid("final_hop", full_trace_id);
|
||||
tracing::info_span!(parent: &context_propagator.root_span, "final_hop_processing", trace_id=%full_trace_id)
|
||||
}
|
||||
_ => {
|
||||
tracing::debug_span!("final_hop_processing")
|
||||
}
|
||||
};
|
||||
#[cfg(feature = "otel")]
|
||||
let _entered_span = span.enter();
|
||||
|
||||
process_final_hop(
|
||||
destination,
|
||||
payload.recover_plaintext()?,
|
||||
packet_size,
|
||||
packet_type,
|
||||
key_rotation,
|
||||
)
|
||||
}
|
||||
} => process_final_hop(
|
||||
destination,
|
||||
payload.recover_plaintext()?,
|
||||
packet_size,
|
||||
packet_type,
|
||||
key_rotation,
|
||||
),
|
||||
}?;
|
||||
|
||||
Ok(MixProcessingResult {
|
||||
@@ -344,7 +312,6 @@ fn wrap_processed_outfox_packet(
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
fn perform_final_processing(
|
||||
packet: NymProcessedPacket,
|
||||
packet_size: PacketSize,
|
||||
|
||||
@@ -163,6 +163,19 @@ pub trait FragmentPreparer {
|
||||
})
|
||||
}
|
||||
|
||||
/// Tries to convert this [`Fragment`] into a [`SphinxPacket`] that can be sent through the Nym mix-network,
|
||||
/// such that it contains required SURB-ACK and public component of the ephemeral key used to
|
||||
/// derive the shared key.
|
||||
/// Also all the data, apart from the said public component, is encrypted with an ephemeral shared key.
|
||||
/// This method can fail if the provided network topology is invalid.
|
||||
/// It returns total expected delay as well as the [`SphinxPacket`] (including first hop address)
|
||||
/// to be sent through the network.
|
||||
///
|
||||
/// The procedure is as follows:
|
||||
/// For each fragment:
|
||||
/// - compute SURB_ACK
|
||||
/// - generate (x, g^x)
|
||||
/// - compute k = KDF(remote encryption key ^ x) this is equivalent to KDF( dh(remote, x) )
|
||||
/// - compute v_b = AES-128-CTR(k, serialized_fragment)
|
||||
/// - compute vk_b = g^x || v_b
|
||||
/// - compute sphinx_plaintext = SURB_ACK || g^x || v_b
|
||||
@@ -176,8 +189,6 @@ pub trait FragmentPreparer {
|
||||
packet_sender: &Recipient,
|
||||
packet_recipient: &Recipient,
|
||||
packet_type: PacketType,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>,
|
||||
) -> Result<PreparedFragment, NymTopologyError> {
|
||||
debug!("Preparing chunk for sending");
|
||||
// each plain or repliable packet (i.e. not a reply) attaches an ephemeral public key so that the recipient
|
||||
@@ -238,16 +249,6 @@ pub trait FragmentPreparer {
|
||||
topology.random_route_to_egress(&mut rng, destination)?
|
||||
};
|
||||
|
||||
#[cfg(feature = "otel")]
|
||||
let destination = packet_recipient.as_sphinx_destination(trace_id);
|
||||
|
||||
#[cfg(feature = "otel")]
|
||||
tracing::info!(
|
||||
"Packet destination with trace id: {:?}",
|
||||
&destination.identifier
|
||||
);
|
||||
|
||||
#[cfg(not(feature = "otel"))]
|
||||
let destination = packet_recipient.as_sphinx_destination();
|
||||
|
||||
// including set of delays
|
||||
@@ -273,7 +274,6 @@ pub trait FragmentPreparer {
|
||||
)?,
|
||||
};
|
||||
|
||||
// - compute k = KDF(remote encryption key ^ x) this is equivalent to KDF( dh(remote, x) )
|
||||
// from the previously constructed route extract the first hop
|
||||
let first_hop_address =
|
||||
NymNodeRoutingAddress::try_from(route.first().unwrap().address).unwrap();
|
||||
@@ -428,8 +428,6 @@ where
|
||||
ack_key: &AckKey,
|
||||
packet_recipient: &Recipient,
|
||||
packet_type: PacketType,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id: Option<[u8; 12]>,
|
||||
) -> Result<PreparedFragment, NymTopologyError> {
|
||||
let sender = self.sender_address;
|
||||
|
||||
@@ -441,8 +439,6 @@ where
|
||||
&sender,
|
||||
packet_recipient,
|
||||
packet_type,
|
||||
#[cfg(feature = "otel")]
|
||||
trace_id,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,6 @@ repository = { workspace = true }
|
||||
[dependencies]
|
||||
sphinx-packet = { workspace = true, optional = true }
|
||||
nym-outfox = { path = "../../../nym-outfox", optional = true }
|
||||
# TODO add optional
|
||||
nym-bin-common = { path = "../../../common/bin-common" }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -32,6 +32,8 @@ tracing.workspace = true
|
||||
url.workspace = true
|
||||
|
||||
|
||||
# TEMP
|
||||
#nym-bin-common = { path = "../bin-common", features = ["basic_tracing"]}
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
|
||||
@@ -37,4 +37,3 @@ nym-validator-client = { path = "../client-libs/validator-client" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
otel = ["nym-sphinx/otel"]
|
||||
|
||||
@@ -119,7 +119,6 @@ where
|
||||
let ClientInput {
|
||||
connection_command_sender,
|
||||
input_sender,
|
||||
..
|
||||
} = client_input;
|
||||
|
||||
let ClientOutput {
|
||||
|
||||
@@ -350,8 +350,6 @@ impl SocksClient {
|
||||
self.config.connection_start_surbs,
|
||||
TransmissionLane::ConnectionId(self.connection_id),
|
||||
self.packet_type,
|
||||
#[cfg(feature = "otel")]
|
||||
None,
|
||||
);
|
||||
self.input_sender
|
||||
.send(input_message)
|
||||
@@ -375,8 +373,6 @@ impl SocksClient {
|
||||
msg.into_bytes(),
|
||||
TransmissionLane::ConnectionId(self.connection_id),
|
||||
self.packet_type,
|
||||
#[cfg(feature = "otel")]
|
||||
None,
|
||||
);
|
||||
self.input_sender
|
||||
.send(input_message)
|
||||
@@ -443,8 +439,6 @@ impl SocksClient {
|
||||
per_request_surbs,
|
||||
lane,
|
||||
packet_type,
|
||||
#[cfg(feature = "otel")]
|
||||
None,
|
||||
)
|
||||
} else {
|
||||
InputMessage::new_regular(
|
||||
@@ -452,8 +446,6 @@ impl SocksClient {
|
||||
provider_message.into_bytes(),
|
||||
lane,
|
||||
packet_type,
|
||||
#[cfg(feature = "otel")]
|
||||
None,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -29,7 +29,6 @@ x25519-dalek = { workspace = true, features = ["static_secrets"] }
|
||||
cosmwasm-std = { workspace = true }
|
||||
cosmrs = { workspace = true }
|
||||
|
||||
nym-bin-common = { path = "../../common/bin-common" }
|
||||
nym-validator-client = { path = "../../common/client-libs/validator-client" }
|
||||
nym-mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
nym-vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" }
|
||||
|
||||
@@ -160,12 +160,13 @@ pub async fn setup_gateway_from_api(
|
||||
minimum_performance: u8,
|
||||
ignore_epoch_roles: bool,
|
||||
) -> Result<InitialisationResult, WasmCoreError> {
|
||||
let mut rng = thread_rng();
|
||||
let gateways = gateways_for_init(
|
||||
&mut rng,
|
||||
nym_apis,
|
||||
None,
|
||||
minimum_performance,
|
||||
ignore_epoch_roles,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
setup_gateway_wasm(client_store, force_tls, chosen_gateway, gateways).await
|
||||
@@ -177,12 +178,13 @@ pub async fn current_gateways_wasm(
|
||||
minimum_performance: u8,
|
||||
ignore_epoch_roles: bool,
|
||||
) -> Result<Vec<RoutingNode>, ClientCoreError> {
|
||||
let mut rng = thread_rng();
|
||||
gateways_for_init(
|
||||
&mut rng,
|
||||
nym_apis,
|
||||
user_agent,
|
||||
minimum_performance,
|
||||
ignore_epoch_roles,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -255,12 +255,10 @@ pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result<QueryResponse, C
|
||||
}
|
||||
|
||||
#[entry_point]
|
||||
pub fn migrate(deps: DepsMut<'_>, env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
|
||||
pub fn migrate(deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
|
||||
set_build_information!(deps.storage)?;
|
||||
cw2::ensure_from_older_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
|
||||
|
||||
crate::queued_migrations::introduce_historical_epochs(deps, env)?;
|
||||
|
||||
Ok(Response::new())
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ use crate::epoch_state::storage::{load_current_epoch, save_epoch};
|
||||
use crate::epoch_state::utils::check_epoch_state;
|
||||
use crate::error::ContractError;
|
||||
use crate::state::storage::STATE;
|
||||
use crate::verification_key_shares::storage::vk_shares;
|
||||
use crate::Dealer;
|
||||
use cosmwasm_std::{Deps, DepsMut, Env, Event, MessageInfo, Response};
|
||||
use nym_coconut_dkg_common::dealer::{DealerRegistrationDetails, OwnershipTransfer};
|
||||
@@ -162,14 +161,6 @@ pub fn try_update_announce_address(
|
||||
details.announce_address = new_address.clone();
|
||||
EPOCH_DEALERS_MAP.save(deps.storage, (epoch.epoch_id, &info.sender), &details)?;
|
||||
|
||||
let mut contract_share = vk_shares().load(deps.storage, (&info.sender, epoch.epoch_id))?;
|
||||
contract_share.announce_address = new_address.clone();
|
||||
vk_shares().save(
|
||||
deps.storage,
|
||||
(&info.sender, epoch.epoch_id),
|
||||
&contract_share,
|
||||
)?;
|
||||
|
||||
Ok(Response::new().add_event(
|
||||
Event::new("dkg-announce-address-update")
|
||||
.add_attribute("dealer", info.sender)
|
||||
@@ -237,14 +228,9 @@ pub(crate) mod tests {
|
||||
#[cfg(feature = "testable-dkg-contract")]
|
||||
mod tests_with_mock {
|
||||
use super::*;
|
||||
use crate::testable_dkg_contract::{
|
||||
init_contract_tester, init_contract_tester_with_group_members, DkgContractTesterExt,
|
||||
};
|
||||
use anyhow::Context;
|
||||
use crate::testable_dkg_contract::{init_contract_tester, DkgContractTesterExt};
|
||||
use cosmwasm_std::testing::message_info;
|
||||
use nym_coconut_dkg_common::msg::QueryMsg;
|
||||
use nym_coconut_dkg_common::verification_key::PagedVKSharesResponse;
|
||||
use nym_contracts_common_testing::{ChainOpts, ContractOpts};
|
||||
use nym_contracts_common_testing::ContractOpts;
|
||||
|
||||
#[test]
|
||||
fn transferring_ownership() -> anyhow::Result<()> {
|
||||
@@ -450,91 +436,9 @@ mod tests_with_mock {
|
||||
assert_eq!(old_details1, new_details1);
|
||||
assert_eq!(old_details2, new_details2);
|
||||
|
||||
// most recent entry is updated
|
||||
// most recent entry is updated
|
||||
assert_eq!(new_details3.announce_address, new_address);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn updating_announce_address_updates_vk_shares() -> anyhow::Result<()> {
|
||||
let mut contract = init_contract_tester_with_group_members(3);
|
||||
let group_member = contract.random_group_member();
|
||||
|
||||
contract.run_initial_dummy_dkg(); // => epoch 0
|
||||
contract.run_reset_dkg(); // => epoch 1
|
||||
|
||||
// LEAVE DKG MEMBERSHIP
|
||||
contract.remove_group_member(group_member.clone());
|
||||
contract.run_reset_dkg(); // => epoch 2
|
||||
|
||||
// COME BACK
|
||||
contract.add_group_member(group_member.clone());
|
||||
contract.run_reset_dkg(); // => epoch 3
|
||||
|
||||
let old_address = EPOCH_DEALERS_MAP
|
||||
.load(&contract, (3, &group_member))?
|
||||
.announce_address;
|
||||
|
||||
let old_share0 = vk_shares().load(&contract, (&group_member, 0))?;
|
||||
let old_share1 = vk_shares().load(&contract, (&group_member, 1))?;
|
||||
let old_share2 = vk_shares().may_load(&contract, (&group_member, 2))?;
|
||||
assert!(old_share2.is_none());
|
||||
let old_share3 = vk_shares().may_load(&contract, (&group_member, 3))?;
|
||||
assert!(old_share3.is_some());
|
||||
|
||||
let new_address = "https://new-address.com".to_string();
|
||||
try_update_announce_address(
|
||||
contract.deps_mut(),
|
||||
message_info(&group_member, &[]),
|
||||
new_address.clone(),
|
||||
)?;
|
||||
|
||||
let new_share0 = vk_shares().load(&contract, (&group_member, 0))?;
|
||||
let new_share1 = vk_shares().load(&contract, (&group_member, 1))?;
|
||||
let new_share2 = vk_shares().may_load(&contract, (&group_member, 2))?;
|
||||
assert!(new_share2.is_none());
|
||||
let new_share3 = vk_shares().load(&contract, (&group_member, 3))?;
|
||||
|
||||
// old epoch data is unchanged
|
||||
assert_eq!(old_share0, new_share0);
|
||||
assert_eq!(old_share1, new_share1);
|
||||
assert_eq!(old_share2, new_share2);
|
||||
|
||||
// most recent entry is updated
|
||||
assert_eq!(new_share3.announce_address, new_address);
|
||||
|
||||
// finally an integration check against query endpoint
|
||||
let epoch0_shares: PagedVKSharesResponse =
|
||||
contract.query(&QueryMsg::GetVerificationKeys {
|
||||
epoch_id: 0,
|
||||
limit: None,
|
||||
start_after: None,
|
||||
})?;
|
||||
assert_eq!(epoch0_shares.shares.len(), 3);
|
||||
|
||||
let member_share = epoch0_shares
|
||||
.shares
|
||||
.iter()
|
||||
.find(|s| s.owner == group_member)
|
||||
.context("failed to find member's share")?;
|
||||
assert_eq!(member_share.announce_address, old_address);
|
||||
|
||||
let epoch0_shares: PagedVKSharesResponse =
|
||||
contract.query(&QueryMsg::GetVerificationKeys {
|
||||
epoch_id: 3,
|
||||
limit: None,
|
||||
start_after: None,
|
||||
})?;
|
||||
assert_eq!(epoch0_shares.shares.len(), 3);
|
||||
|
||||
let member_share = epoch0_shares
|
||||
.shares
|
||||
.iter()
|
||||
.find(|s| s.owner == group_member)
|
||||
.context("failed to find member's share")?;
|
||||
assert_eq!(member_share.announce_address, new_address);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,2 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::epoch_state::storage::HISTORICAL_EPOCH;
|
||||
use crate::error::ContractError;
|
||||
use cosmwasm_std::{DepsMut, Env};
|
||||
|
||||
pub fn introduce_historical_epochs(deps: DepsMut, env: Env) -> Result<(), ContractError> {
|
||||
if HISTORICAL_EPOCH.may_load(deps.storage)?.is_some() {
|
||||
return Err(ContractError::FailedMigration {
|
||||
comment: "this migration has already been run before".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
let current = crate::epoch_state::storage::CURRENT_EPOCH.load(deps.storage)?;
|
||||
// we won't have information on intermediate states prior to now, but that's not the end of the world
|
||||
HISTORICAL_EPOCH.save(deps.storage, ¤t, env.block.height)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -62,18 +62,12 @@ impl TestableNymContract for DkgContract {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
init_contract_tester()
|
||||
init_contract_tester_with_group_members(DEFAULT_GROUP_MEMBERS)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_contract_tester() -> ContractTester<DkgContract> {
|
||||
init_contract_tester_with_group_members(DEFAULT_GROUP_MEMBERS)
|
||||
}
|
||||
|
||||
pub fn init_contract_tester_with_group_members(members: usize) -> ContractTester<DkgContract> {
|
||||
prepare_contract_tester_builder_with_group_members(members)
|
||||
.build()
|
||||
.with_common_storage_key(CommonStorageKeys::Admin, "dkg-admin")
|
||||
DkgContract::init().with_common_storage_key(CommonStorageKeys::Admin, "dkg-admin")
|
||||
}
|
||||
|
||||
pub fn prepare_contract_tester_builder_with_group_members<C>(
|
||||
@@ -143,6 +137,12 @@ where
|
||||
builder
|
||||
}
|
||||
|
||||
pub fn init_contract_tester_with_group_members(members: usize) -> ContractTester<DkgContract> {
|
||||
prepare_contract_tester_builder_with_group_members(members)
|
||||
.build()
|
||||
.with_common_storage_key(CommonStorageKeys::Admin, "dkg-admin")
|
||||
}
|
||||
|
||||
pub trait DkgContractTesterExt:
|
||||
ContractOpts<ExecuteMsg = ExecuteMsg, QueryMsg = QueryMsg, ContractError = ContractError>
|
||||
+ ChainOpts
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn legacy_mixnode_bonding() {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -2,3 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub(crate) mod transactions;
|
||||
|
||||
// the purpose of that module is to keep track of tests of legacy features that will eventually be phased out
|
||||
// such as standalone mixnode/gateway bonding
|
||||
pub(crate) mod legacy;
|
||||
|
||||
@@ -11,7 +11,6 @@ import { Alert, AlertTitle } from '@mui/material';
|
||||
import { Wallet } from '@cosmos-kit/core';
|
||||
import { CosmosKitLedger } from './ledger';
|
||||
import { CosmosKitSign } from './sign';
|
||||
import type { SignerOptions } from '@cosmos-kit/core';
|
||||
|
||||
const CosmosKitSetup: FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const assetsFixedUp = React.useMemo(() => {
|
||||
@@ -41,16 +40,14 @@ const CosmosKitSetup: FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
return chains;
|
||||
}, [chains]);
|
||||
|
||||
|
||||
// components/cosmos-kit/index.tsx
|
||||
|
||||
return (
|
||||
<ChainProvider
|
||||
chains={chainsFixedUp}
|
||||
assetLists={assetsFixedUp}
|
||||
wallets={[...ledger, ...keplr]}
|
||||
signerOptions={{ preferredSignType: () => 'amino' }}
|
||||
throwErrors={false}
|
||||
signerOptions={{
|
||||
preferredSignType: () => 'amino',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</ChainProvider>
|
||||
|
||||
-141
@@ -1,141 +0,0 @@
|
||||
import { Steps } from 'nextra/components';
|
||||
import { Callout } from 'nextra/components';
|
||||
import { AccordionTemplate } from 'components/accordion-template.tsx';
|
||||
|
||||
<Callout type="info" emoji="ℹ️">
|
||||
**QUIC bridge is a requirement for all nodes which enable Wireguard functionality. Note that it this feature is compatible with nodes from `v1.18.0` (platform release [`v2025.17-isabirra`](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2025.17-isabirra)) and newer!**
|
||||
</ Callout>
|
||||
|
||||
Nym Network uses various [transport bridges](https://github.com/nymtech/nym-bridges/blob/main/README.md) for routing the packets. Right now operators need to configure [our implementation](https://github.com/nymtech/nym-bridges/tree/main/nym-bridge) of general-purpose transport layer network protocol called [QUIC](https://en.wikipedia.org/wiki/QUIC).
|
||||
|
||||
Operators can use [Nym Bridge Configuration Tool](https://github.com/nymtech/nym-bridges/tree/main/bridge-cfg) and compile the [Bridge Runner binary](https://github.com/nymtech/nym-bridges/tree/main/nym-bridge) themselves.
|
||||
|
||||
**We recommend a more convenient QUIC bridge deployment using a script [`quic_bridge_deployment.sh`](https://github.com/nymtech/nym/blob/develop/scripts/nym-node-setup/quic_bridge_deployment.sh), following the steps below.**
|
||||
|
||||
<Steps>
|
||||
###### 1. Download [`quic_bridge_deployment.sh`](https://github.com/nymtech/nym/blob/develop/scripts/nym-node-setup/quic_bridge_deployment.sh) script
|
||||
- SSH to your server
|
||||
- Download the script and make executable
|
||||
```sh
|
||||
wget https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/scripts/nym-node-setup/quic_bridge_deployment.sh && \
|
||||
chmod +x quic_bridge_deployment.sh
|
||||
```
|
||||
|
||||
|
||||
###### 2. Run the script with `full_bridge_setup` command
|
||||
- Optional: open `tmux` in case you will need to run another commands on the VPS
|
||||
- Run the script with a command `full_bridge_setup`
|
||||
```sh
|
||||
./nym-node-setup/quic_bridge_deployment.sh full_bridge_setup
|
||||
```
|
||||
|
||||
###### 3. Follow the interactive prompts
|
||||
- When you are asked for bridge binary URL, look here for one to match your system: [builds.ci.nymte.ch/QUIC](https://builds.ci.nymte.ch/QUIC/)
|
||||
- When you are asked to enter forward address, it's your IPv4 used for bonding the node, alongside port `:51822` (an example: `172.232.238.161:51822`)
|
||||
- To find out your IP address you can always run:
|
||||
- IPv4: `curl -4 https://ifconfig.co/ip`
|
||||
- IPv6: `curl -6 https://ifconfig.co/ip`
|
||||
- **For all prompts with default options, we highly recommend to stick to default (press enter)**
|
||||
|
||||
###### 4. Restart the node service
|
||||
- When done with the deployment, please restart your node systemd service
|
||||
```sh
|
||||
service nym-node restart && journalctl -u nym-node.service -f --all
|
||||
```
|
||||
</Steps>
|
||||
|
||||
Congratulation, you deployed QUIC transport bridge! The script offers a standalone tweaks and checks, you can always run it without any argument to see all the options:
|
||||
```sh
|
||||
./quic_bridge_deployment.sh
|
||||
```
|
||||
<br/>
|
||||
<AccordionTemplate name="Command output">
|
||||
```shell
|
||||
root@localhost:~# ./quic_bridge_deployment.sh
|
||||
iptables-persistent is already installed.
|
||||
Usage: ./quic_bridge_deployment.sh [command] [options]
|
||||
|
||||
Nym QUIC Bridge Deployment Helper Script
|
||||
|
||||
Bridge Installation & Configuration:
|
||||
check_bridge_installation - Check bridge installation status
|
||||
show_bridge_config - Display bridge configuration files
|
||||
show_bridge_keys - Display bridge key information
|
||||
show_bridge_info - Show comprehensive bridge information
|
||||
verify_bridge_prerequisites - Verify all prerequisites are met
|
||||
|
||||
Bridge Setup Commands:
|
||||
install_bridge_binary - Download and install nym-bridge binary
|
||||
generate_bridge_keys - Generate ED25519 bridge identity keys
|
||||
create_client_params - Create client_bridge_params.json
|
||||
create_bridge_config - Create bridges.toml configuration
|
||||
create_bridge_service - Create systemd service file
|
||||
full_bridge_setup - Interactive full bridge setup wizard
|
||||
|
||||
Network Configuration Commands:
|
||||
adjust_ip_forwarding - Enable IPv4 and IPv6 forwarding
|
||||
apply_bridge_iptables_rules - Apply iptables rules for QUIC bridge (nymwg)
|
||||
configure_dns_and_icmp - Allow ICMP ping tests and configure DNS
|
||||
remove_duplicate_bridge_rules - Remove duplicate iptables rules for nymwg
|
||||
|
||||
Network Inspection Commands:
|
||||
fetch_and_display_ipv6 - Show IPv6 on default network device
|
||||
fetch_wg_ipv6_address - Fetch IPv6 for nymwg interface
|
||||
check_bridge_iptables - Check iptables rules for nymwg
|
||||
check_ipv6_ipv4_forwarding - Check IPv4 and IPv6 forwarding status
|
||||
check_ip_routing - Display IP routing tables
|
||||
|
||||
Testing Commands:
|
||||
perform_pings - Test IPv4 and IPv6 connectivity
|
||||
test_bridge_connectivity - Comprehensive bridge connectivity test
|
||||
|
||||
Service Management Commands:
|
||||
check_bridge_service_status - Check nym-bridge and nym-node service status
|
||||
show_bridge_logs [lines] - Show recent nym-bridge logs (default: 50 lines)
|
||||
|
||||
Quick Start:
|
||||
1. Run 'verify_bridge_prerequisites' to check prerequisites
|
||||
2. Run 'check_bridge_installation' to verify installation
|
||||
3. Run 'test_bridge_connectivity' to test connectivity
|
||||
```
|
||||
</AccordionTemplate>
|
||||
|
||||
### Fixing Metadata Port Showing Not Open in Probe Results
|
||||
If you have followed the steps outlined above, but the metadata port is not shown as open in either the Node Status API's probe results or an explorer that gets its data from the API, see below:
|
||||
|
||||
<Steps>
|
||||
###### 1.
|
||||
Ensure that in your `config.toml` file, this value is set to the default one - any other value here will cause the metadata endpoint to fail:
|
||||
|
||||
```
|
||||
# Private IP address of the wireguard gateway.
|
||||
# default: '10.1.0.1'
|
||||
private_ipv4 = '10.1.0.1'
|
||||
```
|
||||
|
||||
Then restart your node.
|
||||
|
||||
###### 2.
|
||||
Run this command if not already done:
|
||||
```
|
||||
ufw allow in on nymwg to any port 51830 proto tcp
|
||||
```
|
||||
|
||||
Check if the port is open with:
|
||||
```
|
||||
iptables -S | grep 51830
|
||||
```
|
||||
|
||||
Then ensure the metadata endpoint is listening from the correct address with:
|
||||
```
|
||||
netstat -an | egrep LISTEN | egrep "51830"
|
||||
```
|
||||
|
||||
###### 3.
|
||||
Once the Node Status API has run a probe on your node, the probe results will reflect this - `can_query_metadata_v4` will have `true` as a value.
|
||||
|
||||
The quickest way to check this is by using the [NymVPN API](https://nymvpn.com/api/public/v1/directory/gateways?show_vpn_only=true) and checking the same field:
|
||||
|
||||

|
||||
|
||||
</Steps>
|
||||
@@ -1 +1 @@
|
||||
Tuesday, October 14th 2025, 11:34:14 UTC
|
||||
Sunday, October 5th 2025, 09:29:02 UTC
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
"@cosmjs/encoding": "^0.32.2",
|
||||
"@cosmjs/proto-signing": "^0.32.2",
|
||||
"@cosmjs/stargate": "^0.32.2",
|
||||
"@cosmos-kit/core": "^2.16.3",
|
||||
"@cosmos-kit/core": "^2.8.9",
|
||||
"@cosmos-kit/keplr": "^2.6.9",
|
||||
"@cosmos-kit/keplr-extension": "^2.7.9",
|
||||
"@cosmos-kit/ledger": "^2.6.9",
|
||||
"@cosmos-kit/react": "^2.22.3",
|
||||
"@cosmos-kit/react": "^2.10.11",
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@interchain-ui/react": "^1.8.0",
|
||||
@@ -54,15 +54,12 @@
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/swc-linux-x64-gnu": "15.5.0",
|
||||
"@types/node": "18.11.10",
|
||||
"@types/react": "^18.3.26",
|
||||
"@types/react-dom": "^18.3.7",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"eslint": "8.46.0",
|
||||
"eslint-config-next": "13.4.13",
|
||||
"raw-loader": "^4.0.2",
|
||||
"typescript": "^5.9.3"
|
||||
"typescript": "^4.9.3"
|
||||
},
|
||||
"private": false
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import { AccordionTemplate } from 'components/accordion-template.tsx';
|
||||
import { Steps } from 'nextra/components';
|
||||
import AbuseResponse from 'components/operators/templates/dmca_response.md';
|
||||
import OperatorIntroduction from 'components/operators/templates/provider_introduction.md';
|
||||
import QuicDeploymentSteps from 'components/operators/snippets/quic-bridge-deployment-script-setup.mdx';
|
||||
|
||||
|
||||
export const TestingSteps = () => (
|
||||
@@ -49,323 +48,6 @@ This page displays a full list of all the changes during our release cycle from
|
||||
|
||||
<VarInfo />
|
||||
|
||||
## `v2025.18-jarlsberg`
|
||||
|
||||
- [Release Binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2025.18-jarlsberg)
|
||||
- [`nym-node`](nodes/nym-node.mdx) version `1.19.0`
|
||||
|
||||
```sh
|
||||
nym-node
|
||||
Binary Name: nym-node
|
||||
Build Timestamp: 2025-10-15T09:04:32.043934599Z
|
||||
Build Version: 1.19.0
|
||||
Commit SHA: 2235a6e1477bea7368ee5443a298f544deb63504
|
||||
Commit Date: 2025-10-15T10:22:16.000000000+02:00
|
||||
Commit Branch: master
|
||||
rustc Version: 1.92.0-nightly
|
||||
rustc Channel: nightly
|
||||
cargo Profile: release
|
||||
```
|
||||
|
||||
### API Changes
|
||||
There have been a few updates to the Node Status API (used by the NymVPN API) to do with Nodes' metadata endpoints, which are used to determine if they are running a QUIC bridge.
|
||||
|
||||
- [Node Status API: add bridge information to dVPN endpoint](https://github.com/nymtech/nym/pull/6069)
|
||||
Scrape the `/api/v1/bridges/client-params` endpoint from nodes to get bridge information and add to the dVPN output:
|
||||
|
||||
```
|
||||
{
|
||||
"identity_key": "3wqfp9ebaajgV8HRKYHeZuZCNXgitnW8BbytxyBH65xZ",
|
||||
"name": "middle winner wing",
|
||||
"authenticator": {
|
||||
"address": "6CQMtm9DqUj7mPVkSD9YarjUuPh7mJaZQnnHWxNpgByh.AGXiTivVieBULeDhL9tuyMKgRydoT67sFCjeoERDN84k@3wqfp9ebaajgV8HRKYHeZuZCNXgitnW8BbytxyBH65xZ"
|
||||
},
|
||||
"ip_packet_router": {
|
||||
"address": "GA47h8294m7f6ciyFuDkjk3mmqrvALqboL2o22jkqFhi.22SdTGBWKFrrBM31hMgzjmgduSH1nosnbE9dgNcY2CXz@3wqfp9ebaajgV8HRKYHeZuZCNXgitnW8BbytxyBH65xZ"
|
||||
},
|
||||
"location": {
|
||||
"two_letter_iso_country_code": "GB",
|
||||
"latitude": 51.5085,
|
||||
"longitude": -0.1257
|
||||
},
|
||||
"last_probe": {
|
||||
"last_updated_utc": "2025-09-02T18:19:10Z",
|
||||
"outcome": {
|
||||
"as_entry": {
|
||||
"can_connect": true,
|
||||
"can_route": true
|
||||
},
|
||||
"as_exit": {
|
||||
"can_connect": true,
|
||||
"can_route_ip_external_v4": true,
|
||||
"can_route_ip_external_v6": true,
|
||||
"can_route_ip_v4": true,
|
||||
"can_route_ip_v6": true
|
||||
},
|
||||
"wg": {
|
||||
"can_handshake_v4": true,
|
||||
"can_handshake_v6": true,
|
||||
"can_register": true,
|
||||
"can_resolve_dns_v4": true,
|
||||
"can_resolve_dns_v6": true,
|
||||
"download_duration_sec_v4": 0,
|
||||
"download_duration_sec_v6": 5,
|
||||
"download_error_v4": "",
|
||||
"download_error_v6": "",
|
||||
"downloaded_file_v4": "https://proof.ovh.net/files/1Mb.dat",
|
||||
"downloaded_file_v6": "https://proof.ovh.net/files/10Mb.dat",
|
||||
"ping_hosts_performance_v4": 1,
|
||||
"ping_hosts_performance_v6": 1,
|
||||
"ping_ips_performance_v4": 1,
|
||||
"ping_ips_performance_v6": 0.6666667,
|
||||
"can_handshake": true,
|
||||
"can_resolve_dns": true,
|
||||
"ping_hosts_performance": 1,
|
||||
"ping_ips_performance": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"ip_addresses": [
|
||||
"178.79.168.250",
|
||||
"2a01:7e00::f03c:95ff:fef8:77f"
|
||||
],
|
||||
"mix_port": 1789,
|
||||
"role": "EntryGateway",
|
||||
"entry": {
|
||||
"hostname": "nym-circ.anonym.tech",
|
||||
"ws_port": 9000,
|
||||
"wss_port": 9443
|
||||
},
|
||||
+ "bridges":{
|
||||
+ "version": 0,
|
||||
+ "transports": [
|
||||
+ {
|
||||
+ "transport_type": "quic_plain",
|
||||
+ "args": {
|
||||
+ "addresses": ["[2a01:7e00::f03c:95ff:fef8:77f]:4443", "178.79.168.250:4443"],
|
||||
+ "id_pubkey": "gyKl6DN9hgdPGhEzdf9gY4Ha2GzrOwSzLCguxeTVTJU=",
|
||||
+ "host": "netdna.bootstrapcdn.com"
|
||||
+ }
|
||||
+ }
|
||||
+ ]
|
||||
+ }
|
||||
"performance": "1",
|
||||
"build_information": {
|
||||
"build_version": "1.16.0",
|
||||
"commit_branch": "build",
|
||||
"commit_sha": "7f97f13799342f864e1b106e8cafc9f6d6c24c0f"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ns-api: add new fields for probe output for query_metadata and download file size and duration in ms](https://github.com/nymtech/nym/pull/6091)
|
||||
|
||||
This PR adds new fields to the Node Status API:
|
||||
|
||||
```json
|
||||
{
|
||||
"node": "ByxGq9hpDQu6Wc8augEh22w7CRWJHPNfDshB1b8nfWkh",
|
||||
"used_entry": "ByxGq9hpDQu6Wc8augEh22w7CRWJHPNfDshB1b8nfWkh",
|
||||
"outcome": {
|
||||
"as_entry": {
|
||||
"can_connect": true,
|
||||
"can_route": true
|
||||
},
|
||||
"as_exit": {
|
||||
"can_connect": true,
|
||||
"can_route_ip_v4": true,
|
||||
"can_route_ip_external_v4": true,
|
||||
"can_route_ip_v6": true,
|
||||
"can_route_ip_external_v6": true
|
||||
},
|
||||
"wg": {
|
||||
"can_register": true,
|
||||
"can_query_metadata_v4": true, // <--------------------------------
|
||||
"can_handshake_v4": true,
|
||||
"can_resolve_dns_v4": true,
|
||||
"ping_hosts_performance_v4": 1.0,
|
||||
"ping_ips_performance_v4": 1.0,
|
||||
"can_handshake_v6": true,
|
||||
"can_resolve_dns_v6": true,
|
||||
"ping_hosts_performance_v6": 1.0,
|
||||
"ping_ips_performance_v6": 0.93333334,
|
||||
"download_duration_sec_v4": 2,
|
||||
"download_duration_milliseconds_v4": 2034, // <--------------------------------
|
||||
"downloaded_file_size_bytes_v4": 1048576, // <--------------------------------
|
||||
"downloaded_file_v4": "https://nym-bandwidth-monitoring.ops-d86.workers.dev/1mb.dat",
|
||||
"download_error_v4": "",
|
||||
"download_duration_sec_v6": 5,
|
||||
"downloaded_file_size_bytes_v6": 1048576,
|
||||
"download_duration_milliseconds_v6": 5501,
|
||||
"downloaded_file_v6": "https://proof.ovh.net/files/1Mb.dat",
|
||||
"download_error_v6": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ns-api: add descriptions to dVPN gateway responses](https://github.com/nymtech/nym/pull/6102)
|
||||
This PR adds the `description` field to dVPN gateways in `/dvpn/v1/directory/gateways`.
|
||||
|
||||
- [NS API: use new probe download filesize and milliseconds field](https://github.com/nymtech/nym/pull/6097)
|
||||
This PR uses the new fields in mainnet to calculate the probe download score.
|
||||
|
||||
- [ns-api: use download files size from probes instead of parsing filenames](https://github.com/nymtech/nym/pull/6095) This PR uses the new field in the probe results that says how many bytes were downloaded to calculate the speed of download. It only uses downloads on ipv4 and ignores ipv6 for now. This might change in the future.
|
||||
|
||||
- [Node Status API: remove sqlite support](https://github.com/nymtech/nym/pull/6004)
|
||||
This PR removes sqlite support, requiring pgsql to run the NS API.
|
||||
|
||||
It also fixes the following issues:
|
||||
|
||||
- deserialisation of `NodeDescription`
|
||||
- defaults for `WireguardDetails` for deserialisation
|
||||
|
||||
It also bumps the version to v4.0.0.
|
||||
|
||||
### Operators Updates & Tools
|
||||
|
||||
- [Node rewards tracker](https://github.com/nymtech/nym/pull/6064)
|
||||
This PR introduces a script fetching operators rewards based on provided Nyx account addresses provided in `data/wallet-addresses.csv`.
|
||||
|
||||
<AccordionTemplate name="Info">
|
||||
**Output is:**
|
||||
1. Printed table in terminal
|
||||
3. Sheet with complete info stored in `data/node-balances.csv`
|
||||
4. Historical data yaml file stored in `data/data.yaml` - this file should not be changed manually, as
|
||||
all values older than 30 days get auto-removed
|
||||
|
||||
**RUN**
|
||||
|
||||
Before you start fill first column of `data/wallet-addresses.csv` called `addresses` with your Nyx account addresses and (optionally) second column called `tag` with an entity, for example *"mysquad"* and *"personal"* to get sorted output per entity.
|
||||
|
||||
- Csv example with `tag`s:
|
||||
```
|
||||
n1foofoofoo, personal
|
||||
n1barbarbar, personal
|
||||
n1bazbazbaz, mysquad
|
||||
n1lollollol, mysquad
|
||||
```
|
||||
- For operators having all nodes under one entity, the tag field will be left empty. Example:
|
||||
```csv
|
||||
n1foofoofoo
|
||||
n1barbarbar
|
||||
n1bazbazbaz
|
||||
```
|
||||
|
||||
Documentation coming soon.
|
||||
</AccordionTemplate>
|
||||
|
||||
- [Bugfix/bloomfilters purge](https://github.com/nymtech/nym/pull/6089)
|
||||
This PR fixes bug where old replay protection bloomfilters were never getting removed.
|
||||
|
||||
|
||||
### Features
|
||||
- [Get wireguard keypair as arg instead of reading it from disk](https://github.com/nymtech/nym/pull/6078)
|
||||
|
||||
- [Registration Client](https://github.com/nymtech/nym/pull/6059)
|
||||
This PR introduces the `RegistrationClient` whose eventual job will be to handle registration with gateway and bandwidth control. This is step 1, where it only handles registration and then hands back the control channel to the vpn-client.
|
||||
|
||||
<AccordionTemplate name="Info">
|
||||
|
||||
**nym-wg-gateway-client**
|
||||
This crate has been smooshed with the nym-authenticator-client as they were doing the same thing : talking with the Authenticator.
|
||||
|
||||
**nym-authenticator-client**
|
||||
The job of the `AuthenticatorClient` is to talk to the `Authenticator`s via the mixnet. They both make use of a `AuthClientMixnetListener` that handles interaction with the mixnet client. No more `SharedMixnetClient`, only clear owners. That component could be turned into an actual multiplexer, but that's out of scope.
|
||||
|
||||
It is designed to be able to shut down, since it won't be necessary for bandwidth top up in the future.
|
||||
|
||||
Lots of types and traits were copied in both repos, some of them are sadly still there. Further work could be done to improve messaging ( `ClientMessage` and `AuthenticatorRequests` for example)
|
||||
|
||||
**nym-ip-packet-client**
|
||||
This crate has minor changes, focused on getting rid of the `SharedMixnetClient`. It still talks to the `IpPacketRouter` but it owns the `MixnetClient`
|
||||
|
||||
**Nym-registration-client**
|
||||
Brand new crates, whose current job is to run a `MixnetClient` with the given options, register with the component related to the tunnel type, and hand back the necessary component for running the tunnel.
|
||||
|
||||
**authenticator-requests**
|
||||
Mostly refactoring, lots of code was duplicated in the vpn-client repo
|
||||
|
||||
**misc**
|
||||
The rest are qol changes that might not be needed right away but that is preparing the future improvements coming soon™
|
||||
</AccordionTemplate>
|
||||
|
||||
- [Feature: Ping probe all nodes /described nodes from a server](https://github.com/nymtech/nym/pull/6074)
|
||||
This script should be ran from a node hosting server. It pings all IPs listed in /described endpoint and returns a file with unreachable IPs. Such list gives operator an idea on IPs potentially blocking their IP.
|
||||
|
||||
- [Feature: Nym node html landing page](https://github.com/nymtech/nym/pull/6053)
|
||||
This PR introduces a new landing page which contains:
|
||||
- no more deprecated tornul
|
||||
- new nym theme
|
||||
- bold text about DMCA
|
||||
- hook for nym-node-cli to use it and add $EMAIL prompted to the operator
|
||||
|
||||
- [feat: DKG contract method for updating announce address](https://github.com/nymtech/nym/pull/6050)
|
||||
|
||||
- [feat: NS ticket faucet](https://github.com/nymtech/nym/pull/6047)
|
||||
Overview: modifies the Node Status API so that it keeps a buffer of tickets inside its storage that it gives out when new test runs get requested. it also slightly adjusts the ticketbook API in a bit hacky way to allow importing ticketbooks with specific index ranges. However, those changes also involve modifying cli arguments passed to both NS API and gateway probes. The associated vpn-client repo branch is `feature/ticket-faucet-probe` which for the same reason is not yet ready
|
||||
|
||||
<AccordionTemplate name="Info">
|
||||
**Node Status API**
|
||||
**Added**
|
||||
- `--config-env-file` / `-c` (optional) - helper allowing testing locally on non-mainnet networks without passing everything through env variables
|
||||
- `--mnemonic` (env: `NYM_NODE_STATUS_API_MNEMONIC`) - account used for obtaining ticketbooks
|
||||
- `--max-concurrent-deposits` (env: `NYM_NODE_STATUS_API_MAX_CONCURRENT_DEPOSITS`) (optional; default: 5) - Specifies the maximum number of deposits the node status api can make in a single transaction. Note that each deposit batch is followed by the same number of sequential signing requests
|
||||
- `--tickets-buffer-size` (env: `NYM_NODE_STATUS_API_TICKETS_BUFFER`) (optional; default: 50) - Specifies the size of the tickets buffer the node status api should have available at any time for each ticket type.
|
||||
- `--tickets-buffer-check-interval` (env: `NYM_NODE_STATUS_API_TICKETS_CHECK_INTERVAL`) (optional; default: 1min) - Specifies interval at which the node status api should check if it has sufficient number of tickets buffered
|
||||
- `--quorum-check-interval` (env: `NYM_NODE_STATUS_API_QUORUM_CHECK_INTERVAL`) (optional; default: 5min) - Specifies interval at which the node status api should check if signing quorum is available
|
||||
- `--buffered-ticket-types` (env: `NYM_NODE_STATUS_BUFFERED_TICKET_TYPES`) (optional; default: `[V1MixnetEntry, V1WireguardEntry, V1WireguardExit]`) - Specifies types of tickets to buffer
|
||||
- `--ecash-client-identifier-bs58` (env: `NYM_NODE_STATUS_API_ECASH_CLIENT_IDENTIFIER_BS58`) - Identifier used for deriving keys embedded in the issued ticketbooks (i.e. seed for the client identity). It can be a random string, but make sure it has sufficient entropy. it has to be base58 encoded.
|
||||
|
||||
**Node Status Agent**
|
||||
**Removed**
|
||||
- `--mnemonic` - no longer needed as tickets are obtained throught the faucet
|
||||
|
||||
**Gateway Probe (vpn-client repo)**
|
||||
**Added**
|
||||
- `--ticket-materials` - all the encoded generated tickets (and global data) needed by the probe
|
||||
- `--ticket-materials-revision` - revision of the serialisation to help with decoding (not strictly needed, but it was already available)
|
||||
**Removed**
|
||||
- `--mnemonic` - no longer needed as tickets are obtained throught the faucet
|
||||
</AccordionTemplate>
|
||||
|
||||
- [Bridge proto client params in Self-Described](https://github.com/nymtech/nym/pull/6035)
|
||||
This PR gives the nym-node a way to expose information about the bridge protocols that the node supports, and the parameters that are necessary to connect using those protocols.
|
||||
|
||||
<AccordionTemplate name="Info">
|
||||
This is meant to be usable by the node status API to be be included into node descriptors that are compiled for the vpn client.
|
||||
|
||||
- Adds a new field to the nym-node config `gateway_tasks.storage_paths.bridge_client_params`
|
||||
- IF the new config field is present a new self-described endpoint is available at `/v1/bridges/client-params`
|
||||
- IF the new config field is NOT present the endpoint is not exposed.
|
||||
|
||||
I arbitrarily chose config v8 as the oldest nym-node configuration version that supports the option. This can probably be propogated further backwards if necessary.
|
||||
|
||||
NOTE: The new `/bridges/client-params` endpoint does not have swagger / utopia docs associated. This interface will likely change in several upcoming iterations and serving from file (for now) means that the types are not defined internally.
|
||||
|
||||
tested as working on node `3wqfp9eb` both when file is provided in config (sucessful response) and when file is not specified in config (path gives 404).
|
||||
|
||||
</AccordionTemplate>
|
||||
|
||||
### Refactors & Maintenance
|
||||
- [[chore] Clippy fix](https://github.com/nymtech/nym/pull/6060)
|
||||
|
||||
- [Bugfix: Nym node CLI download nym-node exception](https://github.com/nymtech/nym/pull/6058)
|
||||
This PR fixes a case when the "Latest" platform release doesn't include `nym-node` by prompting user to insert binary URL instead of failing. Additionally it fixes fetching new landing page script in the CLI.
|
||||
|
||||
- [Benny/ci contract fix](https://github.com/nymtech/nym/pull/5962)
|
||||
|
||||
- [frontdoor typo fix](https://github.com/nymtech/nym/pull/6067)
|
||||
|
||||
- [Hotfix: Update API source in node ping tester script](https://github.com/nymtech/nym/pull/6082)
|
||||
This PR fixes initial development bug where a wrong API endpoint was used.
|
||||
`https://validator.nymtech.net/api/v1/nym-nodes/described` gets all nym nodes, not just gateways.
|
||||
Code is simplified accordingly.
|
||||
|
||||
## QUIC Transport Bridge Deployment
|
||||
|
||||
<QuicDeploymentSteps />
|
||||
|
||||
## `v2025.17-isabirra`
|
||||
|
||||
- [Release Binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2025.17-isabirra)
|
||||
@@ -421,7 +103,7 @@ All of the routes removed had already been deprecated over a year ago. This is m
|
||||
<AccordionTemplate name="Removed API routes">
|
||||
|
||||
### Legacy mixnodes related:
|
||||
|
||||
|
||||
- `/v1/mixnodes`
|
||||
- `/v1/mixnodes/active`
|
||||
- `/v1/mixnodes/active/detailed`
|
||||
@@ -443,9 +125,9 @@ All of the routes removed had already been deprecated over a year ago. This is m
|
||||
- `/v1/status/mixnodes/detailed-unfiltered`
|
||||
- `/v1/status/mixnode/{mix_id}/report`
|
||||
- `/v1/status/mixnode/{mix_id}/avg_uptime`
|
||||
|
||||
|
||||
### Legacy gateways related:
|
||||
|
||||
|
||||
- `/v1/gateways`
|
||||
- `/v1/gateways/described`
|
||||
- `/v1/gateways/blacklisted`
|
||||
@@ -457,21 +139,21 @@ All of the routes removed had already been deprecated over a year ago. This is m
|
||||
</AccordionTemplate>
|
||||
|
||||
#### Structs changes:
|
||||
|
||||
|
||||
- `MixnodeUptimeHistoryResponse` no longer has `owner` field
|
||||
- `GatewayUptimeHistoryResponse` no longer has `owner` field
|
||||
|
||||
|
||||
|
||||
|
||||
#### New Routes Added
|
||||
|
||||
- `/v1/nym-nodes/stake-saturation/{node_id}` - as a better replacement for `/v1/status/mixnode/{mix_id}/stake-saturation` as this information might be potentially useful and can be applied to any nym-node, not just a legacy mixnode.
|
||||
- `/v1/legacy/mixnodes` - returns a list of bonded legacy mixnodes that haven't migrated to nym-nodes
|
||||
- `/v1/legacy/gateways` - returns a list of bonded legacy gateways that haven't migrated to nym-nodes
|
||||
|
||||
|
||||
#### Node Status API
|
||||
|
||||
|
||||
Furthermore the changes remove all scraping of legacy mixnodes from NS and the following routes are removed:
|
||||
|
||||
|
||||
- `/v2/mixnodes/{mix_id}`
|
||||
- `/v2/mixnodes`
|
||||
|
||||
@@ -542,7 +224,7 @@ Furthermore the changes remove all scraping of legacy mixnodes from NS and the f
|
||||
### Operators Updates & Tools
|
||||
|
||||
<Callout type="info" emoji="ℹ️">
|
||||
Nodes receiving stake as a part of [**Nym Delegation Program**](https://nym.com/network/DP) are updated weekly based on the [rules](https://forms.nym.com/form/#/2/form/view/BRh8QroXFinjOF4D3FHgYiX76zbiRvUV2Sy+czaoKFQ) without prior notification given to the operators.
|
||||
Nodes receiving stake as a part of [**Nym Delegation Program**](https://nym.com/network/DP) are updated weekly based on the [rules](https://forms.nym.com/form/#/2/form/view/BRh8QroXFinjOF4D3FHgYiX76zbiRvUV2Sy+czaoKFQ) without prior notification given to the operators.
|
||||
|
||||
[**Nym Delegation account**](https://explorer.nym.spectredao.net/account/n1rnxpdpx3kldygsklfft0gech7fhfcux4zst5lw) `n1rnxpdpx3kldygsklfft0gech7fhfcux4zst5lw` is a single source of truth. If you expect your node to have Nym team stake and it doesn't, please reach out in in the [**Node Operators Matrix channel**](https://matrix.to/#/#operators:nymtech.chat).
|
||||
</Callout>
|
||||
@@ -565,32 +247,32 @@ nym-vpnc connect --enable-two-hop --entry-gateway-id 7CWjY3QFoA9dgE535u9bQiXCfz
|
||||
|
||||
- [Feature/testing utils](https://github.com/nymtech/nym/pull/5963): This PR introduces a couple of general helpers, in particular some mocks for sending across values using Stream/Sink and AsyncRead/AsyncWrite without actual underlying networking. Example implementation are with NymNoise (which was the original inspiration) and gateway handshake.
|
||||
|
||||
- [Backport metadata endpoint](https://github.com/nymtech/nym/pull/6010)
|
||||
- [Backport metadata endpoint](https://github.com/nymtech/nym/pull/6010)
|
||||
|
||||
### Bugfix
|
||||
|
||||
- [Fix rust `1.89` `clippy` issues](https://github.com/nymtech/nym/pull/5944)
|
||||
|
||||
- [`http api` client adjustment](https://github.com/nymtech/nym/pull/5953): It fixes missing `feature-lock` when cloning the client and adds helper macro for user agent creation
|
||||
- [`http api` client adjustment](https://github.com/nymtech/nym/pull/5953): It fixes missing `feature-lock` when cloning the client and adds helper macro for user agent creation
|
||||
|
||||
- [Fix `ci-build` for linux (and use updated runner)](https://github.com/nymtech/nym/pull/5958): This PR fixes our build pipeline by using correct (updated) linux runner and updates all the conditional steps that were behind `ubuntu` runners (which no longer exist)
|
||||
|
||||
- [Fixing the ci for ns agent](https://github.com/nymtech/nym/pull/5965)
|
||||
- [Fixing the ci for ns agent](https://github.com/nymtech/nym/pull/5965)
|
||||
|
||||
- [Manually calculate per node work on rewarded set changes](https://github.com/nymtech/nym/pull/5972): This PR fixes:
|
||||
1. Nym rewarded set was set to X, for argument sake say 200
|
||||
1. Nym rewarded set was set to X, for argument sake say 200
|
||||
2. We sent transaction to update it to Y, say 100
|
||||
3. This internally updated the interval rewarding parameters inside the mixnet contract including the default active and standby node work factors. Note that the rewarded set itself stayed the same, as it only changes after epoch rolls over and new one is assigned (by the `nym-api`)
|
||||
4. Epoch has finished and `nym-api` wanted to do the rewarding. It grabbed the **current** rewarded set (of X, 200) and started calculating the total work in the system. But since the contract already had new parameters (adjusted for size of Y, 100), the result was greater than 1 thus `nym-api` was preventably blowing up.
|
||||
To fix it we introduce additional checks, so that if the current rewarded set does not match the specification defined in the contract rewarding parameters, `nym-api` will attempt to do its best to manually calculate work factors for this epoch.
|
||||
|
||||
- [Fix the ns api ci workflow](https://github.com/nymtech/nym/pull/5981)
|
||||
- [Fix the ns api ci workflow](https://github.com/nymtech/nym/pull/5981)
|
||||
|
||||
- [Make sure tables are removed in correct order to not trigger FK constraint issue](https://github.com/nymtech/nym/pull/5987)
|
||||
- [Make sure tables are removed in correct order to not trigger FK constraint issue](https://github.com/nymtech/nym/pull/5987)
|
||||
|
||||
### Refactors & Maintenance
|
||||
|
||||
- [Move credential verifier in peer controller](https://github.com/nymtech/nym/pull/5938): This PR is to not duplicate the verifier code (minus the actual verification operation, which is harder to unit test because of expiration checks)
|
||||
- [Move credential verifier in peer controller](https://github.com/nymtech/nym/pull/5938): This PR is to not duplicate the verifier code (minus the actual verification operation, which is harder to unit test because of expiration checks)
|
||||
|
||||
- [Remove unused import](https://github.com/nymtech/nym/pull/5942)
|
||||
|
||||
@@ -601,7 +283,7 @@ nym-vpnc connect --enable-two-hop --entry-gateway-id 7CWjY3QFoA9dgE535u9bQiXCfz
|
||||
- [Remove freshness check on testrun submit](https://github.com/nymtech/nym/pull/5977):
|
||||
- Freshness is enforced by a background task that marks test runs as stale after a configured amount of time
|
||||
- Make existing freshness period configurable to avoid code changes in the future
|
||||
- Added `humantime` for parsing
|
||||
- Added `humantime` for parsing
|
||||
|
||||
- [Move authenticator into gateway crate](https://github.com/nymtech/nym/pull/5982)
|
||||
|
||||
@@ -624,7 +306,7 @@ nym-vpnc connect --enable-two-hop --entry-gateway-id 7CWjY3QFoA9dgE535u9bQiXCfz
|
||||
|
||||
- [Ecash liveness check](https://github.com/nymtech/nym/pull/5890)
|
||||
|
||||
- [Basic zulip client for sending messages](https://github.com/nymtech/nym/pull/5913): In order to be able to send zulip notifications about *emergency* upgrade mode being activated, we need some sort of client. Unfortunately there isn't any rust library that's maintained (the only one had last commit 4 years ago). This simple thing now currently only supports message sending
|
||||
- [Basic zulip client for sending messages](https://github.com/nymtech/nym/pull/5913): In order to be able to send zulip notifications about *emergency* upgrade mode being activated, we need some sort of client. Unfortunately there isn't any rust library that's maintained (the only one had last commit 4 years ago). This simple thing now currently only supports message sending
|
||||
|
||||
- [`nym-node` debug command to reset providers db](https://github.com/nymtech/nym/pull/5914)
|
||||
|
||||
@@ -634,7 +316,7 @@ nym-vpnc connect --enable-two-hop --entry-gateway-id 7CWjY3QFoA9dgE535u9bQiXCfz
|
||||
|
||||
### Refactors & Maintenance
|
||||
|
||||
- [Allow compatibility with 'CDLA-Permissive-2.0'](https://github.com/nymtech/nym/pull/5910): This license is present in the included `webpki-roots`
|
||||
- [Allow compatibility with 'CDLA-Permissive-2.0'](https://github.com/nymtech/nym/pull/5910): This license is present in the included `webpki-roots`
|
||||
|
||||
- [Migrate strum to `0.27.2`](https://github.com/nymtech/nym/pull/5960): This PR migrates strum to the latest. Notably all macros' were moved into `strum_macros`. The rest stays the same.
|
||||
|
||||
@@ -659,9 +341,9 @@ cargo Profile: release
|
||||
|
||||
### Operators Updates & Tools
|
||||
|
||||
- Stark Industries is on a sanction list by EU. IP addresses managed by Stark Ind. and their subsidies (ASN 44477 / ASN 33993) had been put on [spamhaus.org](http://spamhaus.org/) [list](https://www.spamhaus.org/drop/asndrop.json). The effect on NymVPN user experience is that Exit Gateways IPs hosted on Stark Ind. are seen as a spam proxies by many online services.
|
||||
- Stark Industries is on a sanction list by EU. IP addresses managed by Stark Ind. and their subsidies (ASN 44477 / ASN 33993) had been put on [spamhaus.org](http://spamhaus.org/) [list](https://www.spamhaus.org/drop/asndrop.json). The effect on NymVPN user experience is that Exit Gateways IPs hosted on Stark Ind. are seen as a spam proxies by many online services.
|
||||
|
||||
- We ask operators - especially Exit Gateways - to consider moving to another ISP. Visit an updated [ISP list](community-counsel/isp-list) and feel free to add more providers, following [these steps](community-counsel/add-content).
|
||||
- We ask operators - especially Exit Gateways - to consider moving to another ISP. Visit an updated [ISP list](community-counsel/isp-list) and feel free to add more providers, following [these steps](community-counsel/add-content).
|
||||
|
||||
### Features
|
||||
|
||||
@@ -675,13 +357,13 @@ cargo Profile: release
|
||||
- [`sqlx-pool-guard`: allocate more memory on windows](https://github.com/nymtech/nym/pull/5896):
|
||||
- Allocate 1.5x more memory than reported by the system to provide a safety margin
|
||||
- Increase number of retry attempts to 5
|
||||
|
||||
|
||||
|
||||
- [dkg epoch dealers query](https://github.com/nymtech/nym/pull/5899)
|
||||
|
||||
- [dkg snapshot epoch](https://github.com/nymtech/nym/pull/5900): In order to determine if signer quorum has been down at particular height, we need to know with certainty the dkg epoch id corresponding to given block height. This PR makes it possible. Every time epoch state is changed (due to DKG progress), snapshot is saved and can be queried. This doesn't work for past data, but given mainnet has only had a single DKG instance, that's not an issue.
|
||||
|
||||
- [`sqlx-pool-guard`: obtain filename from connect options](https://github.com/nymtech/nym/pull/5905):
|
||||
- [`sqlx-pool-guard`: obtain filename from connect options](https://github.com/nymtech/nym/pull/5905):
|
||||
|
||||
### Refactors & Maintenance
|
||||
|
||||
@@ -737,7 +419,7 @@ cargo Profile: release
|
||||
|
||||
- [Remove old explorer references](https://github.com/nymtech/nym/pull/5846)
|
||||
|
||||
- [Listen for shutdown signals during nym-node startup](https://github.com/nymtech/nym/pull/5879): This is to avoid situation where the process can't be killed without 'kill -9' because the logic to listen to shutdown signals hasn't been hit yet
|
||||
- [Listen for shutdown signals during nym-node startup](https://github.com/nymtech/nym/pull/5879): This is to avoid situation where the process can't be killed without 'kill -9' because the logic to listen to shutdown signals hasn't been hit yet
|
||||
|
||||
### Bugfixes
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import ExitPolicyStatusOutput from 'components/operators/snippets/wg-exit-policy
|
||||
import ExitPolicyTestOutput from 'components/operators/snippets/wg-exit-policy-test-output.mdx';
|
||||
import ExitPolicyTestServer from 'components/operators/snippets/wg-exit-policy-testing-from-server.mdx';
|
||||
import ExitPolicyTestOutside from 'components/operators/snippets/wg-exit-policy-testing-from-outside.mdx';
|
||||
import QuicDeploymentSteps from 'components/operators/snippets/quic-bridge-deployment-script-setup.mdx';
|
||||
|
||||
|
||||
export const ManagerIPOutput = () => (
|
||||
@@ -535,9 +534,6 @@ You can validate the application of the IP tables routes on your `nym-node` by c
|
||||
|
||||
Your node has successfully implemented wireguard exit policy with the same routing permissions like [Nym exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) used on 5-hop (Mixnet).
|
||||
|
||||
## QUIC Transport Bridge Deployment
|
||||
|
||||
<QuicDeploymentSteps />
|
||||
|
||||
## Running `nym-node` as a non-root
|
||||
|
||||
|
||||
@@ -21,13 +21,13 @@ This documentation page provides a guide on how to set up and run a [NYM NODE](.
|
||||
```sh
|
||||
nym-node
|
||||
Binary Name: nym-node
|
||||
Build Timestamp: 2025-10-15T09:04:32.043934599Z
|
||||
Build Version: 1.19.0
|
||||
Commit SHA: 2235a6e1477bea7368ee5443a298f544deb63504
|
||||
Commit Date: 2025-10-15T10:22:16.000000000+02:00
|
||||
Commit Branch: master
|
||||
rustc Version: 1.92.0-nightly
|
||||
rustc Channel: nightly
|
||||
Build Timestamp: 2025-10-01T10:42:58.647419869Z
|
||||
Build Version: 1.18.0
|
||||
Commit SHA: bbea2ff9e913f49cb7bf6c7bafa9d9b158c80de5
|
||||
Commit Date: 2025-10-01T12:06:07.000000000+02:00
|
||||
Commit Branch: HEAD
|
||||
rustc Version: 1.88.0
|
||||
rustc Channel: stable
|
||||
cargo Profile: release
|
||||
```
|
||||
|
||||
|
||||
Generated
+138
-194
@@ -36,11 +36,11 @@ importers:
|
||||
specifier: ^0.32.2
|
||||
version: 0.32.4
|
||||
'@cosmos-kit/core':
|
||||
specifier: ^2.16.3
|
||||
specifier: ^2.8.9
|
||||
version: 2.16.3
|
||||
'@cosmos-kit/keplr':
|
||||
specifier: ^2.6.9
|
||||
version: 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@5.9.3)(zod@3.25.76)
|
||||
version: 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@4.9.5)(zod@3.25.76)
|
||||
'@cosmos-kit/keplr-extension':
|
||||
specifier: ^2.7.9
|
||||
version: 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(starknet@7.6.4)
|
||||
@@ -48,41 +48,38 @@ importers:
|
||||
specifier: ^2.6.9
|
||||
version: 2.14.3(@cosmjs/amino@0.32.4)(@cosmjs/crypto@0.32.4)(@cosmjs/encoding@0.32.4)(@cosmjs/proto-signing@0.32.4)
|
||||
'@cosmos-kit/react':
|
||||
specifier: ^2.22.3
|
||||
version: 2.22.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@interchain-ui/react@1.26.3(@types/react@18.3.26)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
specifier: ^2.10.11
|
||||
version: 2.22.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@interchain-ui/react@1.26.3(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@emotion/react':
|
||||
specifier: ^11.11.1
|
||||
version: 11.14.0(@types/react@18.3.26)(react@18.3.1)
|
||||
version: 11.14.0(react@18.3.1)
|
||||
'@emotion/styled':
|
||||
specifier: ^11.11.0
|
||||
version: 11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
|
||||
version: 11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1)
|
||||
'@interchain-ui/react':
|
||||
specifier: ^1.8.0
|
||||
version: 1.26.3(@types/react@18.3.26)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
version: 1.26.3(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@mui/icons-material':
|
||||
specifier: ^5.14.9
|
||||
version: 5.18.0(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
|
||||
version: 5.18.0(@mui/material@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||
'@mui/lab':
|
||||
specifier: ^5.0.0-alpha.145
|
||||
version: 5.0.0-alpha.177(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
version: 5.0.0-alpha.177(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(@mui/material@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@mui/material':
|
||||
specifier: ^5.14.8
|
||||
version: 5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
version: 5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/accordion':
|
||||
specifier: ^2.0.40
|
||||
version: 2.2.7(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/react':
|
||||
specifier: ^2.4.8
|
||||
version: 2.6.11(@types/react@18.3.26)(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@4.1.12)
|
||||
'@nymproject/contract-clients':
|
||||
specifier: '>=1.2.4-rc.2 || ^1'
|
||||
version: 1.4.1
|
||||
version: 2.6.11(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@4.1.12)
|
||||
'@nymproject/mix-fetch-full-fat':
|
||||
specifier: '>=1.2.4-rc.2 || ^1'
|
||||
version: 1.2.3
|
||||
specifier: file:../../dist/wasm/mix-fetch
|
||||
version: '@nymproject/mix-fetch-wasm@file:../../dist/wasm/mix-fetch'
|
||||
'@nymproject/sdk-full-fat':
|
||||
specifier: '>=1.2.4-rc.2 || ^1'
|
||||
version: 1.2.3
|
||||
specifier: file:../../dist/wasm/client
|
||||
version: '@nymproject/nym-client-wasm@file:../../dist/wasm/client'
|
||||
'@redocly/cli':
|
||||
specifier: ^1.25.15
|
||||
version: 1.34.5(ajv@8.17.1)
|
||||
@@ -120,18 +117,9 @@ importers:
|
||||
specifier: ^9.0.0
|
||||
version: 9.0.1
|
||||
devDependencies:
|
||||
'@next/swc-linux-x64-gnu':
|
||||
specifier: 15.5.0
|
||||
version: 15.5.0
|
||||
'@types/node':
|
||||
specifier: 18.11.10
|
||||
version: 18.11.10
|
||||
'@types/react':
|
||||
specifier: ^18.3.26
|
||||
version: 18.3.26
|
||||
'@types/react-dom':
|
||||
specifier: ^18.3.7
|
||||
version: 18.3.7(@types/react@18.3.26)
|
||||
copy-webpack-plugin:
|
||||
specifier: ^11.0.0
|
||||
version: 11.0.0(webpack@5.101.3)
|
||||
@@ -140,13 +128,13 @@ importers:
|
||||
version: 8.46.0
|
||||
eslint-config-next:
|
||||
specifier: 13.4.13
|
||||
version: 13.4.13(eslint@8.46.0)(typescript@5.9.3)
|
||||
version: 13.4.13(eslint@8.46.0)(typescript@4.9.5)
|
||||
raw-loader:
|
||||
specifier: ^4.0.2
|
||||
version: 4.0.2(webpack@5.101.3)
|
||||
typescript:
|
||||
specifier: ^5.9.3
|
||||
version: 5.9.3
|
||||
specifier: ^4.9.3
|
||||
version: 4.9.5
|
||||
|
||||
packages:
|
||||
|
||||
@@ -1676,14 +1664,11 @@ packages:
|
||||
resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
|
||||
engines: {node: '>=12.4.0'}
|
||||
|
||||
'@nymproject/contract-clients@1.4.1':
|
||||
resolution: {integrity: sha512-HuJZ4Hv+Rl6ZZEtCHKgurNLJapM+QQRJlGkevFH2a4UdqUqF9omUkUi3AVes4679dPoSFgvA7plyVSDBdbgV6w==}
|
||||
'@nymproject/mix-fetch-wasm@file:../../dist/wasm/mix-fetch':
|
||||
resolution: {directory: ../../dist/wasm/mix-fetch, type: directory}
|
||||
|
||||
'@nymproject/mix-fetch-full-fat@1.2.3':
|
||||
resolution: {integrity: sha512-5yAQhw33LC0cNsyV0Rj+LIa2kvJY+8jsfgOSr1aeKNfQ7dG4fngWkKnGUbPGzhUTJjqgXPTwNVeJSd6hwGim+g==}
|
||||
|
||||
'@nymproject/sdk-full-fat@1.2.3':
|
||||
resolution: {integrity: sha512-lheA1Zk020o2t95FPVZfdUR0aSI52aD0aJQs074fjH16QkoNNEMotzhJGAnsnnczVg3bpddKghNpCLyDOWvg9A==}
|
||||
'@nymproject/nym-client-wasm@file:../../dist/wasm/client':
|
||||
resolution: {directory: ../../dist/wasm/client, type: directory}
|
||||
|
||||
'@opentelemetry/api-logs@0.53.0':
|
||||
resolution: {integrity: sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==}
|
||||
@@ -2859,18 +2844,13 @@ packages:
|
||||
'@types/prop-types@15.7.15':
|
||||
resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
|
||||
|
||||
'@types/react-dom@18.3.7':
|
||||
resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==}
|
||||
peerDependencies:
|
||||
'@types/react': ^18.0.0
|
||||
|
||||
'@types/react-transition-group@4.4.12':
|
||||
resolution: {integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
|
||||
'@types/react@18.3.26':
|
||||
resolution: {integrity: sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==}
|
||||
'@types/react@19.1.10':
|
||||
resolution: {integrity: sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==}
|
||||
|
||||
'@types/stylis@4.2.5':
|
||||
resolution: {integrity: sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==}
|
||||
@@ -6406,9 +6386,9 @@ packages:
|
||||
typeforce@1.18.0:
|
||||
resolution: {integrity: sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==}
|
||||
|
||||
typescript@5.9.3:
|
||||
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
||||
engines: {node: '>=14.17'}
|
||||
typescript@4.9.5:
|
||||
resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==}
|
||||
engines: {node: '>=4.2.0'}
|
||||
hasBin: true
|
||||
|
||||
ufo@1.6.1:
|
||||
@@ -7179,16 +7159,16 @@ snapshots:
|
||||
- uploadthing
|
||||
- utf-8-validate
|
||||
|
||||
'@cosmos-kit/keplr-mobile@2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@5.9.3)(zod@3.25.76)':
|
||||
'@cosmos-kit/keplr-mobile@2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@4.9.5)(zod@3.25.76)':
|
||||
dependencies:
|
||||
'@chain-registry/keplr': 1.74.313
|
||||
'@cosmjs/amino': 0.32.4
|
||||
'@cosmjs/proto-signing': 0.32.4
|
||||
'@cosmos-kit/core': 2.16.3
|
||||
'@cosmos-kit/keplr-extension': 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(starknet@7.6.4)
|
||||
'@cosmos-kit/walletconnect': 2.13.3(@cosmjs/amino@0.32.4)(@walletconnect/types@2.21.8)(typescript@5.9.3)(zod@3.25.76)
|
||||
'@cosmos-kit/walletconnect': 2.13.3(@cosmjs/amino@0.32.4)(@walletconnect/types@2.21.8)(typescript@4.9.5)(zod@3.25.76)
|
||||
'@keplr-wallet/provider-extension': 0.12.264(starknet@7.6.4)
|
||||
'@keplr-wallet/wc-client': 0.12.264(@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)
|
||||
'@keplr-wallet/wc-client': 0.12.264(@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)
|
||||
transitivePeerDependencies:
|
||||
- '@azure/app-configuration'
|
||||
- '@azure/cosmos'
|
||||
@@ -7219,10 +7199,10 @@ snapshots:
|
||||
- utf-8-validate
|
||||
- zod
|
||||
|
||||
'@cosmos-kit/keplr@2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@5.9.3)(zod@3.25.76)':
|
||||
'@cosmos-kit/keplr@2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@4.9.5)(zod@3.25.76)':
|
||||
dependencies:
|
||||
'@cosmos-kit/keplr-extension': 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(starknet@7.6.4)
|
||||
'@cosmos-kit/keplr-mobile': 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@5.9.3)(zod@3.25.76)
|
||||
'@cosmos-kit/keplr-mobile': 2.15.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)(typescript@4.9.5)(zod@3.25.76)
|
||||
transitivePeerDependencies:
|
||||
- '@azure/app-configuration'
|
||||
- '@azure/cosmos'
|
||||
@@ -7290,13 +7270,11 @@ snapshots:
|
||||
- uploadthing
|
||||
- utf-8-validate
|
||||
|
||||
'@cosmos-kit/react-lite@2.16.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
'@cosmos-kit/react-lite@2.16.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@chain-registry/types': 0.46.15
|
||||
'@cosmos-kit/core': 2.16.3
|
||||
'@dao-dao/cosmiframe': 1.0.0(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)
|
||||
'@types/react': 18.3.26
|
||||
'@types/react-dom': 18.3.7(@types/react@18.3.26)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
transitivePeerDependencies:
|
||||
@@ -7326,15 +7304,13 @@ snapshots:
|
||||
- uploadthing
|
||||
- utf-8-validate
|
||||
|
||||
'@cosmos-kit/react@2.22.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@interchain-ui/react@1.26.3(@types/react@18.3.26)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
'@cosmos-kit/react@2.22.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@interchain-ui/react@1.26.3(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@chain-registry/types': 0.46.15
|
||||
'@cosmos-kit/core': 2.16.3
|
||||
'@cosmos-kit/react-lite': 2.16.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@interchain-ui/react': 1.26.3(@types/react@18.3.26)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@cosmos-kit/react-lite': 2.16.3(@cosmjs/amino@0.32.4)(@cosmjs/proto-signing@0.32.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@interchain-ui/react': 1.26.3(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@react-icons/all-files': 4.1.0(react@18.3.1)
|
||||
'@types/react': 18.3.26
|
||||
'@types/react-dom': 18.3.7(@types/react@18.3.26)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
transitivePeerDependencies:
|
||||
@@ -7364,14 +7340,14 @@ snapshots:
|
||||
- uploadthing
|
||||
- utf-8-validate
|
||||
|
||||
'@cosmos-kit/walletconnect@2.13.3(@cosmjs/amino@0.32.4)(@walletconnect/types@2.21.8)(typescript@5.9.3)(zod@3.25.76)':
|
||||
'@cosmos-kit/walletconnect@2.13.3(@cosmjs/amino@0.32.4)(@walletconnect/types@2.21.8)(typescript@4.9.5)(zod@3.25.76)':
|
||||
dependencies:
|
||||
'@cosmjs/amino': 0.32.4
|
||||
'@cosmjs/proto-signing': 0.32.4
|
||||
'@cosmos-kit/core': 2.16.3
|
||||
'@walletconnect/sign-client': 2.21.8(typescript@5.9.3)(zod@3.25.76)
|
||||
'@walletconnect/sign-client': 2.21.8(typescript@4.9.5)(zod@3.25.76)
|
||||
'@walletconnect/types': 2.21.8
|
||||
'@walletconnect/utils': 2.21.8(typescript@5.9.3)(zod@3.25.76)
|
||||
'@walletconnect/utils': 2.21.8(typescript@4.9.5)(zod@3.25.76)
|
||||
events: 3.3.0
|
||||
transitivePeerDependencies:
|
||||
- '@azure/app-configuration'
|
||||
@@ -7460,7 +7436,7 @@ snapshots:
|
||||
|
||||
'@emotion/memoize@0.9.0': {}
|
||||
|
||||
'@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1)':
|
||||
'@emotion/react@11.14.0(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.3
|
||||
'@emotion/babel-plugin': 11.13.5
|
||||
@@ -7471,8 +7447,6 @@ snapshots:
|
||||
'@emotion/weak-memoize': 0.4.0
|
||||
hoist-non-react-statics: 3.3.2
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.26
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -7486,18 +7460,16 @@ snapshots:
|
||||
|
||||
'@emotion/sheet@1.4.0': {}
|
||||
|
||||
'@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)':
|
||||
'@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.3
|
||||
'@emotion/babel-plugin': 11.13.5
|
||||
'@emotion/is-prop-valid': 1.3.1
|
||||
'@emotion/react': 11.14.0(@types/react@18.3.26)(react@18.3.1)
|
||||
'@emotion/react': 11.14.0(react@18.3.1)
|
||||
'@emotion/serialize': 1.3.3
|
||||
'@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1)
|
||||
'@emotion/utils': 1.4.2
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.26
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -7730,7 +7702,7 @@ snapshots:
|
||||
'@img/sharp-win32-x64@0.34.3':
|
||||
optional: true
|
||||
|
||||
'@interchain-ui/react@1.26.3(@types/react@18.3.26)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
'@interchain-ui/react@1.26.3(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.7.3
|
||||
'@floating-ui/dom': 1.7.3
|
||||
@@ -7759,7 +7731,7 @@ snapshots:
|
||||
react-aria: 3.42.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
react-stately: 3.40.0(react@18.3.1)
|
||||
zustand: 4.5.7(@types/react@18.3.26)(immer@10.1.1)(react@18.3.1)
|
||||
zustand: 4.5.7(immer@10.1.1)(react@18.3.1)
|
||||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
- babel-plugin-macros
|
||||
@@ -7892,11 +7864,11 @@ snapshots:
|
||||
big-integer: 1.6.52
|
||||
utility-types: 3.11.0
|
||||
|
||||
'@keplr-wallet/wc-client@0.12.264(@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)':
|
||||
'@keplr-wallet/wc-client@0.12.264(@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76))(@walletconnect/types@2.21.8)(starknet@7.6.4)':
|
||||
dependencies:
|
||||
'@keplr-wallet/provider': 0.12.264(starknet@7.6.4)
|
||||
'@keplr-wallet/types': 0.12.264(starknet@7.6.4)
|
||||
'@walletconnect/sign-client': 2.21.8(typescript@5.9.3)(zod@3.25.76)
|
||||
'@walletconnect/sign-client': 2.21.8(typescript@4.9.5)(zod@3.25.76)
|
||||
'@walletconnect/types': 2.21.8
|
||||
buffer: 6.0.3
|
||||
deepmerge: 4.3.1
|
||||
@@ -7966,61 +7938,56 @@ snapshots:
|
||||
'@mdx-js/react@2.3.0(react@18.3.1)':
|
||||
dependencies:
|
||||
'@types/mdx': 2.0.13
|
||||
'@types/react': 18.3.26
|
||||
'@types/react': 19.1.10
|
||||
react: 18.3.1
|
||||
|
||||
'@msgpack/msgpack@3.1.2': {}
|
||||
|
||||
'@mui/base@5.0.0-beta.40-1(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
'@mui/base@5.0.0-beta.40-1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.3
|
||||
'@floating-ui/react-dom': 2.1.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@mui/types': 7.2.24(@types/react@18.3.26)
|
||||
'@mui/utils': 5.17.1(@types/react@18.3.26)(react@18.3.1)
|
||||
'@mui/types': 7.2.24
|
||||
'@mui/utils': 5.17.1(react@18.3.1)
|
||||
'@popperjs/core': 2.11.8
|
||||
clsx: 2.1.1
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.26
|
||||
|
||||
'@mui/core-downloads-tracker@5.18.0': {}
|
||||
|
||||
'@mui/icons-material@5.18.0(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)':
|
||||
'@mui/icons-material@5.18.0(@mui/material@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.3
|
||||
'@mui/material': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@mui/material': 5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.26
|
||||
|
||||
'@mui/lab@5.0.0-alpha.177(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
'@mui/lab@5.0.0-alpha.177(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(@mui/material@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.3
|
||||
'@mui/base': 5.0.0-beta.40-1(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@mui/material': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@mui/system': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
|
||||
'@mui/types': 7.2.24(@types/react@18.3.26)
|
||||
'@mui/utils': 5.17.1(@types/react@18.3.26)(react@18.3.1)
|
||||
'@mui/base': 5.0.0-beta.40-1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@mui/material': 5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@mui/system': 5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||
'@mui/types': 7.2.24
|
||||
'@mui/utils': 5.17.1(react@18.3.1)
|
||||
clsx: 2.1.1
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.14.0(@types/react@18.3.26)(react@18.3.1)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
|
||||
'@types/react': 18.3.26
|
||||
'@emotion/react': 11.14.0(react@18.3.1)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1)
|
||||
|
||||
'@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
'@mui/material@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.3
|
||||
'@mui/core-downloads-tracker': 5.18.0
|
||||
'@mui/system': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
|
||||
'@mui/types': 7.2.24(@types/react@18.3.26)
|
||||
'@mui/utils': 5.17.1(@types/react@18.3.26)(react@18.3.1)
|
||||
'@mui/system': 5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||
'@mui/types': 7.2.24
|
||||
'@mui/utils': 5.17.1(react@18.3.1)
|
||||
'@popperjs/core': 2.11.8
|
||||
'@types/react-transition-group': 4.4.12(@types/react@18.3.26)
|
||||
'@types/react-transition-group': 4.4.12
|
||||
clsx: 2.1.1
|
||||
csstype: 3.1.3
|
||||
prop-types: 15.8.1
|
||||
@@ -8029,20 +7996,17 @@ snapshots:
|
||||
react-is: 19.1.1
|
||||
react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.14.0(@types/react@18.3.26)(react@18.3.1)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
|
||||
'@types/react': 18.3.26
|
||||
'@emotion/react': 11.14.0(react@18.3.1)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1)
|
||||
|
||||
'@mui/private-theming@5.17.1(@types/react@18.3.26)(react@18.3.1)':
|
||||
'@mui/private-theming@5.17.1(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.3
|
||||
'@mui/utils': 5.17.1(@types/react@18.3.26)(react@18.3.1)
|
||||
'@mui/utils': 5.17.1(react@18.3.1)
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.26
|
||||
|
||||
'@mui/styled-engine@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(react@18.3.1)':
|
||||
'@mui/styled-engine@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.3
|
||||
'@emotion/cache': 11.14.0
|
||||
@@ -8051,40 +8015,35 @@ snapshots:
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.14.0(@types/react@18.3.26)(react@18.3.1)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
|
||||
'@emotion/react': 11.14.0(react@18.3.1)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1)
|
||||
|
||||
'@mui/system@5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)':
|
||||
'@mui/system@5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.3
|
||||
'@mui/private-theming': 5.17.1(@types/react@18.3.26)(react@18.3.1)
|
||||
'@mui/styled-engine': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1))(react@18.3.1)
|
||||
'@mui/types': 7.2.24(@types/react@18.3.26)
|
||||
'@mui/utils': 5.17.1(@types/react@18.3.26)(react@18.3.1)
|
||||
'@mui/private-theming': 5.17.1(react@18.3.1)
|
||||
'@mui/styled-engine': 5.18.0(@emotion/react@11.14.0(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||
'@mui/types': 7.2.24
|
||||
'@mui/utils': 5.17.1(react@18.3.1)
|
||||
clsx: 2.1.1
|
||||
csstype: 3.1.3
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.14.0(@types/react@18.3.26)(react@18.3.1)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.26)(react@18.3.1))(@types/react@18.3.26)(react@18.3.1)
|
||||
'@types/react': 18.3.26
|
||||
'@emotion/react': 11.14.0(react@18.3.1)
|
||||
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(react@18.3.1))(react@18.3.1)
|
||||
|
||||
'@mui/types@7.2.24(@types/react@18.3.26)':
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.26
|
||||
'@mui/types@7.2.24': {}
|
||||
|
||||
'@mui/utils@5.17.1(@types/react@18.3.26)(react@18.3.1)':
|
||||
'@mui/utils@5.17.1(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.3
|
||||
'@mui/types': 7.2.24(@types/react@18.3.26)
|
||||
'@mui/types': 7.2.24
|
||||
'@types/prop-types': 15.7.15
|
||||
clsx: 2.1.1
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
react-is: 19.1.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.26
|
||||
|
||||
'@napi-rs/simple-git-android-arm-eabi@0.1.22':
|
||||
optional: true
|
||||
@@ -8174,7 +8133,8 @@ snapshots:
|
||||
'@next/swc-linux-arm64-musl@15.5.0':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-gnu@15.5.0': {}
|
||||
'@next/swc-linux-x64-gnu@15.5.0':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-musl@15.5.0':
|
||||
optional: true
|
||||
@@ -8239,12 +8199,12 @@ snapshots:
|
||||
- '@nextui-org/theme'
|
||||
- framer-motion
|
||||
|
||||
'@nextui-org/autocomplete@2.3.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(@types/react@18.3.26)(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
'@nextui-org/autocomplete@2.3.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@nextui-org/aria-utils': 2.2.7(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/button': 2.2.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/form': 2.1.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/input': 2.4.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/input': 2.4.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/listbox': 2.3.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/popover': 2.3.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/react-utils': 2.1.3(react@18.3.1)
|
||||
@@ -8556,7 +8516,7 @@ snapshots:
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@nextui-org/input@2.4.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
'@nextui-org/input@2.4.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@nextui-org/form': 2.1.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/react-utils': 2.1.3(react@18.3.1)
|
||||
@@ -8574,7 +8534,7 @@ snapshots:
|
||||
'@react-types/textfield': 3.10.0(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
react-textarea-autosize: 8.5.9(@types/react@18.3.26)(react@18.3.1)
|
||||
react-textarea-autosize: 8.5.9(react@18.3.1)
|
||||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
|
||||
@@ -8774,11 +8734,11 @@ snapshots:
|
||||
'@nextui-org/shared-utils': 2.1.2
|
||||
react: 18.3.1
|
||||
|
||||
'@nextui-org/react@2.6.11(@types/react@18.3.26)(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@4.1.12)':
|
||||
'@nextui-org/react@2.6.11(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@4.1.12)':
|
||||
dependencies:
|
||||
'@nextui-org/accordion': 2.2.7(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/alert': 2.2.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/autocomplete': 2.3.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(@types/react@18.3.26)(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/autocomplete': 2.3.9(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/avatar': 2.2.6(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/badge': 2.2.5(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/breadcrumbs': 2.2.6(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
@@ -8796,7 +8756,7 @@ snapshots:
|
||||
'@nextui-org/form': 2.1.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/framer-utils': 2.1.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/image': 2.2.5(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/input': 2.4.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/input': 2.4.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/input-otp': 2.1.8(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/kbd': 2.2.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@nextui-org/link': 2.2.7(@nextui-org/system@2.4.6(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(framer-motion@12.23.12(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.4.5(tailwindcss@4.1.12))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
@@ -9245,11 +9205,9 @@ snapshots:
|
||||
|
||||
'@nolyfill/is-core-module@1.0.39': {}
|
||||
|
||||
'@nymproject/contract-clients@1.4.1': {}
|
||||
'@nymproject/mix-fetch-wasm@file:../../dist/wasm/mix-fetch': {}
|
||||
|
||||
'@nymproject/mix-fetch-full-fat@1.2.3': {}
|
||||
|
||||
'@nymproject/sdk-full-fat@1.2.3': {}
|
||||
'@nymproject/nym-client-wasm@file:../../dist/wasm/client': {}
|
||||
|
||||
'@opentelemetry/api-logs@0.53.0':
|
||||
dependencies:
|
||||
@@ -11211,17 +11169,10 @@ snapshots:
|
||||
|
||||
'@types/prop-types@15.7.15': {}
|
||||
|
||||
'@types/react-dom@18.3.7(@types/react@18.3.26)':
|
||||
dependencies:
|
||||
'@types/react': 18.3.26
|
||||
'@types/react-transition-group@4.4.12': {}
|
||||
|
||||
'@types/react-transition-group@4.4.12(@types/react@18.3.26)':
|
||||
'@types/react@19.1.10':
|
||||
dependencies:
|
||||
'@types/react': 18.3.26
|
||||
|
||||
'@types/react@18.3.26':
|
||||
dependencies:
|
||||
'@types/prop-types': 15.7.15
|
||||
csstype: 3.1.3
|
||||
|
||||
'@types/stylis@4.2.5': {}
|
||||
@@ -11233,16 +11184,16 @@ snapshots:
|
||||
|
||||
'@types/unist@3.0.3': {}
|
||||
|
||||
'@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@5.9.3)':
|
||||
'@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@4.9.5)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 6.21.0
|
||||
'@typescript-eslint/types': 6.21.0
|
||||
'@typescript-eslint/typescript-estree': 6.21.0(typescript@5.9.3)
|
||||
'@typescript-eslint/typescript-estree': 6.21.0(typescript@4.9.5)
|
||||
'@typescript-eslint/visitor-keys': 6.21.0
|
||||
debug: 4.4.1
|
||||
eslint: 8.46.0
|
||||
optionalDependencies:
|
||||
typescript: 5.9.3
|
||||
typescript: 4.9.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -11253,7 +11204,7 @@ snapshots:
|
||||
|
||||
'@typescript-eslint/types@6.21.0': {}
|
||||
|
||||
'@typescript-eslint/typescript-estree@6.21.0(typescript@5.9.3)':
|
||||
'@typescript-eslint/typescript-estree@6.21.0(typescript@4.9.5)':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 6.21.0
|
||||
'@typescript-eslint/visitor-keys': 6.21.0
|
||||
@@ -11262,9 +11213,9 @@ snapshots:
|
||||
is-glob: 4.0.3
|
||||
minimatch: 9.0.3
|
||||
semver: 7.7.2
|
||||
ts-api-utils: 1.4.3(typescript@5.9.3)
|
||||
ts-api-utils: 1.4.3(typescript@4.9.5)
|
||||
optionalDependencies:
|
||||
typescript: 5.9.3
|
||||
typescript: 4.9.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -11363,7 +11314,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@vanilla-extract/css': 1.17.4(babel-plugin-macros@3.1.0)
|
||||
|
||||
'@walletconnect/core@2.21.8(typescript@5.9.3)(zod@3.25.76)':
|
||||
'@walletconnect/core@2.21.8(typescript@4.9.5)(zod@3.25.76)':
|
||||
dependencies:
|
||||
'@walletconnect/heartbeat': 1.2.2
|
||||
'@walletconnect/jsonrpc-provider': 1.0.14
|
||||
@@ -11377,7 +11328,7 @@ snapshots:
|
||||
'@walletconnect/safe-json': 1.0.2
|
||||
'@walletconnect/time': 1.0.2
|
||||
'@walletconnect/types': 2.21.8
|
||||
'@walletconnect/utils': 2.21.8(typescript@5.9.3)(zod@3.25.76)
|
||||
'@walletconnect/utils': 2.21.8(typescript@4.9.5)(zod@3.25.76)
|
||||
'@walletconnect/window-getters': 1.0.1
|
||||
es-toolkit: 1.39.3
|
||||
events: 3.3.0
|
||||
@@ -11504,16 +11455,16 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 1.14.1
|
||||
|
||||
'@walletconnect/sign-client@2.21.8(typescript@5.9.3)(zod@3.25.76)':
|
||||
'@walletconnect/sign-client@2.21.8(typescript@4.9.5)(zod@3.25.76)':
|
||||
dependencies:
|
||||
'@walletconnect/core': 2.21.8(typescript@5.9.3)(zod@3.25.76)
|
||||
'@walletconnect/core': 2.21.8(typescript@4.9.5)(zod@3.25.76)
|
||||
'@walletconnect/events': 1.0.1
|
||||
'@walletconnect/heartbeat': 1.2.2
|
||||
'@walletconnect/jsonrpc-utils': 1.0.8
|
||||
'@walletconnect/logger': 2.1.2
|
||||
'@walletconnect/time': 1.0.2
|
||||
'@walletconnect/types': 2.21.8
|
||||
'@walletconnect/utils': 2.21.8(typescript@5.9.3)(zod@3.25.76)
|
||||
'@walletconnect/utils': 2.21.8(typescript@4.9.5)(zod@3.25.76)
|
||||
events: 3.3.0
|
||||
transitivePeerDependencies:
|
||||
- '@azure/app-configuration'
|
||||
@@ -11599,7 +11550,7 @@ snapshots:
|
||||
- ioredis
|
||||
- uploadthing
|
||||
|
||||
'@walletconnect/utils@2.21.8(typescript@5.9.3)(zod@3.25.76)':
|
||||
'@walletconnect/utils@2.21.8(typescript@4.9.5)(zod@3.25.76)':
|
||||
dependencies:
|
||||
'@msgpack/msgpack': 3.1.2
|
||||
'@noble/ciphers': 1.3.0
|
||||
@@ -11620,7 +11571,7 @@ snapshots:
|
||||
detect-browser: 5.3.0
|
||||
query-string: 7.1.3
|
||||
uint8arrays: 3.1.1
|
||||
viem: 2.31.0(typescript@5.9.3)(zod@3.25.76)
|
||||
viem: 2.31.0(typescript@4.9.5)(zod@3.25.76)
|
||||
transitivePeerDependencies:
|
||||
- '@azure/app-configuration'
|
||||
- '@azure/cosmos'
|
||||
@@ -11741,9 +11692,9 @@ snapshots:
|
||||
fs-extra: 10.1.0
|
||||
yargs: 17.7.2
|
||||
|
||||
abitype@1.0.8(typescript@5.9.3)(zod@3.25.76):
|
||||
abitype@1.0.8(typescript@4.9.5)(zod@3.25.76):
|
||||
optionalDependencies:
|
||||
typescript: 5.9.3
|
||||
typescript: 4.9.5
|
||||
zod: 3.25.76
|
||||
|
||||
abort-controller@3.0.0:
|
||||
@@ -12759,20 +12710,20 @@ snapshots:
|
||||
|
||||
escape-string-regexp@5.0.0: {}
|
||||
|
||||
eslint-config-next@13.4.13(eslint@8.46.0)(typescript@5.9.3):
|
||||
eslint-config-next@13.4.13(eslint@8.46.0)(typescript@4.9.5):
|
||||
dependencies:
|
||||
'@next/eslint-plugin-next': 13.4.13
|
||||
'@rushstack/eslint-patch': 1.12.0
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.46.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.46.0)(typescript@4.9.5)
|
||||
eslint: 8.46.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@4.9.5))(eslint-import-resolver-typescript@3.10.1)(eslint@8.46.0)
|
||||
eslint-plugin-jsx-a11y: 6.10.2(eslint@8.46.0)
|
||||
eslint-plugin-react: 7.37.5(eslint@8.46.0)
|
||||
eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.46.0)
|
||||
optionalDependencies:
|
||||
typescript: 5.9.3
|
||||
typescript: 4.9.5
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-webpack
|
||||
- eslint-plugin-import-x
|
||||
@@ -12797,22 +12748,22 @@ snapshots:
|
||||
tinyglobby: 0.2.14
|
||||
unrs-resolver: 1.11.1
|
||||
optionalDependencies:
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@4.9.5))(eslint-import-resolver-typescript@3.10.1)(eslint@8.46.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.12.1(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0):
|
||||
eslint-module-utils@2.12.1(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.46.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.46.0)(typescript@4.9.5)
|
||||
eslint: 8.46.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0):
|
||||
eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@4.9.5))(eslint-import-resolver-typescript@3.10.1)(eslint@8.46.0):
|
||||
dependencies:
|
||||
'@rtsao/scc': 1.1.0
|
||||
array-includes: 3.1.9
|
||||
@@ -12823,7 +12774,7 @@ snapshots:
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.46.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.12.1(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0)
|
||||
eslint-module-utils: 2.12.1(@typescript-eslint/parser@6.21.0(eslint@8.46.0)(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.46.0))(eslint@8.46.0))(eslint@8.46.0)
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.16.1
|
||||
is-glob: 4.0.3
|
||||
@@ -12835,7 +12786,7 @@ snapshots:
|
||||
string.prototype.trimend: 1.0.9
|
||||
tsconfig-paths: 3.15.0
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.46.0)(typescript@5.9.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.46.0)(typescript@4.9.5)
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
@@ -14704,7 +14655,7 @@ snapshots:
|
||||
object-keys: 1.1.1
|
||||
safe-push-apply: 1.0.0
|
||||
|
||||
ox@0.7.1(typescript@5.9.3)(zod@3.25.76):
|
||||
ox@0.7.1(typescript@4.9.5)(zod@3.25.76):
|
||||
dependencies:
|
||||
'@adraffy/ens-normalize': 1.11.0
|
||||
'@noble/ciphers': 1.3.0
|
||||
@@ -14712,10 +14663,10 @@ snapshots:
|
||||
'@noble/hashes': 1.8.0
|
||||
'@scure/bip32': 1.7.0
|
||||
'@scure/bip39': 1.6.0
|
||||
abitype: 1.0.8(typescript@5.9.3)(zod@3.25.76)
|
||||
abitype: 1.0.8(typescript@4.9.5)(zod@3.25.76)
|
||||
eventemitter3: 5.0.1
|
||||
optionalDependencies:
|
||||
typescript: 5.9.3
|
||||
typescript: 4.9.5
|
||||
transitivePeerDependencies:
|
||||
- zod
|
||||
|
||||
@@ -15027,12 +14978,12 @@ snapshots:
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
|
||||
react-textarea-autosize@8.5.9(@types/react@18.3.26)(react@18.3.1):
|
||||
react-textarea-autosize@8.5.9(react@18.3.1):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.3
|
||||
react: 18.3.1
|
||||
use-composed-ref: 1.4.0(@types/react@18.3.26)(react@18.3.1)
|
||||
use-latest: 1.3.0(@types/react@18.3.26)(react@18.3.1)
|
||||
use-composed-ref: 1.4.0(react@18.3.1)
|
||||
use-latest: 1.3.0(react@18.3.1)
|
||||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
|
||||
@@ -15759,9 +15710,9 @@ snapshots:
|
||||
|
||||
trough@2.2.0: {}
|
||||
|
||||
ts-api-utils@1.4.3(typescript@5.9.3):
|
||||
ts-api-utils@1.4.3(typescript@4.9.5):
|
||||
dependencies:
|
||||
typescript: 5.9.3
|
||||
typescript: 4.9.5
|
||||
|
||||
ts-dedent@2.2.0: {}
|
||||
|
||||
@@ -15825,7 +15776,7 @@ snapshots:
|
||||
|
||||
typeforce@1.18.0: {}
|
||||
|
||||
typescript@5.9.3: {}
|
||||
typescript@4.9.5: {}
|
||||
|
||||
ufo@1.6.1: {}
|
||||
|
||||
@@ -15994,24 +15945,18 @@ snapshots:
|
||||
|
||||
url-template@2.0.8: {}
|
||||
|
||||
use-composed-ref@1.4.0(@types/react@18.3.26)(react@18.3.1):
|
||||
use-composed-ref@1.4.0(react@18.3.1):
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.26
|
||||
|
||||
use-isomorphic-layout-effect@1.2.1(@types/react@18.3.26)(react@18.3.1):
|
||||
use-isomorphic-layout-effect@1.2.1(react@18.3.1):
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.26
|
||||
|
||||
use-latest@1.3.0(@types/react@18.3.26)(react@18.3.1):
|
||||
use-latest@1.3.0(react@18.3.1):
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
use-isomorphic-layout-effect: 1.2.1(@types/react@18.3.26)(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.26
|
||||
use-isomorphic-layout-effect: 1.2.1(react@18.3.1)
|
||||
|
||||
use-sync-external-store@1.5.0(react@18.3.1):
|
||||
dependencies:
|
||||
@@ -16065,18 +16010,18 @@ snapshots:
|
||||
'@types/unist': 3.0.3
|
||||
vfile-message: 4.0.3
|
||||
|
||||
viem@2.31.0(typescript@5.9.3)(zod@3.25.76):
|
||||
viem@2.31.0(typescript@4.9.5)(zod@3.25.76):
|
||||
dependencies:
|
||||
'@noble/curves': 1.9.1
|
||||
'@noble/hashes': 1.8.0
|
||||
'@scure/bip32': 1.7.0
|
||||
'@scure/bip39': 1.6.0
|
||||
abitype: 1.0.8(typescript@5.9.3)(zod@3.25.76)
|
||||
abitype: 1.0.8(typescript@4.9.5)(zod@3.25.76)
|
||||
isows: 1.0.7(ws@8.18.2)
|
||||
ox: 0.7.1(typescript@5.9.3)(zod@3.25.76)
|
||||
ox: 0.7.1(typescript@4.9.5)(zod@3.25.76)
|
||||
ws: 8.18.2
|
||||
optionalDependencies:
|
||||
typescript: 5.9.3
|
||||
typescript: 4.9.5
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
@@ -16250,11 +16195,10 @@ snapshots:
|
||||
|
||||
zod@3.25.76: {}
|
||||
|
||||
zustand@4.5.7(@types/react@18.3.26)(immer@10.1.1)(react@18.3.1):
|
||||
zustand@4.5.7(immer@10.1.1)(react@18.3.1):
|
||||
dependencies:
|
||||
use-sync-external-store: 1.5.0(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.26
|
||||
immer: 10.1.1
|
||||
react: 18.3.1
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 70 KiB |
@@ -50,7 +50,6 @@ zeroize = { workspace = true }
|
||||
|
||||
# internal
|
||||
nym-api-requests = { path = "../nym-api/nym-api-requests" }
|
||||
nym-bin-common = { path = "../common/bin-common" }
|
||||
nym-credentials = { path = "../common/credentials" }
|
||||
nym-credentials-interface = { path = "../common/credentials-interface" }
|
||||
nym-credential-verification = { path = "../common/credential-verification" }
|
||||
@@ -83,25 +82,9 @@ nym-service-provider-requests-common = { path = "../common/service-provider-requ
|
||||
|
||||
|
||||
defguard_wireguard_rs = { workspace = true }
|
||||
opentelemetry = { workspace = true, optional = true }
|
||||
opentelemetry_sdk = { workspace = true, optional = true }
|
||||
tracing-opentelemetry = { workspace = true, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
nym-gateway-storage = { path = "../common/gateway-storage", features = ["mock"] }
|
||||
nym-wireguard = { path = "../common/wireguard", features = ["mock"] }
|
||||
mock_instant = "0.6.0"
|
||||
time = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
otel = [
|
||||
"nym-bin-common/otel",
|
||||
"nym-client-core/otel",
|
||||
"nym-gateway-requests/otel",
|
||||
"nym-sphinx/otel",
|
||||
"nym-sdk/otel",
|
||||
"opentelemetry",
|
||||
"opentelemetry_sdk",
|
||||
"tracing-opentelemetry",
|
||||
]
|
||||
|
||||
@@ -14,8 +14,6 @@ use futures::{
|
||||
future::{FusedFuture, OptionFuture},
|
||||
FutureExt, StreamExt,
|
||||
};
|
||||
#[cfg(feature = "otel")]
|
||||
use nym_bin_common::opentelemetry::context::ManualContextPropagator;
|
||||
use nym_credential_verification::CredentialVerifier;
|
||||
use nym_credential_verification::{
|
||||
bandwidth_storage_manager::BandwidthStorageManager, ClientBandwidth,
|
||||
@@ -33,8 +31,6 @@ use nym_sphinx::forwarding::packet::MixPacket;
|
||||
use nym_statistics_common::{gateways::GatewaySessionEvent, types::SessionType};
|
||||
use nym_validator_client::coconut::EcashApiError;
|
||||
use rand::{random, CryptoRng, Rng};
|
||||
#[cfg(feature = "otel")]
|
||||
use std::collections::HashMap;
|
||||
use std::{process, time::Duration};
|
||||
use thiserror::Error;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
@@ -151,8 +147,6 @@ pub(crate) struct AuthenticatedHandler<R, S> {
|
||||
// senders that are used to return the result of the ping to the handler requesting the ping.
|
||||
is_active_request_receiver: IsActiveRequestReceiver,
|
||||
is_active_ping_pending_reply: Option<(u64, IsActiveResultSender)>,
|
||||
#[cfg(feature = "otel")]
|
||||
pub otel_propagator: Option<ManualContextPropagator>,
|
||||
}
|
||||
|
||||
// explicitly remove handle from the global store upon being dropped
|
||||
@@ -195,24 +189,6 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
client_address: client.address.as_base58_string(),
|
||||
})?;
|
||||
|
||||
#[cfg(feature = "otel")]
|
||||
let manual_ctx_propagator = {
|
||||
let context = match client.otel_context {
|
||||
Some(ref ctx) => ctx.clone(),
|
||||
None => HashMap::new(),
|
||||
};
|
||||
|
||||
let manual_ctx_propagator = if !context.is_empty() {
|
||||
Some(ManualContextPropagator::new(
|
||||
"upgrading_fresh_to_authenticated",
|
||||
context,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
manual_ctx_propagator
|
||||
};
|
||||
|
||||
let handler = AuthenticatedHandler {
|
||||
bandwidth_storage_manager: BandwidthStorageManager::new(
|
||||
Box::new(fresh.shared_state.storage.clone()),
|
||||
@@ -226,8 +202,6 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
mix_receiver,
|
||||
is_active_request_receiver,
|
||||
is_active_ping_pending_reply: None,
|
||||
#[cfg(feature = "otel")]
|
||||
otel_propagator: manual_ctx_propagator,
|
||||
};
|
||||
handler.send_metrics(GatewaySessionEvent::new_session_start(
|
||||
handler.client.address,
|
||||
@@ -253,19 +227,7 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `mix_packet`: packet received from the client that should get forwarded into the network.
|
||||
#[instrument(skip_all)]
|
||||
fn forward_packet(&self, mix_packet: MixPacket) {
|
||||
#[cfg(feature = "otel")]
|
||||
{
|
||||
let span = match &self.otel_propagator {
|
||||
Some(propagator) => {
|
||||
info_span!(parent: &propagator.root_span, "forwarding_mix_packet")
|
||||
}
|
||||
None => info_span!("forwarding_mix_packet_no_otel"),
|
||||
};
|
||||
let _enter = span.enter();
|
||||
}
|
||||
|
||||
if let Err(err) = self
|
||||
.inner
|
||||
.shared_state
|
||||
@@ -325,26 +287,11 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
&mut self,
|
||||
mix_packet: MixPacket,
|
||||
) -> Result<ServerResponse, RequestHandlingError> {
|
||||
trace!("forwarding sphinx packet");
|
||||
#[cfg(feature = "otel")]
|
||||
let span = {
|
||||
let span = match &self.otel_propagator {
|
||||
Some(propagator) => {
|
||||
info_span!(parent: &propagator.root_span, "handling_forward_sphinx")
|
||||
}
|
||||
None => debug_span!("handling_forward_sphinx_no_otel"),
|
||||
};
|
||||
span
|
||||
};
|
||||
#[cfg(feature = "otel")]
|
||||
let _enter = span.enter();
|
||||
|
||||
let required_bandwidth = mix_packet.packet().len() as i64;
|
||||
|
||||
let remaining_bandwidth = self
|
||||
.bandwidth_storage_manager
|
||||
.try_use_bandwidth(required_bandwidth)
|
||||
.in_current_span()
|
||||
.await?;
|
||||
self.forward_packet(mix_packet);
|
||||
|
||||
@@ -358,22 +305,8 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `bin_msg`: raw message to handle.
|
||||
#[instrument(skip_all)]
|
||||
async fn handle_binary(&mut self, bin_msg: Vec<u8>) -> Message {
|
||||
trace!("binary request");
|
||||
#[cfg(feature = "otel")]
|
||||
let span = {
|
||||
let span = match &self.otel_propagator {
|
||||
Some(propagator) => {
|
||||
info_span!(parent: &propagator.root_span, "handling_binary_request")
|
||||
}
|
||||
None => info_span!("handling_binary_request_no_otel"),
|
||||
};
|
||||
span
|
||||
};
|
||||
#[cfg(feature = "otel")]
|
||||
let _enter = span.enter();
|
||||
|
||||
// this function decrypts the request and checks the MAC
|
||||
match BinaryRequest::try_from_encrypted_tagged_bytes(bin_msg, &self.client.shared_keys) {
|
||||
Err(e) => {
|
||||
@@ -383,11 +316,9 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
Ok(request) => match request {
|
||||
// currently only a single type exists
|
||||
BinaryRequest::ForwardSphinx { packet }
|
||||
| BinaryRequest::ForwardSphinxV2 { packet } => self
|
||||
.handle_forward_sphinx(packet)
|
||||
.in_current_span()
|
||||
.await
|
||||
.into_ws_message(),
|
||||
| BinaryRequest::ForwardSphinxV2 { packet } => {
|
||||
self.handle_forward_sphinx(packet).await.into_ws_message()
|
||||
}
|
||||
_ => RequestHandlingError::UnknownBinaryRequest.into_error_message(),
|
||||
},
|
||||
}
|
||||
@@ -448,7 +379,6 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
Ok(SensitiveServerResponse::KeyUpgradeAck {}.encrypt(&self.client.shared_keys)?)
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn handle_encrypted_text_request(
|
||||
&mut self,
|
||||
ciphertext: Vec<u8>,
|
||||
@@ -478,7 +408,6 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `raw_request`: raw message to handle.
|
||||
#[instrument(skip_all)]
|
||||
async fn handle_text(&mut self, raw_request: String) -> Message
|
||||
where
|
||||
R: Rng + CryptoRng,
|
||||
@@ -623,7 +552,6 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn handle_is_active_request(
|
||||
&mut self,
|
||||
reply_tx: IsActiveResultSender,
|
||||
@@ -654,37 +582,20 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
/// Simultaneously listens for incoming client requests, which realistically should only be
|
||||
/// binary requests to forward sphinx packets or increase bandwidth
|
||||
/// and for sphinx packets received from the mix network that should be sent back to the client.
|
||||
#[instrument(level = "debug", skip_all,
|
||||
fields(
|
||||
client = %self.client.address.as_base58_string()
|
||||
)
|
||||
)]
|
||||
pub(crate) async fn listen_for_requests(mut self)
|
||||
where
|
||||
R: Rng + CryptoRng,
|
||||
S: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
trace!("Started listening for ALL incoming requests...");
|
||||
|
||||
// Ping timeout future used to check if the client responded to our ping request
|
||||
let mut ping_timeout: OptionFuture<_> = None.into();
|
||||
|
||||
#[cfg(feature = "otel")]
|
||||
let from_client_span = {
|
||||
let span = match &self.otel_propagator {
|
||||
Some(propagator) => {
|
||||
info_span!(parent: &propagator.root_span, "authenticated_client_handler_listen")
|
||||
}
|
||||
None => tracing::debug_span!("authenticated_client_handler_listen_no_otel"),
|
||||
};
|
||||
span
|
||||
};
|
||||
#[cfg(feature = "otel")]
|
||||
let _enter = from_client_span.enter();
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
// Received a request to ping the client to check if it's still active
|
||||
tx = self.is_active_request_receiver.next().in_current_span() => {
|
||||
tx = self.is_active_request_receiver.next() => {
|
||||
match tx {
|
||||
None => break,
|
||||
Some(reply_tx) => {
|
||||
@@ -698,10 +609,10 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
},
|
||||
// The ping timeout expired, meaning the client didn't respond to our ping request
|
||||
_ = &mut ping_timeout, if !ping_timeout.is_terminated() => {
|
||||
ping_timeout = None.into();
|
||||
self.handle_ping_timeout().await;
|
||||
ping_timeout = None.into();
|
||||
self.handle_ping_timeout().await;
|
||||
},
|
||||
socket_msg = self.inner.read_websocket_message().in_current_span() => {
|
||||
socket_msg = self.inner.read_websocket_message() => {
|
||||
let socket_msg = match socket_msg {
|
||||
None => break,
|
||||
Some(Ok(socket_msg)) => socket_msg,
|
||||
@@ -716,7 +627,7 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
}
|
||||
|
||||
if let Some(response) = self.handle_request(socket_msg).await {
|
||||
if let Err(err) = self.inner.send_websocket_message(response).in_current_span().await {
|
||||
if let Err(err) = self.inner.send_websocket_message(response).await {
|
||||
debug!(
|
||||
"Failed to send message over websocket: {err}. Assuming the connection is dead.",
|
||||
);
|
||||
@@ -724,7 +635,7 @@ impl<R, S> AuthenticatedHandler<R, S> {
|
||||
}
|
||||
}
|
||||
},
|
||||
mix_messages = self.mix_receiver.next().in_current_span() => {
|
||||
mix_messages = self.mix_receiver.next() => {
|
||||
let mix_messages = match mix_messages {
|
||||
None => {
|
||||
debug!("mix receiver was closed! Assuming the connection is dead.");
|
||||
|
||||
@@ -13,8 +13,6 @@ use futures::{
|
||||
channel::{mpsc, oneshot},
|
||||
SinkExt, StreamExt,
|
||||
};
|
||||
#[cfg(feature = "otel")]
|
||||
use nym_bin_common::opentelemetry::context::ManualContextPropagator;
|
||||
use nym_credentials_interface::AvailableBandwidth;
|
||||
use nym_crypto::aes::cipher::crypto_common::rand_core::RngCore;
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
@@ -36,8 +34,6 @@ use nym_node_metrics::events::MetricsEvent;
|
||||
use nym_sphinx::DestinationAddressBytes;
|
||||
use nym_task::ShutdownToken;
|
||||
use rand::CryptoRng;
|
||||
#[cfg(feature = "otel")]
|
||||
use std::collections::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
use std::time::Duration;
|
||||
use thiserror::Error;
|
||||
@@ -45,9 +41,7 @@ use time::OffsetDateTime;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tokio::time::timeout;
|
||||
use tokio_tungstenite::tungstenite::{protocol::Message, Error as WsError};
|
||||
#[cfg(feature = "otel")]
|
||||
use tracing::info_span;
|
||||
use tracing::{debug, error, info, instrument, warn, Instrument};
|
||||
use tracing::*;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub(crate) enum InitialAuthenticationError {
|
||||
@@ -169,7 +163,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
|
||||
/// Attempts to perform websocket handshake with the remote and upgrades the raw TCP socket
|
||||
/// to the framed WebSocket.
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn perform_websocket_handshake(&mut self) -> Result<(), WsError>
|
||||
where
|
||||
S: AsyncRead + AsyncWrite + Unpin,
|
||||
@@ -193,7 +186,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `init_msg`: a client handshake init message which should contain its identity public key as well as an ephemeral key.
|
||||
#[instrument(skip_all)]
|
||||
async fn perform_registration_handshake(
|
||||
&mut self,
|
||||
init_msg: Vec<u8>,
|
||||
@@ -219,7 +211,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
}
|
||||
|
||||
/// Attempts to read websocket message from the associated socket.
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn read_websocket_message(&mut self) -> Option<Result<Message, WsError>>
|
||||
where
|
||||
S: AsyncRead + AsyncWrite + Unpin,
|
||||
@@ -235,7 +226,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `msg`: WebSocket message to write back to the client.
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn send_websocket_message(
|
||||
&mut self,
|
||||
msg: impl Into<Message>,
|
||||
@@ -252,7 +242,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn send_error_response(
|
||||
&mut self,
|
||||
err: impl std::error::Error,
|
||||
@@ -280,7 +269,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
///
|
||||
/// * `shared_keys`: keys derived between the client and gateway.
|
||||
/// * `packets`: unwrapped packets that are to be pushed back to the client.
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn push_packets_to_client(
|
||||
&mut self,
|
||||
shared_keys: &SharedGatewayKey,
|
||||
@@ -338,7 +326,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
///
|
||||
/// * `client_address`: address of the client that is going to receive the messages.
|
||||
/// * `shared_keys`: shared keys derived between the client and the gateway used to encrypt and tag the messages.
|
||||
#[instrument(skip_all)]
|
||||
async fn push_stored_messages_to_client(
|
||||
&mut self,
|
||||
client_address: DestinationAddressBytes,
|
||||
@@ -645,8 +632,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
address,
|
||||
shared_keys.key,
|
||||
session_request_start,
|
||||
#[cfg(feature = "otel")]
|
||||
None,
|
||||
)),
|
||||
ServerResponse::Authenticate {
|
||||
protocol_version: Some(negotiated_protocol),
|
||||
@@ -656,13 +641,9 @@ impl<R, S> FreshHandler<R, S> {
|
||||
))
|
||||
}
|
||||
|
||||
#[instrument(skip_all, fields(
|
||||
address = %request.content.client_identity.derive_destination_address(),
|
||||
))]
|
||||
async fn handle_authenticate_v2(
|
||||
&mut self,
|
||||
request: Box<AuthenticateRequest>,
|
||||
#[cfg(feature = "otel")] otel_context: Option<HashMap<String, String>>,
|
||||
) -> Result<InitialAuthResult, InitialAuthenticationError>
|
||||
where
|
||||
S: AsyncRead + AsyncWrite + Unpin,
|
||||
@@ -737,8 +718,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
address,
|
||||
shared_key.key,
|
||||
session_request_start,
|
||||
#[cfg(feature = "otel")]
|
||||
otel_context,
|
||||
)),
|
||||
ServerResponse::Authenticate {
|
||||
protocol_version: Some(negotiated_protocol),
|
||||
@@ -837,8 +816,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
remote_address,
|
||||
shared_keys,
|
||||
OffsetDateTime::now_utc(),
|
||||
#[cfg(feature = "otel")]
|
||||
None,
|
||||
);
|
||||
|
||||
Ok(InitialAuthResult::new(
|
||||
@@ -869,7 +846,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn handle_initial_client_request(
|
||||
&mut self,
|
||||
request: ClientControlRequest,
|
||||
@@ -878,58 +854,17 @@ impl<R, S> FreshHandler<R, S> {
|
||||
S: AsyncRead + AsyncWrite + Unpin + Send,
|
||||
R: CryptoRng + RngCore + Send,
|
||||
{
|
||||
// extract and set up opentelemetry context if provided
|
||||
#[cfg(feature = "otel")]
|
||||
let (context_propagator, otel_ctx) =
|
||||
if let ClientControlRequest::AuthenticateV2(ref auth_req) = request {
|
||||
if let Some(otel_context) = &auth_req.otel_context {
|
||||
info!(
|
||||
"=== OpenTelemetry context provided in the request: {otel_context:?} ==="
|
||||
);
|
||||
(
|
||||
Some(ManualContextPropagator::new(
|
||||
"handling_initial_client_request_with_otel",
|
||||
otel_context.clone(),
|
||||
)),
|
||||
Some(otel_context.clone()),
|
||||
)
|
||||
} else {
|
||||
debug!("No OpenTelemetry context provided in the request");
|
||||
(None, None)
|
||||
}
|
||||
} else {
|
||||
debug!("No OpenTelemetry context provided in the request");
|
||||
(None, None)
|
||||
};
|
||||
#[cfg(feature = "otel")]
|
||||
let child_span = match context_propagator {
|
||||
Some(ref propagator) => {
|
||||
let span = info_span!(parent: &propagator.root_span, "=== Handling initial client request with otel context ===");
|
||||
span
|
||||
}
|
||||
None => {
|
||||
tracing::debug_span!("=== Handling initial client request without otel context ===")
|
||||
}
|
||||
};
|
||||
#[cfg(feature = "otel")]
|
||||
let _enter = child_span.enter();
|
||||
|
||||
// we can handle stateless client requests without prior authentication, like `ClientControlRequest::SupportedProtocol`
|
||||
let auth_result = match request {
|
||||
ClientControlRequest::Authenticate {
|
||||
protocol_version,
|
||||
address,
|
||||
enc_address,
|
||||
iv,
|
||||
otel_context: _,
|
||||
} => {
|
||||
self.handle_legacy_authenticate(protocol_version, address, enc_address, iv)
|
||||
.await
|
||||
}
|
||||
#[cfg(feature = "otel")]
|
||||
ClientControlRequest::AuthenticateV2(req) => {
|
||||
self.handle_authenticate_v2(req, otel_ctx).await
|
||||
}
|
||||
#[cfg(not(feature = "otel"))]
|
||||
ClientControlRequest::AuthenticateV2(req) => self.handle_authenticate_v2(req).await,
|
||||
ClientControlRequest::RegisterHandshakeInitRequest {
|
||||
protocol_version,
|
||||
@@ -954,6 +889,7 @@ impl<R, S> FreshHandler<R, S> {
|
||||
}
|
||||
other => debug!("authentication failure: {other}"),
|
||||
}
|
||||
|
||||
self.send_and_forget_error_response(&err).await;
|
||||
return Err(err);
|
||||
}
|
||||
@@ -976,11 +912,9 @@ impl<R, S> FreshHandler<R, S> {
|
||||
warn!("could not establish client details");
|
||||
return Err(InitialAuthenticationError::EmptyClientDetails);
|
||||
};
|
||||
|
||||
Ok(Some(client_details))
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn handle_until_authenticated_or_failure(
|
||||
mut self,
|
||||
) -> Option<AuthenticatedHandler<R, S>>
|
||||
@@ -1019,7 +953,7 @@ impl<R, S> FreshHandler<R, S> {
|
||||
registration_details.session_request_timestamp,
|
||||
);
|
||||
|
||||
let auth_handle = AuthenticatedHandler::upgrade(
|
||||
return AuthenticatedHandler::upgrade(
|
||||
self,
|
||||
registration_details,
|
||||
mix_receiver,
|
||||
@@ -1028,12 +962,10 @@ impl<R, S> FreshHandler<R, S> {
|
||||
.await
|
||||
.inspect_err(|err| error!("failed to upgrade client handler: {err}"))
|
||||
.ok();
|
||||
return auth_handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn wait_for_initial_message(
|
||||
&mut self,
|
||||
) -> Result<ClientControlRequest, InitialAuthenticationError>
|
||||
@@ -1084,7 +1016,6 @@ impl<R, S> FreshHandler<R, S> {
|
||||
.map_err(|_| InitialAuthenticationError::InvalidRequest)
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn start_handling(self)
|
||||
where
|
||||
S: AsyncRead + AsyncWrite + Unpin + Send,
|
||||
@@ -1094,10 +1025,10 @@ impl<R, S> FreshHandler<R, S> {
|
||||
let shutdown = self.shutdown.clone();
|
||||
tokio::select! {
|
||||
_ = shutdown.cancelled() => {
|
||||
tracing::trace!("received cancellation")
|
||||
trace!("received cancellation")
|
||||
}
|
||||
_ = super::handle_connection(self).instrument(tracing::debug_span!("connection_handler", remote = %remote)) => {
|
||||
tracing::debug!("finished connection handler for {remote}")
|
||||
_ = super::handle_connection(self) => {
|
||||
debug!("finished connection handler for {remote}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,10 @@ use nym_gateway_requests::shared_key::SharedGatewayKey;
|
||||
use nym_gateway_requests::ServerResponse;
|
||||
use nym_sphinx::DestinationAddressBytes;
|
||||
use rand::{CryptoRng, Rng};
|
||||
#[cfg(feature = "otel")]
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tokio_tungstenite::WebSocketStream;
|
||||
use tracing::Instrument;
|
||||
use tracing::{debug, instrument, trace, warn};
|
||||
|
||||
pub(crate) use self::authenticated::AuthenticatedHandler;
|
||||
@@ -51,8 +48,6 @@ pub(crate) struct ClientDetails {
|
||||
// note, this does **NOT ALWAYS** indicate timestamp of when client connected
|
||||
// it is (for v2 auth) timestamp the client **signed** when it created the request
|
||||
pub(crate) session_request_timestamp: OffsetDateTime,
|
||||
#[cfg(feature = "otel")]
|
||||
pub(crate) otel_context: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
||||
impl ClientDetails {
|
||||
@@ -61,15 +56,12 @@ impl ClientDetails {
|
||||
address: DestinationAddressBytes,
|
||||
shared_keys: SharedGatewayKey,
|
||||
session_request_timestamp: OffsetDateTime,
|
||||
#[cfg(feature = "otel")] otel_context: Option<HashMap<String, String>>,
|
||||
) -> Self {
|
||||
ClientDetails {
|
||||
address,
|
||||
id,
|
||||
shared_keys,
|
||||
session_request_timestamp,
|
||||
#[cfg(feature = "otel")]
|
||||
otel_context,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +92,7 @@ impl InitialAuthResult {
|
||||
}
|
||||
|
||||
// imo there's no point in including the peer address in anything higher than debug
|
||||
#[instrument(skip_all)]
|
||||
#[instrument(level = "debug", skip_all, fields(peer = %handle.peer_address))]
|
||||
pub(crate) async fn handle_connection<R, S>(mut handle: FreshHandler<R, S>)
|
||||
where
|
||||
R: Rng + CryptoRng + Send,
|
||||
@@ -125,25 +117,8 @@ where
|
||||
|
||||
trace!("managed to perform websocket handshake!");
|
||||
|
||||
if let Some(auth_handle) = handle.handle_until_authenticated_or_failure().in_current_span().await {
|
||||
#[cfg(feature = "otel")]
|
||||
{
|
||||
let from_client_span = {
|
||||
let parent = match auth_handle.otel_propagator.as_ref() {
|
||||
Some(propagator) => propagator.root_span(),
|
||||
None => &tracing::Span::current(), // fallback to current span if no propagator
|
||||
};
|
||||
tracing::info_span!(parent: parent, "listening for requests")
|
||||
};
|
||||
auth_handle
|
||||
.listen_for_requests()
|
||||
.instrument(from_client_span)
|
||||
.await
|
||||
}
|
||||
#[cfg(not(feature = "otel"))]
|
||||
{
|
||||
auth_handle.listen_for_requests().await;
|
||||
}
|
||||
if let Some(auth_handle) = handle.handle_until_authenticated_or_failure().await {
|
||||
auth_handle.listen_for_requests().await
|
||||
}
|
||||
|
||||
trace!("the handler is done!");
|
||||
|
||||
@@ -53,7 +53,6 @@ impl Listener {
|
||||
)
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
fn try_handle_accepted_connection(&self, accepted: io::Result<(TcpStream, SocketAddr)>) {
|
||||
match accepted {
|
||||
Ok((socket, remote_address)) => {
|
||||
@@ -91,7 +90,7 @@ impl Listener {
|
||||
let metrics_ref = handle.shared_state.metrics.clone();
|
||||
|
||||
// 4.1. handle all client requests until connection gets terminated
|
||||
handle.start_handling().in_current_span().await;
|
||||
handle.start_handling().await;
|
||||
|
||||
// 4.2. decrement the connection counter
|
||||
metrics_ref.network.disconnected_ingress_websocket_client();
|
||||
@@ -105,7 +104,6 @@ impl Listener {
|
||||
|
||||
// TODO: change the signature to pub(crate) async fn run(&self, handler: Handler)
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn run(&mut self) {
|
||||
info!("Starting websocket listener at {}", self.address);
|
||||
let tcp_listener = match tokio::net::TcpListener::bind(self.address).await {
|
||||
@@ -124,7 +122,7 @@ impl Listener {
|
||||
trace!("client_handling::Listener: received shutdown");
|
||||
break
|
||||
}
|
||||
connection = tcp_listener.accept().in_current_span() => {
|
||||
connection = tcp_listener.accept() => {
|
||||
self.try_handle_accepted_connection(connection)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -977,8 +977,6 @@ fn create_input_message(
|
||||
response_packet,
|
||||
lane,
|
||||
packet_type,
|
||||
#[cfg(feature = "otel")]
|
||||
None,
|
||||
))
|
||||
} else {
|
||||
tracing::error!("No nym-address or sender tag provided");
|
||||
|
||||
+2
-6
@@ -4,7 +4,7 @@
|
||||
[package]
|
||||
name = "nym-api"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.67"
|
||||
version = "1.1.66"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
rust-version.workspace = true
|
||||
@@ -95,7 +95,7 @@ nym-topology = { path = "../common/topology" }
|
||||
nym-api-requests = { path = "nym-api-requests" }
|
||||
nym-validator-client = { path = "../common/client-libs/validator-client" }
|
||||
nym-http-api-client = { path = "../common/http-api-client" }
|
||||
nym-bin-common = { path = "../common/bin-common", features = ["output_format", "openapi"] }
|
||||
nym-bin-common = { path = "../common/bin-common", features = ["output_format", "openapi", "basic_tracing"] }
|
||||
nym-node-tester-utils = { path = "../common/node-tester-utils" }
|
||||
nym-node-requests = { path = "../nym-node/nym-node-requests" }
|
||||
nym-types = { path = "../common/types" }
|
||||
@@ -110,10 +110,6 @@ nym-ecash-signer-check = { path = "../common/ecash-signer-check" }
|
||||
no-reward = []
|
||||
v2-performance = []
|
||||
generate-ts = ["ts-rs"]
|
||||
otel = [
|
||||
"nym-bin-common/otel",
|
||||
"nym-node-tester-utils/otel",
|
||||
]
|
||||
|
||||
[build-dependencies]
|
||||
anyhow = { workspace = true }
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ async fn main() -> Result<(), anyhow::Error> {
|
||||
// instrument tokio console subscriber needs RUSTFLAGS="--cfg tokio_unstable" at build time
|
||||
console_subscriber::init();
|
||||
} else {
|
||||
nym_bin_common::logging::setup_no_otel_logger().expect("failed to initialize logging");
|
||||
nym_bin_common::logging::setup_tracing_logger();
|
||||
}}
|
||||
|
||||
info!("Starting nym api...");
|
||||
|
||||
@@ -124,7 +124,6 @@ pub struct Config {
|
||||
pub node_status_api: NodeStatusAPI,
|
||||
|
||||
#[serde(alias = "topology_cacher")]
|
||||
#[serde(default)]
|
||||
pub describe_cache: DescribeCache,
|
||||
|
||||
#[serde(default)]
|
||||
|
||||
@@ -70,6 +70,30 @@ per_node_test_packets = {{ network_monitor.debug.per_node_test_packets }}
|
||||
# Path to the database file containing uptime statuses for all mixnodes and gateways.
|
||||
database_path = '{{ node_status_api.storage_paths.database_path }}'
|
||||
|
||||
[node_status_api.debug]
|
||||
|
||||
caching_interval = '{{ node_status_api.debug.caching_interval }}'
|
||||
|
||||
|
||||
##### topology cacher config options #####
|
||||
|
||||
[topology_cacher.debug]
|
||||
|
||||
caching_interval = '{{ topology_cacher.debug.caching_interval }}'
|
||||
|
||||
|
||||
##### circulating supply cacher config options #####
|
||||
|
||||
[circulating_supply_cacher]
|
||||
|
||||
# Specifies whether circulating supply caching service is enabled in this process.
|
||||
enabled = {{ circulating_supply_cacher.enabled }}
|
||||
|
||||
[circulating_supply_cacher.debug]
|
||||
|
||||
caching_interval = '{{ circulating_supply_cacher.debug.caching_interval }}'
|
||||
|
||||
|
||||
##### rewarding config options #####
|
||||
|
||||
[rewarding]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user