From 7ceaf9a40ec9ee41758100c9785dcf836b9ff3e7 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 14 Apr 2026 20:13:12 +0000 Subject: [PATCH 01/37] Max/mixtcp (#6321) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add mixtcp crate Components: - NymIprDevice: smoltcp::phy::Device impl using channel-based I/O - NymIprBridge: async task bridging the device to IpMixStream - create_device(): helper to set up the complete stack * - Cleanup - Add graceful shutdown - Declutter logging - move a lot of bridge info! -> trace! - Move rustls, nym-bin-common, bytes to dev-dependencies - Extract TlsOverTcp to mod.rs - Make timing more granular - Update readme * Add UDP example * Add UDP example to readme * rename mixtcp -> smolmix * Add Tunnel API with TcpStream and UdpSocket over tokio-smoltcp * Re-export Tunnel API and add init_logging convenience function * Remove raw smoltcp path, flatten tunnel module * Clean up bridge, device, and tunnel code * Consolidate architecture docs, tidy examples and README - Add src/ARCHITECTURE.md as single source of truth for architecture - Include in docs.rs via doc = include_str! - Strip duplicated diagrams from tunnel.rs, device.rs, README - Extract tls_connector() helper in HTTPS example to match websocket example - Use consistent 'smolmix' casing in README * Update smolmix imports for ipr_wrapper API - stream_wrapper::{IpMixStream, NetworkEnvironment} → ipr_wrapper:: - connect_tunnel() → check_connected() - disconnect_stream() → disconnect() - allocated_ips() returns &IpPair directly (no Option) * Add Tunnel::new_with_ipr, re-export IpPair/Recipient, tidy examples - Add Tunnel::new_with_ipr() for targeting a specific exit node - Re-export IpPair and Recipient so users don't need direct deps - Add DNS leak warning to WebSocket example - Await hyper connection task in HTTPS example * Restructure smolmix into multi-crate workspace - Move core tunnel code to smolmix/core/- Rewrite examples for each crate with clearnet/mixnet comparisons * Add workspace README with architecture overview * Update nym-sdk README module descriptions - Replace stale stream_wrapper description with ipr_wrapper + mixnet::stream - Remove TODO comment * Remove companion crates, scope to smolmix-core * Comment out additional components on -core branch README.md * Cargo.lock fix for compilation issue * Downgrade accidentally bumped dependencies in Cargo lock + change smolmix dependencies to import from workspace * Fix workspace deps + move nym-bin-common to dev-deps * PR review changes + fix Sink delegation * Fix borked merge + update README.md * Fix up stale docs + rewrite examples to use proper imports and timing logs * Update readmes + architecture file * Impl Drop for BridgeShutdownHandle + update comment --- Cargo.lock | 121 ++++++++++ Cargo.toml | 7 + sdk/rust/nym-sdk/README.md | 2 - smolmix/README.md | 67 ++++++ smolmix/core/Cargo.toml | 36 +++ smolmix/core/README.md | 19 ++ smolmix/core/examples/tcp.rs | 131 +++++++++++ smolmix/core/examples/udp.rs | 96 ++++++++ smolmix/core/examples/websocket.rs | 143 ++++++++++++ smolmix/core/src/ARCHITECTURE.md | 70 ++++++ smolmix/core/src/bridge.rs | 164 +++++++++++++ smolmix/core/src/device.rs | 94 ++++++++ smolmix/core/src/error.rs | 19 ++ smolmix/core/src/lib.rs | 62 +++++ smolmix/core/src/tunnel.rs | 361 +++++++++++++++++++++++++++++ 15 files changed, 1390 insertions(+), 2 deletions(-) create mode 100644 smolmix/README.md create mode 100644 smolmix/core/Cargo.toml create mode 100644 smolmix/core/README.md create mode 100644 smolmix/core/examples/tcp.rs create mode 100644 smolmix/core/examples/udp.rs create mode 100644 smolmix/core/examples/websocket.rs create mode 100644 smolmix/core/src/ARCHITECTURE.md create mode 100644 smolmix/core/src/bridge.rs create mode 100644 smolmix/core/src/device.rs create mode 100644 smolmix/core/src/error.rs create mode 100644 smolmix/core/src/lib.rs create mode 100644 smolmix/core/src/tunnel.rs diff --git a/Cargo.lock b/Cargo.lock index 6ca431e70e..bd00183414 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2350,6 +2350,47 @@ dependencies = [ "x25519-dalek", ] +[[package]] +name = "defmt" +version = "0.3.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0963443817029b2024136fc4dd07a5107eb8f977eaf18fcd1fdeb11306b64ad" +dependencies = [ + "defmt 1.0.1", +] + +[[package]] +name = "defmt" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d4fc12a85bcf441cfe44344c4b72d58493178ce635338a3f3b78943aceb258e" +dependencies = [ + "defmt-parser", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror 2.0.12", +] + [[package]] name = "delegate-display" version = "3.0.0" @@ -3398,6 +3439,15 @@ dependencies = [ "serde_json", ] +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -3523,6 +3573,16 @@ dependencies = [ "http 1.3.1", ] +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.4.1" @@ -5047,6 +5107,12 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "managed" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" + [[package]] name = "maplit" version = "1.0.2" @@ -11074,6 +11140,47 @@ dependencies = [ "serde_core", ] +[[package]] +name = "smolmix" +version = "0.0.1" +dependencies = [ + "futures", + "hickory-proto", + "hickory-resolver", + "http-body-util", + "hyper 1.6.0", + "hyper-util", + "nym-bin-common", + "nym-ip-packet-requests", + "nym-sdk", + "reqwest 0.13.1", + "rustls 0.23.37", + "smoltcp", + "thiserror 2.0.12", + "tokio", + "tokio-rustls 0.26.2", + "tokio-smoltcp", + "tokio-tungstenite", + "tracing", + "webpki-roots 0.26.11", +] + +[[package]] +name = "smoltcp" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad095989c1533c1c266d9b1e8d70a1329dd3723c3edac6d03bbd67e7bf6f4bb" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "cfg-if", + "defmt 0.3.100", + "heapless", + "libc", + "log", + "managed", +] + [[package]] name = "snafu" version = "0.7.5" @@ -12040,6 +12147,20 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-smoltcp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5f5d53da1c3095663a8900d86c2abb0ffe02d3f6aa86527b066148fcb33e65e" +dependencies = [ + "futures", + "parking_lot", + "pin-project-lite", + "smoltcp", + "tokio", + "tokio-util", +] + [[package]] name = "tokio-stream" version = "0.1.17" diff --git a/Cargo.toml b/Cargo.toml index f559bae048..66ba465d80 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -147,6 +147,7 @@ members = [ "sdk/ffi/go", "sdk/ffi/shared", "sdk/rust/nym-sdk", + "smolmix/core", "service-providers/common", "service-providers/ip-packet-router", "service-providers/network-requester", @@ -279,6 +280,7 @@ getrandom03 = { package = "getrandom", version = "=0.3.3" } glob = "0.3" handlebars = "3.5.5" hex = "0.4.3" +hickory-proto = "0.25.2" hickory-resolver = "0.25.2" hkdf = "0.12.3" hmac = "0.12.1" @@ -347,6 +349,8 @@ serde_yaml = "0.9.25" serde_plain = "1.0.2" sha2 = "0.10.3" si-scale = "0.2.3" +smolmix = { version = "0.0.1", path = "smolmix/core" } +smoltcp = "0.12" snow = "0.9.6" sphinx-packet = "=0.6.0" sqlx = "0.8.6" @@ -367,6 +371,8 @@ tokio-postgres = "0.7" tokio-stream = "0.1.17" tokio-test = "0.4.4" tokio-tun = "0.11.5" +tokio-rustls = "0.26" +tokio-smoltcp = "0.5" tokio-tungstenite = { version = "0.20.1" } tokio-util = "0.7.15" toml = "0.8.22" @@ -559,6 +565,7 @@ wasm-bindgen = "0.2.99" wasm-bindgen-futures = "0.4.49" wasm-bindgen-test = "0.3.49" wasmtimer = "0.4.1" +webpki-roots = "0.26" web-sys = "0.3.76" # for local development: diff --git a/sdk/rust/nym-sdk/README.md b/sdk/rust/nym-sdk/README.md index be8bdab8ed..16f1989414 100644 --- a/sdk/rust/nym-sdk/README.md +++ b/sdk/rust/nym-sdk/README.md @@ -1,7 +1,5 @@ # Nym Rust SDK - - This repo contains several components: - `mixnet`: exposes Nym Client builders and methods. This is useful if you want to interact directly with the Client, or build transport abstractions. - `tcp_proxy`: exposes functionality to set up client/server instances that expose a localhost TcpSocket to read/write to like a 'normal' socket connection. `tcp_proxy/bin/` contains standalone `nym-proxy-client` and `nym-proxy-server` binaries. diff --git a/smolmix/README.md b/smolmix/README.md new file mode 100644 index 0000000000..3bd4e861b7 --- /dev/null +++ b/smolmix/README.md @@ -0,0 +1,67 @@ +# smolmix + +TCP/UDP tunnel over the Nym mixnet. Uses a userspace network stack (smoltcp) +to provide real `TcpStream` and `UdpSocket` types that work transparently +with the async Rust ecosystem — tokio-rustls, hyper, tokio-tungstenite, +libp2p, and anything else built on `AsyncRead + AsyncWrite`. + +## Why IP, not messages + +The Nym SDK works at the **message layer**: you send and receive `Vec` +payloads through the mixnet. Every protocol must be hand-adapted — you need +custom framing, ordering, connection state, and flow control. + +`smolmix` operates at the **IP layer**. A userspace smoltcp stack manages +real TCP state machines (retransmits, windowing, port allocation) and UDP +datagram delivery, and the mixnet becomes a transparent transport underneath. +Any protocol that works over TCP or UDP works over smolmix — with zero +adaptation. + +```text +┌──────────────────────────────────────────────────────────────────┐ +│ Application protocols that "just work" over smolmix │ +│ │ +│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ ┌────────────────┐ │ +│ │ TLS │ │ HTTP/1.1 │ │ WebSocket │ │ libp2p │ │ +│ │ (rustls) │ │ (hyper) │ │ (tungstenite)│ │ (noise+yamux) │ │ +│ └────┬─────┘ └────┬─────┘ └──────┬───────┘ └───────┬────────┘ │ +│ │ │ │ │ │ +│ └─────────────┴──────────────┴─────────────────┘ │ +│ │ │ +│ tokio_smoltcp::TcpStream │ +│ (AsyncRead + AsyncWrite, Send, Unpin) │ +├──────────────────────────────────────────────────────────────────┤ +│ smolmix Tunnel │ +│ (smoltcp → mixnet → IPR) │ +└──────────────────────────────────────────────────────────────────┘ +``` + +## Quick start + +```rust +use smolmix::Tunnel; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; + +let tunnel = Tunnel::new().await?; + +// Raw TCP — works with any protocol +let mut tcp = tunnel.tcp_connect("1.1.1.1:80".parse()?).await?; +tcp.write_all(b"GET / HTTP/1.1\r\nHost: 1.1.1.1\r\nConnection: close\r\n\r\n").await?; + +// Raw UDP — datagrams over the mixnet +let udp = tunnel.udp_socket().await?; +udp.send_to(&packet, "1.1.1.1:53".parse()?).await?; +``` + +## Examples + +```sh +cargo run -p smolmix --example tcp # HTTPS via hyper +cargo run -p smolmix --example udp # DNS via hickory-proto +cargo run -p smolmix --example websocket # WebSocket via tungstenite +``` + +## Architecture + +See [`core/src/ARCHITECTURE.md`](core/src/ARCHITECTURE.md) for the internal +stack (smoltcp, device adapter, bridge, mixnet client). diff --git a/smolmix/core/Cargo.toml b/smolmix/core/Cargo.toml new file mode 100644 index 0000000000..173e519178 --- /dev/null +++ b/smolmix/core/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "smolmix" +version = "0.0.1" +edition = "2021" +license.workspace = true + +[dependencies] +smoltcp = { workspace = true, features = [ + "std", + "medium-ip", + "proto-ipv4", + "socket-tcp", + "socket-udp", +] } +tokio = { workspace = true } +tokio-smoltcp = { workspace = true } +futures = { workspace = true } +tracing = { workspace = true } +nym-sdk = { workspace = true } +nym-ip-packet-requests = { workspace = true } +thiserror.workspace = true + +[dev-dependencies] +futures = { workspace = true } +tokio = { workspace = true, features = ["io-util", "macros", "rt-multi-thread", "time", "net"] } +tokio-tungstenite.workspace = true +webpki-roots.workspace = true +rustls = { workspace = true, features = ["std", "ring"] } +tokio-rustls = { workspace = true } +nym-bin-common = { workspace = true, features = ["basic_tracing"] } +hickory-proto = { workspace = true } +hickory-resolver = { workspace = true, features = ["tokio", "system-config"] } +hyper = { workspace = true, features = ["client", "http1"] } +hyper-util = { workspace = true, features = ["tokio"] } +http-body-util = { workspace = true } +reqwest = { workspace = true, features = ["rustls"] } diff --git a/smolmix/core/README.md b/smolmix/core/README.md new file mode 100644 index 0000000000..500941938a --- /dev/null +++ b/smolmix/core/README.md @@ -0,0 +1,19 @@ +# smolmix + +A TCP/UDP tunnel over the Nym mixnet. Uses smoltcp as a userspace network stack and connects to an Exit Gateway's IP Packet Router, so the exit IP is the gateway's — not yours. + +`Tunnel` gives you standard `TcpStream` and `UdpSocket` types (from tokio-smoltcp) that work transparently with the async Rust ecosystem: tokio-rustls for TLS, hyper for HTTP, tokio-tungstenite for WebSockets, etc. + +## Examples + +All examples include a clearnet-vs-mixnet comparison with timing and accept `--ipr
` for targeting a specific exit node. + +```sh +cargo run -p smolmix --example tcp # raw TCP connection +cargo run -p smolmix --example udp # raw UDP datagram +cargo run -p smolmix --example websocket # WebSocket over TLS (raw TcpStream composability) +``` + +## Architecture + +See [`src/ARCHITECTURE.md`](src/ARCHITECTURE.md). diff --git a/smolmix/core/examples/tcp.rs b/smolmix/core/examples/tcp.rs new file mode 100644 index 0000000000..884346a85c --- /dev/null +++ b/smolmix/core/examples/tcp.rs @@ -0,0 +1,131 @@ +//! HTTPS request through the Nym mixnet. +//! +//! Fetches Cloudflare's `/cdn-cgi/trace` diagnostic endpoint over clearnet +//! (reqwest) and through the mixnet (hyper over tokio-rustls over smolmix), +//! then compares the responses. The exit IP should differ — the mixnet path +//! exits through an IPR gateway. +//! +//! Run with: +//! cargo run -p smolmix --example tcp +//! cargo run -p smolmix --example tcp -- --ipr + +use std::sync::Arc; + +use http_body_util::BodyExt; +use hyper::body::Bytes; +use hyper::Request; +use hyper_util::rt::TokioIo; +use rustls::pki_types::ServerName; +use smolmix::Tunnel; +use tokio_rustls::TlsConnector; +use tracing::info; + +type BoxError = Box; + +const HOST: &str = "cloudflare.com"; +const PATH: &str = "/cdn-cgi/trace"; + +fn tls_connector() -> TlsConnector { + let mut root_store = rustls::RootCertStore::empty(); + root_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); + let config = rustls::ClientConfig::builder() + .with_root_certificates(root_store) + .with_no_client_auth(); + TlsConnector::from(Arc::new(config)) +} + +#[tokio::main] +async fn main() -> Result<(), BoxError> { + nym_bin_common::logging::setup_tracing_logger(); + rustls::crypto::ring::default_provider() + .install_default() + .expect("Failed to install rustls crypto provider"); + + // Clearnet baseline via reqwest + info!("Fetching via clearnet..."); + let clearnet_start = tokio::time::Instant::now(); + let clearnet_resp = reqwest::get(format!("https://{HOST}{PATH}")).await?; + let clearnet_status = clearnet_resp.status(); + let clearnet_body = clearnet_resp.text().await?; + let clearnet_duration = clearnet_start.elapsed(); + info!("Clearnet: {} in {:?}", clearnet_status, clearnet_duration); + + // Mixnet: smolmix TCP -> tokio-rustls -> hyper + let args: Vec = std::env::args().collect(); + let ipr_addr = args + .iter() + .position(|a| a == "--ipr") + .and_then(|i| args.get(i + 1)); + + let mut builder = Tunnel::builder(); + if let Some(addr) = ipr_addr { + builder = builder.ipr_address(addr.parse().expect("invalid IPR address")); + } + let tunnel = builder.build().await?; + + // Phase 1: Setup (TCP + TLS + HTTP handshakes) + let setup_start = tokio::time::Instant::now(); + + info!("TCP connecting to 1.1.1.1:443 via mixnet..."); + let tcp = tunnel.tcp_connect("1.1.1.1:443".parse()?).await?; + info!("TCP connected ({:?})", setup_start.elapsed()); + + info!("TLS handshake..."); + let connector = tls_connector(); + let domain = ServerName::try_from(HOST)?.to_owned(); + let tls = connector.connect(domain, tcp).await?; + info!("TLS established ({:?})", setup_start.elapsed()); + + info!("HTTP/1.1 handshake..."); + let (mut sender, conn) = hyper::client::conn::http1::handshake(TokioIo::new(tls)).await?; + tokio::spawn(conn); + + let setup_duration = setup_start.elapsed(); + info!("Setup complete ({:?})", setup_duration); + + // Phase 2: Request/response + let request_start = tokio::time::Instant::now(); + + info!("Sending GET {PATH}..."); + let req = Request::get(PATH) + .header("Host", HOST) + .body(http_body_util::Empty::::new())?; + let resp = sender.send_request(req).await?; + let mixnet_status = resp.status(); + let body_bytes = resp.into_body().collect().await?.to_bytes(); + let mixnet_body = String::from_utf8_lossy(&body_bytes); + + let request_duration = request_start.elapsed(); + info!( + "Response: {} ({} bytes, {:?})", + mixnet_status, + body_bytes.len(), + request_duration + ); + + // Results + let clearnet_ip = clearnet_body.lines().find(|l| l.starts_with("ip=")); + let mixnet_ip = mixnet_body.lines().find(|l| l.starts_with("ip=")); + + info!("Clearnet: {} in {:?}", clearnet_status, clearnet_duration); + info!( + "Mixnet: {} (setup {:?} + request {:?} = {:?})", + mixnet_status, + setup_duration, + request_duration, + setup_duration + request_duration + ); + info!("Clearnet IP: {}", clearnet_ip.unwrap_or("?")); + info!("Mixnet IP: {}", mixnet_ip.unwrap_or("?")); + + let total = setup_duration + request_duration; + let slowdown = total.as_millis() as f64 / clearnet_duration.as_millis().max(1) as f64; + info!( + "Slowdown: {slowdown:.1}x (setup: {:.1}x, request: {:.1}x)", + setup_duration.as_millis() as f64 / clearnet_duration.as_millis().max(1) as f64, + request_duration.as_millis() as f64 / clearnet_duration.as_millis().max(1) as f64 + ); + + tunnel.shutdown().await; + Ok(()) +} diff --git a/smolmix/core/examples/udp.rs b/smolmix/core/examples/udp.rs new file mode 100644 index 0000000000..6600fe6e8b --- /dev/null +++ b/smolmix/core/examples/udp.rs @@ -0,0 +1,96 @@ +//! DNS lookup through the Nym mixnet. +//! +//! Resolves `example.com` via clearnet (hickory-resolver) and via the mixnet +//! (hickory-proto UDP query to Cloudflare 1.1.1.1), then compares resolved +//! IPs and timing. +//! +//! +//! Run with: +//! cargo run -p smolmix --example udp +//! cargo run -p smolmix --example udp -- --ipr + +use std::net::Ipv4Addr; + +use hickory_proto::op::{Message, Query}; +use hickory_proto::rr::{Name, RData, RecordType}; +use hickory_resolver::TokioResolver; +use smolmix::Tunnel; +use tracing::info; + +type BoxError = Box; + +#[tokio::main] +async fn main() -> Result<(), BoxError> { + nym_bin_common::logging::setup_tracing_logger(); + + let domain = "example.com"; + + // Clearnet baseline via hickory-resolver + info!("Clearnet DNS lookup for '{domain}'..."); + let resolver = TokioResolver::builder_tokio()?.build(); + let clearnet_start = tokio::time::Instant::now(); + let lookup = resolver.lookup_ip(domain).await?; + let clearnet_ips: Vec = lookup + .iter() + .filter_map(|ip| match ip { + std::net::IpAddr::V4(v4) => Some(v4), + _ => None, + }) + .collect(); + let clearnet_duration = clearnet_start.elapsed(); + info!("Clearnet: {:?} in {:?}", clearnet_ips, clearnet_duration); + + // Mixnet: hickory-proto query over smolmix UDP + let args: Vec = std::env::args().collect(); + let ipr_addr = args + .iter() + .position(|a| a == "--ipr") + .and_then(|i| args.get(i + 1)); + + let mut builder = Tunnel::builder(); + if let Some(addr) = ipr_addr { + builder = builder.ipr_address(addr.parse().expect("invalid IPR address")); + } + let tunnel = builder.build().await?; + + let udp = tunnel.udp_socket().await?; + + let mut query = Message::new(); + query.set_recursion_desired(true); + query.add_query(Query::query(Name::from_ascii(domain)?, RecordType::A)); + let query_bytes = query.to_vec()?; + + // UDP is connectionless — no setup phase, just send/recv + info!("Sending DNS query via mixnet..."); + let mixnet_start = tokio::time::Instant::now(); + udp.send_to(&query_bytes, "1.1.1.1:53".parse()?).await?; + info!("Query sent ({:?})", mixnet_start.elapsed()); + + let mut buf = vec![0u8; 1500]; + let (n, _from) = udp.recv_from(&mut buf).await?; + let mixnet_duration = mixnet_start.elapsed(); + info!("Response received ({} bytes, {:?})", n, mixnet_duration); + + let response = Message::from_vec(&buf[..n])?; + let mixnet_ips: Vec = response + .answers() + .iter() + .filter_map(|r| match r.data() { + RData::A(a) => Some(a.0), + _ => None, + }) + .collect(); + + // Results + info!("Clearnet: {:?} ({:?})", clearnet_ips, clearnet_duration); + info!("Mixnet: {:?} ({:?})", mixnet_ips, mixnet_duration); + + let ips_match = !mixnet_ips.is_empty() && mixnet_ips.iter().all(|ip| clearnet_ips.contains(ip)); + info!("IPs match: {ips_match}"); + + let slowdown = mixnet_duration.as_millis() as f64 / clearnet_duration.as_millis().max(1) as f64; + info!("Slowdown: {slowdown:.1}x"); + + tunnel.shutdown().await; + Ok(()) +} diff --git a/smolmix/core/examples/websocket.rs b/smolmix/core/examples/websocket.rs new file mode 100644 index 0000000000..e5f3070e72 --- /dev/null +++ b/smolmix/core/examples/websocket.rs @@ -0,0 +1,143 @@ +//! WebSocket echo over the Nym mixnet. +//! +//! Demonstrates stacking tokio-tungstenite on top of tokio-rustls on top of +//! smolmix TcpStream. Sends a message to a public echo server via clearnet +//! and via the mixnet, then compares responses and timing. +//! +//! The clearnet and mixnet paths use the *exact same* TLS + WebSocket stack — +//! only the underlying TCP transport differs: +//! +//! ```text +//! tokio-tungstenite (WebSocket framing) +//! └─ tokio-rustls (TLS encryption) +//! └─ tokio::net::TcpStream (clearnet) +//! └─ smolmix::TcpStream (mixnet) +//! ``` +//! +//! Run with: +//! cargo run -p smolmix --example websocket +//! cargo run -p smolmix --example websocket -- --ipr + +use std::sync::Arc; + +use futures::{SinkExt, StreamExt}; +use rustls::pki_types::ServerName; +use smolmix::Tunnel; +use tokio_tungstenite::tungstenite::Message; +use tracing::info; + +type BoxError = Box; + +const WS_HOST: &str = "ws.postman-echo.com"; +const WS_PATH: &str = "/raw"; +const ECHO_MSG: &str = "Hello from the Nym mixnet!"; + +fn tls_connector() -> tokio_rustls::TlsConnector { + let mut root_store = rustls::RootCertStore::empty(); + root_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); + let config = rustls::ClientConfig::builder() + .with_root_certificates(root_store) + .with_no_client_auth(); + tokio_rustls::TlsConnector::from(Arc::new(config)) +} + +#[tokio::main] +async fn main() -> Result<(), BoxError> { + nym_bin_common::logging::setup_tracing_logger(); + rustls::crypto::ring::default_provider() + .install_default() + .expect("Failed to install rustls crypto provider"); + + // Resolve hostname via clearnet DNS - you can resolve via the Mixnet (see UDP example) but for this test its not necessary + let addr = tokio::net::lookup_host(format!("{WS_HOST}:443")) + .await? + .next() + .ok_or("DNS resolution failed")?; + info!("Resolved {WS_HOST} -> {addr}"); + + let connector = tls_connector(); + let domain = ServerName::try_from(WS_HOST)?.to_owned(); + + // Clearnet baseline: tokio TCP -> rustls -> tungstenite + info!("Connecting via clearnet..."); + let clearnet_start = tokio::time::Instant::now(); + + let clearnet_tcp = tokio::net::TcpStream::connect(addr).await?; + let clearnet_tls = connector.connect(domain.clone(), clearnet_tcp).await?; + let (mut clearnet_ws, _) = + tokio_tungstenite::client_async(format!("wss://{WS_HOST}{WS_PATH}"), clearnet_tls).await?; + + clearnet_ws.send(Message::Text(ECHO_MSG.into())).await?; + let clearnet_reply = clearnet_ws.next().await.ok_or("no clearnet reply")??; + let clearnet_duration = clearnet_start.elapsed(); + let clearnet_text = clearnet_reply.into_text()?; + clearnet_ws.close(None).await?; + + info!("Clearnet: \"{clearnet_text}\" in {clearnet_duration:?}"); + + // Mixnet: smolmix TCP -> rustls -> tungstenite (same stack) + let args: Vec = std::env::args().collect(); + let ipr_addr = args + .iter() + .position(|a| a == "--ipr") + .and_then(|i| args.get(i + 1)); + + let mut builder = Tunnel::builder(); + if let Some(addr) = ipr_addr { + builder = builder.ipr_address(addr.parse().expect("invalid IPR address")); + } + let tunnel = builder.build().await?; + info!("Allocated IP: {}", tunnel.allocated_ips().ipv4); + + // Phase 1: Setup (TCP + TLS + WebSocket handshakes) + let setup_start = tokio::time::Instant::now(); + + info!("TCP connecting via mixnet..."); + let mixnet_tcp = tunnel.tcp_connect(addr).await?; + info!("TCP connected ({:?})", setup_start.elapsed()); + + info!("TLS handshake..."); + let mixnet_tls = connector.connect(domain, mixnet_tcp).await?; + info!("TLS established ({:?})", setup_start.elapsed()); + + info!("WebSocket upgrade..."); + let (mut mixnet_ws, _) = + tokio_tungstenite::client_async(format!("wss://{WS_HOST}{WS_PATH}"), mixnet_tls).await?; + + let setup_duration = setup_start.elapsed(); + info!("Setup complete ({:?})", setup_duration); + + // Phase 2: Echo request/response + let request_start = tokio::time::Instant::now(); + + mixnet_ws.send(Message::Text(ECHO_MSG.into())).await?; + let mixnet_reply = mixnet_ws.next().await.ok_or("no mixnet reply")??; + + let request_duration = request_start.elapsed(); + let mixnet_text = mixnet_reply.into_text()?; + mixnet_ws.close(None).await?; + + info!("Echo: \"{mixnet_text}\" ({:?})", request_duration); + + // Results + info!("Clearnet: \"{clearnet_text}\" in {clearnet_duration:?}"); + info!( + "Mixnet: \"{mixnet_text}\" (setup {:?} + echo {:?} = {:?})", + setup_duration, + request_duration, + setup_duration + request_duration + ); + info!("Clearnet echo match: {}", clearnet_text == ECHO_MSG); + info!("Mixnet echo match: {}", mixnet_text == ECHO_MSG); + + let total = setup_duration + request_duration; + let slowdown = total.as_millis() as f64 / clearnet_duration.as_millis().max(1) as f64; + info!( + "Slowdown: {slowdown:.1}x (setup: {:.1}x, echo: {:.1}x)", + setup_duration.as_millis() as f64 / clearnet_duration.as_millis().max(1) as f64, + request_duration.as_millis() as f64 / clearnet_duration.as_millis().max(1) as f64 + ); + + tunnel.shutdown().await; + Ok(()) +} diff --git a/smolmix/core/src/ARCHITECTURE.md b/smolmix/core/src/ARCHITECTURE.md new file mode 100644 index 0000000000..5425ad8b47 --- /dev/null +++ b/smolmix/core/src/ARCHITECTURE.md @@ -0,0 +1,70 @@ +# Architecture + +smolmix is a TCP/UDP tunnel over the Nym mixnet. It gives you standard +`TcpStream` and `UdpSocket` types that work transparently with the async Rust +ecosystem (tokio-rustls, hyper, tokio-tungstenite, etc.) while routing all +traffic through the mixnet for metadata privacy. + +## Stack + +```text +┌─────────────────────────────────────────────────────────────────┐ +│ User code │ +│ tunnel.tcp_connect() → TcpStream (AsyncRead + AsyncWrite) │ +│ tunnel.udp_socket() → UdpSocket (send_to / recv_from) │ +├─────────────────────────────────────────────────────────────────┤ +│ tokio-smoltcp::Net │ +│ Owns the smoltcp Interface + SocketSet + async poll loop. │ +│ Manages TCP state machines, retransmits, port allocation. │ +├─────────────────────────────────────────────────────────────────┤ +│ NymAsyncDevice (device.rs) │ +│ Stream + Sink adapter for raw IP packets over mpsc channels. │ +├─────────────────────────────────────────────────────────────────┤ +│ NymIprBridge (bridge.rs) │ +│ Background task shuttling packets between channels and the │ +│ mixnet. Bundles outgoing packets with MultiIpPacketCodec │ +│ (required by the IPR protocol). │ +├─────────────────────────────────────────────────────────────────┤ +│ IpMixStream → MixnetClient → Nym mixnet → IPR exit node │ +└─────────────────────────────────────────────────────────────────┘ +``` + +## Data flow + +```text +outgoing: smoltcp → NymAsyncDevice (Sink) → channel → NymIprBridge → IpMixStream → mixnet +incoming: mixnet → IpMixStream → NymIprBridge → channel → NymAsyncDevice (Stream) → smoltcp +``` + +tokio-smoltcp handles all the hard parts (smoltcp polling, TCP state machines, +port allocation, waker management). We just give it a device that produces and +consumes raw IP packets — `NymAsyncDevice` wraps the mpsc channel ends in the +`Stream`/`Sink` traits that tokio-smoltcp requires. + +## Key design decisions + +- **Single async device adapter.** All traffic flows through one + `NymAsyncDevice`. If you need a new transport type (e.g. ICMP), add a method + to `Tunnel` rather than introducing a separate device — the device and bridge + don't need to change. smoltcp already supports ICMP sockets; you'd enable + the `socket-icmp` feature in `Cargo.toml`, add a method like + `Tunnel::icmp_socket()` that calls the appropriate `Net` method, and expose + the socket type via a re-export in `lib.rs`. + +- **Tokio-only.** The bridge, SDK (`IpMixStream`, `MixnetClient`), and shutdown + signaling are tokio-based. The data-plane channels use `futures::channel::mpsc` + because `UnboundedSender` implements `Sink` — required by tokio-smoltcp's + `AsyncDevice` trait. An earlier version had a sync smoltcp `Device` adapter + for use without tokio-smoltcp, but it still required a tokio runtime + underneath (for the bridge and SDK), so it provided no real runtime + independence — just duplicated the bridging logic. If alternative-runtime + support is ever needed, it would require swapping out the bridge, SDK, and + channel layers — a separate crate, not a feature flag on this one. + +- **Unbounded channels.** The channels between the device and bridge are + unbounded. Backpressure is handled at the mixnet layer (IPR protocol), not + at the channel level. If that assumption changes, consider bounded channels + with a drop policy. + +- **`Medium::Ip` (no Ethernet framing).** Raw IP packets go in and out, + matching what the IPR protocol expects. diff --git a/smolmix/core/src/bridge.rs b/smolmix/core/src/bridge.rs new file mode 100644 index 0000000000..39577aba71 --- /dev/null +++ b/smolmix/core/src/bridge.rs @@ -0,0 +1,164 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-2.0-only + +use crate::error::SmolmixError; +use futures::channel::mpsc; +use futures::StreamExt; +use nym_ip_packet_requests::codec::MultiIpPacketCodec; +use nym_sdk::ipr_wrapper::IpMixStream; +use tokio::sync::oneshot; +use tracing::{debug, error, info, trace, warn}; + +/// Asynchronous bridge between the smoltcp device and the Nym mixnet. +/// +/// Runs as a background task, shuttling raw IP packets in both directions: +/// +/// **Outgoing** (smoltcp → mixnet): receives packets from the device via channel, +/// bundles them with [`MultiIpPacketCodec`] (required by the IPR protocol), and +/// sends them through the mixnet. +/// +/// **Incoming** (mixnet → smoltcp): polls the mixnet for packets and forwards +/// them to the device via channel for smoltcp consumption. +pub(crate) struct NymIprBridge { + stream: IpMixStream, + /// Receives outgoing packets from the device (smoltcp → bridge → mixnet). + outgoing_rx: mpsc::UnboundedReceiver>, + /// Sends incoming packets to the device (mixnet → bridge → smoltcp). + /// + /// Unbounded: backpressure is handled at the mixnet layer (IPR protocol), + /// not here. If that changes, consider bounded channels with a drop policy. + incoming_tx: mpsc::UnboundedSender>, + shutdown_rx: oneshot::Receiver<()>, +} + +/// Handle for signaling the bridge to shut down gracefully. +pub(crate) struct BridgeShutdownHandle { + tx: Option>, +} + +impl BridgeShutdownHandle { + /// Signal the bridge to shut down gracefully. + /// + /// Sends a one-shot signal that breaks the bridge event loop. The bridge + /// then calls `IpMixStream::disconnect()` before returning. Consumes + /// `self` — can only be called once. + /// + /// If this handle is dropped without calling `shutdown()`, the `Drop` + /// impl sends the signal automatically. + pub(crate) fn shutdown(mut self) { + if let Some(tx) = self.tx.take() { + let _ = tx.send(()); + } + } +} + +impl Drop for BridgeShutdownHandle { + fn drop(&mut self) { + if let Some(tx) = self.tx.take() { + let _ = tx.send(()); + } + } +} + +impl NymIprBridge { + /// Create a new bridge and its associated shutdown handle. + /// + /// Returns `(bridge, shutdown_handle)`. + /// + /// # Parameters + /// - `stream` — the connected `IpMixStream` (owns the mixnet client) + /// - `outgoing_rx` — receives raw IP packets from the smoltcp device + /// - `incoming_tx` — sends raw IP packets to the smoltcp device + pub(crate) fn new( + stream: IpMixStream, + outgoing_rx: mpsc::UnboundedReceiver>, + incoming_tx: mpsc::UnboundedSender>, + ) -> (Self, BridgeShutdownHandle) { + let (shutdown_tx, shutdown_rx) = oneshot::channel(); + ( + Self { + stream, + outgoing_rx, + incoming_tx, + shutdown_rx, + }, + BridgeShutdownHandle { + tx: Some(shutdown_tx), + }, + ) + } + + /// Runs the bridge event loop. + /// + /// Should be spawned via `tokio::spawn`. The loop exits when a shutdown + /// signal is received, channels close, or an unrecoverable error occurs. + /// + /// # Cancel safety + /// + /// `IpMixStream::handle_incoming()` is **not** cancel-safe — its internal + /// `FramedRead` buffers partial frames, and it mutates connection state after + /// awaiting. In `tokio::select!`, the shutdown branch can cancel a pending + /// `handle_incoming()` call, potentially losing buffered data. This is + /// acceptable during shutdown but worth noting for future changes. + pub(crate) async fn run(mut self) -> Result<(), SmolmixError> { + info!("Starting bridge"); + let mut packets_sent: u64 = 0; + let mut packets_received: u64 = 0; + + loop { + tokio::select! { + _ = &mut self.shutdown_rx => { + info!(packets_sent, packets_received, "Bridge received shutdown signal"); + break; + } + + Some(packet) = self.outgoing_rx.next() => { + trace!(len = packet.len(), "Sending packet to mixnet"); + + // IPR expects packets wrapped in MultiIpPacketCodec framing. + let bundled = MultiIpPacketCodec::bundle_one_packet(packet.into()); + if let Err(e) = self.stream.send_ip_packet(&bundled).await { + error!("Failed to send packet through mixnet: {e}"); + } else { + packets_sent += 1; + debug!(packets_sent, "Packet sent"); + } + } + + result = self.stream.handle_incoming() => { + match result { + Ok(packets) if !packets.is_empty() => { + trace!(count = packets.len(), "Received packets from mixnet"); + for packet in packets { + if self.incoming_tx.unbounded_send(packet.to_vec()).is_err() { + error!("Device channel closed"); + return Err(SmolmixError::ChannelClosed); + } + packets_received += 1; + } + debug!(packets_received, "Packets received"); + } + Ok(_) => {} // empty batch, keep polling + Err(e) => { + // handle_incoming() internally uses a 10-second timeout, + // so this won't busy-loop on persistent errors. + warn!("Mixnet receive error: {e}"); + } + } + } + + else => { + info!(packets_sent, packets_received, "All channels closed, shutting down"); + break; + } + } + } + + // disconnect() internally waits for all SDK tasks via TaskTracker. + info!("Disconnecting from mixnet..."); + self.stream.disconnect().await; + info!("Disconnected"); + + Ok(()) + } +} diff --git a/smolmix/core/src/device.rs b/smolmix/core/src/device.rs new file mode 100644 index 0000000000..012c3fa768 --- /dev/null +++ b/smolmix/core/src/device.rs @@ -0,0 +1,94 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-2.0-only + +//! Async device adapter for tokio-smoltcp. +//! +//! Wraps mpsc channel ends (connected to [`NymIprBridge`](crate::bridge::NymIprBridge)) +//! in the [`Stream`]/[`Sink`] traits that tokio-smoltcp requires. See the +//! [crate-level docs](crate) for how this fits into the full stack. + +use std::io; +use std::pin::Pin; +use std::task::{Context, Poll}; + +use futures::channel::mpsc; +use futures::{Sink, Stream}; +use smoltcp::phy::{DeviceCapabilities, Medium}; +use tokio_smoltcp::device::AsyncDevice; + +/// Async adapter bridging mpsc channels to tokio-smoltcp's [`AsyncDevice`] trait. +/// +/// Incoming packets (mixnet → smoltcp) arrive via the `rx` channel as a [`Stream`]. +/// Outgoing packets (smoltcp → mixnet) are sent via the `tx` channel as a [`Sink`]. +pub(crate) struct NymAsyncDevice { + rx: mpsc::UnboundedReceiver>, + tx: mpsc::UnboundedSender>, + capabilities: DeviceCapabilities, +} + +impl NymAsyncDevice { + pub(crate) fn new( + rx: mpsc::UnboundedReceiver>, + tx: mpsc::UnboundedSender>, + ) -> Self { + let mut capabilities = DeviceCapabilities::default(); + capabilities.medium = Medium::Ip; + capabilities.max_transmission_unit = 1500; + capabilities.max_burst_size = Some(1); + + Self { + rx, + tx, + capabilities, + } + } +} + +// tokio-smoltcp calls poll_next() in its reactor loop to feed packets into the +// smoltcp Interface for processing. +impl Stream for NymAsyncDevice { + type Item = io::Result>; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.rx).poll_next(cx).map(|opt| opt.map(Ok)) + } +} + +// When smoltcp produces a packet (e.g. TCP SYN, data segment, UDP datagram), +// tokio-smoltcp sends it here and we forward it to the bridge for mixnet delivery. +// +// Delegates to the built-in Sink impl on futures::channel::mpsc::UnboundedSender, +// which handles channel liveness checks (poll_ready) and disconnect (poll_close). +impl Sink> for NymAsyncDevice { + type Error = io::Error; + + fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.tx) + .poll_ready(cx) + .map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, "bridge channel closed")) + } + + fn start_send(mut self: Pin<&mut Self>, item: Vec) -> Result<(), Self::Error> { + Pin::new(&mut self.tx) + .start_send(item) + .map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, "bridge channel closed")) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.tx) + .poll_flush(cx) + .map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, "bridge channel closed")) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.tx) + .poll_close(cx) + .map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, "bridge channel closed")) + } +} + +impl AsyncDevice for NymAsyncDevice { + fn capabilities(&self) -> &DeviceCapabilities { + &self.capabilities + } +} diff --git a/smolmix/core/src/error.rs b/smolmix/core/src/error.rs new file mode 100644 index 0000000000..226fcb9efd --- /dev/null +++ b/smolmix/core/src/error.rs @@ -0,0 +1,19 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-2.0-only + +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum SmolmixError { + #[error("Channel closed")] + ChannelClosed, + + #[error("Not connected to IPR")] + NotConnected, + + #[error("Nym SDK error: {0}")] + NymSdk(#[from] nym_sdk::Error), + + #[error("IO error: {0}")] + Io(#[from] std::io::Error), +} diff --git a/smolmix/core/src/lib.rs b/smolmix/core/src/lib.rs new file mode 100644 index 0000000000..45a0392ab4 --- /dev/null +++ b/smolmix/core/src/lib.rs @@ -0,0 +1,62 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-2.0-only + +#![doc = include_str!("ARCHITECTURE.md")] + +mod bridge; +mod device; +mod error; +mod tunnel; + +/// Error type for all fallible smolmix operations. +pub use error::SmolmixError; + +/// The IPv4/IPv6 address pair allocated to this tunnel by the IPR. +pub use tunnel::IpPair; + +/// A Nym mixnet address, used to target a specific IPR exit node. +pub use tunnel::Recipient; + +/// A TCP stream routed through the mixnet. Implements `AsyncRead + AsyncWrite`. +/// +/// Obtained via [`Tunnel::tcp_connect`]. Works as a drop-in replacement for +/// `tokio::net::TcpStream` with tokio-rustls, hyper, tokio-tungstenite, etc. +/// +/// ```no_run +/// # async fn example() -> Result<(), Box> { +/// # let tunnel = smolmix::Tunnel::new().await?; +/// use tokio::io::{AsyncReadExt, AsyncWriteExt}; +/// +/// let mut stream = tunnel.tcp_connect("1.1.1.1:80".parse()?).await?; +/// stream.write_all(b"GET / HTTP/1.1\r\nHost: 1.1.1.1\r\nConnection: close\r\n\r\n").await?; +/// let mut buf = Vec::new(); +/// stream.read_to_end(&mut buf).await?; +/// # Ok(()) +/// # } +/// ``` +pub use tunnel::TcpStream; + +/// A mixnet tunnel providing TCP and UDP socket access. +pub use tunnel::Tunnel; + +/// Builder for configuring and creating a [`Tunnel`]. +/// +/// See [`Tunnel::builder()`] for usage. +pub use tunnel::TunnelBuilder; + +/// A UDP socket routed through the mixnet. Supports `send_to` / `recv_from`. +/// +/// Obtained via [`Tunnel::udp_socket`] or [`Tunnel::udp_socket_on`]. +/// +/// ```no_run +/// # async fn example() -> Result<(), Box> { +/// # let tunnel = smolmix::Tunnel::new().await?; +/// let udp = tunnel.udp_socket().await?; +/// udp.send_to(b"hello", "1.1.1.1:9999".parse()?).await?; +/// +/// let mut buf = [0u8; 1024]; +/// let (len, _src) = udp.recv_from(&mut buf).await?; +/// # Ok(()) +/// # } +/// ``` +pub use tunnel::UdpSocket; diff --git a/smolmix/core/src/tunnel.rs b/smolmix/core/src/tunnel.rs new file mode 100644 index 0000000000..b59b86953b --- /dev/null +++ b/smolmix/core/src/tunnel.rs @@ -0,0 +1,361 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-2.0-only + +//! High-level tunnel providing TCP and UDP sockets over the Nym mixnet. +//! +//! See the [crate-level docs](crate) for the full architecture diagram. +//! +//! The returned [`TcpStream`] implements `tokio::io::AsyncRead + AsyncWrite`, so it +//! works transparently with the entire async Rust ecosystem: tokio-rustls for TLS, +//! tokio-tungstenite for WebSockets, hyper for HTTP, etc. + +use std::net::SocketAddr; +use std::sync::Arc; + +use futures::channel::mpsc; +pub use nym_ip_packet_requests::IpPair; +use nym_sdk::ipr_wrapper::IpMixStream; +use smoltcp::iface::Config; +use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr, Ipv4Address}; +use tokio::sync::Mutex; +use tokio::task::JoinHandle; +use tracing::info; + +use crate::bridge::{BridgeShutdownHandle, NymIprBridge}; +use crate::device::NymAsyncDevice; +use crate::SmolmixError; +use tokio_smoltcp::{Net, NetConfig}; + +pub use nym_sdk::mixnet::Recipient; +pub use tokio_smoltcp::{TcpStream, UdpSocket}; + +struct ShutdownState { + bridge_shutdown: BridgeShutdownHandle, + bridge_handle: JoinHandle>, +} + +struct TunnelInner { + /// tokio-smoltcp network stack. Its methods take &self, so multiple tasks can + /// open sockets concurrently without locking. + net: Net, + allocated_ips: IpPair, + /// Mutex only protects shutdown — called once, not on the hot path. + shutdown: Mutex>, +} + +/// A mixnet tunnel providing TCP and UDP socket access. +/// +/// `Tunnel` manages a smoltcp network stack connected to the Nym mixnet via an IPR +/// (Internet Packet Router). It spawns a background bridge task and a network reactor, +/// then provides familiar socket APIs on top. +/// +/// +/// # Shutdown +/// +/// Call [`shutdown()`](Self::shutdown) for a clean disconnect. Rust has no async `Drop`, +/// so dropping without calling `shutdown()` triggers a fire-and-forget cleanup via the +/// oneshot channel — the bridge will still shut down, but the caller can't await it. +/// +/// # Examples +/// +/// ```no_run +/// # async fn example() -> Result<(), Box> { +/// use smolmix::Tunnel; +/// use tokio::io::{AsyncReadExt, AsyncWriteExt}; +/// +/// let tunnel = Tunnel::new().await?; +/// +/// // TCP — connect and use like any async stream +/// let mut tcp = tunnel.tcp_connect("1.1.1.1:80".parse()?).await?; +/// tcp.write_all(b"GET / HTTP/1.1\r\nHost: 1.1.1.1\r\nConnection: close\r\n\r\n").await?; +/// let mut buf = Vec::new(); +/// tcp.read_to_end(&mut buf).await?; +/// +/// // UDP — datagrams over the mixnet +/// let udp = tunnel.udp_socket().await?; +/// udp.send_to(b"hello", "1.1.1.1:9999".parse()?).await?; +/// +/// // Share across tasks (cheap Arc-based clone) +/// let t2 = tunnel.clone(); +/// tokio::spawn(async move { +/// let _tcp2 = t2.tcp_connect("93.184.216.34:80".parse().unwrap()).await.unwrap(); +/// }); +/// +/// tunnel.shutdown().await; +/// # Ok(()) +/// # } +/// ``` +/// +/// See also the repository examples: `tcp`, `udp`, `websocket`. +#[derive(Clone)] +pub struct Tunnel { + inner: Arc, +} + +/// Builder for configuring and creating a [`Tunnel`]. +/// +/// Use [`Tunnel::builder()`] to create a new builder. +/// +/// # Examples +/// +/// ```no_run +/// # async fn example() -> Result<(), Box> { +/// use smolmix::Tunnel; +/// +/// // Auto-discover the best IPR: +/// let tunnel = Tunnel::builder().build().await?; +/// +/// // Or specify an IPR exit node: +/// use smolmix::Recipient; +/// let ipr: Recipient = "gateway-address...".parse()?; +/// let tunnel = Tunnel::builder().ipr_address(ipr).build().await?; +/// # Ok(()) +/// # } +/// ``` +/// +/// For full control over the mixnet client (credentials, gateway selection, +/// storage, etc.), configure an [`IpMixStream`] directly and pass it to +/// [`Tunnel::from_stream()`]. Deeper builder integration with `MixnetClientBuilder` +/// will require upstream SDK changes to expose `IpMixStream` internals (TODO). +pub struct TunnelBuilder { + ipr_address: Option, +} + +impl TunnelBuilder { + /// Target a specific IPR exit node instead of auto-discovering one. + pub fn ipr_address(mut self, addr: Recipient) -> Self { + self.ipr_address = Some(addr); + self + } + + /// Build and connect the tunnel. + pub async fn build(self) -> Result { + let stream = match self.ipr_address { + Some(addr) => IpMixStream::new_with_ipr(addr).await?, + None => IpMixStream::new().await?, + }; + Tunnel::from_stream(stream).await + } +} + +impl Tunnel { + /// Create a [`TunnelBuilder`] for configuring the tunnel before connecting. + /// + /// ```no_run + /// # async fn example() -> Result<(), Box> { + /// use smolmix::Tunnel; + /// let tunnel = Tunnel::builder().build().await?; + /// # Ok(()) + /// # } + /// ``` + pub fn builder() -> TunnelBuilder { + TunnelBuilder { ipr_address: None } + } + + /// Create a new tunnel, automatically discovering the best IPR exit node. + /// + /// Shorthand for `Tunnel::builder().build().await`. + /// + /// ```no_run + /// # async fn example() -> Result<(), Box> { + /// use smolmix::Tunnel; + /// let tunnel = Tunnel::new().await?; + /// let tcp = tunnel.tcp_connect("1.1.1.1:443".parse()?).await?; + /// # Ok(()) + /// # } + /// ``` + pub async fn new() -> Result { + Self::builder().build().await + } + + /// Create a new tunnel connected to a specific IPR exit node. + /// + /// Shorthand for `Tunnel::builder().ipr_address(addr).build().await`. + /// + /// ```no_run + /// # async fn example() -> Result<(), Box> { + /// use smolmix::{Recipient, Tunnel}; + /// let ipr: Recipient = "gateway-address...".parse()?; + /// let tunnel = Tunnel::new_with_ipr(ipr).await?; + /// # Ok(()) + /// # } + /// ``` + pub async fn new_with_ipr(ipr_address: Recipient) -> Result { + Self::builder().ipr_address(ipr_address).build().await + } + + /// Create a tunnel from a pre-configured [`IpMixStream`]. + /// + /// Use this for full control over the mixnet client (credentials, gateway + /// selection, storage, etc.) — configure the `IpMixStream` upstream and + /// pass it in directly. + pub async fn from_stream(ipr_stream: IpMixStream) -> Result { + ipr_stream + .check_connected() + .map_err(|_| SmolmixError::NotConnected)?; + + let allocated_ips = *ipr_stream.allocated_ips(); + + // Wire up two channel pairs connecting the bridge (async mixnet I/O) to the + // async device adapter (which tokio-smoltcp polls for raw IP packets): + // + // outgoing: smoltcp → NymAsyncDevice.Sink → outgoing_tx → outgoing_rx → Bridge → mixnet + // incoming: mixnet → Bridge → incoming_tx → incoming_rx → NymAsyncDevice.Stream → smoltcp + let (outgoing_tx, outgoing_rx) = mpsc::unbounded(); + let (incoming_tx, incoming_rx) = mpsc::unbounded(); + + // Bridge runs as a background task, shuttling packets between channels and IpMixStream. + let (bridge, bridge_shutdown) = NymIprBridge::new(ipr_stream, outgoing_rx, incoming_tx); + let bridge_handle = tokio::spawn(bridge.run()); + + // NymAsyncDevice wraps the channel ends as Stream + Sink, which is all + // tokio-smoltcp needs to drive the smoltcp Interface internally. + let device = NymAsyncDevice::new(incoming_rx, outgoing_tx); + + // Configure smoltcp: raw IP mode (no Ethernet), /32 for our allocated IP, + // default route via unspecified (the IPR handles actual routing). + let iface_config = Config::new(HardwareAddress::Ip); + let net_config = NetConfig::new( + iface_config, + IpCidr::new(IpAddress::from(allocated_ips.ipv4), 32), + vec![IpAddress::from(Ipv4Address::UNSPECIFIED)], + ); + + // Net::new spawns the smoltcp reactor as a background task. From here on, + // tcp_connect/udp_bind create sockets managed by that reactor. + let net = Net::new(device, net_config); + + info!("Tunnel ready, allocated IP: {}", allocated_ips.ipv4); + + Ok(Self { + inner: Arc::new(TunnelInner { + net, + allocated_ips, + shutdown: Mutex::new(Some(ShutdownState { + bridge_shutdown, + bridge_handle, + })), + }), + }) + } + + /// Open a TCP connection to `addr` through the mixnet. + /// + /// The returned [`TcpStream`] implements `tokio::io::AsyncRead + AsyncWrite`, + /// so it works transparently with tokio-rustls, hyper, tokio-tungstenite, and + /// any other async I/O consumer. + /// + /// # Errors + /// + /// Returns [`SmolmixError::Io`] if the TCP handshake fails (connection + /// refused, timeout, etc.) or if the tunnel has been shut down. + /// + /// # Examples + /// + /// Raw HTTP request: + /// ```no_run + /// # async fn example() -> Result<(), Box> { + /// # let tunnel = smolmix::Tunnel::new().await?; + /// use tokio::io::{AsyncReadExt, AsyncWriteExt}; + /// + /// let mut tcp = tunnel.tcp_connect("1.1.1.1:80".parse()?).await?; + /// tcp.write_all(b"GET / HTTP/1.1\r\nHost: 1.1.1.1\r\nConnection: close\r\n\r\n").await?; + /// + /// let mut response = Vec::new(); + /// tcp.read_to_end(&mut response).await?; + /// # Ok(()) + /// # } + /// ``` + /// + /// TLS via tokio-rustls (the stream is a drop-in for `tokio::net::TcpStream`): + /// ```no_run + /// # async fn example() -> Result<(), Box> { + /// # let tunnel = smolmix::Tunnel::new().await?; + /// use rustls::pki_types::ServerName; + /// use tokio_rustls::TlsConnector; + /// + /// let tcp = tunnel.tcp_connect("93.184.216.34:443".parse()?).await?; + /// # let connector: TlsConnector = todo!(); + /// let tls = connector.connect(ServerName::try_from("example.com")?.to_owned(), tcp).await?; + /// // `tls` implements AsyncRead + AsyncWrite — use with hyper, tungstenite, etc. + /// # Ok(()) + /// # } + /// ``` + pub async fn tcp_connect(&self, addr: SocketAddr) -> Result { + Ok(self.inner.net.tcp_connect(addr).await?) + } + + /// Create a UDP socket bound to an ephemeral port. + /// + /// The port is chosen by smoltcp's allocator. Use [`udp_socket_on`](Self::udp_socket_on) + /// if you need a specific port (e.g. for a protocol that expects replies on + /// a known port). + /// + /// The returned [`UdpSocket`] supports `send_to` / `recv_from` for datagram I/O. + /// + /// # Examples + /// + /// Send a DNS query and read the response: + /// ```no_run + /// # async fn example() -> Result<(), Box> { + /// # let tunnel = smolmix::Tunnel::new().await?; + /// let udp = tunnel.udp_socket().await?; + /// + /// // Send a raw DNS query to Cloudflare + /// let query = b"\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\ + /// \x07example\x03com\x00\x00\x01\x00\x01"; + /// udp.send_to(query, "1.1.1.1:53".parse()?).await?; + /// + /// let mut buf = [0u8; 512]; + /// let (len, _src) = udp.recv_from(&mut buf).await?; + /// println!("Got {} bytes back", len); + /// # Ok(()) + /// # } + /// ``` + pub async fn udp_socket(&self) -> Result { + let addr: SocketAddr = ([0, 0, 0, 0], 0).into(); + Ok(self.inner.net.udp_bind(addr).await?) + } + + /// Create a UDP socket bound to a specific local port. + /// + /// Binds to `0.0.0.0:` on the tunnel's virtual interface. Use this when + /// the remote side expects replies on a well-known port, or when you need + /// multiple sockets on distinct ports. + pub async fn udp_socket_on(&self, port: u16) -> Result { + let addr: SocketAddr = ([0, 0, 0, 0], port).into(); + Ok(self.inner.net.udp_bind(addr).await?) + } + + /// The IPv4/IPv6 address pair allocated to this tunnel by the IPR. + /// + /// Available immediately after construction. The IPv4 address is assigned as + /// a /32 on the tunnel's virtual interface — all traffic to/from external + /// hosts appears to originate from this IP at the exit gateway. + pub fn allocated_ips(&self) -> IpPair { + self.inner.allocated_ips + } + + /// Gracefully shut down the tunnel. + /// + /// Signals the bridge to disconnect from the mixnet and waits for it to finish. + /// The smoltcp reactor stops when all `Tunnel` clones are dropped. + /// + /// If the `Tunnel` is dropped without calling `shutdown()`, cleanup still happens: + /// dropping the `Arc` drops the oneshot sender inside `ShutdownState`, + /// which resolves the bridge's `shutdown_rx` and triggers its shutdown path. However, + /// the drop path is fire-and-forget — call `shutdown()` explicitly if you need to + /// wait for the mixnet disconnect to complete. + /// + /// After shutdown, new socket operations (`tcp_connect`, `udp_socket`) will fail + /// with IO errors — the bridge channels are closed. + pub async fn shutdown(&self) { + let mut state = self.inner.shutdown.lock().await; + if let Some(s) = state.take() { + info!("Shutting down tunnel"); + s.bridge_shutdown.shutdown(); + let _ = s.bridge_handle.await; + info!("Tunnel shut down"); + } + } +} From ad56645fc50017adfc2dd096c97a3d4f2fbb9673 Mon Sep 17 00:00:00 2001 From: dynco-nym <173912580+dynco-nym@users.noreply.github.com> Date: Wed, 15 Apr 2026 15:59:38 +0200 Subject: [PATCH 02/37] Block non-public IPR/NR checks (#6670) * Block non-public IPR/NR checks * Add CLI override flag --- common/bin-common/Cargo.toml | 1 + .../bin-common/src/ip_check/mod.rs | 31 +++++++---------- common/bin-common/src/lib.rs | 3 ++ nym-node/Cargo.toml | 1 + nym-node/src/cli/commands/run/mod.rs | 2 +- nym-node/src/cli/helpers.rs | 26 ++++++++++++++ nym-node/src/config/helpers.rs | 2 ++ .../src/config/old_configs/old_config_v12.rs | 2 ++ nym-node/src/config/service_providers.rs | 12 +++++++ nym-node/src/env.rs | 2 ++ .../src/node/mixnet/packet_forwarding/mod.rs | 2 -- .../src/node/routing_filter/network_filter.rs | 2 +- service-providers/ip-packet-router/Cargo.toml | 2 +- .../ip-packet-router/src/config/mod.rs | 6 ++++ .../src/config/old_config_v1.rs | 1 + .../src/request_filter/exit_policy/mod.rs | 22 ++++++++++-- .../src/request_filter/mod.rs | 12 +++++-- .../network-requester/Cargo.toml | 2 +- .../network-requester/src/config/mod.rs | 6 ++++ .../network-requester/src/config/old/v5.rs | 1 + .../network-requester/src/config/template.rs | 5 +++ .../src/request_filter/exit_policy/mod.rs | 34 +++++++++++++++---- 22 files changed, 142 insertions(+), 35 deletions(-) rename nym-node/src/node/mixnet/packet_forwarding/global.rs => common/bin-common/src/ip_check/mod.rs (92%) diff --git a/common/bin-common/Cargo.toml b/common/bin-common/Cargo.toml index b10a29b84c..dd2a70291b 100644 --- a/common/bin-common/Cargo.toml +++ b/common/bin-common/Cargo.toml @@ -38,6 +38,7 @@ default = [] openapi = ["utoipa"] output_format = ["serde_json", "dep:clap"] bin_info_schema = ["schemars"] +ip_check = [] basic_tracing = ["dep:tracing", "dep:tracing-subscriber"] otel-otlp = [ "basic_tracing", diff --git a/nym-node/src/node/mixnet/packet_forwarding/global.rs b/common/bin-common/src/ip_check/mod.rs similarity index 92% rename from nym-node/src/node/mixnet/packet_forwarding/global.rs rename to common/bin-common/src/ip_check/mod.rs index 6f27444a57..26a10e9005 100644 --- a/nym-node/src/node/mixnet/packet_forwarding/global.rs +++ b/common/bin-common/src/ip_check/mod.rs @@ -1,29 +1,12 @@ -// Copyright 2025 - Nym Technologies SA -// SPDX-License-Identifier: GPL-3.0-only - use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; -// use `ip` feature without nightly -// issue: https://github.com/rust-lang/rust/issues/27709 -pub(crate) const fn is_global_ip(ip: &IpAddr) -> bool { +pub const fn is_global_ip(ip: &IpAddr) -> bool { match ip { IpAddr::V4(addr) => is_global_ipv4(addr), IpAddr::V6(addr) => is_global_ipv6(addr), } } -const fn is_shared_ipv4(ip: &Ipv4Addr) -> bool { - ip.octets()[0] == 100 && (ip.octets()[1] & 0b1100_0000 == 0b0100_0000) -} - -const fn is_benchmarking_ipv4(ip: &Ipv4Addr) -> bool { - ip.octets()[0] == 198 && (ip.octets()[1] & 0xfe) == 18 -} - -const fn is_reserved_ipv4(ip: &Ipv4Addr) -> bool { - ip.octets()[0] & 240 == 240 && !ip.is_broadcast() -} - const fn is_global_ipv4(ip: &Ipv4Addr) -> bool { !(ip.octets()[0] == 0 // "This network" || ip.is_private() @@ -42,6 +25,18 @@ const fn is_global_ipv4(ip: &Ipv4Addr) -> bool { || ip.is_broadcast()) } +const fn is_shared_ipv4(ip: &Ipv4Addr) -> bool { + ip.octets()[0] == 100 && (ip.octets()[1] & 0b1100_0000 == 0b0100_0000) +} + +const fn is_benchmarking_ipv4(ip: &Ipv4Addr) -> bool { + ip.octets()[0] == 198 && (ip.octets()[1] & 0xfe) == 18 +} + +const fn is_reserved_ipv4(ip: &Ipv4Addr) -> bool { + ip.octets()[0] & 240 == 240 && !ip.is_broadcast() +} + const fn is_documentation_ipv6(ip: &Ipv6Addr) -> bool { (ip.segments()[0] == 0x2001) && (ip.segments()[1] == 0xdb8) } diff --git a/common/bin-common/src/lib.rs b/common/bin-common/src/lib.rs index 9353302b2f..663936085d 100644 --- a/common/bin-common/src/lib.rs +++ b/common/bin-common/src/lib.rs @@ -9,3 +9,6 @@ pub mod completions; #[cfg(feature = "output_format")] pub mod output_format; + +#[cfg(feature = "ip_check")] +pub mod ip_check; diff --git a/nym-node/Cargo.toml b/nym-node/Cargo.toml index 26eb3d6f12..1cd66c1de3 100644 --- a/nym-node/Cargo.toml +++ b/nym-node/Cargo.toml @@ -58,6 +58,7 @@ sysinfo = { workspace = true } nym-bin-common = { workspace = true, features = [ "basic_tracing", "output_format", + "ip_check" ] } nym-client-core-config-types = { workspace = true, features = [ "disk-persistence", diff --git a/nym-node/src/cli/commands/run/mod.rs b/nym-node/src/cli/commands/run/mod.rs index 450a88a761..d436bc441e 100644 --- a/nym-node/src/cli/commands/run/mod.rs +++ b/nym-node/src/cli/commands/run/mod.rs @@ -5,7 +5,7 @@ use crate::config::upgrade_helpers::try_load_current_config; use crate::error::NymNodeError; use crate::node::NymNode; use crate::node::bonding_information::BondingInformation; -use crate::node::mixnet::packet_forwarding::global::is_global_ip; +use nym_bin_common::ip_check::is_global_ip; use std::fs; use std::net::IpAddr; use tracing::{debug, info, trace, warn}; diff --git a/nym-node/src/cli/helpers.rs b/nym-node/src/cli/helpers.rs index 147a5a0129..85e0df1b7e 100644 --- a/nym-node/src/cli/helpers.rs +++ b/nym-node/src/cli/helpers.rs @@ -512,6 +512,26 @@ pub(crate) struct ExitGatewayArgs { env = NYMNODE_OPEN_PROXY_ARG, )] pub(crate) open_proxy: Option, + + /// Allow the network requester to forward traffic to non-globally-routable + /// addresses. Intended for local development, private-network deployments, + /// and testnet scenarios. + /// Not recommended on production exit gateway unless you know what you're doing. + #[clap( + long, + env = NYMNODE_NR_ALLOW_LOCAL_IPS_ARG, + )] + pub(crate) nr_allow_local_ips: Option, + + /// Allow the IP packet router to forward traffic to non-globally-routable + /// addresses. Intended for local development, private-network deployments, + /// and testnet scenarios. + /// Not recommended on production exit gateway unless you know what you're doing. + #[clap( + long, + env = NYMNODE_IPR_ALLOW_LOCAL_IPS_ARG, + )] + pub(crate) ipr_allow_local_ips: Option, } impl ExitGatewayArgs { @@ -533,6 +553,12 @@ impl ExitGatewayArgs { if let Some(open_proxy) = self.open_proxy { section.open_proxy = open_proxy } + if let Some(allow_local_ips) = self.nr_allow_local_ips { + section.network_requester.allow_local_ips = allow_local_ips + } + if let Some(allow_local_ips) = self.ipr_allow_local_ips { + section.ip_packet_router.allow_local_ips = allow_local_ips + } section } diff --git a/nym-node/src/config/helpers.rs b/nym-node/src/config/helpers.rs index 88f225fc93..8d43a10f3d 100644 --- a/nym-node/src/config/helpers.rs +++ b/nym-node/src/config/helpers.rs @@ -107,6 +107,7 @@ pub fn gateway_tasks_config(config: &Config) -> GatewayTasksConfig { }, network_requester: nym_network_requester::config::NetworkRequester { open_proxy: config.service_providers.open_proxy, + allow_local_ips: config.service_providers.network_requester.allow_local_ips, disable_poisson_rate: config .service_providers .network_requester @@ -150,6 +151,7 @@ pub fn gateway_tasks_config(config: &Config) -> GatewayTasksConfig { }, ip_packet_router: nym_ip_packet_router::config::IpPacketRouter { open_proxy: config.service_providers.open_proxy, + allow_local_ips: config.service_providers.ip_packet_router.allow_local_ips, disable_poisson_rate: config .service_providers .ip_packet_router diff --git a/nym-node/src/config/old_configs/old_config_v12.rs b/nym-node/src/config/old_configs/old_config_v12.rs index 9e71ab6be4..ce0b381e3f 100644 --- a/nym-node/src/config/old_configs/old_config_v12.rs +++ b/nym-node/src/config/old_configs/old_config_v12.rs @@ -938,6 +938,7 @@ pub async fn try_upgrade_config_v12>( open_proxy: old_cfg.service_providers.open_proxy, upstream_exit_policy_url: old_cfg.service_providers.upstream_exit_policy_url, network_requester: NetworkRequester { + allow_local_ips: false, debug: NetworkRequesterDebug { enabled: old_cfg.service_providers.network_requester.debug.enabled, disable_poisson_rate: old_cfg @@ -953,6 +954,7 @@ pub async fn try_upgrade_config_v12>( }, }, ip_packet_router: IpPacketRouter { + allow_local_ips: false, debug: IpPacketRouterDebug { enabled: old_cfg.service_providers.ip_packet_router.debug.enabled, disable_poisson_rate: old_cfg diff --git a/nym-node/src/config/service_providers.rs b/nym-node/src/config/service_providers.rs index b7d2f2cb77..863218b1f8 100644 --- a/nym-node/src/config/service_providers.rs +++ b/nym-node/src/config/service_providers.rs @@ -75,6 +75,11 @@ impl ServiceProvidersConfig { #[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)] pub struct NetworkRequester { + /// Allow the network requester to forward traffic to non-globally-routable addresses. + /// Intended for development & testing. + #[serde(default)] + pub allow_local_ips: bool, + #[serde(default)] pub debug: NetworkRequesterDebug, } @@ -83,6 +88,7 @@ pub struct NetworkRequester { impl Default for NetworkRequester { fn default() -> Self { NetworkRequester { + allow_local_ips: false, debug: Default::default(), } } @@ -117,6 +123,11 @@ impl Default for NetworkRequesterDebug { #[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] pub struct IpPacketRouter { + /// Allow the IP packet router to forward traffic to non-globally-routable addresses. + /// Intended for development & testing. + #[serde(default)] + pub allow_local_ips: bool, + #[serde(default)] pub debug: IpPacketRouterDebug, } @@ -125,6 +136,7 @@ pub struct IpPacketRouter { impl Default for IpPacketRouter { fn default() -> Self { IpPacketRouter { + allow_local_ips: false, debug: Default::default(), } } diff --git a/nym-node/src/env.rs b/nym-node/src/env.rs index 01f8a7113d..196c5dcc2f 100644 --- a/nym-node/src/env.rs +++ b/nym-node/src/env.rs @@ -70,6 +70,8 @@ pub mod vars { // exit gateway: pub const NYMNODE_UPSTREAM_EXIT_POLICY_ARG: &str = "NYMNODE_UPSTREAM_EXIT_POLICY"; pub const NYMNODE_OPEN_PROXY_ARG: &str = "NYMNODE_OPEN_PROXY"; + pub const NYMNODE_NR_ALLOW_LOCAL_IPS_ARG: &str = "NYMNODE_NR_ALLOW_LOCAL_IPS"; + pub const NYMNODE_IPR_ALLOW_LOCAL_IPS_ARG: &str = "NYMNODE_IPR_ALLOW_LOCAL_IPS"; // LP: pub const NYMNODE_LP_CONTROL_BIND_ADDRESS_ARG: &str = "NYMNODE_LP_CONTROL_BIND_ADDRESS"; diff --git a/nym-node/src/node/mixnet/packet_forwarding/mod.rs b/nym-node/src/node/mixnet/packet_forwarding/mod.rs index 6fa21d31c5..dc8d4af7d4 100644 --- a/nym-node/src/node/mixnet/packet_forwarding/mod.rs +++ b/nym-node/src/node/mixnet/packet_forwarding/mod.rs @@ -15,8 +15,6 @@ use std::io; use tokio::time::Instant; use tracing::{debug, error, trace, warn}; -pub(crate) mod global; - pub struct PacketForwarder { delay_queue: NonExhaustiveDelayQueue, mixnet_client: C, diff --git a/nym-node/src/node/routing_filter/network_filter.rs b/nym-node/src/node/routing_filter/network_filter.rs index eae67a66f7..274015f784 100644 --- a/nym-node/src/node/routing_filter/network_filter.rs +++ b/nym-node/src/node/routing_filter/network_filter.rs @@ -1,9 +1,9 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::node::mixnet::packet_forwarding::global::is_global_ip; use crate::node::routing_filter::RoutingFilter; use arc_swap::ArcSwap; +use nym_bin_common::ip_check::is_global_ip; use std::collections::HashSet; use std::net::IpAddr; use std::sync::Arc; diff --git a/service-providers/ip-packet-router/Cargo.toml b/service-providers/ip-packet-router/Cargo.toml index fdb12ae514..956205f8b5 100644 --- a/service-providers/ip-packet-router/Cargo.toml +++ b/service-providers/ip-packet-router/Cargo.toml @@ -19,7 +19,7 @@ etherparse = { workspace = true } futures = { workspace = true } log = { workspace = true } -nym-bin-common = { workspace = true, features = ["clap", "basic_tracing"] } +nym-bin-common = { workspace = true, features = ["clap", "basic_tracing", "ip_check"] } nym-client-core = { workspace = true } nym-config = { workspace = true } nym-crypto = { workspace = true } diff --git a/service-providers/ip-packet-router/src/config/mod.rs b/service-providers/ip-packet-router/src/config/mod.rs index 3b39fa9706..2df5152045 100644 --- a/service-providers/ip-packet-router/src/config/mod.rs +++ b/service-providers/ip-packet-router/src/config/mod.rs @@ -192,6 +192,11 @@ pub struct IpPacketRouter { /// and thus would attempt to resolve **ANY** request it receives. pub open_proxy: bool, + /// Allow the IP packet router to forward traffic to non-globally-routable addresses. + /// Intended for development & testing. + #[serde(default)] + pub allow_local_ips: bool, + /// Disable Poisson sending rate. pub disable_poisson_rate: bool, @@ -204,6 +209,7 @@ impl Default for IpPacketRouter { fn default() -> Self { IpPacketRouter { open_proxy: false, + allow_local_ips: false, disable_poisson_rate: true, #[allow(clippy::expect_used)] upstream_exit_policy_url: Some( diff --git a/service-providers/ip-packet-router/src/config/old_config_v1.rs b/service-providers/ip-packet-router/src/config/old_config_v1.rs index 1352812a24..a2c5c9c2ff 100644 --- a/service-providers/ip-packet-router/src/config/old_config_v1.rs +++ b/service-providers/ip-packet-router/src/config/old_config_v1.rs @@ -95,6 +95,7 @@ impl From for IpPacketRouter { fn from(value: IpPacketRouterV1) -> Self { IpPacketRouter { open_proxy: false, + allow_local_ips: false, disable_poisson_rate: value.disable_poisson_rate, upstream_exit_policy_url: value.upstream_exit_policy_url, } diff --git a/service-providers/ip-packet-router/src/request_filter/exit_policy/mod.rs b/service-providers/ip-packet-router/src/request_filter/exit_policy/mod.rs index 133df560c7..544768cdd8 100644 --- a/service-providers/ip-packet-router/src/request_filter/exit_policy/mod.rs +++ b/service-providers/ip-packet-router/src/request_filter/exit_policy/mod.rs @@ -4,6 +4,8 @@ use std::net::SocketAddr; use crate::error::IpPacketRouterError; +use log::warn; +use nym_bin_common::ip_check::is_global_ip; use nym_exit_policy::ExitPolicy; use nym_exit_policy::client::get_exit_policy; use reqwest::IntoUrl; @@ -13,10 +15,14 @@ pub struct ExitPolicyRequestFilter { #[allow(unused)] upstream: Option, policy: ExitPolicy, + allow_local_ips: bool, } impl ExitPolicyRequestFilter { - pub(crate) async fn new_upstream(url: impl IntoUrl) -> Result { + pub(crate) async fn new_upstream( + url: impl IntoUrl, + allow_local_ips: bool, + ) -> Result { let url = url .into_url() .map_err(|source| IpPacketRouterError::MalformedExitPolicyUpstreamUrl { source })?; @@ -24,21 +30,24 @@ impl ExitPolicyRequestFilter { Ok(ExitPolicyRequestFilter { upstream: Some(url.clone()), policy: get_exit_policy(url).await?, + allow_local_ips, }) } #[allow(unused)] - pub(crate) fn new(policy: ExitPolicy) -> Self { + pub(crate) fn new(policy: ExitPolicy, allow_local_ips: bool) -> Self { ExitPolicyRequestFilter { upstream: None, policy, + allow_local_ips, } } - pub fn new_from_policy(policy: ExitPolicy) -> Self { + pub fn new_from_policy(policy: ExitPolicy, allow_local_ips: bool) -> Self { ExitPolicyRequestFilter { upstream: None, policy, + allow_local_ips, } } @@ -53,6 +62,13 @@ impl ExitPolicyRequestFilter { } pub(crate) async fn check(&self, addr: &SocketAddr) -> Result { + // private ranges are disallowed regardless of policy: end user has + // no business with internal/private IP ranges of IPR + if !self.allow_local_ips && !is_global_ip(&addr.ip()) { + warn!("Rejecting non-global address {addr}"); + return Ok(false); + } + self.policy .allows_sockaddr(addr) .ok_or(IpPacketRouterError::AddressNotCoveredByExitPolicy { addr: *addr }) diff --git a/service-providers/ip-packet-router/src/request_filter/mod.rs b/service-providers/ip-packet-router/src/request_filter/mod.rs index 2c724af9eb..4d928e366a 100644 --- a/service-providers/ip-packet-router/src/request_filter/mod.rs +++ b/service-providers/ip-packet-router/src/request_filter/mod.rs @@ -43,15 +43,23 @@ impl RequestFilter { } async fn new_exit_policy_filter(config: &Config) -> Result { + let allow_local_ips = config.ip_packet_router.allow_local_ips; + if allow_local_ips { + warn!( + "Requests to non-global destinations are allowed by the policy guard. \ + This is intended for local development and NOT recommended in production \ + unless you know what you're doing." + ); + } let policy_filter = if config.ip_packet_router.open_proxy { - ExitPolicyRequestFilter::new_from_policy(ExitPolicy::new_open()) + ExitPolicyRequestFilter::new_from_policy(ExitPolicy::new_open(), allow_local_ips) } else { let upstream_url = config .ip_packet_router .upstream_exit_policy_url .as_ref() .ok_or(IpPacketRouterError::NoUpstreamExitPolicy)?; - ExitPolicyRequestFilter::new_upstream(upstream_url.clone()).await? + ExitPolicyRequestFilter::new_upstream(upstream_url.clone(), allow_local_ips).await? }; Ok(RequestFilter { diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index fcb1d3a0d6..426c6a6b22 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -44,7 +44,7 @@ zeroize = { workspace = true } # internal nym-async-file-watcher = { workspace = true } -nym-bin-common = { workspace = true, features = ["output_format", "clap", "basic_tracing"] } +nym-bin-common = { workspace = true, features = ["output_format", "clap", "basic_tracing", "ip_check"] } nym-client-core = { workspace = true, features = ["cli", "fs-gateways-storage", "fs-surb-storage"] } nym-client-websocket-requests = { workspace = true } nym-config = { workspace = true } diff --git a/service-providers/network-requester/src/config/mod.rs b/service-providers/network-requester/src/config/mod.rs index 635e7f16b0..3d0e7f2fd1 100644 --- a/service-providers/network-requester/src/config/mod.rs +++ b/service-providers/network-requester/src/config/mod.rs @@ -210,6 +210,11 @@ pub struct NetworkRequester { /// and thus would attempt to resolve **ANY** request it receives. pub open_proxy: bool, + /// Allow the network requester to forward traffic to non-globally-routable addresses. + /// Intended for development & testing. + #[serde(default)] + pub allow_local_ips: bool, + /// Disable Poisson sending rate. /// This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true, pub disable_poisson_rate: bool, @@ -223,6 +228,7 @@ impl Default for NetworkRequester { fn default() -> Self { NetworkRequester { open_proxy: false, + allow_local_ips: false, disable_poisson_rate: true, upstream_exit_policy_url: Some( mainnet::EXIT_POLICY_URL diff --git a/service-providers/network-requester/src/config/old/v5.rs b/service-providers/network-requester/src/config/old/v5.rs index 6e6d5de055..6fe5042007 100644 --- a/service-providers/network-requester/src/config/old/v5.rs +++ b/service-providers/network-requester/src/config/old/v5.rs @@ -113,6 +113,7 @@ impl From for NetworkRequester { fn from(value: NetworkRequesterV5) -> Self { NetworkRequester { open_proxy: value.open_proxy, + allow_local_ips: false, disable_poisson_rate: value.disable_poisson_rate, upstream_exit_policy_url: value.upstream_exit_policy_url, } diff --git a/service-providers/network-requester/src/config/template.rs b/service-providers/network-requester/src/config/template.rs index ac1f52f37b..a9886c16d3 100644 --- a/service-providers/network-requester/src/config/template.rs +++ b/service-providers/network-requester/src/config/template.rs @@ -81,6 +81,11 @@ nr_description = '{{ storage_paths.nr_description }}' # and thus would attempt to resolve **ANY** request it receives. open_proxy = {{ network_requester.open_proxy }} +# Allow forwarding traffic to non-globally-routable addresses. +# Intended for local development for security reasons. +# Only enable if you know what you're doing. +allow_local_ips = {{ network_requester.allow_local_ips }} + # Disable Poisson sending rate # This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true, disable_poisson_rate = {{ network_requester.disable_poisson_rate }} diff --git a/service-providers/network-requester/src/request_filter/exit_policy/mod.rs b/service-providers/network-requester/src/request_filter/exit_policy/mod.rs index 140091625e..61e15ca438 100644 --- a/service-providers/network-requester/src/request_filter/exit_policy/mod.rs +++ b/service-providers/network-requester/src/request_filter/exit_policy/mod.rs @@ -3,7 +3,8 @@ use crate::config::Config; use crate::error::NetworkRequesterError; -use log::trace; +use log::{trace, warn}; +use nym_bin_common::ip_check::is_global_ip; use nym_exit_policy::ExitPolicy; use nym_exit_policy::client::get_exit_policy; use nym_socks5_requests::RemoteAddress; @@ -14,16 +15,20 @@ use url::Url; pub struct ExitPolicyRequestFilter { upstream: Option, policy: ExitPolicy, + allow_local_ips: bool, } impl From for ExitPolicyRequestFilter { fn from(value: ExitPolicy) -> Self { - ExitPolicyRequestFilter::new_from_policy(value) + ExitPolicyRequestFilter::new_from_policy(value, false) } } impl ExitPolicyRequestFilter { - pub(crate) async fn new_upstream(url: impl IntoUrl) -> Result { + pub(crate) async fn new_upstream( + url: impl IntoUrl, + allow_local_ips: bool, + ) -> Result { let url = url .into_url() .map_err(|source| NetworkRequesterError::MalformedExitPolicyUpstreamUrl { source })?; @@ -31,27 +36,37 @@ impl ExitPolicyRequestFilter { Ok(ExitPolicyRequestFilter { upstream: Some(url.clone()), policy: get_exit_policy(url).await?, + allow_local_ips, }) } pub(crate) async fn new(config: &Config) -> Result { + let allow_local_ips = config.network_requester.allow_local_ips; + if allow_local_ips { + warn!( + "Requests to non-global destinations are allowed by the policy guard. \ + This is intended for local development and NOT recommended in production \ + unless you know what you're doing." + ); + } let policy_filter = if config.network_requester.open_proxy { - ExitPolicyRequestFilter::new_from_policy(ExitPolicy::new_open()) + ExitPolicyRequestFilter::new_from_policy(ExitPolicy::new_open(), allow_local_ips) } else { let upstream_url = config .network_requester .upstream_exit_policy_url .as_ref() .ok_or(NetworkRequesterError::NoUpstreamExitPolicy)?; - ExitPolicyRequestFilter::new_upstream(upstream_url.clone()).await? + ExitPolicyRequestFilter::new_upstream(upstream_url.clone(), allow_local_ips).await? }; Ok(policy_filter) } - pub fn new_from_policy(policy: ExitPolicy) -> Self { + pub fn new_from_policy(policy: ExitPolicy, allow_local_ips: bool) -> Self { ExitPolicyRequestFilter { upstream: None, policy, + allow_local_ips, } } @@ -89,6 +104,13 @@ impl ExitPolicyRequestFilter { // if the remote decided to give us an address that can resolve to multiple socket addresses, // they'd better make sure all of them are allowed by the exit policy. for addr in addrs { + // private ranges are disallowed regardless of policy: end user has + // no business with internal/private IP ranges of network requester + if !self.allow_local_ips && !is_global_ip(&addr.ip()) { + warn!("Rejecting non-global address {addr} for '{remote}'"); + return Ok(false); + } + // exit policy determines which PUBLIC facing addresses are allowed if !self .policy .allows_sockaddr(&addr) From cd476ef6a23e932a9a11f3a5db256d3edc435653 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Wed, 15 Apr 2026 17:30:57 +0100 Subject: [PATCH 03/37] Update libcrux crates to use versions published on crates.io instead of git import --- Cargo.lock | 82 ++++++++++++++++++++++++++++++++++-------------------- Cargo.toml | 16 +++++------ 2 files changed, 60 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd00183414..53728ac268 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1691,7 +1691,8 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-models" version = "0.0.5" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "657f625ff361906f779745d08375ae3cc9fef87a35fba5f22874cf773010daf4" dependencies = [ "hax-lib", "pastey 0.2.1", @@ -4671,7 +4672,8 @@ checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libcrux-aesgcm" version = "0.0.7" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99f2a019dab4097585a7d4f5b9deebe46cd1e628b16a5bc4cb0ce35e1da334e6" dependencies = [ "libcrux-intrinsics", "libcrux-platform", @@ -4681,8 +4683,9 @@ dependencies = [ [[package]] name = "libcrux-chacha20poly1305" -version = "0.0.6" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc08d044676af21343b32b988411fa98dbb5cf65a03c9df478ced221bbdfdb1b" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", @@ -4694,7 +4697,8 @@ dependencies = [ [[package]] name = "libcrux-curve25519" version = "0.0.6" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1e5fd8476a6ed609d24ef42aee5ab6f99f7c65d054f92412da9f499e423299" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", @@ -4705,7 +4709,8 @@ dependencies = [ [[package]] name = "libcrux-ecdh" version = "0.0.6" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b65f73ce79337c762eb38bbac91e4c9b9e60cf318e8501b812750c640814d45e" dependencies = [ "libcrux-curve25519", "libcrux-p256", @@ -4715,8 +4720,9 @@ dependencies = [ [[package]] name = "libcrux-ed25519" -version = "0.0.6" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835919315b7042fe9e03b6458efe0db94bf2aa7b873934dbee5b5463a8124b43" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", @@ -4728,7 +4734,8 @@ dependencies = [ [[package]] name = "libcrux-hacl-rs" version = "0.0.4" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2637dc87d158e1f1b550fd9b226443e84153fded4de69028d897b534d16d22e6" dependencies = [ "libcrux-macros", ] @@ -4736,7 +4743,8 @@ dependencies = [ [[package]] name = "libcrux-hkdf" version = "0.0.6" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1a89ca0c89be3a268a921e47105fb7873badf7267f5e3ebf4ea46baedd73ef" dependencies = [ "libcrux-hacl-rs", "libcrux-hmac", @@ -4746,7 +4754,8 @@ dependencies = [ [[package]] name = "libcrux-hmac" version = "0.0.6" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7a242707d65960770bd7e14e4f18a92bdf0b967777dd404887db8d087a643b" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", @@ -4756,7 +4765,8 @@ dependencies = [ [[package]] name = "libcrux-intrinsics" version = "0.0.6" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1b5db005ff8001e026b73a6842ee81bbef8ec5ff0e1915a67ae65fd2a9fafa5" dependencies = [ "core-models", "hax-lib", @@ -4764,8 +4774,9 @@ dependencies = [ [[package]] name = "libcrux-kem" -version = "0.0.6" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12631592f491d22fd1a176d32b2c6edfb673998fd3987e9d95f8fa79ad2a737b" dependencies = [ "libcrux-curve25519", "libcrux-ecdh", @@ -4780,7 +4791,8 @@ dependencies = [ [[package]] name = "libcrux-macros" version = "0.0.3" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffd6aa2dcd5be681662001b81d493f1569c6d49a32361f470b0c955465cd0338" dependencies = [ "quote", "syn 2.0.106", @@ -4788,8 +4800,9 @@ dependencies = [ [[package]] name = "libcrux-ml-dsa" -version = "0.0.7" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a72929ed421cc3bf16a946b3e7d2a58d215b0b5c2a12be26b53629f081bf49b2" dependencies = [ "core-models", "hax-lib", @@ -4802,8 +4815,9 @@ dependencies = [ [[package]] name = "libcrux-ml-kem" -version = "0.0.7" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a14ab3e477de9df6ee1273a114018ff62c4996ca9220070c4e5cb1743f94a67d" dependencies = [ "hax-lib", "libcrux-intrinsics", @@ -4818,7 +4832,8 @@ dependencies = [ [[package]] name = "libcrux-p256" version = "0.0.6" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4778ba25cb08bb8a96bd100e19ed9aecf78337198fd176036e21042b2dd99bc" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", @@ -4830,15 +4845,17 @@ dependencies = [ [[package]] name = "libcrux-platform" version = "0.0.3" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9e21d7ed31a92ac539bd69a8c970b183ee883872d2d19ce27036e24cb8ecc4" dependencies = [ "libc", ] [[package]] name = "libcrux-poly1305" -version = "0.0.4" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02491808ee5b9db8cb65fad64ae0be812db64beef179d945c00c7787dc7dfcf9" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", @@ -4846,8 +4863,9 @@ dependencies = [ [[package]] name = "libcrux-psq" -version = "0.0.7" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "779ade7aa5e1b4b400c716b313cbf69070988dd005f92e961c2da4c3c42fbea4" dependencies = [ "classic-mceliece-rust", "libcrux-aesgcm", @@ -4869,7 +4887,8 @@ dependencies = [ [[package]] name = "libcrux-secrets" version = "0.0.5" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce650f3041b44ba40d4263852347d007cd2cd9d1cc856a6f6c8b2e10c3fd40b" dependencies = [ "hax-lib", ] @@ -4877,7 +4896,8 @@ dependencies = [ [[package]] name = "libcrux-sha2" version = "0.0.6" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d253473f259fc74a280c43f29c464f7e374abdf28b4942234dc707f529d4b7" dependencies = [ "libcrux-hacl-rs", "libcrux-macros", @@ -4886,8 +4906,9 @@ dependencies = [ [[package]] name = "libcrux-sha3" -version = "0.0.7" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1ae0b7d0e1cc4793a609fd0ff2ca3b3a3fabae523770c619a3d4bc86417b0d7" dependencies = [ "hax-lib", "libcrux-intrinsics", @@ -4898,7 +4919,8 @@ dependencies = [ [[package]] name = "libcrux-traits" version = "0.0.6" -source = "git+https://github.com/cryspen/libcrux?rev=b17f8687b67cdcfc10b55aeecc998bbbca28f775#b17f8687b67cdcfc10b55aeecc998bbbca28f775" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e4fa89f3f5e34b47f928b22b1b78395a0d4ec23b1f583db635f128159d65f" dependencies = [ "libcrux-secrets", "rand 0.9.2", diff --git a/Cargo.toml b/Cargo.toml index 66ba465d80..1d1db9f1da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -404,14 +404,14 @@ prometheus = { version = "0.14.0" } # libcrux -libcrux-kem = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" } -libcrux-ecdh = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" } -libcrux-curve25519 = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" } -libcrux-chacha20poly1305 = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" } -libcrux-psq = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" } -libcrux-ml-kem = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" } -libcrux-sha3 = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" } -libcrux-traits = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" } +libcrux-kem = "0.0.7" +libcrux-ecdh = "0.0.6" +libcrux-curve25519 = "0.0.6" +libcrux-chacha20poly1305 = "0.0.7" +libcrux-psq = "0.0.8" +libcrux-ml-kem = "0.0.8" +libcrux-sha3 = "0.0.8" +libcrux-traits = "0.0.8" # Workspace dep definitions required by crates.io publication - we need a workspace version since `cargo workspaces` doesn't work with path imports from crate manifests nym-api-requests = { version = "1.20.4", path = "nym-api/nym-api-requests" } From 0de14718cb92f09706911517b1374a127b1bfd9e Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Tue, 24 Feb 2026 07:49:03 +0100 Subject: [PATCH 04/37] attempt at fix --- .../workflows/ci-crates-publish-dry-run.yml | 51 ++++++++++++++++--- .../workflows/ci-crates-publish-resume.yml | 2 + .github/workflows/ci-crates-publish.yml | 2 + .github/workflows/ci-crates-version-bump.yml | 2 + common/nym-kkt-ciphersuite/Cargo.toml | 1 + 5 files changed, 52 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-crates-publish-dry-run.yml b/.github/workflows/ci-crates-publish-dry-run.yml index f57efbe87e..3d023ef245 100644 --- a/.github/workflows/ci-crates-publish-dry-run.yml +++ b/.github/workflows/ci-crates-publish-dry-run.yml @@ -15,6 +15,9 @@ env: jobs: publish-dry-run: runs-on: arc-linux-latest + timeout-minutes: 35 + env: + RUSTUP_PERMIT_COPY_RENAME: 1 steps: - name: Checkout repo uses: actions/checkout@v6 @@ -59,20 +62,56 @@ jobs: - name: Bump versions (local only) run: | cargo workspaces version custom ${{ inputs.version }} \ - --allow-branch ${{ github.ref_name }} \ --no-git-commit \ + --yes # Dry run may show cascading dependency errors because packages aren't # actually uploaded - these are expected and ignored. We check for real # errors like packaging failures, missing metadata, or invalid Cargo.toml. - name: Publish (dry run) run: | - output=$(cargo workspaces publish --dry-run --allow-dirty 2>&1) || true - echo "$output" + set +e + publish_status=1 + max_attempts=2 + attempt=1 + rm -f /tmp/publish-dry-run.log - # Check for real errors (not cascading dependency errors) - # Cascading errors mention "crates.io index", real errors mention "Cargo.toml" - echo "$output" | grep -i "Cargo.toml" && exit 1 || true + while [ "$attempt" -le "$max_attempts" ]; do + echo "Dry-run publish attempt ${attempt}/${max_attempts}" + cargo workspaces publish --dry-run --allow-dirty 2>&1 | tee /tmp/publish-dry-run.log + publish_status=${PIPESTATUS[0]} + + if [ "$publish_status" -eq 0 ]; then + break + fi + + # Retry once for interruption/runner issues. + if [ "$attempt" -lt "$max_attempts" ] && \ + { [ "$publish_status" -eq 130 ] || [ "$publish_status" -eq 137 ]; }; then + echo "Publish dry-run interrupted (exit ${publish_status}), retrying in 10s..." + sleep 10 + attempt=$((attempt + 1)) + continue + fi + + break + done + set -e + + if grep -Eiq \ + "failed to verify manifest|failed to parse manifest|invalid Cargo.toml|error: package .* has no (description|license|repository)" \ + /tmp/publish-dry-run.log; then + echo "Detected real packaging/manifest errors" + exit 1 + fi + + # In dry-run mode, non-zero publish status is expected due to + # dependency-cascade failures against crates.io index. + if [ "$publish_status" -ne 0 ]; then + echo "Dry-run publish returned non-zero (${publish_status}) but no real manifest blockers were detected." + fi + + echo "Only expected dry-run dependency cascade errors detected (if any)." # Show the list of packages published - name: Show package versions diff --git a/.github/workflows/ci-crates-publish-resume.yml b/.github/workflows/ci-crates-publish-resume.yml index 77f448a2b8..8fcf5ef7b4 100644 --- a/.github/workflows/ci-crates-publish-resume.yml +++ b/.github/workflows/ci-crates-publish-resume.yml @@ -17,6 +17,8 @@ on: jobs: publish: runs-on: arc-linux-latest + env: + RUSTUP_PERMIT_COPY_RENAME: 1 steps: - name: Checkout repo uses: actions/checkout@v6 diff --git a/.github/workflows/ci-crates-publish.yml b/.github/workflows/ci-crates-publish.yml index 3c7250d241..94290c8a2d 100644 --- a/.github/workflows/ci-crates-publish.yml +++ b/.github/workflows/ci-crates-publish.yml @@ -17,6 +17,8 @@ on: jobs: publish: runs-on: arc-linux-latest + env: + RUSTUP_PERMIT_COPY_RENAME: 1 steps: - name: Checkout repo uses: actions/checkout@v6 diff --git a/.github/workflows/ci-crates-version-bump.yml b/.github/workflows/ci-crates-version-bump.yml index 790e2a062a..eebc0d64ac 100644 --- a/.github/workflows/ci-crates-version-bump.yml +++ b/.github/workflows/ci-crates-version-bump.yml @@ -15,6 +15,8 @@ env: jobs: version-bump: runs-on: arc-linux-latest + env: + RUSTUP_PERMIT_COPY_RENAME: 1 permissions: contents: write steps: diff --git a/common/nym-kkt-ciphersuite/Cargo.toml b/common/nym-kkt-ciphersuite/Cargo.toml index ef1b8e7738..65722caab8 100644 --- a/common/nym-kkt-ciphersuite/Cargo.toml +++ b/common/nym-kkt-ciphersuite/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "nym-kkt-ciphersuite" +description = "Nym KKT ciphersuite" authors.workspace = true repository.workspace = true homepage.workspace = true From a399a75b035332c74bd1a6485be633e54d821422 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Fri, 27 Feb 2026 17:24:44 +0100 Subject: [PATCH 05/37] test.. --- .../workflows/ci-crates-publish-dry-run.yml | 135 ++++++++++++++++++ common/nym-kkt-ciphersuite/Cargo.toml | 1 - 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-crates-publish-dry-run.yml b/.github/workflows/ci-crates-publish-dry-run.yml index 3d023ef245..2bff35312f 100644 --- a/.github/workflows/ci-crates-publish-dry-run.yml +++ b/.github/workflows/ci-crates-publish-dry-run.yml @@ -65,6 +65,141 @@ jobs: --no-git-commit \ --yes + - name: Preflight publish checks + run: | + python3 - <<'PY' + import tomllib + import pathlib + import sys + + root = pathlib.Path(".") + ws = tomllib.loads((root / "Cargo.toml").read_text()) + members = ws["workspace"]["members"] + errors = [] + workspace_members = {} + + for member in members: + manifest = root / member / "Cargo.toml" + if not manifest.exists(): + continue + + data = tomllib.loads(manifest.read_text()) + package = data.get("package") + if not package: + continue + + publish = package.get("publish", True) + publishable = publish is not False + workspace_members[package.get("name", member)] = { + "member": member, + "manifest": manifest, + "publishable": publishable, + "data": data, + } + + def dependency_sections(crate_data): + for section in ("dependencies", "dev-dependencies", "build-dependencies"): + deps = crate_data.get(section, {}) + if isinstance(deps, dict): + yield section, deps + + target = crate_data.get("target", {}) + if isinstance(target, dict): + for target_name, target_data in target.items(): + if not isinstance(target_data, dict): + continue + for section in ("dependencies", "dev-dependencies", "build-dependencies"): + deps = target_data.get(section, {}) + if isinstance(deps, dict): + yield f"target.{target_name}.{section}", deps + + def resolve_workspace_dep_name(dep_name, spec, manifest): + if not isinstance(spec, dict): + return None + + if spec.get("workspace") is True: + return dep_name + + candidate = spec.get("package", dep_name) + if candidate in workspace_members: + return candidate + + dep_path = spec.get("path") + if not dep_path: + return None + + dep_manifest = (manifest.parent / dep_path / "Cargo.toml").resolve() + if not dep_manifest.exists(): + return None + + dep_data = tomllib.loads(dep_manifest.read_text()) + dep_package = dep_data.get("package", {}) + resolved_name = dep_package.get("name") + if resolved_name in workspace_members: + return resolved_name + return None + + for member in members: + manifest = root / member / "Cargo.toml" + if not manifest.exists(): + continue + + data = tomllib.loads(manifest.read_text()) + package = data.get("package") + if not package: + continue + if package.get("publish", True) is False: + continue + + crate_name = package.get("name", member) + + for field in ("description", "license", "repository"): + value = package.get(field) + has_value = ( + (isinstance(value, str) and bool(value.strip())) + or (isinstance(value, dict) and value.get("workspace") is True) + ) + if not has_value: + errors.append( + f"{member}: package '{crate_name}' missing required field '{field}'" + ) + + for section, dependencies in dependency_sections(data): + for dep_name, spec in dependencies.items(): + if isinstance(spec, dict) and "path" in spec: + if spec.get("workspace") is True: + continue + if "version" not in spec: + errors.append( + f"{member}: {section} '{dep_name}' uses path dependency without version ({spec['path']})" + ) + + resolved_dep = resolve_workspace_dep_name(dep_name, spec, manifest) + if ( + resolved_dep + and resolved_dep in workspace_members + and not workspace_members[resolved_dep]["publishable"] + ): + errors.append( + f"{member}: package '{crate_name}' ({section}) depends on non-publishable workspace crate '{resolved_dep}'" + ) + + workspace_deps = ws.get("workspace", {}).get("dependencies", {}) + for dep_name, spec in workspace_deps.items(): + if isinstance(spec, dict) and "path" in spec and "version" not in spec: + errors.append( + f"workspace.dependencies: '{dep_name}' has path but no version" + ) + + if errors: + print("Preflight checks failed:") + for err in errors: + print(f"- {err}") + sys.exit(1) + + print("Preflight checks passed.") + PY + # Dry run may show cascading dependency errors because packages aren't # actually uploaded - these are expected and ignored. We check for real # errors like packaging failures, missing metadata, or invalid Cargo.toml. diff --git a/common/nym-kkt-ciphersuite/Cargo.toml b/common/nym-kkt-ciphersuite/Cargo.toml index 65722caab8..28e4aecae8 100644 --- a/common/nym-kkt-ciphersuite/Cargo.toml +++ b/common/nym-kkt-ciphersuite/Cargo.toml @@ -10,7 +10,6 @@ license.workspace = true rust-version.workspace = true readme.workspace = true version.workspace = true -publish = false [dependencies] thiserror = { workspace = true } From 3531901a173c4ed9e71adc1a9ca97077575d48c8 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Fri, 27 Feb 2026 18:56:27 +0100 Subject: [PATCH 06/37] ? --- .../workflows/ci-crates-publish-dry-run.yml | 133 +----------------- .../workflows/resume-publish-crates-io.yml | 4 + common/nym-kkt-ciphersuite/Cargo.toml | 1 + 3 files changed, 6 insertions(+), 132 deletions(-) diff --git a/.github/workflows/ci-crates-publish-dry-run.yml b/.github/workflows/ci-crates-publish-dry-run.yml index 2bff35312f..fa2714e7bb 100644 --- a/.github/workflows/ci-crates-publish-dry-run.yml +++ b/.github/workflows/ci-crates-publish-dry-run.yml @@ -67,138 +67,7 @@ jobs: - name: Preflight publish checks run: | - python3 - <<'PY' - import tomllib - import pathlib - import sys - - root = pathlib.Path(".") - ws = tomllib.loads((root / "Cargo.toml").read_text()) - members = ws["workspace"]["members"] - errors = [] - workspace_members = {} - - for member in members: - manifest = root / member / "Cargo.toml" - if not manifest.exists(): - continue - - data = tomllib.loads(manifest.read_text()) - package = data.get("package") - if not package: - continue - - publish = package.get("publish", True) - publishable = publish is not False - workspace_members[package.get("name", member)] = { - "member": member, - "manifest": manifest, - "publishable": publishable, - "data": data, - } - - def dependency_sections(crate_data): - for section in ("dependencies", "dev-dependencies", "build-dependencies"): - deps = crate_data.get(section, {}) - if isinstance(deps, dict): - yield section, deps - - target = crate_data.get("target", {}) - if isinstance(target, dict): - for target_name, target_data in target.items(): - if not isinstance(target_data, dict): - continue - for section in ("dependencies", "dev-dependencies", "build-dependencies"): - deps = target_data.get(section, {}) - if isinstance(deps, dict): - yield f"target.{target_name}.{section}", deps - - def resolve_workspace_dep_name(dep_name, spec, manifest): - if not isinstance(spec, dict): - return None - - if spec.get("workspace") is True: - return dep_name - - candidate = spec.get("package", dep_name) - if candidate in workspace_members: - return candidate - - dep_path = spec.get("path") - if not dep_path: - return None - - dep_manifest = (manifest.parent / dep_path / "Cargo.toml").resolve() - if not dep_manifest.exists(): - return None - - dep_data = tomllib.loads(dep_manifest.read_text()) - dep_package = dep_data.get("package", {}) - resolved_name = dep_package.get("name") - if resolved_name in workspace_members: - return resolved_name - return None - - for member in members: - manifest = root / member / "Cargo.toml" - if not manifest.exists(): - continue - - data = tomllib.loads(manifest.read_text()) - package = data.get("package") - if not package: - continue - if package.get("publish", True) is False: - continue - - crate_name = package.get("name", member) - - for field in ("description", "license", "repository"): - value = package.get(field) - has_value = ( - (isinstance(value, str) and bool(value.strip())) - or (isinstance(value, dict) and value.get("workspace") is True) - ) - if not has_value: - errors.append( - f"{member}: package '{crate_name}' missing required field '{field}'" - ) - - for section, dependencies in dependency_sections(data): - for dep_name, spec in dependencies.items(): - if isinstance(spec, dict) and "path" in spec: - if spec.get("workspace") is True: - continue - if "version" not in spec: - errors.append( - f"{member}: {section} '{dep_name}' uses path dependency without version ({spec['path']})" - ) - - resolved_dep = resolve_workspace_dep_name(dep_name, spec, manifest) - if ( - resolved_dep - and resolved_dep in workspace_members - and not workspace_members[resolved_dep]["publishable"] - ): - errors.append( - f"{member}: package '{crate_name}' ({section}) depends on non-publishable workspace crate '{resolved_dep}'" - ) - - workspace_deps = ws.get("workspace", {}).get("dependencies", {}) - for dep_name, spec in workspace_deps.items(): - if isinstance(spec, dict) and "path" in spec and "version" not in spec: - errors.append( - f"workspace.dependencies: '{dep_name}' has path but no version" - ) - - if errors: - print("Preflight checks failed:") - for err in errors: - print(f"- {err}") - sys.exit(1) - - print("Preflight checks passed.") - PY + python3 tools/internal/check_publish_preflight.py # Dry run may show cascading dependency errors because packages aren't # actually uploaded - these are expected and ignored. We check for real diff --git a/.github/workflows/resume-publish-crates-io.yml b/.github/workflows/resume-publish-crates-io.yml index ef322790d7..db95e8e0fd 100644 --- a/.github/workflows/resume-publish-crates-io.yml +++ b/.github/workflows/resume-publish-crates-io.yml @@ -25,6 +25,10 @@ jobs: - name: Install cargo-workspaces run: cargo install cargo-workspaces + - name: Preflight publish checks + run: | + python3 tools/internal/check_publish_preflight.py + - name: Publish remaining crates env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/common/nym-kkt-ciphersuite/Cargo.toml b/common/nym-kkt-ciphersuite/Cargo.toml index 28e4aecae8..65722caab8 100644 --- a/common/nym-kkt-ciphersuite/Cargo.toml +++ b/common/nym-kkt-ciphersuite/Cargo.toml @@ -10,6 +10,7 @@ license.workspace = true rust-version.workspace = true readme.workspace = true version.workspace = true +publish = false [dependencies] thiserror = { workspace = true } From e66a069d5f22fa30175acd5008e94414bb70b028 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Fri, 27 Feb 2026 19:01:00 +0100 Subject: [PATCH 07/37] add file --- tools/internal/check_publish_preflight.py | 190 ++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 tools/internal/check_publish_preflight.py diff --git a/tools/internal/check_publish_preflight.py b/tools/internal/check_publish_preflight.py new file mode 100644 index 0000000000..894a398a3d --- /dev/null +++ b/tools/internal/check_publish_preflight.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python3 + +import json +import pathlib +import subprocess +import sys +from collections import defaultdict + + +def dependency_section(dep): + kind = dep.get("kind") or "normal" + section = { + "normal": "dependencies", + "dev": "dev-dependencies", + "build": "build-dependencies", + }.get(kind, f"{kind}-dependencies") + target = dep.get("target") + if target: + return f"target.{target}.{section}" + return section + + +def manifest_member(root, manifest_path): + manifest_parent = pathlib.Path(manifest_path).resolve().parent + try: + return str(manifest_parent.relative_to(root)) + except ValueError: + return str(manifest_parent) + + +def publish_status(pkg): + publish = pkg.get("publish") + if publish is None: + return True, "publishable to crates.io" + + if isinstance(publish, list): + if not publish: + return False, "publish disabled (`publish = false`)" + if "crates-io" in publish: + return True, "publishable to crates.io" + registries = ", ".join(publish) + return False, f"publish restricted to non-crates.io registries ({registries})" + + return False, f"unrecognized `publish` setting: {publish!r}" + + +def main(): + root = pathlib.Path(".").resolve() + metadata = json.loads( + subprocess.check_output( + ["cargo", "metadata", "--no-deps", "--format-version", "1"], + text=True, + ) + ) + packages_by_id = {pkg["id"]: pkg for pkg in metadata["packages"]} + workspace_ids = set(metadata["workspace_members"]) + workspace_packages = [ + packages_by_id[pkg_id] for pkg_id in workspace_ids if pkg_id in packages_by_id + ] + workspace_by_name = {pkg["name"]: pkg for pkg in workspace_packages} + workspace_dir_to_name = { + str(pathlib.Path(pkg["manifest_path"]).resolve().parent): pkg["name"] + for pkg in workspace_packages + } + + package_info = {} + for pkg in workspace_packages: + name = pkg["name"] + member = manifest_member(root, pkg["manifest_path"]) + explicitly_publishable, publish_reason = publish_status(pkg) + package_info[name] = { + "pkg": pkg, + "member": member, + "explicitly_publishable": explicitly_publishable, + "publish_reason": publish_reason, + } + + direct_issues = defaultdict(set) + workspace_deps = defaultdict(list) + + for name, info in package_info.items(): + pkg = info["pkg"] + member = info["member"] + explicitly_publishable = info["explicitly_publishable"] + + if not explicitly_publishable: + direct_issues[name].add(info["publish_reason"]) + continue + + for field in ("description", "license", "repository"): + value = pkg.get(field) + if not isinstance(value, str) or not value.strip(): + direct_issues[name].add(f"missing required field '{field}'") + + for dep in pkg.get("dependencies", []): + section = dependency_section(dep) + dep_name = dep["name"] + dep_source = dep.get("source") + + dep_workspace_name = workspace_by_name.get(dep_name, {}).get("name") + dep_path = dep.get("path") + if dep_workspace_name is None and dep_path: + dep_workspace_name = workspace_dir_to_name.get( + str(pathlib.Path(dep_path).resolve()) + ) + + if dep_path and dep.get("req") in ("*", ""): + direct_issues[name].add( + f"{section}: path dependency '{dep_name}' has no explicit version ({dep_path})" + ) + + if dep_workspace_name: + workspace_deps[name].append((dep_workspace_name, section)) + continue + + if dep_source and not dep_source.startswith("registry+"): + direct_issues[name].add( + f"{section}: non-registry dependency '{dep_name}' from '{dep_source}'" + ) + + effective_issues = {} + + def collect_effective_issues(crate_name, stack): + cached = effective_issues.get(crate_name) + if cached is not None: + return cached + + issues = set(direct_issues.get(crate_name, set())) + stack = stack | {crate_name} + + for dep_name, dep_section in workspace_deps.get(crate_name, []): + dep_info = package_info[dep_name] + if not dep_info["explicitly_publishable"]: + issues.add( + f"{dep_section}: depends on non-publishable workspace crate '{dep_name}' ({dep_info['publish_reason']})" + ) + continue + + if dep_name in stack: + continue + + dep_issues = collect_effective_issues(dep_name, stack) + if dep_issues: + issues.add( + f"{dep_section}: depends on blocked workspace crate '{dep_name}'" + ) + + effective_issues[crate_name] = issues + return issues + + for crate_name in package_info: + collect_effective_issues(crate_name, set()) + + unpublishable = [] + for crate_name, info in sorted(package_info.items()): + issues = sorted(effective_issues.get(crate_name, set())) + if not issues: + continue + unpublishable.append((crate_name, info["member"], issues)) + + print("Publishability report:") + print(f"- workspace crates inspected: {len(package_info)}") + print(f"- unpublishable crates: {len(unpublishable)}") + + if unpublishable: + print("\nUnpublishable crate details:") + for crate_name, member, issues in unpublishable: + print(f"- {crate_name} ({member})") + for issue in issues: + print(f" - {issue}") + + blocking = [] + for crate_name, info in package_info.items(): + if not info["explicitly_publishable"]: + continue + if effective_issues.get(crate_name): + blocking.append(crate_name) + + if blocking: + print("\nPreflight checks failed:") + print( + f"- {len(blocking)} crate(s) configured for crates.io publish are currently blocked." + ) + sys.exit(1) + + print("\nPreflight checks passed.") + + +if __name__ == "__main__": + main() From e024d68fac4cab2559b8b707ba9d3e002d79aa73 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Fri, 27 Feb 2026 19:06:49 +0100 Subject: [PATCH 08/37] mebbe --- tools/internal/check_publish_preflight.py | 73 ++++++++++++++++------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/tools/internal/check_publish_preflight.py b/tools/internal/check_publish_preflight.py index 894a398a3d..5e6f857051 100644 --- a/tools/internal/check_publish_preflight.py +++ b/tools/internal/check_publish_preflight.py @@ -110,6 +110,12 @@ def main(): ) if dep_workspace_name: + dep_info = package_info[dep_workspace_name] + if not dep_info["explicitly_publishable"]: + direct_issues[name].add( + f"{section}: depends on non-publishable workspace crate '{dep_workspace_name}' ({dep_info['publish_reason']})" + ) + continue workspace_deps[name].append((dep_workspace_name, section)) continue @@ -151,36 +157,57 @@ def main(): for crate_name in package_info: collect_effective_issues(crate_name, set()) - unpublishable = [] - for crate_name, info in sorted(package_info.items()): - issues = sorted(effective_issues.get(crate_name, set())) - if not issues: - continue - unpublishable.append((crate_name, info["member"], issues)) + publish_targets = sorted( + name for name, info in package_info.items() if info["explicitly_publishable"] + ) + root_blockers = sorted( + name + for name in publish_targets + if direct_issues.get(name) + ) + transitive_blocked = sorted( + name + for name in publish_targets + if not direct_issues.get(name) and effective_issues.get(name) + ) - print("Publishability report:") + disabled_by_config = sorted( + name for name, info in package_info.items() if not info["explicitly_publishable"] + ) + + print("Publishability preflight report:") print(f"- workspace crates inspected: {len(package_info)}") - print(f"- unpublishable crates: {len(unpublishable)}") + print(f"- crates configured for crates.io publish: {len(publish_targets)}") + print(f"- root blockers (direct issues): {len(root_blockers)}") + print(f"- downstream blocked crates (transitive): {len(transitive_blocked)}") + print(f"- crates excluded by config (publish = false / restricted): {len(disabled_by_config)}") - if unpublishable: - print("\nUnpublishable crate details:") - for crate_name, member, issues in unpublishable: - print(f"- {crate_name} ({member})") - for issue in issues: + if root_blockers: + print("\nAction required: root blockers") + for crate_name in root_blockers: + info = package_info[crate_name] + print(f"- {crate_name} ({info['member']})") + for issue in sorted(direct_issues[crate_name]): print(f" - {issue}") - blocking = [] - for crate_name, info in package_info.items(): - if not info["explicitly_publishable"]: - continue - if effective_issues.get(crate_name): - blocking.append(crate_name) + if transitive_blocked: + print("\nDownstream blocked crates") + print("- These crates have no direct issue; they are blocked by dependencies listed below.") + for crate_name in transitive_blocked: + info = package_info[crate_name] + blockers = set() + for dep_name, dep_section in workspace_deps.get(crate_name, []): + dep_info = package_info[dep_name] + if not dep_info["explicitly_publishable"] or effective_issues.get(dep_name): + blockers.add(f"{dep_name} via {dep_section}") - if blocking: + print(f"- {crate_name} ({info['member']})") + for blocker in sorted(blockers): + print(f" - blocked by {blocker}") + + if root_blockers or transitive_blocked: print("\nPreflight checks failed:") - print( - f"- {len(blocking)} crate(s) configured for crates.io publish are currently blocked." - ) + print(f"- {len(root_blockers) + len(transitive_blocked)} crate(s) configured for crates.io publish are blocked.") sys.exit(1) print("\nPreflight checks passed.") From 42ffb7d36ecfc3ca9c230538bdd99637f4b0d217 Mon Sep 17 00:00:00 2001 From: benedetta davico <46782255+benedettadavico@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:10:51 +0200 Subject: [PATCH 09/37] Enable publishing for nym-kkt-ciphersuite --- common/nym-kkt-ciphersuite/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/nym-kkt-ciphersuite/Cargo.toml b/common/nym-kkt-ciphersuite/Cargo.toml index 65722caab8..5c71596d02 100644 --- a/common/nym-kkt-ciphersuite/Cargo.toml +++ b/common/nym-kkt-ciphersuite/Cargo.toml @@ -10,7 +10,7 @@ license.workspace = true rust-version.workspace = true readme.workspace = true version.workspace = true -publish = false +publish = true [dependencies] thiserror = { workspace = true } From 5a08a4cdd264ecb8fabb41f9ad4d600466a7de78 Mon Sep 17 00:00:00 2001 From: benedetta davico <46782255+benedettadavico@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:11:07 +0200 Subject: [PATCH 10/37] Enable publishing for nym-lp Cargo package --- common/nym-lp/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/nym-lp/Cargo.toml b/common/nym-lp/Cargo.toml index 56ba2c2c11..a71339a60a 100644 --- a/common/nym-lp/Cargo.toml +++ b/common/nym-lp/Cargo.toml @@ -9,7 +9,7 @@ license.workspace = true rust-version.workspace = true readme.workspace = true version.workspace = true -publish = false +publish = true [dependencies] thiserror = { workspace = true } From cfce6dedffba851ef2c8e404d224e43597584d3e Mon Sep 17 00:00:00 2001 From: benedetta davico <46782255+benedettadavico@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:13:35 +0200 Subject: [PATCH 11/37] Update Cargo.toml --- common/nym-kkt/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/nym-kkt/Cargo.toml b/common/nym-kkt/Cargo.toml index 02c9f50d49..6c7892e511 100644 --- a/common/nym-kkt/Cargo.toml +++ b/common/nym-kkt/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = ["Georgio Nicolas "] edition = { workspace = true } license.workspace = true -publish = false +publish = true [dependencies] thiserror = { workspace = true } From 55e485ebce8b7095422da42717511e9be5010331 Mon Sep 17 00:00:00 2001 From: benedetta davico <46782255+benedettadavico@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:16:37 +0200 Subject: [PATCH 12/37] Update Cargo.toml --- common/nym-kkt-context/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/nym-kkt-context/Cargo.toml b/common/nym-kkt-context/Cargo.toml index 9ab1c8e123..008eaddcaf 100644 --- a/common/nym-kkt-context/Cargo.toml +++ b/common/nym-kkt-context/Cargo.toml @@ -9,7 +9,7 @@ license.workspace = true rust-version.workspace = true readme.workspace = true version.workspace = true -publish = false +publish = true [dependencies] num_enum = { workspace = true } From 395c1341869afcf77cc09c4dbd3f8b5481aafd24 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 16 Apr 2026 14:02:57 +0100 Subject: [PATCH 13/37] Cargo.toml package field fixes for preflight check --- common/config/Cargo.toml | 1 + common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml | 1 + common/nym-kkt-context/Cargo.toml | 3 ++- common/nym-kkt/Cargo.toml | 2 ++ common/nym-lp/Cargo.toml | 1 + smolmix/core/Cargo.toml | 3 +++ 6 files changed, 10 insertions(+), 1 deletion(-) diff --git a/common/config/Cargo.toml b/common/config/Cargo.toml index 4c364f9292..2adbab789c 100644 --- a/common/config/Cargo.toml +++ b/common/config/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true authors = ["Jedrzej Stuczynski "] edition = "2021" license.workspace = true +repository.workspace = true homepage.workspace = true description = "Config related helpers and functions" diff --git a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml index 31aef542af..c6a1894aca 100644 --- a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition = "2021" license.workspace = true description = "Common code for the Nym multisig CosmWasm smart contract" +repository.workspace = true homepage.workspace = true [dependencies] diff --git a/common/nym-kkt-context/Cargo.toml b/common/nym-kkt-context/Cargo.toml index 008eaddcaf..b91f6b38e1 100644 --- a/common/nym-kkt-context/Cargo.toml +++ b/common/nym-kkt-context/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "nym-kkt-context" +description = "Context types and definitions for the Nym KKT protocol" authors.workspace = true repository.workspace = true homepage.workspace = true @@ -15,7 +16,7 @@ publish = true num_enum = { workspace = true } thiserror = { workspace = true } -nym-kkt-ciphersuite = { path = "../nym-kkt-ciphersuite" } +nym-kkt-ciphersuite = { workspace = true } [lints] workspace = true diff --git a/common/nym-kkt/Cargo.toml b/common/nym-kkt/Cargo.toml index 6c7892e511..1bff6d7a09 100644 --- a/common/nym-kkt/Cargo.toml +++ b/common/nym-kkt/Cargo.toml @@ -1,7 +1,9 @@ [package] name = "nym-kkt" +description = "Key transport protocol for the Nym network" version = "0.1.0" authors = ["Georgio Nicolas "] +repository.workspace = true edition = { workspace = true } license.workspace = true publish = true diff --git a/common/nym-lp/Cargo.toml b/common/nym-lp/Cargo.toml index a71339a60a..eeca6fcfc6 100644 --- a/common/nym-lp/Cargo.toml +++ b/common/nym-lp/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "nym-lp" +description = "Lewes Protocol session and transport layer for the Nym network" authors.workspace = true repository.workspace = true homepage.workspace = true diff --git a/smolmix/core/Cargo.toml b/smolmix/core/Cargo.toml index 173e519178..aee3249372 100644 --- a/smolmix/core/Cargo.toml +++ b/smolmix/core/Cargo.toml @@ -1,5 +1,8 @@ [package] name = "smolmix" +publish = true +repository.workspace = true +description = "Tunnel for TCP and UDP traffic to be sent over Nym mixnet to clearnet remote hosts" version = "0.0.1" edition = "2021" license.workspace = true From 924d7d1ccc0374ad377eafb146060a6277ce674c Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Fri, 17 Apr 2026 07:49:50 +0100 Subject: [PATCH 14/37] Enforce ordering of [package] fields in cargo.toml files --- clients/native/Cargo.toml | 4 ++-- clients/native/websocket-requests/Cargo.toml | 2 +- clients/socks5/Cargo.toml | 4 ++-- common/async-file-watcher/Cargo.toml | 2 +- common/authenticator-requests/Cargo.toml | 6 +++--- common/bandwidth-controller/Cargo.toml | 2 +- common/bin-common/Cargo.toml | 4 ++-- common/client-core/Cargo.toml | 4 ++-- common/client-core/config-types/Cargo.toml | 2 +- common/client-core/gateways-storage/Cargo.toml | 4 ++-- common/client-core/surb-storage/Cargo.toml | 2 +- common/client-libs/gateway-client/Cargo.toml | 2 +- common/client-libs/mixnet-client/Cargo.toml | 2 +- common/client-libs/validator-client/Cargo.toml | 4 ++-- common/commands/Cargo.toml | 2 +- common/config/Cargo.toml | 2 +- common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml | 2 +- .../contracts-common-testing/Cargo.toml | 6 +++--- .../cosmwasm-smart-contracts/contracts-common/Cargo.toml | 4 ++-- common/cosmwasm-smart-contracts/easy_addr/Cargo.toml | 2 +- common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml | 2 +- common/cosmwasm-smart-contracts/group-contract/Cargo.toml | 2 +- .../cosmwasm-smart-contracts/mixnet-contract/Cargo.toml | 6 +++--- .../cosmwasm-smart-contracts/multisig-contract/Cargo.toml | 2 +- .../nym-performance-contract/Cargo.toml | 6 +++--- .../cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml | 6 +++--- .../cosmwasm-smart-contracts/vesting-contract/Cargo.toml | 4 ++-- common/credential-proxy/Cargo.toml | 6 +++--- common/credential-storage/Cargo.toml | 4 ++-- common/credential-utils/Cargo.toml | 2 +- common/credential-verification/Cargo.toml | 6 +++--- common/credentials-interface/Cargo.toml | 6 +++--- common/credentials/Cargo.toml | 2 +- common/crypto/Cargo.toml | 4 ++-- common/dkg/Cargo.toml | 4 ++-- common/ecash-signer-check-types/Cargo.toml | 6 +++--- common/ecash-signer-check/Cargo.toml | 6 +++--- common/ecash-time/Cargo.toml | 6 +++--- common/exit-policy/Cargo.toml | 6 +++--- common/gateway-requests/Cargo.toml | 2 +- common/gateway-stats-storage/Cargo.toml | 6 +++--- common/gateway-storage/Cargo.toml | 6 +++--- common/http-api-client-macro/Cargo.toml | 6 +++--- common/http-api-client/Cargo.toml | 6 +++--- common/http-api-common/Cargo.toml | 6 +++--- common/inclusion-probability/Cargo.toml | 4 ++-- common/ip-packet-requests/Cargo.toml | 6 +++--- common/mixnode-common/Cargo.toml | 2 +- common/network-defaults/Cargo.toml | 4 ++-- common/node-tester-utils/Cargo.toml | 2 +- common/nonexhaustive-delayqueue/Cargo.toml | 2 +- common/nym-cache/Cargo.toml | 6 +++--- common/nym-common/Cargo.toml | 6 +++--- common/nym-connection-monitor/Cargo.toml | 4 ++-- common/nym-id/Cargo.toml | 6 +++--- common/nym-kcp/Cargo.toml | 4 ++-- common/nym-kkt-ciphersuite/Cargo.toml | 6 +++--- common/nym-kkt-context/Cargo.toml | 6 +++--- common/nym-kkt/Cargo.toml | 2 +- common/nym-lp/Cargo.toml | 6 +++--- common/nym-metrics/Cargo.toml | 6 +++--- common/nym_offline_compact_ecash/Cargo.toml | 2 +- common/nymnoise/Cargo.toml | 2 +- common/nymnoise/keys/Cargo.toml | 2 +- common/nymsphinx/Cargo.toml | 4 ++-- common/nymsphinx/acknowledgements/Cargo.toml | 4 ++-- common/nymsphinx/addressing/Cargo.toml | 4 ++-- common/nymsphinx/anonymous-replies/Cargo.toml | 4 ++-- common/nymsphinx/chunking/Cargo.toml | 4 ++-- common/nymsphinx/cover/Cargo.toml | 4 ++-- common/nymsphinx/forwarding/Cargo.toml | 4 ++-- common/nymsphinx/framing/Cargo.toml | 4 ++-- common/nymsphinx/params/Cargo.toml | 4 ++-- common/nymsphinx/routing/Cargo.toml | 4 ++-- common/nymsphinx/types/Cargo.toml | 4 ++-- common/nyxd-scraper-psql/Cargo.toml | 4 ++-- common/nyxd-scraper-shared/Cargo.toml | 6 +++--- common/nyxd-scraper-sqlite/Cargo.toml | 4 ++-- common/pemstore/Cargo.toml | 2 +- common/registration/Cargo.toml | 6 +++--- common/serde-helpers/Cargo.toml | 6 +++--- common/service-provider-requests-common/Cargo.toml | 6 +++--- common/socks5-client-core/Cargo.toml | 2 +- common/socks5/ordered-buffer/Cargo.toml | 2 +- common/socks5/proxy-helpers/Cargo.toml | 2 +- common/socks5/requests/Cargo.toml | 2 +- common/statistics/Cargo.toml | 2 +- common/store-cipher/Cargo.toml | 2 +- common/task/Cargo.toml | 4 ++-- common/test-utils/Cargo.toml | 6 +++--- common/ticketbooks-merkle/Cargo.toml | 6 +++--- common/topology/Cargo.toml | 4 ++-- common/tun/Cargo.toml | 6 +++--- common/types/Cargo.toml | 4 ++-- common/upgrade-mode-check/Cargo.toml | 6 +++--- common/verloc/Cargo.toml | 6 +++--- common/wasm/client-core/Cargo.toml | 4 ++-- common/wasm/storage/Cargo.toml | 2 +- common/wasm/utils/Cargo.toml | 2 +- common/wireguard-private-metadata/client/Cargo.toml | 6 +++--- common/wireguard-private-metadata/server/Cargo.toml | 6 +++--- common/wireguard-private-metadata/shared/Cargo.toml | 6 +++--- common/wireguard-private-metadata/tests/Cargo.toml | 6 +++--- common/wireguard-types/Cargo.toml | 6 +++--- common/wireguard/Cargo.toml | 6 +++--- common/zulip-client/Cargo.toml | 4 ++-- contracts/coconut-dkg/Cargo.toml | 2 +- contracts/ecash/Cargo.toml | 2 +- contracts/mixnet-vesting-integration-tests/Cargo.toml | 2 +- contracts/mixnet/Cargo.toml | 5 ++--- contracts/multisig/cw3-flex-multisig/Cargo.toml | 2 +- contracts/multisig/cw4-group/Cargo.toml | 3 +-- contracts/nym-pool/Cargo.toml | 2 +- contracts/performance/Cargo.toml | 4 ++-- contracts/vesting/Cargo.toml | 5 ++--- cpu-cycles/Cargo.toml | 2 +- documentation/autodoc/Cargo.toml | 4 ++-- gateway/Cargo.toml | 4 ++-- integration-tests/Cargo.toml | 4 ++-- nym-api/Cargo.toml | 2 +- nym-api/nym-api-requests/Cargo.toml | 2 +- nym-authenticator-client/Cargo.toml | 4 ++-- nym-browser-extension/storage/Cargo.toml | 4 ++-- .../nym-credential-proxy-requests/Cargo.toml | 6 +++--- nym-credential-proxy/nym-credential-proxy/Cargo.toml | 4 ++-- nym-data-observatory/Cargo.toml | 4 ++-- nym-gateway-probe/Cargo.toml | 4 ++-- nym-ip-packet-client/Cargo.toml | 6 +++--- nym-network-monitor/Cargo.toml | 4 ++-- nym-node-status-api/nym-node-status-agent/Cargo.toml | 4 ++-- nym-node-status-api/nym-node-status-api/Cargo.toml | 4 ++-- nym-node-status-api/nym-node-status-client/Cargo.toml | 4 ++-- nym-node/Cargo.toml | 4 ++-- nym-node/nym-node-metrics/Cargo.toml | 6 +++--- nym-node/nym-node-requests/Cargo.toml | 6 +++--- nym-outfox/Cargo.toml | 4 ++-- nym-registration-client/Cargo.toml | 6 +++--- nym-signers-monitor/Cargo.toml | 4 ++-- nym-sqlx-pool-guard/Cargo.toml | 2 +- nym-statistics-api/Cargo.toml | 4 ++-- nym-validator-rewarder/Cargo.toml | 4 ++-- nym-wallet/nym-wallet-types/Cargo.toml | 2 +- nym-wallet/src-tauri/Cargo.toml | 8 ++++---- nyx-chain-watcher/Cargo.toml | 4 ++-- sdk/ffi/cpp/Cargo.toml | 4 ++-- sdk/ffi/go/Cargo.toml | 4 ++-- sdk/ffi/shared/Cargo.toml | 4 ++-- sdk/rust/nym-sdk/Cargo.toml | 2 +- service-providers/common/Cargo.toml | 2 +- service-providers/ip-packet-router/Cargo.toml | 4 ++-- service-providers/network-requester/Cargo.toml | 2 +- smolmix/core/Cargo.toml | 4 ++-- tools/echo-server/Cargo.toml | 4 ++-- .../contract-state-importer/importer-cli/Cargo.toml | 4 ++-- .../contract-state-importer/importer-contract/Cargo.toml | 4 ++-- tools/internal/localnet-orchestrator/Cargo.toml | 4 ++-- .../localnet-orchestrator/dkg-bypass-contract/Cargo.toml | 2 +- tools/internal/mixnet-connectivity-check/Cargo.toml | 4 ++-- tools/internal/sdk-version-bump/Cargo.toml | 4 ++-- tools/internal/validator-status-check/Cargo.toml | 4 ++-- tools/nym-id-cli/Cargo.toml | 4 ++-- tools/nym-lp-client/Cargo.toml | 2 +- tools/nymvisor/Cargo.toml | 4 ++-- wasm/client/Cargo.toml | 6 +++--- wasm/full-nym-wasm/Cargo.toml | 4 ++-- wasm/mix-fetch/Cargo.toml | 4 ++-- wasm/node-tester/Cargo.toml | 4 ++-- wasm/zknym-lib/Cargo.toml | 4 ++-- 168 files changed, 335 insertions(+), 338 deletions(-) diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 755ebcf189..32321ce650 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "nym-client" +description = "Implementation of the Nym Client" version = "1.1.74" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] -description = "Implementation of the Nym Client" edition = "2021" -rust-version = "1.85" license.workspace = true +rust-version = "1.85" publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/clients/native/websocket-requests/Cargo.toml b/clients/native/websocket-requests/Cargo.toml index 25defd82ff..51e352dec4 100644 --- a/clients/native/websocket-requests/Cargo.toml +++ b/clients/native/websocket-requests/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-client-websocket-requests" +description = "Request and response definitions for Nym client websocket connections" version.workspace = true authors = ["Jędrzej Stuczyński "] edition = "2021" license.workspace = true -description = "Request and response definitions for Nym client websocket connections" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index 249d801cc2..186ff54caa 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "nym-socks5-client" +description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" version = "1.1.74" authors = ["Dave Hrycyszyn "] -description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" edition = "2021" -rust-version = "1.85" license.workspace = true +rust-version = "1.85" publish = false [dependencies] diff --git a/common/async-file-watcher/Cargo.toml b/common/async-file-watcher/Cargo.toml index 4c4af2ab4c..97ab6f6f86 100644 --- a/common/async-file-watcher/Cargo.toml +++ b/common/async-file-watcher/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-async-file-watcher" +description = "Simple file watcher that sends a notification whenever there was any change in the watched file" version.workspace = true edition.workspace = true license.workspace = true -description = "Simple file watcher that sends a notification whenever there was any change in the watched file" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/authenticator-requests/Cargo.toml b/common/authenticator-requests/Cargo.toml index 89873c5c20..c0cd0a34c5 100644 --- a/common/authenticator-requests/Cargo.toml +++ b/common/authenticator-requests/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-authenticator-requests" +description = "Crate defining requests and responses for the Nym authenticator client" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Crate defining requests and responses for the Nym authenticator client" [dependencies] base64 = { workspace = true } diff --git a/common/bandwidth-controller/Cargo.toml b/common/bandwidth-controller/Cargo.toml index d93ddbab85..a4ba0986ac 100644 --- a/common/bandwidth-controller/Cargo.toml +++ b/common/bandwidth-controller/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-bandwidth-controller" +description = "Crate for controlling the use of zknym credentials to ensure constant bandwidth availability for NymVPN app" version.workspace = true edition = "2021" license.workspace = true -description = "Crate for controlling the use of zknym credentials to ensure constant bandwidth availability for NymVPN app" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/bin-common/Cargo.toml b/common/bin-common/Cargo.toml index dd2a70291b..80570659a4 100644 --- a/common/bin-common/Cargo.toml +++ b/common/bin-common/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-bin-common" -version.workspace = true description = "Common code for nym binaries" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/client-core/Cargo.toml b/common/client-core/Cargo.toml index ce2e932b17..6f8dbb6f67 100644 --- a/common/client-core/Cargo.toml +++ b/common/client-core/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "nym-client-core" +description = "Crate containing core client functionality and configs, used by all other Nym client implentations" version.workspace = true authors = ["Dave Hrycyszyn "] edition = "2024" -rust-version = "1.85" license.workspace = true -description = "Crate containing core client functionality and configs, used by all other Nym client implentations" repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version = "1.85" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/client-core/config-types/Cargo.toml b/common/client-core/config-types/Cargo.toml index 4c586ec1c3..af3b60d7f4 100644 --- a/common/client-core/config-types/Cargo.toml +++ b/common/client-core/config-types/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-client-core-config-types" +description = "Low level configs and constants used by Nym clients and nodes" version.workspace = true edition = "2021" license.workspace = true -description = "Low level configs and constants used by Nym clients and nodes" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/client-core/gateways-storage/Cargo.toml b/common/client-core/gateways-storage/Cargo.toml index 1a1e9f7c2d..18fede97b8 100644 --- a/common/client-core/gateways-storage/Cargo.toml +++ b/common/client-core/gateways-storage/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-client-core-gateways-storage" +description = "Functionality for Nym clients to store and retrive Gateway connections" version.workspace = true edition = "2021" license.workspace = true -rust-version.workspace = true -description = "Functionality for Nym clients to store and retrive Gateway connections" repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/client-core/surb-storage/Cargo.toml b/common/client-core/surb-storage/Cargo.toml index 04168ec19e..d73b32a67a 100644 --- a/common/client-core/surb-storage/Cargo.toml +++ b/common/client-core/surb-storage/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-client-core-surb-storage" +description = "Functionality for Nym clients to generate and use Single Use Reply Blocks (SURBs)" version.workspace = true edition = "2021" license.workspace = true -description = "Functionality for Nym clients to generate and use Single Use Reply Blocks (SURBs)" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/client-libs/gateway-client/Cargo.toml b/common/client-libs/gateway-client/Cargo.toml index 914c23a45e..06803c67ef 100644 --- a/common/client-libs/gateway-client/Cargo.toml +++ b/common/client-libs/gateway-client/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-gateway-client" +description = "Functions and types for Nym client <> Gateway connections" version.workspace = true authors = ["Jędrzej Stuczyński "] edition = "2021" license.workspace = true -description = "Functions and types for Nym client <> Gateway connections" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/client-libs/mixnet-client/Cargo.toml b/common/client-libs/mixnet-client/Cargo.toml index 72f838e50b..59cc416cdd 100644 --- a/common/client-libs/mixnet-client/Cargo.toml +++ b/common/client-libs/mixnet-client/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-mixnet-client" +description = "Client for Mix Node <> Mix Node & Mix Node <> Gateway communication" version.workspace = true authors = ["Jedrzej Stuczynski "] edition = "2021" license.workspace = true -description = "Client for Mix Node <> Mix Node & Mix Node <> Gateway communication" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index e7215d456b..4f5ca7a43c 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "nym-validator-client" +description = "Client for interacting with Nyx Cosmos SDK blockchain" version.workspace = true authors = ["Jędrzej Stuczyński "] edition = "2021" -rust-version = "1.85" license.workspace = true -description = "Client for interacting with Nyx Cosmos SDK blockchain" repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version = "1.85" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/commands/Cargo.toml b/common/commands/Cargo.toml index 1c7d1f8da8..0eccd1194c 100644 --- a/common/commands/Cargo.toml +++ b/common/commands/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-cli-commands" +description = "Common commands crate used by the nym-cli tool for interacting with the Nyx Cosmos SDK blockchain and Mixnet endpoints" version.workspace = true authors.workspace = true edition = "2021" license.workspace = true -description = "Common commands crate used by the nym-cli tool for interacting with the Nyx Cosmos SDK blockchain and Mixnet endpoints" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/config/Cargo.toml b/common/config/Cargo.toml index 2adbab789c..7b618d0e77 100644 --- a/common/config/Cargo.toml +++ b/common/config/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "nym-config" +description = "Config related helpers and functions" version.workspace = true authors = ["Jedrzej Stuczynski "] edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true -description = "Config related helpers and functions" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml b/common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml index 158b920e24..adfbddd5e1 100644 --- a/common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml +++ b/common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-coconut-dkg-common" +description = "Common crate for Nym's DKG cosmwasm contract" version.workspace = true edition = "2021" license.workspace = true -description = "Common crate for Nym's DKG cosmwasm contract" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/cosmwasm-smart-contracts/contracts-common-testing/Cargo.toml b/common/cosmwasm-smart-contracts/contracts-common-testing/Cargo.toml index 69f429b24d..eebc0e0d76 100644 --- a/common/cosmwasm-smart-contracts/contracts-common-testing/Cargo.toml +++ b/common/cosmwasm-smart-contracts/contracts-common-testing/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-contracts-common-testing" +description = "Common crate for cosmwasm contract tests" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Common crate for cosmwasm contract tests" [dependencies] anyhow = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml b/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml index 277351d5d0..787cd43bd4 100644 --- a/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml +++ b/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-contracts-common" -version.workspace = true description = "Common library for Nym cosmwasm contracts" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/easy_addr/Cargo.toml b/common/cosmwasm-smart-contracts/easy_addr/Cargo.toml index b8a48b40a7..e832cd96e9 100644 --- a/common/cosmwasm-smart-contracts/easy_addr/Cargo.toml +++ b/common/cosmwasm-smart-contracts/easy_addr/Cargo.toml @@ -2,8 +2,8 @@ name = "easy-addr" version.workspace = true edition = "2021" -publish = false license.workspace = true +publish = false [lib] proc-macro = true diff --git a/common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml b/common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml index dce59308ce..0c6f060a1e 100644 --- a/common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-ecash-contract-common" +description = "Common crate for Nym's ecash/zknym cosmwasm contract" version.workspace = true edition = "2021" license.workspace = true -description = "Common crate for Nym's ecash/zknym cosmwasm contract" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/cosmwasm-smart-contracts/group-contract/Cargo.toml b/common/cosmwasm-smart-contracts/group-contract/Cargo.toml index 17cb3e83db..c76b813a6b 100644 --- a/common/cosmwasm-smart-contracts/group-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/group-contract/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-group-contract-common" +description = "Common crate for Nym's group cosmwasm contract" version.workspace = true edition = "2021" license.workspace = true -description = "Common crate for Nym's group cosmwasm contract" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml index fb7143723d..5a8a31ee44 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "nym-mixnet-contract-common" -version.workspace = true description = "Common library for the Nym mixnet contract" -rust-version = "1.85" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +rust-version = "1.85" [dependencies] bs58 = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml index c6a1894aca..44d368a817 100644 --- a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-multisig-contract-common" +description = "Common code for the Nym multisig CosmWasm smart contract" version.workspace = true edition = "2021" license.workspace = true -description = "Common code for the Nym multisig CosmWasm smart contract" repository.workspace = true homepage.workspace = true diff --git a/common/cosmwasm-smart-contracts/nym-performance-contract/Cargo.toml b/common/cosmwasm-smart-contracts/nym-performance-contract/Cargo.toml index 8fd19ff838..8d778d434d 100644 --- a/common/cosmwasm-smart-contracts/nym-performance-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/nym-performance-contract/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-performance-contract-common" +description = "Common crate for Nym's group performance contract" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Common crate for Nym's group performance contract" [dependencies] thiserror = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml b/common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml index a4567fb0c2..7e12aa793e 100644 --- a/common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-pool-contract-common" -version.workspace = true description = "Common library for the Nym Pool contract" +version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true diff --git a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml index cc29aebe12..e004f6ff03 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-vesting-contract-common" -version.workspace = true description = "Common library for the Nym vesting contract" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/credential-proxy/Cargo.toml b/common/credential-proxy/Cargo.toml index 65549f2753..cab3a24b06 100644 --- a/common/credential-proxy/Cargo.toml +++ b/common/credential-proxy/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-credential-proxy-lib" +description = "Build script and core functionality of the Nym Credential Proxy" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Build script and core functionality of the Nym Credential Proxy" [dependencies] anyhow = { workspace = true } diff --git a/common/credential-storage/Cargo.toml b/common/credential-storage/Cargo.toml index 42da92cedc..90910a94dd 100644 --- a/common/credential-storage/Cargo.toml +++ b/common/credential-storage/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-credential-storage" +description = "Crate for handling and storing spent and unspent zknym ticketbooks" version.workspace = true edition = "2021" license.workspace = true -rust-version.workspace = true -description = "Crate for handling and storing spent and unspent zknym ticketbooks" repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/credential-utils/Cargo.toml b/common/credential-utils/Cargo.toml index f3d6986d1d..2311188907 100644 --- a/common/credential-utils/Cargo.toml +++ b/common/credential-utils/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-credential-utils" +description = "Utils crate for dealing with zknym credentials" version.workspace = true edition = "2021" license.workspace = true -description = "Utils crate for dealing with zknym credentials" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/credential-verification/Cargo.toml b/common/credential-verification/Cargo.toml index d5af1fff19..a159119ef8 100644 --- a/common/credential-verification/Cargo.toml +++ b/common/credential-verification/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-credential-verification" +description = "Store and verify zknym credentials" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Store and verify zknym credentials" [dependencies] async-trait = { workspace = true } diff --git a/common/credentials-interface/Cargo.toml b/common/credentials-interface/Cargo.toml index fd2f6d895d..07c3e91d31 100644 --- a/common/credentials-interface/Cargo.toml +++ b/common/credentials-interface/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-credentials-interface" +description = "Interface for Nym's compact eacash / zknym credential scheme" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Interface for Nym's compact eacash / zknym credential scheme" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/credentials/Cargo.toml b/common/credentials/Cargo.toml index 1a429bc24c..af918db7f6 100644 --- a/common/credentials/Cargo.toml +++ b/common/credentials/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-credentials" +description = "Crate for using Nym's zknym credentials" version.workspace = true edition = "2021" license.workspace = true -description = "Crate for using Nym's zknym credentials" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/crypto/Cargo.toml b/common/crypto/Cargo.toml index 7d037f1a97..7f8f54d746 100644 --- a/common/crypto/Cargo.toml +++ b/common/crypto/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-crypto" -version.workspace = true description = "Crypto library for the nym mixnet" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/dkg/Cargo.toml b/common/dkg/Cargo.toml index e45a2a8d7f..9dccc4646f 100644 --- a/common/dkg/Cargo.toml +++ b/common/dkg/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-dkg" +description = "Nym's Distributed Key Generation functionality" version.workspace = true edition = "2021" -resolver = "2" license.workspace = true -description = "Nym's Distributed Key Generation functionality" repository.workspace = true homepage.workspace = true documentation.workspace = true +resolver = "2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/ecash-signer-check-types/Cargo.toml b/common/ecash-signer-check-types/Cargo.toml index ac3a6f084d..818ddcd78f 100644 --- a/common/ecash-signer-check-types/Cargo.toml +++ b/common/ecash-signer-check-types/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-ecash-signer-check-types" +description = "Crate containing types for the `ecash-signer-check` crate used to check if zknym signers are up and running properly" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Crate containing types for the `ecash-signer-check` crate used to check if zknym signers are up and running properly" [dependencies] semver = { workspace = true } diff --git a/common/ecash-signer-check/Cargo.toml b/common/ecash-signer-check/Cargo.toml index 976df1bf55..4cd66d8106 100644 --- a/common/ecash-signer-check/Cargo.toml +++ b/common/ecash-signer-check/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-ecash-signer-check" +description = "Functions to interact with zknym signers, checking their status and health" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Functions to interact with zknym signers, checking their status and health" [dependencies] futures = { workspace = true } diff --git a/common/ecash-time/Cargo.toml b/common/ecash-time/Cargo.toml index 1780a96afe..f1aca80ab3 100644 --- a/common/ecash-time/Cargo.toml +++ b/common/ecash-time/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-ecash-time" +description = "Time-related helper functions for Nym's zknym scheme" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Time-related helper functions for Nym's zknym scheme" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/exit-policy/Cargo.toml b/common/exit-policy/Cargo.toml index 3db220a920..7cd6e83fcd 100644 --- a/common/exit-policy/Cargo.toml +++ b/common/exit-policy/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-exit-policy" +description = "Get and set the Nym Exit Policy, used by Exit Gateways" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Get and set the Nym Exit Policy, used by Exit Gateways" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/gateway-requests/Cargo.toml b/common/gateway-requests/Cargo.toml index b9cdf43d01..e929215acc 100644 --- a/common/gateway-requests/Cargo.toml +++ b/common/gateway-requests/Cargo.toml @@ -3,11 +3,11 @@ [package] name = "nym-gateway-requests" +description = "Request and response definitions for Nym Gateway <> client communication" version.workspace = true authors = ["Jedrzej Stuczynski "] edition = "2021" license.workspace = true -description = "Request and response definitions for Nym Gateway <> client communication" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/gateway-stats-storage/Cargo.toml b/common/gateway-stats-storage/Cargo.toml index 7c1f996059..b5307601ef 100644 --- a/common/gateway-stats-storage/Cargo.toml +++ b/common/gateway-stats-storage/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "nym-gateway-stats-storage" +description = "Functionality Nym Gateway statistics storage" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true -description = "Functionality Nym Gateway statistics storage" [dependencies] sqlx = { workspace = true, features = [ diff --git a/common/gateway-storage/Cargo.toml b/common/gateway-storage/Cargo.toml index 32424e7d4a..0b60496015 100644 --- a/common/gateway-storage/Cargo.toml +++ b/common/gateway-storage/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "nym-gateway-storage" +description = "Crate handling db setup and use for Nym Gateways, used for credentials, packets, connections" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true -description = "Crate handling db setup and use for Nym Gateways, used for credentials, packets, connections" [dependencies] async-trait = { workspace = true } diff --git a/common/http-api-client-macro/Cargo.toml b/common/http-api-client-macro/Cargo.toml index f5e12bef4c..a05fb9558e 100644 --- a/common/http-api-client-macro/Cargo.toml +++ b/common/http-api-client-macro/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-http-api-client-macro" +description = "Proc-macros for configuring HTTP clients globally via the `inventory` crate" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Proc-macros for configuring HTTP clients globally via the `inventory` crate" [lib] proc-macro = true diff --git a/common/http-api-client/Cargo.toml b/common/http-api-client/Cargo.toml index 00d083bbf2..6625080599 100644 --- a/common/http-api-client/Cargo.toml +++ b/common/http-api-client/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-http-api-client" +description = "Nym's HTTP API client, examples, and tests" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Nym's HTTP API client, examples, and tests" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/http-api-common/Cargo.toml b/common/http-api-common/Cargo.toml index 17d7521788..5fe20b08b3 100644 --- a/common/http-api-common/Cargo.toml +++ b/common/http-api-common/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-http-api-common" +description = "Common crate for Nym-related HTTP API interaction" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Common crate for Nym-related HTTP API interaction" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/inclusion-probability/Cargo.toml b/common/inclusion-probability/Cargo.toml index d27d0a23fa..61563c451e 100644 --- a/common/inclusion-probability/Cargo.toml +++ b/common/inclusion-probability/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-inclusion-probability" -version.workspace = true description = "Nym active set probability simulator" -edition.workspace = true +version.workspace = true authors.workspace = true +edition.workspace = true license.workspace = true repository.workspace = true diff --git a/common/ip-packet-requests/Cargo.toml b/common/ip-packet-requests/Cargo.toml index 0d062b2d45..34b040f240 100644 --- a/common/ip-packet-requests/Cargo.toml +++ b/common/ip-packet-requests/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-ip-packet-requests" +description = "Codec, signing functionality, and different version definitions for IP packet request and responses" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Codec, signing functionality, and different version definitions for IP packet request and responses" [features] diff --git a/common/mixnode-common/Cargo.toml b/common/mixnode-common/Cargo.toml index 50d1c94cde..198b0f71f9 100644 --- a/common/mixnode-common/Cargo.toml +++ b/common/mixnode-common/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-mixnode-common" +description = "Common crate for Nym Mix Nodes" version.workspace = true authors = ["Jędrzej Stuczyński "] edition = "2021" license.workspace = true -description = "Common crate for Nym Mix Nodes" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/network-defaults/Cargo.toml b/common/network-defaults/Cargo.toml index 305f31916f..746386736d 100644 --- a/common/network-defaults/Cargo.toml +++ b/common/network-defaults/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-network-defaults" -version.workspace = true description = "Nym network defaults" -edition.workspace = true +version.workspace = true authors.workspace = true +edition.workspace = true license.workspace = true repository.workspace = true # Exclude build.rs from published crate - it's only used for dev-time sync diff --git a/common/node-tester-utils/Cargo.toml b/common/node-tester-utils/Cargo.toml index d3845fb094..e2be4ac7b8 100644 --- a/common/node-tester-utils/Cargo.toml +++ b/common/node-tester-utils/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-node-tester-utils" +description = "Utils for the Nym Node Tester" version.workspace = true edition = "2021" license.workspace = true -description = "Utils for the Nym Node Tester" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/nonexhaustive-delayqueue/Cargo.toml b/common/nonexhaustive-delayqueue/Cargo.toml index f8d4671688..2ac9bf2096 100644 --- a/common/nonexhaustive-delayqueue/Cargo.toml +++ b/common/nonexhaustive-delayqueue/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-nonexhaustive-delayqueue" +description = "A copy of tokio-util delay_queue with `Sleep` and `Instant` being replaced with`wasm_timer` equivalents" version.workspace = true authors = ["Jędrzej Stuczyński "] edition = "2021" license.workspace = true -description = "A copy of tokio-util delay_queue with `Sleep` and `Instant` being replaced with`wasm_timer` equivalents" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/nym-cache/Cargo.toml b/common/nym-cache/Cargo.toml index 3d935c3e89..e9afc05c13 100644 --- a/common/nym-cache/Cargo.toml +++ b/common/nym-cache/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-cache" +description = "Helper functions around a RwLock for writing to local cache of items" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Helper functions around a RwLock for writing to local cache of items" [dependencies] tokio = { workspace = true, features = ["sync"] } diff --git a/common/nym-common/Cargo.toml b/common/nym-common/Cargo.toml index 6bdbef1bce..f0b10a6eb0 100644 --- a/common/nym-common/Cargo.toml +++ b/common/nym-common/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "nym-common" +description = "Runtime diagnostics for high frequency logging, debugging and error handling utilities" version.workspace = true authors.workspace = true -repository.workspace = true -license.workspace = true edition.workspace = true -description = "Runtime diagnostics for high frequency logging, debugging and error handling utilities" +license.workspace = true +repository.workspace = true [lints] workspace = true diff --git a/common/nym-connection-monitor/Cargo.toml b/common/nym-connection-monitor/Cargo.toml index 03de5da740..c7ce2c445e 100644 --- a/common/nym-connection-monitor/Cargo.toml +++ b/common/nym-connection-monitor/Cargo.toml @@ -2,11 +2,11 @@ name = "nym-connection-monitor" version = "1.18.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true publish = false [lints] diff --git a/common/nym-id/Cargo.toml b/common/nym-id/Cargo.toml index 17b4ac31ef..2af699c96c 100644 --- a/common/nym-id/Cargo.toml +++ b/common/nym-id/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-id" +description = "Functionality for importing and storing credentials and cryptographic keys" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Functionality for importing and storing credentials and cryptographic keys" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/nym-kcp/Cargo.toml b/common/nym-kcp/Cargo.toml index 3f435e94e5..b866fd7954 100644 --- a/common/nym-kcp/Cargo.toml +++ b/common/nym-kcp/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-kcp" -version = "0.1.0" description = "KCP protocol implementation for Nym" -edition = { workspace = true } +version = "0.1.0" authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } publish = false diff --git a/common/nym-kkt-ciphersuite/Cargo.toml b/common/nym-kkt-ciphersuite/Cargo.toml index 5c71596d02..d1d69e9fea 100644 --- a/common/nym-kkt-ciphersuite/Cargo.toml +++ b/common/nym-kkt-ciphersuite/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-kkt-ciphersuite" description = "Nym KKT ciphersuite" +version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -version.workspace = true publish = true [dependencies] diff --git a/common/nym-kkt-context/Cargo.toml b/common/nym-kkt-context/Cargo.toml index b91f6b38e1..53f5bbf530 100644 --- a/common/nym-kkt-context/Cargo.toml +++ b/common/nym-kkt-context/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-kkt-context" description = "Context types and definitions for the Nym KKT protocol" +version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -version.workspace = true publish = true [dependencies] diff --git a/common/nym-kkt/Cargo.toml b/common/nym-kkt/Cargo.toml index 1bff6d7a09..7b5f64dbf1 100644 --- a/common/nym-kkt/Cargo.toml +++ b/common/nym-kkt/Cargo.toml @@ -3,9 +3,9 @@ name = "nym-kkt" description = "Key transport protocol for the Nym network" version = "0.1.0" authors = ["Georgio Nicolas "] -repository.workspace = true edition = { workspace = true } license.workspace = true +repository.workspace = true publish = true [dependencies] diff --git a/common/nym-lp/Cargo.toml b/common/nym-lp/Cargo.toml index eeca6fcfc6..24f78711a0 100644 --- a/common/nym-lp/Cargo.toml +++ b/common/nym-lp/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-lp" description = "Lewes Protocol session and transport layer for the Nym network" +version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -version.workspace = true publish = true [dependencies] diff --git a/common/nym-metrics/Cargo.toml b/common/nym-metrics/Cargo.toml index 491b72f07d..6453cf083d 100644 --- a/common/nym-metrics/Cargo.toml +++ b/common/nym-metrics/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-metrics" +description = "Metrics macros" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Metrics macros" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/nym_offline_compact_ecash/Cargo.toml b/common/nym_offline_compact_ecash/Cargo.toml index e70063bd17..5247442625 100644 --- a/common/nym_offline_compact_ecash/Cargo.toml +++ b/common/nym_offline_compact_ecash/Cargo.toml @@ -3,11 +3,11 @@ [package] name = "nym-compact-ecash" +description = "Nym's ecash implementation" version.workspace = true authors = ["Ania Piotrowska "] edition = "2021" license = { workspace = true } -description = "Nym's ecash implementation" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/nymnoise/Cargo.toml b/common/nymnoise/Cargo.toml index 64dd0470f5..397df48dc6 100644 --- a/common/nymnoise/Cargo.toml +++ b/common/nymnoise/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-noise" +description = "Nym's Noise protocol implementation" version.workspace = true authors = ["Simon Wicky "] edition = "2021" license.workspace = true -description = "Nym's Noise protocol implementation" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/nymnoise/keys/Cargo.toml b/common/nymnoise/keys/Cargo.toml index 3dfc1c64d2..57ed842b30 100644 --- a/common/nymnoise/keys/Cargo.toml +++ b/common/nymnoise/keys/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-noise-keys" +description = "Helpers and type definition of Nym's Noise protocol keys" version.workspace = true authors = ["Simon Wicky "] edition = "2021" license.workspace = true -description = "Helpers and type definition of Nym's Noise protocol keys" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/nymsphinx/Cargo.toml b/common/nymsphinx/Cargo.toml index 1fba34a0c2..487508e3f6 100644 --- a/common/nymsphinx/Cargo.toml +++ b/common/nymsphinx/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sphinx" -version.workspace = true description = "Top-level crate for sphinx packets as used by the Nym mixnet" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/nymsphinx/acknowledgements/Cargo.toml b/common/nymsphinx/acknowledgements/Cargo.toml index 6d0fe4fcff..a3032889bf 100644 --- a/common/nymsphinx/acknowledgements/Cargo.toml +++ b/common/nymsphinx/acknowledgements/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sphinx-acknowledgements" -version.workspace = true description = "Sphinx packet ack messages" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/nymsphinx/addressing/Cargo.toml b/common/nymsphinx/addressing/Cargo.toml index 5aec9af3ed..4675248f2c 100644 --- a/common/nymsphinx/addressing/Cargo.toml +++ b/common/nymsphinx/addressing/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sphinx-addressing" -version.workspace = true description = "Nym mixnet addressing" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/nymsphinx/anonymous-replies/Cargo.toml b/common/nymsphinx/anonymous-replies/Cargo.toml index fe9f272146..abdbc63612 100644 --- a/common/nymsphinx/anonymous-replies/Cargo.toml +++ b/common/nymsphinx/anonymous-replies/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sphinx-anonymous-replies" -version.workspace = true description = "Anonymous sphinx packet replies using singly-use-reply-blocks (SURB)" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/nymsphinx/chunking/Cargo.toml b/common/nymsphinx/chunking/Cargo.toml index 708ecb5c10..c955737b83 100644 --- a/common/nymsphinx/chunking/Cargo.toml +++ b/common/nymsphinx/chunking/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sphinx-chunking" -version.workspace = true description = "Sphinx packet chunking of underlying data packets" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/nymsphinx/cover/Cargo.toml b/common/nymsphinx/cover/Cargo.toml index 69dcf6fe65..8d1ce48d3a 100644 --- a/common/nymsphinx/cover/Cargo.toml +++ b/common/nymsphinx/cover/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sphinx-cover" -version.workspace = true description = "Sphinx packets used as cover traffic" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/nymsphinx/forwarding/Cargo.toml b/common/nymsphinx/forwarding/Cargo.toml index e9a299c626..2c514f8e60 100644 --- a/common/nymsphinx/forwarding/Cargo.toml +++ b/common/nymsphinx/forwarding/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sphinx-forwarding" -version.workspace = true description = "Sphinx packet forwarding as Nym mix packets" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/nymsphinx/framing/Cargo.toml b/common/nymsphinx/framing/Cargo.toml index a2f42c7e16..3919d97326 100644 --- a/common/nymsphinx/framing/Cargo.toml +++ b/common/nymsphinx/framing/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sphinx-framing" -version.workspace = true description = "Sphinx packet framing for the Nym mixnet" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/nymsphinx/params/Cargo.toml b/common/nymsphinx/params/Cargo.toml index c5fd617d63..3e6b354507 100644 --- a/common/nymsphinx/params/Cargo.toml +++ b/common/nymsphinx/params/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sphinx-params" -version.workspace = true description = "Sphinx packet parameters for the Nym mixnet" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/nymsphinx/routing/Cargo.toml b/common/nymsphinx/routing/Cargo.toml index 209c9baefb..2613fbf672 100644 --- a/common/nymsphinx/routing/Cargo.toml +++ b/common/nymsphinx/routing/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sphinx-routing" -version.workspace = true description = "Sphinx packet routing as Nym mix packets" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/nymsphinx/types/Cargo.toml b/common/nymsphinx/types/Cargo.toml index 776f88a41a..ce8a5f73ae 100644 --- a/common/nymsphinx/types/Cargo.toml +++ b/common/nymsphinx/types/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sphinx-types" -version.workspace = true description = "Re-export sphinx packet types" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/nyxd-scraper-psql/Cargo.toml b/common/nyxd-scraper-psql/Cargo.toml index c99249f0cd..51e62a2092 100644 --- a/common/nyxd-scraper-psql/Cargo.toml +++ b/common/nyxd-scraper-psql/Cargo.toml @@ -2,11 +2,11 @@ name = "nyxd-scraper-psql" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true publish = false diff --git a/common/nyxd-scraper-shared/Cargo.toml b/common/nyxd-scraper-shared/Cargo.toml index 299d2a6186..d046ef02ee 100644 --- a/common/nyxd-scraper-shared/Cargo.toml +++ b/common/nyxd-scraper-shared/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nyxd-scraper-shared" +description = "Common crate for the sqlite and psql Nyxd blockchain scrapers" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Common crate for the sqlite and psql Nyxd blockchain scrapers" [dependencies] async-trait.workspace = true diff --git a/common/nyxd-scraper-sqlite/Cargo.toml b/common/nyxd-scraper-sqlite/Cargo.toml index bcf59ce2cf..20bf4bd39b 100644 --- a/common/nyxd-scraper-sqlite/Cargo.toml +++ b/common/nyxd-scraper-sqlite/Cargo.toml @@ -2,11 +2,11 @@ name = "nyxd-scraper-sqlite" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/pemstore/Cargo.toml b/common/pemstore/Cargo.toml index 5534b81dd0..3b35d25492 100644 --- a/common/pemstore/Cargo.toml +++ b/common/pemstore/Cargo.toml @@ -2,8 +2,8 @@ name = "nym-pemstore" description = "Store private-public keypairs in PEM format" version.workspace = true -edition = { workspace = true } authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/common/registration/Cargo.toml b/common/registration/Cargo.toml index c361b21461..27f96a63f4 100644 --- a/common/registration/Cargo.toml +++ b/common/registration/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-registration-common" +description = "Struct definitions for NymNode, GatewayData, and AssignedAddresses" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Struct definitions for NymNode, GatewayData, and AssignedAddresses" [lints] workspace = true diff --git a/common/serde-helpers/Cargo.toml b/common/serde-helpers/Cargo.toml index 9b219e23cb..ab69538007 100644 --- a/common/serde-helpers/Cargo.toml +++ b/common/serde-helpers/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-serde-helpers" +description = "Serde helpers for hex/base64/base58/datetime" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Serde helpers for hex/base64/base58/datetime" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/service-provider-requests-common/Cargo.toml b/common/service-provider-requests-common/Cargo.toml index b289a776b7..caae905475 100644 --- a/common/service-provider-requests-common/Cargo.toml +++ b/common/service-provider-requests-common/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-service-provider-requests-common" +description = "Common crate for requests and responses for Nym Service Providers" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Common crate for requests and responses for Nym Service Providers" [dependencies] serde = { workspace = true, features = ["derive"] } diff --git a/common/socks5-client-core/Cargo.toml b/common/socks5-client-core/Cargo.toml index f86c6cf686..8faf069852 100644 --- a/common/socks5-client-core/Cargo.toml +++ b/common/socks5-client-core/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-socks5-client-core" +description = "Core functionality of the Nym SOCKS client" version.workspace = true edition = "2021" license.workspace = true -description = "Core functionality of the Nym SOCKS client" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/socks5/ordered-buffer/Cargo.toml b/common/socks5/ordered-buffer/Cargo.toml index 572f2c0d59..42d32b0b20 100644 --- a/common/socks5/ordered-buffer/Cargo.toml +++ b/common/socks5/ordered-buffer/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-ordered-buffer" +description = "This crate takes care of reliably and speedily turning bytes into a series of ordered message fragments on one side, and of reliably reassembling the fragments into the original message on the other" version.workspace = true authors = ["Dave Hrycyszyn "] edition = "2021" license.workspace = true -description = "This crate takes care of reliably and speedily turning bytes into a series of ordered message fragments on one side, and of reliably reassembling the fragments into the original message on the other" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/socks5/proxy-helpers/Cargo.toml b/common/socks5/proxy-helpers/Cargo.toml index 9b74fd005d..f1e6dc6b85 100644 --- a/common/socks5/proxy-helpers/Cargo.toml +++ b/common/socks5/proxy-helpers/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-socks5-proxy-helpers" +description = "Helpers for the Nym SOCKS client" version.workspace = true authors = ["Jedrzej Stuczynski "] edition = "2021" license.workspace = true -description = "Helpers for the Nym SOCKS client" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/socks5/requests/Cargo.toml b/common/socks5/requests/Cargo.toml index 1197c4beb3..6776145819 100644 --- a/common/socks5/requests/Cargo.toml +++ b/common/socks5/requests/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-socks5-requests" +description = "Request and response definitions for the Nym SOCKS client" version.workspace = true authors = ["Dave Hrycyszyn "] edition = "2021" license.workspace = true -description = "Request and response definitions for the Nym SOCKS client" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/statistics/Cargo.toml b/common/statistics/Cargo.toml index c086bd8374..85bb78f8b3 100644 --- a/common/statistics/Cargo.toml +++ b/common/statistics/Cargo.toml @@ -3,10 +3,10 @@ [package] name = "nym-statistics-common" +description = "This crate contains basic statistics utilities and abstractions to be re-used and applied throughout both the client and gateway implementations" version.workspace = true edition.workspace = true license.workspace = true -description = "This crate contains basic statistics utilities and abstractions to be re-used and applied throughout both the client and gateway implementations" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/store-cipher/Cargo.toml b/common/store-cipher/Cargo.toml index a2066a5247..7b7fa6c6a6 100644 --- a/common/store-cipher/Cargo.toml +++ b/common/store-cipher/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-store-cipher" +description = "Helpers for various ciphers used throughout the Nym network" version.workspace = true edition = "2021" license.workspace = true -description = "Helpers for various ciphers used throughout the Nym network" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/task/Cargo.toml b/common/task/Cargo.toml index 0daef2c763..b915f7c800 100644 --- a/common/task/Cargo.toml +++ b/common/task/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-task" -version.workspace = true description = "Task handling" -edition.workspace = true +version.workspace = true authors.workspace = true +edition.workspace = true license.workspace = true repository.workspace = true diff --git a/common/test-utils/Cargo.toml b/common/test-utils/Cargo.toml index ead0cff923..77ad5388ba 100644 --- a/common/test-utils/Cargo.toml +++ b/common/test-utils/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-test-utils" +description = "Helpers, traits, and mock definitions for tests" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Helpers, traits, and mock definitions for tests" [dependencies] anyhow = { workspace = true } diff --git a/common/ticketbooks-merkle/Cargo.toml b/common/ticketbooks-merkle/Cargo.toml index 037852a91d..b89e4768fb 100644 --- a/common/ticketbooks-merkle/Cargo.toml +++ b/common/ticketbooks-merkle/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-ticketbooks-merkle" +description = "Generate and verify merkleproofs of zknym ticketbooks" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Generate and verify merkleproofs of zknym ticketbooks" [dependencies] sha2 = { workspace = true } diff --git a/common/topology/Cargo.toml b/common/topology/Cargo.toml index da51f63bbd..579571eb2a 100644 --- a/common/topology/Cargo.toml +++ b/common/topology/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-topology" +description = "Nym's topology crate" version.workspace = true -edition = { workspace = true } authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } homepage = { workspace = true } documentation = { workspace = true } -description = "Nym's topology crate" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/tun/Cargo.toml b/common/tun/Cargo.toml index e5451f0f81..ab5226a2f1 100644 --- a/common/tun/Cargo.toml +++ b/common/tun/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-tun" +description = "Nym's tun implementation" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Nym's tun implementation" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/types/Cargo.toml b/common/types/Cargo.toml index 2f6ae032b4..1451fbfe6d 100644 --- a/common/types/Cargo.toml +++ b/common/types/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "nym-types" -version.workspace = true description = "Nym common types" +version.workspace = true authors.workspace = true edition = "2021" -rust-version.workspace = true license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true [dependencies] base64 = { workspace = true } diff --git a/common/upgrade-mode-check/Cargo.toml b/common/upgrade-mode-check/Cargo.toml index d47d4ba5f9..4f8d8c5359 100644 --- a/common/upgrade-mode-check/Cargo.toml +++ b/common/upgrade-mode-check/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-upgrade-mode-check" +description = "Functions and tests for checking Nym's Credential Proxy is being properly upgraded" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Functions and tests for checking Nym's Credential Proxy is being properly upgraded" [dependencies] jwt-simple = { workspace = true } diff --git a/common/verloc/Cargo.toml b/common/verloc/Cargo.toml index fa218f9aee..4db1b99577 100644 --- a/common/verloc/Cargo.toml +++ b/common/verloc/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "nym-verloc" +description = "Nym's verloc (Verifiable Location) implementation" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true -description = "Nym's verloc (Verifiable Location) implementation" [dependencies] bytes = { workspace = true } diff --git a/common/wasm/client-core/Cargo.toml b/common/wasm/client-core/Cargo.toml index f7811e6f84..73e2eef5bb 100644 --- a/common/wasm/client-core/Cargo.toml +++ b/common/wasm/client-core/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "nym-wasm-client-core" -authors = ["Jedrzej Stuczynski "] +description = "Crate containing core WASM client functionality and configs" version.workspace = true +authors = ["Jedrzej Stuczynski "] edition = "2021" license = "Apache-2.0" repository = "https://github.com/nymtech/nym" -description = "Crate containing core WASM client functionality and configs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/wasm/storage/Cargo.toml b/common/wasm/storage/Cargo.toml index 7c07592da2..89d53e1b21 100644 --- a/common/wasm/storage/Cargo.toml +++ b/common/wasm/storage/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-wasm-storage" +description = "indexeddb-backed in-browser storage with optional encryption implentation and helpers" version.workspace = true authors = ["Jedrzej Stuczynski "] edition = "2021" license.workspace = true -description = "indexeddb-backed in-browser storage with optional encryption implentation and helpers" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/wasm/utils/Cargo.toml b/common/wasm/utils/Cargo.toml index 49af79aa41..5d11cb98f3 100644 --- a/common/wasm/utils/Cargo.toml +++ b/common/wasm/utils/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "nym-wasm-utils" +description = "Helpers and macros for the Nym WASM client" version.workspace = true authors = ["Jedrzej Stuczynski "] edition = "2021" license.workspace = true -description = "Helpers and macros for the Nym WASM client" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/common/wireguard-private-metadata/client/Cargo.toml b/common/wireguard-private-metadata/client/Cargo.toml index d039810387..f79423ad9e 100644 --- a/common/wireguard-private-metadata/client/Cargo.toml +++ b/common/wireguard-private-metadata/client/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-wireguard-private-metadata-client" +description = "nym-wireguard client implementation" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "nym-wireguard client implementation" [dependencies] async-trait = { workspace = true } diff --git a/common/wireguard-private-metadata/server/Cargo.toml b/common/wireguard-private-metadata/server/Cargo.toml index b16725b149..47961434a6 100644 --- a/common/wireguard-private-metadata/server/Cargo.toml +++ b/common/wireguard-private-metadata/server/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-wireguard-private-metadata-server" +description = "nym-wireguard server implementation" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "nym-wireguard server implementation" [dependencies] anyhow = { workspace = true } diff --git a/common/wireguard-private-metadata/shared/Cargo.toml b/common/wireguard-private-metadata/shared/Cargo.toml index 4c4ffacca8..37038361f9 100644 --- a/common/wireguard-private-metadata/shared/Cargo.toml +++ b/common/wireguard-private-metadata/shared/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-wireguard-private-metadata-shared" +description = "Common crate for nym-wireguard server, client, and tests" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Common crate for nym-wireguard server, client, and tests" [dependencies] axum = { workspace = true } diff --git a/common/wireguard-private-metadata/tests/Cargo.toml b/common/wireguard-private-metadata/tests/Cargo.toml index de8a2ab501..4e0b670d0d 100644 --- a/common/wireguard-private-metadata/tests/Cargo.toml +++ b/common/wireguard-private-metadata/tests/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-wireguard-private-metadata-tests" +description = "Tests for nym-wireguard implementation" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Tests for nym-wireguard implementation" [dependencies] async-trait = { workspace = true } diff --git a/common/wireguard-types/Cargo.toml b/common/wireguard-types/Cargo.toml index 8d271feb0e..57e8491941 100644 --- a/common/wireguard-types/Cargo.toml +++ b/common/wireguard-types/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-wireguard-types" +description = "Wireguard public key and config definitions" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Wireguard public key and config definitions" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/wireguard/Cargo.toml b/common/wireguard/Cargo.toml index f6b3c0e6fb..5269253dd3 100644 --- a/common/wireguard/Cargo.toml +++ b/common/wireguard/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-wireguard" +description = "Interface and peer handling functionality for Wireguard protocol" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Interface and peer handling functionality for Wireguard protocol" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/zulip-client/Cargo.toml b/common/zulip-client/Cargo.toml index 8661cbe247..bef2cc57fc 100644 --- a/common/zulip-client/Cargo.toml +++ b/common/zulip-client/Cargo.toml @@ -2,11 +2,11 @@ name = "zulip-client" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true publish = false diff --git a/contracts/coconut-dkg/Cargo.toml b/contracts/coconut-dkg/Cargo.toml index 66cb2acbe0..f84d51beae 100644 --- a/contracts/coconut-dkg/Cargo.toml +++ b/contracts/coconut-dkg/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "nym-coconut-dkg" version = "0.1.0" -edition = { workspace = true } authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/contracts/ecash/Cargo.toml b/contracts/ecash/Cargo.toml index 6391ebd269..c89e8ee455 100644 --- a/contracts/ecash/Cargo.toml +++ b/contracts/ecash/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "nym-ecash" version = "0.1.0" -edition = { workspace = true } authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/contracts/mixnet-vesting-integration-tests/Cargo.toml b/contracts/mixnet-vesting-integration-tests/Cargo.toml index a1f6aa3104..361885e353 100644 --- a/contracts/mixnet-vesting-integration-tests/Cargo.toml +++ b/contracts/mixnet-vesting-integration-tests/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "mixnet-vesting-integration-tests" version = "0.1.0" -edition = { workspace = true } authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } publish = false diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index e5c7b47719..b629b265c0 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -1,13 +1,12 @@ [package] name = "nym-mixnet-contract" -version = "1.5.1" description = "Nym mixnet contract" -edition = { workspace = true } +version = "1.5.1" authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } readme = "README.md" - exclude = [ # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. "contract.wasm", diff --git a/contracts/multisig/cw3-flex-multisig/Cargo.toml b/contracts/multisig/cw3-flex-multisig/Cargo.toml index e016a5f4c8..f928ee3d18 100644 --- a/contracts/multisig/cw3-flex-multisig/Cargo.toml +++ b/contracts/multisig/cw3-flex-multisig/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "cw3-flex-multisig" +description = "Implementing cw3 with multiple voting patterns and dynamic groups" version = "2.0.0" authors = ["Ethan Frey "] edition = "2021" -description = "Implementing cw3 with multiple voting patterns and dynamic groups" license = "Apache-2.0" repository = "https://github.com/CosmWasm/cw-plus" homepage = "https://cosmwasm.com" diff --git a/contracts/multisig/cw4-group/Cargo.toml b/contracts/multisig/cw4-group/Cargo.toml index b8334b756e..22ee45388c 100644 --- a/contracts/multisig/cw4-group/Cargo.toml +++ b/contracts/multisig/cw4-group/Cargo.toml @@ -1,14 +1,13 @@ [package] name = "cw4-group" +description = "Simple cw4 implementation of group membership controlled by admin " version = "2.0.0" authors = ["Ethan Frey "] edition = "2021" -description = "Simple cw4 implementation of group membership controlled by admin " license = "Apache-2.0" repository = "https://github.com/CosmWasm/cw-plus" homepage = "https://cosmwasm.com" documentation = "https://docs.cosmwasm.com" - exclude = [ # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. "artifacts/*", diff --git a/contracts/nym-pool/Cargo.toml b/contracts/nym-pool/Cargo.toml index f3fc80740e..244f20f52f 100644 --- a/contracts/nym-pool/Cargo.toml +++ b/contracts/nym-pool/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "nym-pool-contract" version = "0.1.0" -edition = { workspace = true } authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/contracts/performance/Cargo.toml b/contracts/performance/Cargo.toml index 72086ad419..ae81ace997 100644 --- a/contracts/performance/Cargo.toml +++ b/contracts/performance/Cargo.toml @@ -2,11 +2,11 @@ name = "nym-performance-contract" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true [[bin]] name = "schema" diff --git a/contracts/vesting/Cargo.toml b/contracts/vesting/Cargo.toml index bc227c5806..a7f590bc0b 100644 --- a/contracts/vesting/Cargo.toml +++ b/contracts/vesting/Cargo.toml @@ -1,13 +1,12 @@ [package] name = "nym-vesting-contract" -version = "1.4.1" description = "Nym vesting contract" -edition = { workspace = true } +version = "1.4.1" authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } readme = "README.md" - exclude = [ # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. "contract.wasm", diff --git a/cpu-cycles/Cargo.toml b/cpu-cycles/Cargo.toml index 4c234b8d30..1ccdd3f504 100644 --- a/cpu-cycles/Cargo.toml +++ b/cpu-cycles/Cargo.toml @@ -2,9 +2,9 @@ name = "cpu-cycles" version = "0.1.0" edition = "2021" +license = "LicenseRef-PD-hp OR CC0-1.0 OR 0BSD OR MIT-0 OR MIT" build = "build.rs" links = "cpucycles" -license = "LicenseRef-PD-hp OR CC0-1.0 OR 0BSD OR MIT-0 OR MIT" [dependencies] libc = "0.2.140" diff --git a/documentation/autodoc/Cargo.toml b/documentation/autodoc/Cargo.toml index 1905285f99..6586cdd256 100644 --- a/documentation/autodoc/Cargo.toml +++ b/documentation/autodoc/Cargo.toml @@ -2,11 +2,11 @@ name = "autodoc" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true publish = false [dependencies] diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index 51e3c98c6c..d5c76b9b54 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -3,14 +3,14 @@ [package] name = "nym-gateway" -license = "GPL-3.0" +description = "Implementation of the Nym Mixnet Gateway" version = "1.1.36" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", ] -description = "Implementation of the Nym Mixnet Gateway" edition = "2021" +license = "GPL-3.0" rust-version = "1.85" publish = false diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index aaeced8b6d..9f7fe77d06 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -2,11 +2,11 @@ name = "integration-tests" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true publish = false diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 8ce67d316a..446d463ce9 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -3,10 +3,10 @@ [package] name = "nym-api" -license = "GPL-3.0" version = "1.1.77" authors.workspace = true edition = "2021" +license = "GPL-3.0" rust-version.workspace = true publish = false diff --git a/nym-api/nym-api-requests/Cargo.toml b/nym-api/nym-api-requests/Cargo.toml index 176eb0920f..164002a3a2 100644 --- a/nym-api/nym-api-requests/Cargo.toml +++ b/nym-api/nym-api-requests/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-api-requests" +description = "Nym API request types and functions" version.workspace = true edition = "2021" license.workspace = true -description = "Nym API request types and functions" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/nym-authenticator-client/Cargo.toml b/nym-authenticator-client/Cargo.toml index b1793b6cbf..b502237316 100644 --- a/nym-authenticator-client/Cargo.toml +++ b/nym-authenticator-client/Cargo.toml @@ -2,11 +2,11 @@ name = "nym-authenticator-client" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true publish = false [lints] diff --git a/nym-browser-extension/storage/Cargo.toml b/nym-browser-extension/storage/Cargo.toml index e25c1b107f..5ee0d1b961 100644 --- a/nym-browser-extension/storage/Cargo.toml +++ b/nym-browser-extension/storage/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "extension-storage" +description = "WebAssembly-based secure storage for browser extension mnemonics" version = "1.4.1" +authors = ["Nym Technologies SA "] edition = "2024" license = "Apache-2.0" repository = "https://github.com/nymtech/nym" -description = "WebAssembly-based secure storage for browser extension mnemonics" -authors = ["Nym Technologies SA "] publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nym-credential-proxy/nym-credential-proxy-requests/Cargo.toml b/nym-credential-proxy/nym-credential-proxy-requests/Cargo.toml index d81b35e70b..4891c86c81 100644 --- a/nym-credential-proxy/nym-credential-proxy-requests/Cargo.toml +++ b/nym-credential-proxy/nym-credential-proxy-requests/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-credential-proxy-requests" +description = "Request and response definitions for interacting with the Nym Credential Proxy" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Request and response definitions for interacting with the Nym Credential Proxy" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nym-credential-proxy/nym-credential-proxy/Cargo.toml b/nym-credential-proxy/nym-credential-proxy/Cargo.toml index 9a680358a7..4354534ee3 100644 --- a/nym-credential-proxy/nym-credential-proxy/Cargo.toml +++ b/nym-credential-proxy/nym-credential-proxy/Cargo.toml @@ -2,11 +2,11 @@ name = "nym-credential-proxy" version = "0.3.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true publish = false diff --git a/nym-data-observatory/Cargo.toml b/nym-data-observatory/Cargo.toml index 4a6a09685b..906f8dd651 100644 --- a/nym-data-observatory/Cargo.toml +++ b/nym-data-observatory/Cargo.toml @@ -5,11 +5,11 @@ name = "nym-data-observatory" version = "1.0.1" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true publish = false diff --git a/nym-gateway-probe/Cargo.toml b/nym-gateway-probe/Cargo.toml index 684f54a288..7cb0bf8575 100644 --- a/nym-gateway-probe/Cargo.toml +++ b/nym-gateway-probe/Cargo.toml @@ -2,11 +2,11 @@ name = "nym-gateway-probe" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true publish = false [lints] diff --git a/nym-ip-packet-client/Cargo.toml b/nym-ip-packet-client/Cargo.toml index e631a759ca..c213107871 100644 --- a/nym-ip-packet-client/Cargo.toml +++ b/nym-ip-packet-client/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-ip-packet-client" +description = "Nym's implementation of a client that sends and receives IP packets" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Nym's implementation of a client that sends and receives IP packets" [lints] workspace = true diff --git a/nym-network-monitor/Cargo.toml b/nym-network-monitor/Cargo.toml index 5f68dec06e..eba4bd06d9 100644 --- a/nym-network-monitor/Cargo.toml +++ b/nym-network-monitor/Cargo.toml @@ -2,11 +2,11 @@ name = "nym-network-monitor" version = "1.0.2" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nym-node-status-api/nym-node-status-agent/Cargo.toml b/nym-node-status-api/nym-node-status-agent/Cargo.toml index 653bda4b95..6171d7c927 100644 --- a/nym-node-status-api/nym-node-status-agent/Cargo.toml +++ b/nym-node-status-api/nym-node-status-agent/Cargo.toml @@ -5,11 +5,11 @@ name = "nym-node-status-agent" version = "2.0.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true publish = false diff --git a/nym-node-status-api/nym-node-status-api/Cargo.toml b/nym-node-status-api/nym-node-status-api/Cargo.toml index 2f534a1f7c..52a521897a 100644 --- a/nym-node-status-api/nym-node-status-api/Cargo.toml +++ b/nym-node-status-api/nym-node-status-api/Cargo.toml @@ -5,11 +5,11 @@ name = "nym-node-status-api" version = "4.5.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true publish = false diff --git a/nym-node-status-api/nym-node-status-client/Cargo.toml b/nym-node-status-api/nym-node-status-client/Cargo.toml index 8bd8541f55..63272148a1 100644 --- a/nym-node-status-api/nym-node-status-client/Cargo.toml +++ b/nym-node-status-api/nym-node-status-client/Cargo.toml @@ -5,11 +5,11 @@ name = "nym-node-status-client" version = "0.3.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true publish = false diff --git a/nym-node/Cargo.toml b/nym-node/Cargo.toml index 1cd66c1de3..6d41224654 100644 --- a/nym-node/Cargo.toml +++ b/nym-node/Cargo.toml @@ -5,11 +5,11 @@ name = "nym-node" version = "1.29.0" authors.workspace = true +edition.workspace = true +license = "GPL-3.0" repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license = "GPL-3.0" publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nym-node/nym-node-metrics/Cargo.toml b/nym-node/nym-node-metrics/Cargo.toml index 28b32ac5e8..9ccabdcffb 100644 --- a/nym-node/nym-node-metrics/Cargo.toml +++ b/nym-node/nym-node-metrics/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-node-metrics" +description = "Crate defining various metrics for Nym Nodes (Mix Nodes and Gateways) such as ongoing connections, packets mixed, and packets dropped" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Crate defining various metrics for Nym Nodes (Mix Nodes and Gateways) such as ongoing connections, packets mixed, and packets dropped" [dependencies] dashmap = { workspace = true } diff --git a/nym-node/nym-node-requests/Cargo.toml b/nym-node/nym-node-requests/Cargo.toml index b051086220..eb0bcbc77c 100644 --- a/nym-node/nym-node-requests/Cargo.toml +++ b/nym-node/nym-node-requests/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-node-requests" +description = "Nym Node API endpoint definitions and functions" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Nym Node API endpoint definitions and functions" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nym-outfox/Cargo.toml b/nym-outfox/Cargo.toml index d3ea59291d..b7b6600941 100644 --- a/nym-outfox/Cargo.toml +++ b/nym-outfox/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-outfox" -version.workspace = true description = "Outfox package format" -edition = { workspace = true } +version.workspace = true authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/nym-registration-client/Cargo.toml b/nym-registration-client/Cargo.toml index a1c3aa335a..0a7e845864 100644 --- a/nym-registration-client/Cargo.toml +++ b/nym-registration-client/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-registration-client" +description = "Crate for dealing with Mixnet and Wireguard registration between Nym clients and Gateways" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true -description = "Crate for dealing with Mixnet and Wireguard registration between Nym clients and Gateways" publish = false [lints] diff --git a/nym-signers-monitor/Cargo.toml b/nym-signers-monitor/Cargo.toml index 56adfc4ac5..265ee22192 100644 --- a/nym-signers-monitor/Cargo.toml +++ b/nym-signers-monitor/Cargo.toml @@ -2,11 +2,11 @@ name = "nym-signers-monitor" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true publish = false diff --git a/nym-sqlx-pool-guard/Cargo.toml b/nym-sqlx-pool-guard/Cargo.toml index 3eecfffb99..fe899cd057 100644 --- a/nym-sqlx-pool-guard/Cargo.toml +++ b/nym-sqlx-pool-guard/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sqlx-pool-guard" +description = "Platform-specific functions for SQLX dbs" version.workspace = true edition = "2024" license.workspace = true -description = "Platform-specific functions for SQLX dbs" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/nym-statistics-api/Cargo.toml b/nym-statistics-api/Cargo.toml index d603503585..e826ca90ac 100644 --- a/nym-statistics-api/Cargo.toml +++ b/nym-statistics-api/Cargo.toml @@ -5,11 +5,11 @@ name = "nym-statistics-api" version = "0.3.1" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true publish = false diff --git a/nym-validator-rewarder/Cargo.toml b/nym-validator-rewarder/Cargo.toml index bf2fc671f8..66de013893 100644 --- a/nym-validator-rewarder/Cargo.toml +++ b/nym-validator-rewarder/Cargo.toml @@ -2,11 +2,11 @@ name = "nym-validator-rewarder" version = "0.3.0" authors.workspace = true +edition.workspace = true +license = "GPL-3.0" repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license = "GPL-3.0" publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nym-wallet/nym-wallet-types/Cargo.toml b/nym-wallet/nym-wallet-types/Cargo.toml index b07382912a..d91f8e8761 100644 --- a/nym-wallet/nym-wallet-types/Cargo.toml +++ b/nym-wallet/nym-wallet-types/Cargo.toml @@ -2,8 +2,8 @@ name = "nym-wallet-types" version = "1.0.0" edition = "2021" -rust-version = "1.85" license = "Apache-2.0" +rust-version = "1.85" [dependencies] hex-literal = "0.3.3" diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index ace8911a78..f2385aa02f 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "NymWallet" -version = "1.2.19" description = "Nym Native Wallet" +version = "1.2.19" authors = ["Nym Technologies SA"] +edition = "2021" license = "" repository = "" -default-run = "NymWallet" -edition = "2021" -build = "src/build.rs" rust-version = "1.85" +default-run = "NymWallet" +build = "src/build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nyx-chain-watcher/Cargo.toml b/nyx-chain-watcher/Cargo.toml index e8f2b4b2e0..04c7b41793 100644 --- a/nyx-chain-watcher/Cargo.toml +++ b/nyx-chain-watcher/Cargo.toml @@ -5,11 +5,11 @@ name = "nyx-chain-watcher" version = "0.1.15" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true publish = false diff --git a/sdk/ffi/cpp/Cargo.toml b/sdk/ffi/cpp/Cargo.toml index 307f669a15..8422564362 100644 --- a/sdk/ffi/cpp/Cargo.toml +++ b/sdk/ffi/cpp/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "nym-cpp-ffi" +description = "C++ FFI bindings for Nym Rust SDK" version.workspace = true edition = "2021" +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -license.workspace = true -description = "C++ FFI bindings for Nym Rust SDK" [lib] name = "nym_cpp_ffi" diff --git a/sdk/ffi/go/Cargo.toml b/sdk/ffi/go/Cargo.toml index 76b1e91a57..88fd0e33ab 100644 --- a/sdk/ffi/go/Cargo.toml +++ b/sdk/ffi/go/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "nym-go-ffi" +description = "Go FFI bindings for Nym Rust SDK" version.workspace = true edition = "2021" +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -license.workspace = true -description = "Go FFI bindings for Nym Rust SDK" [lib] crate-type = ["cdylib"] diff --git a/sdk/ffi/shared/Cargo.toml b/sdk/ffi/shared/Cargo.toml index d5e3434892..f99d2a5aa6 100644 --- a/sdk/ffi/shared/Cargo.toml +++ b/sdk/ffi/shared/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "nym-ffi-shared" +description = "Common crate for use by Rust SDK FFI crates" version.workspace = true edition = "2021" +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -license.workspace = true -description = "Common crate for use by Rust SDK FFI crates" [dependencies] # Async runtime diff --git a/sdk/rust/nym-sdk/Cargo.toml b/sdk/rust/nym-sdk/Cargo.toml index 9fddca8295..5ccc260b8c 100644 --- a/sdk/rust/nym-sdk/Cargo.toml +++ b/sdk/rust/nym-sdk/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-sdk" +description = "Nym's Rust SDK" version.workspace = true edition = "2021" license.workspace = true -description = "Nym's Rust SDK" repository = "https://github.com/nymtech/nym/sdk/rust/nym-sdk/" # documentation = "https://docs.rs/nym-sdk" Max: once we upload to crates.io and this is generated, this can be uncommented. diff --git a/service-providers/common/Cargo.toml b/service-providers/common/Cargo.toml index 93661af48f..b610c737d0 100644 --- a/service-providers/common/Cargo.toml +++ b/service-providers/common/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "nym-service-providers-common" +description = "Common crate for Nym Service Providers" version.workspace = true edition = "2021" license.workspace = true -description = "Common crate for Nym Service Providers" repository.workspace = true homepage.workspace = true documentation.workspace = true diff --git a/service-providers/ip-packet-router/Cargo.toml b/service-providers/ip-packet-router/Cargo.toml index 956205f8b5..8c05b495e7 100644 --- a/service-providers/ip-packet-router/Cargo.toml +++ b/service-providers/ip-packet-router/Cargo.toml @@ -2,11 +2,11 @@ name = "nym-ip-packet-router" version.workspace = true authors.workspace = true +edition.workspace = true +license = "GPL-3.0" repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license = "GPL-3.0" publish = false [dependencies] diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 426c6a6b22..91b0ca6f5e 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -3,10 +3,10 @@ [package] name = "nym-network-requester" -license = "GPL-3.0" version = "1.1.75" authors.workspace = true edition.workspace = true +license = "GPL-3.0" rust-version = "1.85" publish = false diff --git a/smolmix/core/Cargo.toml b/smolmix/core/Cargo.toml index aee3249372..93acc1ed8b 100644 --- a/smolmix/core/Cargo.toml +++ b/smolmix/core/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "smolmix" -publish = true -repository.workspace = true description = "Tunnel for TCP and UDP traffic to be sent over Nym mixnet to clearnet remote hosts" version = "0.0.1" edition = "2021" license.workspace = true +repository.workspace = true +publish = true [dependencies] smoltcp = { workspace = true, features = [ diff --git a/tools/echo-server/Cargo.toml b/tools/echo-server/Cargo.toml index 4f9ec4de02..73f57d986d 100644 --- a/tools/echo-server/Cargo.toml +++ b/tools/echo-server/Cargo.toml @@ -2,11 +2,11 @@ name = "echo-server" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true publish = false diff --git a/tools/internal/contract-state-importer/importer-cli/Cargo.toml b/tools/internal/contract-state-importer/importer-cli/Cargo.toml index 143b18ffbb..63e0aa5b3d 100644 --- a/tools/internal/contract-state-importer/importer-cli/Cargo.toml +++ b/tools/internal/contract-state-importer/importer-cli/Cargo.toml @@ -2,11 +2,11 @@ name = "importer-cli" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true publish = false diff --git a/tools/internal/contract-state-importer/importer-contract/Cargo.toml b/tools/internal/contract-state-importer/importer-contract/Cargo.toml index 72f0476206..99290faff4 100644 --- a/tools/internal/contract-state-importer/importer-contract/Cargo.toml +++ b/tools/internal/contract-state-importer/importer-contract/Cargo.toml @@ -2,11 +2,11 @@ name = "importer-contract" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true readme.workspace = true publish = false diff --git a/tools/internal/localnet-orchestrator/Cargo.toml b/tools/internal/localnet-orchestrator/Cargo.toml index 7aef726f07..8d6421cb3f 100644 --- a/tools/internal/localnet-orchestrator/Cargo.toml +++ b/tools/internal/localnet-orchestrator/Cargo.toml @@ -2,11 +2,11 @@ name = "localnet-orchestrator" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true publish = false diff --git a/tools/internal/localnet-orchestrator/dkg-bypass-contract/Cargo.toml b/tools/internal/localnet-orchestrator/dkg-bypass-contract/Cargo.toml index 5074d8d91f..895f133786 100644 --- a/tools/internal/localnet-orchestrator/dkg-bypass-contract/Cargo.toml +++ b/tools/internal/localnet-orchestrator/dkg-bypass-contract/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "dkg-bypass-contract" version = "0.1.0" -edition = { workspace = true } authors = { workspace = true } +edition = { workspace = true } license = { workspace = true } repository = { workspace = true } publish = false diff --git a/tools/internal/mixnet-connectivity-check/Cargo.toml b/tools/internal/mixnet-connectivity-check/Cargo.toml index 9d2d36c9d8..34210518c4 100644 --- a/tools/internal/mixnet-connectivity-check/Cargo.toml +++ b/tools/internal/mixnet-connectivity-check/Cargo.toml @@ -2,11 +2,11 @@ name = "mixnet-connectivity-check" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true publish = false diff --git a/tools/internal/sdk-version-bump/Cargo.toml b/tools/internal/sdk-version-bump/Cargo.toml index ba51b1caf6..e53edbda65 100644 --- a/tools/internal/sdk-version-bump/Cargo.toml +++ b/tools/internal/sdk-version-bump/Cargo.toml @@ -2,11 +2,11 @@ name = "sdk-version-bump" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/internal/validator-status-check/Cargo.toml b/tools/internal/validator-status-check/Cargo.toml index 7b335095b7..774b5c4cbb 100644 --- a/tools/internal/validator-status-check/Cargo.toml +++ b/tools/internal/validator-status-check/Cargo.toml @@ -2,11 +2,11 @@ name = "validator-status-check" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true rust-version.workspace = true readme.workspace = true publish = false diff --git a/tools/nym-id-cli/Cargo.toml b/tools/nym-id-cli/Cargo.toml index 7d264bb2e8..f718450ac0 100644 --- a/tools/nym-id-cli/Cargo.toml +++ b/tools/nym-id-cli/Cargo.toml @@ -2,11 +2,11 @@ name = "nym-id-cli" version = "0.1.0" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/nym-lp-client/Cargo.toml b/tools/nym-lp-client/Cargo.toml index e91e052662..c33b04f366 100644 --- a/tools/nym-lp-client/Cargo.toml +++ b/tools/nym-lp-client/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "nym-lp-client" +description = "LP+KCP mixnet client" version = "0.1.0" edition = "2021" -description = "LP+KCP mixnet client" license.workspace = true publish = false diff --git a/tools/nymvisor/Cargo.toml b/tools/nymvisor/Cargo.toml index a99cb29472..f61d3c10b9 100644 --- a/tools/nymvisor/Cargo.toml +++ b/tools/nymvisor/Cargo.toml @@ -2,11 +2,11 @@ name = "nymvisor" version = "0.1.39" authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/wasm/client/Cargo.toml b/wasm/client/Cargo.toml index 2377ddcb6d..eed416767b 100644 --- a/wasm/client/Cargo.toml +++ b/wasm/client/Cargo.toml @@ -1,17 +1,17 @@ [package] name = "nym-client-wasm" +description = "A webassembly client which can be used to interact with the the Nym privacy platform. Wasm is used for Sphinx packet generation." +version = "1.4.1" authors = [ "Dave Hrycyszyn ", "Jedrzej Stuczynski ", ] -version = "1.4.1" edition = "2021" -keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"] license = "Apache-2.0" repository = "https://github.com/nymtech/nym" -description = "A webassembly client which can be used to interact with the the Nym privacy platform. Wasm is used for Sphinx packet generation." rust-version = "1.85" publish = false +keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"] [lib] crate-type = ["cdylib", "rlib"] diff --git a/wasm/full-nym-wasm/Cargo.toml b/wasm/full-nym-wasm/Cargo.toml index f3a7357e6c..ee6aadf5fe 100644 --- a/wasm/full-nym-wasm/Cargo.toml +++ b/wasm/full-nym-wasm/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-wasm-sdk" -authors = ["Jedrzej Stuczynski "] version = "1.2.2" +authors = ["Jedrzej Stuczynski "] edition = "2021" -keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"] license = "Apache-2.0" repository = "https://github.com/nymtech/nym" rust-version = "1.85" publish = false +keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/wasm/mix-fetch/Cargo.toml b/wasm/mix-fetch/Cargo.toml index 9573365b4d..8fca01cdc8 100644 --- a/wasm/mix-fetch/Cargo.toml +++ b/wasm/mix-fetch/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "mix-fetch-wasm" -authors = ["Jedrzej Stuczynski "] version = "1.4.3" +authors = ["Jedrzej Stuczynski "] edition = "2021" -keywords = ["nym", "fetch", "wasm", "webassembly", "privacy"] license = "Apache-2.0" repository = "https://github.com/nymtech/nym" rust-version = "1.85" publish = false +keywords = ["nym", "fetch", "wasm", "webassembly", "privacy"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/wasm/node-tester/Cargo.toml b/wasm/node-tester/Cargo.toml index 8a61eb06ab..88e7e5b9a5 100644 --- a/wasm/node-tester/Cargo.toml +++ b/wasm/node-tester/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nym-node-tester-wasm" -authors = ["Jedrzej Stuczynski "] version = "1.3.1" +authors = ["Jedrzej Stuczynski "] edition = "2021" -keywords = ["nym", "sphinx", "webassembly", "privacy", "tester"] license = "Apache-2.0" repository = "https://github.com/nymtech/nym" rust-version = "1.85" publish = false +keywords = ["nym", "sphinx", "webassembly", "privacy", "tester"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/wasm/zknym-lib/Cargo.toml b/wasm/zknym-lib/Cargo.toml index 385ed467f1..23cc1f50ea 100644 --- a/wasm/zknym-lib/Cargo.toml +++ b/wasm/zknym-lib/Cargo.toml @@ -2,11 +2,11 @@ name = "zknym-lib" version.workspace = true authors.workspace = true +edition.workspace = true +license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -edition.workspace = true -license.workspace = true publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From 6ee1f16ce892bdc3eab2c997a64af48b8d505f0f Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Fri, 17 Apr 2026 08:17:18 +0100 Subject: [PATCH 15/37] Canonical ordering lefthook checker --- lefthook.yml | 3 ++ nym-wallet/src-tauri/Cargo.toml | 2 +- .../internal/check_cargo_toml_field_order.py | 42 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 tools/internal/check_cargo_toml_field_order.py diff --git a/lefthook.yml b/lefthook.yml index 0687e78972..27c29ce3a2 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -51,3 +51,6 @@ pre-commit: glob: "*.rs" run: cargo fmt stage_fixed: true + cargo-toml-order: + glob: "**/Cargo.toml" + run: python3 tools/internal/check_cargo_toml_field_order.py {staged_files} diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index f2385aa02f..1a17b80962 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -7,8 +7,8 @@ edition = "2021" license = "" repository = "" rust-version = "1.85" -default-run = "NymWallet" build = "src/build.rs" +default-run = "NymWallet" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/internal/check_cargo_toml_field_order.py b/tools/internal/check_cargo_toml_field_order.py new file mode 100644 index 0000000000..b91fd62682 --- /dev/null +++ b/tools/internal/check_cargo_toml_field_order.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""Check that [package] fields in Cargo.toml follow canonical ordering.""" +import re, sys + +ORDER = [ + "name", "description", "version", "authors", "edition", "license", + "repository", "homepage", "documentation", "rust-version", "readme", + "publish", "keywords", "exclude", "build", "links", "default-run", + "resolver", +] + +bad = [] +for path in sys.argv[1:]: + fields, in_pkg = [], False + for line in open(path): + s = line.strip() + if s == "[package]": + in_pkg = True + continue + if in_pkg and s.startswith("["): + break + if in_pkg: + m = re.match(r"^(\w[\w-]*)", s) + if m and "=" in line: + fields.append(m.group(1)) + unknown = [f for f in fields if f not in ORDER] + if unknown: + bad.append((path, f"unknown field(s): {', '.join(unknown)}")) + continue + expected = sorted(fields, key=ORDER.index) + if fields != expected: + first = next(a for a, b in zip(fields, expected) if a != b) + bad.append((path, f"first mismatch: '{first}'")) + +if bad: + print("[package] fields out of canonical order:") + for path, reason in bad: + print(f" {path} ({reason})") + print("\nCanonical order:") + for f in ORDER: + print(f" - {f}") + sys.exit(1) From dd6a45f25152ecc3ead77fd4df54db3cc1b0bd3c Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Fri, 17 Apr 2026 09:23:55 +0100 Subject: [PATCH 16/37] Make publication explicit --- clients/native/websocket-requests/Cargo.toml | 3 ++ common/async-file-watcher/Cargo.toml | 4 +++ common/authenticator-requests/Cargo.toml | 3 ++ common/bandwidth-controller/Cargo.toml | 4 +++ common/bin-common/Cargo.toml | 5 +++ common/client-core/Cargo.toml | 2 ++ common/client-core/config-types/Cargo.toml | 4 +++ .../client-core/gateways-storage/Cargo.toml | 3 ++ common/client-core/surb-storage/Cargo.toml | 4 +++ common/client-libs/gateway-client/Cargo.toml | 3 ++ common/client-libs/mixnet-client/Cargo.toml | 3 ++ .../client-libs/validator-client/Cargo.toml | 2 ++ common/commands/Cargo.toml | 3 ++ common/config/Cargo.toml | 4 +++ .../coconut-dkg/Cargo.toml | 4 +++ .../contracts-common-testing/Cargo.toml | 1 + .../contracts-common/Cargo.toml | 5 +++ .../ecash-contract/Cargo.toml | 4 +++ .../group-contract/Cargo.toml | 4 +++ .../mixnet-contract/Cargo.toml | 4 +++ .../multisig-contract/Cargo.toml | 5 +++ .../nym-performance-contract/Cargo.toml | 1 + .../nym-pool-contract/Cargo.toml | 1 + .../vesting-contract/Cargo.toml | 5 +++ common/credential-proxy/Cargo.toml | 1 + common/credential-storage/Cargo.toml | 3 ++ common/credential-utils/Cargo.toml | 4 +++ common/credential-verification/Cargo.toml | 1 + common/credentials-interface/Cargo.toml | 3 ++ common/credentials/Cargo.toml | 4 +++ common/crypto/Cargo.toml | 5 +++ common/dkg/Cargo.toml | 4 +++ common/ecash-signer-check-types/Cargo.toml | 1 + common/ecash-signer-check/Cargo.toml | 1 + common/ecash-time/Cargo.toml | 3 ++ common/exit-policy/Cargo.toml | 3 ++ common/gateway-requests/Cargo.toml | 3 ++ common/gateway-stats-storage/Cargo.toml | 2 ++ common/gateway-storage/Cargo.toml | 2 ++ common/http-api-client-macro/Cargo.toml | 1 + common/http-api-client/Cargo.toml | 3 ++ common/http-api-common/Cargo.toml | 3 ++ common/inclusion-probability/Cargo.toml | 5 +++ common/ip-packet-requests/Cargo.toml | 3 ++ common/mixnode-common/Cargo.toml | 3 ++ common/network-defaults/Cargo.toml | 5 +++ common/node-tester-utils/Cargo.toml | 4 +++ common/nonexhaustive-delayqueue/Cargo.toml | 3 ++ common/nym-cache/Cargo.toml | 1 + common/nym-common/Cargo.toml | 5 +++ common/nym-id/Cargo.toml | 3 ++ common/nym-kkt/Cargo.toml | 4 +++ common/nym-metrics/Cargo.toml | 3 ++ common/nym_offline_compact_ecash/Cargo.toml | 3 ++ common/nymnoise/Cargo.toml | 3 ++ common/nymnoise/keys/Cargo.toml | 3 ++ common/nymsphinx/Cargo.toml | 5 +++ common/nymsphinx/acknowledgements/Cargo.toml | 5 +++ common/nymsphinx/addressing/Cargo.toml | 5 +++ common/nymsphinx/anonymous-replies/Cargo.toml | 5 +++ common/nymsphinx/chunking/Cargo.toml | 5 +++ common/nymsphinx/cover/Cargo.toml | 5 +++ common/nymsphinx/forwarding/Cargo.toml | 5 +++ common/nymsphinx/framing/Cargo.toml | 5 +++ common/nymsphinx/params/Cargo.toml | 5 +++ common/nymsphinx/routing/Cargo.toml | 5 +++ common/nymsphinx/types/Cargo.toml | 5 +++ common/nyxd-scraper-shared/Cargo.toml | 1 + common/pemstore/Cargo.toml | 5 +++ common/registration/Cargo.toml | 3 ++ common/serde-helpers/Cargo.toml | 3 ++ .../Cargo.toml | 1 + common/socks5-client-core/Cargo.toml | 4 +++ common/socks5/ordered-buffer/Cargo.toml | 3 ++ common/socks5/proxy-helpers/Cargo.toml | 3 ++ common/socks5/requests/Cargo.toml | 3 ++ common/statistics/Cargo.toml | 4 +++ common/store-cipher/Cargo.toml | 4 +++ common/task/Cargo.toml | 5 +++ common/test-utils/Cargo.toml | 1 + common/ticketbooks-merkle/Cargo.toml | 1 + common/topology/Cargo.toml | 3 ++ common/tun/Cargo.toml | 3 ++ common/types/Cargo.toml | 2 ++ common/upgrade-mode-check/Cargo.toml | 1 + common/verloc/Cargo.toml | 1 + common/wasm/client-core/Cargo.toml | 5 +++ common/wasm/storage/Cargo.toml | 3 ++ common/wasm/utils/Cargo.toml | 3 ++ .../client/Cargo.toml | 3 ++ .../server/Cargo.toml | 3 ++ .../shared/Cargo.toml | 3 ++ .../tests/Cargo.toml | 3 ++ common/wireguard-types/Cargo.toml | 3 ++ common/wireguard/Cargo.toml | 3 ++ contracts/coconut-dkg/Cargo.toml | 1 + contracts/ecash/Cargo.toml | 1 + contracts/mixnet/Cargo.toml | 1 + .../multisig/cw3-flex-multisig/Cargo.toml | 1 + contracts/multisig/cw4-group/Cargo.toml | 1 + contracts/nym-pool/Cargo.toml | 1 + contracts/performance/Cargo.toml | 1 + contracts/vesting/Cargo.toml | 1 + cpu-cycles/Cargo.toml | 1 + .../cli/commands/verify-signature/Cargo.toml | 1 + nym-api/nym-api-requests/Cargo.toml | 4 +++ .../nym-credential-proxy-requests/Cargo.toml | 3 ++ nym-ip-packet-client/Cargo.toml | 3 ++ nym-node/nym-node-metrics/Cargo.toml | 3 ++ nym-node/nym-node-requests/Cargo.toml | 3 ++ nym-outfox/Cargo.toml | 5 +++ nym-sqlx-pool-guard/Cargo.toml | 4 +++ nym-wallet/nym-wallet-recovery-cli/Cargo.toml | 1 + nym-wallet/nym-wallet-types/Cargo.toml | 1 + nym-wallet/src-tauri/Cargo.toml | 1 + sdk/ffi/cpp/Cargo.toml | 4 +++ sdk/ffi/go/Cargo.toml | 4 +++ sdk/ffi/shared/Cargo.toml | 4 +++ sdk/rust/nym-sdk/Cargo.toml | 6 ++++ service-providers/common/Cargo.toml | 4 +++ smolmix/core/Cargo.toml | 5 +++ .../internal/check_cargo_toml_field_order.py | 34 ++++++++++++++++--- tools/internal/sdk-version-bump/Cargo.toml | 1 + 123 files changed, 406 insertions(+), 5 deletions(-) diff --git a/clients/native/websocket-requests/Cargo.toml b/clients/native/websocket-requests/Cargo.toml index 51e352dec4..ae232bd83c 100644 --- a/clients/native/websocket-requests/Cargo.toml +++ b/clients/native/websocket-requests/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/async-file-watcher/Cargo.toml b/common/async-file-watcher/Cargo.toml index 97ab6f6f86..1a8e3a4b87 100644 --- a/common/async-file-watcher/Cargo.toml +++ b/common/async-file-watcher/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-async-file-watcher" description = "Simple file watcher that sends a notification whenever there was any change in the watched file" version.workspace = true +authors.workspace = true edition.workspace = true license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/authenticator-requests/Cargo.toml b/common/authenticator-requests/Cargo.toml index c0cd0a34c5..27d3fcfc6e 100644 --- a/common/authenticator-requests/Cargo.toml +++ b/common/authenticator-requests/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] base64 = { workspace = true } diff --git a/common/bandwidth-controller/Cargo.toml b/common/bandwidth-controller/Cargo.toml index a4ba0986ac..228442a053 100644 --- a/common/bandwidth-controller/Cargo.toml +++ b/common/bandwidth-controller/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-bandwidth-controller" description = "Crate for controlling the use of zknym credentials to ensure constant bandwidth availability for NymVPN app" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/bin-common/Cargo.toml b/common/bin-common/Cargo.toml index 80570659a4..db389c8a4c 100644 --- a/common/bin-common/Cargo.toml +++ b/common/bin-common/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] clap = { workspace = true, features = ["derive"], optional = true } diff --git a/common/client-core/Cargo.toml b/common/client-core/Cargo.toml index 6f8dbb6f67..351ed58fc8 100644 --- a/common/client-core/Cargo.toml +++ b/common/client-core/Cargo.toml @@ -9,6 +9,8 @@ repository.workspace = true homepage.workspace = true documentation.workspace = true rust-version = "1.85" +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/client-core/config-types/Cargo.toml b/common/client-core/config-types/Cargo.toml index af3b60d7f4..9236820211 100644 --- a/common/client-core/config-types/Cargo.toml +++ b/common/client-core/config-types/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-client-core-config-types" description = "Low level configs and constants used by Nym clients and nodes" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/client-core/gateways-storage/Cargo.toml b/common/client-core/gateways-storage/Cargo.toml index 18fede97b8..e788467688 100644 --- a/common/client-core/gateways-storage/Cargo.toml +++ b/common/client-core/gateways-storage/Cargo.toml @@ -2,12 +2,15 @@ name = "nym-client-core-gateways-storage" description = "Functionality for Nym clients to store and retrive Gateway connections" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/client-core/surb-storage/Cargo.toml b/common/client-core/surb-storage/Cargo.toml index d73b32a67a..6bb6c2f965 100644 --- a/common/client-core/surb-storage/Cargo.toml +++ b/common/client-core/surb-storage/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-client-core-surb-storage" description = "Functionality for Nym clients to generate and use Single Use Reply Blocks (SURBs)" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/client-libs/gateway-client/Cargo.toml b/common/client-libs/gateway-client/Cargo.toml index 06803c67ef..8a9a3157f2 100644 --- a/common/client-libs/gateway-client/Cargo.toml +++ b/common/client-libs/gateway-client/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/client-libs/mixnet-client/Cargo.toml b/common/client-libs/mixnet-client/Cargo.toml index 59cc416cdd..614e4e698e 100644 --- a/common/client-libs/mixnet-client/Cargo.toml +++ b/common/client-libs/mixnet-client/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index 4f5ca7a43c..ea1de63563 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -9,6 +9,8 @@ repository.workspace = true homepage.workspace = true documentation.workspace = true rust-version = "1.85" +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/commands/Cargo.toml b/common/commands/Cargo.toml index 0eccd1194c..53b29b842f 100644 --- a/common/commands/Cargo.toml +++ b/common/commands/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] anyhow = { workspace = true } diff --git a/common/config/Cargo.toml b/common/config/Cargo.toml index 7b618d0e77..6e34d07d41 100644 --- a/common/config/Cargo.toml +++ b/common/config/Cargo.toml @@ -7,6 +7,10 @@ edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml b/common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml index adfbddd5e1..bea9907df1 100644 --- a/common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml +++ b/common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-coconut-dkg-common" description = "Common crate for Nym's DKG cosmwasm contract" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/cosmwasm-smart-contracts/contracts-common-testing/Cargo.toml b/common/cosmwasm-smart-contracts/contracts-common-testing/Cargo.toml index eebc0e0d76..b2940bb474 100644 --- a/common/cosmwasm-smart-contracts/contracts-common-testing/Cargo.toml +++ b/common/cosmwasm-smart-contracts/contracts-common-testing/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] anyhow = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml b/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml index 787cd43bd4..10e838b621 100644 --- a/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml +++ b/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] bs58 = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml b/common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml index 0c6f060a1e..49e2be8c60 100644 --- a/common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-ecash-contract-common" description = "Common crate for Nym's ecash/zknym cosmwasm contract" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/cosmwasm-smart-contracts/group-contract/Cargo.toml b/common/cosmwasm-smart-contracts/group-contract/Cargo.toml index c76b813a6b..2306376d56 100644 --- a/common/cosmwasm-smart-contracts/group-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/group-contract/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-group-contract-common" description = "Common crate for Nym's group cosmwasm contract" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] cosmwasm-schema = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml index 5a8a31ee44..b53e1d3420 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml @@ -6,7 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true rust-version = "1.85" +readme.workspace = true +publish = true [dependencies] bs58 = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml index 44d368a817..a489eb4298 100644 --- a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml @@ -2,10 +2,15 @@ name = "nym-multisig-contract-common" description = "Common code for the Nym multisig CosmWasm smart contract" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] cosmwasm-schema = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/nym-performance-contract/Cargo.toml b/common/cosmwasm-smart-contracts/nym-performance-contract/Cargo.toml index 8d778d434d..c16dd083d0 100644 --- a/common/cosmwasm-smart-contracts/nym-performance-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/nym-performance-contract/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] thiserror = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml b/common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml index 7e12aa793e..e98e238c1a 100644 --- a/common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] thiserror = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml index e004f6ff03..b744e26ff3 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] cosmwasm-std = { workspace = true } diff --git a/common/credential-proxy/Cargo.toml b/common/credential-proxy/Cargo.toml index cab3a24b06..56a02266e3 100644 --- a/common/credential-proxy/Cargo.toml +++ b/common/credential-proxy/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] anyhow = { workspace = true } diff --git a/common/credential-storage/Cargo.toml b/common/credential-storage/Cargo.toml index 90910a94dd..c6b49edb6c 100644 --- a/common/credential-storage/Cargo.toml +++ b/common/credential-storage/Cargo.toml @@ -2,12 +2,15 @@ name = "nym-credential-storage" description = "Crate for handling and storing spent and unspent zknym ticketbooks" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/credential-utils/Cargo.toml b/common/credential-utils/Cargo.toml index 2311188907..3dfaacf07a 100644 --- a/common/credential-utils/Cargo.toml +++ b/common/credential-utils/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-credential-utils" description = "Utils crate for dealing with zknym credentials" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/common/credential-verification/Cargo.toml b/common/credential-verification/Cargo.toml index a159119ef8..80e0918330 100644 --- a/common/credential-verification/Cargo.toml +++ b/common/credential-verification/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] async-trait = { workspace = true } diff --git a/common/credentials-interface/Cargo.toml b/common/credentials-interface/Cargo.toml index 07c3e91d31..615bec2bbc 100644 --- a/common/credentials-interface/Cargo.toml +++ b/common/credentials-interface/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/credentials/Cargo.toml b/common/credentials/Cargo.toml index af918db7f6..ab45bf851f 100644 --- a/common/credentials/Cargo.toml +++ b/common/credentials/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-credentials" description = "Crate for using Nym's zknym credentials" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/crypto/Cargo.toml b/common/crypto/Cargo.toml index 7f8f54d746..1cc48788b6 100644 --- a/common/crypto/Cargo.toml +++ b/common/crypto/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] aes-gcm-siv = { workspace = true, optional = true } diff --git a/common/dkg/Cargo.toml b/common/dkg/Cargo.toml index 9dccc4646f..da5584b76a 100644 --- a/common/dkg/Cargo.toml +++ b/common/dkg/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-dkg" description = "Nym's Distributed Key Generation functionality" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true resolver = "2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/ecash-signer-check-types/Cargo.toml b/common/ecash-signer-check-types/Cargo.toml index 818ddcd78f..6536ed5b76 100644 --- a/common/ecash-signer-check-types/Cargo.toml +++ b/common/ecash-signer-check-types/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] semver = { workspace = true } diff --git a/common/ecash-signer-check/Cargo.toml b/common/ecash-signer-check/Cargo.toml index 4cd66d8106..425b4d3697 100644 --- a/common/ecash-signer-check/Cargo.toml +++ b/common/ecash-signer-check/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] futures = { workspace = true } diff --git a/common/ecash-time/Cargo.toml b/common/ecash-time/Cargo.toml index f1aca80ab3..bc7021167a 100644 --- a/common/ecash-time/Cargo.toml +++ b/common/ecash-time/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/exit-policy/Cargo.toml b/common/exit-policy/Cargo.toml index 7cd6e83fcd..172f95c90f 100644 --- a/common/exit-policy/Cargo.toml +++ b/common/exit-policy/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/gateway-requests/Cargo.toml b/common/gateway-requests/Cargo.toml index e929215acc..7803769ada 100644 --- a/common/gateway-requests/Cargo.toml +++ b/common/gateway-requests/Cargo.toml @@ -11,6 +11,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/gateway-stats-storage/Cargo.toml b/common/gateway-stats-storage/Cargo.toml index b5307601ef..cb37725db1 100644 --- a/common/gateway-stats-storage/Cargo.toml +++ b/common/gateway-stats-storage/Cargo.toml @@ -9,6 +9,8 @@ repository.workspace = true homepage.workspace = true documentation.workspace = true rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] sqlx = { workspace = true, features = [ diff --git a/common/gateway-storage/Cargo.toml b/common/gateway-storage/Cargo.toml index 0b60496015..76a8ad56d0 100644 --- a/common/gateway-storage/Cargo.toml +++ b/common/gateway-storage/Cargo.toml @@ -9,6 +9,8 @@ repository.workspace = true homepage.workspace = true documentation.workspace = true rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] async-trait = { workspace = true } diff --git a/common/http-api-client-macro/Cargo.toml b/common/http-api-client-macro/Cargo.toml index a05fb9558e..de4e6e619a 100644 --- a/common/http-api-client-macro/Cargo.toml +++ b/common/http-api-client-macro/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [lib] proc-macro = true diff --git a/common/http-api-client/Cargo.toml b/common/http-api-client/Cargo.toml index 6625080599..0952580bce 100644 --- a/common/http-api-client/Cargo.toml +++ b/common/http-api-client/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/http-api-common/Cargo.toml b/common/http-api-common/Cargo.toml index 5fe20b08b3..94601f3b61 100644 --- a/common/http-api-common/Cargo.toml +++ b/common/http-api-common/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/inclusion-probability/Cargo.toml b/common/inclusion-probability/Cargo.toml index 61563c451e..f73167cd3d 100644 --- a/common/inclusion-probability/Cargo.toml +++ b/common/inclusion-probability/Cargo.toml @@ -6,6 +6,11 @@ authors.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] log = { workspace = true } diff --git a/common/ip-packet-requests/Cargo.toml b/common/ip-packet-requests/Cargo.toml index 34b040f240..bd95393c99 100644 --- a/common/ip-packet-requests/Cargo.toml +++ b/common/ip-packet-requests/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [features] diff --git a/common/mixnode-common/Cargo.toml b/common/mixnode-common/Cargo.toml index 198b0f71f9..9a4a587867 100644 --- a/common/mixnode-common/Cargo.toml +++ b/common/mixnode-common/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/network-defaults/Cargo.toml b/common/network-defaults/Cargo.toml index 746386736d..238503673d 100644 --- a/common/network-defaults/Cargo.toml +++ b/common/network-defaults/Cargo.toml @@ -6,6 +6,11 @@ authors.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # Exclude build.rs from published crate - it's only used for dev-time sync # of env files and requires workspace context exclude = ["build.rs"] diff --git a/common/node-tester-utils/Cargo.toml b/common/node-tester-utils/Cargo.toml index e2be4ac7b8..ff1bd497a4 100644 --- a/common/node-tester-utils/Cargo.toml +++ b/common/node-tester-utils/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-node-tester-utils" description = "Utils for the Nym Node Tester" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/nonexhaustive-delayqueue/Cargo.toml b/common/nonexhaustive-delayqueue/Cargo.toml index 2ac9bf2096..8705ebaa55 100644 --- a/common/nonexhaustive-delayqueue/Cargo.toml +++ b/common/nonexhaustive-delayqueue/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/nym-cache/Cargo.toml b/common/nym-cache/Cargo.toml index e9afc05c13..ea344bc050 100644 --- a/common/nym-cache/Cargo.toml +++ b/common/nym-cache/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] tokio = { workspace = true, features = ["sync"] } diff --git a/common/nym-common/Cargo.toml b/common/nym-common/Cargo.toml index f0b10a6eb0..ba59dbf46e 100644 --- a/common/nym-common/Cargo.toml +++ b/common/nym-common/Cargo.toml @@ -6,6 +6,11 @@ authors.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [lints] workspace = true diff --git a/common/nym-id/Cargo.toml b/common/nym-id/Cargo.toml index 2af699c96c..5ef2a3d119 100644 --- a/common/nym-id/Cargo.toml +++ b/common/nym-id/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/nym-kkt/Cargo.toml b/common/nym-kkt/Cargo.toml index 7b5f64dbf1..e278e33887 100644 --- a/common/nym-kkt/Cargo.toml +++ b/common/nym-kkt/Cargo.toml @@ -6,6 +6,10 @@ authors = ["Georgio Nicolas "] edition = { workspace = true } license.workspace = true repository.workspace = true +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true publish = true [dependencies] diff --git a/common/nym-metrics/Cargo.toml b/common/nym-metrics/Cargo.toml index 6453cf083d..ab459c35f3 100644 --- a/common/nym-metrics/Cargo.toml +++ b/common/nym-metrics/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/nym_offline_compact_ecash/Cargo.toml b/common/nym_offline_compact_ecash/Cargo.toml index 5247442625..1eac6b4af8 100644 --- a/common/nym_offline_compact_ecash/Cargo.toml +++ b/common/nym_offline_compact_ecash/Cargo.toml @@ -11,6 +11,9 @@ license = { workspace = true } repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/nymnoise/Cargo.toml b/common/nymnoise/Cargo.toml index 397df48dc6..aa7d184518 100644 --- a/common/nymnoise/Cargo.toml +++ b/common/nymnoise/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] arc-swap = { workspace = true } diff --git a/common/nymnoise/keys/Cargo.toml b/common/nymnoise/keys/Cargo.toml index 57ed842b30..779dae7a02 100644 --- a/common/nymnoise/keys/Cargo.toml +++ b/common/nymnoise/keys/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] schemars = { workspace = true, features = ["preserve_order"] } diff --git a/common/nymsphinx/Cargo.toml b/common/nymsphinx/Cargo.toml index 487508e3f6..2ff13840ec 100644 --- a/common/nymsphinx/Cargo.toml +++ b/common/nymsphinx/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] tracing = { workspace = true } diff --git a/common/nymsphinx/acknowledgements/Cargo.toml b/common/nymsphinx/acknowledgements/Cargo.toml index a3032889bf..bf94fd649a 100644 --- a/common/nymsphinx/acknowledgements/Cargo.toml +++ b/common/nymsphinx/acknowledgements/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] rand = { workspace = true } diff --git a/common/nymsphinx/addressing/Cargo.toml b/common/nymsphinx/addressing/Cargo.toml index 4675248f2c..a5b2ed291e 100644 --- a/common/nymsphinx/addressing/Cargo.toml +++ b/common/nymsphinx/addressing/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] nym-crypto = { workspace = true, features = ["asymmetric", "sphinx"] } # all addresses are expressed in terms on their crypto keys diff --git a/common/nymsphinx/anonymous-replies/Cargo.toml b/common/nymsphinx/anonymous-replies/Cargo.toml index abdbc63612..75d651fe60 100644 --- a/common/nymsphinx/anonymous-replies/Cargo.toml +++ b/common/nymsphinx/anonymous-replies/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] rand = { workspace = true } diff --git a/common/nymsphinx/chunking/Cargo.toml b/common/nymsphinx/chunking/Cargo.toml index c955737b83..625a330a1d 100644 --- a/common/nymsphinx/chunking/Cargo.toml +++ b/common/nymsphinx/chunking/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/nymsphinx/cover/Cargo.toml b/common/nymsphinx/cover/Cargo.toml index 8d1ce48d3a..cf65805c02 100644 --- a/common/nymsphinx/cover/Cargo.toml +++ b/common/nymsphinx/cover/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] rand = { workspace = true } diff --git a/common/nymsphinx/forwarding/Cargo.toml b/common/nymsphinx/forwarding/Cargo.toml index 2c514f8e60..6ba8d1403f 100644 --- a/common/nymsphinx/forwarding/Cargo.toml +++ b/common/nymsphinx/forwarding/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] nym-sphinx-addressing = { workspace = true } diff --git a/common/nymsphinx/framing/Cargo.toml b/common/nymsphinx/framing/Cargo.toml index 3919d97326..78a4e5954e 100644 --- a/common/nymsphinx/framing/Cargo.toml +++ b/common/nymsphinx/framing/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] bytes = { workspace = true } diff --git a/common/nymsphinx/params/Cargo.toml b/common/nymsphinx/params/Cargo.toml index 3e6b354507..88ffe4a225 100644 --- a/common/nymsphinx/params/Cargo.toml +++ b/common/nymsphinx/params/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] thiserror = { workspace = true } diff --git a/common/nymsphinx/routing/Cargo.toml b/common/nymsphinx/routing/Cargo.toml index 2613fbf672..53d424b803 100644 --- a/common/nymsphinx/routing/Cargo.toml +++ b/common/nymsphinx/routing/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] thiserror = { workspace = true } diff --git a/common/nymsphinx/types/Cargo.toml b/common/nymsphinx/types/Cargo.toml index ce8a5f73ae..234382035c 100644 --- a/common/nymsphinx/types/Cargo.toml +++ b/common/nymsphinx/types/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] sphinx-packet = { workspace = true, optional = true } diff --git a/common/nyxd-scraper-shared/Cargo.toml b/common/nyxd-scraper-shared/Cargo.toml index d046ef02ee..986b39319c 100644 --- a/common/nyxd-scraper-shared/Cargo.toml +++ b/common/nyxd-scraper-shared/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] async-trait.workspace = true diff --git a/common/pemstore/Cargo.toml b/common/pemstore/Cargo.toml index 3b35d25492..ff2d78250e 100644 --- a/common/pemstore/Cargo.toml +++ b/common/pemstore/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] pem = { workspace = true } diff --git a/common/registration/Cargo.toml b/common/registration/Cargo.toml index 27f96a63f4..75f882a4f5 100644 --- a/common/registration/Cargo.toml +++ b/common/registration/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [lints] workspace = true diff --git a/common/serde-helpers/Cargo.toml b/common/serde-helpers/Cargo.toml index ab69538007..609474808d 100644 --- a/common/serde-helpers/Cargo.toml +++ b/common/serde-helpers/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/service-provider-requests-common/Cargo.toml b/common/service-provider-requests-common/Cargo.toml index caae905475..c25adafdde 100644 --- a/common/service-provider-requests-common/Cargo.toml +++ b/common/service-provider-requests-common/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] serde = { workspace = true, features = ["derive"] } diff --git a/common/socks5-client-core/Cargo.toml b/common/socks5-client-core/Cargo.toml index 8faf069852..911e9e23fa 100644 --- a/common/socks5-client-core/Cargo.toml +++ b/common/socks5-client-core/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-socks5-client-core" description = "Core functionality of the Nym SOCKS client" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/socks5/ordered-buffer/Cargo.toml b/common/socks5/ordered-buffer/Cargo.toml index 42d32b0b20..fc66833eb4 100644 --- a/common/socks5/ordered-buffer/Cargo.toml +++ b/common/socks5/ordered-buffer/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/socks5/proxy-helpers/Cargo.toml b/common/socks5/proxy-helpers/Cargo.toml index f1e6dc6b85..6d58b118a1 100644 --- a/common/socks5/proxy-helpers/Cargo.toml +++ b/common/socks5/proxy-helpers/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/socks5/requests/Cargo.toml b/common/socks5/requests/Cargo.toml index 6776145819..b1aae2ed1a 100644 --- a/common/socks5/requests/Cargo.toml +++ b/common/socks5/requests/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/statistics/Cargo.toml b/common/statistics/Cargo.toml index 85bb78f8b3..b92798f180 100644 --- a/common/statistics/Cargo.toml +++ b/common/statistics/Cargo.toml @@ -5,11 +5,15 @@ name = "nym-statistics-common" description = "This crate contains basic statistics utilities and abstractions to be re-used and applied throughout both the client and gateway implementations" version.workspace = true +authors.workspace = true edition.workspace = true license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/store-cipher/Cargo.toml b/common/store-cipher/Cargo.toml index 7b7fa6c6a6..29792d9ce6 100644 --- a/common/store-cipher/Cargo.toml +++ b/common/store-cipher/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-store-cipher" description = "Helpers for various ciphers used throughout the Nym network" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/task/Cargo.toml b/common/task/Cargo.toml index b915f7c800..a6d9e396c7 100644 --- a/common/task/Cargo.toml +++ b/common/task/Cargo.toml @@ -6,6 +6,11 @@ authors.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] cfg-if = { workspace = true } diff --git a/common/test-utils/Cargo.toml b/common/test-utils/Cargo.toml index 77ad5388ba..8d8cb55116 100644 --- a/common/test-utils/Cargo.toml +++ b/common/test-utils/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] anyhow = { workspace = true } diff --git a/common/ticketbooks-merkle/Cargo.toml b/common/ticketbooks-merkle/Cargo.toml index b89e4768fb..feb2354c47 100644 --- a/common/ticketbooks-merkle/Cargo.toml +++ b/common/ticketbooks-merkle/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] sha2 = { workspace = true } diff --git a/common/topology/Cargo.toml b/common/topology/Cargo.toml index 579571eb2a..32530840bc 100644 --- a/common/topology/Cargo.toml +++ b/common/topology/Cargo.toml @@ -8,6 +8,9 @@ license = { workspace = true } repository = { workspace = true } homepage = { workspace = true } documentation = { workspace = true } +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/tun/Cargo.toml b/common/tun/Cargo.toml index ab5226a2f1..318c53fa6b 100644 --- a/common/tun/Cargo.toml +++ b/common/tun/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/types/Cargo.toml b/common/types/Cargo.toml index 1451fbfe6d..31fdcfc200 100644 --- a/common/types/Cargo.toml +++ b/common/types/Cargo.toml @@ -9,6 +9,8 @@ repository.workspace = true homepage.workspace = true documentation.workspace = true rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] base64 = { workspace = true } diff --git a/common/upgrade-mode-check/Cargo.toml b/common/upgrade-mode-check/Cargo.toml index 4f8d8c5359..e3fe21f506 100644 --- a/common/upgrade-mode-check/Cargo.toml +++ b/common/upgrade-mode-check/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] jwt-simple = { workspace = true } diff --git a/common/verloc/Cargo.toml b/common/verloc/Cargo.toml index 4db1b99577..0617192dff 100644 --- a/common/verloc/Cargo.toml +++ b/common/verloc/Cargo.toml @@ -10,6 +10,7 @@ homepage.workspace = true documentation.workspace = true rust-version.workspace = true readme.workspace = true +publish = true [dependencies] bytes = { workspace = true } diff --git a/common/wasm/client-core/Cargo.toml b/common/wasm/client-core/Cargo.toml index 73e2eef5bb..749272e9a2 100644 --- a/common/wasm/client-core/Cargo.toml +++ b/common/wasm/client-core/Cargo.toml @@ -6,6 +6,11 @@ authors = ["Jedrzej Stuczynski "] edition = "2021" license = "Apache-2.0" repository = "https://github.com/nymtech/nym" +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/wasm/storage/Cargo.toml b/common/wasm/storage/Cargo.toml index 89d53e1b21..2e4f4430c4 100644 --- a/common/wasm/storage/Cargo.toml +++ b/common/wasm/storage/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/wasm/utils/Cargo.toml b/common/wasm/utils/Cargo.toml index 5d11cb98f3..73984f73e6 100644 --- a/common/wasm/utils/Cargo.toml +++ b/common/wasm/utils/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/wireguard-private-metadata/client/Cargo.toml b/common/wireguard-private-metadata/client/Cargo.toml index f79423ad9e..dc5ee67df4 100644 --- a/common/wireguard-private-metadata/client/Cargo.toml +++ b/common/wireguard-private-metadata/client/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] async-trait = { workspace = true } diff --git a/common/wireguard-private-metadata/server/Cargo.toml b/common/wireguard-private-metadata/server/Cargo.toml index 47961434a6..5e551a986c 100644 --- a/common/wireguard-private-metadata/server/Cargo.toml +++ b/common/wireguard-private-metadata/server/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] anyhow = { workspace = true } diff --git a/common/wireguard-private-metadata/shared/Cargo.toml b/common/wireguard-private-metadata/shared/Cargo.toml index 37038361f9..cc43487b3a 100644 --- a/common/wireguard-private-metadata/shared/Cargo.toml +++ b/common/wireguard-private-metadata/shared/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] axum = { workspace = true } diff --git a/common/wireguard-private-metadata/tests/Cargo.toml b/common/wireguard-private-metadata/tests/Cargo.toml index 4e0b670d0d..552afc0468 100644 --- a/common/wireguard-private-metadata/tests/Cargo.toml +++ b/common/wireguard-private-metadata/tests/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] async-trait = { workspace = true } diff --git a/common/wireguard-types/Cargo.toml b/common/wireguard-types/Cargo.toml index 57e8491941..30df325d31 100644 --- a/common/wireguard-types/Cargo.toml +++ b/common/wireguard-types/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/wireguard/Cargo.toml b/common/wireguard/Cargo.toml index 5269253dd3..70b95559ff 100644 --- a/common/wireguard/Cargo.toml +++ b/common/wireguard/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/contracts/coconut-dkg/Cargo.toml b/contracts/coconut-dkg/Cargo.toml index f84d51beae..bc410dc4ef 100644 --- a/contracts/coconut-dkg/Cargo.toml +++ b/contracts/coconut-dkg/Cargo.toml @@ -5,6 +5,7 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/contracts/ecash/Cargo.toml b/contracts/ecash/Cargo.toml index c89e8ee455..81d323f29c 100644 --- a/contracts/ecash/Cargo.toml +++ b/contracts/ecash/Cargo.toml @@ -5,6 +5,7 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +publish = false [[bin]] name = "schema" diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index b629b265c0..20222063f6 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -7,6 +7,7 @@ edition = { workspace = true } license = { workspace = true } repository = { workspace = true } readme = "README.md" +publish = false exclude = [ # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. "contract.wasm", diff --git a/contracts/multisig/cw3-flex-multisig/Cargo.toml b/contracts/multisig/cw3-flex-multisig/Cargo.toml index f928ee3d18..649b946357 100644 --- a/contracts/multisig/cw3-flex-multisig/Cargo.toml +++ b/contracts/multisig/cw3-flex-multisig/Cargo.toml @@ -8,6 +8,7 @@ license = "Apache-2.0" repository = "https://github.com/CosmWasm/cw-plus" homepage = "https://cosmwasm.com" documentation = "https://docs.cosmwasm.com" +publish = false [[bin]] name = "schema" diff --git a/contracts/multisig/cw4-group/Cargo.toml b/contracts/multisig/cw4-group/Cargo.toml index 22ee45388c..e6c2940d73 100644 --- a/contracts/multisig/cw4-group/Cargo.toml +++ b/contracts/multisig/cw4-group/Cargo.toml @@ -8,6 +8,7 @@ license = "Apache-2.0" repository = "https://github.com/CosmWasm/cw-plus" homepage = "https://cosmwasm.com" documentation = "https://docs.cosmwasm.com" +publish = false exclude = [ # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. "artifacts/*", diff --git a/contracts/nym-pool/Cargo.toml b/contracts/nym-pool/Cargo.toml index 244f20f52f..d4d68fde37 100644 --- a/contracts/nym-pool/Cargo.toml +++ b/contracts/nym-pool/Cargo.toml @@ -5,6 +5,7 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +publish = false [[bin]] name = "schema" diff --git a/contracts/performance/Cargo.toml b/contracts/performance/Cargo.toml index ae81ace997..78069a02de 100644 --- a/contracts/performance/Cargo.toml +++ b/contracts/performance/Cargo.toml @@ -7,6 +7,7 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +publish = false [[bin]] name = "schema" diff --git a/contracts/vesting/Cargo.toml b/contracts/vesting/Cargo.toml index a7f590bc0b..467e35c7d7 100644 --- a/contracts/vesting/Cargo.toml +++ b/contracts/vesting/Cargo.toml @@ -7,6 +7,7 @@ edition = { workspace = true } license = { workspace = true } repository = { workspace = true } readme = "README.md" +publish = false exclude = [ # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. "contract.wasm", diff --git a/cpu-cycles/Cargo.toml b/cpu-cycles/Cargo.toml index 1ccdd3f504..fe139b5d47 100644 --- a/cpu-cycles/Cargo.toml +++ b/cpu-cycles/Cargo.toml @@ -3,6 +3,7 @@ name = "cpu-cycles" version = "0.1.0" edition = "2021" license = "LicenseRef-PD-hp OR CC0-1.0 OR 0BSD OR MIT-0 OR MIT" +publish = false build = "build.rs" links = "cpucycles" diff --git a/examples/cli/commands/verify-signature/Cargo.toml b/examples/cli/commands/verify-signature/Cargo.toml index 5ad0673115..bd4c0553a0 100644 --- a/examples/cli/commands/verify-signature/Cargo.toml +++ b/examples/cli/commands/verify-signature/Cargo.toml @@ -2,6 +2,7 @@ name = "example-verify-signature" version = "0.1.0" edition = "2021" +publish = false [workspace] diff --git a/nym-api/nym-api-requests/Cargo.toml b/nym-api/nym-api-requests/Cargo.toml index 164002a3a2..28d18fc632 100644 --- a/nym-api/nym-api-requests/Cargo.toml +++ b/nym-api/nym-api-requests/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-api-requests" description = "Nym API request types and functions" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nym-credential-proxy/nym-credential-proxy-requests/Cargo.toml b/nym-credential-proxy/nym-credential-proxy-requests/Cargo.toml index 4891c86c81..2adbd39d9a 100644 --- a/nym-credential-proxy/nym-credential-proxy-requests/Cargo.toml +++ b/nym-credential-proxy/nym-credential-proxy-requests/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nym-ip-packet-client/Cargo.toml b/nym-ip-packet-client/Cargo.toml index c213107871..47b2de02c3 100644 --- a/nym-ip-packet-client/Cargo.toml +++ b/nym-ip-packet-client/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [lints] workspace = true diff --git a/nym-node/nym-node-metrics/Cargo.toml b/nym-node/nym-node-metrics/Cargo.toml index 9ccabdcffb..9e6b4c416c 100644 --- a/nym-node/nym-node-metrics/Cargo.toml +++ b/nym-node/nym-node-metrics/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] dashmap = { workspace = true } diff --git a/nym-node/nym-node-requests/Cargo.toml b/nym-node/nym-node-requests/Cargo.toml index eb0bcbc77c..bd78701287 100644 --- a/nym-node/nym-node-requests/Cargo.toml +++ b/nym-node/nym-node-requests/Cargo.toml @@ -8,6 +8,9 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nym-outfox/Cargo.toml b/nym-outfox/Cargo.toml index b7b6600941..075c380d28 100644 --- a/nym-outfox/Cargo.toml +++ b/nym-outfox/Cargo.toml @@ -6,6 +6,11 @@ authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nym-sqlx-pool-guard/Cargo.toml b/nym-sqlx-pool-guard/Cargo.toml index fe899cd057..85622863ad 100644 --- a/nym-sqlx-pool-guard/Cargo.toml +++ b/nym-sqlx-pool-guard/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-sqlx-pool-guard" description = "Platform-specific functions for SQLX dbs" version.workspace = true +authors.workspace = true edition = "2024" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [lints] workspace = true diff --git a/nym-wallet/nym-wallet-recovery-cli/Cargo.toml b/nym-wallet/nym-wallet-recovery-cli/Cargo.toml index 5d78d02d41..4a60d01ba5 100644 --- a/nym-wallet/nym-wallet-recovery-cli/Cargo.toml +++ b/nym-wallet/nym-wallet-recovery-cli/Cargo.toml @@ -2,6 +2,7 @@ name = "nym-wallet-recovery-cli" version = "0.1.0" edition = "2021" +publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nym-wallet/nym-wallet-types/Cargo.toml b/nym-wallet/nym-wallet-types/Cargo.toml index d91f8e8761..a91188a94a 100644 --- a/nym-wallet/nym-wallet-types/Cargo.toml +++ b/nym-wallet/nym-wallet-types/Cargo.toml @@ -4,6 +4,7 @@ version = "1.0.0" edition = "2021" license = "Apache-2.0" rust-version = "1.85" +publish = false [dependencies] hex-literal = "0.3.3" diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index 1a17b80962..0ade98b950 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" license = "" repository = "" rust-version = "1.85" +publish = false build = "src/build.rs" default-run = "NymWallet" diff --git a/sdk/ffi/cpp/Cargo.toml b/sdk/ffi/cpp/Cargo.toml index 8422564362..786009064e 100644 --- a/sdk/ffi/cpp/Cargo.toml +++ b/sdk/ffi/cpp/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-cpp-ffi" description = "C++ FFI bindings for Nym Rust SDK" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [lib] name = "nym_cpp_ffi" diff --git a/sdk/ffi/go/Cargo.toml b/sdk/ffi/go/Cargo.toml index 88fd0e33ab..a47eb63308 100644 --- a/sdk/ffi/go/Cargo.toml +++ b/sdk/ffi/go/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-go-ffi" description = "Go FFI bindings for Nym Rust SDK" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [lib] crate-type = ["cdylib"] diff --git a/sdk/ffi/shared/Cargo.toml b/sdk/ffi/shared/Cargo.toml index f99d2a5aa6..c4531df638 100644 --- a/sdk/ffi/shared/Cargo.toml +++ b/sdk/ffi/shared/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-ffi-shared" description = "Common crate for use by Rust SDK FFI crates" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true [dependencies] # Async runtime diff --git a/sdk/rust/nym-sdk/Cargo.toml b/sdk/rust/nym-sdk/Cargo.toml index 5ccc260b8c..931c640edb 100644 --- a/sdk/rust/nym-sdk/Cargo.toml +++ b/sdk/rust/nym-sdk/Cargo.toml @@ -2,9 +2,15 @@ name = "nym-sdk" description = "Nym's Rust SDK" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository = "https://github.com/nymtech/nym/sdk/rust/nym-sdk/" +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # documentation = "https://docs.rs/nym-sdk" Max: once we upload to crates.io and this is generated, this can be uncommented. # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/service-providers/common/Cargo.toml b/service-providers/common/Cargo.toml index b610c737d0..0966f51cf5 100644 --- a/service-providers/common/Cargo.toml +++ b/service-providers/common/Cargo.toml @@ -2,11 +2,15 @@ name = "nym-service-providers-common" description = "Common crate for Nym Service Providers" version.workspace = true +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +rust-version.workspace = true +readme.workspace = true +publish = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/smolmix/core/Cargo.toml b/smolmix/core/Cargo.toml index 93acc1ed8b..9ef598b42d 100644 --- a/smolmix/core/Cargo.toml +++ b/smolmix/core/Cargo.toml @@ -2,9 +2,14 @@ name = "smolmix" description = "Tunnel for TCP and UDP traffic to be sent over Nym mixnet to clearnet remote hosts" version = "0.0.1" +authors.workspace = true edition = "2021" license.workspace = true repository.workspace = true +homepage.workspace = true +documentation.workspace = true +rust-version.workspace = true +readme.workspace = true publish = true [dependencies] diff --git a/tools/internal/check_cargo_toml_field_order.py b/tools/internal/check_cargo_toml_field_order.py index b91fd62682..dbe3ddfa64 100644 --- a/tools/internal/check_cargo_toml_field_order.py +++ b/tools/internal/check_cargo_toml_field_order.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Check that [package] fields in Cargo.toml follow canonical ordering.""" +"""Check [package] field ordering and required fields in Cargo.toml files.""" import re, sys ORDER = [ @@ -9,9 +9,16 @@ ORDER = [ "resolver", ] +# Required when publish = true or publish.workspace = true +REQUIRED = { + "name", "description", "version", "authors", "edition", "license", + "repository", "homepage", "documentation", "rust-version", "readme", + "publish", +} + bad = [] for path in sys.argv[1:]: - fields, in_pkg = [], False + fields, values, in_pkg = [], {}, False for line in open(path): s = line.strip() if s == "[package]": @@ -23,20 +30,37 @@ for path in sys.argv[1:]: m = re.match(r"^(\w[\w-]*)", s) if m and "=" in line: fields.append(m.group(1)) + values[m.group(1)] = s + + if not fields: + continue + unknown = [f for f in fields if f not in ORDER] if unknown: bad.append((path, f"unknown field(s): {', '.join(unknown)}")) continue + expected = sorted(fields, key=ORDER.index) if fields != expected: first = next(a for a, b in zip(fields, expected) if a != b) - bad.append((path, f"first mismatch: '{first}'")) + bad.append((path, f"field ordering: first mismatch is '{first}'")) + + # publish must always be present (explicit intent) + field_set = set(fields) + if "publish" not in field_set: + bad.append((path, "missing 'publish' field (must be explicit)")) + # Check remaining required fields when publishable + elif "true" in values["publish"] or "workspace" in values["publish"]: + missing = sorted(REQUIRED - field_set, key=ORDER.index) + if missing: + bad.append((path, f"missing required: {', '.join(missing)}")) if bad: - print("[package] fields out of canonical order:") + print("[package] field issues:") for path, reason in bad: print(f" {path} ({reason})") print("\nCanonical order:") for f in ORDER: - print(f" - {f}") + req = " (required)" if f in REQUIRED else "" + print(f" - {f}{req}") sys.exit(1) diff --git a/tools/internal/sdk-version-bump/Cargo.toml b/tools/internal/sdk-version-bump/Cargo.toml index e53edbda65..281aa976ef 100644 --- a/tools/internal/sdk-version-bump/Cargo.toml +++ b/tools/internal/sdk-version-bump/Cargo.toml @@ -7,6 +7,7 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From 534a5068d3d1ba5fba14c6eb94569ee6c26592e7 Mon Sep 17 00:00:00 2001 From: dynco-nym <173912580+dynco-nym@users.noreply.github.com> Date: Fri, 17 Apr 2026 13:42:48 +0200 Subject: [PATCH 17/37] Return ipv6 addresses as well (#6684) * Return ipv6 addresses as well * Fix clippy * Bump NS API version --- Cargo.lock | 2 +- nym-node-status-api/nym-node-status-api/Cargo.toml | 2 +- nym-node-status-api/nym-node-status-api/src/http/state.rs | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd00183414..0f4c797f7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7558,7 +7558,7 @@ dependencies = [ [[package]] name = "nym-node-status-api" -version = "4.5.0" +version = "4.6.0" dependencies = [ "ammonia", "anyhow", diff --git a/nym-node-status-api/nym-node-status-api/Cargo.toml b/nym-node-status-api/nym-node-status-api/Cargo.toml index 2f534a1f7c..49e6f44b8c 100644 --- a/nym-node-status-api/nym-node-status-api/Cargo.toml +++ b/nym-node-status-api/nym-node-status-api/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-node-status-api" -version = "4.5.0" +version = "4.6.0" authors.workspace = true repository.workspace = true homepage.workspace = true diff --git a/nym-node-status-api/nym-node-status-api/src/http/state.rs b/nym-node-status-api/nym-node-status-api/src/http/state.rs index 3f5d5c2887..b630c17d40 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/state.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/state.rs @@ -9,7 +9,7 @@ use nym_node_status_client::auth::VerifiableRequest; use nym_validator_client::nym_api::SkimmedNodeV1; use semver::Version; use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, net::IpAddr, sync::Arc, time::Duration}; +use std::{collections::HashMap, sync::Arc, time::Duration}; use time::UtcDateTime; use tokio::sync::RwLock; use tracing::{error, instrument, trace, warn}; @@ -456,7 +456,6 @@ impl HttpCache { .await .into_iter() .flat_map(|gw| gw.ip_addresses) - .filter(IpAddr::is_ipv4) .map(|ip| ip.to_string()) .sorted() .dedup() From d285b70030daabc03954844ff98c06114298407d Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Fri, 17 Apr 2026 13:04:14 +0100 Subject: [PATCH 18/37] Specify Rust v1.85 for all contract crates (test) --- common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml | 2 +- .../contracts-common-testing/Cargo.toml | 2 +- common/cosmwasm-smart-contracts/contracts-common/Cargo.toml | 2 +- common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml | 2 +- common/cosmwasm-smart-contracts/group-contract/Cargo.toml | 2 +- common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml | 2 +- .../nym-performance-contract/Cargo.toml | 2 +- common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml | 2 +- common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml b/common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml index bea9907df1..dc4fe926af 100644 --- a/common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml +++ b/common/cosmwasm-smart-contracts/coconut-dkg/Cargo.toml @@ -8,7 +8,7 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -rust-version.workspace = true +rust-version = "1.85" readme.workspace = true publish = true diff --git a/common/cosmwasm-smart-contracts/contracts-common-testing/Cargo.toml b/common/cosmwasm-smart-contracts/contracts-common-testing/Cargo.toml index b2940bb474..0cef554a87 100644 --- a/common/cosmwasm-smart-contracts/contracts-common-testing/Cargo.toml +++ b/common/cosmwasm-smart-contracts/contracts-common-testing/Cargo.toml @@ -8,7 +8,7 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -rust-version.workspace = true +rust-version = "1.85" readme.workspace = true publish = true diff --git a/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml b/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml index 10e838b621..82ac9871ae 100644 --- a/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml +++ b/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml @@ -8,7 +8,7 @@ license = { workspace = true } repository = { workspace = true } homepage.workspace = true documentation.workspace = true -rust-version.workspace = true +rust-version = "1.85" readme.workspace = true publish = true diff --git a/common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml b/common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml index 49e2be8c60..dd9a616b2d 100644 --- a/common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/ecash-contract/Cargo.toml @@ -8,7 +8,7 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -rust-version.workspace = true +rust-version = "1.85" readme.workspace = true publish = true diff --git a/common/cosmwasm-smart-contracts/group-contract/Cargo.toml b/common/cosmwasm-smart-contracts/group-contract/Cargo.toml index 2306376d56..9de9779622 100644 --- a/common/cosmwasm-smart-contracts/group-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/group-contract/Cargo.toml @@ -8,7 +8,7 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -rust-version.workspace = true +rust-version = "1.85" readme.workspace = true publish = true diff --git a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml index a489eb4298..7fc32eacab 100644 --- a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml @@ -8,7 +8,7 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -rust-version.workspace = true +rust-version = "1.85" readme.workspace = true publish = true diff --git a/common/cosmwasm-smart-contracts/nym-performance-contract/Cargo.toml b/common/cosmwasm-smart-contracts/nym-performance-contract/Cargo.toml index c16dd083d0..13612c9b96 100644 --- a/common/cosmwasm-smart-contracts/nym-performance-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/nym-performance-contract/Cargo.toml @@ -8,7 +8,7 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -rust-version.workspace = true +rust-version = "1.85" readme.workspace = true publish = true diff --git a/common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml b/common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml index e98e238c1a..02f6fdd4a3 100644 --- a/common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/nym-pool-contract/Cargo.toml @@ -8,7 +8,7 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true -rust-version.workspace = true +rust-version = "1.85" readme.workspace = true publish = true diff --git a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml index b744e26ff3..dd9553bc05 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml @@ -8,7 +8,7 @@ license = { workspace = true } repository = { workspace = true } homepage.workspace = true documentation.workspace = true -rust-version.workspace = true +rust-version = "1.85" readme.workspace = true publish = true From 7140ba4ea9d398967b3c168d971bf0a2f6a8bafb Mon Sep 17 00:00:00 2001 From: dynco-nym <173912580+dynco-nym@users.noreply.github.com> Date: Fri, 17 Apr 2026 16:49:17 +0200 Subject: [PATCH 19/37] Fix invalid ticket spend (#6683) * Fix * PR feedback * Bump version * Update sqlx files --- Cargo.lock | 2 +- .../src/common/bandwidth_helpers.rs | 15 ++++++- .../nym-node-status-api/Cargo.toml | 2 +- .../src/ticketbook_manager/state.rs | 4 +- .../storage/auxiliary_models.rs | 37 +++++++++++++--- .../src/ticketbook_manager/storage/mod.rs | 44 +++++++++++++------ 6 files changed, 79 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca08ebe21f..f0f3f85101 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7580,7 +7580,7 @@ dependencies = [ [[package]] name = "nym-node-status-api" -version = "4.6.0" +version = "4.6.1" dependencies = [ "ammonia", "anyhow", diff --git a/nym-gateway-probe/src/common/bandwidth_helpers.rs b/nym-gateway-probe/src/common/bandwidth_helpers.rs index 10962a1eb6..5f968b8d92 100644 --- a/nym-gateway-probe/src/common/bandwidth_helpers.rs +++ b/nym-gateway-probe/src/common/bandwidth_helpers.rs @@ -86,10 +86,21 @@ pub(crate) async fn import_bandwidth( // 2. import actual tickets for ticket in attached_ticket_materials.attached_tickets { let ticketbook = ticket.ticketbook.try_unpack()?; + let total = ticketbook.params_total_tickets(); + if ticket.usable_index as u64 >= total { + error!( + "⚠️ received usable_index {} >= params_total_tickets {} for {}. \ + This ticket is unusable: spending will fail with SpendExceedsAllowance.", + ticket.usable_index, + total, + ticketbook.ticketbook_type() + ); + } info!( - "importing partial ticketbook {}. index to use: {}", + "importing partial ticketbook {}. index to use: {}, params_total_tickets: {}", ticketbook.ticketbook_type(), - ticket.usable_index + ticket.usable_index, + total, ); bandwidth_importer .import_partial_ticketbook(&ticketbook, ticket.usable_index, ticket.usable_index) diff --git a/nym-node-status-api/nym-node-status-api/Cargo.toml b/nym-node-status-api/nym-node-status-api/Cargo.toml index 64db4e1f4c..729404d8b6 100644 --- a/nym-node-status-api/nym-node-status-api/Cargo.toml +++ b/nym-node-status-api/nym-node-status-api/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-node-status-api" -version = "4.6.0" +version = "4.6.1" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/state.rs b/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/state.rs index bf4ad1e161..e1e507b272 100644 --- a/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/state.rs +++ b/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/state.rs @@ -68,8 +68,8 @@ impl TicketbookManagerState { for typ in &self.buffered_ticket_types { debug!("attempting to get materials for ticket of type {typ}"); if let Some(ticket) = self.storage.next_ticket(*typ, testrun_id).await? { - let epoch_id = ticket.ticketbook.epoch_id(); - let expiration_date = ticket.ticketbook.expiration_date(); + let epoch_id = ticket.epoch_id(); + let expiration_date = ticket.expiration_date(); debug!( "retrieved ticket corresponds to epoch {epoch_id} and expiration date {expiration_date}" diff --git a/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/storage/auxiliary_models.rs b/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/storage/auxiliary_models.rs index 904bb7eb57..a40611ea08 100644 --- a/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/storage/auxiliary_models.rs +++ b/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/storage/auxiliary_models.rs @@ -1,25 +1,50 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only +use anyhow::bail; use nym_credentials::IssuedTicketBook; use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; use nym_gateway_probe::types::AttachedTicket; +use nym_validator_client::nym_api::EpochId; use sqlx::FromRow; use time::Date; use zeroize::{Zeroize, ZeroizeOnDrop}; -pub struct RetrievedTicketbook { - pub ticketbook_id: i32, - pub total_tickets: u32, - pub spent_tickets: u32, - pub ticketbook: IssuedTicketBook, +pub(crate) struct RetrievedTicketbook { + usable_index: u32, + ticketbook: IssuedTicketBook, +} + +impl RetrievedTicketbook { + pub fn new(ticketbook: IssuedTicketBook) -> anyhow::Result { + let usable_index = ticketbook.spent_tickets() as u32 - 1; + // spent_tickets is the post-increment number from the DB: the ticket we're + // handing out has already been counted as "used" in the DB, but has NOT YET + // been spent yet by the recipient. To get its 0-based index in the ticketbook, + // subtract 1 (e.g. spent_tickets=1, the ticket at index 0). + if usable_index < 1 { + bail!("Malformed ticket: cannot convert from ticket with spent_tickets=0"); + } + Ok(Self { + usable_index, + ticketbook, + }) + } + + pub fn epoch_id(&self) -> EpochId { + self.ticketbook.epoch_id() + } + + pub fn expiration_date(&self) -> time::Date { + self.ticketbook.expiration_date() + } } impl From for AttachedTicket { fn from(retrieved: RetrievedTicketbook) -> Self { AttachedTicket { ticketbook: retrieved.ticketbook.pack(), - usable_index: retrieved.spent_tickets, + usable_index: retrieved.usable_index, } } } diff --git a/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/storage/mod.rs b/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/storage/mod.rs index e8f2091448..f2aebcfafd 100644 --- a/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/storage/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/storage/mod.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::db::Storage; -use crate::ticketbook_manager::storage::auxiliary_models::RetrievedTicketbook; -use anyhow::{Context, anyhow}; +use anyhow::{Context, anyhow, bail}; +use auxiliary_models::RetrievedTicketbook; use nym_credential_proxy_lib::error::CredentialProxyError; use nym_credential_proxy_lib::shared_state::ecash_state::{ IssuanceTicketBook, IssuedTicketBook, TicketType, @@ -16,6 +16,7 @@ use nym_crypto::aes::cipher::zeroize::Zeroizing; use nym_ecash_time::{EcashTime, ecash_today}; use nym_validator_client::nym_api::EpochId; use time::Date; +use tracing::warn; pub(crate) mod auxiliary_models; @@ -85,7 +86,7 @@ impl TicketbookManagerStorage { /// Tries to retrieve one of the stored ticketbook that has not yet expired /// it immediately updated the on-disk number of used tickets so that another task /// could obtain their own tickets at the same time - pub(crate) async fn next_ticket( + pub(super) async fn next_ticket( &self, ticket_type: TicketType, testrun_id: i32, @@ -113,16 +114,33 @@ impl TicketbookManagerStorage { .set_distributed_ticketbook(testrun_id, raw.id, raw.used_tickets) .await?; - deserialised.update_spent_tickets(raw.used_tickets as u64); - Ok(Some(RetrievedTicketbook { - ticketbook_id: raw.id, - total_tickets: raw - .total_tickets - .try_into() - .context("failed to convert i32 total tickets into u32")?, - spent_tickets: deserialised.spent_tickets() as u32, - ticketbook: deserialised, - })) + deserialised.update_spent_tickets((raw.used_tickets) as u64); + + let total = deserialised.params_total_tickets(); + let spent = raw.used_tickets as u64; + + if spent > total { + // should never happen: implies a bug in DB fetching + bail!( + "testrun_id={testrun_id}, ticketbook_id={}, ticket_type={ticket_type}, \ + marked as used_tickets = {spent} > params_total_tickets = {total}. \ + Cannot have spent more than is in the ticketbook", + raw.id, + ); + } else { + tracing::debug!( + "testrun_id={testrun_id}, ticketbook_id={}, ticket_type={ticket_type}, \ + db_used_tickets={} / total_tickets={total}", + raw.id, + raw.used_tickets, + ); + } + + let retrieved_ticketbook = RetrievedTicketbook::new(deserialised) + .inspect_err(|e| warn!("Failed to convert retrieved ticketbook: {e}")) + .ok(); + + Ok(retrieved_ticketbook) } } From 17894880e0f223cc0812dab2703d9fbf021f99e1 Mon Sep 17 00:00:00 2001 From: Merve <111695676+merve64@users.noreply.github.com> Date: Wed, 22 Apr 2026 11:41:12 +0300 Subject: [PATCH 20/37] Changelog urda (#6698) * test identity * changelog update --- .../docs/pages/operators/changelog.mdx | 30 +++++++++++++++++++ .../pages/operators/nodes/nym-node/setup.mdx | 8 ++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/documentation/docs/pages/operators/changelog.mdx b/documentation/docs/pages/operators/changelog.mdx index 24a04cb6d1..352753bc24 100644 --- a/documentation/docs/pages/operators/changelog.mdx +++ b/documentation/docs/pages/operators/changelog.mdx @@ -57,6 +57,36 @@ This page displays a full list of all the changes during our release cycle from +## `v2026.8-urda` + +- [Release Binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2026.8-urda) +- [`nym-node`](nodes/nym-node.mdx) version `1.30.0` + +```sh +nym-node +Binary Name: nym-node +Build Timestamp: 2026-04-21T10:11:28.164080002Z +Build Version: 1.30.0 +Commit SHA: 0c83ae2408ea9efcc1abae613711c6e4e16148ad +Commit Date: 2026-04-21T12:06:23.000000000+02:00 +Commit Branch: HEAD +rustc Version: 1.91.1 +rustc Channel: stable +cargo Profile: release +``` + +### Operator & Developer Updates + +### Features + +- [Include all gateways in the returned list](https://github.com/nymtech/nym/pull/6649): Ensures gateway APIs return the full gateway set instead of filtered results, improving consistency across services. +- [Max/sdk stream wrapper](https://github.com/nymtech/nym/pull/6320): Introduces a Rust SDK stream abstraction enabling IPR-based mixnet communication and client-side streaming support. +- [Max/sdk docrs](https://github.com/nymtech/nym/pull/6566): Updates SDK documentation to reflect the new stream-based architecture and IPR communication model. + +### Refactors & Maintenance + +- [Optimize GW probe in NS agent](https://github.com/nymtech/nym/pull/6636): Refactors gateway probe integration from subprocess execution to library usage, removing CLI dependency and improving typed communication between agent and probe. + ## `v2026.7-tola` - [Release Binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2026.7-tola) diff --git a/documentation/docs/pages/operators/nodes/nym-node/setup.mdx b/documentation/docs/pages/operators/nodes/nym-node/setup.mdx index 6873349219..9b33e1c891 100644 --- a/documentation/docs/pages/operators/nodes/nym-node/setup.mdx +++ b/documentation/docs/pages/operators/nodes/nym-node/setup.mdx @@ -20,10 +20,10 @@ This documentation page provides a guide on how to set up and run a [NYM NODE](. ```sh Binary Name: nym-node -Build Timestamp: 2026-04-08T10:31:49.141185557Z -Build Version: 1.29.0 -Commit SHA: 97068b2aace6626e3dff6864a26e7b1ff35f5725 -Commit Date: 2026-04-07T15:51:44.000000000+02:00 +Build Timestamp: 2026-04-21T10:11:28.164080002Z +Build Version: 1.30.0 +Commit SHA: 0c83ae2408ea9efcc1abae613711c6e4e16148ad +Commit Date: 2026-04-21T12:06:23.000000000+02:00 Commit Branch: HEAD rustc Version: 1.91.1 rustc Channel: stable From cca19f36c2e645d5deca600c1cccd17f9920eb1f Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Wed, 22 Apr 2026 09:35:59 +0000 Subject: [PATCH 21/37] Remove unused header (#6699) --- documentation/docs/pages/operators/changelog.mdx | 2 -- 1 file changed, 2 deletions(-) diff --git a/documentation/docs/pages/operators/changelog.mdx b/documentation/docs/pages/operators/changelog.mdx index 352753bc24..a5124633e1 100644 --- a/documentation/docs/pages/operators/changelog.mdx +++ b/documentation/docs/pages/operators/changelog.mdx @@ -75,8 +75,6 @@ rustc Channel: stable cargo Profile: release ``` -### Operator & Developer Updates - ### Features - [Include all gateways in the returned list](https://github.com/nymtech/nym/pull/6649): Ensures gateway APIs return the full gateway set instead of filtered results, improving consistency across services. From 9e642c635447d1d4f1ae2d3ccbf3bee4e5a41b21 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Mon, 20 Apr 2026 12:29:58 +0200 Subject: [PATCH 22/37] v9 bugfix --- service-providers/ip-packet-router/src/messages/request.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/service-providers/ip-packet-router/src/messages/request.rs b/service-providers/ip-packet-router/src/messages/request.rs index 0f8419e5e1..0c613a2fd4 100644 --- a/service-providers/ip-packet-router/src/messages/request.rs +++ b/service-providers/ip-packet-router/src/messages/request.rs @@ -10,6 +10,7 @@ use nym_ip_packet_requests::{ IpPair, v6::request::IpPacketRequest as IpPacketRequestV6, v7::request::IpPacketRequest as IpPacketRequestV7, v8::request::IpPacketRequest as IpPacketRequestV8, + v9::request::IpPacketRequest as IpPacketRequestV9, }; use nym_sdk::mixnet::ReconstructedMessage; use nym_service_provider_requests_common::{Protocol, ServiceProviderType}; @@ -131,14 +132,14 @@ impl TryFrom<&ReconstructedMessage> for IpPacketRequest { Ok(IpPacketRequest::from((request_v8, sender_tag))) } 9 => { - let request_v8 = IpPacketRequestV8::from_reconstructed_message(reconstructed) + let request_v9 = IpPacketRequestV9::from_reconstructed_message(reconstructed) .map_err( |source| IpPacketRouterError::FailedToDeserializeTaggedPacket { source }, )?; let sender_tag = reconstructed .sender_tag .ok_or(IpPacketRouterError::MissingSenderTag)?; - Ok(v9::convert(request_v8, sender_tag)) + Ok(v9::convert(request_v9, sender_tag)) } _ => { log::info!("Received packet with invalid version: v{request_version}"); From 9f26759b8d6237d8b7613c0d5ebdc31cb6a208f2 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Mon, 20 Apr 2026 15:55:11 +0200 Subject: [PATCH 23/37] v9 bugfix --- service-providers/ip-packet-router/src/messages/response.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/service-providers/ip-packet-router/src/messages/response.rs b/service-providers/ip-packet-router/src/messages/response.rs index 4801983f48..deefccc146 100644 --- a/service-providers/ip-packet-router/src/messages/response.rs +++ b/service-providers/ip-packet-router/src/messages/response.rs @@ -130,7 +130,11 @@ impl VersionedResponse { ClientVersion::V6 => IpPacketResponseV6::try_from(self)?.to_bytes(), ClientVersion::V7 => IpPacketResponseV7::try_from(self)?.to_bytes(), ClientVersion::V8 => IpPacketResponseV8::try_from(self)?.to_bytes(), - ClientVersion::V9 => IpPacketResponseV8::try_from(self)?.to_bytes(), + ClientVersion::V9 => { + let mut resp = IpPacketResponseV8::try_from(self)?; + resp.version = nym_ip_packet_requests::v9::VERSION; + resp.to_bytes() + } } .map_err(|err| IpPacketRouterError::FailedToSerializeResponsePacket { source: err }) } From 42aade29ebf2d2119eeca85e43c76c7b314878e8 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Mon, 20 Apr 2026 20:21:06 +0200 Subject: [PATCH 24/37] more v9 fixes --- nym-ip-packet-client/src/connect.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nym-ip-packet-client/src/connect.rs b/nym-ip-packet-client/src/connect.rs index 0448c0cf40..e28405d321 100644 --- a/nym-ip-packet-client/src/connect.rs +++ b/nym-ip-packet-client/src/connect.rs @@ -80,7 +80,7 @@ impl IprClientConnect { } async fn send_connect_request(&self, ip_packet_router_address: Recipient) -> Result { - let (request, request_id) = IpPacketRequest::new_connect_request(None); + let (request, request_id) = nym_ip_packet_requests::v9::new_connect_request(None); // We use 20 surbs for the connect request because typically the IPR is configured to have // a min threshold of 10 surbs that it reserves for itself to request additional surbs. From 50433fe2654d1744ba77b4b073723677c15ae537 Mon Sep 17 00:00:00 2001 From: Andrej Mihajlov Date: Thu, 23 Apr 2026 16:29:02 +0200 Subject: [PATCH 25/37] Only init SHARED_CLIENT if requested --- common/http-api-client/src/lib.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/common/http-api-client/src/lib.rs b/common/http-api-client/src/lib.rs index 9d94dcf30e..856b2ad0e7 100644 --- a/common/http-api-client/src/lib.rs +++ b/common/http-api-client/src/lib.rs @@ -1152,7 +1152,10 @@ impl ApiClientCore for Client { #[cfg(target_arch = "wasm32")] let response: Result = { - let client = self.reqwest_client.as_ref().unwrap_or(&*SHARED_CLIENT); + let client = self + .reqwest_client + .as_ref() + .unwrap_or_else(|| &*SHARED_CLIENT); Ok( wasmtimer::tokio::timeout(self.request_timeout, client.execute(req)) .await @@ -1162,7 +1165,10 @@ impl ApiClientCore for Client { #[cfg(not(target_arch = "wasm32"))] let response = { - let client = self.reqwest_client.as_ref().unwrap_or(&*SHARED_CLIENT); + let client = self + .reqwest_client + .as_ref() + .unwrap_or_else(|| &*SHARED_CLIENT); client.execute(req).await }; From 7669d0933f1ea60739d46468270808685c882656 Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Thu, 23 Apr 2026 15:39:11 +0100 Subject: [PATCH 26/37] Migrate ESLint config to flat config for ESLint 9 Dependabot bumped eslint to ^9 across the lint-scoped TS packages but did not migrate the legacy .eslintrc.* configs, breaking CI lint on develop. Behavior preserved: yarn lint passes locally with the same effective rule coverage as the pre-bump setup. Pre-existing warnings in nym-wallet and mui-theme are unchanged. Orphan .eslintrc files in sdk/typescript outside the lerna lint scope are left untouched. --- nym-wallet/eslint.config.js | 23 +++ .../packages/mui-theme/eslint.config.js | 123 +++++++++++++++ .../react-components/eslint.config.js | 147 ++++++++++++++++++ .../eslint.config.js | 38 +++++ ts-packages/types/eslint.config.js | 25 +++ ts-packages/webpack/eslint.config.js | 37 +++++ 6 files changed, 393 insertions(+) create mode 100644 nym-wallet/eslint.config.js create mode 100644 sdk/typescript/packages/mui-theme/eslint.config.js create mode 100644 sdk/typescript/packages/react-components/eslint.config.js create mode 100644 ts-packages/eslint-config-react-typescript/eslint.config.js create mode 100644 ts-packages/types/eslint.config.js create mode 100644 ts-packages/webpack/eslint.config.js diff --git a/nym-wallet/eslint.config.js b/nym-wallet/eslint.config.js new file mode 100644 index 0000000000..d4a9f8cec9 --- /dev/null +++ b/nym-wallet/eslint.config.js @@ -0,0 +1,23 @@ +/** + * Flat ESLint config for @nymproject/nym-wallet-app. + * + * Imports the shared React/TS preset and overrides parserOptions.project to + * point at the wallet's dedicated lint tsconfig. + */ + +const sharedConfig = require('@nymproject/eslint-config-react-typescript'); + +module.exports = [ + ...sharedConfig, + { + languageOptions: { + parserOptions: { + project: './tsconfig.eslint.json', + tsconfigRootDir: __dirname, + }, + }, + }, + { + ignores: ['dist/**', 'node_modules/**', 'src-tauri/**', '*.config.js'], + }, +]; diff --git a/sdk/typescript/packages/mui-theme/eslint.config.js b/sdk/typescript/packages/mui-theme/eslint.config.js new file mode 100644 index 0000000000..afe00b9339 --- /dev/null +++ b/sdk/typescript/packages/mui-theme/eslint.config.js @@ -0,0 +1,123 @@ +/** + * Flat ESLint config for @nymproject/mui-theme. + * + * Mirrors the previous inherited config at sdk/typescript/.eslintrc.js + * (airbnb-base, NOT airbnb-React). mui-theme has no dedicated tsconfig.eslint + * - it uses tsconfig.json, matching the previous parent default. + * + * Behavior preserved 1:1 with the pre-ESLint-9 setup. + */ + +const { FlatCompat } = require('@eslint/eslintrc'); +const js = require('@eslint/js'); + +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +module.exports = [ + ...compat.config({ + env: { + browser: true, + es6: true, + node: true, + jest: true, + }, + parserOptions: { + ecmaVersion: 2019, + sourceType: 'module', + }, + globals: { + Atomics: 'readonly', + SharedArrayBuffer: 'readonly', + }, + plugins: ['prettier'], + // airbnb-typescript/base is intentionally NOT at the top level - see the + // matching note in react-components/eslint.config.js for the rationale. + extends: ['airbnb-base', 'prettier'], + rules: { + 'prettier/prettier': 'error', + 'import/prefer-default-export': 'off', + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: ['**/*.test.[jt]s', '**/*.spec.[jt]s'], + }, + ], + 'import/extensions': [ + 'error', + 'ignorePackages', + { + ts: 'never', + js: 'never', + }, + ], + }, + overrides: [ + { + files: ['**/*.ts', '**/*.tsx'], + parser: '@typescript-eslint/parser', + parserOptions: { + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'airbnb-typescript/base', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier', + ], + rules: { + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + 'no-use-before-define': [0], + '@typescript-eslint/no-use-before-define': [1], + 'import/no-unresolved': 0, + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: ['**/*.test.ts', '**/*.spec.ts'], + }, + ], + quotes: [ + 2, + 'single', + { + avoidEscape: true, + }, + ], + '@typescript-eslint/no-unused-vars': [ + 2, + { argsIgnorePattern: '^_', caughtErrors: 'none' }, + ], + + // Rules removed in @typescript-eslint v6/v7/v8 but still referenced + // by airbnb-typescript@16; disable to avoid unknown-rule errors. + '@typescript-eslint/lines-between-class-members': 'off', + '@typescript-eslint/no-throw-literal': 'off', + '@typescript-eslint/space-before-function-paren': 'off', + '@typescript-eslint/no-loss-of-precision': 'off', + '@typescript-eslint/quotes': 'off', + + // New in @typescript-eslint v8 - was previously @typescript-eslint/no-empty-interface + // and @typescript-eslint/ban-types. Disabled to preserve pre-v8 behavior on + // existing code (the project relies on `{}` as the default type parameter in some + // .d.ts type aliases). Address in a follow-up code-cleanup PR. + '@typescript-eslint/no-empty-object-type': 'off', + + // Pre-existing relative-directory imports rely on Node module resolution + // (e.g. `import './theme'` resolving to `./theme/index.ts`). The legacy + // setup did not enforce file extensions for this case either. + 'import/extensions': 'off', + }, + }, + ], + }), + { + ignores: ['tsconfig.json', '**/*.d.ts', 'dist/**/*', 'dist', 'node_modules', '*.config.js'], + }, +]; diff --git a/sdk/typescript/packages/react-components/eslint.config.js b/sdk/typescript/packages/react-components/eslint.config.js new file mode 100644 index 0000000000..bd52a2428a --- /dev/null +++ b/sdk/typescript/packages/react-components/eslint.config.js @@ -0,0 +1,147 @@ +/** + * Flat ESLint config for @nymproject/react. + * + * Mirrors the previous inherited config at sdk/typescript/.eslintrc.js + * (airbnb-base, NOT airbnb-React) plus the per-package parserOptions override + * that previously lived in this directory's .eslintrc.json. + * + * Behavior preserved 1:1 with the pre-ESLint-9 setup. The fact that React + * rules are not active here is pre-existing and intentionally not changed in + * this migration PR. + */ + +const { FlatCompat } = require('@eslint/eslintrc'); +const js = require('@eslint/js'); + +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +module.exports = [ + ...compat.config({ + env: { + browser: true, + es6: true, + node: true, + jest: true, + }, + parserOptions: { + ecmaVersion: 2019, + sourceType: 'module', + }, + globals: { + Atomics: 'readonly', + SharedArrayBuffer: 'readonly', + }, + plugins: ['prettier'], + // airbnb-typescript/base is intentionally NOT at the top level because it + // bundles type-aware @typescript-eslint rules (e.g. dot-notation, return-await) + // that throw hard errors on .js files lacking parserOptions.project under + // typescript-eslint v8. The legacy v5 setup let these rules fail silently; + // this restructure preserves the effective behavior (no type-aware checks on + // .js files) without the new hard errors. + extends: ['airbnb-base', 'prettier'], + rules: { + 'prettier/prettier': 'error', + 'import/prefer-default-export': 'off', + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: ['**/*.test.[jt]s', '**/*.spec.[jt]s'], + }, + ], + 'import/extensions': [ + 'error', + 'ignorePackages', + { + ts: 'never', + js: 'never', + }, + ], + }, + overrides: [ + { + // Intentionally NOT including '**/*.tsx'. The legacy eslintrc had + // `files: '**/*.ts'` (no tsx), and ESLint 8's default extension list + // was .js-only, so .tsx files were never actually linted. Adding them + // here would surface a large body of pre-existing issues unrelated to + // the v9 migration; address in a follow-up dedicated to lint cleanup. + files: ['**/*.ts'], + parser: '@typescript-eslint/parser', + parserOptions: { + project: './tsconfig.eslint.json', + tsconfigRootDir: __dirname, + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'airbnb-typescript/base', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier', + ], + rules: { + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + 'no-use-before-define': [0], + '@typescript-eslint/no-use-before-define': [1], + 'import/no-unresolved': 0, + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: ['**/*.test.ts', '**/*.spec.ts'], + }, + ], + quotes: [ + 2, + 'single', + { + avoidEscape: true, + }, + ], + '@typescript-eslint/no-unused-vars': [ + 2, + { argsIgnorePattern: '^_', caughtErrors: 'none' }, + ], + + // Rules removed in @typescript-eslint v6/v7/v8 but still referenced + // by airbnb-typescript@16; disable to avoid unknown-rule errors. + '@typescript-eslint/lines-between-class-members': 'off', + '@typescript-eslint/no-throw-literal': 'off', + '@typescript-eslint/space-before-function-paren': 'off', + '@typescript-eslint/no-loss-of-precision': 'off', + '@typescript-eslint/quotes': 'off', + + // New in @typescript-eslint v8 - was previously @typescript-eslint/no-empty-interface + // and @typescript-eslint/ban-types. Disabled to preserve pre-v8 behavior on + // existing code. Address in a follow-up code-cleanup PR. + '@typescript-eslint/no-empty-object-type': 'off', + + // Pre-existing relative-directory imports rely on Node module resolution. + // The legacy setup did not enforce file extensions for this case either. + 'import/extensions': 'off', + }, + }, + ], + }), + { + // Skip .tsx files and the .storybook dir to match what the legacy eslintrc + // setup actually linted in practice (default .js extensions plus the + // **/*.ts override). The .storybook/*.js files use modern syntax (optional + // chaining, JSX in .js) that would require a separate parser config; the + // .tsx files have a pre-existing backlog of lint issues. Both are out of + // scope for the v9 migration PR. + ignores: [ + 'tsconfig.json', + '**/*.d.ts', + '**/*.tsx', + '.storybook/**', + 'dist/**/*', + 'dist', + 'node_modules', + '*.config.js', + ], + }, +]; diff --git a/ts-packages/eslint-config-react-typescript/eslint.config.js b/ts-packages/eslint-config-react-typescript/eslint.config.js new file mode 100644 index 0000000000..f4037093ac --- /dev/null +++ b/ts-packages/eslint-config-react-typescript/eslint.config.js @@ -0,0 +1,38 @@ +/** + * Self-lint config for the shared eslint-config package itself. + * + * Intentionally lightweight - this file lints `index.js` (and only that), so + * we avoid pulling in the full airbnb / typescript-eslint chain that the + * exported config carries for consumers. + */ + +const js = require('@eslint/js'); +const prettierPlugin = require('eslint-plugin-prettier'); +const prettierConfig = require('eslint-config-prettier'); + +module.exports = [ + js.configs.recommended, + { + files: ['*.js'], + languageOptions: { + ecmaVersion: 2022, + sourceType: 'commonjs', + globals: { + module: 'readonly', + require: 'readonly', + __dirname: 'readonly', + process: 'readonly', + }, + }, + plugins: { + prettier: prettierPlugin, + }, + rules: { + ...prettierConfig.rules, + 'prettier/prettier': 'error', + }, + }, + { + ignores: ['node_modules/**', 'dist/**'], + }, +]; diff --git a/ts-packages/types/eslint.config.js b/ts-packages/types/eslint.config.js new file mode 100644 index 0000000000..466f949aa4 --- /dev/null +++ b/ts-packages/types/eslint.config.js @@ -0,0 +1,25 @@ +/** + * Flat ESLint config for @nymproject/types. + * + * Imports the shared React/TS preset and overrides parserOptions.project to + * point at this package's tsconfig (the shared preset assumes ./tsconfig.json + * which is what we already use here). + */ + +const sharedConfig = require('@nymproject/eslint-config-react-typescript'); +const path = require('path'); + +module.exports = [ + ...sharedConfig, + { + languageOptions: { + parserOptions: { + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, + }, + }, + { + ignores: ['dist/**', 'node_modules/**', '*.config.js'], + }, +]; diff --git a/ts-packages/webpack/eslint.config.js b/ts-packages/webpack/eslint.config.js new file mode 100644 index 0000000000..b0c50fe579 --- /dev/null +++ b/ts-packages/webpack/eslint.config.js @@ -0,0 +1,37 @@ +/** + * Lints the webpack helper scripts in this package (index.js, webpack.*.js). + * + * Intentionally minimal - prettier + eslint:recommended only; matches the + * pre-flat-config behavior from the previous .eslintrc.json. + */ + +const js = require('@eslint/js'); +const prettierPlugin = require('eslint-plugin-prettier'); +const prettierConfig = require('eslint-config-prettier'); + +module.exports = [ + js.configs.recommended, + { + files: ['*.js'], + languageOptions: { + ecmaVersion: 2022, + sourceType: 'commonjs', + globals: { + module: 'readonly', + require: 'readonly', + __dirname: 'readonly', + process: 'readonly', + }, + }, + plugins: { + prettier: prettierPlugin, + }, + rules: { + ...prettierConfig.rules, + 'prettier/prettier': 'error', + }, + }, + { + ignores: ['node_modules/**', 'dist/**'], + }, +]; From aaa8ee9d53a6f959d3caee42b99b1ee9a39729d5 Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Thu, 23 Apr 2026 15:42:27 +0100 Subject: [PATCH 27/37] Revert "Merge remote-tracking branch 'origin/develop' into chore/eslint-9-flat-config-migration" This reverts commit ab0f6af4b9b39057919990fbb6d185f5d48bf0a0, reversing changes made to cca19f36c2e645d5deca600c1cccd17f9920eb1f. --- nym-wallet/eslint.config.js | 23 --- .../packages/mui-theme/eslint.config.js | 123 --------------- .../react-components/eslint.config.js | 147 ------------------ .../eslint.config.js | 38 ----- ts-packages/types/eslint.config.js | 25 --- ts-packages/webpack/eslint.config.js | 37 ----- 6 files changed, 393 deletions(-) delete mode 100644 nym-wallet/eslint.config.js delete mode 100644 sdk/typescript/packages/mui-theme/eslint.config.js delete mode 100644 sdk/typescript/packages/react-components/eslint.config.js delete mode 100644 ts-packages/eslint-config-react-typescript/eslint.config.js delete mode 100644 ts-packages/types/eslint.config.js delete mode 100644 ts-packages/webpack/eslint.config.js diff --git a/nym-wallet/eslint.config.js b/nym-wallet/eslint.config.js deleted file mode 100644 index d4a9f8cec9..0000000000 --- a/nym-wallet/eslint.config.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Flat ESLint config for @nymproject/nym-wallet-app. - * - * Imports the shared React/TS preset and overrides parserOptions.project to - * point at the wallet's dedicated lint tsconfig. - */ - -const sharedConfig = require('@nymproject/eslint-config-react-typescript'); - -module.exports = [ - ...sharedConfig, - { - languageOptions: { - parserOptions: { - project: './tsconfig.eslint.json', - tsconfigRootDir: __dirname, - }, - }, - }, - { - ignores: ['dist/**', 'node_modules/**', 'src-tauri/**', '*.config.js'], - }, -]; diff --git a/sdk/typescript/packages/mui-theme/eslint.config.js b/sdk/typescript/packages/mui-theme/eslint.config.js deleted file mode 100644 index afe00b9339..0000000000 --- a/sdk/typescript/packages/mui-theme/eslint.config.js +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Flat ESLint config for @nymproject/mui-theme. - * - * Mirrors the previous inherited config at sdk/typescript/.eslintrc.js - * (airbnb-base, NOT airbnb-React). mui-theme has no dedicated tsconfig.eslint - * - it uses tsconfig.json, matching the previous parent default. - * - * Behavior preserved 1:1 with the pre-ESLint-9 setup. - */ - -const { FlatCompat } = require('@eslint/eslintrc'); -const js = require('@eslint/js'); - -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all, -}); - -module.exports = [ - ...compat.config({ - env: { - browser: true, - es6: true, - node: true, - jest: true, - }, - parserOptions: { - ecmaVersion: 2019, - sourceType: 'module', - }, - globals: { - Atomics: 'readonly', - SharedArrayBuffer: 'readonly', - }, - plugins: ['prettier'], - // airbnb-typescript/base is intentionally NOT at the top level - see the - // matching note in react-components/eslint.config.js for the rationale. - extends: ['airbnb-base', 'prettier'], - rules: { - 'prettier/prettier': 'error', - 'import/prefer-default-export': 'off', - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: ['**/*.test.[jt]s', '**/*.spec.[jt]s'], - }, - ], - 'import/extensions': [ - 'error', - 'ignorePackages', - { - ts: 'never', - js: 'never', - }, - ], - }, - overrides: [ - { - files: ['**/*.ts', '**/*.tsx'], - parser: '@typescript-eslint/parser', - parserOptions: { - project: './tsconfig.json', - tsconfigRootDir: __dirname, - }, - plugins: ['@typescript-eslint/eslint-plugin'], - extends: [ - 'airbnb-typescript/base', - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended', - 'prettier', - ], - rules: { - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-var-requires': 'off', - 'no-use-before-define': [0], - '@typescript-eslint/no-use-before-define': [1], - 'import/no-unresolved': 0, - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: ['**/*.test.ts', '**/*.spec.ts'], - }, - ], - quotes: [ - 2, - 'single', - { - avoidEscape: true, - }, - ], - '@typescript-eslint/no-unused-vars': [ - 2, - { argsIgnorePattern: '^_', caughtErrors: 'none' }, - ], - - // Rules removed in @typescript-eslint v6/v7/v8 but still referenced - // by airbnb-typescript@16; disable to avoid unknown-rule errors. - '@typescript-eslint/lines-between-class-members': 'off', - '@typescript-eslint/no-throw-literal': 'off', - '@typescript-eslint/space-before-function-paren': 'off', - '@typescript-eslint/no-loss-of-precision': 'off', - '@typescript-eslint/quotes': 'off', - - // New in @typescript-eslint v8 - was previously @typescript-eslint/no-empty-interface - // and @typescript-eslint/ban-types. Disabled to preserve pre-v8 behavior on - // existing code (the project relies on `{}` as the default type parameter in some - // .d.ts type aliases). Address in a follow-up code-cleanup PR. - '@typescript-eslint/no-empty-object-type': 'off', - - // Pre-existing relative-directory imports rely on Node module resolution - // (e.g. `import './theme'` resolving to `./theme/index.ts`). The legacy - // setup did not enforce file extensions for this case either. - 'import/extensions': 'off', - }, - }, - ], - }), - { - ignores: ['tsconfig.json', '**/*.d.ts', 'dist/**/*', 'dist', 'node_modules', '*.config.js'], - }, -]; diff --git a/sdk/typescript/packages/react-components/eslint.config.js b/sdk/typescript/packages/react-components/eslint.config.js deleted file mode 100644 index bd52a2428a..0000000000 --- a/sdk/typescript/packages/react-components/eslint.config.js +++ /dev/null @@ -1,147 +0,0 @@ -/** - * Flat ESLint config for @nymproject/react. - * - * Mirrors the previous inherited config at sdk/typescript/.eslintrc.js - * (airbnb-base, NOT airbnb-React) plus the per-package parserOptions override - * that previously lived in this directory's .eslintrc.json. - * - * Behavior preserved 1:1 with the pre-ESLint-9 setup. The fact that React - * rules are not active here is pre-existing and intentionally not changed in - * this migration PR. - */ - -const { FlatCompat } = require('@eslint/eslintrc'); -const js = require('@eslint/js'); - -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all, -}); - -module.exports = [ - ...compat.config({ - env: { - browser: true, - es6: true, - node: true, - jest: true, - }, - parserOptions: { - ecmaVersion: 2019, - sourceType: 'module', - }, - globals: { - Atomics: 'readonly', - SharedArrayBuffer: 'readonly', - }, - plugins: ['prettier'], - // airbnb-typescript/base is intentionally NOT at the top level because it - // bundles type-aware @typescript-eslint rules (e.g. dot-notation, return-await) - // that throw hard errors on .js files lacking parserOptions.project under - // typescript-eslint v8. The legacy v5 setup let these rules fail silently; - // this restructure preserves the effective behavior (no type-aware checks on - // .js files) without the new hard errors. - extends: ['airbnb-base', 'prettier'], - rules: { - 'prettier/prettier': 'error', - 'import/prefer-default-export': 'off', - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: ['**/*.test.[jt]s', '**/*.spec.[jt]s'], - }, - ], - 'import/extensions': [ - 'error', - 'ignorePackages', - { - ts: 'never', - js: 'never', - }, - ], - }, - overrides: [ - { - // Intentionally NOT including '**/*.tsx'. The legacy eslintrc had - // `files: '**/*.ts'` (no tsx), and ESLint 8's default extension list - // was .js-only, so .tsx files were never actually linted. Adding them - // here would surface a large body of pre-existing issues unrelated to - // the v9 migration; address in a follow-up dedicated to lint cleanup. - files: ['**/*.ts'], - parser: '@typescript-eslint/parser', - parserOptions: { - project: './tsconfig.eslint.json', - tsconfigRootDir: __dirname, - }, - plugins: ['@typescript-eslint/eslint-plugin'], - extends: [ - 'airbnb-typescript/base', - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended', - 'prettier', - ], - rules: { - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-var-requires': 'off', - 'no-use-before-define': [0], - '@typescript-eslint/no-use-before-define': [1], - 'import/no-unresolved': 0, - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: ['**/*.test.ts', '**/*.spec.ts'], - }, - ], - quotes: [ - 2, - 'single', - { - avoidEscape: true, - }, - ], - '@typescript-eslint/no-unused-vars': [ - 2, - { argsIgnorePattern: '^_', caughtErrors: 'none' }, - ], - - // Rules removed in @typescript-eslint v6/v7/v8 but still referenced - // by airbnb-typescript@16; disable to avoid unknown-rule errors. - '@typescript-eslint/lines-between-class-members': 'off', - '@typescript-eslint/no-throw-literal': 'off', - '@typescript-eslint/space-before-function-paren': 'off', - '@typescript-eslint/no-loss-of-precision': 'off', - '@typescript-eslint/quotes': 'off', - - // New in @typescript-eslint v8 - was previously @typescript-eslint/no-empty-interface - // and @typescript-eslint/ban-types. Disabled to preserve pre-v8 behavior on - // existing code. Address in a follow-up code-cleanup PR. - '@typescript-eslint/no-empty-object-type': 'off', - - // Pre-existing relative-directory imports rely on Node module resolution. - // The legacy setup did not enforce file extensions for this case either. - 'import/extensions': 'off', - }, - }, - ], - }), - { - // Skip .tsx files and the .storybook dir to match what the legacy eslintrc - // setup actually linted in practice (default .js extensions plus the - // **/*.ts override). The .storybook/*.js files use modern syntax (optional - // chaining, JSX in .js) that would require a separate parser config; the - // .tsx files have a pre-existing backlog of lint issues. Both are out of - // scope for the v9 migration PR. - ignores: [ - 'tsconfig.json', - '**/*.d.ts', - '**/*.tsx', - '.storybook/**', - 'dist/**/*', - 'dist', - 'node_modules', - '*.config.js', - ], - }, -]; diff --git a/ts-packages/eslint-config-react-typescript/eslint.config.js b/ts-packages/eslint-config-react-typescript/eslint.config.js deleted file mode 100644 index f4037093ac..0000000000 --- a/ts-packages/eslint-config-react-typescript/eslint.config.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Self-lint config for the shared eslint-config package itself. - * - * Intentionally lightweight - this file lints `index.js` (and only that), so - * we avoid pulling in the full airbnb / typescript-eslint chain that the - * exported config carries for consumers. - */ - -const js = require('@eslint/js'); -const prettierPlugin = require('eslint-plugin-prettier'); -const prettierConfig = require('eslint-config-prettier'); - -module.exports = [ - js.configs.recommended, - { - files: ['*.js'], - languageOptions: { - ecmaVersion: 2022, - sourceType: 'commonjs', - globals: { - module: 'readonly', - require: 'readonly', - __dirname: 'readonly', - process: 'readonly', - }, - }, - plugins: { - prettier: prettierPlugin, - }, - rules: { - ...prettierConfig.rules, - 'prettier/prettier': 'error', - }, - }, - { - ignores: ['node_modules/**', 'dist/**'], - }, -]; diff --git a/ts-packages/types/eslint.config.js b/ts-packages/types/eslint.config.js deleted file mode 100644 index 466f949aa4..0000000000 --- a/ts-packages/types/eslint.config.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Flat ESLint config for @nymproject/types. - * - * Imports the shared React/TS preset and overrides parserOptions.project to - * point at this package's tsconfig (the shared preset assumes ./tsconfig.json - * which is what we already use here). - */ - -const sharedConfig = require('@nymproject/eslint-config-react-typescript'); -const path = require('path'); - -module.exports = [ - ...sharedConfig, - { - languageOptions: { - parserOptions: { - project: './tsconfig.json', - tsconfigRootDir: __dirname, - }, - }, - }, - { - ignores: ['dist/**', 'node_modules/**', '*.config.js'], - }, -]; diff --git a/ts-packages/webpack/eslint.config.js b/ts-packages/webpack/eslint.config.js deleted file mode 100644 index b0c50fe579..0000000000 --- a/ts-packages/webpack/eslint.config.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Lints the webpack helper scripts in this package (index.js, webpack.*.js). - * - * Intentionally minimal - prettier + eslint:recommended only; matches the - * pre-flat-config behavior from the previous .eslintrc.json. - */ - -const js = require('@eslint/js'); -const prettierPlugin = require('eslint-plugin-prettier'); -const prettierConfig = require('eslint-config-prettier'); - -module.exports = [ - js.configs.recommended, - { - files: ['*.js'], - languageOptions: { - ecmaVersion: 2022, - sourceType: 'commonjs', - globals: { - module: 'readonly', - require: 'readonly', - __dirname: 'readonly', - process: 'readonly', - }, - }, - plugins: { - prettier: prettierPlugin, - }, - rules: { - ...prettierConfig.rules, - 'prettier/prettier': 'error', - }, - }, - { - ignores: ['node_modules/**', 'dist/**'], - }, -]; From f94d6d51cf660b0dec253e4092d0cbaff74e9fd9 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Fri, 24 Apr 2026 14:11:19 +0200 Subject: [PATCH 28/37] adding debugging traces --- nym-ip-packet-client/src/connect.rs | 18 +++++++++++++++++- .../src/clients/connected_client_handler.rs | 11 ++++++++++- .../ip-packet-router/src/messages/request.rs | 2 ++ .../ip-packet-router/src/messages/response.rs | 10 +++++++++- 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/nym-ip-packet-client/src/connect.rs b/nym-ip-packet-client/src/connect.rs index e28405d321..78ca7b3dff 100644 --- a/nym-ip-packet-client/src/connect.rs +++ b/nym-ip-packet-client/src/connect.rs @@ -81,6 +81,16 @@ impl IprClientConnect { async fn send_connect_request(&self, ip_packet_router_address: Recipient) -> Result { let (request, request_id) = nym_ip_packet_requests::v9::new_connect_request(None); + tracing::info!( + request_id = request_id, + protocol_version = request.protocol.version, + current_version = crate::current::VERSION, + "Sending IPR connect request" + ); + if let Ok(bytes) = request.to_bytes() { + let prefix = bytes.get(0..2).unwrap_or(&bytes); + tracing::info!(request_id = request_id, bytes_0_2 = ?prefix, "IPR connect bytes"); + } // We use 20 surbs for the connect request because typically the IPR is configured to have // a min threshold of 10 surbs that it reserves for itself to request additional surbs. @@ -129,7 +139,13 @@ impl IprClientConnect { for msg in msgs { // Confirm that the version is correct if let Err(err) = check_ipr_message_version(&msg) { - tracing::info!("Mixnet message version mismatch: {err}"); + let raw: &[u8] = msg.message.as_ref(); + tracing::info!( + first_byte = raw.first().copied(), + expected = crate::current::VERSION, + len = raw.len(), + "Mixnet message version mismatch: {err}" + ); continue; } diff --git a/service-providers/ip-packet-router/src/clients/connected_client_handler.rs b/service-providers/ip-packet-router/src/clients/connected_client_handler.rs index e44b543276..f0b50580df 100644 --- a/service-providers/ip-packet-router/src/clients/connected_client_handler.rs +++ b/service-providers/ip-packet-router/src/clients/connected_client_handler.rs @@ -218,7 +218,16 @@ fn create_ip_packet_response( ClientVersion::V6 => IpPacketResponseV6::new_ip_packet(packets).to_bytes(), ClientVersion::V7 => IpPacketResponseV7::new_ip_packet(packets).to_bytes(), ClientVersion::V8 => IpPacketResponseV8::new_ip_packet(packets).to_bytes(), - ClientVersion::V9 => v9::new_ip_packet_response(packets).to_bytes(), + ClientVersion::V9 => { + let resp = v9::new_ip_packet_response(packets); + log::info!("IPR send data resp version byte: {}", resp.version); + let bytes = resp.to_bytes()?; + log::info!( + "IPR send data resp first byte: {:?}", + bytes.first().copied() + ); + Ok(bytes) + } } } diff --git a/service-providers/ip-packet-router/src/messages/request.rs b/service-providers/ip-packet-router/src/messages/request.rs index 0c613a2fd4..6f1fd0b153 100644 --- a/service-providers/ip-packet-router/src/messages/request.rs +++ b/service-providers/ip-packet-router/src/messages/request.rs @@ -88,6 +88,7 @@ impl TryFrom<&ReconstructedMessage> for IpPacketRequest { .message .first_chunk::<2>() .ok_or(IpPacketRouterError::EmptyPacket)?; + log::info!("IPR recv header bytes: {:02x?}", request_version); // With version v8 and onwards, the type of the service provider is included in the // header. @@ -103,6 +104,7 @@ impl TryFrom<&ReconstructedMessage> for IpPacketRequest { } let request_version = request_version[0]; + log::info!("IPR recv version byte: {request_version}"); match request_version { 6 => { let request_v6 = IpPacketRequestV6::from_reconstructed_message(reconstructed) diff --git a/service-providers/ip-packet-router/src/messages/response.rs b/service-providers/ip-packet-router/src/messages/response.rs index deefccc146..0955b1e25e 100644 --- a/service-providers/ip-packet-router/src/messages/response.rs +++ b/service-providers/ip-packet-router/src/messages/response.rs @@ -133,7 +133,15 @@ impl VersionedResponse { ClientVersion::V9 => { let mut resp = IpPacketResponseV8::try_from(self)?; resp.version = nym_ip_packet_requests::v9::VERSION; - resp.to_bytes() + log::info!("IPR send control resp version byte: {}", resp.version); + let bytes = resp.to_bytes(); + if let Ok(ref bytes) = bytes { + log::info!( + "IPR send control resp first byte: {:?}", + bytes.first().copied() + ); + } + bytes } } .map_err(|err| IpPacketRouterError::FailedToSerializeResponsePacket { source: err }) From 2653d12e550757a55ec0fcf5ebd6f4d8804e0df6 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Fri, 24 Apr 2026 16:07:49 +0200 Subject: [PATCH 29/37] fix ipr msg, and unit tests --- Cargo.lock | 1 + common/ip-packet-requests/src/lib.rs | 20 +++++ nym-gateway-probe/src/common/helpers.rs | 8 +- nym-gateway-probe/src/common/icmp.rs | 29 +++++-- nym-gateway-probe/src/common/probe_tests.rs | 23 ++++-- nym-ip-packet-client/Cargo.toml | 1 + nym-ip-packet-client/src/connect.rs | 46 ++++++++--- nym-ip-packet-client/src/helpers.rs | 26 +++--- nym-ip-packet-client/src/lib.rs | 1 + nym-ip-packet-client/src/lp_stream.rs | 79 +++++++++++++++++++ .../nym-sdk/src/ipr_wrapper/ip_mix_stream.rs | 10 +-- .../ip-packet-router/src/mixnet_listener.rs | 24 ++++-- 12 files changed, 219 insertions(+), 49 deletions(-) create mode 100644 nym-ip-packet-client/src/lp_stream.rs diff --git a/Cargo.lock b/Cargo.lock index a1015be7fb..970150dff0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7028,6 +7028,7 @@ dependencies = [ "bytes", "futures", "nym-ip-packet-requests", + "nym-lp", "nym-sdk", "thiserror 2.0.12", "tokio", diff --git a/common/ip-packet-requests/src/lib.rs b/common/ip-packet-requests/src/lib.rs index f3014a69ec..2ff84dddee 100644 --- a/common/ip-packet-requests/src/lib.rs +++ b/common/ip-packet-requests/src/lib.rs @@ -12,6 +12,26 @@ pub mod v7; pub mod v8; pub mod v9; +/// Highest IPR protocol version that is allowed to be sent as a **non-stream** mixnet payload +/// (i.e. not wrapped in `LpFrameKind::SphinxStream`). +pub const MAX_NON_STREAM_VERSION: u8 = v8::VERSION; + +/// First IPR protocol version that **requires** the SphinxStream (LP) transport for non-stream +/// mixnet sends, matching the node-side enforcement in `ip-packet-router`. +pub const SPHINX_STREAM_VERSION_THRESHOLD: u8 = v9::VERSION; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn stream_transport_threshold_is_consistent() { + assert_eq!(MAX_NON_STREAM_VERSION, v8::VERSION); + assert_eq!(SPHINX_STREAM_VERSION_THRESHOLD, v9::VERSION); + assert!(SPHINX_STREAM_VERSION_THRESHOLD > MAX_NON_STREAM_VERSION); + } +} + // version 3: initial version // version 4: IPv6 support // version 5: Add severity level to info response diff --git a/nym-gateway-probe/src/common/helpers.rs b/nym-gateway-probe/src/common/helpers.rs index 5dc330e9cc..54822c3987 100644 --- a/nym-gateway-probe/src/common/helpers.rs +++ b/nym-gateway-probe/src/common/helpers.rs @@ -1,9 +1,10 @@ // Copyright 2026 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use nym_ip_packet_requests::v8::response::{ +use nym_ip_packet_client::current::response::{ ControlResponse, DataResponse, InfoLevel, IpPacketResponse, IpPacketResponseData, }; +use nym_ip_packet_client::lp_stream; use nym_sdk::{ DebugConfig, NymApiTopologyProvider, NymApiTopologyProviderConfig, NymNetworkDetails, TopologyProvider, mixnet::ReconstructedMessage, @@ -32,7 +33,10 @@ pub fn mixnet_debug_config( } pub fn unpack_data_response(reconstructed_message: &ReconstructedMessage) -> Option { - match IpPacketResponse::from_reconstructed_message(reconstructed_message) { + let payload = + lp_stream::maybe_unwrap_lp_stream_payload_from_reconstructed(reconstructed_message); + + match IpPacketResponse::from_bytes(payload) { Ok(response) => match response.data { IpPacketResponseData::Data(data_response) => Some(data_response), IpPacketResponseData::Control(control) => match *control { diff --git a/nym-gateway-probe/src/common/icmp.rs b/nym-gateway-probe/src/common/icmp.rs index ec757623f1..2d96a27da5 100644 --- a/nym-gateway-probe/src/common/icmp.rs +++ b/nym-gateway-probe/src/common/icmp.rs @@ -9,7 +9,7 @@ use nym_connection_monitor::{ wrap_icmp_in_ipv6, }, }; -use nym_ip_packet_requests::{IpPair, codec::MultiIpPacketCodec, v8::request::IpPacketRequest}; +use nym_ip_packet_requests::{IpPair, codec::MultiIpPacketCodec}; use nym_sdk::mixnet::{ InputMessage, MixnetClient, MixnetMessageSender, Recipient, TransmissionLane, }; @@ -25,6 +25,7 @@ pub async fn send_ping_v4( sequence_number: u16, destination: Ipv4Addr, exit_router_address: Recipient, + stream_id: u64, ) -> anyhow::Result<()> { let icmp_identifier = icmp_identifier(); let icmp_echo_request = create_icmpv4_echo_request(sequence_number, icmp_identifier)?; @@ -35,7 +36,12 @@ pub async fn send_ping_v4( MultiIpPacketCodec::bundle_one_packet(ipv4_packet.packet().to_vec().into()); // Wrap into a mixnet input message addressed to the IPR - let mixnet_message = create_input_message(exit_router_address, bundled_packet)?; + let mixnet_message = create_input_message( + exit_router_address, + bundled_packet, + stream_id, + sequence_number, + )?; mixnet_client.send(mixnet_message).await?; Ok(()) @@ -47,6 +53,7 @@ pub async fn send_ping_v6( sequence_number: u16, destination: Ipv6Addr, exit_router_address: Recipient, + stream_id: u64, ) -> anyhow::Result<()> { let icmp_identifier = icmp_identifier(); let icmp_echo_request = create_icmpv6_echo_request( @@ -62,7 +69,12 @@ pub async fn send_ping_v6( MultiIpPacketCodec::bundle_one_packet(ipv6_packet.packet().to_vec().into()); // Wrap into a mixnet input message addressed to the IPR - let mixnet_message = create_input_message(exit_router_address, bundled_packet)?; + let mixnet_message = create_input_message( + exit_router_address, + bundled_packet, + stream_id, + sequence_number, + )?; // Send across the mixnet mixnet_client.send(mixnet_message).await?; @@ -72,15 +84,22 @@ pub async fn send_ping_v6( fn create_input_message( recipient: impl Into, bundled_packets: Bytes, + stream_id: u64, + sequence_number: u16, ) -> anyhow::Result { - let packet = IpPacketRequest::new_data_request(bundled_packets).to_bytes()?; + let packet = nym_ip_packet_client::current::new_data_request(bundled_packets).to_bytes()?; + let framed_packet = nym_ip_packet_client::lp_stream::encode_stream_frame( + stream_id, + sequence_number as u32, + packet, + ); let lane = TransmissionLane::General; let packet_type = None; let surbs = 0; Ok(InputMessage::new_anonymous( recipient.into(), - packet, + framed_packet, surbs, lane, packet_type, diff --git a/nym-gateway-probe/src/common/probe_tests.rs b/nym-gateway-probe/src/common/probe_tests.rs index d37a1042d2..081fba9c21 100644 --- a/nym-gateway-probe/src/common/probe_tests.rs +++ b/nym-gateway-probe/src/common/probe_tests.rs @@ -256,8 +256,8 @@ pub async fn do_ping( let (maybe_ip_pair, mut mixnet_client) = connect_exit(mixnet_client, exit_router_address).await; match maybe_ip_pair { - Some(ip_pair) => ( - do_ping_exit(&mut mixnet_client, ip_pair, exit_router_address).await, + Some((ip_pair, stream_id)) => ( + do_ping_exit(&mut mixnet_client, ip_pair, stream_id, exit_router_address).await, mixnet_client, ), None => (Ok(Some(Exit::fail_to_connect())), mixnet_client), @@ -304,7 +304,7 @@ async fn do_ping_entry( async fn connect_exit( mixnet_client: MixnetClient, exit_router_address: Recipient, -) -> (Option, MixnetClient) { +) -> (Option<(IpPair, u64)>, MixnetClient) { // Step 2: connect to the exit gateway info!( "Connecting to exit gateway: {}", @@ -315,12 +315,19 @@ async fn connect_exit( let mut ipr_client = IprClientConnect::new(mixnet_client, cancel_token); let maybe_ip_pair = ipr_client.connect(exit_router_address).await; + let stream_id = ipr_client.active_stream_id(); let mixnet_client = ipr_client.into_mixnet_client(); if let Ok(our_ips) = maybe_ip_pair { info!("Successfully connected to exit gateway"); info!("Using mixnet VPN IP addresses: {our_ips}"); - (Some(our_ips), mixnet_client) + let Some(stream_id) = stream_id else { + tracing::warn!( + "No active IPR stream id set after connect; cannot run IPR data-plane tests" + ); + return (None, mixnet_client); + }; + (Some((our_ips, stream_id)), mixnet_client) } else { (None, mixnet_client) } @@ -329,10 +336,11 @@ async fn connect_exit( pub async fn do_ping_exit( mixnet_client: &mut MixnetClient, our_ips: IpPair, + stream_id: u64, exit_router_address: Recipient, ) -> anyhow::Result> { // Step 3: perform ICMP connectivity checks for the exit gateway - send_icmp_pings(mixnet_client, our_ips, exit_router_address).await?; + send_icmp_pings(mixnet_client, our_ips, exit_router_address, stream_id).await?; listen_for_icmp_ping_replies(mixnet_client, our_ips).await } @@ -340,6 +348,7 @@ async fn send_icmp_pings( mixnet_client: &MixnetClient, our_ips: IpPair, exit_router_address: Recipient, + stream_id: u64, ) -> anyhow::Result<()> { // ipv4 addresses for testing let ipr_tun_ip_v4 = NYM_TUN_DEVICE_ADDRESS_V4; @@ -361,6 +370,7 @@ async fn send_icmp_pings( ii, ipr_tun_ip_v4, exit_router_address, + stream_id, ) .await?; icmp::send_ping_v4( @@ -369,6 +379,7 @@ async fn send_icmp_pings( ii, external_ip_v4, exit_router_address, + stream_id, ) .await?; } @@ -381,6 +392,7 @@ async fn send_icmp_pings( ii, ipr_tun_ip_v6, exit_router_address, + stream_id, ) .await?; icmp::send_ping_v6( @@ -389,6 +401,7 @@ async fn send_icmp_pings( ii, external_ip_v6, exit_router_address, + stream_id, ) .await?; } diff --git a/nym-ip-packet-client/Cargo.toml b/nym-ip-packet-client/Cargo.toml index 47b2de02c3..4117d80350 100644 --- a/nym-ip-packet-client/Cargo.toml +++ b/nym-ip-packet-client/Cargo.toml @@ -26,3 +26,4 @@ tracing.workspace = true nym-sdk = { workspace = true } nym-ip-packet-requests = { workspace = true } +nym-lp = { workspace = true } diff --git a/nym-ip-packet-client/src/connect.rs b/nym-ip-packet-client/src/connect.rs index 78ca7b3dff..6ca04e2227 100644 --- a/nym-ip-packet-client/src/connect.rs +++ b/nym-ip-packet-client/src/connect.rs @@ -14,7 +14,7 @@ use tracing::{debug, error}; use nym_ip_packet_requests::response_helpers::{self, IprResponseError}; use crate::{ - current::{request::IpPacketRequest, response::IpPacketResponse}, + current::{self, response::IpPacketResponse}, error::{Error, Result}, helpers::check_ipr_message_version, }; @@ -36,6 +36,7 @@ pub struct IprClientConnect { mixnet_client: MixnetClient, connected: ConnectionState, cancel_token: CancellationToken, + active_stream_id: Option, } impl IprClientConnect { @@ -44,6 +45,7 @@ impl IprClientConnect { mixnet_client, connected: ConnectionState::Disconnected, cancel_token, + active_stream_id: None, } } @@ -51,6 +53,10 @@ impl IprClientConnect { self.mixnet_client } + pub fn active_stream_id(&self) -> Option { + self.active_stream_id + } + pub async fn connect(&mut self, ip_packet_router_address: Recipient) -> Result { if self.connected != ConnectionState::Disconnected { return Err(Error::AlreadyConnected); @@ -79,8 +85,8 @@ impl IprClientConnect { self.listen_for_connect_response(request_id).await } - async fn send_connect_request(&self, ip_packet_router_address: Recipient) -> Result { - let (request, request_id) = nym_ip_packet_requests::v9::new_connect_request(None); + async fn send_connect_request(&mut self, ip_packet_router_address: Recipient) -> Result { + let (request, request_id) = current::new_connect_request(None); tracing::info!( request_id = request_id, protocol_version = request.protocol.version, @@ -95,10 +101,13 @@ impl IprClientConnect { // We use 20 surbs for the connect request because typically the IPR is configured to have // a min threshold of 10 surbs that it reserves for itself to request additional surbs. let surbs = 20; + let request_bytes = request.to_bytes()?; + let framed_bytes = maybe_wrap_stream_frame(request_id, 0, request_bytes); + self.active_stream_id = Some(request_id); self.mixnet_client - .send(create_input_message( + .send(create_input_message_bytes( ip_packet_router_address, - request, + framed_bytes, surbs, )?) .await @@ -151,7 +160,7 @@ impl IprClientConnect { // Then we deserialize the message tracing::debug!("IprClient: got message while waiting for connect response"); - let Ok(response) = IpPacketResponse::from_reconstructed_message(&msg) else { + let Ok(response) = ipr_response_from_reconstructed_message(&msg) else { // This is ok, it's likely just one of our self-pings tracing::debug!("Failed to deserialize mixnet message"); continue; @@ -176,14 +185,33 @@ impl IprClientConnect { } } -fn create_input_message( +fn maybe_wrap_stream_frame(stream_id: u64, sequence_num: u32, payload: Vec) -> Vec { + if !crate::lp_stream::current_requires_sphinx_stream_transport() { + return payload; + } + + crate::lp_stream::encode_stream_frame(stream_id, sequence_num, payload) +} + +fn ipr_response_from_reconstructed_message( + msg: &nym_sdk::mixnet::ReconstructedMessage, +) -> std::result::Result { + let payload = if crate::lp_stream::current_requires_sphinx_stream_transport() { + crate::lp_stream::maybe_unwrap_lp_stream_payload_from_reconstructed(msg) + } else { + &msg.message + }; + IpPacketResponse::from_bytes(payload) +} + +fn create_input_message_bytes( recipient: Recipient, - request: IpPacketRequest, + bytes: Vec, surbs: u32, ) -> Result { Ok(InputMessage::new_anonymous( recipient, - request.to_bytes()?, + bytes, surbs, TransmissionLane::General, None, diff --git a/nym-ip-packet-client/src/helpers.rs b/nym-ip-packet-client/src/helpers.rs index 1b31870ff8..cfa0957aec 100644 --- a/nym-ip-packet-client/src/helpers.rs +++ b/nym-ip-packet-client/src/helpers.rs @@ -7,18 +7,16 @@ use nym_sdk::mixnet::ReconstructedMessage; use crate::{current::VERSION as CURRENT_VERSION, error::Result}; pub(crate) fn check_ipr_message_version(message: &ReconstructedMessage) -> Result<()> { - nym_ip_packet_requests::response_helpers::check_ipr_message_version( - &message.message, - CURRENT_VERSION, - ) - .map_err(|e| match e { - IprResponseError::NoVersionByte => crate::Error::NoVersionInMessage, - IprResponseError::VersionMismatch { expected, received } if received < expected => { - crate::Error::ReceivedResponseWithOldVersion { expected, received } - } - IprResponseError::VersionMismatch { expected, received } => { - crate::Error::ReceivedResponseWithNewVersion { expected, received } - } - _ => crate::Error::NoVersionInMessage, - }) + let payload = crate::lp_stream::maybe_unwrap_lp_stream_payload_from_reconstructed(message); + nym_ip_packet_requests::response_helpers::check_ipr_message_version(payload, CURRENT_VERSION) + .map_err(|e| match e { + IprResponseError::NoVersionByte => crate::Error::NoVersionInMessage, + IprResponseError::VersionMismatch { expected, received } if received < expected => { + crate::Error::ReceivedResponseWithOldVersion { expected, received } + } + IprResponseError::VersionMismatch { expected, received } => { + crate::Error::ReceivedResponseWithNewVersion { expected, received } + } + _ => crate::Error::NoVersionInMessage, + }) } diff --git a/nym-ip-packet-client/src/lib.rs b/nym-ip-packet-client/src/lib.rs index 0ab5c2eb24..40478fc650 100644 --- a/nym-ip-packet-client/src/lib.rs +++ b/nym-ip-packet-client/src/lib.rs @@ -5,6 +5,7 @@ mod connect; mod error; mod helpers; mod listener; +pub mod lp_stream; pub use connect::IprClientConnect; pub use error::Error; diff --git a/nym-ip-packet-client/src/lp_stream.rs b/nym-ip-packet-client/src/lp_stream.rs new file mode 100644 index 0000000000..821ef39d0d --- /dev/null +++ b/nym-ip-packet-client/src/lp_stream.rs @@ -0,0 +1,79 @@ +use bytes::BytesMut; +use nym_ip_packet_requests::SPHINX_STREAM_VERSION_THRESHOLD; +use nym_lp::packet::frame::{ + LpFrame, LpFrameHeader, LpFrameKind, SphinxStreamFrameAttributes, SphinxStreamMsgType, +}; +use nym_sdk::mixnet::ReconstructedMessage; + +/// Whether the "current" IPR client is operating at a version where the node expects +/// non-stream mixnet IPR messages to be LP Stream framed (see `SPHINX_STREAM_VERSION_THRESHOLD`). +pub(crate) fn current_requires_sphinx_stream_transport() -> bool { + crate::current::VERSION >= SPHINX_STREAM_VERSION_THRESHOLD +} + +pub fn maybe_unwrap_lp_stream_payload(data: &[u8]) -> &[u8] { + if data.len() < LpFrameHeader::SIZE { + return data; + } + let Ok(header) = LpFrameHeader::parse(data) else { + return data; + }; + if header.kind == LpFrameKind::SphinxStream { + &data[LpFrameHeader::SIZE..] + } else { + data + } +} + +pub fn maybe_unwrap_lp_stream_payload_from_reconstructed(message: &ReconstructedMessage) -> &[u8] { + maybe_unwrap_lp_stream_payload(&message.message) +} + +pub fn encode_stream_frame(stream_id: u64, sequence_num: u32, payload: Vec) -> Vec { + let attrs = SphinxStreamFrameAttributes { + stream_id, + msg_type: SphinxStreamMsgType::Data, + sequence_num, + }; + let frame = LpFrame::new_stream(attrs, payload); + let mut buf = BytesMut::with_capacity(LpFrameHeader::SIZE + frame.content.len()); + frame.encode(&mut buf); + buf.to_vec() +} + +#[cfg(test)] +mod tests { + use super::*; + use nym_lp::packet::frame::SphinxStreamFrameAttributes; + + #[test] + fn stream_frame_roundtrip_unwraps_payload() { + let stream_id = 0x0123_4567_89ab_cdef; + let seq = 42u32; + let payload = b"hello-ipr".to_vec(); + + let framed = encode_stream_frame(stream_id, seq, payload.clone()); + + let header = LpFrameHeader::parse(&framed).expect("valid lp header"); + assert_eq!(header.kind, LpFrameKind::SphinxStream); + + let attrs = + SphinxStreamFrameAttributes::parse(&header.frame_attributes).expect("valid attrs"); + assert_eq!(attrs.stream_id, stream_id); + assert_eq!(attrs.sequence_num, seq); + assert_eq!(attrs.msg_type, SphinxStreamMsgType::Data); + + let unwrapped = maybe_unwrap_lp_stream_payload(&framed); + assert_eq!(unwrapped, payload.as_slice()); + } + + #[test] + fn unwrap_noops_on_non_stream_or_malformed_data() { + let raw = b"\x09\x00\x01\x02\x03"; + assert_eq!(maybe_unwrap_lp_stream_payload(raw), raw); + + // malformed header: not enough bytes for LP header + let short = b"\x00\x01"; + assert_eq!(maybe_unwrap_lp_stream_payload(short), short); + } +} diff --git a/sdk/rust/nym-sdk/src/ipr_wrapper/ip_mix_stream.rs b/sdk/rust/nym-sdk/src/ipr_wrapper/ip_mix_stream.rs index 13cfb56e23..b4e75746e0 100644 --- a/sdk/rust/nym-sdk/src/ipr_wrapper/ip_mix_stream.rs +++ b/sdk/rust/nym-sdk/src/ipr_wrapper/ip_mix_stream.rs @@ -9,11 +9,9 @@ use crate::ip_packet_client::{ use crate::mixnet::{MixnetClient, MixnetStream, Recipient}; use crate::Error; use bytes::Bytes; +use current_ipr::response::IpPacketResponse; use nym_ip_packet_requests::response_helpers; -use nym_ip_packet_requests::{ - v9::{self, response::IpPacketResponse}, - IpPair, -}; +use nym_ip_packet_requests::{v9 as current_ipr, IpPair}; use nym_network_defaults::NymNetworkDetails; use std::time::Duration; use tokio::io::AsyncWriteExt; @@ -107,7 +105,7 @@ impl IpMixStream { } async fn connect_tunnel(stream: &mut MixnetStream) -> Result { - let (request, request_id) = v9::new_connect_request(None); + let (request, request_id) = current_ipr::new_connect_request(None); debug!("Sending connect request with ID: {}", request_id); let request_bytes = request.to_bytes()?; @@ -146,7 +144,7 @@ impl IpMixStream { /// Send an IP packet through the tunnel. pub async fn send_ip_packet(&mut self, packet: &[u8]) -> Result<(), Error> { self.check_connected()?; - let request = v9::new_data_request(packet.to_vec().into()); + let request = current_ipr::new_data_request(packet.to_vec().into()); let request_bytes = request.to_bytes()?; self.stream .write_all(&request_bytes) diff --git a/service-providers/ip-packet-router/src/mixnet_listener.rs b/service-providers/ip-packet-router/src/mixnet_listener.rs index fa25adbf71..3295dfeeb1 100644 --- a/service-providers/ip-packet-router/src/mixnet_listener.rs +++ b/service-providers/ip-packet-router/src/mixnet_listener.rs @@ -23,6 +23,7 @@ use crate::{ }; use futures::StreamExt; use nym_ip_packet_requests::codec::MultiIpPacketCodec; +use nym_ip_packet_requests::{MAX_NON_STREAM_VERSION, SPHINX_STREAM_VERSION_THRESHOLD}; use nym_lp::packet::frame::{LpFrameHeader, LpFrameKind, SphinxStreamFrameAttributes}; use nym_sdk::mixnet::MixnetMessageSender; use nym_sphinx::receiver::ReconstructedMessage; @@ -559,8 +560,9 @@ impl MixnetListener { /// /// # Version / transport enforcement /// - /// - LP Stream frames (`stream_id` is `Some`) **must** carry v9+ payloads. - /// - Non-stream messages (`stream_id` is `None`) **must** be v8 or lower. + /// - LP Stream frames (`stream_id` is `Some`) **must** carry payloads with version + /// `>= SPHINX_STREAM_VERSION_THRESHOLD` (see `nym_ip_packet_requests`). + /// - Non-stream messages (`stream_id` is `None`) **must** be `<= MAX_NON_STREAM_VERSION`. /// /// Messages that violate these rules are dropped. async fn on_ipr_message( @@ -578,16 +580,22 @@ impl MixnetListener { }?; // Enforce version/transport consistency: - // - LP Stream frames must carry v9+ payloads - // - Non-stream messages must be v8 or lower + // - LP Stream frames must carry payloads at/above the SphinxStream threshold + // - Non-stream messages must be at/below the max non-stream version let version_num = request.version().into_u8(); - if stream_id.is_some() && version_num < 9 { - log::warn!("LP Stream frame contains v{version_num} payload, expected v9+; dropping",); + if stream_id.is_some() && version_num < SPHINX_STREAM_VERSION_THRESHOLD { + log::warn!( + "LP Stream frame contains v{version_num} payload, expected v{expected}+; dropping", + expected = SPHINX_STREAM_VERSION_THRESHOLD + ); return Ok(vec![]); } - if stream_id.is_none() && version_num >= 9 { - log::warn!("Non-stream message claims v{version_num}, expected v8 or lower; dropping",); + if stream_id.is_none() && version_num > MAX_NON_STREAM_VERSION { + log::warn!( + "Non-stream message claims v{version_num}, expected v{expected} or lower; dropping", + expected = MAX_NON_STREAM_VERSION + ); return Ok(vec![]); } From 54ba710ea062e071316a2cad15c846b74edd76ab Mon Sep 17 00:00:00 2001 From: benedetta davico <46782255+benedettadavico@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:33:57 +0200 Subject: [PATCH 30/37] Change CI platform from ubuntu-22.04 to arc-ubuntu-22.04 --- .github/workflows/ci-build-upload-binaries.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-build-upload-binaries.yml b/.github/workflows/ci-build-upload-binaries.yml index db189fe80f..03ac19b7f2 100644 --- a/.github/workflows/ci-build-upload-binaries.yml +++ b/.github/workflows/ci-build-upload-binaries.yml @@ -36,7 +36,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ubuntu-22.04] + platform: [arc-ubuntu-22.04] runs-on: ${{ matrix.platform }} env: From 02a926b74a63fe9f75f6a9f893cf930dc06af425 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Mon, 27 Apr 2026 10:10:08 +0200 Subject: [PATCH 31/37] addressing comments --- common/ip-packet-requests/src/lib.rs | 4 +- nym-gateway-probe/src/common/probe_tests.rs | 2 +- nym-ip-packet-client/src/connect.rs | 41 +++++++++++-------- nym-ip-packet-client/src/lp_stream.rs | 3 ++ .../src/clients/connected_client_handler.rs | 8 +--- .../ip-packet-router/src/messages/request.rs | 2 - .../ip-packet-router/src/messages/response.rs | 7 ---- 7 files changed, 31 insertions(+), 36 deletions(-) diff --git a/common/ip-packet-requests/src/lib.rs b/common/ip-packet-requests/src/lib.rs index 2ff84dddee..eb1ef05086 100644 --- a/common/ip-packet-requests/src/lib.rs +++ b/common/ip-packet-requests/src/lib.rs @@ -26,8 +26,8 @@ mod tests { #[test] fn stream_transport_threshold_is_consistent() { - assert_eq!(MAX_NON_STREAM_VERSION, v8::VERSION); - assert_eq!(SPHINX_STREAM_VERSION_THRESHOLD, v9::VERSION); + assert_eq!(MAX_NON_STREAM_VERSION, 8); + assert_eq!(SPHINX_STREAM_VERSION_THRESHOLD, 9); assert!(SPHINX_STREAM_VERSION_THRESHOLD > MAX_NON_STREAM_VERSION); } } diff --git a/nym-gateway-probe/src/common/probe_tests.rs b/nym-gateway-probe/src/common/probe_tests.rs index 081fba9c21..7f6bee2d01 100644 --- a/nym-gateway-probe/src/common/probe_tests.rs +++ b/nym-gateway-probe/src/common/probe_tests.rs @@ -315,7 +315,7 @@ async fn connect_exit( let mut ipr_client = IprClientConnect::new(mixnet_client, cancel_token); let maybe_ip_pair = ipr_client.connect(exit_router_address).await; - let stream_id = ipr_client.active_stream_id(); + let stream_id = ipr_client.stream_id(); let mixnet_client = ipr_client.into_mixnet_client(); if let Ok(our_ips) = maybe_ip_pair { diff --git a/nym-ip-packet-client/src/connect.rs b/nym-ip-packet-client/src/connect.rs index 6ca04e2227..9050e676e7 100644 --- a/nym-ip-packet-client/src/connect.rs +++ b/nym-ip-packet-client/src/connect.rs @@ -24,8 +24,12 @@ const IPR_CONNECT_TIMEOUT: Duration = Duration::from_secs(10); #[derive(Clone, Debug, PartialEq, Eq)] enum ConnectionState { Disconnected, - Connecting, - Connected, + Connecting { + stream_id: u64, + }, + Connected { + stream_id: u64, + }, #[allow(unused)] Disconnecting, } @@ -36,7 +40,6 @@ pub struct IprClientConnect { mixnet_client: MixnetClient, connected: ConnectionState, cancel_token: CancellationToken, - active_stream_id: Option, } impl IprClientConnect { @@ -45,7 +48,6 @@ impl IprClientConnect { mixnet_client, connected: ConnectionState::Disconnected, cancel_token, - active_stream_id: None, } } @@ -53,8 +55,12 @@ impl IprClientConnect { self.mixnet_client } - pub fn active_stream_id(&self) -> Option { - self.active_stream_id + pub fn stream_id(&self) -> Option { + match self.connected { + ConnectionState::Connecting { stream_id } + | ConnectionState::Connected { stream_id } => Some(stream_id), + ConnectionState::Disconnected | ConnectionState::Disconnecting => None, + } } pub async fn connect(&mut self, ip_packet_router_address: Recipient) -> Result { @@ -63,11 +69,13 @@ impl IprClientConnect { } tracing::info!("Connecting to exit gateway"); - self.connected = ConnectionState::Connecting; match self.connect_inner(ip_packet_router_address).await { Ok(ips) => { debug!("Successfully connected to the ip-packet-router"); - self.connected = ConnectionState::Connected; + let Some(stream_id) = self.stream_id() else { + return Err(Error::UnexpectedConnectResponse); + }; + self.connected = ConnectionState::Connected { stream_id }; Ok(ips) } Err(err) => { @@ -80,6 +88,9 @@ impl IprClientConnect { async fn connect_inner(&mut self, ip_packet_router_address: Recipient) -> Result { let request_id = self.send_connect_request(ip_packet_router_address).await?; + self.connected = ConnectionState::Connecting { + stream_id: request_id, + }; debug!("Waiting for reply..."); self.listen_for_connect_response(request_id).await @@ -95,7 +106,8 @@ impl IprClientConnect { ); if let Ok(bytes) = request.to_bytes() { let prefix = bytes.get(0..2).unwrap_or(&bytes); - tracing::info!(request_id = request_id, bytes_0_2 = ?prefix, "IPR connect bytes"); + let prefix_hex = format!("{:02x?}", prefix); + tracing::info!(request_id = request_id, prefix = %prefix_hex, "IPR connect bytes prefix"); } // We use 20 surbs for the connect request because typically the IPR is configured to have @@ -103,9 +115,8 @@ impl IprClientConnect { let surbs = 20; let request_bytes = request.to_bytes()?; let framed_bytes = maybe_wrap_stream_frame(request_id, 0, request_bytes); - self.active_stream_id = Some(request_id); self.mixnet_client - .send(create_input_message_bytes( + .send(create_input_message( ip_packet_router_address, framed_bytes, surbs, @@ -149,7 +160,7 @@ impl IprClientConnect { // Confirm that the version is correct if let Err(err) = check_ipr_message_version(&msg) { let raw: &[u8] = msg.message.as_ref(); - tracing::info!( + tracing::warn!( first_byte = raw.first().copied(), expected = crate::current::VERSION, len = raw.len(), @@ -204,11 +215,7 @@ fn ipr_response_from_reconstructed_message( IpPacketResponse::from_bytes(payload) } -fn create_input_message_bytes( - recipient: Recipient, - bytes: Vec, - surbs: u32, -) -> Result { +fn create_input_message(recipient: Recipient, bytes: Vec, surbs: u32) -> Result { Ok(InputMessage::new_anonymous( recipient, bytes, diff --git a/nym-ip-packet-client/src/lp_stream.rs b/nym-ip-packet-client/src/lp_stream.rs index 821ef39d0d..813c7feb30 100644 --- a/nym-ip-packet-client/src/lp_stream.rs +++ b/nym-ip-packet-client/src/lp_stream.rs @@ -4,6 +4,7 @@ use nym_lp::packet::frame::{ LpFrame, LpFrameHeader, LpFrameKind, SphinxStreamFrameAttributes, SphinxStreamMsgType, }; use nym_sdk::mixnet::ReconstructedMessage; +use tracing::trace; /// Whether the "current" IPR client is operating at a version where the node expects /// non-stream mixnet IPR messages to be LP Stream framed (see `SPHINX_STREAM_VERSION_THRESHOLD`). @@ -16,11 +17,13 @@ pub fn maybe_unwrap_lp_stream_payload(data: &[u8]) -> &[u8] { return data; } let Ok(header) = LpFrameHeader::parse(data) else { + trace!("expected LP header but failed to parse; treating as raw payload"); return data; }; if header.kind == LpFrameKind::SphinxStream { &data[LpFrameHeader::SIZE..] } else { + trace!(kind = ?header.kind, "lp header parsed but not a sphinx stream frame; treating as raw payload"); data } } diff --git a/service-providers/ip-packet-router/src/clients/connected_client_handler.rs b/service-providers/ip-packet-router/src/clients/connected_client_handler.rs index f0b50580df..ff0e8e4924 100644 --- a/service-providers/ip-packet-router/src/clients/connected_client_handler.rs +++ b/service-providers/ip-packet-router/src/clients/connected_client_handler.rs @@ -220,13 +220,7 @@ fn create_ip_packet_response( ClientVersion::V8 => IpPacketResponseV8::new_ip_packet(packets).to_bytes(), ClientVersion::V9 => { let resp = v9::new_ip_packet_response(packets); - log::info!("IPR send data resp version byte: {}", resp.version); - let bytes = resp.to_bytes()?; - log::info!( - "IPR send data resp first byte: {:?}", - bytes.first().copied() - ); - Ok(bytes) + resp.to_bytes() } } } diff --git a/service-providers/ip-packet-router/src/messages/request.rs b/service-providers/ip-packet-router/src/messages/request.rs index 6f1fd0b153..0c613a2fd4 100644 --- a/service-providers/ip-packet-router/src/messages/request.rs +++ b/service-providers/ip-packet-router/src/messages/request.rs @@ -88,7 +88,6 @@ impl TryFrom<&ReconstructedMessage> for IpPacketRequest { .message .first_chunk::<2>() .ok_or(IpPacketRouterError::EmptyPacket)?; - log::info!("IPR recv header bytes: {:02x?}", request_version); // With version v8 and onwards, the type of the service provider is included in the // header. @@ -104,7 +103,6 @@ impl TryFrom<&ReconstructedMessage> for IpPacketRequest { } let request_version = request_version[0]; - log::info!("IPR recv version byte: {request_version}"); match request_version { 6 => { let request_v6 = IpPacketRequestV6::from_reconstructed_message(reconstructed) diff --git a/service-providers/ip-packet-router/src/messages/response.rs b/service-providers/ip-packet-router/src/messages/response.rs index 0955b1e25e..e928487a26 100644 --- a/service-providers/ip-packet-router/src/messages/response.rs +++ b/service-providers/ip-packet-router/src/messages/response.rs @@ -133,14 +133,7 @@ impl VersionedResponse { ClientVersion::V9 => { let mut resp = IpPacketResponseV8::try_from(self)?; resp.version = nym_ip_packet_requests::v9::VERSION; - log::info!("IPR send control resp version byte: {}", resp.version); let bytes = resp.to_bytes(); - if let Ok(ref bytes) = bytes { - log::info!( - "IPR send control resp first byte: {:?}", - bytes.first().copied() - ); - } bytes } } From ce39fb667562fb168b2b65c61d3c51ece55772db Mon Sep 17 00:00:00 2001 From: benedetta davico <46782255+benedettadavico@users.noreply.github.com> Date: Mon, 27 Apr 2026 10:20:10 +0200 Subject: [PATCH 32/37] Update publish-nym-binaries.yml --- .github/workflows/publish-nym-binaries.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-nym-binaries.yml b/.github/workflows/publish-nym-binaries.yml index e2f4c2463f..0a15eb2717 100644 --- a/.github/workflows/publish-nym-binaries.yml +++ b/.github/workflows/publish-nym-binaries.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-22.04 + - os: arc-ubuntu-22.04 target: x86_64-unknown-linux-gnu runs-on: ${{ matrix.os }} From f13a2a6c065cb7adb27e8469fa679ff3e581bc4f Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Mon, 27 Apr 2026 10:45:42 +0200 Subject: [PATCH 33/37] change to warn level --- nym-ip-packet-client/src/lp_stream.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nym-ip-packet-client/src/lp_stream.rs b/nym-ip-packet-client/src/lp_stream.rs index 813c7feb30..75171985fc 100644 --- a/nym-ip-packet-client/src/lp_stream.rs +++ b/nym-ip-packet-client/src/lp_stream.rs @@ -17,7 +17,7 @@ pub fn maybe_unwrap_lp_stream_payload(data: &[u8]) -> &[u8] { return data; } let Ok(header) = LpFrameHeader::parse(data) else { - trace!("expected LP header but failed to parse; treating as raw payload"); + warn!("expected LP header but failed to parse; treating as raw payload"); return data; }; if header.kind == LpFrameKind::SphinxStream { From 1451db39e64621af5fbb5f322f05398450c78487 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Mon, 27 Apr 2026 11:27:41 +0200 Subject: [PATCH 34/37] warn --- nym-ip-packet-client/src/connect.rs | 6 +---- nym-ip-packet-client/src/lp_stream.rs | 38 +++++++++++++++++++++------ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/nym-ip-packet-client/src/connect.rs b/nym-ip-packet-client/src/connect.rs index 9050e676e7..3c80882edb 100644 --- a/nym-ip-packet-client/src/connect.rs +++ b/nym-ip-packet-client/src/connect.rs @@ -207,11 +207,7 @@ fn maybe_wrap_stream_frame(stream_id: u64, sequence_num: u32, payload: Vec) fn ipr_response_from_reconstructed_message( msg: &nym_sdk::mixnet::ReconstructedMessage, ) -> std::result::Result { - let payload = if crate::lp_stream::current_requires_sphinx_stream_transport() { - crate::lp_stream::maybe_unwrap_lp_stream_payload_from_reconstructed(msg) - } else { - &msg.message - }; + let payload = crate::lp_stream::unwrap_ipr_payload_from_reconstructed(msg); IpPacketResponse::from_bytes(payload) } diff --git a/nym-ip-packet-client/src/lp_stream.rs b/nym-ip-packet-client/src/lp_stream.rs index 75171985fc..262c65ebcb 100644 --- a/nym-ip-packet-client/src/lp_stream.rs +++ b/nym-ip-packet-client/src/lp_stream.rs @@ -4,7 +4,7 @@ use nym_lp::packet::frame::{ LpFrame, LpFrameHeader, LpFrameKind, SphinxStreamFrameAttributes, SphinxStreamMsgType, }; use nym_sdk::mixnet::ReconstructedMessage; -use tracing::trace; +use tracing::warn; /// Whether the "current" IPR client is operating at a version where the node expects /// non-stream mixnet IPR messages to be LP Stream framed (see `SPHINX_STREAM_VERSION_THRESHOLD`). @@ -12,24 +12,46 @@ pub(crate) fn current_requires_sphinx_stream_transport() -> bool { crate::current::VERSION >= SPHINX_STREAM_VERSION_THRESHOLD } -pub fn maybe_unwrap_lp_stream_payload(data: &[u8]) -> &[u8] { +pub fn maybe_unwrap_lp_stream_payload(data: &[u8], warn_on_unexpected: bool) -> &[u8] { if data.len() < LpFrameHeader::SIZE { + if warn_on_unexpected { + warn!( + len = data.len(), + header_size = LpFrameHeader::SIZE, + "expected LP SphinxStream frame for IPR payload, but message is shorter than LP header; treating as raw payload" + ); + } return data; } + let Ok(header) = LpFrameHeader::parse(data) else { - warn!("expected LP header but failed to parse; treating as raw payload"); + if warn_on_unexpected { + warn!( + "expected LP SphinxStream frame for IPR payload, but failed to parse LP header; treating as raw payload" + ); + } return data; }; + if header.kind == LpFrameKind::SphinxStream { &data[LpFrameHeader::SIZE..] } else { - trace!(kind = ?header.kind, "lp header parsed but not a sphinx stream frame; treating as raw payload"); + if warn_on_unexpected { + warn!( + kind = ?header.kind, + "expected LP SphinxStream frame for IPR payload, but got different LP frame kind; treating as raw payload" + ); + } data } } pub fn maybe_unwrap_lp_stream_payload_from_reconstructed(message: &ReconstructedMessage) -> &[u8] { - maybe_unwrap_lp_stream_payload(&message.message) + maybe_unwrap_lp_stream_payload(&message.message, false) +} + +pub fn unwrap_ipr_payload_from_reconstructed(message: &ReconstructedMessage) -> &[u8] { + maybe_unwrap_lp_stream_payload(&message.message, current_requires_sphinx_stream_transport()) } pub fn encode_stream_frame(stream_id: u64, sequence_num: u32, payload: Vec) -> Vec { @@ -66,17 +88,17 @@ mod tests { assert_eq!(attrs.sequence_num, seq); assert_eq!(attrs.msg_type, SphinxStreamMsgType::Data); - let unwrapped = maybe_unwrap_lp_stream_payload(&framed); + let unwrapped = maybe_unwrap_lp_stream_payload(&framed, false); assert_eq!(unwrapped, payload.as_slice()); } #[test] fn unwrap_noops_on_non_stream_or_malformed_data() { let raw = b"\x09\x00\x01\x02\x03"; - assert_eq!(maybe_unwrap_lp_stream_payload(raw), raw); + assert_eq!(maybe_unwrap_lp_stream_payload(raw, false), raw); // malformed header: not enough bytes for LP header let short = b"\x00\x01"; - assert_eq!(maybe_unwrap_lp_stream_payload(short), short); + assert_eq!(maybe_unwrap_lp_stream_payload(short, false), short); } } From 917993d8fb6ac9d2e35f198e93d3da706091e2a7 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Mon, 27 Apr 2026 12:17:31 +0200 Subject: [PATCH 35/37] clean --- nym-ip-packet-client/src/connect.rs | 4 +++- nym-ip-packet-client/src/lp_stream.rs | 4 ---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/nym-ip-packet-client/src/connect.rs b/nym-ip-packet-client/src/connect.rs index 3c80882edb..b49d87daa5 100644 --- a/nym-ip-packet-client/src/connect.rs +++ b/nym-ip-packet-client/src/connect.rs @@ -207,7 +207,9 @@ fn maybe_wrap_stream_frame(stream_id: u64, sequence_num: u32, payload: Vec) fn ipr_response_from_reconstructed_message( msg: &nym_sdk::mixnet::ReconstructedMessage, ) -> std::result::Result { - let payload = crate::lp_stream::unwrap_ipr_payload_from_reconstructed(msg); + let warn_on_unexpected = crate::lp_stream::current_requires_sphinx_stream_transport(); + let payload = + crate::lp_stream::maybe_unwrap_lp_stream_payload(&msg.message, warn_on_unexpected); IpPacketResponse::from_bytes(payload) } diff --git a/nym-ip-packet-client/src/lp_stream.rs b/nym-ip-packet-client/src/lp_stream.rs index 262c65ebcb..736d55f378 100644 --- a/nym-ip-packet-client/src/lp_stream.rs +++ b/nym-ip-packet-client/src/lp_stream.rs @@ -50,10 +50,6 @@ pub fn maybe_unwrap_lp_stream_payload_from_reconstructed(message: &Reconstructed maybe_unwrap_lp_stream_payload(&message.message, false) } -pub fn unwrap_ipr_payload_from_reconstructed(message: &ReconstructedMessage) -> &[u8] { - maybe_unwrap_lp_stream_payload(&message.message, current_requires_sphinx_stream_transport()) -} - pub fn encode_stream_frame(stream_id: u64, sequence_num: u32, payload: Vec) -> Vec { let attrs = SphinxStreamFrameAttributes { stream_id, From e554f1e0adc6ada98c3540949f1cdb530014a4ef Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Tue, 28 Apr 2026 15:02:40 +0200 Subject: [PATCH 36/37] bump versions --- Cargo.lock | 14 +++++++------- clients/native/Cargo.toml | 2 +- clients/socks5/Cargo.toml | 2 +- nym-api/Cargo.toml | 2 +- nym-node/Cargo.toml | 2 +- service-providers/network-requester/Cargo.toml | 2 +- tools/nym-cli/Cargo.toml | 2 +- tools/nymvisor/Cargo.toml | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 970150dff0..2fc4083844 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5635,7 +5635,7 @@ dependencies = [ [[package]] name = "nym-api" -version = "1.1.78" +version = "1.1.79" dependencies = [ "anyhow", "async-trait", @@ -5880,7 +5880,7 @@ dependencies = [ [[package]] name = "nym-cli" -version = "1.1.75" +version = "1.1.76" dependencies = [ "anyhow", "base64 0.22.1", @@ -5963,7 +5963,7 @@ dependencies = [ [[package]] name = "nym-client" -version = "1.1.75" +version = "1.1.76" dependencies = [ "bs58", "clap", @@ -7373,7 +7373,7 @@ dependencies = [ [[package]] name = "nym-network-requester" -version = "1.1.76" +version = "1.1.77" dependencies = [ "addr", "anyhow", @@ -7423,7 +7423,7 @@ dependencies = [ [[package]] name = "nym-node" -version = "1.30.0" +version = "1.31.0" dependencies = [ "anyhow", "arc-swap", @@ -7975,7 +7975,7 @@ dependencies = [ [[package]] name = "nym-socks5-client" -version = "1.1.75" +version = "1.1.76" dependencies = [ "bs58", "clap", @@ -8773,7 +8773,7 @@ dependencies = [ [[package]] name = "nymvisor" -version = "0.1.40" +version = "0.1.41" dependencies = [ "anyhow", "bytes", diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 63b0ff2ba2..83e9bd5d97 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-client" description = "Implementation of the Nym Client" -version = "1.1.75" +version = "1.1.76" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] edition = "2021" license.workspace = true diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index 2b0dad092b..a22ad47a08 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-socks5-client" description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" -version = "1.1.75" +version = "1.1.76" authors = ["Dave Hrycyszyn "] edition = "2021" license.workspace = true diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index b4caee8ae4..93f2e44db4 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-api" -version = "1.1.78" +version = "1.1.79" authors.workspace = true edition = "2021" license = "GPL-3.0" diff --git a/nym-node/Cargo.toml b/nym-node/Cargo.toml index 5aa9ada3e5..574d41d60a 100644 --- a/nym-node/Cargo.toml +++ b/nym-node/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-node" -version = "1.30.0" +version = "1.31.0" authors.workspace = true edition.workspace = true license = "GPL-3.0" diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 754fd52387..c55c845e97 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-network-requester" -version = "1.1.76" +version = "1.1.77" authors.workspace = true edition.workspace = true license = "GPL-3.0" diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index e40d9c7fae..f1f8836a30 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-cli" -version = "1.1.75" +version = "1.1.76" authors.workspace = true edition = "2021" license.workspace = true diff --git a/tools/nymvisor/Cargo.toml b/tools/nymvisor/Cargo.toml index 3596905d9d..f8dc2249cd 100644 --- a/tools/nymvisor/Cargo.toml +++ b/tools/nymvisor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nymvisor" -version = "0.1.40" +version = "0.1.41" authors.workspace = true edition.workspace = true license.workspace = true From f84de25302e886d4bd97a898885c569724c002a7 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Wed, 6 May 2026 07:16:42 +0200 Subject: [PATCH 37/37] update changelog --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a998c1e782..e58f5e8b5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,22 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ## [Unreleased] +## [2026.9-venaco] (2026-05-06) + +- Fix for v9 IPR ([#6710]) +- Only init SHARED_CLIENT if requested ([#6708]) +- Fixes to crates and CI ([#6686]) +- Return ipv6 addresses as well ([#6684]) +- Fix invalid ticket spend ([#6683]) +- Block non-public IPR/NR checks ([#6670]) + +[#6710]: https://github.com/nymtech/nym/pull/6710 +[#6708]: https://github.com/nymtech/nym/pull/6708 +[#6686]: https://github.com/nymtech/nym/pull/6686 +[#6684]: https://github.com/nymtech/nym/pull/6684 +[#6683]: https://github.com/nymtech/nym/pull/6683 +[#6670]: https://github.com/nymtech/nym/pull/6670 + ## [2026.8-urda] (2026-04-20) - Include all gateways in the returned list ([#6649])