diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index cd3cfb848b..9adb0df9d8 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -81,12 +81,21 @@ jobs: command: fmt args: --all -- --check - - name: Clippy + - name: Clippy (macos) + if: contains(matrix.os, 'mac') + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --workspace --all-targets --exclude nym-gateway-probe -- -D warnings + + - name: Clippy (non-macos) + if: contains(matrix.os, 'linux') || contains(matrix.os, 'windows') uses: actions-rs/cargo@v1 with: command: clippy args: --workspace --all-targets -- -D warnings + - name: Build all binaries uses: actions-rs/cargo@v1 with: diff --git a/Cargo.lock b/Cargo.lock index 85285f4ad7..825a68cf13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "accessory" @@ -920,7 +920,7 @@ dependencies = [ [[package]] name = "bls12_381" version = "0.8.0" -source = "git+https://github.com/jstuczyn/bls12_381?branch=temp/experimental-serdect-updated#9bf520059cb28323fc51469cae86868ef4fa6fbd" +source = "git+https://github.com/jstuczyn/bls12_381?branch=temp%2Fexperimental-serdect-updated#9bf520059cb28323fc51469cae86868ef4fa6fbd" dependencies = [ "digest 0.10.7", "ff", @@ -2016,14 +2016,38 @@ dependencies = [ "serde", ] +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + [[package]] name = "darling" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.106", ] [[package]] @@ -2040,13 +2064,24 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn 2.0.106", +] + [[package]] name = "darling_macro" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ - "darling_core", + "darling_core 0.21.3", "quote", "syn 2.0.106", ] @@ -2147,6 +2182,37 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.106", +] + [[package]] name = "derive_more" version = "1.0.0" @@ -4658,6 +4724,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + [[package]] name = "nom" version = "7.1.3" @@ -5018,7 +5090,7 @@ dependencies = [ "tracing-subscriber", "tracing-tree", "utoipa", - "vergen", + "vergen 8.3.1", ] [[package]] @@ -5311,6 +5383,14 @@ dependencies = [ "nym-multisig-contract-common", ] +[[package]] +name = "nym-common" +version = "1.18.0" +dependencies = [ + "tracing", + "tracing-test", +] + [[package]] name = "nym-compact-ecash" version = "0.1.0" @@ -5349,6 +5429,24 @@ dependencies = [ "url", ] +[[package]] +name = "nym-connection-monitor" +version = "1.18.0" +dependencies = [ + "bincode", + "bytes", + "futures", + "nym-common", + "nym-config", + "nym-ip-packet-requests", + "nym-sdk", + "pnet_packet", + "thiserror 2.0.17", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "nym-contracts-common" version = "0.5.0" @@ -5363,7 +5461,7 @@ dependencies = [ "serde_json", "thiserror 2.0.17", "utoipa", - "vergen", + "vergen 8.3.1", ] [[package]] @@ -5837,6 +5935,51 @@ dependencies = [ "zeroize", ] +[[package]] +name = "nym-gateway-probe" +version = "1.18.0" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bincode", + "bs58", + "bytes", + "clap", + "futures", + "hex", + "nym-authenticator-client", + "nym-authenticator-requests", + "nym-bandwidth-controller", + "nym-bin-common", + "nym-client-core", + "nym-config", + "nym-connection-monitor", + "nym-credential-utils", + "nym-credentials", + "nym-credentials-interface", + "nym-crypto", + "nym-http-api-client", + "nym-http-api-client-macro", + "nym-ip-packet-client", + "nym-ip-packet-requests", + "nym-node-status-client", + "nym-sdk", + "nym-topology", + "nym-validator-client", + "pnet_packet", + "rand 0.8.5", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", + "tokio-util", + "tracing", + "tracing-subscriber", + "url", + "vergen-gitcl", + "x25519-dalek", +] + [[package]] name = "nym-gateway-requests" version = "0.1.0" @@ -8201,6 +8344,48 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "pnet_base" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc190d4067df16af3aba49b3b74c469e611cad6314676eaf1157f31aa0fb2f7" +dependencies = [ + "no-std-net", +] + +[[package]] +name = "pnet_macros" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13325ac86ee1a80a480b0bc8e3d30c25d133616112bb16e86f712dcf8a71c863" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn 2.0.106", +] + +[[package]] +name = "pnet_macros_support" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed67a952585d509dd0003049b1fc56b982ac665c8299b124b90ea2bdb3134ab" +dependencies = [ + "pnet_base", +] + +[[package]] +name = "pnet_packet" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c96ebadfab635fcc23036ba30a7d33a80c39e8461b8bd7dc7bb186acb96560f" +dependencies = [ + "glob", + "pnet_base", + "pnet_macros", + "pnet_macros_support", +] + [[package]] name = "polling" version = "2.8.0" @@ -9557,7 +9742,7 @@ version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7e6c180db0816026a61afa1cff5344fb7ebded7e4d3062772179f2501481c27" dependencies = [ - "darling", + "darling 0.21.3", "proc-macro2", "quote", "syn 2.0.106", @@ -11109,6 +11294,27 @@ dependencies = [ "tracing-log 0.2.0", ] +[[package]] +name = "tracing-test" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "557b891436fe0d5e0e363427fc7f217abf9ccd510d5136549847bdcbcd011d68" +dependencies = [ + "tracing-core", + "tracing-subscriber", + "tracing-test-macro", +] + +[[package]] +name = "tracing-test-macro" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" +dependencies = [ + "quote", + "syn 2.0.106", +] + [[package]] name = "tracing-tree" version = "0.2.5" @@ -11661,6 +11867,47 @@ dependencies = [ "time", ] +[[package]] +name = "vergen" +version = "9.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b2bf58be11fc9414104c6d3a2e464163db5ef74b12296bda593cac37b6e4777" +dependencies = [ + "anyhow", + "cargo_metadata 0.19.2", + "derive_builder", + "regex", + "rustc_version 0.4.1", + "rustversion", + "time", + "vergen-lib", +] + +[[package]] +name = "vergen-gitcl" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9dfc1de6eb2e08a4ddf152f1b179529638bedc0ea95e6d667c014506377aefe" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", + "time", + "vergen 9.0.6", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b07e6010c0f3e59fcb164e0163834597da68d1f864e2b8ca49f74de01e9c166" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", +] + [[package]] name = "version_check" version = "0.9.5" diff --git a/Cargo.toml b/Cargo.toml index 24baeac724..77dd204105 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ members = [ "common/client-libs/mixnet-client", "common/client-libs/validator-client", "common/commands", + "common/nym-common", "common/config", "common/cosmwasm-smart-contracts/coconut-dkg", "common/cosmwasm-smart-contracts/contracts-common", @@ -58,7 +59,8 @@ members = [ "common/gateway-requests", "common/gateway-stats-storage", "common/gateway-storage", - "common/http-api-client", "common/http-api-client-macro", + "common/http-api-client", + "common/http-api-client-macro", "common/http-api-common", "common/inclusion-probability", "common/ip-packet-requests", @@ -66,7 +68,9 @@ members = [ "common/mixnode-common", "common/network-defaults", "common/node-tester-utils", - "common/nonexhaustive-delayqueue", "common/nym-cache", + "common/nonexhaustive-delayqueue", + "common/nym-cache", + "common/nym-connection-monitor", "common/nym-id", "common/nym-metrics", "common/nym_offline_compact_ecash", @@ -98,7 +102,8 @@ members = [ "common/ticketbooks-merkle", "common/topology", "common/tun", - "common/types", "common/upgrade-mode-check", + "common/types", + "common/upgrade-mode-check", "common/verloc", "common/wasm/client-core", "common/wasm/storage", @@ -160,6 +165,7 @@ members = [ "wasm/mix-fetch", "wasm/node-tester", "wasm/zknym-lib", + "nym-gateway-probe" ] default-members = [ @@ -178,16 +184,16 @@ default-members = [ "tools/nymvisor", ] -exclude = ["explorer", "contracts", "nym-wallet", "cpu-cycles"] +exclude = ["contracts", "nym-wallet", "cpu-cycles"] [workspace.package] authors = ["Nym Technologies SA"] repository = "https://github.com/nymtech/nym" homepage = "https://nymtech.net" documentation = "https://nymtech.net" -edition = "2021" +edition = "2024" license = "Apache-2.0" -rust-version = "1.81" +rust-version = "1.85" readme = "README.md" [workspace.dependencies] @@ -300,6 +306,7 @@ parking_lot = "0.12.3" pem = "0.8" petgraph = "0.6.5" pin-project = "1.1" +pnet_packet = "0.35.0" pin-project-lite = "0.2.16" publicsuffix = "2.3.0" proc_pidinfo = "0.1.3" @@ -358,6 +365,7 @@ tracing-opentelemetry = "0.19.0" tracing-subscriber = "0.3.19" tracing-tree = "0.2.2" tracing-indicatif = "0.3.9" +tracing-test = "0.2.5" ts-rs = "10.1.0" tungstenite = { version = "0.20.1", default-features = false } uniffi = "0.29.2" @@ -368,6 +376,7 @@ utoipa-swagger-ui = "8.1" utoipauto = "0.2" uuid = "*" vergen = { version = "=8.3.1", default-features = false } +vergen-gitcl = { version = "1.0.8", default-features = false } walkdir = "2" x25519-dalek = "2.0.0" zeroize = "1.7.0" diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 9ac6a9ae3a..130585bca9 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -4,7 +4,7 @@ version = "1.1.63" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] description = "Implementation of the Nym Client" edition = "2021" -rust-version = "1.70" +rust-version = "1.85" license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index e2ed20d193..1b71b018f7 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -4,7 +4,7 @@ version = "1.1.63" 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.70" +rust-version = "1.85" license.workspace = true [dependencies] diff --git a/common/async-file-watcher/src/lib.rs b/common/async-file-watcher/src/lib.rs index 0fdeb7da3a..8b0d4d7512 100644 --- a/common/async-file-watcher/src/lib.rs +++ b/common/async-file-watcher/src/lib.rs @@ -1,8 +1,8 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use futures::channel::mpsc; use futures::StreamExt; +use futures::channel::mpsc; use notify::event::{DataChange, MetadataKind, ModifyKind}; use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher}; use std::collections::HashMap; @@ -96,10 +96,10 @@ impl AsyncFileWatcher { // when testing I was consistently getting two `Modify(Data(Any))` events in quick succession // (probably to modify content and metadata). // we really only want to propagate one of them - if let Some(previous) = self.last_received.get(&event.kind) { - if now.duration_since(*previous) < self.tick_duration { - return false; - } + if let Some(previous) = self.last_received.get(&event.kind) + && now.duration_since(*previous) < self.tick_duration + { + return false; } let Some(filters) = &self.filters else { diff --git a/common/authenticator-requests/src/client_message.rs b/common/authenticator-requests/src/client_message.rs index d0a19ab6a9..06a910b9b9 100644 --- a/common/authenticator-requests/src/client_message.rs +++ b/common/authenticator-requests/src/client_message.rs @@ -5,9 +5,10 @@ use nym_sphinx::addressing::Recipient; use nym_wireguard_types::PeerPublicKey; use crate::{ + AuthenticatorVersion, Error, latest::registration::IpPair, traits::{FinalMessage, InitMessage, QueryBandwidthMessage, TopUpMessage, Versionable}, - v2, v3, v4, v5, AuthenticatorVersion, Error, + v2, v3, v4, v5, }; // This is very redundant with AuthenticatorRequest and I reckon they could be smooshed. diff --git a/common/authenticator-requests/src/traits.rs b/common/authenticator-requests/src/traits.rs index 48e1a4cb23..36e999383d 100644 --- a/common/authenticator-requests/src/traits.rs +++ b/common/authenticator-requests/src/traits.rs @@ -9,7 +9,7 @@ use nym_crypto::asymmetric::x25519::PrivateKey; use nym_wireguard_types::PeerPublicKey; use crate::latest::registration::IpPair; -use crate::{v1, v2, v3, v4, v5, AuthenticatorVersion, Error}; +use crate::{AuthenticatorVersion, Error, v1, v2, v3, v4, v5}; pub trait Versionable { fn version(&self) -> AuthenticatorVersion; diff --git a/common/authenticator-requests/src/v1/registration.rs b/common/authenticator-requests/src/v1/registration.rs index 03cfc30c22..6807325921 100644 --- a/common/authenticator-requests/src/v1/registration.rs +++ b/common/authenticator-requests/src/v1/registration.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::error::Error; -use base64::{engine::general_purpose, Engine}; +use base64::{Engine, engine::general_purpose}; use nym_wireguard_types::PeerPublicKey; use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/common/authenticator-requests/src/v2/registration.rs b/common/authenticator-requests/src/v2/registration.rs index 436fde5346..a8d5f5e089 100644 --- a/common/authenticator-requests/src/v2/registration.rs +++ b/common/authenticator-requests/src/v2/registration.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::error::Error; -use base64::{engine::general_purpose, Engine}; +use base64::{Engine, engine::general_purpose}; use nym_credentials_interface::CredentialSpendingData; use nym_wireguard_types::PeerPublicKey; use serde::{Deserialize, Serialize}; diff --git a/common/authenticator-requests/src/v3/registration.rs b/common/authenticator-requests/src/v3/registration.rs index 21a50882ca..00cb146772 100644 --- a/common/authenticator-requests/src/v3/registration.rs +++ b/common/authenticator-requests/src/v3/registration.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::error::Error; -use base64::{engine::general_purpose, Engine}; +use base64::{Engine, engine::general_purpose}; use nym_credentials_interface::CredentialSpendingData; use nym_wireguard_types::PeerPublicKey; use serde::{Deserialize, Serialize}; diff --git a/common/authenticator-requests/src/v4/registration.rs b/common/authenticator-requests/src/v4/registration.rs index 28aadf9c6d..a383b79beb 100644 --- a/common/authenticator-requests/src/v4/registration.rs +++ b/common/authenticator-requests/src/v4/registration.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::error::Error; -use base64::{engine::general_purpose, Engine}; +use base64::{Engine, engine::general_purpose}; use nym_credentials_interface::CredentialSpendingData; use nym_network_defaults::constants::{WG_TUN_DEVICE_IP_ADDRESS_V4, WG_TUN_DEVICE_IP_ADDRESS_V6}; use nym_wireguard_types::PeerPublicKey; diff --git a/common/authenticator-requests/src/v5/registration.rs b/common/authenticator-requests/src/v5/registration.rs index 3c51776ca0..151401da97 100644 --- a/common/authenticator-requests/src/v5/registration.rs +++ b/common/authenticator-requests/src/v5/registration.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::error::Error; -use base64::{engine::general_purpose, Engine}; +use base64::{Engine, engine::general_purpose}; use nym_credentials_interface::CredentialSpendingData; use nym_network_defaults::constants::{WG_TUN_DEVICE_IP_ADDRESS_V4, WG_TUN_DEVICE_IP_ADDRESS_V6}; use nym_wireguard_types::PeerPublicKey; diff --git a/common/authenticator-requests/src/version.rs b/common/authenticator-requests/src/version.rs index ac71de9ae0..4bb8b6d591 100644 --- a/common/authenticator-requests/src/version.rs +++ b/common/authenticator-requests/src/version.rs @@ -129,7 +129,11 @@ impl From for AuthenticatorVersion { // if provided version is higher (or equal) to release version of V5, // we return the latest (i.e. v5) - debug_assert_eq!(Self::V5, Self::LATEST, "a new AuthenticatorVersion variant has been introduced without adjusting the `From` trait"); + debug_assert_eq!( + Self::V5, + Self::LATEST, + "a new AuthenticatorVersion variant has been introduced without adjusting the `From` trait" + ); Self::LATEST } } diff --git a/common/bin-common/src/completions/mod.rs b/common/bin-common/src/completions/mod.rs index 15344ec834..afca56cd32 100644 --- a/common/bin-common/src/completions/mod.rs +++ b/common/bin-common/src/completions/mod.rs @@ -1,8 +1,8 @@ +use clap::Args; use clap::builder::Command; use clap::clap_derive::ValueEnum; -use clap::Args; -use clap_complete::generator::generate; use clap_complete::Shell as ClapShell; +use clap_complete::generator::generate; use std::io; pub fn fig_generate(command: &mut Command, name: &str) { diff --git a/common/client-core/Cargo.toml b/common/client-core/Cargo.toml index 3728a2421f..fd1e82d7ac 100644 --- a/common/client-core/Cargo.toml +++ b/common/client-core/Cargo.toml @@ -3,7 +3,7 @@ name = "nym-client-core" version = "1.1.15" authors = ["Dave Hrycyszyn "] edition = "2021" -rust-version = "1.76" +rust-version = "1.85" license.workspace = 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 ea4e8beeb4..afb988c98c 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -3,7 +3,7 @@ name = "nym-validator-client" version = "0.1.0" authors = ["Jędrzej Stuczyński "] edition = "2021" -rust-version = "1.56" +rust-version = "1.85" license.workspace = 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/src/helpers.rs b/common/cosmwasm-smart-contracts/contracts-common-testing/src/helpers.rs index d1fcace36e..f7870b290b 100644 --- a/common/cosmwasm-smart-contracts/contracts-common-testing/src/helpers.rs +++ b/common/cosmwasm-smart-contracts/contracts-common-testing/src/helpers.rs @@ -1,17 +1,17 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use cosmwasm_std::testing::{message_info, MockApi, MockQuerier, MockStorage}; +use cosmwasm_std::testing::{MockApi, MockQuerier, MockStorage, message_info}; use cosmwasm_std::{ - coins, Addr, BankMsg, CosmosMsg, Decimal, Empty, Env, MemoryStorage, MessageInfo, Order, - OwnedDeps, Response, StdResult, Storage, + Addr, BankMsg, CosmosMsg, Decimal, Empty, Env, MemoryStorage, MessageInfo, Order, OwnedDeps, + Response, StdResult, Storage, coins, }; use cw_storage_plus::{KeyDeserialize, Map, Prefix, PrimaryKey}; use nym_contracts_common::events::may_find_attribute; use rand::{RngCore, SeedableRng}; use rand_chacha::ChaCha20Rng; -use serde::de::DeserializeOwned; use serde::Serialize; +use serde::de::DeserializeOwned; use std::fmt::Debug; use std::str::FromStr; diff --git a/common/cosmwasm-smart-contracts/contracts-common-testing/src/tester/basic_traits.rs b/common/cosmwasm-smart-contracts/contracts-common-testing/src/tester/basic_traits.rs index f471b64be4..facc2983de 100644 --- a/common/cosmwasm-smart-contracts/contracts-common-testing/src/tester/basic_traits.rs +++ b/common/cosmwasm-smart-contracts/contracts-common-testing/src/tester/basic_traits.rs @@ -4,12 +4,12 @@ use crate::{ContractTester, TestableNymContract}; use cosmwasm_std::testing::{message_info, mock_env}; use cosmwasm_std::{ - from_json, Addr, BlockInfo, Coin, ContractInfo, Deps, DepsMut, Env, MessageInfo, Response, - StdResult, Storage, Timestamp, + Addr, BlockInfo, Coin, ContractInfo, Deps, DepsMut, Env, MessageInfo, Response, StdResult, + Storage, Timestamp, from_json, }; -use cw_multi_test::{next_block, AppResponse, Executor}; -use serde::de::DeserializeOwned; +use cw_multi_test::{AppResponse, Executor, next_block}; use serde::Serialize; +use serde::de::DeserializeOwned; use std::any::type_name; use std::fmt::Debug; diff --git a/common/cosmwasm-smart-contracts/contracts-common-testing/src/tester/extensions.rs b/common/cosmwasm-smart-contracts/contracts-common-testing/src/tester/extensions.rs index b70b3159e1..f77cd3f61a 100644 --- a/common/cosmwasm-smart-contracts/contracts-common-testing/src/tester/extensions.rs +++ b/common/cosmwasm-smart-contracts/contracts-common-testing/src/tester/extensions.rs @@ -2,18 +2,18 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - CommonStorageKeys, ContractOpts, ContractTester, StorageWrapper, TestableNymContract, - TEST_DENOM, + CommonStorageKeys, ContractOpts, ContractTester, StorageWrapper, TEST_DENOM, + TestableNymContract, }; use cosmwasm_std::testing::message_info; use cosmwasm_std::{ - coin, coins, from_json, to_json_vec, Addr, Coin, MessageInfo, StdError, StdResult, Storage, + Addr, Coin, MessageInfo, StdError, StdResult, Storage, coin, coins, from_json, to_json_vec, }; use cw_multi_test::Executor; use cw_storage_plus::{Key, Path, PrimaryKey}; use rand_chacha::ChaCha20Rng; -use serde::de::DeserializeOwned; use serde::Serialize; +use serde::de::DeserializeOwned; use std::any::type_name; use std::ops::Deref; diff --git a/common/cosmwasm-smart-contracts/contracts-common-testing/src/tester/mod.rs b/common/cosmwasm-smart-contracts/contracts-common-testing/src/tester/mod.rs index b6a5a7398e..a2267e88b4 100644 --- a/common/cosmwasm-smart-contracts/contracts-common-testing/src/tester/mod.rs +++ b/common/cosmwasm-smart-contracts/contracts-common-testing/src/tester/mod.rs @@ -1,16 +1,16 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::{mock_api, test_rng, TEST_DENOM}; +use crate::{TEST_DENOM, mock_api, test_rng}; use cosmwasm_std::testing::MockApi; use cosmwasm_std::{ - coin, coins, Addr, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Order, QuerierWrapper, - Record, Response, Storage, + Addr, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Order, QuerierWrapper, Record, Response, + Storage, coin, coins, }; use cw_multi_test::{App, AppBuilder, BankKeeper, Contract, ContractWrapper, Executor}; use rand_chacha::ChaCha20Rng; -use serde::de::DeserializeOwned; use serde::Serialize; +use serde::de::DeserializeOwned; use std::collections::HashMap; use std::fmt::{Debug, Display}; use std::marker::PhantomData; diff --git a/common/cosmwasm-smart-contracts/contracts-common/src/contract_querier.rs b/common/cosmwasm-smart-contracts/contracts-common/src/contract_querier.rs index aed353ef90..8dc00a408a 100644 --- a/common/cosmwasm-smart-contracts/contracts-common/src/contract_querier.rs +++ b/common/cosmwasm-smart-contracts/contracts-common/src/contract_querier.rs @@ -1,9 +1,9 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use cosmwasm_std::{from_json, Binary, CustomQuery, QuerierWrapper, StdResult}; -use serde::de::DeserializeOwned; +use cosmwasm_std::{Binary, CustomQuery, QuerierWrapper, StdResult, from_json}; use serde::Serialize; +use serde::de::DeserializeOwned; // re-expose methods from QuerierWrapper as traits so that we could more easily define extension traits pub trait ContractQuerier { diff --git a/common/cosmwasm-smart-contracts/contracts-common/src/signing/mod.rs b/common/cosmwasm-smart-contracts/contracts-common/src/signing/mod.rs index 3d0b28a247..b88d42ef71 100644 --- a/common/cosmwasm-smart-contracts/contracts-common/src/signing/mod.rs +++ b/common/cosmwasm-smart-contracts/contracts-common/src/signing/mod.rs @@ -1,10 +1,10 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use cosmwasm_std::{from_json, to_json_vec, Addr, Coin, MessageInfo, StdResult}; +use cosmwasm_std::{Addr, Coin, MessageInfo, StdResult, from_json, to_json_vec}; use schemars::JsonSchema; use serde::de::DeserializeOwned; -use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; use std::fmt::{Display, Formatter}; use std::str::FromStr; pub use verifier::Verifier; diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml index d0a7b3b913..ed9b7ac125 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml @@ -2,7 +2,7 @@ name = "nym-mixnet-contract-common" version = "0.6.0" description = "Common library for the Nym mixnet contract" -rust-version = "1.62" +rust-version = "1.85" edition = { workspace = true } authors = { workspace = true } license = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/error.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/error.rs index 8104a1c910..9298b38523 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/error.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/error.rs @@ -5,8 +5,8 @@ use crate::nym_node::Role; use crate::{ EpochEventId, EpochState, IntervalEventId, NodeId, OperatingCostRange, ProfitMarginRange, }; -use contracts_common::signing::verifier::ApiVerifierError; use contracts_common::Percent; +use contracts_common::signing::verifier::ApiVerifierError; use cosmwasm_std::{Addr, Coin, Decimal, Uint128}; use cw_controllers::AdminError; use thiserror::Error; @@ -47,7 +47,9 @@ pub enum MixnetContractError { )] InvalidPubKey, - #[error("Attempted to reduce node pledge ({current}{denom} - {decrease_by}{denom}) below the minimum amount: {minimum}{denom}")] + #[error( + "Attempted to reduce node pledge ({current}{denom} - {decrease_by}{denom}) below the minimum amount: {minimum}{denom}" + )] InvalidPledgeReduction { current: Uint128, decrease_by: Uint128, @@ -123,7 +125,9 @@ pub enum MixnetContractError { #[error("Provided ed25519 signature did not verify correctly")] InvalidEd25519Signature, - #[error("Can't perform the specified action as the current epoch is still progress. It started at {epoch_start} and finishes at {epoch_end}, while the current block time is {current_block_time}")] + #[error( + "Can't perform the specified action as the current epoch is still progress. It started at {epoch_start} and finishes at {epoch_end}, while the current block time is {current_block_time}" + )] EpochInProgress { current_block_time: u64, epoch_start: i64, @@ -133,7 +137,9 @@ pub enum MixnetContractError { #[error("attempted to reward a gateway node - this has not been fully integrated yet")] GatewayRewarding, - #[error("node {node_id} has already been rewarded during the current rewarding epoch ({absolute_epoch_id})")] + #[error( + "node {node_id} has already been rewarded during the current rewarding epoch ({absolute_epoch_id})" + )] NodeAlreadyRewarded { node_id: NodeId, absolute_epoch_id: u32, @@ -172,7 +178,9 @@ pub enum MixnetContractError { #[error("one of the roles in the new active set is empty")] EmptyRoleAssignment, - #[error("the number of mixnodes in the rewarded set is not divisible by the number of mix-layers (3)")] + #[error( + "the number of mixnodes in the rewarded set is not divisible by the number of mix-layers (3)" + )] UnevenLayerAssignment, #[error("provided active set is bigger than the rewarded set")] @@ -196,25 +204,35 @@ pub enum MixnetContractError { #[error("key rotation validity below minimum value")] TooShortRotationInterval, - #[error("this validator ({current_validator}) is not the one responsible for advancing this epoch. It's responsibility of {chosen_validator}.")] + #[error( + "this validator ({current_validator}) is not the one responsible for advancing this epoch. It's responsibility of {chosen_validator}." + )] RewardingValidatorMismatch { current_validator: Addr, chosen_validator: Addr, }, - #[error("the epoch is currently in the process of being advanced. (the state is {current_state}) Please try sending your transaction again once this has finished")] + #[error( + "the epoch is currently in the process of being advanced. (the state is {current_state}) Please try sending your transaction again once this has finished" + )] EpochAdvancementInProgress { current_state: EpochState }, - #[error("the epoch is in an unexpected state. expected 'mix rewarding' state, but we're in {current_state} instead.")] + #[error( + "the epoch is in an unexpected state. expected 'mix rewarding' state, but we're in {current_state} instead." + )] UnexpectedNonRewardingEpochState { current_state: EpochState }, - #[error("attempted to reward mixnode out of order. Attempted to reward {attempted_to_reward} while last rewarded was {last_rewarded}.")] + #[error( + "attempted to reward mixnode out of order. Attempted to reward {attempted_to_reward} while last rewarded was {last_rewarded}." + )] RewardingOutOfOrder { last_rewarded: NodeId, attempted_to_reward: NodeId, }, - #[error("the epoch is currently not in the 'event reconciliation' state. (the state is {current_state})")] + #[error( + "the epoch is currently not in the 'event reconciliation' state. (the state is {current_state})" + )] EpochNotInEventReconciliationState { current_state: EpochState }, #[error( @@ -225,14 +243,18 @@ pub enum MixnetContractError { #[error("unexpected role assignment. got: {got} while expected: {expected}")] UnexpectedRoleAssignment { expected: Role, got: Role }, - #[error("attempted to assign an invalid number of nodes for a role of {role}. got {assigned}, but the maximum allowed is {allowed}")] + #[error( + "attempted to assign an invalid number of nodes for a role of {role}. got {assigned}, but the maximum allowed is {allowed}" + )] IllegalRoleCount { role: Role, assigned: u32, allowed: u32, }, - #[error("the epoch is currently not in the 'epoch advancement' state. (the state is {current_state})")] + #[error( + "the epoch is currently not in the 'epoch advancement' state. (the state is {current_state})" + )] EpochNotInAdvancementState { current_state: EpochState }, #[error("failed to verify message signature: {source}")] @@ -241,7 +263,9 @@ pub enum MixnetContractError { source: ApiVerifierError, }, - #[error("this operation is no longer allowed to be performed with vesting tokens. please move them to your liquid balance and try again")] + #[error( + "this operation is no longer allowed to be performed with vesting tokens. please move them to your liquid balance and try again" + )] DisabledVestingOperation, #[error( @@ -249,7 +273,9 @@ pub enum MixnetContractError { )] NotAVestingMixnode, - #[error("this delegation has not been performed with the vesting tokens or has already been migrated")] + #[error( + "this delegation has not been performed with the vesting tokens or has already been migrated" + )] NotAVestingDelegation, #[error("the provided profit margin ({provided}) is outside the allowed range: {range}")] @@ -258,7 +284,9 @@ pub enum MixnetContractError { range: ProfitMarginRange, }, - #[error("the provided interval operating cost ({provided}{denom}) is outside the allowed range: {range}")] + #[error( + "the provided interval operating cost ({provided}{denom}) is outside the allowed range: {range}" + )] OperatingCostOutsideRange { denom: String, provided: Uint128, @@ -279,7 +307,9 @@ pub enum MixnetContractError { #[error("the provided nym-node version is not a valid semver. got: {provided}")] InvalidNymNodeSemver { provided: String }, - #[error("the provided nym-node version is not greater than the current one. got: {provided}. current: {current}")] + #[error( + "the provided nym-node version is not greater than the current one. got: {provided}. current: {current}" + )] NonIncreasingSemver { provided: String, current: String }, } diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/events.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/events.rs index b29fba4bd0..a53c5dc1a9 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/events.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/events.rs @@ -9,7 +9,7 @@ use crate::reward_params::{ActiveSetUpdate, IntervalRewardParams, IntervalReward use crate::rewarding::RewardDistribution; use crate::{BlockHeight, ContractStateParamsUpdate, EpochId, IdentityKeyRef, Interval, NodeId}; pub use contracts_common::events::*; -use cosmwasm_std::{attr, Addr, Coin, Decimal, Event}; +use cosmwasm_std::{Addr, Coin, Decimal, Event, attr}; use std::fmt::Display; pub const EVENT_VERSION_PREFIX: &str = "v2_"; diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/gateway.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/gateway.rs index 72e848aef1..1e9a5b03d7 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/gateway.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/gateway.rs @@ -3,7 +3,7 @@ use crate::{IdentityKey, NodeId, SphinxKey}; use cosmwasm_schema::cw_serde; -use cosmwasm_std::{to_json_string, Addr, Coin}; +use cosmwasm_std::{Addr, Coin, to_json_string}; use std::cmp::Ordering; use std::fmt::Display; diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/interval.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/interval.rs index 39cd180bf8..6f9e2326fa 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/interval.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/interval.rs @@ -1,13 +1,13 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::NodeId; use crate::error::MixnetContractError; use crate::nym_node::Role; -use crate::NodeId; use cosmwasm_schema::cw_serde; -use cosmwasm_schema::schemars::gen::SchemaGenerator; -use cosmwasm_schema::schemars::schema::{InstanceType, Schema, SchemaObject}; use cosmwasm_schema::schemars::JsonSchema; +use cosmwasm_schema::schemars::r#gen::SchemaGenerator; +use cosmwasm_schema::schemars::schema::{InstanceType, Schema, SchemaObject}; use cosmwasm_std::{Addr, Env}; use serde::{Deserialize, Serialize}; use std::fmt::{Display, Formatter}; @@ -27,8 +27,8 @@ pub(crate) mod string_rfc3339_offset_date_time { use serde::ser::Error; use serde::{Deserializer, Serialize, Serializer}; use std::fmt::Formatter; - use time::format_description::well_known::Rfc3339; use time::OffsetDateTime; + use time::format_description::well_known::Rfc3339; struct Rfc3339OffsetDateTimeVisitor; @@ -91,7 +91,7 @@ impl EpochStatus { ) -> Result { match &mut self.state { EpochState::Rewarding { - ref mut last_rewarded, + last_rewarded, final_node_id, } => { if new_last_rewarded <= *last_rewarded { @@ -254,7 +254,7 @@ impl JsonSchema for Interval { "Interval".to_owned() } - fn json_schema(gen: &mut SchemaGenerator) -> Schema { + fn json_schema(r#gen: &mut SchemaGenerator) -> Schema { let mut schema_object = SchemaObject { instance_type: Some(InstanceType::Object.into()), ..SchemaObject::default() @@ -263,12 +263,13 @@ impl JsonSchema for Interval { let object_validation = schema_object.object(); object_validation .properties - .insert("id".to_owned(), gen.subschema_for::()); + .insert("id".to_owned(), r#gen.subschema_for::()); object_validation.required.insert("id".to_owned()); - object_validation - .properties - .insert("epochs_in_interval".to_owned(), gen.subschema_for::()); + object_validation.properties.insert( + "epochs_in_interval".to_owned(), + r#gen.subschema_for::(), + ); object_validation .required .insert("epochs_in_interval".to_owned()); @@ -277,7 +278,7 @@ impl JsonSchema for Interval { // serialization to string, so we just specify the schema to be String. object_validation.properties.insert( "current_epoch_start".to_owned(), - gen.subschema_for::(), + r#gen.subschema_for::(), ); object_validation .required @@ -285,7 +286,7 @@ impl JsonSchema for Interval { object_validation.properties.insert( "current_epoch_id".to_owned(), - gen.subschema_for::(), + r#gen.subschema_for::(), ); object_validation .required @@ -293,12 +294,12 @@ impl JsonSchema for Interval { object_validation .properties - .insert("epoch_length".to_owned(), gen.subschema_for::()); + .insert("epoch_length".to_owned(), r#gen.subschema_for::()); object_validation.required.insert("epoch_length".to_owned()); object_validation.properties.insert( "total_elapsed_epochs".to_owned(), - gen.subschema_for::(), + r#gen.subschema_for::(), ); object_validation .required diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs index ea45cd0414..66f7d05113 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs @@ -9,14 +9,14 @@ use crate::error::MixnetContractError; use crate::helpers::IntoBaseDecimal; use crate::nym_node::Role; use crate::reward_params::{NodeRewardingParameters, RewardingParams}; -use crate::rewarding::helpers::truncate_reward; use crate::rewarding::RewardDistribution; +use crate::rewarding::helpers::truncate_reward; use crate::{ Delegation, EpochEventId, EpochId, IdentityKey, IntervalEventId, NodeId, OperatingCostRange, Percent, ProfitMarginRange, SphinxKey, }; use cosmwasm_schema::cw_serde; -use cosmwasm_std::{to_json_string, Addr, Coin, Decimal, StdResult, Uint128}; +use cosmwasm_std::{Addr, Coin, Decimal, StdResult, Uint128, to_json_string}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs index 0fedbd84e9..a85d86fedf 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs @@ -18,7 +18,7 @@ use crate::{ VersionScoreFormulaParams, }; use crate::{OperatingCostRange, ProfitMarginRange}; -use contracts_common::{signing::MessageSignature, IdentityKey, Percent}; +use contracts_common::{IdentityKey, Percent, signing::MessageSignature}; use cosmwasm_schema::cw_serde; use cosmwasm_std::{Coin, Decimal}; use std::time::Duration; @@ -55,7 +55,7 @@ use crate::{ types::{ContractState, ContractStateParams}, }; #[cfg(feature = "schema")] -use contracts_common::{signing::Nonce, ContractBuildInformation}; +use contracts_common::{ContractBuildInformation, signing::Nonce}; #[cfg(feature = "schema")] use cosmwasm_schema::QueryResponses; diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/reward_params.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/reward_params.rs index 6f9d01eb6f..4e702a6fda 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/reward_params.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/reward_params.rs @@ -3,9 +3,9 @@ use crate::helpers::IntoBaseDecimal; use crate::nym_node::Role; -use crate::{error::MixnetContractError, Percent}; +use crate::{Percent, error::MixnetContractError}; use cosmwasm_schema::cw_serde; -use cosmwasm_std::{to_json_string, Decimal}; +use cosmwasm_std::{Decimal, to_json_string}; pub type Performance = Percent; pub type WorkFactor = Decimal; diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/rewarding/simulator/mod.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/rewarding/simulator/mod.rs index 25f588b476..8b98c0ffcd 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/rewarding/simulator/mod.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/rewarding/simulator/mod.rs @@ -4,8 +4,8 @@ use crate::error::MixnetContractError; use crate::helpers::IntoBaseDecimal; use crate::reward_params::{NodeRewardingParameters, WorkFactor}; -use crate::rewarding::simulator::simulated_node::SimulatedNode; use crate::rewarding::RewardDistribution; +use crate::rewarding::simulator::simulated_node::SimulatedNode; use crate::{Delegation, Interval, IntervalRewardParams, NodeCostParams, NodeId, RewardingParams}; use cosmwasm_std::{Coin, Decimal}; use std::collections::BTreeMap; @@ -226,9 +226,9 @@ impl Simulator { #[cfg(test)] mod tests { use super::*; + use crate::Percent; use crate::helpers::compare_decimals; use crate::reward_params::RewardedSetParams; - use crate::Percent; use cosmwasm_std::testing::mock_env; use std::time::Duration; diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs index 9281e35bbb..ebe198186d 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs @@ -1,10 +1,10 @@ // Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::EpochId; use crate::config_score::{ConfigScoreParams, OutdatedVersionWeights, VersionScoreFormulaParams}; use crate::nym_node::Role; use crate::reward_params::RewardedSetParams; -use crate::EpochId; use contracts_common::Percent; use cosmwasm_schema::cw_serde; use cosmwasm_std::Coin; diff --git a/common/cosmwasm-smart-contracts/nym-performance-contract/src/error.rs b/common/cosmwasm-smart-contracts/nym-performance-contract/src/error.rs index 68d4e8832b..adc86db068 100644 --- a/common/cosmwasm-smart-contracts/nym-performance-contract/src/error.rs +++ b/common/cosmwasm-smart-contracts/nym-performance-contract/src/error.rs @@ -23,7 +23,9 @@ pub enum NymPerformanceContractError { #[error("{address} is not an authorised network monitor")] NotAuthorised { address: Addr }, - #[error("attempted to submit performance data for epoch {epoch_id} and node {node_id} whilst last submitted was {last_epoch_id} for node {last_node_id}")] + #[error( + "attempted to submit performance data for epoch {epoch_id} and node {node_id} whilst last submitted was {last_epoch_id} for node {last_node_id}" + )] StalePerformanceSubmission { epoch_id: EpochId, node_id: NodeId, diff --git a/common/cosmwasm-smart-contracts/nym-pool-contract/src/error.rs b/common/cosmwasm-smart-contracts/nym-pool-contract/src/error.rs index 35ad7ec745..3ddb49d83a 100644 --- a/common/cosmwasm-smart-contracts/nym-pool-contract/src/error.rs +++ b/common/cosmwasm-smart-contracts/nym-pool-contract/src/error.rs @@ -16,7 +16,9 @@ pub enum NymPoolContractError { #[error(transparent)] StdErr(#[from] cosmwasm_std::StdError), - #[error("this sender is not authorised to revoke this grant. its neither the admin or the original (and still whitelisted) granter")] + #[error( + "this sender is not authorised to revoke this grant. its neither the admin or the original (and still whitelisted) granter" + )] UnauthorizedGrantRevocation, #[error("the specified address is already a whitelisted granter")] @@ -28,7 +30,9 @@ pub enum NymPoolContractError { #[error("invalid coin denomination. got {got}, but expected {expected}")] InvalidDenom { expected: String, got: String }, - #[error("there already exists an active grant for {grantee}. it was granted by {granter} at block height {created_at_height}")] + #[error( + "there already exists an active grant for {grantee}. it was granted by {granter} at block height {created_at_height}" + )] GrantAlreadyExist { granter: String, grantee: String, @@ -38,13 +42,17 @@ pub enum NymPoolContractError { #[error("could not find any active grants for {grantee}")] GrantNotFound { grantee: String }, - #[error("the provided timestamp value ({timestamp}) is set in the past. the current block timestamp is {current_block_timestamp}")] + #[error( + "the provided timestamp value ({timestamp}) is set in the past. the current block timestamp is {current_block_timestamp}" + )] TimestampInThePast { timestamp: u64, current_block_timestamp: u64, }, - #[error("there are not enough tokens to process this request. {available} are available, but {required} is needed.")] + #[error( + "there are not enough tokens to process this request. {available} are available, but {required} is needed." + )] InsufficientTokens { available: Coin, required: Coin }, #[error("the period length can't be zero")] @@ -53,22 +61,30 @@ pub enum NymPoolContractError { #[error("the provided coin value is zero")] ZeroAmount, - #[error("the periodic spend limit of {periodic} was set to be higher than the total spend limit {total_limit}")] + #[error( + "the periodic spend limit of {periodic} was set to be higher than the total spend limit {total_limit}" + )] PeriodicGrantOverSpendLimit { periodic: Coin, total_limit: Coin }, - #[error("the accumulation spend limit of {accumulation} was set to be lower than the periodic grant amount of {periodic_grant}")] + #[error( + "the accumulation spend limit of {accumulation} was set to be lower than the periodic grant amount of {periodic_grant}" + )] AccumulationBelowGrantAmount { accumulation: Coin, periodic_grant: Coin, }, - #[error("the accumulation spend limit of {accumulation} was set to be higher than the total spend limit of {total_limit}")] + #[error( + "the accumulation spend limit of {accumulation} was set to be higher than the total spend limit of {total_limit}" + )] AccumulationOverSpendLimit { accumulation: Coin, total_limit: Coin, }, - #[error("the specified delayed allowance would never be available. it would become active at {available_timestamp} yet it expires at {expiration_timestamp}")] + #[error( + "the specified delayed allowance would never be available. it would become active at {available_timestamp} yet it expires at {expiration_timestamp}" + )] UnattainableDelayedAllowance { expiration_timestamp: u64, available_timestamp: u64, diff --git a/common/cosmwasm-smart-contracts/nym-pool-contract/src/types.rs b/common/cosmwasm-smart-contracts/nym-pool-contract/src/types.rs index 8bffe7dc6a..ab6743f2ef 100644 --- a/common/cosmwasm-smart-contracts/nym-pool-contract/src/types.rs +++ b/common/cosmwasm-smart-contracts/nym-pool-contract/src/types.rs @@ -88,10 +88,10 @@ pub mod grants { pub fn basic_mut(&mut self) -> &mut BasicAllowance { match self { - Allowance::Basic(ref mut allowance) => allowance, - Allowance::ClassicPeriodic(ref mut allowance) => &mut allowance.basic, - Allowance::CumulativePeriodic(ref mut allowance) => &mut allowance.basic, - Allowance::Delayed(ref mut allowance) => &mut allowance.basic, + Allowance::Basic(allowance) => allowance, + Allowance::ClassicPeriodic(allowance) => &mut allowance.basic, + Allowance::CumulativePeriodic(allowance) => &mut allowance.basic, + Allowance::Delayed(allowance) => &mut allowance.basic, } } @@ -752,7 +752,7 @@ pub mod query_responses { #[cfg(test)] mod tests { use super::*; - use cosmwasm_std::{coin, Uint128}; + use cosmwasm_std::{Uint128, coin}; const TEST_DENOM: &str = "unym"; @@ -873,8 +873,8 @@ mod tests { #[cfg(test)] mod basic_allowance { use super::*; - use cosmwasm_std::testing::mock_env; use cosmwasm_std::Timestamp; + use cosmwasm_std::testing::mock_env; #[test] fn doesnt_allow_expirations_in_the_past() { @@ -1158,8 +1158,8 @@ mod tests { #[cfg(test)] mod delayed_allowance { use super::*; - use cosmwasm_std::testing::mock_env; use cosmwasm_std::Timestamp; + use cosmwasm_std::testing::mock_env; #[test] fn doesnt_allow_availability_in_the_past() { diff --git a/common/cosmwasm-smart-contracts/nym-pool-contract/src/utils.rs b/common/cosmwasm-smart-contracts/nym-pool-contract/src/utils.rs index 0b6f5ba1f4..8a5ac59264 100644 --- a/common/cosmwasm-smart-contracts/nym-pool-contract/src/utils.rs +++ b/common/cosmwasm-smart-contracts/nym-pool-contract/src/utils.rs @@ -20,8 +20,8 @@ pub fn ensure_unix_timestamp_not_in_the_past( #[cfg(test)] mod tests { use super::*; - use cosmwasm_std::testing::mock_env; use cosmwasm_std::Timestamp; + use cosmwasm_std::testing::mock_env; use time::macros::datetime; #[test] diff --git a/common/cosmwasm-smart-contracts/vesting-contract/src/error.rs b/common/cosmwasm-smart-contracts/vesting-contract/src/error.rs index a9453b6834..c8b1c03594 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/src/error.rs +++ b/common/cosmwasm-smart-contracts/vesting-contract/src/error.rs @@ -61,7 +61,9 @@ pub enum VestingContractError { #[error("VESTING ({l}): No bond found for account {0}", l = line!())] NoBondFound(String), - #[error("VESTING: Attempted to reduce mixnode bond pledge below zero! The current pledge is {current} and we attempted to reduce it by {decrease_by}.")] + #[error( + "VESTING: Attempted to reduce mixnode bond pledge below zero! The current pledge is {current} and we attempted to reduce it by {decrease_by}." + )] InvalidBondPledgeReduction { current: Coin, decrease_by: Coin }, #[error("VESTING ({l}): Action can only be executed by account owner -> {0}", l = line!())] @@ -85,13 +87,17 @@ pub enum VestingContractError { #[error("VESTING: ({l}: Account owned by {owner} has unpopulated vesting periods!", l = line!())] UnpopulatedVestingPeriods { owner: Addr }, - #[error("VESTING: Vesting account associated with {0} already exists, only addresses with not existing vesting accounts can be added as staking addresses")] + #[error( + "VESTING: Vesting account associated with {0} already exists, only addresses with not existing vesting accounts can be added as staking addresses" + )] StakingAccountExists(String), #[error("VESTING: {address} is not permitted to perform staking on behalf of {for_account}")] InvalidStakingAccount { address: Addr, for_account: Addr }, - #[error("VESTING: {address} ({acc_id} has already performed {num} individual delegations towards {mix_id}. No further delegations are allowed. Please consider consolidating those delegations instead. The current cap is {cap}.")] + #[error( + "VESTING: {address} ({acc_id} has already performed {num} individual delegations towards {mix_id}. No further delegations are allowed. Please consider consolidating those delegations instead. The current cap is {cap}." + )] TooManyDelegations { address: Addr, acc_id: VestingAccountStorageKey, diff --git a/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs b/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs index 303fe1e89f..9b2d4aa6e9 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs +++ b/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs @@ -6,9 +6,9 @@ use contracts_common::signing::MessageSignature; use cosmwasm_schema::cw_serde; use cosmwasm_std::{Coin, Timestamp}; use mixnet_contract_common::{ + Gateway, MixNode, NodeId, gateway::GatewayConfigUpdate, mixnode::{MixNodeConfigUpdate, NodeCostParams}, - Gateway, MixNode, NodeId, }; #[cfg(feature = "schema")] @@ -18,10 +18,10 @@ use cosmwasm_schema::QueryResponses; #[cfg(feature = "schema")] use crate::{ - account::Account, - types::{Period, PledgeData, VestingDelegation}, AccountsResponse, AllDelegationsResponse, DelegationTimesResponse, OriginalVestingResponse, VestingCoinsResponse, + account::Account, + types::{Period, PledgeData, VestingDelegation}, }; #[cw_serde] diff --git a/common/credential-proxy/src/deposits_buffer/helpers.rs b/common/credential-proxy/src/deposits_buffer/helpers.rs index 01613905ce..2c9203feed 100644 --- a/common/credential-proxy/src/deposits_buffer/helpers.rs +++ b/common/credential-proxy/src/deposits_buffer/helpers.rs @@ -118,7 +118,9 @@ pub async fn make_deposits_request( // that one is tricky. deposits technically got made, but we somehow failed to parse response, // in this case terminate the proxy with 0 exit code so it wouldn't get automatically restarted // because it requires some serious MANUAL intervention - error!("CRITICAL FAILURE: failed to parse out deposit information from the contract transaction. either the chain got upgraded and the schema changed or the ecash contract got changed! terminating the process. it has to be inspected manually. error was: {err}"); + error!( + "CRITICAL FAILURE: failed to parse out deposit information from the contract transaction. either the chain got upgraded and the schema changed or the ecash contract got changed! terminating the process. it has to be inspected manually. error was: {err}" + ); cancellation_on_critical_failure.cancel(); return Err(CredentialProxyError::DepositFailure); } @@ -126,7 +128,10 @@ pub async fn make_deposits_request( if contract_data.len() != amount { // another critical failure, that one should be quite impossible and thus has to be manually inspected - error!("CRITICAL FAILURE: failed to parse out all deposit information from the contract transaction. got {} responses while we sent {amount} deposits! either the chain got upgraded and the schema changed or the ecash contract got changed! terminating the process. it has to be inspected manually", contract_data.len()); + error!( + "CRITICAL FAILURE: failed to parse out all deposit information from the contract transaction. got {} responses while we sent {amount} deposits! either the chain got upgraded and the schema changed or the ecash contract got changed! terminating the process. it has to be inspected manually", + contract_data.len() + ); cancellation_on_critical_failure.cancel(); return Err(CredentialProxyError::DepositFailure); } @@ -138,7 +143,9 @@ pub async fn make_deposits_request( Ok(deposit_id) => deposit_id, Err(err) => { // another impossibility - error!("CRITICAL FAILURE: failed to parse out deposit id out of the response at index {response_index}: {err}. either the chain got upgraded and the schema changed or the ecash contract got changed! terminating the process. it has to be inspected manually"); + error!( + "CRITICAL FAILURE: failed to parse out deposit id out of the response at index {response_index}: {err}. either the chain got upgraded and the schema changed or the ecash contract got changed! terminating the process. it has to be inspected manually" + ); cancellation_on_critical_failure.cancel(); return Err(CredentialProxyError::DepositFailure); } diff --git a/common/credential-proxy/src/deposits_buffer/mod.rs b/common/credential-proxy/src/deposits_buffer/mod.rs index db88857353..6ddaa9fedf 100644 --- a/common/credential-proxy/src/deposits_buffer/mod.rs +++ b/common/credential-proxy/src/deposits_buffer/mod.rs @@ -17,7 +17,7 @@ use tokio_util::sync::CancellationToken; use tracing::{debug, info, instrument, warn}; use uuid::Uuid; -pub use helpers::{make_deposits_request, split_deposits, BufferedDeposit, PerformedDeposits}; +pub use helpers::{BufferedDeposit, PerformedDeposits, make_deposits_request, split_deposits}; pub(crate) mod helpers; mod refill_task; @@ -219,7 +219,9 @@ impl DepositsBuffer { match maybe_deposit { None => { - warn!("we currently don't have any usable deposits! are we using them up faster than we request them?"); + warn!( + "we currently don't have any usable deposits! are we using them up faster than we request them?" + ); // we have to wait until refill task has completed (either initiated by this or another fn call) self.wait_for_deposit(request_uuid, requested_on, client_pubkey) @@ -242,7 +244,9 @@ impl DepositsBuffer { let task_handle = self.inner.deposits_refill_task.take_task_join_handle(); if let Some(task_handle) = task_handle { if !task_handle.is_finished() { - info!("the deposit refill task is currently in progress - waiting for the current transaction to finish before concluding shutdown"); + info!( + "the deposit refill task is currently in progress - waiting for the current transaction to finish before concluding shutdown" + ); let _ = task_handle.await; } } diff --git a/common/credential-proxy/src/deposits_buffer/refill_task.rs b/common/credential-proxy/src/deposits_buffer/refill_task.rs index 4f09df55b0..e06571aca7 100644 --- a/common/credential-proxy/src/deposits_buffer/refill_task.rs +++ b/common/credential-proxy/src/deposits_buffer/refill_task.rs @@ -42,7 +42,9 @@ impl RefillTask { if let Some(existing_handle) = guard.as_ref() { if !existing_handle.is_finished() { - error!("CRITICAL BUG: there was already a deposit refill task spawned that hasn't yet finished") + error!( + "CRITICAL BUG: there was already a deposit refill task spawned that hasn't yet finished" + ) } } diff --git a/common/credential-proxy/src/error.rs b/common/credential-proxy/src/error.rs index d50264cdc7..8db781da1e 100644 --- a/common/credential-proxy/src/error.rs +++ b/common/credential-proxy/src/error.rs @@ -3,7 +3,7 @@ use nym_ecash_signer_check::SignerCheckError; use nym_validator_client::coconut::EcashApiError; -use nym_validator_client::nym_api::{error::NymAPIError, EpochId}; +use nym_validator_client::nym_api::{EpochId, error::NymAPIError}; use nym_validator_client::nyxd::error::NyxdError; use std::io; use std::net::SocketAddr; @@ -33,7 +33,9 @@ pub enum CredentialProxyError { #[error("the provided expiration date is too early")] ExpirationDateTooEarly, - #[error("failed to bind to {address}: {source}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?")] + #[error( + "failed to bind to {address}: {source}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?" + )] SocketBindFailure { address: SocketAddr, source: io::Error, @@ -89,7 +91,7 @@ pub enum CredentialProxyError { InsufficientNumberOfSigners { available: usize, threshold: u64 }, #[error( - "we have only managed to obtain {available} partial credentials while the minimum threshold is {threshold}" + "we have only managed to obtain {available} partial credentials while the minimum threshold is {threshold}" )] InsufficientNumberOfCredentials { available: usize, threshold: u64 }, @@ -102,7 +104,9 @@ pub enum CredentialProxyError { #[error("the DKG has not yet been initialised in the system")] UninitialisedDkg, - #[error("credentials can't yet be issued in the system. approximate expected availability: {availability}")] + #[error( + "credentials can't yet be issued in the system. approximate expected availability: {availability}" + )] CredentialsNotYetIssuable { availability: OffsetDateTime }, #[error("reached seemingly impossible ecash failure")] @@ -140,7 +144,9 @@ pub enum CredentialProxyError { #[error("failed to obtain wallet shares with id {id}: {message}")] ShareByIdLoadError { message: String, id: i64 }, - #[error("failed to obtain wallet shares with device_id {device_id} and credential_id: {credential_id}: {message}")] + #[error( + "failed to obtain wallet shares with device_id {device_id} and credential_id: {credential_id}: {message}" + )] ShareByDeviceLoadError { message: String, device_id: String, diff --git a/common/credential-proxy/src/helpers.rs b/common/credential-proxy/src/helpers.rs index 8f45ea99e4..2721c7a521 100644 --- a/common/credential-proxy/src/helpers.rs +++ b/common/credential-proxy/src/helpers.rs @@ -1,8 +1,8 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use rand::rngs::OsRng; use rand::RngCore; +use rand::rngs::OsRng; use time::OffsetDateTime; use tracing::{debug, info, warn}; use uuid::Uuid; diff --git a/common/credential-proxy/src/http_helpers.rs b/common/credential-proxy/src/http_helpers.rs index 129fcfa86b..d1c187802e 100644 --- a/common/credential-proxy/src/http_helpers.rs +++ b/common/credential-proxy/src/http_helpers.rs @@ -2,9 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use crate::error::CredentialProxyError; +use axum::Json; use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; -use axum::Json; use nym_credential_proxy_requests::api::v1::ErrorResponse; use tracing::warn; use uuid::Uuid; diff --git a/common/credential-proxy/src/nym_api_helpers.rs b/common/credential-proxy/src/nym_api_helpers.rs index 3ed51e3805..71caa2806f 100644 --- a/common/credential-proxy/src/nym_api_helpers.rs +++ b/common/credential-proxy/src/nym_api_helpers.rs @@ -5,12 +5,12 @@ // it should have been therefore extracted to a common crate instead and imported as dependency use crate::error::CredentialProxyError; -use futures::{stream, StreamExt}; +use futures::{StreamExt, stream}; use nym_cache::CachedImmutableItems; -use nym_credentials::ecash::utils::{cred_exp_date, ecash_today, EcashTime}; +use nym_credentials::ecash::utils::{EcashTime, cred_exp_date, ecash_today}; +use nym_validator_client::EcashApiClient; use nym_validator_client::nym_api::EpochId; use nym_validator_client::nyxd::contract_traits::dkg_query_client::Epoch; -use nym_validator_client::EcashApiClient; use std::cmp::min; use std::future::Future; use time::{Date, OffsetDateTime}; diff --git a/common/credential-proxy/src/quorum_checker.rs b/common/credential-proxy/src/quorum_checker.rs index 6940a90749..47a8ba6baf 100644 --- a/common/credential-proxy/src/quorum_checker.rs +++ b/common/credential-proxy/src/quorum_checker.rs @@ -5,8 +5,8 @@ use crate::error::CredentialProxyError; use crate::shared_state::nyxd_client::ChainClient; use nym_ecash_signer_check::{check_known_dealers, dkg_details_with_client}; use std::ops::Deref; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; use tokio_util::sync::CancellationToken; use tracing::{error, info, warn}; @@ -67,7 +67,9 @@ impl QuorumStateChecker { let res = check_known_dealers(dkg_details).await?; let Some(signing_threshold) = res.threshold else { - warn!("signing threshold is currently unavailable and we have not yet implemented credential issuance during DKG transition"); + warn!( + "signing threshold is currently unavailable and we have not yet implemented credential issuance during DKG transition" + ); return Ok(false); }; diff --git a/common/credential-proxy/src/shared_state/ecash_state.rs b/common/credential-proxy/src/shared_state/ecash_state.rs index cc4b850edb..5a83e16eea 100644 --- a/common/credential-proxy/src/shared_state/ecash_state.rs +++ b/common/credential-proxy/src/shared_state/ecash_state.rs @@ -3,7 +3,7 @@ use crate::error::CredentialProxyError; use crate::nym_api_helpers::{ - ensure_sane_expiration_date, query_all_threshold_apis, CachedEpoch, CachedImmutableEpochItem, + CachedEpoch, CachedImmutableEpochItem, ensure_sane_expiration_date, query_all_threshold_apis, }; use crate::quorum_checker::QuorumState; use crate::shared_state::nyxd_client::ChainClient; @@ -16,20 +16,20 @@ use nym_credentials::ecash::utils::EcashTime; use nym_credentials::{ AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, EpochVerificationKey, }; +use nym_validator_client::EcashApiClient; use nym_validator_client::client::NymApiClientExt; use nym_validator_client::coconut::EcashApiError; use nym_validator_client::nym_api::EpochId; +use nym_validator_client::nyxd::Coin; use nym_validator_client::nyxd::contract_traits::dkg_query_client::Epoch; use nym_validator_client::nyxd::contract_traits::{DkgQueryClient, PagedDkgQueryClient}; -use nym_validator_client::nyxd::Coin; -use nym_validator_client::EcashApiClient; use time::{Date, OffsetDateTime}; use tokio::sync::{RwLock, RwLockReadGuard}; use tracing::info; +pub use nym_compact_ecash::VerificationKeyAuth; pub use nym_compact_ecash::scheme::coin_indices_signatures::CoinIndexSignatureShare; pub use nym_compact_ecash::scheme::expiration_date_signatures::ExpirationDateSignatureShare; -pub use nym_compact_ecash::VerificationKeyAuth; pub use nym_credentials::{IssuanceTicketBook, IssuedTicketBook}; pub use nym_credentials_interface::{TicketType, TicketTypeRepr}; diff --git a/common/credential-proxy/src/shared_state/mod.rs b/common/credential-proxy/src/shared_state/mod.rs index f9bccb94b5..565f49a8f5 100644 --- a/common/credential-proxy/src/shared_state/mod.rs +++ b/common/credential-proxy/src/shared_state/mod.rs @@ -13,10 +13,10 @@ use nym_credential_proxy_requests::api::v1::ticketbook::models::{ }; use nym_credentials::{AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures}; use nym_ecash_contract_common::deposit::DepositId; -use nym_validator_client::nym_api::EpochId; -use nym_validator_client::nyxd::contract_traits::dkg_query_client::Epoch; -use nym_validator_client::nyxd::Coin; use nym_validator_client::EcashApiClient; +use nym_validator_client::nym_api::EpochId; +use nym_validator_client::nyxd::Coin; +use nym_validator_client::nyxd::contract_traits::dkg_query_client::Epoch; use std::sync::Arc; use std::time::Duration; use time::{Date, OffsetDateTime}; @@ -92,7 +92,9 @@ impl CredentialProxyState { let time_taken = start.elapsed(); let formatted = humantime::format_duration(time_taken); if time_taken > Duration::from_secs(10) { - warn!("attempting to get buffered deposit took {formatted}. perhaps the buffer is too small or the process/chain is overloaded?") + warn!( + "attempting to get buffered deposit took {formatted}. perhaps the buffer is too small or the process/chain is overloaded?" + ) } else { debug!("attempting to get buffered deposit took {formatted}") }; @@ -106,7 +108,9 @@ impl CredentialProxyState { .insert_deposit_usage_error(deposit_id, error) .await { - error!("failed to insert information about deposit (id: {deposit_id}) usage failure: {err}") + error!( + "failed to insert information about deposit (id: {deposit_id}) usage failure: {err}" + ) } } diff --git a/common/credential-proxy/src/shared_state/nyxd_client.rs b/common/credential-proxy/src/shared_state/nyxd_client.rs index 4c9878291d..6adaf3d600 100644 --- a/common/credential-proxy/src/shared_state/nyxd_client.rs +++ b/common/credential-proxy/src/shared_state/nyxd_client.rs @@ -7,7 +7,7 @@ use nym_ecash_contract_common::msg::ExecuteMsg; use nym_validator_client::nyxd::contract_traits::NymContractsProvider; use nym_validator_client::nyxd::cosmwasm_client::types::ExecuteResult; use nym_validator_client::nyxd::{Coin, Config, CosmWasmClient, NyxdClient}; -use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient}; +use nym_validator_client::{DirectSigningHttpRpcNyxdClient, nyxd}; use std::ops::Deref; use std::sync::Arc; use std::time::Duration; diff --git a/common/credential-proxy/src/shared_state/required_deposit_cache.rs b/common/credential-proxy/src/shared_state/required_deposit_cache.rs index 9b45f5da4b..fa8094cb53 100644 --- a/common/credential-proxy/src/shared_state/required_deposit_cache.rs +++ b/common/credential-proxy/src/shared_state/required_deposit_cache.rs @@ -3,8 +3,8 @@ use crate::error::CredentialProxyError; use crate::shared_state::nyxd_client::ChainClient; -use nym_validator_client::nyxd::contract_traits::EcashQueryClient; use nym_validator_client::nyxd::Coin; +use nym_validator_client::nyxd::contract_traits::EcashQueryClient; use std::sync::Arc; use time::OffsetDateTime; use tokio::sync::RwLock; diff --git a/common/credential-proxy/src/storage/manager.rs b/common/credential-proxy/src/storage/manager.rs index f72341cd08..e959f9bb2c 100644 --- a/common/credential-proxy/src/storage/manager.rs +++ b/common/credential-proxy/src/storage/manager.rs @@ -380,8 +380,9 @@ impl SqliteStorageManager { return Ok(()); } - let mut query_builder = - sqlx::QueryBuilder::new("INSERT INTO ecash_deposit (deposit_id, deposit_tx_hash, requested_on, deposit_amount, ed25519_deposit_private_key) "); + let mut query_builder = sqlx::QueryBuilder::new( + "INSERT INTO ecash_deposit (deposit_id, deposit_tx_hash, requested_on, deposit_amount, ed25519_deposit_private_key) ", + ); query_builder.push_values(&deposits, |mut b, deposit| { b.push_bind(deposit.deposit_id) diff --git a/common/credential-proxy/src/storage/mod.rs b/common/credential-proxy/src/storage/mod.rs index fa403f425d..b3c2714ece 100644 --- a/common/credential-proxy/src/storage/mod.rs +++ b/common/credential-proxy/src/storage/mod.rs @@ -13,8 +13,8 @@ use nym_credentials::{ use nym_validator_client::ecash::BlindedSignatureResponse; use nym_validator_client::nym_api::EpochId; use nym_validator_client::nyxd::contract_traits::ecash_query_client::DepositId; -use sqlx::sqlite::{SqliteAutoVacuum, SqliteSynchronous}; use sqlx::ConnectOptions; +use sqlx::sqlite::{SqliteAutoVacuum, SqliteSynchronous}; use std::fmt::Debug; use std::path::Path; use std::time::Duration; @@ -405,8 +405,8 @@ mod tests { use nym_compact_ecash::scheme::keygen::KeyPairUser; use nym_crypto::asymmetric::ed25519; use nym_validator_client::nyxd::{Coin, Hash}; - use rand::rngs::OsRng; use rand::RngCore; + use rand::rngs::OsRng; use std::ops::Deref; use tempfile::{NamedTempFile, TempPath}; diff --git a/common/credential-proxy/src/ticketbook_manager/mod.rs b/common/credential-proxy/src/ticketbook_manager/mod.rs index cbe48460dc..ccc7a7ad9e 100644 --- a/common/credential-proxy/src/ticketbook_manager/mod.rs +++ b/common/credential-proxy/src/ticketbook_manager/mod.rs @@ -4,12 +4,12 @@ use crate::deposits_buffer::DepositsBuffer; use crate::error::CredentialProxyError; use crate::quorum_checker::QuorumStateChecker; +use crate::shared_state::CredentialProxyState; use crate::shared_state::ecash_state::EcashState; use crate::shared_state::nyxd_client::ChainClient; use crate::shared_state::required_deposit_cache::RequiredDepositCache; -use crate::shared_state::CredentialProxyState; -use crate::storage::pruner::StoragePruner; use crate::storage::CredentialProxyStorage; +use crate::storage::pruner::StoragePruner; use crate::webhook::ZkNymWebhook; use nym_credentials::ecash::utils::ecash_default_expiration_date; use nym_validator_client::nym_api::EpochId; diff --git a/common/credential-proxy/src/ticketbook_manager/shares_handlers.rs b/common/credential-proxy/src/ticketbook_manager/shares_handlers.rs index 4890c7608b..095931e06e 100644 --- a/common/credential-proxy/src/ticketbook_manager/shares_handlers.rs +++ b/common/credential-proxy/src/ticketbook_manager/shares_handlers.rs @@ -8,7 +8,7 @@ use nym_credential_proxy_requests::api::v1::ticketbook::models::{ GlobalDataParams, TicketbookWalletSharesResponse, }; use nym_validator_client::nym_api::EpochId; -use tracing::{debug, span, Instrument, Level}; +use tracing::{Instrument, Level, debug, span}; use uuid::Uuid; impl TicketbookManager { diff --git a/common/credential-proxy/src/ticketbook_manager/ticketbook_handlers.rs b/common/credential-proxy/src/ticketbook_manager/ticketbook_handlers.rs index b812878e22..bcfd4c3e9d 100644 --- a/common/credential-proxy/src/ticketbook_manager/ticketbook_handlers.rs +++ b/common/credential-proxy/src/ticketbook_manager/ticketbook_handlers.rs @@ -12,7 +12,7 @@ use nym_credential_proxy_requests::api::v1::ticketbook::models::{ TicketbookWalletSharesResponse, }; use time::OffsetDateTime; -use tracing::{error, info, span, warn, Instrument, Level}; +use tracing::{Instrument, Level, error, info, span, warn}; use uuid::Uuid; impl TicketbookManager { diff --git a/common/credential-proxy/src/ticketbook_manager/wallet_shares.rs b/common/credential-proxy/src/ticketbook_manager/wallet_shares.rs index d6508ce2fe..de4c3f848f 100644 --- a/common/credential-proxy/src/ticketbook_manager/wallet_shares.rs +++ b/common/credential-proxy/src/ticketbook_manager/wallet_shares.rs @@ -4,7 +4,7 @@ use crate::error::CredentialProxyError; use crate::storage::models::BlindedShares; use crate::ticketbook_manager::TicketbookManager; -use futures::{stream, StreamExt}; +use futures::{StreamExt, stream}; use nym_compact_ecash::Base58; use nym_credential_proxy_requests::api::v1::ticketbook::models::{ TicketbookAsyncRequest, TicketbookObtainParams, TicketbookRequest, diff --git a/common/credential-proxy/src/webhook.rs b/common/credential-proxy/src/webhook.rs index 256a6e76fb..79dc4d134a 100644 --- a/common/credential-proxy/src/webhook.rs +++ b/common/credential-proxy/src/webhook.rs @@ -3,7 +3,7 @@ use reqwest::header::AUTHORIZATION; use serde::Serialize; -use tracing::{debug, error, instrument, span, Instrument, Level}; +use tracing::{Instrument, Level, debug, error, instrument, span}; use url::Url; use uuid::Uuid; diff --git a/common/credential-verification/src/bandwidth_storage_manager.rs b/common/credential-verification/src/bandwidth_storage_manager.rs index 17f89a59fb..7286229e68 100644 --- a/common/credential-verification/src/bandwidth_storage_manager.rs +++ b/common/credential-verification/src/bandwidth_storage_manager.rs @@ -1,9 +1,9 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::error::*; use crate::BandwidthFlushingBehaviourConfig; use crate::ClientBandwidth; +use crate::error::*; use nym_credentials::ecash::utils::ecash_today; use nym_credentials_interface::Bandwidth; use nym_gateway_requests::ServerResponse; diff --git a/common/credential-verification/src/ecash/credential_sender.rs b/common/credential-verification/src/ecash/credential_sender.rs index 98706f37ac..85c54b01ad 100644 --- a/common/credential-verification/src/ecash/credential_sender.rs +++ b/common/credential-verification/src/ecash/credential_sender.rs @@ -1,10 +1,10 @@ // Copyright 2022-2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only +use crate::Error; use crate::ecash::error::EcashTicketError; use crate::ecash::helpers::for_each_api_concurrent; use crate::ecash::state::SharedState; -use crate::Error; use cosmwasm_std::Fraction; use cw_utils::ThresholdResponse; use futures::channel::mpsc::UnboundedReceiver; @@ -13,22 +13,22 @@ use nym_api_requests::constants::MIN_BATCH_REDEMPTION_DELAY; use nym_api_requests::ecash::models::{BatchRedeemTicketsBody, VerifyEcashTicketBody}; use nym_credentials_interface::Bandwidth; use nym_credentials_interface::{ClientTicket, TicketType}; +use nym_validator_client::EcashApiClient; use nym_validator_client::coconut::EcashApiError; use nym_validator_client::nym_api::{EpochId, NymApiClientExt}; +use nym_validator_client::nyxd::AccountId; use nym_validator_client::nyxd::contract_traits::{ EcashSigningClient, MultisigQueryClient, MultisigSigningClient, PagedMultisigQueryClient, }; use nym_validator_client::nyxd::cosmwasm_client::ContractResponseData; use nym_validator_client::nyxd::cw3::Status; -use nym_validator_client::nyxd::AccountId; -use nym_validator_client::EcashApiClient; use si_scale::helpers::bibytes2; use std::collections::{HashMap, HashSet}; use std::ops::Deref; use std::sync::atomic::{AtomicUsize, Ordering}; use time::OffsetDateTime; use tokio::sync::{Mutex, RwLockReadGuard}; -use tokio::time::{interval_at, Duration, Instant}; +use tokio::time::{Duration, Instant, interval_at}; use tracing::{debug, error, info, instrument, trace, warn}; enum ProposalResult { @@ -352,7 +352,9 @@ impl CredentialHandler { Ok(accepted) } Err(err) => { - error!("failed to send ticket {ticket_id} for verification to ecash signer '{client}': {err}. if we don't reach quorum, we'll retry later"); + error!( + "failed to send ticket {ticket_id} for verification to ecash signer '{client}': {err}. if we don't reach quorum, we'll retry later" + ); Err(EcashTicketError::ApiFailure(EcashApiError::NymApi { source: nym_validator_client::ValidatorClientError::from(err), })) @@ -443,7 +445,9 @@ impl CredentialHandler { let rejected_ratio = rejected as f32 / total as f32; let rejected_perc = rejected_ratio * 100.; if rejected_ratio >= (1. - self.config.minimum_api_quorum) { - error!("{rejected_perc:.2}% of signers rejected ticket {ticket_id}. we won't be able to redeem it"); + error!( + "{rejected_perc:.2}% of signers rejected ticket {ticket_id}. we won't be able to redeem it" + ); self.shared_state .storage @@ -456,12 +460,19 @@ impl CredentialHandler { let accepted_ratio = (total - rejected - num_failures) as f32 / total as f32; let accepted_perc = accepted_ratio * 100.; match accepted_ratio { - n if n < self.multisig_threshold => error!("less than 2/3 of signers ({accepted_perc:.2}%) accepted ticket {ticket_id}. we won't be able to spend it"), - n if n < self.config.minimum_api_quorum => warn!("less than 80%, but more than 67% of signers ({accepted_perc:.2}%) accepted ticket {ticket_id}. technically we could redeem it, but we'll wait for the bigger quorum"), + n if n < self.multisig_threshold => error!( + "less than 2/3 of signers ({accepted_perc:.2}%) accepted ticket {ticket_id}. we won't be able to spend it" + ), + n if n < self.config.minimum_api_quorum => warn!( + "less than 80%, but more than 67% of signers ({accepted_perc:.2}%) accepted ticket {ticket_id}. technically we could redeem it, but we'll wait for the bigger quorum" + ), _ => { trace!("{accepted_perc:.2}% of signers accepted ticket {ticket_id}"); - self.shared_state.storage.update_verified_ticket(pending.ticket.ticket_id).await?; - return Ok(true) + self.shared_state + .storage + .update_verified_ticket(pending.ticket.ticket_id) + .await?; + return Ok(true); } } @@ -484,7 +495,10 @@ impl CredentialHandler { .send_pending_ticket_for_verification(&mut pending, Some(api_clients)) .await?; if !got_quorum { - debug!("failed to reach quorum for ticket {}. apis: {:?} haven't responded. we'll retry later", pending.ticket.ticket_id, pending.pending); + debug!( + "failed to reach quorum for ticket {}. apis: {:?} haven't responded. we'll retry later", + pending.ticket.ticket_id, pending.pending + ); self.pending_tickets.push(pending); } else { // since we reached the quorum we no longer need to hold the ticket's binary data @@ -513,7 +527,10 @@ impl CredentialHandler { match self.try_resolve_pending_proposal(&mut pending, None).await { Ok(resolution) => { if resolution.is_pending() { - warn!("still failed to reach quorum for proposal {}. apis: {:?} haven't responded. we'll retry later", pending.proposal_id, pending.pending); + warn!( + "still failed to reach quorum for proposal {}. apis: {:?} haven't responded. we'll retry later", + pending.proposal_id, pending.pending + ); still_failing.push(pending); } else { self.shared_state @@ -527,7 +544,9 @@ impl CredentialHandler { } } Err(err) => { - error!("experienced internal error when attempting to resolve pending proposal: {err}"); + error!( + "experienced internal error when attempting to resolve pending proposal: {err}" + ); // make sure to update internal state to not lose any data self.pending_redemptions.push(pending); self.pending_redemptions.append(&mut still_failing); @@ -547,7 +566,10 @@ impl CredentialHandler { { Ok(got_quorum) => { if !got_quorum { - warn!("still failed to reach quorum for ticket {}. apis: {:?} haven't responded. we'll retry later", pending.ticket.ticket_id, pending.pending); + warn!( + "still failed to reach quorum for ticket {}. apis: {:?} haven't responded. we'll retry later", + pending.ticket.ticket_id, pending.pending + ); still_failing.push(pending); } else { // since we reached the quorum we no longer need to hold the ticket's binary data @@ -558,7 +580,9 @@ impl CredentialHandler { } } Err(err) => { - error!("experienced internal error when attempting to resolve pending ticket: {err}"); + error!( + "experienced internal error when attempting to resolve pending ticket: {err}" + ); // make sure to update internal state to not lose any data self.pending_tickets.push(pending); self.pending_tickets.append(&mut still_failing); @@ -591,7 +615,9 @@ impl CredentialHandler { Ok(accepted) } Err(err) => { - error!("failed to send proposal {proposal_id} for redemption vote to ecash signer '{client}': {err}. if we don't reach quorum, we'll retry later"); + error!( + "failed to send proposal {proposal_id} for redemption vote to ecash signer '{client}': {err}. if we don't reach quorum, we'll retry later" + ); Ok(false) } } @@ -713,7 +739,9 @@ impl CredentialHandler { let rejected_ratio = rejected as f32 / total as f32; let rejected_perc = rejected_ratio * 100.; if rejected_ratio >= (1. - self.multisig_threshold) { - error!("{rejected_perc:.2}% of signers rejected proposal {proposal_id}. we won't be able to execute it"); + error!( + "{rejected_perc:.2}% of signers rejected proposal {proposal_id}. we won't be able to execute it" + ); // no need to query the chain as with so many rejections it's impossible it has passed. return Ok(ProposalResult::Rejected); } @@ -722,11 +750,15 @@ impl CredentialHandler { let accepted_perc = accepted_ratio * 100.; match accepted_ratio { n if n < self.multisig_threshold => { - error!("less than 2/3 of signers ({accepted_perc:.2}%) accepted proposal {proposal_id}. we're not yet be able to execute it to get funds out"); + error!( + "less than 2/3 of signers ({accepted_perc:.2}%) accepted proposal {proposal_id}. we're not yet be able to execute it to get funds out" + ); return Ok(ProposalResult::Pending); } n if n < self.config.minimum_api_quorum => { - warn!("the system seems to be a bit unstable: less than 80%, but more than 67% of signers ({accepted_perc:.2}%) accepted proposal {proposal_id}"); + warn!( + "the system seems to be a bit unstable: less than 80%, but more than 67% of signers ({accepted_perc:.2}%) accepted proposal {proposal_id}" + ); } _ => { trace!("{accepted_perc:.2}% of signers accepted proposal {proposal_id}"); @@ -784,7 +816,9 @@ impl CredentialHandler { None } (_, Some(on_chain)) => { - warn!("we seem to have crashed after creating proposal, but before persisting it onto disk!"); + warn!( + "we seem to have crashed after creating proposal, but before persisting it onto disk!" + ); Some(on_chain) } @@ -805,12 +839,20 @@ impl CredentialHandler { if latest_stored.created_at + self.config.maximum_time_between_redemption < now { {} } else { - debug!("we only have {} verified tickets. there's no point in creating a redemption request yet. (we need at least {} (configurable))", verified_tickets.len(), self.config.minimum_redemption_tickets); + debug!( + "we only have {} verified tickets. there's no point in creating a redemption request yet. (we need at least {} (configurable))", + verified_tickets.len(), + self.config.minimum_redemption_tickets + ); return Ok(()); } } else { // first proposal - debug!("we only have {} verified tickets. there's no point in creating a redemption request yet. (we need at least {} (configurable))", verified_tickets.len(), self.config.minimum_redemption_tickets); + debug!( + "we only have {} verified tickets. there's no point in creating a redemption request yet. (we need at least {} (configurable))", + verified_tickets.len(), + self.config.minimum_redemption_tickets + ); return Ok(()); } } @@ -879,7 +921,10 @@ impl CredentialHandler { .try_resolve_pending_proposal(&mut pending, Some(api_clients)) .await?; if resolution.is_pending() { - warn!("failed to reach quorum for proposal {proposal_id}. apis: {:?} haven't responded. we'll retry later", pending.pending); + warn!( + "failed to reach quorum for proposal {proposal_id}. apis: {:?} haven't responded. we'll retry later", + pending.pending + ); self.pending_redemptions.push(pending); } else { self.shared_state @@ -896,7 +941,9 @@ impl CredentialHandler { } async fn periodic_operations(&mut self) -> Result<(), EcashTicketError> { - trace!("attempting to resolve all pending operations -> tickets that are waiting for verification and possibly redemption"); + trace!( + "attempting to resolve all pending operations -> tickets that are waiting for verification and possibly redemption" + ); // 1. retry all operations that have failed in the past: verification requests and pending redemption self.resolve_pending().await?; diff --git a/common/credential-verification/src/ecash/error.rs b/common/credential-verification/src/ecash/error.rs index ff85a32c3e..e4fd2f503b 100644 --- a/common/credential-verification/src/ecash/error.rs +++ b/common/credential-verification/src/ecash/error.rs @@ -72,7 +72,9 @@ pub enum EcashTicketError { #[error("the DKG contract is unavailable")] UnavailableDkgContract, - #[error("the DKG threshold value for epoch {epoch_id} is currently unavailable. we're probably mid-epoch transition")] + #[error( + "the DKG threshold value for epoch {epoch_id} is currently unavailable. we're probably mid-epoch transition" + )] DKGThresholdUnavailable { epoch_id: EpochId }, #[error("could not create redemption proposal as we have tickets pending full verification")] diff --git a/common/credential-verification/src/ecash/mod.rs b/common/credential-verification/src/ecash/mod.rs index 71d1198988..a5eac14867 100644 --- a/common/credential-verification/src/ecash/mod.rs +++ b/common/credential-verification/src/ecash/mod.rs @@ -9,10 +9,10 @@ use error::EcashTicketError; use futures::channel::mpsc::{self, UnboundedSender}; use nym_credentials::CredentialSpendingData; use nym_credentials_interface::{ClientTicket, CompactEcashError, NymPayInfo, VerificationKeyAuth}; -use nym_gateway_storage::traits::BandwidthGatewayStorage; use nym_gateway_storage::GatewayStorage; -use nym_validator_client::nym_api::EpochId; +use nym_gateway_storage::traits::BandwidthGatewayStorage; use nym_validator_client::DirectSigningHttpRpcNyxdClient; +use nym_validator_client::nym_api::EpochId; use state::SharedState; use time::OffsetDateTime; use tokio::sync::{Mutex, RwLockReadGuard}; diff --git a/common/credential-verification/src/ecash/state.rs b/common/credential-verification/src/ecash/state.rs index 85ada02f5c..389ee98c68 100644 --- a/common/credential-verification/src/ecash/state.rs +++ b/common/credential-verification/src/ecash/state.rs @@ -1,19 +1,19 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::ecash::error::EcashTicketError; use crate::Error; -use cosmwasm_std::{from_json, CosmosMsg, WasmMsg}; +use crate::ecash::error::EcashTicketError; +use cosmwasm_std::{CosmosMsg, WasmMsg, from_json}; use nym_credentials_interface::VerificationKeyAuth; use nym_ecash_contract_common::msg::ExecuteMsg; use nym_gateway_storage::traits::BandwidthGatewayStorage; use nym_validator_client::coconut::all_ecash_api_clients; use nym_validator_client::nym_api::EpochId; +use nym_validator_client::nyxd::AccountId; use nym_validator_client::nyxd::contract_traits::{ DkgQueryClient, MultisigQueryClient, NymContractsProvider, }; use nym_validator_client::nyxd::cw3::ProposalResponse; -use nym_validator_client::nyxd::AccountId; use nym_validator_client::{DirectSigningHttpRpcNyxdClient, EcashApiClient}; use std::collections::BTreeMap; use std::ops::Deref; @@ -53,7 +53,9 @@ impl SharedState { } let Ok(current_epoch) = nyxd_client.get_current_epoch().await else { - error!("the specified DKG contract address is invalid - no coconut credentials will be redeemable"); + error!( + "the specified DKG contract address is invalid - no coconut credentials will be redeemable" + ); // if we require coconut credentials, we MUST have DKG contract available return Err(EcashTicketError::UnavailableDkgContract.into()); }; diff --git a/common/credential-verification/src/error.rs b/common/credential-verification/src/error.rs index 34dbdb53b6..a00ce0e268 100644 --- a/common/credential-verification/src/error.rs +++ b/common/credential-verification/src/error.rs @@ -35,7 +35,9 @@ pub enum Error { #[error("This gateway is only accepting coconut credentials for bandwidth")] OnlyCoconutCredentials, - #[error("insufficient bandwidth available to process the request. required: {required}B, available: {available}B")] + #[error( + "insufficient bandwidth available to process the request. required: {required}B, available: {available}B" + )] OutOfBandwidth { required: i64, available: i64 }, #[error("Internal gateway storage error")] diff --git a/common/credential-verification/src/lib.rs b/common/credential-verification/src/lib.rs index 61f9a1b30c..f306867d98 100644 --- a/common/credential-verification/src/lib.rs +++ b/common/credential-verification/src/lib.rs @@ -4,7 +4,7 @@ use crate::ecash::traits::EcashManager; use async_trait::async_trait; use bandwidth_storage_manager::BandwidthStorageManager; -use nym_credentials::ecash::utils::{cred_exp_date, ecash_today, EcashTime}; +use nym_credentials::ecash::utils::{EcashTime, cred_exp_date, ecash_today}; use nym_credentials_interface::{Bandwidth, ClientTicket, TicketType}; use nym_gateway_requests::models::CredentialSpendingRequest; use std::sync::Arc; diff --git a/common/credentials-interface/src/lib.rs b/common/credentials-interface/src/lib.rs index 7a8ed7fce2..91e08ee770 100644 --- a/common/credentials-interface/src/lib.rs +++ b/common/credentials-interface/src/lib.rs @@ -7,9 +7,12 @@ use thiserror::Error; use time::{Date, OffsetDateTime}; pub use nym_compact_ecash::{ + Base58, BlindedSignature, Bytable, EncodedDate, EncodedTicketType, PartialWallet, PayInfo, + PublicKeyUser, SecretKeyUser, VerificationKeyAuth, WithdrawalRequest, aggregate_verification_keys, aggregate_wallets, constants, ecash_parameters, error::CompactEcashError, generate_keypair_user, generate_keypair_user_from_seed, issue_verify, + scheme::Payment, scheme::coin_indices_signatures::aggregate_indices_signatures, scheme::coin_indices_signatures::{ AnnotatedCoinIndexSignature, CoinIndexSignature, CoinIndexSignatureShare, @@ -22,12 +25,10 @@ pub use nym_compact_ecash::{ }, scheme::keygen::KeyPairUser, scheme::withdrawal::RequestInfo, - scheme::Payment, scheme::{Wallet, WalletSignatures}, - withdrawal_request, Base58, BlindedSignature, Bytable, EncodedDate, EncodedTicketType, - PartialWallet, PayInfo, PublicKeyUser, SecretKeyUser, VerificationKeyAuth, WithdrawalRequest, + withdrawal_request, }; -pub use nym_ecash_time::{ecash_today, EcashTime}; +pub use nym_ecash_time::{EcashTime, ecash_today}; pub use nym_network_defaults::TicketTypeRepr; #[derive(Debug, Clone)] diff --git a/common/crypto/src/asymmetric/ed25519/mod.rs b/common/crypto/src/asymmetric/ed25519/mod.rs index 8d23ee7d8c..7862cf85bf 100644 --- a/common/crypto/src/asymmetric/ed25519/mod.rs +++ b/common/crypto/src/asymmetric/ed25519/mod.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 pub use ed25519_dalek::SignatureError; -pub use ed25519_dalek::{Verifier, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATURE_LENGTH}; +pub use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATURE_LENGTH, Verifier}; use ed25519_dalek::Signer; use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair}; @@ -18,7 +18,7 @@ pub mod serde_helpers; pub use serde_helpers::*; #[cfg(feature = "sphinx")] -use nym_sphinx_types::{DestinationAddressBytes, DESTINATION_ADDRESS_LENGTH}; +use nym_sphinx_types::{DESTINATION_ADDRESS_LENGTH, DestinationAddressBytes}; #[cfg(feature = "rand")] use rand::{CryptoRng, Rng, RngCore}; @@ -75,7 +75,7 @@ pub struct KeyPair { impl KeyPair { #[cfg(feature = "rand")] pub fn new(rng: &mut R) -> Self { - let index = rng.gen(); + let index = rng.r#gen(); let ed25519_signing_key = ed25519_dalek::SigningKey::generate(rng); KeyPair { @@ -504,10 +504,12 @@ mod tests { jwt_simple::algorithms::Edwards25519KeyPair::from_bytes(&jwt_keys.to_bytes()).unwrap(); let compact_ed25519 = jwt_keys_inner.as_ref(); - assert!(compact_ed25519 - .sk - .validate_public_key(&compact_ed25519.pk) - .is_ok()); + assert!( + compact_ed25519 + .sk + .validate_public_key(&compact_ed25519.pk) + .is_ok() + ); let dummy_message = "hello world"; let sig1 = keys.private_key.sign(dummy_message).to_bytes(); diff --git a/common/crypto/src/asymmetric/x25519/mod.rs b/common/crypto/src/asymmetric/x25519/mod.rs index 3f41319a97..c01e437ef4 100644 --- a/common/crypto/src/asymmetric/x25519/mod.rs +++ b/common/crypto/src/asymmetric/x25519/mod.rs @@ -168,6 +168,10 @@ impl PublicKey { pub fn to_base64(&self) -> String { base64::engine::general_purpose::STANDARD.encode(self.as_bytes()) } + + pub fn inner(&self) -> x25519_dalek::PublicKey { + self.0 + } } impl FromStr for PublicKey { diff --git a/common/crypto/src/hkdf.rs b/common/crypto/src/hkdf.rs index d12fadfac5..c343002430 100644 --- a/common/crypto/src/hkdf.rs +++ b/common/crypto/src/hkdf.rs @@ -2,11 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 use hkdf::{ - hmac::{ - digest::{crypto_common::BlockSizeUser, Digest}, - SimpleHmac, - }, Hkdf, + hmac::{ + SimpleHmac, + digest::{Digest, crypto_common::BlockSizeUser}, + }, }; use sha2::{Sha256, Sha512}; diff --git a/common/crypto/src/hmac.rs b/common/crypto/src/hmac.rs index f878df238c..49a131a0f6 100644 --- a/common/crypto/src/hmac.rs +++ b/common/crypto/src/hmac.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use hmac::{ - digest::{crypto_common::BlockSizeUser, CtOutput, Digest, Output}, Mac, SimpleHmac, + digest::{CtOutput, Digest, Output, crypto_common::BlockSizeUser}, }; pub use hmac; diff --git a/common/crypto/src/shared_key.rs b/common/crypto/src/shared_key.rs index 19f6442545..dbd03adb17 100644 --- a/common/crypto/src/shared_key.rs +++ b/common/crypto/src/shared_key.rs @@ -4,8 +4,8 @@ use crate::asymmetric::x25519; use crate::hkdf; use cipher::{Key, KeyIvInit, StreamCipher}; -use digest::crypto_common::BlockSizeUser; use digest::Digest; +use digest::crypto_common::BlockSizeUser; #[cfg(feature = "rand")] use rand::{CryptoRng, RngCore}; diff --git a/common/ecash-signer-check/src/client_check.rs b/common/ecash-signer-check/src/client_check.rs index aff2db6725..4d0026384c 100644 --- a/common/ecash-signer-check/src/client_check.rs +++ b/common/ecash-signer-check/src/client_check.rs @@ -56,7 +56,10 @@ impl ClientUnderTest { true } Ok(Err(err)) => { - warn!("{}: failed to retrieve build information: {err}. the signer is most likely down", self.api_client.current_url()); + warn!( + "{}: failed to retrieve build information: {err}. the signer is most likely down", + self.api_client.current_url() + ); false } Err(_timeout) => { diff --git a/common/ecash-signer-check/src/lib.rs b/common/ecash-signer-check/src/lib.rs index c7ddb07113..47e6d68875 100644 --- a/common/ecash-signer-check/src/lib.rs +++ b/common/ecash-signer-check/src/lib.rs @@ -4,8 +4,8 @@ use crate::client_check::check_client; use futures::stream::{FuturesUnordered, StreamExt}; use nym_network_defaults::NymNetworkDetails; -use nym_validator_client::nyxd::contract_traits::{DkgQueryClient, PagedDkgQueryClient}; use nym_validator_client::QueryHttpRpcNyxdClient; +use nym_validator_client::nyxd::contract_traits::{DkgQueryClient, PagedDkgQueryClient}; use std::collections::HashMap; use url::Url; diff --git a/common/exit-policy/src/client.rs b/common/exit-policy/src/client.rs index c6dfbe3f3b..57b8d194f7 100644 --- a/common/exit-policy/src/client.rs +++ b/common/exit-policy/src/client.rs @@ -1,8 +1,8 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::policy::PolicyError; use crate::ExitPolicy; +use crate::policy::PolicyError; use reqwest::IntoUrl; pub async fn get_exit_policy(url: impl IntoUrl) -> Result { diff --git a/common/exit-policy/src/policy/address_policy.rs b/common/exit-policy/src/policy/address_policy.rs index 07a1595d93..921e76ca00 100644 --- a/common/exit-policy/src/policy/address_policy.rs +++ b/common/exit-policy/src/policy/address_policy.rs @@ -639,27 +639,41 @@ mod test { policy.push(AddressPolicyAction::Accept, "*:0".parse()?); let policy = policy; // drop mut - assert!(policy - .allows_sockaddr(&"[::6]:443".parse().unwrap()) - .unwrap()); - assert!(policy - .allows_sockaddr(&"127.0.0.1:443".parse().unwrap()) - .unwrap()); - assert!(policy - .allows_sockaddr(&"[::1]:80".parse().unwrap()) - .unwrap()); - assert!(!policy - .allows_sockaddr(&"[::2]:80".parse().unwrap()) - .unwrap()); - assert!(!policy - .allows_sockaddr(&"127.0.0.1:80".parse().unwrap()) - .unwrap()); - assert!(policy - .allows_sockaddr(&"127.0.0.1:66".parse().unwrap()) - .is_none()); - assert!(policy - .allows_sockaddr(&"127.0.0.1:0".parse().unwrap()) - .unwrap()); + assert!( + policy + .allows_sockaddr(&"[::6]:443".parse().unwrap()) + .unwrap() + ); + assert!( + policy + .allows_sockaddr(&"127.0.0.1:443".parse().unwrap()) + .unwrap() + ); + assert!( + policy + .allows_sockaddr(&"[::1]:80".parse().unwrap()) + .unwrap() + ); + assert!( + !policy + .allows_sockaddr(&"[::2]:80".parse().unwrap()) + .unwrap() + ); + assert!( + !policy + .allows_sockaddr(&"127.0.0.1:80".parse().unwrap()) + .unwrap() + ); + assert!( + policy + .allows_sockaddr(&"127.0.0.1:66".parse().unwrap()) + .is_none() + ); + assert!( + policy + .allows_sockaddr(&"127.0.0.1:0".parse().unwrap()) + .unwrap() + ); Ok(()) } diff --git a/common/exit-policy/src/policy/error.rs b/common/exit-policy/src/policy/error.rs index 5a39e096e5..622c35f4b6 100644 --- a/common/exit-policy/src/policy/error.rs +++ b/common/exit-policy/src/policy/error.rs @@ -54,7 +54,9 @@ pub enum PolicyError { InvalidPort { raw: String }, /// A port range had its starting-point higher than its ending point. - #[error("the provided port range ({start}-{end}) was invalid. either the start was 0 or it was greater than the end.")] + #[error( + "the provided port range ({start}-{end}) was invalid. either the start was 0 or it was greater than the end." + )] InvalidRange { start: u16, end: u16 }, #[error("could not parse '{raw}' into a valid policy address:port pattern")] diff --git a/common/gateway-stats-storage/src/lib.rs b/common/gateway-stats-storage/src/lib.rs index d29de3a1b0..7b04881b47 100644 --- a/common/gateway-stats-storage/src/lib.rs +++ b/common/gateway-stats-storage/src/lib.rs @@ -8,8 +8,8 @@ use nym_sphinx::DestinationAddressBytes; use nym_statistics_common::types::SessionType; use sessions::SessionManager; use sqlx::{ - sqlite::{SqliteAutoVacuum, SqliteSynchronous}, ConnectOptions, + sqlite::{SqliteAutoVacuum, SqliteSynchronous}, }; use std::path::Path; use time::Date; diff --git a/common/gateway-storage/src/lib.rs b/common/gateway-storage/src/lib.rs index e10fdc3c1e..0a3144ac13 100644 --- a/common/gateway-storage/src/lib.rs +++ b/common/gateway-storage/src/lib.rs @@ -13,8 +13,8 @@ use nym_gateway_requests::shared_key::SharedGatewayKey; use nym_sphinx::DestinationAddressBytes; use shared_keys::SharedKeysManager; use sqlx::{ - sqlite::{SqliteAutoVacuum, SqliteSynchronous}, ConnectOptions, + sqlite::{SqliteAutoVacuum, SqliteSynchronous}, }; use std::{path::Path, time::Duration}; use tickets::TicketStorageManager; diff --git a/common/gateway-storage/src/traits.rs b/common/gateway-storage/src/traits.rs index aa7e01e434..fcd113a293 100644 --- a/common/gateway-storage/src/traits.rs +++ b/common/gateway-storage/src/traits.rs @@ -8,12 +8,12 @@ use nym_sphinx::DestinationAddressBytes; use time::OffsetDateTime; use crate::{ + GatewayStorageError, clients::ClientType, models::{ Client, PersistedBandwidth, PersistedSharedKeys, RedemptionProposal, StoredMessage, VerifiedTicket, WireguardPeer, }, - GatewayStorageError, }; #[async_trait] @@ -169,7 +169,7 @@ pub trait BandwidthGatewayStorage: dyn_clone::DynClone { /// /// * `peer_public_key`: wireguard public key of the peer to be removed. async fn remove_wireguard_peer(&self, peer_public_key: &str) - -> Result<(), GatewayStorageError>; + -> Result<(), GatewayStorageError>; } #[cfg(feature = "mock")] diff --git a/common/http-api-client-macro/src/lib.rs b/common/http-api-client-macro/src/lib.rs index cd1c1dd179..357536cfab 100644 --- a/common/http-api-client-macro/src/lib.rs +++ b/common/http-api-client-macro/src/lib.rs @@ -60,15 +60,15 @@ //! - Positive priorities: Late configuration (e.g., 100 for overrides) use proc_macro::TokenStream; +use proc_macro_crate::{FoundCrate, crate_name}; use proc_macro2::{Span, TokenStream as TokenStream2}; -use proc_macro_crate::{crate_name, FoundCrate}; use quote::{format_ident, quote}; use syn::{ - braced, + Expr, Ident, LitInt, Result, Token, braced, parse::{Parse, ParseStream}, parse_macro_input, punctuated::Punctuated, - token, Expr, Ident, LitInt, Result, Token, + token, }; // ------------------ core crate path resolution ------------------ diff --git a/common/http-api-client/examples/test_timeout.rs b/common/http-api-client/examples/test_timeout.rs index fe3658e34b..c49e025589 100644 --- a/common/http-api-client/examples/test_timeout.rs +++ b/common/http-api-client/examples/test_timeout.rs @@ -1,5 +1,5 @@ use nym_http_api_client::registry; -use nym_http_api_client::{inventory, ReqwestClientBuilder}; +use nym_http_api_client::{ReqwestClientBuilder, inventory}; use nym_http_api_client_macro::client_defaults; use std::time::{Duration, Instant}; @@ -87,7 +87,9 @@ async fn main() { if e.is_timeout() { println!("✓ Request timed out after {:?}", elapsed); if elapsed < Duration::from_secs(290) { - println!(" Note: Timeout occurred faster than 300s, might be connection timeout not total timeout"); + println!( + " Note: Timeout occurred faster than 300s, might be connection timeout not total timeout" + ); } } else if e.is_connect() { println!("✓ Connection failed after {:?} (connect timeout)", elapsed); diff --git a/common/http-api-client/src/dns.rs b/common/http-api-client/src/dns.rs index 3c68afee1e..d3fa9dde35 100644 --- a/common/http-api-client/src/dns.rs +++ b/common/http-api-client/src/dns.rs @@ -35,10 +35,10 @@ use std::{ }; use hickory_resolver::{ + ResolveError, TokioResolver, config::{LookupIpStrategy, NameServerConfigGroup, ResolverConfig, ServerOrderingStrategy}, lookup_ip::{LookupIp, LookupIpIntoIter}, name_server::TokioConnectionProvider, - ResolveError, TokioResolver, }; use once_cell::sync::OnceCell; use reqwest::dns::{Addrs, Name, Resolve, Resolving}; diff --git a/common/http-api-client/src/fronted.rs b/common/http-api-client/src/fronted.rs index f41ce8f3cf..4b5a9d9eab 100644 --- a/common/http-api-client/src/fronted.rs +++ b/common/http-api-client/src/fronted.rs @@ -73,7 +73,9 @@ impl ClientBuilder { // Check if any of the supplied urls even support fronting if !self.urls.iter().any(|url| url.has_front()) { - warn!("fronting is enabled, but none of the supplied urls have configured fronting domains"); + warn!( + "fronting is enabled, but none of the supplied urls have configured fronting domains" + ); } self.front = Some(front); @@ -85,7 +87,7 @@ impl ClientBuilder { #[cfg(test)] mod tests { use super::*; - use crate::{ApiClientCore, Url, NO_PARAMS}; + use crate::{ApiClientCore, NO_PARAMS, Url}; #[tokio::test] async fn nym_api_works() { diff --git a/common/http-api-client/src/lib.rs b/common/http-api-client/src/lib.rs index 1e05f514fb..3ac1ef6ea9 100644 --- a/common/http-api-client/src/lib.rs +++ b/common/http-api-client/src/lib.rs @@ -147,8 +147,8 @@ pub mod registry; use crate::path::RequestPath; use async_trait::async_trait; use bytes::Bytes; -use http::header::{ACCEPT, CONTENT_TYPE}; use http::HeaderMap; +use http::header::{ACCEPT, CONTENT_TYPE}; use itertools::Itertools; use mime::Mime; use reqwest::header::HeaderValue; @@ -267,10 +267,10 @@ impl Display for ReqwestErrorWrapper { if self.0.is_timeout() { write!(f, "timed out: ")?; } - if self.0.is_redirect() { - if let Some(final_stop) = self.0.url() { - write!(f, "redirect loop at {final_stop}: ")?; - } + if self.0.is_redirect() + && let Some(final_stop) = self.0.url() + { + write!(f, "redirect loop at {final_stop}: ")?; } self.0.fmt(f)?; @@ -358,7 +358,9 @@ pub enum HttpClientError { // #[error("request failed with error message: {0}")] // GenericRequestFailure(String), // - #[error("the request for {url} failed with status '{status}'. no additional error message provided. response headers: {headers:?}")] + #[error( + "the request for {url} failed with status '{status}'. no additional error message provided. response headers: {headers:?}" + )] RequestFailure { url: reqwest::Url, status: StatusCode, @@ -374,7 +376,9 @@ pub enum HttpClientError { headers: Box, }, - #[error("failed to resolve request for {url}. status: '{status}'. response headers: {headers:?}. additional error message: {error}")] + #[error( + "failed to resolve request for {url}. status: '{status}'. response headers: {headers:?}. additional error message: {error}" + )] EndpointFailure { url: reqwest::Url, status: StatusCode, @@ -571,7 +575,9 @@ impl ClientBuilder { // a naive check: if the provided URL does not start with http(s), add that scheme if !str_url.starts_with("http") { let alt = format!("http://{str_url}"); - warn!("the provided url ('{str_url}') does not contain scheme information. Changing it to '{alt}' ..."); + warn!( + "the provided url ('{str_url}') does not contain scheme information. Changing it to '{alt}' ..." + ); // TODO: or should we maybe default to https? Self::new(alt) } else { @@ -864,17 +870,17 @@ impl Client { /// If multiple base urls are available rotate to next (e.g. when the current one resulted in an error) fn update_host(&self) { #[cfg(feature = "tunneling")] - if let Some(ref front) = self.front { - if front.is_enabled() { - // if we are using fronting, try updating to the next front - let url = self.current_url(); + if let Some(ref front) = self.front + && front.is_enabled() + { + // if we are using fronting, try updating to the next front + let url = self.current_url(); - // try to update the current host to use a next front, if one is available, otherwise - // we move on and try the next base url (if one is available) - if url.has_front() && !url.update() { - // we swapped to the next front for the current host - return; - } + // try to update the current host to use a next front, if one is available, otherwise + // we move on and try the next base url (if one is available) + if url.has_front() && !url.update() { + // we swapped to the next front for the current host + return; } } @@ -884,16 +890,16 @@ impl Client { // if fronting is enabled we want to update to a host that has fronts configured #[cfg(feature = "tunneling")] - if let Some(ref front) = self.front { - if front.is_enabled() { - while next != orig { - if self.base_urls[next].has_front() { - // we have a front for the next host, so we can use it - break; - } - - next = (next + 1) % self.base_urls.len(); + if let Some(ref front) = self.front + && front.is_enabled() + { + while next != orig { + if self.base_urls[next].has_front() { + // we have a front for the next host, so we can use it + break; } + + next = (next + 1) % self.base_urls.len(); } } @@ -918,34 +924,38 @@ impl Client { r.url_mut().set_host(url.host_str()).unwrap(); #[cfg(feature = "tunneling")] - if let Some(ref front) = self.front { - if front.is_enabled() { - if let Some(front_host) = url.front_str() { - if let Some(actual_host) = url.host_str() { - tracing::debug!( - "Domain fronting enabled: routing via CDN {} to actual host {}", - front_host, - actual_host - ); + if let Some(ref front) = self.front + && front.is_enabled() + { + if let Some(front_host) = url.front_str() { + if let Some(actual_host) = url.host_str() { + tracing::debug!( + "Domain fronting enabled: routing via CDN {} to actual host {}", + front_host, + actual_host + ); - // this should never fail as we are transplanting the host from one url to another - r.url_mut().set_host(Some(front_host)).unwrap(); + // this should never fail as we are transplanting the host from one url to another + r.url_mut().set_host(Some(front_host)).unwrap(); - let actual_host_header: HeaderValue = - actual_host.parse().unwrap_or(HeaderValue::from_static("")); - // If the map did have this key present, the new value is associated with the key - // and all previous values are removed. (reqwest HeaderMap docs) - _ = r - .headers_mut() - .insert(reqwest::header::HOST, actual_host_header); + let actual_host_header: HeaderValue = + actual_host.parse().unwrap_or(HeaderValue::from_static("")); + // If the map did have this key present, the new value is associated with the key + // and all previous values are removed. (reqwest HeaderMap docs) + _ = r + .headers_mut() + .insert(reqwest::header::HOST, actual_host_header); - return (url.as_str(), url.front_str()); - } else { - warn!("Domain fronting is enabled, but no host_url is defined! Domain fronting WILL NOT WORK") - } + return (url.as_str(), url.front_str()); } else { - warn!("Domain fronting is enabled, but no front_url is defined! Domain fronting WILL NOT WORK") + warn!( + "Domain fronting is enabled, but no host_url is defined! Domain fronting WILL NOT WORK" + ) } + } else { + warn!( + "Domain fronting is enabled, but no front_url is defined! Domain fronting WILL NOT WORK" + ) } } (url.as_str(), None) @@ -1430,14 +1440,12 @@ where tracing::trace!("status: {status} (success: {})", status.is_success()); tracing::trace!("headers: {headers:?}"); - if !allow_empty { - if let Some(0) = res.content_length() { - return Err(HttpClientError::EmptyResponse { - url, - status, - headers: Box::new(headers), - }); - } + if !allow_empty && let Some(0) = res.content_length() { + return Err(HttpClientError::EmptyResponse { + url, + status, + headers: Box::new(headers), + }); } if res.status().is_success() { diff --git a/common/http-api-client/src/url.rs b/common/http-api-client/src/url.rs index b4a872e109..d964a6a3f4 100644 --- a/common/http-api-client/src/url.rs +++ b/common/http-api-client/src/url.rs @@ -4,12 +4,12 @@ //! functionality for handling front domains, which are used for reverse proxying. use std::fmt::Display; -use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; use itertools::Itertools; -use url::form_urlencoded; pub use url::ParseError; +use url::form_urlencoded; /// A trait to try to convert some type into a `Url`. pub trait IntoUrl { @@ -215,13 +215,13 @@ impl Url { /// Returns true if updating the front wraps back to the first front, or if no fronts are set pub fn update(&self) -> bool { - if let Some(fronts) = &self.fronts { - if fronts.len() > 1 { - let current = self.current_front.load(Ordering::Relaxed); - let next = (current + 1) % fronts.len(); - self.current_front.store(next, Ordering::Relaxed); - return next == 0; - } + if let Some(fronts) = &self.fronts + && fronts.len() > 1 + { + let current = self.current_front.load(Ordering::Relaxed); + let next = (current + 1) % fronts.len(); + self.current_front.store(next, Ordering::Relaxed); + return next == 0; } true } diff --git a/common/http-api-common/src/middleware/bearer_auth.rs b/common/http-api-common/src/middleware/bearer_auth.rs index bb334ab944..803c9ce031 100644 --- a/common/http-api-common/src/middleware/bearer_auth.rs +++ b/common/http-api-common/src/middleware/bearer_auth.rs @@ -1,7 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use axum::http::{header, HeaderValue, StatusCode}; +use axum::http::{HeaderValue, StatusCode, header}; use axum::response::IntoResponse; use axum::{extract::Request, response::Response}; use futures::future::BoxFuture; diff --git a/common/http-api-common/src/middleware/logging.rs b/common/http-api-common/src/middleware/logging.rs index 84c33c8a7d..dfa03d5b50 100644 --- a/common/http-api-common/src/middleware/logging.rs +++ b/common/http-api-common/src/middleware/logging.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use axum::extract::Request; -use axum::http::header::{HOST, USER_AGENT}; use axum::http::HeaderValue; +use axum::http::header::{HOST, USER_AGENT}; use axum::middleware::Next; use axum::response::IntoResponse; use axum_client_ip::InsecureClientIp; diff --git a/common/http-api-common/src/response/bincode.rs b/common/http-api-common/src/response/bincode.rs index cea2ae10d3..f26349fc77 100644 --- a/common/http-api-common/src/response/bincode.rs +++ b/common/http-api-common/src/response/bincode.rs @@ -1,9 +1,9 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::response::{error_response, ResponseWrapper}; +use crate::response::{ResponseWrapper, error_response}; use axum::http::header::IntoHeaderName; -use axum::http::{header, HeaderValue}; +use axum::http::{HeaderValue, header}; use axum::response::{IntoResponse, Response}; use bytes::{BufMut, BytesMut}; use serde::Serialize; diff --git a/common/http-api-common/src/response/json.rs b/common/http-api-common/src/response/json.rs index a1b46e7d50..088eeeebdb 100644 --- a/common/http-api-common/src/response/json.rs +++ b/common/http-api-common/src/response/json.rs @@ -1,9 +1,9 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::response::{error_response, ResponseWrapper}; +use crate::response::{ResponseWrapper, error_response}; use axum::http::header::IntoHeaderName; -use axum::http::{header, HeaderValue}; +use axum::http::{HeaderValue, header}; use axum::response::{IntoResponse, Response}; use bytes::{BufMut, BytesMut}; use serde::Serialize; diff --git a/common/http-api-common/src/response/mod.rs b/common/http-api-common/src/response/mod.rs index 2753aaf8f0..eb0552ed37 100644 --- a/common/http-api-common/src/response/mod.rs +++ b/common/http-api-common/src/response/mod.rs @@ -2,13 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 use axum::http::header::IntoHeaderName; -use axum::http::{header, HeaderMap, HeaderValue, StatusCode}; +use axum::http::{HeaderMap, HeaderValue, StatusCode, header}; use axum::response::{IntoResponse, Response}; use serde::{Deserialize, Serialize}; use std::time::Duration; +use time::OffsetDateTime; use time::format_description::BorrowedFormatItem; use time::macros::{format_description, offset}; -use time::OffsetDateTime; pub mod bincode; pub mod json; diff --git a/common/http-api-common/src/response/yaml.rs b/common/http-api-common/src/response/yaml.rs index d9bc163c1a..008a9acbdf 100644 --- a/common/http-api-common/src/response/yaml.rs +++ b/common/http-api-common/src/response/yaml.rs @@ -1,9 +1,9 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::response::{error_response, ResponseWrapper}; +use crate::response::{ResponseWrapper, error_response}; use axum::http::header::IntoHeaderName; -use axum::http::{header, HeaderValue}; +use axum::http::{HeaderValue, header}; use axum::response::{IntoResponse, Response}; use bytes::{BufMut, BytesMut}; use serde::Serialize; diff --git a/common/inclusion-probability/src/lib.rs b/common/inclusion-probability/src/lib.rs index 8894dc4764..76bb0bd017 100644 --- a/common/inclusion-probability/src/lib.rs +++ b/common/inclusion-probability/src/lib.rs @@ -218,7 +218,7 @@ fn max_diff(v1: &[f64], v2: &[f64]) -> Result { #[cfg(test)] mod tests { - use rand::{rngs::StdRng, SeedableRng}; + use rand::{SeedableRng, rngs::StdRng}; use super::*; diff --git a/common/ip-packet-requests/src/v6/request.rs b/common/ip-packet-requests/src/v6/request.rs index 67f1d09b0f..00b8eb1a65 100644 --- a/common/ip-packet-requests/src/v6/request.rs +++ b/common/ip-packet-requests/src/v6/request.rs @@ -1,7 +1,7 @@ use nym_sphinx::addressing::clients::Recipient; use serde::{Deserialize, Serialize}; -use crate::{make_bincode_serializer, IpPair}; +use crate::{IpPair, make_bincode_serializer}; use super::VERSION; diff --git a/common/ip-packet-requests/src/v6/response.rs b/common/ip-packet-requests/src/v6/response.rs index 327f690793..b7ceec03a0 100644 --- a/common/ip-packet-requests/src/v6/response.rs +++ b/common/ip-packet-requests/src/v6/response.rs @@ -1,7 +1,7 @@ use nym_sphinx::addressing::clients::Recipient; use serde::{Deserialize, Serialize}; -use crate::{make_bincode_serializer, IpPair}; +use crate::{IpPair, make_bincode_serializer}; use super::VERSION; @@ -386,9 +386,7 @@ pub struct InfoResponse { pub enum InfoResponseReply { #[error("{msg}")] Generic { msg: String }, - #[error( - "version mismatch: response is v{request_version} and response is v{response_version}" - )] + #[error("version mismatch: response is v{request_version} and response is v{response_version}")] VersionMismatch { request_version: u8, response_version: u8, diff --git a/common/ip-packet-requests/src/v7/request.rs b/common/ip-packet-requests/src/v7/request.rs index e82a85ae53..20817d0bb4 100644 --- a/common/ip-packet-requests/src/v7/request.rs +++ b/common/ip-packet-requests/src/v7/request.rs @@ -6,8 +6,8 @@ use serde::{Deserialize, Serialize}; use time::OffsetDateTime; use crate::{ - sign::{SignatureError, SignedRequest}, IpPair, + sign::{SignatureError, SignedRequest}, }; use super::VERSION; diff --git a/common/ip-packet-requests/src/v7/response.rs b/common/ip-packet-requests/src/v7/response.rs index d0eb42bbed..57e831ab4a 100644 --- a/common/ip-packet-requests/src/v7/response.rs +++ b/common/ip-packet-requests/src/v7/response.rs @@ -1,7 +1,7 @@ use nym_sphinx::addressing::clients::Recipient; use serde::{Deserialize, Serialize}; -use crate::{make_bincode_serializer, IpPair}; +use crate::{IpPair, make_bincode_serializer}; use super::VERSION; @@ -395,9 +395,7 @@ pub struct InfoResponse { pub enum InfoResponseReply { #[error("{msg}")] Generic { msg: String }, - #[error( - "version mismatch: response is v{request_version} and response is v{response_version}" - )] + #[error("version mismatch: response is v{request_version} and response is v{response_version}")] VersionMismatch { request_version: u8, response_version: u8, diff --git a/common/ip-packet-requests/src/v8/response.rs b/common/ip-packet-requests/src/v8/response.rs index 946a8621be..12256252bd 100644 --- a/common/ip-packet-requests/src/v8/response.rs +++ b/common/ip-packet-requests/src/v8/response.rs @@ -1,7 +1,7 @@ use nym_bin_common::build_information::BinaryBuildInformationOwned; use serde::{Deserialize, Serialize}; -use crate::{make_bincode_serializer, IpPair}; +use crate::{IpPair, make_bincode_serializer}; use super::VERSION; @@ -142,9 +142,7 @@ pub enum InfoResponseReply { #[error("{msg}")] Generic { msg: String }, - #[error( - "version mismatch: response is v{request_version} and response is v{response_version}" - )] + #[error("version mismatch: response is v{request_version} and response is v{response_version}")] VersionMismatch { request_version: u8, response_version: u8, diff --git a/common/network-defaults/src/env_setup.rs b/common/network-defaults/src/env_setup.rs index fb67056387..66a8243d00 100644 --- a/common/network-defaults/src/env_setup.rs +++ b/common/network-defaults/src/env_setup.rs @@ -6,14 +6,16 @@ use crate::var_names::{DEPRECATED_API_VALIDATOR, DEPRECATED_NYMD_VALIDATOR, NYM_ use std::path::Path; fn fix_deprecated_environmental_variables() { - // if we're using the outdated environmental variables, set the updated ones to preserve compatibility - if let Ok(nyxd) = std::env::var(DEPRECATED_NYMD_VALIDATOR) { - if std::env::var(NYXD).is_err() { + unsafe { + // if we're using the outdated environmental variables, set the updated ones to preserve compatibility + if let Ok(nyxd) = std::env::var(DEPRECATED_NYMD_VALIDATOR) + && std::env::var(NYXD).is_err() + { std::env::set_var(NYXD, nyxd) } - } - if let Ok(nym_apis) = std::env::var(DEPRECATED_API_VALIDATOR) { - if std::env::var(NYM_API).is_err() { + if let Ok(nym_apis) = std::env::var(DEPRECATED_API_VALIDATOR) + && std::env::var(NYM_API).is_err() + { std::env::set_var(NYM_API, nym_apis) } } diff --git a/common/network-defaults/src/mainnet.rs b/common/network-defaults/src/mainnet.rs index af64bd4d63..8bace8f485 100644 --- a/common/network-defaults/src/mainnet.rs +++ b/common/network-defaults/src/mainnet.rs @@ -84,8 +84,10 @@ const DEFAULT_SUFFIX: &str = "_MAINNET_DEFAULT"; #[cfg(all(feature = "env", feature = "network"))] fn set_var_to_default(var: &str, value: &str) { - std::env::set_var(var, value); - std::env::set_var(format!("{var}{DEFAULT_SUFFIX}"), "1") + unsafe { + std::env::set_var(var, value); + std::env::set_var(format!("{var}{DEFAULT_SUFFIX}"), "1") + } } #[cfg(all(feature = "env", feature = "network"))] diff --git a/common/network-defaults/src/network.rs b/common/network-defaults/src/network.rs index 3fdf03671e..f870c0b3d0 100644 --- a/common/network-defaults/src/network.rs +++ b/common/network-defaults/src/network.rs @@ -1,7 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::{mainnet, GAS_PRICE_AMOUNT}; +use crate::{GAS_PRICE_AMOUNT, mainnet}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::ops::Not; @@ -107,7 +107,7 @@ impl NymNetworkDetails { #[cfg(feature = "env")] pub fn new_from_env() -> Self { use crate::var_names; - use std::env::{var, VarError}; + use std::env::{VarError, var}; use std::ffi::OsStr; fn get_optional_env>(env: K) -> Option { @@ -208,35 +208,38 @@ impl NymNetworkDetails { fn set_optional_var(var_name: &str, value: Option) { if let Some(value) = value { - set_var(var_name, value); + unsafe {set_var(var_name, value)} } } + unsafe { + set_var(var_names::NETWORK_NAME, self.network_name); + set_var(var_names::BECH32_PREFIX, self.chain_details.bech32_account_prefix); - set_var(var_names::NETWORK_NAME, self.network_name); - set_var(var_names::BECH32_PREFIX, self.chain_details.bech32_account_prefix); + set_var(var_names::MIX_DENOM, self.chain_details.mix_denom.base); + set_var(var_names::MIX_DENOM_DISPLAY, self.chain_details.mix_denom.display); - set_var(var_names::MIX_DENOM, self.chain_details.mix_denom.base); - set_var(var_names::MIX_DENOM_DISPLAY, self.chain_details.mix_denom.display); + set_var(var_names::STAKE_DENOM, self.chain_details.stake_denom.base); + set_var(var_names::STAKE_DENOM_DISPLAY, self.chain_details.stake_denom.display); - set_var(var_names::STAKE_DENOM, self.chain_details.stake_denom.base); - set_var(var_names::STAKE_DENOM_DISPLAY, self.chain_details.stake_denom.display); + set_var(var_names::DENOMS_EXPONENT, self.chain_details.mix_denom.display_exponent.to_string()); - set_var(var_names::DENOMS_EXPONENT, self.chain_details.mix_denom.display_exponent.to_string()); + if let Some(e) = self.endpoints.first() { + set_var(var_names::NYXD, e.nyxd_url.clone()); + set_optional_var(var_names::NYM_API, e.api_url.clone()); + set_optional_var(var_names::NYXD_WEBSOCKET, e.websocket_url.clone()); + } - if let Some(e) = self.endpoints.first() { - set_var(var_names::NYXD, e.nyxd_url.clone()); - set_optional_var(var_names::NYM_API, e.api_url.clone()); - set_optional_var(var_names::NYXD_WEBSOCKET, e.websocket_url.clone()); + set_optional_var(var_names::MIXNET_CONTRACT_ADDRESS, self.contracts.mixnet_contract_address); + set_optional_var(var_names::VESTING_CONTRACT_ADDRESS, self.contracts.vesting_contract_address); + set_optional_var(var_names::ECASH_CONTRACT_ADDRESS, self.contracts.ecash_contract_address); + set_optional_var(var_names::GROUP_CONTRACT_ADDRESS, self.contracts.group_contract_address); + set_optional_var(var_names::MULTISIG_CONTRACT_ADDRESS, self.contracts.multisig_contract_address); + set_optional_var(var_names::COCONUT_DKG_CONTRACT_ADDRESS, self.contracts.coconut_dkg_contract_address); + + set_optional_var(var_names::NYM_VPN_API, self.nym_vpn_api_url); } - set_optional_var(var_names::MIXNET_CONTRACT_ADDRESS, self.contracts.mixnet_contract_address); - set_optional_var(var_names::VESTING_CONTRACT_ADDRESS, self.contracts.vesting_contract_address); - set_optional_var(var_names::ECASH_CONTRACT_ADDRESS, self.contracts.ecash_contract_address); - set_optional_var(var_names::GROUP_CONTRACT_ADDRESS, self.contracts.group_contract_address); - set_optional_var(var_names::MULTISIG_CONTRACT_ADDRESS, self.contracts.multisig_contract_address); - set_optional_var(var_names::COCONUT_DKG_CONTRACT_ADDRESS, self.contracts.coconut_dkg_contract_address); - set_optional_var(var_names::NYM_VPN_API, self.nym_vpn_api_url); } pub fn default_gas_price_amount(&self) -> f64 { diff --git a/common/nym-common/Cargo.toml b/common/nym-common/Cargo.toml new file mode 100644 index 0000000000..5bf119c8ee --- /dev/null +++ b/common/nym-common/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "nym-common" +version = "1.18.0" +authors.workspace = true +repository.workspace = true +license.workspace = true +edition.workspace = true + +[lints] +workspace = true + +[dependencies] +tracing.workspace = true +tracing-test.workspace = true diff --git a/common/nym-common/src/error.rs b/common/nym-common/src/error.rs new file mode 100644 index 0000000000..062ca14813 --- /dev/null +++ b/common/nym-common/src/error.rs @@ -0,0 +1,109 @@ +// Copyright 2016-2024 Mullvad VPN AB. All Rights Reserved. +// Copyright 2024 Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use std::{error::Error, fmt, fmt::Write}; +use tracing::error; + +/// Used to generate string representations of error chains. +pub trait ErrorExt { + /// Creates a string representation of the entire error chain. + fn display_chain(&self) -> String; + + /// Like [Self::display_chain] but with an extra message at the start of the chain. + fn display_chain_with_msg>(&self, msg: S) -> String; +} + +impl ErrorExt for E { + fn display_chain(&self) -> String { + let mut s = format!("Error: {self}"); + let mut source = self.source(); + while let Some(error) = source { + if let Err(err) = write!(&mut s, "\nCaused by: {error}") { + error!("error formatting failure: {err}"); + } + source = error.source(); + } + s + } + + fn display_chain_with_msg>(&self, msg: S) -> String { + let mut s = format!("Error: {}\nCaused by: {}", msg.as_ref(), self); + let mut source = self.source(); + while let Some(error) = source { + if let Err(err) = write!(&mut s, "\nCaused by: {error}") { + error!("error formatting failure: {err}"); + } + source = error.source(); + } + s + } +} + +#[macro_export] +macro_rules! trace_err_chain { + ($err:expr) => { + tracing::error!("{}", $crate::ErrorExt::display_chain(&$err)); + }; + ($err:expr, $($args:tt)*) => { + tracing::error!("{}", $crate::ErrorExt::display_chain_with_msg(&$err, ::std::format!($($args)*))); + }; +} + +#[cfg(test)] +mod tests { + use tracing_test::traced_test; + + use std::{io, path::PathBuf}; + + #[test] + #[traced_test] + fn test_trace_err_chain() { + trace_err_chain!(io::Error::other("file not found")); + assert!(logs_contain("Error: file not found")); + } + + #[test] + #[traced_test] + fn test_trace_err_chain_with_msg() { + trace_err_chain!(io::Error::other("file not found"), "failed to open file"); + assert!(logs_contain("Error: failed to open file")); + // todo: fix once it supports multiline messages + // https://github.com/dbrgn/tracing-test/issues/48 + // assert!(logs_contain("Caused by: file not found")); + } + + #[test] + #[traced_test] + fn test_trace_err_chain_with_msgfmt() { + trace_err_chain!( + io::Error::other("file not found"), + "failed to open file: {}", + PathBuf::from("test.txt").display() + ); + assert!(logs_contain("Error: failed to open file: test.txt")); + // todo: fix once it supports multiline messages + // https://github.com/dbrgn/tracing-test/issues/48 + // assert!(logs_contain("Caused by: file not found")); + } +} +#[derive(Debug)] +pub struct BoxedError(Box); + +impl fmt::Display for BoxedError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl Error for BoxedError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + self.0.source() + } +} + +impl BoxedError { + pub fn new(error: impl Error + 'static + Send) -> Self { + BoxedError(Box::new(error)) + } +} diff --git a/common/nym-common/src/flood.rs b/common/nym-common/src/flood.rs new file mode 100644 index 0000000000..e2d9bda278 --- /dev/null +++ b/common/nym-common/src/flood.rs @@ -0,0 +1,55 @@ +// Copyright 2016-2024 Mullvad VPN AB. All Rights Reserved. +// Copyright 2024 Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use std::time::{Duration, Instant}; + +const CALLS_INTERVAL: Duration = Duration::from_secs(5); +const CALLS_THRESHOLD: usize = 1000; + +/// Log when a line is hit unusually frequently, that is, over `CALLS_THRESHOLD` times within a +/// period of `CALLS_INTERVAL`. +#[macro_export] +macro_rules! detect_flood { + () => {{ + static FLOOD: ::std::sync::Mutex<$crate::flood::DetectFlood> = + ::std::sync::Mutex::new($crate::flood::DetectFlood::new()); + if FLOOD.lock().unwrap().bump() { + ::tracing::warn!("Flood: {}, line {}, col {}", file!(), line!(), column!()); + } + }}; +} + +/// Used to detect code that is running too frequently +pub struct DetectFlood { + last_clear: Option, + counter: usize, +} + +impl Default for DetectFlood { + fn default() -> Self { + DetectFlood::new() + } +} + +impl DetectFlood { + pub const fn new() -> Self { + DetectFlood { + last_clear: None, + counter: 0, + } + } + + pub fn bump(&mut self) -> bool { + let now = Instant::now(); + let last_clear = self.last_clear.get_or_insert(now); + if now.saturating_duration_since(*last_clear) >= CALLS_INTERVAL { + self.last_clear = Some(now); + self.counter = 0; + false + } else { + self.counter = self.counter.saturating_add(1); + self.counter == CALLS_THRESHOLD + } + } +} diff --git a/common/nym-common/src/lib.rs b/common/nym-common/src/lib.rs new file mode 100644 index 0000000000..b59be68666 --- /dev/null +++ b/common/nym-common/src/lib.rs @@ -0,0 +1,8 @@ +// Copyright 2016-2024 Mullvad VPN AB. All Rights Reserved. +// Copyright 2024 Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +mod error; +pub mod flood; + +pub use error::*; diff --git a/common/nym-connection-monitor/Cargo.toml b/common/nym-connection-monitor/Cargo.toml new file mode 100644 index 0000000000..e19991d3e4 --- /dev/null +++ b/common/nym-connection-monitor/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "nym-connection-monitor" +version = "1.18.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true + +[lints] +workspace = true + +[dependencies] +bincode.workspace = true +bytes.workspace = true +futures.workspace = true +nym-config = { path = "../config" } +nym-common = { path = "../nym-common" } +nym-ip-packet-requests = { path = "../ip-packet-requests" } +nym-sdk = { path = "../../sdk/rust/nym-sdk" } +pnet_packet.workspace = true +thiserror.workspace = true +tokio.workspace = true +tokio-util.workspace = true +tracing.workspace = true diff --git a/common/nym-connection-monitor/src/error.rs b/common/nym-connection-monitor/src/error.rs new file mode 100644 index 0000000000..463499a95d --- /dev/null +++ b/common/nym-connection-monitor/src/error.rs @@ -0,0 +1,31 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("nym sdk")] + NymSdkError(#[source] Box), + + #[error( + "timeout waiting for mixnet self ping, the entry gateway is not routing our mixnet traffic" + )] + TimeoutWaitingForMixnetSelfPing, + + #[error("failed to serialize message")] + FailedToSerializeMessage { + #[from] + source: bincode::Error, + }, + + #[error("failed to create icmp echo request packet")] + IcmpEchoRequestPacketCreationFailure, + + #[error("failed to create icmp packet")] + IcmpPacketCreationFailure, + + #[error("failed to create ipv4 packet")] + Ipv4PacketCreationFailure, +} + +// Result type based on our error type +pub type Result = std::result::Result; diff --git a/common/nym-connection-monitor/src/icmp_beacon.rs b/common/nym-connection-monitor/src/icmp_beacon.rs new file mode 100644 index 0000000000..07dd8df059 --- /dev/null +++ b/common/nym-connection-monitor/src/icmp_beacon.rs @@ -0,0 +1,251 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use std::{ + net::{Ipv4Addr, Ipv6Addr}, + time::Duration, +}; + +use bytes::Bytes; +use nym_common::trace_err_chain; +use nym_config::defaults::mixnet_vpn::{NYM_TUN_DEVICE_ADDRESS_V4, NYM_TUN_DEVICE_ADDRESS_V6}; +use nym_ip_packet_requests::{IpPair, codec::MultiIpPacketCodec}; +use nym_sdk::mixnet::{ + InputMessage, MixnetClientSender, MixnetMessageSender, Recipient, TransmissionLane, +}; +use pnet_packet::Packet; +use tokio::task::JoinHandle; +use tokio_util::sync::CancellationToken; +use tracing::{debug, trace}; + +use crate::{ + Error, + error::Result, + nym_ip_packet_requests_current::request::IpPacketRequest, + packet_helpers::{ + create_icmpv4_echo_request, create_icmpv6_echo_request, is_icmp_echo_reply, + is_icmp_v6_echo_reply, wrap_icmp_in_ipv4, wrap_icmp_in_ipv6, + }, +}; + +const ICMP_BEACON_PING_INTERVAL: Duration = Duration::from_millis(1000); + +// This can be anything really, we just want to check if the exit IPR can reach the internet +// TODO: have a pool of IPs to ping +const ICMP_IPR_TUN_EXTERNAL_PING_V4: Ipv4Addr = Ipv4Addr::new(8, 8, 8, 8); +const ICMP_IPR_TUN_EXTERNAL_PING_V6: Ipv6Addr = + Ipv6Addr::new(0x2001, 0x4860, 0x4860, 0, 0, 0, 0, 0x8888); + +struct IcmpConnectionBeacon { + mixnet_client_sender: MixnetClientSender, + our_ips: IpPair, + ipr_address: Recipient, + sequence_number: u16, + icmp_identifier: u16, +} + +impl IcmpConnectionBeacon { + fn new( + mixnet_client_sender: MixnetClientSender, + our_ips: IpPair, + ipr_address: Recipient, + icmp_identifier: u16, + ) -> Self { + IcmpConnectionBeacon { + mixnet_client_sender, + our_ips, + ipr_address, + sequence_number: 0, + icmp_identifier, + } + } + + fn get_next_sequence_number(&mut self) -> u16 { + let sequence_number = self.sequence_number; + self.sequence_number = self.sequence_number.wrapping_add(1); + sequence_number + } + + async fn send_icmp_v4_ping(&mut self, destination: Ipv4Addr) -> Result<()> { + // Create ICMP/IPv4 echo request packet + let sequence_number = self.get_next_sequence_number(); + let identifier = self.icmp_identifier; + let icmp_echo_request = create_icmpv4_echo_request(sequence_number, identifier)?; + let ipv4_packet = wrap_icmp_in_ipv4(icmp_echo_request, self.our_ips.ipv4, destination)?; + + // Wrap the IPv4 packet in a MultiIpPacket + let bundled_packet = + MultiIpPacketCodec::bundle_one_packet(ipv4_packet.packet().to_vec().into()); + + // Wrap into a mixnet input message addressed to the IPR + let mixnet_message = wrap_in_mixnet_message(self.ipr_address, bundled_packet)?; + + // Send across the mixnet + self.mixnet_client_sender + .send(mixnet_message) + .await + .map_err(|err| Error::NymSdkError(Box::new(err))) + } + + async fn send_icmp_v6_ping(&mut self, destination: Ipv6Addr) -> Result<()> { + // Create ICMP/IPv6 echo request packet + let sequence_number = self.get_next_sequence_number(); + let identifier = self.icmp_identifier; + let icmp_echo_request = create_icmpv6_echo_request( + sequence_number, + identifier, + &self.our_ips.ipv6, + &destination, + )?; + let ipv6_packet = wrap_icmp_in_ipv6(icmp_echo_request, self.our_ips.ipv6, destination)?; + + // Wrap the IPv6 packet in a MultiIpPacket + let bundled_packet = + MultiIpPacketCodec::bundle_one_packet(ipv6_packet.packet().to_vec().into()); + + // Wrap into a mixnet input message addressed to the IPR + let mixnet_message = wrap_in_mixnet_message(self.ipr_address, bundled_packet)?; + + // Send across the mixnet + self.mixnet_client_sender + .send(mixnet_message) + .await + .map_err(|err| Error::NymSdkError(Box::new(err))) + } + + async fn ping_v4_ipr_tun_device_over_the_mixnet(&mut self) -> Result<()> { + self.send_icmp_v4_ping(NYM_TUN_DEVICE_ADDRESS_V4).await + } + + async fn ping_v6_ipr_tun_device_over_the_mixnet(&mut self) -> Result<()> { + self.send_icmp_v6_ping(NYM_TUN_DEVICE_ADDRESS_V6).await + } + + async fn ping_v4_some_external_ip_over_the_mixnet(&mut self) -> Result<()> { + // TODO: ramdon external IP from a pool + self.send_icmp_v4_ping(ICMP_IPR_TUN_EXTERNAL_PING_V4).await + } + + async fn ping_v6_some_external_ip_over_the_mixnet(&mut self) -> Result<()> { + // TODO: ramdon external IP from a pool + self.send_icmp_v6_ping(ICMP_IPR_TUN_EXTERNAL_PING_V6).await + } + + pub async fn run(mut self, shutdown: CancellationToken) -> Result<()> { + debug!("Icmp connection beacon is running"); + let mut ping_interval = tokio::time::interval(ICMP_BEACON_PING_INTERVAL); + while !shutdown.is_cancelled() { + tokio::select! { + _ = shutdown.cancelled() => { + trace!("IcmpConnectionBeacon: Received shutdown"); + break; + } + _ = ping_interval.tick() => { + let cancellable_fut = async { + if let Err(err) = self.ping_v4_ipr_tun_device_over_the_mixnet().await { + trace_err_chain!(err, "Failed to send ICMP ping"); + } + if let Err(err) = self.ping_v6_ipr_tun_device_over_the_mixnet().await { + trace_err_chain!(err, "Failed to send ICMPv6 ping"); + } + if let Err(err) = self.ping_v4_some_external_ip_over_the_mixnet().await { + trace_err_chain!(err, "Failed to send ICMP ping"); + } + if let Err(err) = self.ping_v6_some_external_ip_over_the_mixnet().await { + trace_err_chain!(err, "Failed to send ICMPv6 ping"); + } + }; + + tokio::select! { + _ = cancellable_fut => { + continue; + }, + _ = shutdown.cancelled() => { + trace!("IcmpConnectionBeacon: Received shutdown"); + break; + } + } + } + } + } + debug!("IcmpConnectionBeacon: Exiting"); + Ok(()) + } +} + +fn wrap_in_mixnet_message(recipient: Recipient, bundled_packets: Bytes) -> Result { + let packet = IpPacketRequest::new_data_request(bundled_packets).to_bytes()?; + let surbs = 0; + let mixnet_message = nym_sdk::mixnet::InputMessage::new_anonymous( + recipient, + packet, + surbs, + TransmissionLane::General, + None, + ) + .with_max_retransmissions(0); + Ok(mixnet_message) +} + +pub enum IcmpBeaconReply { + TunDeviceReply, + ExternalPingReply(Ipv4Addr), +} + +pub enum Icmpv6BeaconReply { + TunDeviceReply, + ExternalPingReply(Ipv6Addr), +} + +pub fn is_icmp_beacon_reply( + packet: &Bytes, + identifier: u16, + destination: Ipv4Addr, +) -> Option { + if let Some((reply_identifier, reply_source, reply_destination)) = is_icmp_echo_reply(packet) + && reply_identifier == identifier + && reply_destination == destination + { + if reply_source == NYM_TUN_DEVICE_ADDRESS_V4 { + return Some(IcmpBeaconReply::TunDeviceReply); + } else if reply_source == ICMP_IPR_TUN_EXTERNAL_PING_V4 { + return Some(IcmpBeaconReply::ExternalPingReply(reply_source)); + } + } + None +} + +pub fn is_icmp_v6_beacon_reply( + packet: &Bytes, + identifier: u16, + destination: Ipv6Addr, +) -> Option { + if let Some((reply_identifier, reply_source, reply_destination)) = is_icmp_v6_echo_reply(packet) + && reply_identifier == identifier + && reply_destination == destination + { + if reply_source == NYM_TUN_DEVICE_ADDRESS_V6 { + return Some(Icmpv6BeaconReply::TunDeviceReply); + } else if reply_source == ICMP_IPR_TUN_EXTERNAL_PING_V6 { + return Some(Icmpv6BeaconReply::ExternalPingReply(reply_source)); + } + } + None +} + +pub fn start_icmp_connection_beacon( + mixnet_client_sender: MixnetClientSender, + our_ips: IpPair, + ipr_address: Recipient, + icmp_identifier: u16, + shutdown_listener: CancellationToken, +) -> JoinHandle> { + debug!("Creating icmp connection beacon"); + let beacon = + IcmpConnectionBeacon::new(mixnet_client_sender, our_ips, ipr_address, icmp_identifier); + tokio::spawn(async move { + beacon.run(shutdown_listener).await.inspect_err(|err| { + trace_err_chain!(err, "IcmpConnectionBeacon failed"); + }) + }) +} diff --git a/common/nym-connection-monitor/src/lib.rs b/common/nym-connection-monitor/src/lib.rs new file mode 100644 index 0000000000..0aeec143f9 --- /dev/null +++ b/common/nym-connection-monitor/src/lib.rs @@ -0,0 +1,87 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use futures::channel::mpsc; +use nym_ip_packet_requests::IpPair; +use nym_sdk::mixnet::{MixnetClientSender, Recipient}; +use tokio_util::sync::CancellationToken; +use tracing::info; + +// Import these here for for all modules to use, to keep the version consistent +pub(crate) use nym_ip_packet_requests::v8 as nym_ip_packet_requests_current; + +mod error; +mod icmp_beacon; +mod mixnet_beacon; +mod monitor; +mod sync_self_ping; + +pub mod packet_helpers; +pub use error::Error; +pub use icmp_beacon::{ + IcmpBeaconReply, Icmpv6BeaconReply, is_icmp_beacon_reply, is_icmp_v6_beacon_reply, +}; +pub use monitor::{ConnectionMonitorStatus, ConnectionStatusEvent}; +pub use sync_self_ping::self_ping_and_wait; + +fn create_icmp_beacon_identifier() -> u16 { + // TODO: use something that is more unique than just process id + std::process::id() as u16 +} + +// Top-level task that sets up the ICMP and mixnet connection beacons and the connection monitor, +// as well as provides the channel to send connection status events read from the mixnet, to the +// monitor. +pub struct ConnectionMonitorTask { + icmp_beacon_identifier: u16, + connection_event_tx: mpsc::UnboundedSender, + connection_event_rx: mpsc::UnboundedReceiver, +} + +impl ConnectionMonitorTask { + pub fn setup() -> ConnectionMonitorTask { + let (connection_event_tx, connection_event_rx) = mpsc::unbounded(); + let icmp_beacon_identifier = create_icmp_beacon_identifier(); + ConnectionMonitorTask { + icmp_beacon_identifier, + connection_event_tx, + connection_event_rx, + } + } + + pub fn event_sender(&self) -> mpsc::UnboundedSender { + self.connection_event_tx.clone() + } + + pub fn icmp_beacon_identifier(&self) -> u16 { + self.icmp_beacon_identifier + } + + pub fn start( + self, + mixnet_client_sender: MixnetClientSender, + our_nym_address: Recipient, + our_ips: IpPair, + exit_router_address: Recipient, + cancel_token: CancellationToken, + ) { + info!("Setting up mixnet connection beacon"); + mixnet_beacon::start_mixnet_connection_beacon( + mixnet_client_sender.clone(), + our_nym_address, + cancel_token.child_token(), + ); + + info!("Setting up ICMP connection beacon"); + icmp_beacon::start_icmp_connection_beacon( + mixnet_client_sender, + our_ips, + exit_router_address, + self.icmp_beacon_identifier, + cancel_token.child_token(), + ); + + info!("Setting up connection monitor"); + monitor::start_connection_monitor(self.connection_event_rx, cancel_token.child_token()); + } +} diff --git a/common/nym-connection-monitor/src/mixnet_beacon.rs b/common/nym-connection-monitor/src/mixnet_beacon.rs new file mode 100644 index 0000000000..021519ef17 --- /dev/null +++ b/common/nym-connection-monitor/src/mixnet_beacon.rs @@ -0,0 +1,106 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use std::time::Duration; + +use nym_common::trace_err_chain; +use nym_sdk::mixnet::{ + InputMessage, MixnetClientSender, MixnetMessageSender, Recipient, TransmissionLane, +}; +use tokio::task::JoinHandle; +use tokio_util::sync::CancellationToken; +use tracing::{debug, trace}; + +use crate::{Error, error::Result, nym_ip_packet_requests_current::request::IpPacketRequest}; + +const MIXNET_SELF_PING_INTERVAL: Duration = Duration::from_millis(1000); + +struct MixnetConnectionBeacon { + mixnet_client_sender: MixnetClientSender, + our_address: Recipient, +} + +impl MixnetConnectionBeacon { + fn new(mixnet_client_sender: MixnetClientSender, our_address: Recipient) -> Self { + MixnetConnectionBeacon { + mixnet_client_sender, + our_address, + } + } + + async fn send_mixnet_self_ping(&self) -> Result { + trace!("Sending mixnet self ping"); + let (input_message, request_id) = create_self_ping(self.our_address); + self.mixnet_client_sender + .send(input_message) + .await + .map_err(|err| Error::NymSdkError(Box::new(err)))?; + Ok(request_id) + } + + pub async fn run(self, shutdown: CancellationToken) -> Result<()> { + debug!("Mixnet connection beacon is running"); + let mut ping_interval = tokio::time::interval(MIXNET_SELF_PING_INTERVAL); + loop { + tokio::select! { + _ = shutdown.cancelled() => { + trace!("MixnetConnectionBeacon: Received shutdown"); + break; + } + _ = ping_interval.tick() => { + tokio::select! { + _ = shutdown.cancelled() => { + trace!("MixnetConnectionBeacon: Received shutdown"); + break; + }, + ping_result = self.send_mixnet_self_ping() => { + let _ping_id = match ping_result { + Ok(id) => id, + Err(err) => { + trace_err_chain!( + err, + "Failed to send mixnet self ping" + ); + continue; + } + }; + // TODO: store ping_id to be able to monitor or ping timeouts + } + }; + } + } + } + debug!("MixnetConnectionBeacon: Exiting"); + Ok(()) + } +} + +pub fn create_self_ping(our_address: Recipient) -> (InputMessage, u64) { + let (request, request_id) = IpPacketRequest::new_ping(); + ( + InputMessage::new_regular( + our_address, + // SAFETY: this message has infallible serialisation + #[allow(clippy::unwrap_used)] + request.to_bytes().unwrap(), + TransmissionLane::General, + None, + ), + request_id, + ) +} + +pub fn start_mixnet_connection_beacon( + mixnet_client_sender: MixnetClientSender, + our_address: Recipient, + cancel_token: CancellationToken, +) -> JoinHandle> { + debug!("Creating mixnet connection beacon"); + let beacon = MixnetConnectionBeacon::new(mixnet_client_sender, our_address); + tokio::spawn(async move { + beacon + .run(cancel_token) + .await + .inspect_err(|err| trace_err_chain!(err, "Mixnet connection beacon error")) + }) +} diff --git a/common/nym-connection-monitor/src/monitor.rs b/common/nym-connection-monitor/src/monitor.rs new file mode 100644 index 0000000000..d0f84e0b95 --- /dev/null +++ b/common/nym-connection-monitor/src/monitor.rs @@ -0,0 +1,301 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use std::{ + fmt, + time::{Duration, Instant}, +}; + +use futures::{StreamExt, channel::mpsc}; +use nym_common::trace_err_chain; +use tokio::task::JoinHandle; +use tokio_util::sync::CancellationToken; + +use crate::error::Result; + +const CONNECTION_MONITOR_REPORT_INTERVAL: Duration = Duration::from_secs(5); + +// When the latest successful ping is older than this, we consider the connection to be down +const PING_REPLY_EXPIRY: Duration = Duration::from_secs(5); + +// Events that are reported by other tasks to the connection monitor +#[derive(Debug)] +pub enum ConnectionStatusEvent { + MixnetSelfPing, + Icmpv4IprTunDevicePingReply, + Icmpv6IprTunDevicePingReply, + Icmpv4IprExternalPingReply, + Icmpv6IprExternalPingReply, +} + +#[derive(Debug, Default)] +struct ConnectionStats { + // TODO: extend with all sorts of good stuff + latest_self_ping: Option, + latest_ipr_tun_device_ping_v4_reply: Option, + latest_ipr_tun_device_ping_v6_reply: Option, + latest_ipr_external_ping_v4_reply: Option, + latest_ipr_external_ping_v6_reply: Option, +} + +impl ConnectionStats { + fn evaluate_connectivity(&self) -> ConnectivityState { + let entry = ConnectivityStatus::from(&self.latest_self_ping); + + let exit_ipv4 = ConnectivityStatus::from(&self.latest_ipr_tun_device_ping_v4_reply); + let exit_ipv6 = ConnectivityStatus::from(&self.latest_ipr_tun_device_ping_v6_reply); + + let exit_routing_ipv4 = ConnectivityStatus::from(&self.latest_ipr_external_ping_v4_reply); + let exit_routing_ipv6 = ConnectivityStatus::from(&self.latest_ipr_external_ping_v6_reply); + + ConnectivityState { + entry, + exit: IpConnectivity { + ipv4: exit_ipv4, + ipv6: exit_ipv6, + }, + exit_routing: IpConnectivity { + ipv4: exit_routing_ipv4, + ipv6: exit_routing_ipv6, + }, + } + } + + fn log_status(&self) { + tracing::trace!( + "Time since latest received self ping: {}ms", + self.latest_self_ping + .map(|t| t.elapsed().as_millis()) + .unwrap_or(0) + ); + tracing::trace!( + "Time since latest received ipr tun device ping v4 reply: {}ms", + self.latest_ipr_tun_device_ping_v4_reply + .map(|t| t.elapsed().as_millis()) + .unwrap_or(0) + ); + tracing::trace!( + "Time since latest received ipr tun device ping v6 reply: {}ms", + self.latest_ipr_tun_device_ping_v6_reply + .map(|t| t.elapsed().as_millis()) + .unwrap_or(0) + ); + tracing::trace!( + "Time since latest received ipr external ping v4 reply: {}ms", + self.latest_ipr_external_ping_v4_reply + .map(|t| t.elapsed().as_millis()) + .unwrap_or(0) + ); + tracing::trace!( + "Time since latest received ipr external ping v6 reply: {}ms", + self.latest_ipr_external_ping_v6_reply + .map(|t| t.elapsed().as_millis()) + .unwrap_or(0) + ); + } +} + +struct ConnectionMonitor { + connection_event_rx: mpsc::UnboundedReceiver, + stats: ConnectionStats, +} + +#[derive(Debug, PartialEq, Eq)] +enum ConnectivityStatus { + Ok, + Fail, +} + +impl From<&Option> for ConnectivityStatus { + fn from(reply: &Option) -> Self { + match reply { + Some(when) if when.elapsed() < PING_REPLY_EXPIRY => ConnectivityStatus::Ok, + Some(_) => ConnectivityStatus::Fail, + None => ConnectivityStatus::Fail, + } + } +} + +struct IpConnectivity { + ipv4: ConnectivityStatus, + ipv6: ConnectivityStatus, +} + +struct ConnectivityState { + entry: ConnectivityStatus, + exit: IpConnectivity, + exit_routing: IpConnectivity, +} + +impl ConnectionMonitor { + fn new(connection_event_rx: mpsc::UnboundedReceiver) -> Self { + ConnectionMonitor { + connection_event_rx, + stats: ConnectionStats::default(), + } + } + + fn record_event(&mut self, event: &ConnectionStatusEvent) { + match event { + ConnectionStatusEvent::MixnetSelfPing => { + tracing::trace!("Received self ping event"); + self.stats.latest_self_ping = Some(Instant::now()); + } + ConnectionStatusEvent::Icmpv4IprTunDevicePingReply => { + tracing::trace!("Received IPR tun device ping reply event"); + self.stats.latest_ipr_tun_device_ping_v4_reply = Some(Instant::now()); + } + ConnectionStatusEvent::Icmpv6IprTunDevicePingReply => { + tracing::trace!("Received IPR tun device ping v6 reply event"); + self.stats.latest_ipr_tun_device_ping_v6_reply = Some(Instant::now()); + } + ConnectionStatusEvent::Icmpv4IprExternalPingReply => { + tracing::trace!("Received IPR external ping reply event"); + self.stats.latest_ipr_external_ping_v4_reply = Some(Instant::now()); + } + ConnectionStatusEvent::Icmpv6IprExternalPingReply => { + tracing::trace!("Received IPR external ping v6 reply event"); + self.stats.latest_ipr_external_ping_v6_reply = Some(Instant::now()); + } + } + } + + async fn run(mut self, cancel_token: CancellationToken) -> Result<()> { + tracing::debug!("Connection monitor is running"); + let mut report_interval = tokio::time::interval(CONNECTION_MONITOR_REPORT_INTERVAL); + // Reset so that we don't send a report immediately before we even have a change for any + // self pings to be sent and received + report_interval.reset(); + + loop { + tokio::select! { + _ = cancel_token.cancelled() => { + tracing::trace!("ConnectionMonitor: Received shutdown"); + break; + } + Some(event) = self.connection_event_rx.next() => { + self.record_event(&event); + } + _ = report_interval.tick() => { + self.stats.log_status(); + let connectivity = self.stats.evaluate_connectivity(); + log_connectivity(&connectivity); + } + } + } + tracing::debug!("ConnectionMonitor: Exiting"); + Ok(()) + } +} + +// Keep that code commented for when we restore connectivity reports +// TODO restore connectivity reports with proper channels +fn log_connectivity(connectivity: &ConnectivityState) { + if connectivity.entry == ConnectivityStatus::Fail { + tracing::error!("Entry gateway not routing our mixnet traffic"); + //task_client.send_status_msg(Box::new(ConnectionMonitorStatus::EntryGatewayDown)); + return; + } + + // If we can route external traffic, then it's ok even if we can't ping the exit IPR. + if connectivity.exit_routing.ipv4 == ConnectivityStatus::Ok { + tracing::debug!("ConnectionMonitor: connection success over ipv4"); + //task_client.send_status_msg(Box::new(ConnectionMonitorStatus::ConnectedIpv4)); + } else if connectivity.exit.ipv4 == ConnectivityStatus::Fail { + tracing::error!("Exit gateway (IPR) not responding to IPv4 traffic"); + //task_client.send_status_msg(Box::new(ConnectionMonitorStatus::ExitGatewayDownIpv4)); + } else if connectivity.exit_routing.ipv4 == ConnectivityStatus::Fail { + tracing::error!("Exit gateway (IPR) not routing IPv4 traffic to external destinations"); + //task_client.send_status_msg(Box::new( + // ConnectionMonitorStatus::ExitGatewayRoutingErrorIpv4, + //)); + } else { + tracing::error!( + "Unexpected connectivity state - exit gateway ipv4 connectivity is ok, but routing is not?" + ); + } + + if connectivity.exit_routing.ipv6 == ConnectivityStatus::Ok { + tracing::debug!("ConnectionMonitor: connection success over ipv6"); + //task_client.send_status_msg(Box::new(ConnectionMonitorStatus::ConnectedIpv6)); + } else if connectivity.exit.ipv6 == ConnectivityStatus::Fail { + tracing::error!("Exit gateway (IPR) not responding to IPv6 traffic"); + //task_client.send_status_msg(Box::new(ConnectionMonitorStatus::ExitGatewayDownIpv6)); + } else if connectivity.exit_routing.ipv6 == ConnectivityStatus::Fail { + tracing::error!("Exit gateway (IPR) not routing IPv6 traffic to external destinations"); + //task_client.send_status_msg(Box::new( + // ConnectionMonitorStatus::ExitGatewayRoutingErrorIpv6, + //)); + } else { + tracing::error!( + "Unexpected connectivity state - exit gateway ipv6 connectivity is ok, but routing is not?" + ); + } +} + +#[derive(Clone, Debug)] +pub enum ConnectionMonitorStatus { + EntryGatewayDown, + ExitGatewayDownIpv4, + ExitGatewayDownIpv6, + ExitGatewayRoutingErrorIpv4, + ExitGatewayRoutingErrorIpv6, + ConnectedIpv4, + ConnectedIpv6, +} + +impl fmt::Display for ConnectionMonitorStatus { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ConnectionMonitorStatus::EntryGatewayDown => { + write!( + f, + "entry gateway appears down - it's not routing our mixnet traffic" + ) + } + ConnectionMonitorStatus::ExitGatewayDownIpv4 => { + write!( + f, + "exit gateway (or ipr) appears down - it's not responding to IPv4 traffic" + ) + } + ConnectionMonitorStatus::ExitGatewayDownIpv6 => { + write!( + f, + "exit gateway (or ipr) appears down - it's not responding to IPv6 traffic" + ) + } + ConnectionMonitorStatus::ExitGatewayRoutingErrorIpv4 => { + write!( + f, + "exit gateway (or ipr) appears to be having issues routing and forwarding our external IPv4 traffic" + ) + } + ConnectionMonitorStatus::ExitGatewayRoutingErrorIpv6 => { + write!( + f, + "exit gateway (or ipr) appears to be having issues routing and forwarding our external IPv6 traffic" + ) + } + ConnectionMonitorStatus::ConnectedIpv4 => { + write!(f, "connected with ipv4") + } + ConnectionMonitorStatus::ConnectedIpv6 => { + write!(f, "connected with ipv6") + } + } + } +} + +pub fn start_connection_monitor( + connection_event_rx: futures::channel::mpsc::UnboundedReceiver, + cancel_token: CancellationToken, +) -> JoinHandle> { + tracing::debug!("Creating connection monitor"); + let monitor = ConnectionMonitor::new(connection_event_rx); + tokio::spawn(async move { + monitor.run(cancel_token).await.inspect_err(|err| { + trace_err_chain!(err, "Connection monitor error"); + }) + }) +} diff --git a/common/nym-connection-monitor/src/packet_helpers.rs b/common/nym-connection-monitor/src/packet_helpers.rs new file mode 100644 index 0000000000..8dfdc9e02a --- /dev/null +++ b/common/nym-connection-monitor/src/packet_helpers.rs @@ -0,0 +1,166 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use std::net::{Ipv4Addr, Ipv6Addr}; + +use bytes::Bytes; +use pnet_packet::{ + Packet, + icmp::{ + IcmpPacket, + echo_reply::EchoReplyPacket, + echo_request::{EchoRequestPacket, MutableEchoRequestPacket}, + }, + icmpv6, + ipv4::{Ipv4Packet, MutableIpv4Packet}, + ipv6::{Ipv6Packet, MutableIpv6Packet}, +}; + +use crate::error::{Error, Result}; + +pub fn create_icmpv4_echo_request( + sequence_number: u16, + identifier: u16, +) -> Result> { + let buffer = vec![0; 64]; + let mut icmp_echo_request = MutableEchoRequestPacket::owned(buffer) + .ok_or(Error::IcmpEchoRequestPacketCreationFailure)?; + + // Configure the ICMP echo request packet + icmp_echo_request.set_identifier(identifier); + icmp_echo_request.set_sequence_number(sequence_number); + icmp_echo_request.set_icmp_type(pnet_packet::icmp::IcmpTypes::EchoRequest); + icmp_echo_request.set_icmp_code(pnet_packet::icmp::IcmpCode::new(0)); + + // Calculate checksum once we've set all the fields + let icmp_packet = + IcmpPacket::new(icmp_echo_request.packet()).ok_or(Error::IcmpPacketCreationFailure)?; + let checksum = pnet_packet::icmp::checksum(&icmp_packet); + icmp_echo_request.set_checksum(checksum); + + Ok(icmp_echo_request.consume_to_immutable()) +} + +pub fn create_icmpv6_echo_request( + sequence_number: u16, + identifier: u16, + source: &Ipv6Addr, + destination: &Ipv6Addr, +) -> Result> { + let buffer = vec![0; 64]; + // let mut icmp_echo_request = MutableEchoRequestPacket::owned(buffer) + let mut icmp_echo_request = icmpv6::echo_request::MutableEchoRequestPacket::owned(buffer) + .ok_or(Error::IcmpEchoRequestPacketCreationFailure)?; + + // Configure the ICMP echo request packet + icmp_echo_request.set_identifier(identifier); + icmp_echo_request.set_sequence_number(sequence_number); + icmp_echo_request.set_icmpv6_type(pnet_packet::icmpv6::Icmpv6Types::EchoRequest); + icmp_echo_request.set_icmpv6_code(pnet_packet::icmpv6::Icmpv6Code::new(0)); + + // Calculate checksum once we've set all the fields + let icmp_packet = icmpv6::Icmpv6Packet::new(icmp_echo_request.packet()) + .ok_or(Error::IcmpPacketCreationFailure)?; + let checksum = pnet_packet::icmpv6::checksum(&icmp_packet, source, destination); + icmp_echo_request.set_checksum(checksum); + + Ok(icmp_echo_request.consume_to_immutable()) +} + +pub fn wrap_icmp_in_ipv4( + icmp_echo_request: EchoRequestPacket, + source: Ipv4Addr, + destination: Ipv4Addr, +) -> Result { + // 20 bytes for IPv4 header + ICMP payload + let total_length = 20 + icmp_echo_request.packet().len(); + // IPv4 header + ICMP payload + let ipv4_buffer = vec![0u8; 20 + icmp_echo_request.packet().len()]; + let mut ipv4_packet = + MutableIpv4Packet::owned(ipv4_buffer).ok_or(Error::Ipv4PacketCreationFailure)?; + + ipv4_packet.set_version(4); + ipv4_packet.set_header_length(5); + ipv4_packet.set_total_length(total_length as u16); + ipv4_packet.set_ttl(64); + ipv4_packet.set_next_level_protocol(pnet_packet::ip::IpNextHeaderProtocols::Icmp); + ipv4_packet.set_source(source); + ipv4_packet.set_destination(destination); + ipv4_packet.set_flags(pnet_packet::ipv4::Ipv4Flags::DontFragment); + ipv4_packet.set_checksum(0); + ipv4_packet.set_payload(icmp_echo_request.packet()); + + let ipv4_checksum = compute_ipv4_checksum(&ipv4_packet.to_immutable()); + ipv4_packet.set_checksum(ipv4_checksum); + + Ok(ipv4_packet.consume_to_immutable()) +} + +pub fn wrap_icmp_in_ipv6( + icmp_echo_request: icmpv6::echo_request::EchoRequestPacket, + source: Ipv6Addr, + destination: Ipv6Addr, +) -> Result { + let ipv6_buffer = vec![0u8; 40 + icmp_echo_request.packet().len()]; + let mut ipv6_packet = + MutableIpv6Packet::owned(ipv6_buffer).ok_or(Error::Ipv4PacketCreationFailure)?; + + ipv6_packet.set_version(6); + ipv6_packet.set_payload_length(icmp_echo_request.packet().len() as u16); + ipv6_packet.set_next_header(pnet_packet::ip::IpNextHeaderProtocols::Icmpv6); + ipv6_packet.set_hop_limit(64); + ipv6_packet.set_source(source); + ipv6_packet.set_destination(destination); + ipv6_packet.set_payload(icmp_echo_request.packet()); + + Ok(ipv6_packet.consume_to_immutable()) +} + +// Compute IPv4 checksum: sum all 16-bit words, add carry, take one's complement +pub(crate) fn compute_ipv4_checksum(header: &Ipv4Packet) -> u16 { + // Header length in 16-bit words + let len = header.get_header_length() as usize * 2; + let mut sum = 0u32; + + for i in 0..len { + let word = ((header.packet()[2 * i] as u32) << 8) | header.packet()[2 * i + 1] as u32; + sum += word; + } + + // Add the carry + while (sum >> 16) > 0 { + sum = (sum & 0xFFFF) + (sum >> 16); + } + + // One's complement + !sum as u16 +} + +pub(crate) fn is_icmp_echo_reply(packet: &Bytes) -> Option<(u16, Ipv4Addr, Ipv4Addr)> { + if let Some(ipv4_packet) = Ipv4Packet::new(packet) + && let Some(icmp_packet) = IcmpPacket::new(ipv4_packet.payload()) + && let Some(echo_reply) = EchoReplyPacket::new(icmp_packet.packet()) + { + return Some(( + echo_reply.get_identifier(), + ipv4_packet.get_source(), + ipv4_packet.get_destination(), + )); + } + None +} + +pub(crate) fn is_icmp_v6_echo_reply(packet: &Bytes) -> Option<(u16, Ipv6Addr, Ipv6Addr)> { + if let Some(ipv6_packet) = Ipv6Packet::new(packet) + && let Some(icmp_packet) = IcmpPacket::new(ipv6_packet.payload()) + && let Some(echo_reply) = + pnet_packet::icmpv6::echo_reply::EchoReplyPacket::new(icmp_packet.packet()) + { + return Some(( + echo_reply.get_identifier(), + ipv6_packet.get_source(), + ipv6_packet.get_destination(), + )); + } + None +} diff --git a/common/nym-connection-monitor/src/sync_self_ping.rs b/common/nym-connection-monitor/src/sync_self_ping.rs new file mode 100644 index 0000000000..79ec9a1098 --- /dev/null +++ b/common/nym-connection-monitor/src/sync_self_ping.rs @@ -0,0 +1,73 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use std::time::Duration; + +use futures::StreamExt; +use nym_sdk::mixnet::{MixnetClient, MixnetMessageSender, Recipient}; +use tracing::{debug, error}; + +use crate::{ + error::{Error, Result}, + mixnet_beacon::create_self_ping, + nym_ip_packet_requests_current::request::IpPacketRequest, +}; + +// Send mixnet self ping and wait for the response +pub async fn self_ping_and_wait( + our_address: Recipient, + mixnet_client: &mut MixnetClient, +) -> Result<()> { + let request_ids = send_self_pings(our_address, mixnet_client).await?; + wait_for_self_ping_return(mixnet_client, &request_ids).await +} + +async fn send_self_pings(our_address: Recipient, mixnet_client: &MixnetClient) -> Result> { + // Send pings + let request_ids = futures::stream::iter(1..=3) + .then(|_| async { + let (input_message, request_id) = create_self_ping(our_address); + mixnet_client + .send(input_message) + .await + .map_err(|err| Error::NymSdkError(Box::new(err)))?; + Ok::(request_id) + }) + .collect::>() + .await; + + // Check the vec of results and return the first error, if any. If there are not errors, unwrap + // all the results into a vec of u64s. + request_ids.into_iter().collect::>>() +} + +async fn wait_for_self_ping_return( + mixnet_client: &mut MixnetClient, + request_ids: &[u64], +) -> Result<()> { + let timeout = tokio::time::sleep(Duration::from_secs(5)); + tokio::pin!(timeout); + + loop { + tokio::select! { + _ = &mut timeout => { + error!("Timed out waiting for mixnet self ping to return"); + return Err(Error::TimeoutWaitingForMixnetSelfPing); + } + Some(msgs) = mixnet_client.wait_for_messages() => { + for msg in msgs { + let Ok(response) = IpPacketRequest::from_reconstructed_message(&msg) else { + // This is a common case when we are reconnecting to a gateway and receive + // all sorts of messages that are buffered since out last connection. + debug!("Failed to deserialize reconstructed message"); + continue; + }; + if request_ids.iter().any(|&id| response.id() == Some(id)) { + debug!("Got the ping we were waiting for"); + return Ok(()); + } + } + } + } + } +} diff --git a/common/nym-id/src/error.rs b/common/nym-id/src/error.rs index b76afa47cf..c232aa6194 100644 --- a/common/nym-id/src/error.rs +++ b/common/nym-id/src/error.rs @@ -25,13 +25,19 @@ pub enum NymIdError { #[error("attempted to import an expired credential (it expired on {expiration})")] ExpiredCredentialImport { expiration: Date }, - #[error("could not import ticketbook expiring at {date} for epoch {epoch_id} since we do not have corresponding expiration date signatures")] + #[error( + "could not import ticketbook expiring at {date} for epoch {epoch_id} since we do not have corresponding expiration date signatures" + )] MissingExpirationDateSignatures { date: Date, epoch_id: u64 }, - #[error("could not import ticketbook for epoch {epoch_id} since we do not have corresponding coin index signatures")] + #[error( + "could not import ticketbook for epoch {epoch_id} since we do not have corresponding coin index signatures" + )] MissingCoinIndexSignatures { epoch_id: u64 }, - #[error("could not import ticketbook for epoch {epoch_id} since we do not have corresponding master verification key")] + #[error( + "could not import ticketbook for epoch {epoch_id} since we do not have corresponding master verification key" + )] MissingMasterVerificationKey { epoch_id: u64 }, #[error("failed to store credential in the provided store: {source}")] diff --git a/common/nym-id/src/import_credential/mod.rs b/common/nym-id/src/import_credential/mod.rs index 878b3bc5bc..1969fb6500 100644 --- a/common/nym-id/src/import_credential/mod.rs +++ b/common/nym-id/src/import_credential/mod.rs @@ -3,11 +3,11 @@ use crate::NymIdError; use nym_credential_storage::storage::Storage; +use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; use nym_credentials::ecash::bandwidth::serialiser::keys::EpochVerificationKey; use nym_credentials::ecash::bandwidth::serialiser::signatures::{ AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, }; -use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; use nym_credentials::ecash::utils::EcashTime; use nym_credentials::{ImportableTicketBook, IssuedTicketBook}; use time::OffsetDateTime; diff --git a/common/nym-metrics/src/lib.rs b/common/nym-metrics/src/lib.rs index 8694ea73d1..dabd542135 100644 --- a/common/nym-metrics/src/lib.rs +++ b/common/nym-metrics/src/lib.rs @@ -3,8 +3,8 @@ use std::fmt; use tracing::{debug, error, warn}; use prometheus::{ - core::Collector, Encoder as _, Gauge, Histogram, HistogramOpts, IntCounter, IntGauge, Registry, - TextEncoder, + Encoder as _, Gauge, Histogram, HistogramOpts, IntCounter, IntGauge, Registry, TextEncoder, + core::Collector, }; pub use prometheus::HistogramTimer; @@ -274,7 +274,10 @@ impl Metric { Metric::IntCounter(c) => c.inc_by(value as u64), Metric::IntGauge(g) => g.add(value), Metric::FloatGauge(g) => { - warn!("attempted to increment a float gauge ('{}') by an integer - this is most likely a bug", self.fq_name()); + warn!( + "attempted to increment a float gauge ('{}') by an integer - this is most likely a bug", + self.fq_name() + ); g.add(value as f64) } Metric::Histogram(_) => { @@ -291,7 +294,10 @@ impl Metric { } Metric::IntGauge(g) => g.set(value), Metric::FloatGauge(g) => { - warn!("attempted to set a float gauge ('{}') to an integer value - this is most likely a bug", self.fq_name()); + warn!( + "attempted to set a float gauge ('{}') to an integer value - this is most likely a bug", + self.fq_name() + ); g.set(value as f64) } Metric::Histogram(_) => { @@ -307,7 +313,10 @@ impl Metric { warn!("Cannot set value for counter {:?}", self.fq_name()); } Metric::IntGauge(g) => { - warn!("attempted to set a integer gauge ('{}') to a float value - this is most likely a bug", self.fq_name()); + warn!( + "attempted to set a integer gauge ('{}') to a float value - this is most likely a bug", + self.fq_name() + ); g.set(value as i64) } Metric::FloatGauge(g) => g.set(value), diff --git a/common/nymsphinx/acknowledgements/src/identifier.rs b/common/nymsphinx/acknowledgements/src/identifier.rs index 544e9be959..4077b135a0 100644 --- a/common/nymsphinx/acknowledgements/src/identifier.rs +++ b/common/nymsphinx/acknowledgements/src/identifier.rs @@ -3,9 +3,9 @@ use crate::AckKey; use nym_crypto::symmetric::stream_cipher::{ - self, encrypt, random_iv, try_iv_from_slice, IvSizeUser, + self, IvSizeUser, encrypt, random_iv, try_iv_from_slice, }; -use nym_sphinx_params::{AckEncryptionAlgorithm, SerializedFragmentIdentifier, FRAG_ID_LEN}; +use nym_sphinx_params::{AckEncryptionAlgorithm, FRAG_ID_LEN, SerializedFragmentIdentifier}; use rand::{CryptoRng, RngCore}; // TODO: should those functions even exist in this file? diff --git a/common/nymsphinx/acknowledgements/src/key.rs b/common/nymsphinx/acknowledgements/src/key.rs index 8ee996cd1d..3a6844ed93 100644 --- a/common/nymsphinx/acknowledgements/src/key.rs +++ b/common/nymsphinx/acknowledgements/src/key.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use nym_crypto::symmetric::stream_cipher::{generate_key, CipherKey, KeySizeUser}; +use nym_crypto::symmetric::stream_cipher::{CipherKey, KeySizeUser, generate_key}; use nym_pemstore::traits::PemStorableKey; use nym_sphinx_params::AckEncryptionAlgorithm; use rand::{CryptoRng, RngCore}; diff --git a/common/nymsphinx/acknowledgements/src/surb_ack.rs b/common/nymsphinx/acknowledgements/src/surb_ack.rs index 982ced55be..a3db8e1fe3 100644 --- a/common/nymsphinx/acknowledgements/src/surb_ack.rs +++ b/common/nymsphinx/acknowledgements/src/surb_ack.rs @@ -1,16 +1,16 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::identifier::prepare_identifier; use crate::AckKey; +use crate::identifier::prepare_identifier; use nym_sphinx_addressing::clients::Recipient; use nym_sphinx_addressing::nodes::{ - NymNodeRoutingAddress, NymNodeRoutingAddressError, MAX_NODE_ADDRESS_UNPADDED_LEN, + MAX_NODE_ADDRESS_UNPADDED_LEN, NymNodeRoutingAddress, NymNodeRoutingAddressError, }; -use nym_sphinx_params::packet_sizes::PacketSize; use nym_sphinx_params::PacketType; +use nym_sphinx_params::packet_sizes::PacketSize; use nym_sphinx_types::delays::Delay; -use nym_sphinx_types::{NymPacket, NymPacketError, MIN_PACKET_SIZE}; +use nym_sphinx_types::{MIN_PACKET_SIZE, NymPacket, NymPacketError}; use nym_topology::{NymRouteProvider, NymTopologyError}; use rand::{CryptoRng, RngCore}; @@ -26,7 +26,9 @@ pub struct SurbAck { #[derive(Debug, Error)] pub enum SurbAckRecoveryError { - #[error("received an invalid number of bytes to deserialize the SURB-Ack. Got {received}, expected {expected}")] + #[error( + "received an invalid number of bytes to deserialize the SURB-Ack. Got {received}, expected {expected}" + )] InvalidPacketSize { received: usize, expected: usize }, #[error("could not extract first hop address information - {0}")] diff --git a/common/nymsphinx/addressing/src/clients.rs b/common/nymsphinx/addressing/src/clients.rs index aa475dc401..d7aba4a13e 100644 --- a/common/nymsphinx/addressing/src/clients.rs +++ b/common/nymsphinx/addressing/src/clients.rs @@ -4,7 +4,7 @@ // of a helper/utils structure, because before it reaches the gateway // it's already destructed). -use crate::nodes::{NodeIdentity, NODE_IDENTITY_SIZE}; +use crate::nodes::{NODE_IDENTITY_SIZE, NodeIdentity}; use nym_crypto::asymmetric::{ed25519, x25519}; use nym_sphinx_types::Destination; use serde::de::{Error as SerdeError, SeqAccess, Unexpected, Visitor}; @@ -68,7 +68,10 @@ impl<'de> Deserialize<'de> for Recipient { type Value = Recipient; fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result { - write!(formatter, "A recipient is 96-byte sequence containing two ed25519 public keys and one x25519 public key all in compressed forms.") + write!( + formatter, + "A recipient is 96-byte sequence containing two ed25519 public keys and one x25519 public key all in compressed forms." + ) } fn visit_bytes(self, bytes: &[u8]) -> Result @@ -97,10 +100,10 @@ impl<'de> Deserialize<'de> for Recipient { { // if we know the size hint, check if it matches expectation, // otherwise return an error - if let Some(size_hint) = seq.size_hint() { - if size_hint != Recipient::LEN { - return Err(SerdeError::invalid_length(size_hint, &self)); - } + if let Some(size_hint) = seq.size_hint() + && size_hint != Recipient::LEN + { + return Err(SerdeError::invalid_length(size_hint, &self)); } let mut recipient_bytes = [0u8; Recipient::LEN]; diff --git a/common/nymsphinx/addressing/src/nodes.rs b/common/nymsphinx/addressing/src/nodes.rs index 264eaa5ed9..49fba4129e 100644 --- a/common/nymsphinx/addressing/src/nodes.rs +++ b/common/nymsphinx/addressing/src/nodes.rs @@ -9,7 +9,7 @@ //! for as long as it's going to fit in the field. use nym_crypto::asymmetric::ed25519; -use nym_sphinx_types::{NodeAddressBytes, NODE_ADDRESS_LENGTH}; +use nym_sphinx_types::{NODE_ADDRESS_LENGTH, NodeAddressBytes}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use thiserror::Error; @@ -28,17 +28,23 @@ pub enum NymNodeRoutingAddressError { #[error("Attempted to deserialize NymNodeRoutingAddress without providing any bytes")] NoBytesProvided, - #[error("Provided insufficient amount of few bytes to deserialize a valid NymNodeRoutingAddress for IPv{protocol_version} variant. Received {received} and required {required}")] + #[error( + "Provided insufficient amount of few bytes to deserialize a valid NymNodeRoutingAddress for IPv{protocol_version} variant. Received {received} and required {required}" + )] TooFewBytesProvided { protocol_version: u8, received: usize, required: usize, }, - #[error("{received} is not a valid version of the Internet Protocol (IP). Expected either '4' or '6'")] + #[error( + "{received} is not a valid version of the Internet Protocol (IP). Expected either '4' or '6'" + )] InvalidIpVersion { received: u8 }, - #[error("Could not serialize NymNodeRoutingAddress into NodeAddressBytes as that requires using at least {required} bytes and only {NODE_ADDRESS_LENGTH} are available")] + #[error( + "Could not serialize NymNodeRoutingAddress into NodeAddressBytes as that requires using at least {required} bytes and only {NODE_ADDRESS_LENGTH} are available" + )] TooSmallBytesRepresentation { required: usize }, } diff --git a/common/nymsphinx/anonymous-replies/src/encryption_key.rs b/common/nymsphinx/anonymous-replies/src/encryption_key.rs index 9dae044f0e..2021cd7998 100644 --- a/common/nymsphinx/anonymous-replies/src/encryption_key.rs +++ b/common/nymsphinx/anonymous-replies/src/encryption_key.rs @@ -2,10 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use nym_crypto::{ - crypto_hash, - generic_array::{typenum::Unsigned, GenericArray}, - symmetric::stream_cipher::{generate_key, CipherKey, KeySizeUser}, - OutputSizeUser, + OutputSizeUser, crypto_hash, + generic_array::{GenericArray, typenum::Unsigned}, + symmetric::stream_cipher::{CipherKey, KeySizeUser, generate_key}, }; use nym_sphinx_params::{ReplySurbEncryptionAlgorithm, ReplySurbKeyDigestAlgorithm}; use rand::{CryptoRng, RngCore}; diff --git a/common/nymsphinx/anonymous-replies/src/reply_surb.rs b/common/nymsphinx/anonymous-replies/src/reply_surb.rs index 6f3dd9137e..5f45c062ca 100644 --- a/common/nymsphinx/anonymous-replies/src/reply_surb.rs +++ b/common/nymsphinx/anonymous-replies/src/reply_surb.rs @@ -2,15 +2,15 @@ // SPDX-License-Identifier: Apache-2.0 use crate::encryption_key::{SurbEncryptionKey, SurbEncryptionKeyError, SurbEncryptionKeySize}; -use nym_crypto::{generic_array::typenum::Unsigned, Digest}; +use nym_crypto::{Digest, generic_array::typenum::Unsigned}; use nym_sphinx_addressing::clients::Recipient; use nym_sphinx_addressing::nodes::{ - NymNodeRoutingAddress, NymNodeRoutingAddressError, MAX_NODE_ADDRESS_UNPADDED_LEN, + MAX_NODE_ADDRESS_UNPADDED_LEN, NymNodeRoutingAddress, NymNodeRoutingAddressError, }; use nym_sphinx_params::packet_sizes::PacketSize; use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm, SphinxKeyRotation}; use nym_sphinx_types::{ - NymPacket, SURBMaterial, SphinxError, HEADER_SIZE, NODE_ADDRESS_LENGTH, SURB, + HEADER_SIZE, NODE_ADDRESS_LENGTH, NymPacket, SURB, SURBMaterial, SphinxError, X25519_WITH_EXPLICIT_PAYLOAD_KEYS_VERSION, }; use nym_topology::{NymRouteProvider, NymTopologyError}; diff --git a/common/nymsphinx/anonymous-replies/src/requests/mod.rs b/common/nymsphinx/anonymous-replies/src/requests/mod.rs index 8dbe741b91..ecb2fc7ac5 100644 --- a/common/nymsphinx/anonymous-replies/src/requests/mod.rs +++ b/common/nymsphinx/anonymous-replies/src/requests/mod.rs @@ -492,12 +492,12 @@ mod tests { use nym_sphinx_addressing::clients::Recipient; use nym_sphinx_params::SphinxKeyRotation; use nym_sphinx_types::{ - Delay, Destination, DestinationAddressBytes, Node, NodeAddressBytes, PrivateKey, - SURBMaterial, NODE_ADDRESS_LENGTH, X25519_WITH_EXPLICIT_PAYLOAD_KEYS_VERSION, + Delay, Destination, DestinationAddressBytes, NODE_ADDRESS_LENGTH, Node, + NodeAddressBytes, PrivateKey, SURBMaterial, X25519_WITH_EXPLICIT_PAYLOAD_KEYS_VERSION, }; use rand::{Rng, RngCore}; - use rand_chacha::rand_core::SeedableRng; use rand_chacha::ChaCha20Rng; + use rand_chacha::rand_core::SeedableRng; pub(crate) const LEGACY_HOPS: u8 = 4; @@ -509,7 +509,7 @@ mod tests { pub(super) fn random_vec_u8(rng: &mut ChaCha20Rng, n: usize) -> Vec { let mut vec = Vec::with_capacity(n); for _ in 0..n { - vec.push(rng.gen()) + vec.push(rng.r#gen()) } vec } diff --git a/common/nymsphinx/anonymous-replies/src/requests/v1.rs b/common/nymsphinx/anonymous-replies/src/requests/v1.rs index 03f3544869..f784437b01 100644 --- a/common/nymsphinx/anonymous-replies/src/requests/v1.rs +++ b/common/nymsphinx/anonymous-replies/src/requests/v1.rs @@ -16,10 +16,10 @@ const fn v1_reply_surb_serialised_len() -> usize { fn v1_reply_surbs_serialised_len(surbs: &[ReplySurbWithKeyRotation]) -> usize { // sanity checks; this should probably be removed later on - if let Some(reply_surb) = surbs.first() { - if reply_surb.inner.surb.uses_key_seeds() { - error!("using v1 surbs encoding with updated structure - the surbs will be unusable") - } + if let Some(reply_surb) = surbs.first() + && reply_surb.inner.surb.uses_key_seeds() + { + error!("using v1 surbs encoding with updated structure - the surbs will be unusable") } // when serialising surbs are always prepended with u32-encoded count diff --git a/common/nymsphinx/anonymous-replies/src/requests/v2.rs b/common/nymsphinx/anonymous-replies/src/requests/v2.rs index 6ed60203b1..8d074cd9e5 100644 --- a/common/nymsphinx/anonymous-replies/src/requests/v2.rs +++ b/common/nymsphinx/anonymous-replies/src/requests/v2.rs @@ -35,10 +35,10 @@ fn v2_reply_surbs_serialised_len(surbs: &[ReplySurbWithKeyRotation]) -> usize { let num_hops = reply_surbs_hops(surbs); // sanity checks; this should probably be removed later on - if let Some(reply_surb) = surbs.first() { - if !reply_surb.inner.surb.uses_key_seeds() { - error!("using v2 surbs encoding with legacy structure - the surbs will be unusable") - } + if let Some(reply_surb) = surbs.first() + && !reply_surb.inner.surb.uses_key_seeds() + { + error!("using v2 surbs encoding with legacy structure - the surbs will be unusable") } // when serialising surbs are always prepended with: diff --git a/common/nymsphinx/chunking/src/fragment.rs b/common/nymsphinx/chunking/src/fragment.rs index 68419cac56..f823d9d3bc 100644 --- a/common/nymsphinx/chunking/src/fragment.rs +++ b/common/nymsphinx/chunking/src/fragment.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::ChunkingError; -use nym_sphinx_params::{SerializedFragmentIdentifier, FRAG_ID_LEN}; +use nym_sphinx_params::{FRAG_ID_LEN, SerializedFragmentIdentifier}; use serde::Serialize; use utoipa::ToSchema; @@ -381,15 +381,15 @@ impl FragmentHeader { if current_fragment == 0 { return Err(ChunkingError::MalformedHeaderError); } - if let Some(pfid) = previous_fragments_set_id { - if pfid <= 0 || current_fragment != 1 || pfid == id { - return Err(ChunkingError::MalformedHeaderError); - } + if let Some(pfid) = previous_fragments_set_id + && (pfid <= 0 || current_fragment != 1 || pfid == id) + { + return Err(ChunkingError::MalformedHeaderError); } - if let Some(nfid) = next_fragments_set_id { - if nfid <= 0 || current_fragment != total_fragments || nfid == id { - return Err(ChunkingError::MalformedHeaderError); - } + if let Some(nfid) = next_fragments_set_id + && (nfid <= 0 || current_fragment != total_fragments || nfid == id) + { + return Err(ChunkingError::MalformedHeaderError); } Ok(FragmentHeader { @@ -504,7 +504,7 @@ impl FragmentHeader { mod fragment_tests { use super::*; use nym_sphinx_params::packet_sizes::PacketSize; - use rand::{thread_rng, RngCore}; + use rand::{RngCore, thread_rng}; fn max_plaintext_size() -> usize { PacketSize::default().plaintext_size() - PacketSize::AckPacket.size() @@ -663,47 +663,55 @@ mod fragment_tests { Fragment::try_new(&full_payload, id, 1, 1, None, None, max_plaintext_size()).is_ok() ); - assert!(Fragment::try_new( - &non_full_payload, - id, - 10, - 10, - None, - None, - max_plaintext_size(), - ) - .is_ok()); - assert!(Fragment::try_new( - &non_full_payload, - id, - 1, - 1, - None, - None, - max_plaintext_size(), - ) - .is_ok()); + assert!( + Fragment::try_new( + &non_full_payload, + id, + 10, + 10, + None, + None, + max_plaintext_size(), + ) + .is_ok() + ); + assert!( + Fragment::try_new( + &non_full_payload, + id, + 1, + 1, + None, + None, + max_plaintext_size(), + ) + .is_ok() + ); - assert!(Fragment::try_new( - &non_full_payload2, - id, - 10, - 10, - None, - None, - max_plaintext_size(), - ) - .is_ok()); - assert!(Fragment::try_new( - &non_full_payload2, - id, - 1, - 1, - None, - None, - max_plaintext_size(), - ) - .is_ok()); + assert!( + Fragment::try_new( + &non_full_payload2, + id, + 10, + 10, + None, + None, + max_plaintext_size(), + ) + .is_ok() + ); + assert!( + Fragment::try_new( + &non_full_payload2, + id, + 1, + 1, + None, + None, + max_plaintext_size(), + ) + .is_ok() + ); } #[test] @@ -716,78 +724,92 @@ mod fragment_tests { let too_much_payload = vec![1u8; unlinked_fragment_payload_max_len(max_plaintext_size()) + 1]; - assert!(Fragment::try_new( - &non_full_payload, - id, - 10, - 1, - None, - None, - max_plaintext_size(), - ) - .is_err()); - assert!(Fragment::try_new( - &non_full_payload, - id, - 10, - 5, - None, - None, - max_plaintext_size(), - ) - .is_err()); + assert!( + Fragment::try_new( + &non_full_payload, + id, + 10, + 1, + None, + None, + max_plaintext_size(), + ) + .is_err() + ); + assert!( + Fragment::try_new( + &non_full_payload, + id, + 10, + 5, + None, + None, + max_plaintext_size(), + ) + .is_err() + ); - assert!(Fragment::try_new( - &too_much_payload, - id, - 10, - 1, - None, - None, - max_plaintext_size(), - ) - .is_err()); - assert!(Fragment::try_new( - &too_much_payload, - id, - 10, - 5, - None, - None, - max_plaintext_size(), - ) - .is_err()); - assert!(Fragment::try_new( - &too_much_payload, - id, - 1, - 1, - None, - None, - max_plaintext_size(), - ) - .is_err()); + assert!( + Fragment::try_new( + &too_much_payload, + id, + 10, + 1, + None, + None, + max_plaintext_size(), + ) + .is_err() + ); + assert!( + Fragment::try_new( + &too_much_payload, + id, + 10, + 5, + None, + None, + max_plaintext_size(), + ) + .is_err() + ); + assert!( + Fragment::try_new( + &too_much_payload, + id, + 1, + 1, + None, + None, + max_plaintext_size(), + ) + .is_err() + ); - assert!(Fragment::try_new( - &non_full_payload2, - id, - 10, - 1, - None, - None, - max_plaintext_size(), - ) - .is_err()); - assert!(Fragment::try_new( - &non_full_payload2, - id, - 10, - 5, - None, - None, - max_plaintext_size(), - ) - .is_err()); + assert!( + Fragment::try_new( + &non_full_payload2, + id, + 10, + 1, + None, + None, + max_plaintext_size(), + ) + .is_err() + ); + assert!( + Fragment::try_new( + &non_full_payload2, + id, + 10, + 5, + None, + None, + max_plaintext_size(), + ) + .is_err() + ); } #[test] @@ -799,57 +821,67 @@ mod fragment_tests { let non_full_payload2 = vec![1u8; linked_fragment_payload_max_len(max_plaintext_size()) - 20]; - assert!(Fragment::try_new( - &full_payload, - id, - 10, - 1, - Some(link_id), - None, - max_plaintext_size(), - ) - .is_ok()); - assert!(Fragment::try_new( - &full_payload, - id, - 1, - 1, - Some(link_id), - None, - max_plaintext_size(), - ) - .is_ok()); - assert!(Fragment::try_new( - &non_full_payload, - id, - 1, - 1, - Some(link_id), - None, - max_plaintext_size(), - ) - .is_ok()); - assert!(Fragment::try_new( - &non_full_payload2, - id, - 1, - 1, - Some(link_id), - None, - max_plaintext_size(), - ) - .is_ok()); + assert!( + Fragment::try_new( + &full_payload, + id, + 10, + 1, + Some(link_id), + None, + max_plaintext_size(), + ) + .is_ok() + ); + assert!( + Fragment::try_new( + &full_payload, + id, + 1, + 1, + Some(link_id), + None, + max_plaintext_size(), + ) + .is_ok() + ); + assert!( + Fragment::try_new( + &non_full_payload, + id, + 1, + 1, + Some(link_id), + None, + max_plaintext_size(), + ) + .is_ok() + ); + assert!( + Fragment::try_new( + &non_full_payload2, + id, + 1, + 1, + Some(link_id), + None, + max_plaintext_size(), + ) + .is_ok() + ); - assert!(Fragment::try_new( - &full_payload, - id, - u8::MAX, - u8::MAX, - None, - Some(link_id), - max_plaintext_size(), - ) - .is_ok()); + assert!( + Fragment::try_new( + &full_payload, + id, + u8::MAX, + u8::MAX, + None, + Some(link_id), + max_plaintext_size(), + ) + .is_ok() + ); } #[test] @@ -861,78 +893,92 @@ mod fragment_tests { vec![1u8; linked_fragment_payload_max_len(max_plaintext_size()) - 20]; let too_much_payload = vec![1u8; linked_fragment_payload_max_len(max_plaintext_size()) + 1]; - assert!(Fragment::try_new( - &non_full_payload, - id, - 10, - 1, - Some(link_id), - None, - max_plaintext_size(), - ) - .is_err()); - assert!(Fragment::try_new( - &non_full_payload2, - id, - 10, - 1, - Some(link_id), - None, - max_plaintext_size(), - ) - .is_err()); - assert!(Fragment::try_new( - &too_much_payload, - id, - 10, - 1, - Some(link_id), - None, - max_plaintext_size(), - ) - .is_err()); - assert!(Fragment::try_new( - &too_much_payload, - id, - 1, - 1, - Some(link_id), - None, - max_plaintext_size(), - ) - .is_err()); + assert!( + Fragment::try_new( + &non_full_payload, + id, + 10, + 1, + Some(link_id), + None, + max_plaintext_size(), + ) + .is_err() + ); + assert!( + Fragment::try_new( + &non_full_payload2, + id, + 10, + 1, + Some(link_id), + None, + max_plaintext_size(), + ) + .is_err() + ); + assert!( + Fragment::try_new( + &too_much_payload, + id, + 10, + 1, + Some(link_id), + None, + max_plaintext_size(), + ) + .is_err() + ); + assert!( + Fragment::try_new( + &too_much_payload, + id, + 1, + 1, + Some(link_id), + None, + max_plaintext_size(), + ) + .is_err() + ); - assert!(Fragment::try_new( - &non_full_payload, - id, - u8::MAX, - u8::MAX, - None, - Some(link_id), - max_plaintext_size(), - ) - .is_err()); - assert!(Fragment::try_new( - &non_full_payload2, - id, - u8::MAX, - u8::MAX, - None, - Some(link_id), - max_plaintext_size(), - ) - .is_err()); + assert!( + Fragment::try_new( + &non_full_payload, + id, + u8::MAX, + u8::MAX, + None, + Some(link_id), + max_plaintext_size(), + ) + .is_err() + ); + assert!( + Fragment::try_new( + &non_full_payload2, + id, + u8::MAX, + u8::MAX, + None, + Some(link_id), + max_plaintext_size(), + ) + .is_err() + ); - assert!(Fragment::try_new( - &too_much_payload, - id, - u8::MAX, - u8::MAX, - None, - Some(link_id), - max_plaintext_size(), - ) - .is_err()); + assert!( + Fragment::try_new( + &too_much_payload, + id, + u8::MAX, + u8::MAX, + None, + Some(link_id), + max_plaintext_size(), + ) + .is_err() + ); } } diff --git a/common/nymsphinx/chunking/src/lib.rs b/common/nymsphinx/chunking/src/lib.rs index 5a6e24633c..2bab3cd50c 100644 --- a/common/nymsphinx/chunking/src/lib.rs +++ b/common/nymsphinx/chunking/src/lib.rs @@ -31,8 +31,8 @@ pub mod monitoring { use crate::{ReceivedFragment, SentFragment}; use dashmap::DashMap; use nym_crypto::asymmetric::ed25519::PublicKey; - use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::LazyLock; + use std::sync::atomic::{AtomicBool, Ordering}; pub static ENABLED: AtomicBool = AtomicBool::new(false); @@ -192,7 +192,9 @@ pub enum ChunkingError { #[error("Provided header was malformed or contained self-contradicting fields")] MalformedHeaderError, - #[error("Received too few bytes to deserialize fragment header. Got {received}, expected {expected}")] + #[error( + "Received too few bytes to deserialize fragment header. Got {received}, expected {expected}" + )] TooShortFragmentHeader { received: usize, expected: usize }, #[error("Received fragment identifier ({received}) is not a valid value!")] diff --git a/common/nymsphinx/chunking/src/reconstruction.rs b/common/nymsphinx/chunking/src/reconstruction.rs index e189ad0725..f91461e543 100644 --- a/common/nymsphinx/chunking/src/reconstruction.rs +++ b/common/nymsphinx/chunking/src/reconstruction.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 use crate::fragment::Fragment; -use crate::{monitoring, ChunkingError}; +use crate::{ChunkingError, monitoring}; use log::*; use std::collections::HashMap; use std::time::Duration; @@ -549,7 +549,7 @@ mod message_reconstructor { use super::*; use crate::fragment::unlinked_fragment_payload_max_len; use crate::set::{max_one_way_linked_set_payload_length, two_way_linked_set_payload_length}; - use rand::{thread_rng, RngCore}; + use rand::{RngCore, thread_rng}; // just some arbitrary value to use in tests const AVAILABLE_PLAINTEXT_SIZE: usize = 1024; @@ -574,22 +574,26 @@ mod message_reconstructor { // first set is fully inserted for raw_fragment in raw_fragments.iter() { - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragment.clone()) - .unwrap() - ) - .is_none()) + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragment.clone()) + .unwrap() + ) + .is_none() + ) } - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[255].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[255].clone()) + .unwrap() + ) + .is_none() + ); let second_set_id = Fragment::try_from_bytes(&raw_fragments[255]).unwrap().id(); reconstructor.check_front_chain(second_set_id); @@ -610,30 +614,36 @@ mod message_reconstructor { .collect(); for raw_fragment in raw_fragments.iter().take(u8::MAX as usize) { - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragment.clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragment.clone()) + .unwrap() + ) + .is_none() + ); } // finish next set for good measure - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[255].clone()) - .unwrap() - ) - .is_none()); - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[256].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[255].clone()) + .unwrap() + ) + .is_none() + ); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[256].clone()) + .unwrap() + ) + .is_none() + ); let first_set_id = Fragment::try_from_bytes(&raw_fragments[0]).unwrap().id(); reconstructor.check_back_chain(first_set_id); @@ -658,29 +668,35 @@ mod message_reconstructor { // note that first set is not fully inserted for raw_fragment in raw_fragments.iter().take(u8::MAX as usize - 1) { - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragment.clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragment.clone()) + .unwrap() + ) + .is_none() + ); } - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[255].clone()) - .unwrap() - ) - .is_none()); - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[256].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[255].clone()) + .unwrap() + ) + .is_none() + ); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[256].clone()) + .unwrap() + ) + .is_none() + ); let second_set_id = Fragment::try_from_bytes(&raw_fragments[255]).unwrap().id(); assert!(!reconstructor.check_front_chain(second_set_id)); @@ -704,23 +720,27 @@ mod message_reconstructor { .collect(); for raw_fragment in raw_fragments.iter().take(u8::MAX as usize) { - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragment.clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragment.clone()) + .unwrap() + ) + .is_none() + ); } // notice that entirety of second set is not inserted - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[255].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[255].clone()) + .unwrap() + ) + .is_none() + ); let first_set_id = Fragment::try_from_bytes(&raw_fragments[0]).unwrap().id(); @@ -746,23 +766,27 @@ mod message_reconstructor { .collect(); for raw_fragment in raw_fragments.iter().take(u8::MAX as usize) { - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragment.clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragment.clone()) + .unwrap() + ) + .is_none() + ); } // notice that entirety of second set is not inserted - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[255].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[255].clone()) + .unwrap() + ) + .is_none() + ); let first_set_id = Fragment::try_from_bytes(&raw_fragments[0]).unwrap().id(); @@ -785,22 +809,26 @@ mod message_reconstructor { // note that first set is not fully inserted for raw_fragment in raw_fragments.iter().take(u8::MAX as usize - 1) { - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragment.clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragment.clone()) + .unwrap() + ) + .is_none() + ); } - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[255].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[255].clone()) + .unwrap() + ) + .is_none() + ); let second_set_id = Fragment::try_from_bytes(&raw_fragments[255]).unwrap().id(); assert!(reconstructor.check_back_chain(second_set_id)); @@ -826,23 +854,27 @@ mod message_reconstructor { .collect(); for raw_fragment in raw_fragments.iter().take(u8::MAX as usize * 2) { - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragment.clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragment.clone()) + .unwrap() + ) + .is_none() + ); } // notice that entirety of third set is not inserted - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[(u8::MAX as usize) * 2].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[(u8::MAX as usize) * 2].clone()) + .unwrap() + ) + .is_none() + ); let second_set_id = Fragment::try_from_bytes(&raw_fragments[300]).unwrap().id(); @@ -869,22 +901,26 @@ mod message_reconstructor { // note that first set is not fully inserted for raw_fragment in raw_fragments.iter().skip(1).take(u8::MAX as usize * 2 - 1) { - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragment.clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragment.clone()) + .unwrap() + ) + .is_none() + ); } - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[(u8::MAX as usize) * 2].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[(u8::MAX as usize) * 2].clone()) + .unwrap() + ) + .is_none() + ); let second_set_id = Fragment::try_from_bytes(&raw_fragments[300]).unwrap().id(); @@ -941,22 +977,26 @@ mod message_reconstructor { // note that first set is not fully inserted for raw_fragment in raw_fragments1.iter().take(u8::MAX as usize - 1) { - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragment.clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragment.clone()) + .unwrap() + ) + .is_none() + ); } - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments1[255].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments1[255].clone()) + .unwrap() + ) + .is_none() + ); let second_set_id = Fragment::try_from_bytes(&raw_fragments1[255]).unwrap().id(); assert!(reconstructor.find_starting_set_id(second_set_id).is_none()); @@ -975,23 +1015,27 @@ mod message_reconstructor { .collect(); for raw_fragment in raw_fragments2.iter().take(u8::MAX as usize) { - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragment.clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragment.clone()) + .unwrap() + ) + .is_none() + ); } // notice that entirety of second set is not inserted - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments2[255].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments2[255].clone()) + .unwrap() + ) + .is_none() + ); let second_set_id = Fragment::try_from_bytes(&raw_fragments2[255]).unwrap().id(); assert!(reconstructor.find_starting_set_id(second_set_id).is_none()); @@ -1015,23 +1059,27 @@ mod message_reconstructor { .collect(); for raw_fragment in raw_fragments.iter().take(u8::MAX as usize) { - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragment.clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragment.clone()) + .unwrap() + ) + .is_none() + ); } // notice that entirety of second set is not inserted - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[255].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[255].clone()) + .unwrap() + ) + .is_none() + ); let first_set_id = Fragment::try_from_bytes(&raw_fragments[0]).unwrap().id(); assert_eq!( @@ -1098,20 +1146,24 @@ mod message_reconstructor { .flat_map(|fragment_set| fragment_set.into_iter()) .map(|x| x.into_bytes()) .collect(); - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[0].clone()) - .unwrap() - ) - .is_none()); - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[1].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[0].clone()) + .unwrap() + ) + .is_none() + ); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[1].clone()) + .unwrap() + ) + .is_none() + ); let id = Fragment::try_from_bytes(&raw_fragments[0]).unwrap().id(); reconstructor.previous_linked_set_id(id); @@ -1156,20 +1208,24 @@ mod message_reconstructor { .flat_map(|fragment_set| fragment_set.into_iter()) .map(|x| x.into_bytes()) .collect(); - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[0].clone()) - .unwrap() - ) - .is_none()); - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[1].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[0].clone()) + .unwrap() + ) + .is_none() + ); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[1].clone()) + .unwrap() + ) + .is_none() + ); let id = Fragment::try_from_bytes(&raw_fragments[0]).unwrap().id(); reconstructor.next_linked_set_id(id); @@ -1214,20 +1270,24 @@ mod message_reconstructor { .flat_map(|fragment_set| fragment_set.into_iter()) .map(|x| x.into_bytes()) .collect(); - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[0].clone()) - .unwrap() - ) - .is_none()); - assert!(reconstructor - .insert_new_fragment( - reconstructor - .recover_fragment(raw_fragments[1].clone()) - .unwrap() - ) - .is_none()); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[0].clone()) + .unwrap() + ) + .is_none() + ); + assert!( + reconstructor + .insert_new_fragment( + reconstructor + .recover_fragment(raw_fragments[1].clone()) + .unwrap() + ) + .is_none() + ); let id = Fragment::try_from_bytes(&raw_fragments[0]).unwrap().id(); reconstructor.extract_set_payload(id); @@ -1299,8 +1359,8 @@ mod message_reconstructor { } #[test] - fn reconstructing_message_for_two_sets_is_equivalent_to_combining_results_of_extracting_set_payload( - ) { + fn reconstructing_message_for_two_sets_is_equivalent_to_combining_results_of_extracting_set_payload() + { // // we're inserting this via the buffer approach as not to trigger immediate re-assembly let mut reconstructor = MessageReconstructor::default(); @@ -1355,9 +1415,11 @@ mod message_reconstructor { #[test] fn adding_invalid_fragment_does_not_change_reconstructor_state() { let empty_reconstructor = MessageReconstructor::default(); - assert!(empty_reconstructor - .recover_fragment([24u8; 43].to_vec()) - .is_err()); + assert!( + empty_reconstructor + .recover_fragment([24u8; 43].to_vec()) + .is_err() + ); assert_eq!(empty_reconstructor, MessageReconstructor::default()); let mut reconstructor_with_data = MessageReconstructor::default(); @@ -1379,9 +1441,11 @@ mod message_reconstructor { ); let reconstructor_clone = reconstructor_with_data.clone(); - assert!(empty_reconstructor - .recover_fragment([24u8; 43].to_vec()) - .is_err()); + assert!( + empty_reconstructor + .recover_fragment([24u8; 43].to_vec()) + .is_err() + ); assert_eq!(reconstructor_with_data, reconstructor_clone); } } @@ -1390,7 +1454,7 @@ mod message_reconstructor { mod message_reconstruction { use super::*; use rand::seq::SliceRandom; - use rand::{thread_rng, RngCore}; + use rand::{RngCore, thread_rng}; // just some arbitrary value to use in tests const AVAILABLE_PLAINTEXT_SIZE: usize = 1024; @@ -1476,13 +1540,15 @@ mod message_reconstruction { assert_eq!(fragments.len(), 2); let mut message_reconstructor = MessageReconstructor::default(); - assert!(message_reconstructor - .insert_new_fragment( - message_reconstructor - .recover_fragment(fragments[0].clone()) - .unwrap() - ) - .is_none()); + assert!( + message_reconstructor + .insert_new_fragment( + message_reconstructor + .recover_fragment(fragments[0].clone()) + .unwrap() + ) + .is_none() + ); let reconstructed_message = message_reconstructor .insert_new_fragment( @@ -1513,13 +1579,15 @@ mod message_reconstruction { assert_eq!(fragments.len(), 2); let mut message_reconstructor = MessageReconstructor::default(); - assert!(message_reconstructor - .insert_new_fragment( - message_reconstructor - .recover_fragment(fragments[0].clone()) - .unwrap() - ) - .is_none()); + assert!( + message_reconstructor + .insert_new_fragment( + message_reconstructor + .recover_fragment(fragments[0].clone()) + .unwrap() + ) + .is_none() + ); let reconstructed_message = message_reconstructor .insert_new_fragment( @@ -1552,13 +1620,15 @@ mod message_reconstruction { let mut message_reconstructor = MessageReconstructor::default(); for fragment in fragments.iter().take(fragments.len() - 1) { - assert!(message_reconstructor - .insert_new_fragment( - message_reconstructor - .recover_fragment(fragment.clone()) - .unwrap() - ) - .is_none()); + assert!( + message_reconstructor + .insert_new_fragment( + message_reconstructor + .recover_fragment(fragment.clone()) + .unwrap() + ) + .is_none() + ); } let reconstructed_message = message_reconstructor @@ -1594,13 +1664,15 @@ mod message_reconstruction { let mut message_reconstructor = MessageReconstructor::default(); for fragment in fragments.iter().take(fragments.len() - 1) { - assert!(message_reconstructor - .insert_new_fragment( - message_reconstructor - .recover_fragment(fragment.clone()) - .unwrap() - ) - .is_none()); + assert!( + message_reconstructor + .insert_new_fragment( + message_reconstructor + .recover_fragment(fragment.clone()) + .unwrap() + ) + .is_none() + ); } let reconstructed_message = message_reconstructor diff --git a/common/nymsphinx/chunking/src/set.rs b/common/nymsphinx/chunking/src/set.rs index a694f608d6..dcfecf9bda 100644 --- a/common/nymsphinx/chunking/src/set.rs +++ b/common/nymsphinx/chunking/src/set.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use crate::fragment::{ - linked_fragment_payload_max_len, unlinked_fragment_payload_max_len, Fragment, - LINKED_FRAGMENTED_HEADER_LEN, UNLINKED_FRAGMENTED_HEADER_LEN, + Fragment, LINKED_FRAGMENTED_HEADER_LEN, UNLINKED_FRAGMENTED_HEADER_LEN, + linked_fragment_payload_max_len, unlinked_fragment_payload_max_len, }; use rand::Rng; @@ -70,7 +70,7 @@ pub(crate) type FragmentSet = Vec; /// `Fragment`s thus allowing for some additional optimizations by letting it skip /// certain procedures when reconstructing. pub(crate) fn generate_set_id(rng: &mut R) -> i32 { - let potential_id = rng.gen::(); + let potential_id = rng.r#gen::(); // make sure id is always non-zero, as we do not want to accidentally have weird // reconstruction cases where unfragmented payload overwrites some part of set with id0 // furthermore, make sure it's not i32::MIN (-2147483648) as due to 2-complement encoding, @@ -399,7 +399,7 @@ mod tests { mod preparing_unlinked_set { // remember this this is only called for a sole set with <= 255 fragments use super::*; - use rand::{thread_rng, RngCore}; + use rand::{RngCore, thread_rng}; #[test] fn makes_set_with_correctly_split_payload() { @@ -464,7 +464,7 @@ mod tests { #[cfg(test)] mod preparing_linked_set { use super::*; - use rand::{thread_rng, RngCore}; + use rand::{RngCore, thread_rng}; #[test] fn makes_set_with_correctly_split_payload_for_pre_linked_set() { @@ -644,7 +644,7 @@ mod tests { #[cfg(test)] mod splitting_into_sets { use super::*; - use rand::{thread_rng, RngCore}; + use rand::{RngCore, thread_rng}; #[test] fn correctly_creates_single_fragmented_set_when_expected() { @@ -661,8 +661,8 @@ mod tests { // a very specific test case that would have saved a lot of headache if was introduced // earlier... #[test] - fn correctly_creates_two_singly_linked_sets_with_second_set_containing_data_fitting_in_unfragmented_payload( - ) { + fn correctly_creates_two_singly_linked_sets_with_second_set_containing_data_fitting_in_unfragmented_payload() + { let mut rng = thread_rng(); let mut message = vec![0u8; max_one_way_linked_set_payload_length(max_plaintext_size()) + 123]; diff --git a/common/nymsphinx/cover/src/lib.rs b/common/nymsphinx/cover/src/lib.rs index 42be1db410..034fd71a1b 100644 --- a/common/nymsphinx/cover/src/lib.rs +++ b/common/nymsphinx/cover/src/lib.rs @@ -3,8 +3,8 @@ use nym_crypto::shared_key::new_ephemeral_shared_key; use nym_crypto::symmetric::stream_cipher; -use nym_sphinx_acknowledgements::surb_ack::{SurbAck, SurbAckRecoveryError}; use nym_sphinx_acknowledgements::AckKey; +use nym_sphinx_acknowledgements::surb_ack::{SurbAck, SurbAckRecoveryError}; use nym_sphinx_addressing::clients::Recipient; use nym_sphinx_addressing::nodes::NymNodeRoutingAddress; use nym_sphinx_chunking::fragment::COVER_FRAG_ID; diff --git a/common/nymsphinx/framing/src/codec.rs b/common/nymsphinx/framing/src/codec.rs index da148908e4..9cb6328cfe 100644 --- a/common/nymsphinx/framing/src/codec.rs +++ b/common/nymsphinx/framing/src/codec.rs @@ -3,11 +3,11 @@ use crate::packet::{FramedNymPacket, Header}; use bytes::{Buf, BufMut, BytesMut}; +use nym_sphinx_params::PacketType; use nym_sphinx_params::key_rotation::InvalidSphinxKeyRotation; use nym_sphinx_params::packet_sizes::{InvalidPacketSize, PacketSize}; use nym_sphinx_params::packet_types::InvalidPacketType; use nym_sphinx_params::packet_version::{InvalidPacketVersion, PacketVersion}; -use nym_sphinx_params::PacketType; use nym_sphinx_types::{NymPacket, NymPacketError}; use std::io; use thiserror::Error; @@ -143,13 +143,13 @@ impl Decoder for NymCodec { #[cfg(test)] mod packet_encoding { use super::*; + use nym_sphinx_params::PacketType; use nym_sphinx_params::packet_version::{ CURRENT_PACKET_VERSION, INITIAL_PACKET_VERSION_NUMBER, }; - use nym_sphinx_params::PacketType; use nym_sphinx_types::{ - Delay as SphinxDelay, Destination, DestinationAddressBytes, Node, NodeAddressBytes, - NymPacket, PrivateKey, DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, NODE_ADDRESS_LENGTH, + DESTINATION_ADDRESS_LENGTH, Delay as SphinxDelay, Destination, DestinationAddressBytes, + IDENTIFIER_LENGTH, NODE_ADDRESS_LENGTH, Node, NodeAddressBytes, NymPacket, PrivateKey, }; fn dummy_header() -> Header { diff --git a/common/nymsphinx/framing/src/packet.rs b/common/nymsphinx/framing/src/packet.rs index f8b86b7988..b320483270 100644 --- a/common/nymsphinx/framing/src/packet.rs +++ b/common/nymsphinx/framing/src/packet.rs @@ -4,12 +4,12 @@ use crate::codec::NymCodecError; use bytes::{BufMut, BytesMut}; use nym_sphinx_forwarding::packet::MixPacket; +use nym_sphinx_params::PacketType; use nym_sphinx_params::key_rotation::SphinxKeyRotation; use nym_sphinx_params::packet_sizes::PacketSize; use nym_sphinx_params::packet_version::{ - PacketVersion, CURRENT_PACKET_VERSION, LEGACY_PACKET_VERSION, + CURRENT_PACKET_VERSION, LEGACY_PACKET_VERSION, PacketVersion, }; -use nym_sphinx_params::PacketType; use nym_sphinx_types::NymPacket; #[derive(Debug)] diff --git a/common/nymsphinx/framing/src/processing.rs b/common/nymsphinx/framing/src/processing.rs index 3703f36d84..d647543d6a 100644 --- a/common/nymsphinx/framing/src/processing.rs +++ b/common/nymsphinx/framing/src/processing.rs @@ -10,7 +10,7 @@ use nym_sphinx_types::header::shared_secret::ExpandedSharedSecret; use nym_sphinx_types::{ Delay as SphinxDelay, DestinationAddressBytes, NodeAddressBytes, NymPacket, NymPacketError, NymProcessedPacket, OutfoxError, OutfoxProcessedPacket, PrivateKey, ProcessedPacketData, - SphinxError, Version as SphinxPacketVersion, REPLAY_TAG_SIZE, + REPLAY_TAG_SIZE, SphinxError, Version as SphinxPacketVersion, }; use std::fmt::Display; use thiserror::Error; diff --git a/common/nymsphinx/params/src/lib.rs b/common/nymsphinx/params/src/lib.rs index 9046425a40..120c7647dd 100644 --- a/common/nymsphinx/params/src/lib.rs +++ b/common/nymsphinx/params/src/lib.rs @@ -1,10 +1,10 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use nym_crypto::Aes256GcmSiv; use nym_crypto::aes::Aes128; use nym_crypto::blake3; use nym_crypto::ctr; -use nym_crypto::Aes256GcmSiv; type Aes128Ctr = ctr::Ctr64BE; diff --git a/common/nymsphinx/params/src/packet_sizes.rs b/common/nymsphinx/params/src/packet_sizes.rs index f4d27ab8be..a3a5841193 100644 --- a/common/nymsphinx/params/src/packet_sizes.rs +++ b/common/nymsphinx/params/src/packet_sizes.rs @@ -2,10 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 use crate::PacketType; -#[cfg(feature = "sphinx")] -use nym_sphinx_types::{header::HEADER_SIZE, PAYLOAD_OVERHEAD_SIZE}; #[cfg(feature = "outfox")] use nym_sphinx_types::{MIN_PACKET_SIZE, MIX_PARAMS_LEN, OUTFOX_PACKET_OVERHEAD}; +#[cfg(feature = "sphinx")] +use nym_sphinx_types::{PAYLOAD_OVERHEAD_SIZE, header::HEADER_SIZE}; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; diff --git a/common/nymsphinx/routing/src/lib.rs b/common/nymsphinx/routing/src/lib.rs index b468fd9754..bbdd7ebd0e 100644 --- a/common/nymsphinx/routing/src/lib.rs +++ b/common/nymsphinx/routing/src/lib.rs @@ -1,7 +1,7 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use nym_sphinx_types::{delays, Delay}; +use nym_sphinx_types::{Delay, delays}; use std::time::Duration; use thiserror::Error; diff --git a/common/nymsphinx/src/message.rs b/common/nymsphinx/src/message.rs index b1066fd872..ebbc94d885 100644 --- a/common/nymsphinx/src/message.rs +++ b/common/nymsphinx/src/message.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use crate::chunking; -use nym_crypto::asymmetric::x25519; use nym_crypto::Digest; +use nym_crypto::asymmetric::x25519; use nym_sphinx_addressing::clients::Recipient; use nym_sphinx_addressing::nodes::MAX_NODE_ADDRESS_UNPADDED_LEN; use nym_sphinx_anonymous_replies::requests::{ diff --git a/common/nymsphinx/src/preparer/mod.rs b/common/nymsphinx/src/preparer/mod.rs index 038f1c4b7a..862612f8b4 100644 --- a/common/nymsphinx/src/preparer/mod.rs +++ b/common/nymsphinx/src/preparer/mod.rs @@ -1,12 +1,12 @@ // Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::message::{NymMessage, ACK_OVERHEAD, OUTFOX_ACK_OVERHEAD}; use crate::NymPayloadBuilder; -use nym_crypto::asymmetric::x25519; +use crate::message::{ACK_OVERHEAD, NymMessage, OUTFOX_ACK_OVERHEAD}; use nym_crypto::Digest; -use nym_sphinx_acknowledgements::surb_ack::SurbAck; +use nym_crypto::asymmetric::x25519; use nym_sphinx_acknowledgements::AckKey; +use nym_sphinx_acknowledgements::surb_ack::SurbAck; use nym_sphinx_addressing::clients::Recipient; use nym_sphinx_addressing::nodes::NymNodeRoutingAddress; use nym_sphinx_anonymous_replies::reply_surb::ReplySurb; @@ -355,7 +355,7 @@ where disable_mix_hops: bool, ) -> Self { let mut rng = rng; - let nonce = rng.gen(); + let nonce = rng.r#gen(); MessagePreparer { rng, deterministic_route_selection, diff --git a/common/nymsphinx/src/receiver.rs b/common/nymsphinx/src/receiver.rs index d99637c88b..eb83ec43ea 100644 --- a/common/nymsphinx/src/receiver.rs +++ b/common/nymsphinx/src/receiver.rs @@ -7,11 +7,11 @@ use nym_crypto::asymmetric::x25519; use nym_crypto::shared_key::recompute_shared_key; use nym_crypto::symmetric::stream_cipher; use nym_crypto::symmetric::stream_cipher::CipherKey; -use nym_sphinx_anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx_anonymous_replies::SurbEncryptionKey; +use nym_sphinx_anonymous_replies::requests::AnonymousSenderTag; +use nym_sphinx_chunking::ChunkingError; use nym_sphinx_chunking::fragment::Fragment; use nym_sphinx_chunking::reconstruction::MessageReconstructor; -use nym_sphinx_chunking::ChunkingError; use nym_sphinx_params::{ PacketEncryptionAlgorithm, PacketHkdfAlgorithm, ReplySurbEncryptionAlgorithm, }; @@ -58,7 +58,9 @@ impl From for ReconstructedMessage { #[derive(Debug, Error)] pub enum MessageRecoveryError { - #[error("The received message did not contain enough bytes to recover the ephemeral public key. Got {provided}. required: {required}")] + #[error( + "The received message did not contain enough bytes to recover the ephemeral public key. Got {provided}. required: {required}" + )] NotEnoughBytesForEphemeralKey { provided: usize, required: usize }, #[error("Recovered remote x25519 public key is invalid - {0}")] diff --git a/common/nymsphinx/types/src/lib.rs b/common/nymsphinx/types/src/lib.rs index aa1a82b848..1f3010b2f1 100644 --- a/common/nymsphinx/types/src/lib.rs +++ b/common/nymsphinx/types/src/lib.rs @@ -19,21 +19,21 @@ pub use nym_outfox::{ #[cfg(feature = "sphinx")] pub use sphinx_packet::{ + Error as SphinxError, ProcessedPacket, ProcessedPacketData, constants::{ self, DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, MAX_PATH_LENGTH, NODE_ADDRESS_LENGTH, PAYLOAD_KEY_SIZE, REPLAY_TAG_SIZE, }, crypto::{self, PrivateKey, PublicKey}, - header::{self, delays, delays::Delay, ProcessedHeader, SphinxHeader, HEADER_SIZE}, + header::{self, HEADER_SIZE, ProcessedHeader, SphinxHeader, delays, delays::Delay}, packet::builder::DEFAULT_PAYLOAD_SIZE, payload::{ + PAYLOAD_OVERHEAD_SIZE, Payload, key::{PayloadKey, PayloadKeySeed}, - Payload, PAYLOAD_OVERHEAD_SIZE, }, route::{Destination, DestinationAddressBytes, Node, NodeAddressBytes, SURBIdentifier}, - surb::{SURBMaterial, SURB}, + surb::{SURB, SURBMaterial}, version::*, - Error as SphinxError, ProcessedPacket, ProcessedPacketData, }; #[derive(Error, Debug)] diff --git a/common/nyxd-scraper/src/block_processor/mod.rs b/common/nyxd-scraper/src/block_processor/mod.rs index d4007de96b..a99bc1c21f 100644 --- a/common/nyxd-scraper/src/block_processor/mod.rs +++ b/common/nyxd-scraper/src/block_processor/mod.rs @@ -1,23 +1,23 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::PruningOptions; use crate::block_processor::helpers::split_request_range; use crate::block_processor::types::BlockToProcess; use crate::block_requester::BlockRequest; use crate::error::ScraperError; use crate::modules::{BlockModule, MsgModule, TxModule}; use crate::rpc_client::RpcClient; -use crate::storage::{persist_block, ScraperStorage}; -use crate::PruningOptions; +use crate::storage::{ScraperStorage, persist_block}; use futures::StreamExt; use std::cmp::max; use std::collections::{BTreeMap, HashSet, VecDeque}; use std::ops::{Add, Range}; use std::sync::Arc; use std::time::Duration; -use tokio::sync::mpsc::{Sender, UnboundedReceiver}; use tokio::sync::Notify; -use tokio::time::{interval_at, Instant}; +use tokio::sync::mpsc::{Sender, UnboundedReceiver}; +use tokio::time::{Instant, interval_at}; use tokio_stream::wrappers::UnboundedReceiverStream; use tokio_util::sync::CancellationToken; use tracing::{debug, error, info, instrument, trace, warn}; diff --git a/common/nyxd-scraper/src/block_processor/types.rs b/common/nyxd-scraper/src/block_processor/types.rs index 6909ff32a0..1c456b9318 100644 --- a/common/nyxd-scraper/src/block_processor/types.rs +++ b/common/nyxd-scraper/src/block_processor/types.rs @@ -3,7 +3,7 @@ use crate::error::ScraperError; use crate::helpers; -use tendermint::{abci, block, tx, Block, Hash}; +use tendermint::{Block, Hash, abci, block, tx}; use tendermint_rpc::endpoint::{block as block_endpoint, block_results, validators}; use tendermint_rpc::event::{Event, EventData}; @@ -90,13 +90,13 @@ impl TryFrom for BlockToProcess { return Err(ScraperError::InvalidSubscriptionEvent { query, kind: "Tx".to_string(), - }) + }); } EventData::GenericJsonEvent(_) => { return Err(ScraperError::InvalidSubscriptionEvent { query, kind: "GenericJsonEvent".to_string(), - }) + }); } }; diff --git a/common/nyxd-scraper/src/error.rs b/common/nyxd-scraper/src/error.rs index 9f9bfd12d2..d9dd359f6a 100644 --- a/common/nyxd-scraper/src/error.rs +++ b/common/nyxd-scraper/src/error.rs @@ -92,7 +92,9 @@ pub enum ScraperError { source: cosmrs::ErrorReport, }, - #[error("received an invalid chain subscription event of kind {kind} while we were waiting for new block data (query: '{query}')")] + #[error( + "received an invalid chain subscription event of kind {kind} while we were waiting for new block data (query: '{query}')" + )] InvalidSubscriptionEvent { query: String, kind: String }, #[error("received block data was empty (query: '{query}')")] @@ -138,13 +140,21 @@ pub enum ScraperError { )] MissingValidatorInfoCommitted { address: String }, - #[error("pruning.interval must not be set to 0. If you want to disable pruning, select pruning.strategy = \"nothing\"")] + #[error( + "pruning.interval must not be set to 0. If you want to disable pruning, select pruning.strategy = \"nothing\"" + )] ZeroPruningInterval, - #[error("pruning.interval must not be smaller than {}. got: {interval}. for most aggressive pruning, select pruning.strategy = \"everything\"", EVERYTHING_PRUNING_INTERVAL)] + #[error( + "pruning.interval must not be smaller than {}. got: {interval}. for most aggressive pruning, select pruning.strategy = \"everything\"", + EVERYTHING_PRUNING_INTERVAL + )] TooSmallPruningInterval { interval: u32 }, - #[error("pruning.keep_recent must not be smaller than {}. got: {keep_recent}. for most aggressive pruning, select pruning.strategy = \"everything\"", EVERYTHING_PRUNING_KEEP_RECENT)] + #[error( + "pruning.keep_recent must not be smaller than {}. got: {keep_recent}. for most aggressive pruning, select pruning.strategy = \"everything\"", + EVERYTHING_PRUNING_KEEP_RECENT + )] TooSmallKeepRecent { keep_recent: u32 }, } diff --git a/common/nyxd-scraper/src/helpers.rs b/common/nyxd-scraper/src/helpers.rs index d11b25a2f3..44bef81b89 100644 --- a/common/nyxd-scraper/src/helpers.rs +++ b/common/nyxd-scraper/src/helpers.rs @@ -6,8 +6,8 @@ use crate::constants::{BECH32_CONESNSUS_PUBKEY_PREFIX, BECH32_CONSENSUS_ADDRESS_ use crate::error::ScraperError; use cosmrs::AccountId; use sha2::{Digest, Sha256}; -use tendermint::{account, PublicKey}; -use tendermint::{validator, Hash}; +use tendermint::{Hash, validator}; +use tendermint::{PublicKey, account}; use tendermint_rpc::endpoint::validators; pub(crate) fn tx_hash>(raw_tx: M) -> Hash { diff --git a/common/nyxd-scraper/src/rpc_client.rs b/common/nyxd-scraper/src/rpc_client.rs index b20a89a098..5a3621abd4 100644 --- a/common/nyxd-scraper/src/rpc_client.rs +++ b/common/nyxd-scraper/src/rpc_client.rs @@ -6,8 +6,8 @@ use crate::block_processor::types::{ }; use crate::error::ScraperError; use crate::helpers::tx_hash; -use futures::future::join3; use futures::StreamExt; +use futures::future::join3; use std::collections::BTreeMap; use std::sync::Arc; use tendermint::Hash; diff --git a/common/nyxd-scraper/src/scraper/mod.rs b/common/nyxd-scraper/src/scraper/mod.rs index 71cb535645..5d067044da 100644 --- a/common/nyxd-scraper/src/scraper/mod.rs +++ b/common/nyxd-scraper/src/scraper/mod.rs @@ -1,6 +1,7 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::PruningOptions; use crate::block_processor::types::BlockToProcess; use crate::block_processor::{BlockProcessor, BlockProcessorConfig}; use crate::block_requester::{BlockRequest, BlockRequester}; @@ -9,14 +10,13 @@ use crate::modules::{BlockModule, MsgModule, TxModule}; use crate::rpc_client::RpcClient; use crate::scraper::subscriber::ChainSubscriber; use crate::storage::ScraperStorage; -use crate::PruningOptions; use futures::future::join_all; use std::path::PathBuf; use std::sync::Arc; -use tokio::sync::mpsc::{ - channel, unbounded_channel, Receiver, Sender, UnboundedReceiver, UnboundedSender, -}; use tokio::sync::Notify; +use tokio::sync::mpsc::{ + Receiver, Sender, UnboundedReceiver, UnboundedSender, channel, unbounded_channel, +}; use tokio_util::sync::CancellationToken; use tokio_util::task::TaskTracker; use tracing::{error, info}; diff --git a/common/nyxd-scraper/src/scraper/subscriber.rs b/common/nyxd-scraper/src/scraper/subscriber.rs index f3a9411647..ec8acfbf27 100644 --- a/common/nyxd-scraper/src/scraper/subscriber.rs +++ b/common/nyxd-scraper/src/scraper/subscriber.rs @@ -98,7 +98,9 @@ impl ChainSubscriber { /// Returns whether the method exited due to the cancellation async fn run_chain_subscription(&mut self) -> Result { let Some(ws_driver) = self.websocket_driver.take() else { - error!("the websocket driver hasn't been created - we probably failed to establish the connection"); + error!( + "the websocket driver hasn't been created - we probably failed to establish the connection" + ); return Ok(false); }; @@ -206,7 +208,9 @@ impl ChainSubscriber { } } - warn!("current socket failure count: {socket_failures}. the last failure was at {last_failure}"); + warn!( + "current socket failure count: {socket_failures}. the last failure was at {last_failure}" + ); let now = OffsetDateTime::now_utc(); diff --git a/common/nyxd-scraper/src/storage/mod.rs b/common/nyxd-scraper/src/storage/mod.rs index e1ff17e5a6..2f0a0a8660 100644 --- a/common/nyxd-scraper/src/storage/mod.rs +++ b/common/nyxd-scraper/src/storage/mod.rs @@ -6,22 +6,22 @@ use crate::{ error::ScraperError, storage::{ manager::{ - insert_block, insert_message, insert_precommit, insert_transaction, insert_validator, - prune_blocks, prune_messages, prune_pre_commits, prune_transactions, - update_last_processed, update_last_pruned, StorageManager, + StorageManager, insert_block, insert_message, insert_precommit, insert_transaction, + insert_validator, prune_blocks, prune_messages, prune_pre_commits, prune_transactions, + update_last_processed, update_last_pruned, }, models::{CommitSignature, Validator}, }, }; use sqlx::{ + ConnectOptions, Sqlite, Transaction, sqlite::{SqliteAutoVacuum, SqliteSynchronous}, types::time::OffsetDateTime, - ConnectOptions, Sqlite, Transaction, }; use std::{fmt::Debug, path::Path}; use tendermint::{ - block::{Commit, CommitSig}, Block, + block::{Commit, CommitSig}, }; use tendermint_rpc::endpoint::validators; use tokio::time::Instant; diff --git a/common/nyxd-scraper/src/storage/models.rs b/common/nyxd-scraper/src/storage/models.rs index 74a3dd9b1c..6c4c16c633 100644 --- a/common/nyxd-scraper/src/storage/models.rs +++ b/common/nyxd-scraper/src/storage/models.rs @@ -1,8 +1,8 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use sqlx::types::time::OffsetDateTime; use sqlx::FromRow; +use sqlx::types::time::OffsetDateTime; #[derive(Debug, Clone, Eq, PartialEq, Hash, FromRow)] pub struct Validator { diff --git a/common/pemstore/src/lib.rs b/common/pemstore/src/lib.rs index 91edc5fef5..0b2abd7b10 100644 --- a/common/pemstore/src/lib.rs +++ b/common/pemstore/src/lib.rs @@ -109,6 +109,8 @@ fn read_pem_file>(filepath: P) -> io::Result { fn write_pem_file>(filepath: P, mut data: Vec, tag: &str) -> io::Result<()> { // ensure the whole directory structure exists + // don't use nested if else due to contracts still being on 2021 and this code being pulled in indirectly in tests + #[allow(clippy::collapsible_if)] if let Some(parent_dir) = filepath.as_ref().parent() { if let Err(err) = std::fs::create_dir_all(parent_dir) { // in case of a failure, make sure to zeroize the data before returning diff --git a/common/serde-helpers/src/lib.rs b/common/serde-helpers/src/lib.rs index 07ad83face..3b5ec767fd 100644 --- a/common/serde-helpers/src/lib.rs +++ b/common/serde-helpers/src/lib.rs @@ -3,7 +3,7 @@ #[cfg(feature = "base64")] pub mod base64 { - use base64::{engine::general_purpose::STANDARD, Engine as _}; + use base64::{Engine as _, engine::general_purpose::STANDARD}; use serde::{Deserialize, Deserializer, Serializer}; pub fn serialize(bytes: &[u8], serializer: S) -> Result { @@ -49,9 +49,9 @@ pub mod hex { #[cfg(feature = "date")] pub mod date { use serde::ser::Error; - use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; - use time::format_description::{modifier, BorrowedFormatItem, Component}; + use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; use time::Date; + use time::format_description::{BorrowedFormatItem, Component, modifier}; // simple YYYY-MM-DD pub const DATE_FORMAT: &[BorrowedFormatItem<'_>] = &[ diff --git a/common/statistics/src/clients/mod.rs b/common/statistics/src/clients/mod.rs index 3c2badcdfe..a174605eb4 100644 --- a/common/statistics/src/clients/mod.rs +++ b/common/statistics/src/clients/mod.rs @@ -42,12 +42,11 @@ impl ClientStatsSender { /// Report a statistics event using the sender. pub fn report(&self, event: ClientStatsEvents) { - if let Some(tx) = &self.stats_tx { - if let Err(err) = tx.send(event) { - if !self.shutdown_token.is_cancelled() { - log::error!("Failed to send stats event: {err}"); - } - } + if let Some(tx) = &self.stats_tx + && let Err(err) = tx.send(event) + && !self.shutdown_token.is_cancelled() + { + log::error!("Failed to send stats event: {err}"); } } } diff --git a/common/task/src/cancellation/manager.rs b/common/task/src/cancellation/manager.rs index f2cf5a9d02..c90aa4175d 100644 --- a/common/task/src/cancellation/manager.rs +++ b/common/task/src/cancellation/manager.rs @@ -1,11 +1,11 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::ShutdownToken; use crate::cancellation::tracker::{Cancelled, ShutdownTracker}; use crate::spawn::JoinHandle; -use crate::ShutdownToken; -use futures::stream::FuturesUnordered; use futures::StreamExt; +use futures::stream::FuturesUnordered; use log::error; use std::future::Future; use std::mem; @@ -20,7 +20,7 @@ use tokio::time::sleep; use wasmtimer::tokio::sleep; #[cfg(unix)] -use tokio::signal::unix::{signal, SignalKind}; +use tokio::signal::unix::{SignalKind, signal}; use tokio::task::JoinSet; /// A top level structure responsible for controlling process shutdown by listening to @@ -588,8 +588,8 @@ impl ShutdownManager { mod tests { use super::*; use nym_test_utils::traits::{ElapsedExt, Timeboxed}; - use std::sync::atomic::AtomicBool; use std::sync::Arc; + use std::sync::atomic::AtomicBool; #[tokio::test] async fn shutdown_with_no_tracked_tasks_and_signals() -> anyhow::Result<()> { diff --git a/common/task/src/cancellation/tracker.rs b/common/task/src/cancellation/tracker.rs index 12e2538dee..1d6b4c605c 100644 --- a/common/task/src/cancellation/tracker.rs +++ b/common/task/src/cancellation/tracker.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::cancellation::token::ShutdownToken; -use crate::spawn::{spawn_named_future, JoinHandle}; +use crate::spawn::{JoinHandle, spawn_named_future}; use crate::spawn_future; use std::future::Future; use thiserror::Error; diff --git a/common/task/src/manager.rs b/common/task/src/manager.rs index 5a6d22bfb6..664ac5d5ce 100644 --- a/common/task/src/manager.rs +++ b/common/task/src/manager.rs @@ -7,8 +7,8 @@ use std::{ time::Duration, }; -use futures::{future::pending, FutureExt, SinkExt, StreamExt}; -use log::{log, Level}; +use futures::{FutureExt, SinkExt, StreamExt, future::pending}; +use log::{Level, log}; use tokio::sync::{ mpsc, watch::{self, error::SendError}, diff --git a/common/task/src/signal.rs b/common/task/src/signal.rs index a8d7f6865d..fa255b7a1a 100644 --- a/common/task/src/signal.rs +++ b/common/task/src/signal.rs @@ -3,7 +3,7 @@ use crate::manager::SentError; #[cfg(unix)] #[allow(clippy::expect_used)] pub async fn wait_for_signal() { - use tokio::signal::unix::{signal, SignalKind}; + use tokio::signal::unix::{SignalKind, signal}; let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM channel"); let mut sigquit = signal(SignalKind::quit()).expect("Failed to setup SIGQUIT channel"); @@ -33,7 +33,7 @@ pub async fn wait_for_signal() { #[cfg(unix)] #[allow(clippy::expect_used)] pub async fn wait_for_signal_and_error(shutdown: &mut crate::TaskManager) -> Result<(), SentError> { - use tokio::signal::unix::{signal, SignalKind}; + use tokio::signal::unix::{SignalKind, signal}; let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM channel"); let mut sigquit = signal(SignalKind::quit()).expect("Failed to setup SIGQUIT channel"); diff --git a/common/task/src/spawn.rs b/common/task/src/spawn.rs index 8929bf2a2b..d8e7c0d3b1 100644 --- a/common/task/src/spawn.rs +++ b/common/task/src/spawn.rs @@ -70,10 +70,6 @@ where #[macro_export] macro_rules! spawn_future { - ($future:expr) => {{ - $crate::spawn_future($future) - }}; - ($future:expr, $name:expr) => {{ - $crate::spawn_named_future($future, $name) - }}; + ($future:expr) => {{ $crate::spawn_future($future) }}; + ($future:expr, $name:expr) => {{ $crate::spawn_named_future($future, $name) }}; } diff --git a/common/test-utils/src/helpers.rs b/common/test-utils/src/helpers.rs index 26dd19f3b1..f157ba88a7 100644 --- a/common/test-utils/src/helpers.rs +++ b/common/test-utils/src/helpers.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use crate::traits::Timeboxed; -use rand_chacha::rand_core::SeedableRng; use rand_chacha::ChaCha20Rng; +use rand_chacha::rand_core::SeedableRng; use std::future::Future; use tokio::task::JoinHandle; use tokio::time::error::Elapsed; diff --git a/common/test-utils/src/mocks/shared.rs b/common/test-utils/src/mocks/shared.rs index c760cd9b5d..ab8dcb8eeb 100644 --- a/common/test-utils/src/mocks/shared.rs +++ b/common/test-utils/src/mocks/shared.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use futures::future::BoxFuture; -use futures::{ready, FutureExt}; +use futures::{FutureExt, ready}; use std::mem; use std::pin::Pin; use std::sync::Arc; diff --git a/common/test-utils/src/mocks/stream_sink.rs b/common/test-utils/src/mocks/stream_sink.rs index 0cd866092e..b6d248689b 100644 --- a/common/test-utils/src/mocks/stream_sink.rs +++ b/common/test-utils/src/mocks/stream_sink.rs @@ -3,7 +3,7 @@ use crate::mocks::shared::{ContentWrapper, InnerWrapper}; use anyhow::{anyhow, bail}; -use futures::{ready, Sink, Stream}; +use futures::{Sink, Stream, ready}; use std::collections::VecDeque; use std::pin::Pin; use std::sync::Arc; diff --git a/common/ticketbooks-merkle/src/lib.rs b/common/ticketbooks-merkle/src/lib.rs index ba7b2dc88f..907b2e1b3e 100644 --- a/common/ticketbooks-merkle/src/lib.rs +++ b/common/ticketbooks-merkle/src/lib.rs @@ -241,9 +241,9 @@ impl IssuedTicketbooksFullMerkleProof { } mod inner_proof_base64_serde { + use rs_merkle::MerkleProof; use rs_merkle::algorithms::Sha256; use rs_merkle::proof_serializers::DirectHashesOrder; - use rs_merkle::MerkleProof; use serde::{Deserializer, Serializer}; pub fn serialize( diff --git a/common/topology/src/error.rs b/common/topology/src/error.rs index 36896effa3..8350baaa94 100644 --- a/common/topology/src/error.rs +++ b/common/topology/src/error.rs @@ -10,13 +10,17 @@ use thiserror::Error; #[derive(Debug, Error)] pub enum NymTopologyError { - #[error("the provided network topology is empty - there are no valid nodes on it - the network request(s) probably failed")] + #[error( + "the provided network topology is empty - there are no valid nodes on it - the network request(s) probably failed" + )] EmptyNetworkTopology, #[error("no node with identity {node_identity} is known")] NonExistentNode { node_identity: Box }, - #[error("could not use node with identity {node_identity} as egress since it didn't get assigned valid role in the current epoch")] + #[error( + "could not use node with identity {node_identity} as egress since it didn't get assigned valid role in the current epoch" + )] InvalidEgressRole { node_identity: Box }, #[error("one (or more) of mixing layers does not have any valid nodes available")] @@ -34,13 +38,17 @@ pub enum NymTopologyError { #[error("timed out while waiting for gateway '{identity_key}' to come online")] TimedOutWaitingForGateway { identity_key: String }, - #[error("Wanted to create a mix route with {requested} hops, while only {available} layers are available")] + #[error( + "Wanted to create a mix route with {requested} hops, while only {available} layers are available" + )] InvalidNumberOfHopsError { available: usize, requested: usize }, #[error("No mixnodes available on layer {layer}")] EmptyMixLayer { layer: MixLayer }, - #[error("Uneven layer distribution. Layer {layer} has {nodes} on it, while we expected a value between {lower_bound} and {upper_bound} as we have {total_nodes} nodes in total. Full breakdown: {layer_distribution:?}")] + #[error( + "Uneven layer distribution. Layer {layer} has {nodes} on it, while we expected a value between {lower_bound} and {upper_bound} as we have {total_nodes} nodes in total. Full breakdown: {layer_distribution:?}" + )] UnevenLayerDistribution { layer: MixLayer, nodes: usize, diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index b6d95e356e..d69897d83b 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -492,14 +492,13 @@ impl NymTopology { }; // a 'valid' egress is one that is currently **not** acting as a mixnode - if !ignore_epoch_roles { - if let Some(role) = self.rewarded_set.role(node.node_id) { - if role.is_mixnode() { - return Err(NymTopologyError::InvalidEgressRole { - node_identity: Box::new(node_identity), - }); - } - } + if !ignore_epoch_roles + && let Some(role) = self.rewarded_set.role(node.node_id) + && role.is_mixnode() + { + return Err(NymTopologyError::InvalidEgressRole { + node_identity: Box::new(node_identity), + }); } Ok(node) @@ -603,7 +602,9 @@ impl NymTopology { Role::Layer3 => self.rewarded_set.layer3 = init_set(node_id), Role::ExitGateway => self.rewarded_set.exit_gateways = init_set(node_id), Role::Standby => { - warn!("attempting to test node in 'standby' mode - are you sure that's what you meant to do?"); + warn!( + "attempting to test node in 'standby' mode - are you sure that's what you meant to do?" + ); self.rewarded_set.standby = init_set(node_id) } } diff --git a/common/topology/src/node.rs b/common/topology/src/node.rs index 47193e6438..c542d93e04 100644 --- a/common/topology/src/node.rs +++ b/common/topology/src/node.rs @@ -74,10 +74,8 @@ impl RoutingNode { return Some(format!("ws://{hostname}:{}", entry.clients_ws_port)); } - if prefer_ipv6 { - if let Some(ipv6) = entry.ip_addresses.iter().find(|ip| ip.is_ipv6()) { - return Some(format!("ws://{ipv6}:{}", entry.clients_ws_port)); - } + if prefer_ipv6 && let Some(ipv6) = entry.ip_addresses.iter().find(|ip| ip.is_ipv6()) { + return Some(format!("ws://{ipv6}:{}", entry.clients_ws_port)); } let any_ip = entry.ip_addresses.first()?; diff --git a/common/topology/src/wasm_helpers.rs b/common/topology/src/wasm_helpers.rs index 5ebce45455..1abf88272b 100644 --- a/common/topology/src/wasm_helpers.rs +++ b/common/topology/src/wasm_helpers.rs @@ -11,7 +11,7 @@ use std::collections::HashMap; use std::net::SocketAddr; use thiserror::Error; use tsify::Tsify; -use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; +use wasm_bindgen::{JsValue, prelude::wasm_bindgen}; use wasm_utils::error::simple_js_error; #[derive(Debug, Error)] diff --git a/common/tun/src/linux/tun_device.rs b/common/tun/src/linux/tun_device.rs index 936a141b3f..0b2a148682 100644 --- a/common/tun/src/linux/tun_device.rs +++ b/common/tun/src/linux/tun_device.rs @@ -12,8 +12,8 @@ use tokio::{ }; use crate::tun_task_channel::{ - tun_task_channel, tun_task_response_channel, TunTaskPayload, TunTaskResponseRx, - TunTaskResponseSendError, TunTaskResponseTx, TunTaskRx, TunTaskTx, + TunTaskPayload, TunTaskResponseRx, TunTaskResponseSendError, TunTaskResponseTx, TunTaskRx, + TunTaskTx, tun_task_channel, tun_task_response_channel, }; const TUN_WRITE_TIMEOUT_MS: u64 = 1000; diff --git a/common/upgrade-mode-check/src/lib.rs b/common/upgrade-mode-check/src/lib.rs index 21bc5402ec..d0f952b361 100644 --- a/common/upgrade-mode-check/src/lib.rs +++ b/common/upgrade-mode-check/src/lib.rs @@ -6,8 +6,8 @@ pub(crate) mod error; pub(crate) mod jwt; pub use attestation::{ - attempt_retrieve, generate_new_attestation, generate_new_attestation_with_starting_time, - UpgradeModeAttestation, + UpgradeModeAttestation, attempt_retrieve, generate_new_attestation, + generate_new_attestation_with_starting_time, }; pub use error::UpgradeModeCheckError; pub use jwt::{generate_jwt_for_upgrade_mode_attestation, validate_upgrade_mode_jwt}; diff --git a/common/verloc/src/measurements/listener.rs b/common/verloc/src/measurements/listener.rs index 8c817ce229..d076dad1a0 100644 --- a/common/verloc/src/measurements/listener.rs +++ b/common/verloc/src/measurements/listener.rs @@ -107,7 +107,9 @@ impl ConnectionHandler { .write_all(reply_packet.to_bytes().as_ref()) .await { - debug!("Failed to write reply packet back to the sender: {err}. Closing the socket on our end"); + debug!( + "Failed to write reply packet back to the sender: {err}. Closing the socket on our end" + ); return; } } diff --git a/common/verloc/src/measurements/measurer.rs b/common/verloc/src/measurements/measurer.rs index 8451207300..cc83426a64 100644 --- a/common/verloc/src/measurements/measurer.rs +++ b/common/verloc/src/measurements/measurer.rs @@ -5,8 +5,8 @@ use crate::measurements::metrics::SharedVerlocStats; use crate::measurements::sender::TestedNode; use crate::measurements::{Config, PacketListener, PacketSender}; use crate::models::VerlocNodeResult; -use futures::stream::FuturesUnordered; use futures::StreamExt; +use futures::stream::FuturesUnordered; use nym_crypto::asymmetric::ed25519; use nym_task::ShutdownToken; use nym_validator_client::models::NymNodeDescription; diff --git a/common/verloc/src/measurements/sender.rs b/common/verloc/src/measurements/sender.rs index 3b821c5176..f27c531603 100644 --- a/common/verloc/src/measurements/sender.rs +++ b/common/verloc/src/measurements/sender.rs @@ -6,7 +6,7 @@ use crate::measurements::packet::{EchoPacket, ReplyPacket}; use crate::models::VerlocMeasurement; use nym_crypto::asymmetric::ed25519; use nym_task::ShutdownToken; -use rand::{thread_rng, Rng}; +use rand::{Rng, thread_rng}; use std::net::SocketAddr; use std::sync::Arc; use std::time::Duration; @@ -15,7 +15,7 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::TcpStream; use tracing::{debug, trace}; -use tokio::time::{sleep, Instant}; +use tokio::time::{Instant, sleep}; #[derive(Copy, Clone)] pub(crate) struct TestedNode { @@ -71,7 +71,7 @@ impl PacketSender { fn random_sequence_number(&self) -> u64 { let mut rng = thread_rng(); loop { - let r: u64 = rng.gen(); + let r: u64 = rng.r#gen(); // make sure we can actually increment it packets_per_node times if r < (u64::MAX - self.packets_per_node as u64) { return r; @@ -95,14 +95,14 @@ impl PacketSender { identity: tested_node.identity.to_string(), err: io::ErrorKind::TimedOut.into(), address: tested_node.address, - }) + }); } Ok(Err(err)) => { return Err(VerlocError::UnreachableNode { identity: tested_node.identity.to_string(), err, address: tested_node.address, - }) + }); } Ok(Ok(conn)) => conn, }; @@ -199,7 +199,11 @@ impl PacketSender { // note that we cannot receive packets not in order as we are not sending a next packet until // we have received the previous one if reply_packet.base_sequence_number() != seq { - debug!("Received reply packet with invalid sequence number! Got {} expected {}. Stopping the test", reply_packet.base_sequence_number(), seq); + debug!( + "Received reply packet with invalid sequence number! Got {} expected {}. Stopping the test", + reply_packet.base_sequence_number(), + seq + ); return Err(VerlocError::UnexpectedReplySequence); } diff --git a/common/wireguard-private-metadata/client/src/lib.rs b/common/wireguard-private-metadata/client/src/lib.rs index fd02fb3847..58d78fb6c6 100644 --- a/common/wireguard-private-metadata/client/src/lib.rs +++ b/common/wireguard-private-metadata/client/src/lib.rs @@ -7,7 +7,7 @@ use tracing::instrument; use nym_http_api_client::{ApiClient, Client, HttpClientError, NO_PARAMS}; use nym_wireguard_private_metadata_shared::{ - routes, Version, {Request, Response}, + Version, routes, {Request, Response}, }; #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] diff --git a/common/wireguard-private-metadata/server/src/http/router.rs b/common/wireguard-private-metadata/server/src/http/router.rs index ac4250e431..099e1d5724 100644 --- a/common/wireguard-private-metadata/server/src/http/router.rs +++ b/common/wireguard-private-metadata/server/src/http/router.rs @@ -2,9 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use anyhow::anyhow; +use axum::Router; use axum::response::Redirect; use axum::routing::get; -use axum::Router; use core::net::SocketAddr; use nym_http_api_common::middleware::logging::log_request_info; use std::future::Future; diff --git a/common/wireguard-private-metadata/server/src/lib.rs b/common/wireguard-private-metadata/server/src/lib.rs index 3d772ac1e0..1836f6687b 100644 --- a/common/wireguard-private-metadata/server/src/lib.rs +++ b/common/wireguard-private-metadata/server/src/lib.rs @@ -6,8 +6,8 @@ mod network; mod transceiver; pub use http::{ + ShutdownHandles, router::{ApiHttpServer, RouterBuilder, RouterWithState}, state::AppState, - ShutdownHandles, }; pub use transceiver::PeerControllerTransceiver; diff --git a/common/wireguard-private-metadata/server/src/network.rs b/common/wireguard-private-metadata/server/src/network.rs index 36b22ba32b..8e27eca5cd 100644 --- a/common/wireguard-private-metadata/server/src/network.rs +++ b/common/wireguard-private-metadata/server/src/network.rs @@ -4,13 +4,14 @@ use std::net::SocketAddr; use axum::{ - extract::{ConnectInfo, Query, State}, Json, Router, + extract::{ConnectInfo, Query, State}, }; use nym_http_api_common::{FormattedResponse, OutputParams}; use nym_wireguard_private_metadata_shared::{ + AxumErrorResponse, AxumResult, Construct, Extract, Request, Response, interface::{RequestData, ResponseData}, - latest, AxumErrorResponse, AxumResult, Construct, Extract, Request, Response, + latest, }; use tower_http::compression::CompressionLayer; diff --git a/common/wireguard-private-metadata/shared/src/lib.rs b/common/wireguard-private-metadata/shared/src/lib.rs index de79157874..54041fd8c7 100644 --- a/common/wireguard-private-metadata/shared/src/lib.rs +++ b/common/wireguard-private-metadata/shared/src/lib.rs @@ -8,8 +8,8 @@ pub mod routes; #[cfg(feature = "testing")] pub use models::v0; pub use models::{ - error::Error as ModelError, interface, latest, v1, AxumErrorResponse, AxumResult, Construct, - ErrorResponse, Extract, Request, Response, Version, + AxumErrorResponse, AxumResult, Construct, ErrorResponse, Extract, Request, Response, Version, + error::Error as ModelError, interface, latest, v1, }; fn make_bincode_serializer() -> impl bincode::Options { diff --git a/common/wireguard-private-metadata/shared/src/models/interface.rs b/common/wireguard-private-metadata/shared/src/models/interface.rs index 3f4537f170..9d5a786c53 100644 --- a/common/wireguard-private-metadata/shared/src/models/interface.rs +++ b/common/wireguard-private-metadata/shared/src/models/interface.rs @@ -5,7 +5,7 @@ use nym_credentials_interface::CredentialSpendingData; #[cfg(feature = "testing")] use crate::models::v0; -use crate::models::{v1, Construct, Extract, Request, Response, Version}; +use crate::models::{Construct, Extract, Request, Response, Version, v1}; pub enum RequestData { AvailableBandwidth(()), diff --git a/common/wireguard-private-metadata/shared/src/models/v0/interface.rs b/common/wireguard-private-metadata/shared/src/models/v0/interface.rs index 2f8fd2805c..f52daba30e 100644 --- a/common/wireguard-private-metadata/shared/src/models/v0/interface.rs +++ b/common/wireguard-private-metadata/shared/src/models/v0/interface.rs @@ -2,13 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 use super::{ + QueryType, VERSION, VersionedRequest, VersionedResponse, available_bandwidth::{ request::InnerAvailableBandwidthRequest, response::InnerAvailableBandwidthResponse, }, topup_bandwidth::{request::InnerTopUpRequest, response::InnerTopUpResponse}, - QueryType, VersionedRequest, VersionedResponse, VERSION, }; -use crate::models::{error::Error, Construct, Extract, Version}; +use crate::models::{Construct, Extract, Version, error::Error}; #[derive(Debug, Clone, PartialEq)] pub enum RequestData { diff --git a/common/wireguard-private-metadata/shared/src/models/v1/interface.rs b/common/wireguard-private-metadata/shared/src/models/v1/interface.rs index 46cafddc7d..763222e04a 100644 --- a/common/wireguard-private-metadata/shared/src/models/v1/interface.rs +++ b/common/wireguard-private-metadata/shared/src/models/v1/interface.rs @@ -7,13 +7,13 @@ use nym_credentials_interface::CredentialSpendingData; use super::super::v0 as previous; use super::{ + QueryType, VERSION, VersionedRequest, VersionedResponse, available_bandwidth::{ request::InnerAvailableBandwidthRequest, response::InnerAvailableBandwidthResponse, }, topup_bandwidth::{request::InnerTopUpRequest, response::InnerTopUpResponse}, - QueryType, VersionedRequest, VersionedResponse, VERSION, }; -use crate::models::{error::Error, Construct, Extract, Version}; +use crate::models::{Construct, Extract, Version, error::Error}; #[derive(Debug, Clone, PartialEq)] pub enum RequestData { diff --git a/common/wireguard-private-metadata/tests/src/lib.rs b/common/wireguard-private-metadata/tests/src/lib.rs index 1ae9ccdd93..7c8cbec81d 100644 --- a/common/wireguard-private-metadata/tests/src/lib.rs +++ b/common/wireguard-private-metadata/tests/src/lib.rs @@ -8,7 +8,7 @@ mod tests { use nym_credential_verification::{ClientBandwidth, TicketVerifier}; use nym_credentials_interface::CredentialSpendingData; use nym_http_api_client::Client; - use nym_wireguard::{peer_controller::PeerControlRequest, CONTROL_CHANNEL_SIZE}; + use nym_wireguard::{CONTROL_CHANNEL_SIZE, peer_controller::PeerControlRequest}; use nym_wireguard_private_metadata_client::WireguardMetadataApiClient; use nym_wireguard_private_metadata_server::{ AppState, PeerControllerTransceiver, RouterBuilder, diff --git a/common/wireguard-private-metadata/tests/src/v0/interface.rs b/common/wireguard-private-metadata/tests/src/v0/interface.rs index 77cd2d12fe..a09ff4307a 100644 --- a/common/wireguard-private-metadata/tests/src/v0/interface.rs +++ b/common/wireguard-private-metadata/tests/src/v0/interface.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use nym_wireguard_private_metadata_shared::{ - v0 as latest, Construct, Extract, Request, Response, Version, + Construct, Extract, Request, Response, Version, v0 as latest, }; pub enum RequestData { diff --git a/common/wireguard-private-metadata/tests/src/v0/network.rs b/common/wireguard-private-metadata/tests/src/v0/network.rs index 0be32d66dc..b0b7361e84 100644 --- a/common/wireguard-private-metadata/tests/src/v0/network.rs +++ b/common/wireguard-private-metadata/tests/src/v0/network.rs @@ -9,14 +9,14 @@ pub(crate) mod test { tests::{MockVerifier, VERIFIER_AVAILABLE_BANDWIDTH}, v0::interface::{RequestData, ResponseData}, }; - use axum::{extract::Query, Json, Router}; + use axum::{Json, Router, extract::Query}; use nym_credential_verification::ClientBandwidth; use nym_http_api_client::Client; use nym_http_api_common::{FormattedResponse, OutputParams}; - use nym_wireguard::{peer_controller::PeerControlRequest, CONTROL_CHANNEL_SIZE}; + use nym_wireguard::{CONTROL_CHANNEL_SIZE, peer_controller::PeerControlRequest}; use nym_wireguard_private_metadata_server::PeerControllerTransceiver; use nym_wireguard_private_metadata_shared::{ - v0 as latest, AxumErrorResponse, AxumResult, Construct, Extract, Request, Response, + AxumErrorResponse, AxumResult, Construct, Extract, Request, Response, v0 as latest, }; use tokio::{net::TcpListener, sync::mpsc}; use tower_http::compression::CompressionLayer; diff --git a/common/wireguard-types/src/error.rs b/common/wireguard-types/src/error.rs index bd8c54b6f7..71f408e02c 100644 --- a/common/wireguard-types/src/error.rs +++ b/common/wireguard-types/src/error.rs @@ -5,14 +5,18 @@ use thiserror::Error; #[derive(Debug, Error)] pub enum Error { - #[error("the provided base64-encoded client x25519 public key ('{pub_key}') was malformed: {source}")] + #[error( + "the provided base64-encoded client x25519 public key ('{pub_key}') was malformed: {source}" + )] MalformedPeerPublicKeyEncoding { pub_key: String, #[source] source: base64::DecodeError, }, - #[error("the provided base64-encoded client x25519 public key ('{pub_key}') has invalid length: {decoded_length}. expected 32 bytes")] + #[error( + "the provided base64-encoded client x25519 public key ('{pub_key}') has invalid length: {decoded_length}. expected 32 bytes" + )] InvalidPeerPublicKeyLength { pub_key: String, decoded_length: usize, diff --git a/common/wireguard-types/src/public_key.rs b/common/wireguard-types/src/public_key.rs index 31cfb448e1..3b3bbd60d1 100644 --- a/common/wireguard-types/src/public_key.rs +++ b/common/wireguard-types/src/public_key.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use crate::Error; -use base64::engine::general_purpose; use base64::Engine; +use base64::engine::general_purpose; use serde::Serialize; use std::fmt; use std::ops::Deref; @@ -15,7 +15,6 @@ use x25519_dalek::PublicKey; pub struct PeerPublicKey(PublicKey); impl PeerPublicKey { - #[allow(dead_code)] pub fn new(key: PublicKey) -> Self { PeerPublicKey(key) } @@ -29,6 +28,12 @@ impl PeerPublicKey { } } +impl From for PeerPublicKey { + fn from(key: PublicKey) -> Self { + PeerPublicKey::new(key) + } +} + impl fmt::Display for PeerPublicKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", general_purpose::STANDARD.encode(self.0.as_bytes())) diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index 5bbce1b4b8..6b2c632d22 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -6,7 +6,7 @@ // #![warn(clippy::expect_used)] // #![warn(clippy::unwrap_used)] -use defguard_wireguard_rs::{host::Peer, key::Key, net::IpAddrMask, WGApi, WireguardInterfaceApi}; +use defguard_wireguard_rs::{WGApi, WireguardInterfaceApi, host::Peer, key::Key, net::IpAddrMask}; #[cfg(target_os = "linux")] use nym_credential_verification::ecash::EcashManager; use nym_crypto::asymmetric::x25519::KeyPair; @@ -166,7 +166,7 @@ pub async fn start_wireguard( shutdown_token: nym_task::ShutdownToken, wireguard_data: WireguardData, ) -> Result, Box> { - use base64::{prelude::BASE64_STANDARD, Engine}; + use base64::{Engine, prelude::BASE64_STANDARD}; use defguard_wireguard_rs::{InterfaceConfiguration, WireguardInterfaceApi}; use ip_network::IpNetwork; use nym_credential_verification::ecash::traits::EcashManager; diff --git a/common/wireguard/src/peer_controller.rs b/common/wireguard/src/peer_controller.rs index 4b294703fb..e9e4f78f2d 100644 --- a/common/wireguard/src/peer_controller.rs +++ b/common/wireguard/src/peer_controller.rs @@ -2,15 +2,15 @@ // SPDX-License-Identifier: Apache-2.0 use defguard_wireguard_rs::{ + WireguardInterfaceApi, host::{Host, Peer}, key::Key, - WireguardInterfaceApi, }; use futures::channel::oneshot; use log::info; use nym_credential_verification::{ - bandwidth_storage_manager::BandwidthStorageManager, ecash::traits::EcashManager, BandwidthFlushingBehaviourConfig, ClientBandwidth, CredentialVerifier, TicketVerifier, + bandwidth_storage_manager::BandwidthStorageManager, ecash::traits::EcashManager, }; use nym_credentials_interface::CredentialSpendingData; use nym_gateway_requests::models::CredentialSpendingRequest; @@ -22,8 +22,8 @@ use std::{ net::IpAddr, time::{Duration, SystemTime}, }; -use tokio::sync::{mpsc, RwLock}; -use tokio_stream::{wrappers::IntervalStream, StreamExt}; +use tokio::sync::{RwLock, mpsc}; +use tokio_stream::{StreamExt, wrappers::IntervalStream}; use crate::{ error::{Error, Result}, @@ -145,7 +145,9 @@ impl PeerController { self.bw_storage_managers.remove(key); let ret = self.wg_api.remove_peer(key); if ret.is_err() { - log::error!("Wireguard peer could not be removed from wireguard kernel module. Process should be restarted so that the interface is reset."); + log::error!( + "Wireguard peer could not be removed from wireguard kernel module. Process should be restarted so that the interface is reset." + ); } Ok(ret?) } diff --git a/common/wireguard/src/peer_handle.rs b/common/wireguard/src/peer_handle.rs index 80ec587a19..57c92d5072 100644 --- a/common/wireguard/src/peer_handle.rs +++ b/common/wireguard/src/peer_handle.rs @@ -10,8 +10,8 @@ use nym_credential_verification::bandwidth_storage_manager::BandwidthStorageMana use nym_task::ShutdownToken; use nym_wireguard_types::DEFAULT_PEER_TIMEOUT_CHECK; use std::sync::Arc; -use tokio::sync::{mpsc, RwLock}; -use tokio_stream::{wrappers::IntervalStream, StreamExt}; +use tokio::sync::{RwLock, mpsc}; +use tokio_stream::{StreamExt, wrappers::IntervalStream}; #[derive(Clone)] pub(crate) struct SharedBandwidthStorageManager { diff --git a/common/zulip-client/src/client.rs b/common/zulip-client/src/client.rs index 60554e5c25..b818c28b10 100644 --- a/common/zulip-client/src/client.rs +++ b/common/zulip-client/src/client.rs @@ -28,7 +28,7 @@ use crate::error::ZulipClientError; use crate::message::{DirectMessage, SendMessageResponse, SendableMessage, StreamMessage}; use nym_bin_common::bin_info; use nym_http_api_client::UserAgent; -use reqwest::{header, Method, RequestBuilder}; +use reqwest::{Method, RequestBuilder, header}; use serde::{Deserialize, Serialize}; use std::str::FromStr; use tracing::trace; diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index 13d80f7a14..1e4a5be417 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -11,7 +11,7 @@ authors = [ ] description = "Implementation of the Nym Mixnet Gateway" edition = "2021" -rust-version = "1.77" +rust-version = "1.85" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/nym-api/src/network_monitor/monitor/preparer.rs b/nym-api/src/network_monitor/monitor/preparer.rs index 35c870c53c..074a4f612f 100644 --- a/nym-api/src/network_monitor/monitor/preparer.rs +++ b/nym-api/src/network_monitor/monitor/preparer.rs @@ -308,7 +308,7 @@ impl PacketPreparer { let gateway = rand_gateways[i].clone(); routes.push(TestRoute::new( - rng.gen(), + rng.r#gen(), current_rotation_id, node_1, node_2, diff --git a/nym-authenticator-client/src/lib.rs b/nym-authenticator-client/src/lib.rs index 371bfef15b..8fe7edb511 100644 --- a/nym-authenticator-client/src/lib.rs +++ b/nym-authenticator-client/src/lib.rs @@ -13,8 +13,8 @@ use tracing::{debug, error, trace}; use crate::mixnet_listener::{MixnetMessageBroadcastReceiver, MixnetMessageInputSender}; use nym_authenticator_requests::{ - client_message::ClientMessage, response::AuthenticatorResponse, traits::Id, v2, v3, v4, v5, - AuthenticatorVersion, + AuthenticatorVersion, client_message::ClientMessage, response::AuthenticatorResponse, + traits::Id, v2, v3, v4, v5, }; use nym_credentials_interface::{CredentialSpendingData, TicketType}; use nym_sdk::mixnet::{IncludedSurbs, Recipient}; @@ -196,8 +196,7 @@ impl AuthenticatorClient { trace!( "received \"pending-registration\" msg from {}: {:?}", - &self.ip_addr, - &pending_registration_response + &self.ip_addr, &pending_registration_response ); let credential = Some( @@ -267,8 +266,7 @@ impl AuthenticatorClient { }; trace!( "sending final msg to {}: {:?}", - &self.ip_addr, - &finalized_message + &self.ip_addr, &finalized_message ); let response = self.send_and_wait_for_response(&finalized_message).await?; @@ -283,8 +281,7 @@ impl AuthenticatorClient { trace!( "received \"registered\" msg from {}: {:?}", - &self.ip_addr, - ®istered_data + &self.ip_addr, ®istered_data ); let gateway_data = GatewayData { diff --git a/nym-credential-proxy/nym-credential-proxy-requests/src/api/v1/ticketbook/models.rs b/nym-credential-proxy/nym-credential-proxy-requests/src/api/v1/ticketbook/models.rs index 061b40a37d..e0b6b6b892 100644 --- a/nym-credential-proxy/nym-credential-proxy-requests/src/api/v1/ticketbook/models.rs +++ b/nym-credential-proxy/nym-credential-proxy-requests/src/api/v1/ticketbook/models.rs @@ -5,9 +5,9 @@ use nym_credentials::ecash::bandwidth::serialiser::signatures::{ AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, }; use nym_credentials_interface::{PublicKeyUser, TicketType, WithdrawalRequest}; -use schemars::gen::SchemaGenerator; -use schemars::schema::Schema; use schemars::JsonSchema; +use schemars::r#gen::SchemaGenerator; +use schemars::schema::Schema; use serde::{Deserialize, Serialize}; use std::ops::{Deref, DerefMut}; use time::{Date, OffsetDateTime}; @@ -132,9 +132,9 @@ impl JsonSchema for WithdrawalRequestBs58Wrapper { "WithdrawalRequestBs58Wrapper".into() } - fn json_schema(gen: &mut SchemaGenerator) -> Schema { + fn json_schema(r#gen: &mut SchemaGenerator) -> Schema { // during serialisation we just use bs58 representation - String::json_schema(gen) + String::json_schema(r#gen) } } diff --git a/nym-credential-proxy/nym-credential-proxy-requests/src/client.rs b/nym-credential-proxy/nym-credential-proxy-requests/src/client.rs index e9b16514f9..7ac16f18cd 100644 --- a/nym-credential-proxy/nym-credential-proxy-requests/src/client.rs +++ b/nym-credential-proxy/nym-credential-proxy-requests/src/client.rs @@ -7,7 +7,7 @@ use crate::api::v1::ticketbook::models::{ }; use async_trait::async_trait; use nym_http_api_client::{ - parse_response, ApiClient, HttpClientError, Params, PathSegments, NO_PARAMS, + ApiClient, HttpClientError, NO_PARAMS, Params, PathSegments, parse_response, }; use reqwest::IntoUrl; use serde::de::DeserializeOwned; diff --git a/nym-credential-proxy/nym-credential-proxy-requests/src/helpers.rs b/nym-credential-proxy/nym-credential-proxy-requests/src/helpers.rs index 5420be21c5..3d9264274a 100644 --- a/nym-credential-proxy/nym-credential-proxy-requests/src/helpers.rs +++ b/nym-credential-proxy/nym-credential-proxy-requests/src/helpers.rs @@ -1,7 +1,7 @@ // Copyright 2024 Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use time::format_description::{modifier, BorrowedFormatItem, Component}; +use time::format_description::{BorrowedFormatItem, Component, modifier}; const DATE_FORMAT: &[BorrowedFormatItem<'_>] = &[ BorrowedFormatItem::Component(Component::Year(modifier::Year::default())), @@ -14,7 +14,7 @@ const DATE_FORMAT: &[BorrowedFormatItem<'_>] = &[ pub(crate) mod date_serde { use crate::helpers::DATE_FORMAT; use serde::ser::Error; - use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; use time::Date; pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result diff --git a/nym-credential-proxy/nym-credential-proxy/src/config/mod.rs b/nym-credential-proxy/nym-credential-proxy/src/config/mod.rs index eeafe05203..174db7aedc 100644 --- a/nym-credential-proxy/nym-credential-proxy/src/config/mod.rs +++ b/nym-credential-proxy/nym-credential-proxy/src/config/mod.rs @@ -1,7 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use nym_config::{must_get_home, DEFAULT_DATA_DIR, NYM_DIR}; +use nym_config::{DEFAULT_DATA_DIR, NYM_DIR, must_get_home}; use std::path::PathBuf; pub const DEFAULT_NYM_CREDENTIAL_PROXY_DIR: &str = "nym-credential-proxy"; diff --git a/nym-credential-proxy/nym-credential-proxy/src/helpers.rs b/nym-credential-proxy/nym-credential-proxy/src/helpers.rs index d4d3742939..41e474cf23 100644 --- a/nym-credential-proxy/nym-credential-proxy/src/helpers.rs +++ b/nym-credential-proxy/nym-credential-proxy/src/helpers.rs @@ -9,7 +9,7 @@ use nym_credential_proxy_lib::ticketbook_manager::TicketbookManager; use tracing::{error, info}; pub async fn wait_for_signal() { - use tokio::signal::unix::{signal, SignalKind}; + use tokio::signal::unix::{SignalKind, signal}; // if we fail to setup the signals, we should just blow up #[allow(clippy::expect_used)] diff --git a/nym-credential-proxy/nym-credential-proxy/src/http/router/api/v1/ticketbook/shares.rs b/nym-credential-proxy/nym-credential-proxy/src/http/router/api/v1/ticketbook/shares.rs index b41173e47e..ba460a1ac1 100644 --- a/nym-credential-proxy/nym-credential-proxy/src/http/router/api/v1/ticketbook/shares.rs +++ b/nym-credential-proxy/nym-credential-proxy/src/http/router/api/v1/ticketbook/shares.rs @@ -3,9 +3,9 @@ use crate::http::router::api::v1::ticketbook::FormattedTicketbookWalletSharesResponse; use crate::http::state::ApiState; +use axum::Router; use axum::extract::{Path, Query, State}; use axum::routing::get; -use axum::Router; use nym_credential_proxy_lib::helpers::random_uuid; use nym_credential_proxy_lib::http_helpers::RequestError; use nym_credential_proxy_requests::api::v1::ticketbook::models::{ diff --git a/nym-credential-proxy/nym-credential-proxy/src/http/router/mod.rs b/nym-credential-proxy/nym-credential-proxy/src/http/router/mod.rs index 292d27a486..8b23bbab42 100644 --- a/nym-credential-proxy/nym-credential-proxy/src/http/router/mod.rs +++ b/nym-credential-proxy/nym-credential-proxy/src/http/router/mod.rs @@ -2,9 +2,9 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::http::state::ApiState; -use axum::response::Redirect; -use axum::routing::{get, MethodRouter}; use axum::Router; +use axum::response::Redirect; +use axum::routing::{MethodRouter, get}; use nym_credential_proxy_requests::routes; use nym_http_api_common::middleware::bearer_auth::AuthLayer; use nym_http_api_common::middleware::logging; diff --git a/nym-credential-proxy/vpn-api-lib-wasm/src/lib.rs b/nym-credential-proxy/vpn-api-lib-wasm/src/lib.rs index 02c3b757f3..abdff1bfe8 100644 --- a/nym-credential-proxy/vpn-api-lib-wasm/src/lib.rs +++ b/nym-credential-proxy/vpn-api-lib-wasm/src/lib.rs @@ -5,8 +5,8 @@ use crate::error::VpnApiLibError; use nym_compact_ecash::scheme::keygen::KeyPairUser; use nym_compact_ecash::scheme::withdrawal::RequestInfo; use nym_compact_ecash::{ - aggregate_wallets, issue_verify, withdrawal_request, Base58, BlindedSignature, - VerificationKeyAuth, WithdrawalRequest, + Base58, BlindedSignature, VerificationKeyAuth, WithdrawalRequest, aggregate_wallets, + issue_verify, withdrawal_request, }; use nym_credential_proxy_requests::api::v1::ticketbook::models::{ MasterVerificationKeyResponse, PartialVerificationKeysResponse, TicketbookRequest, @@ -18,7 +18,7 @@ use nym_credentials::{ }; use nym_credentials_interface::TicketType; use nym_crypto::asymmetric::ed25519; -use nym_ecash_time::{ecash_default_expiration_date, EcashTime}; +use nym_ecash_time::{EcashTime, ecash_default_expiration_date}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use time::Date; @@ -177,7 +177,10 @@ impl NymIssuanceTicketbook { for share in shares.shares { let blinded_sig = BlindedSignature::try_from_bs58(share.bs58_encoded_share)?; let Some(vk) = decoded_keys.get(&share.node_index) else { - console_error!("received a share from issuer {} but did not receive a corresponding verification key!", share.node_index); + console_error!( + "received a share from issuer {} but did not receive a corresponding verification key!", + share.node_index + ); continue; }; diff --git a/nym-gateway-probe/Cargo.toml b/nym-gateway-probe/Cargo.toml new file mode 100644 index 0000000000..74f547ee53 --- /dev/null +++ b/nym-gateway-probe/Cargo.toml @@ -0,0 +1,75 @@ +[package] +name = "nym-gateway-probe" +version = "1.18.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true + +[lints] +workspace = true + +[dependencies] +anyhow.workspace = true +base64.workspace = true +bs58.workspace = true +bincode.workspace = true +bytes.workspace = true +clap = { workspace = true, features = ["cargo", "derive"] } +futures.workspace = true +hex.workspace = true +tracing.workspace = true +pnet_packet.workspace = true +rand.workspace = true +serde.workspace = true +serde_json.workspace = true +thiserror.workspace = true +tokio = { workspace = true, features = [ + "process", + "rt-multi-thread", + "fs", + "sync", + "macros", +] } +tokio-util.workspace = true +tracing-subscriber.workspace = true +url = { workspace = true } +x25519-dalek = { workspace = true, features = [ + "reusable_secrets", + "static_secrets", +] } + +nym-authenticator-requests = { path = "../common/authenticator-requests" } +nym-bandwidth-controller = { path = "../common/bandwidth-controller" } +nym-bin-common = { path = "../common/bin-common" } +nym-client-core = { path = "../common/client-core" } +nym-crypto = { path = "../common/crypto" } +nym-config = { path = "../common/config" } +nym-connection-monitor = { path = "../common/nym-connection-monitor" } +nym-credentials-interface = { path = "../common/credentials-interface" } +nym-credential-utils = { path = "../common/credential-utils" } +nym-ip-packet-client = { path = "../nym-ip-packet-client" } +nym-authenticator-client = { path = "../nym-authenticator-client" } +nym-ip-packet-requests = { path = "../common/ip-packet-requests" } +nym-sdk = { path = "../sdk/rust/nym-sdk" } +nym-validator-client = { path = "../common/client-libs/validator-client" } +nym-credentials = { path = "../common/credentials" } +nym-http-api-client-macro = { path = "../common/http-api-client-macro", features = ["debug-inventory"] } +nym-http-api-client = { path = "../common/http-api-client" } +nym-node-status-client = { path = "../nym-node-status-api/nym-node-status-client" } + +# TEMP: REMOVE BEFORE PR +nym-topology = { path = "../common/topology" } + +[build-dependencies] +anyhow = { workspace = true } +vergen-gitcl = { workspace = true, default-features = false, features = [ + "build", + "cargo", + "rustc", +] } + +[package.metadata.cargo-machete] +ignored = ["vergen", "nym-http-api-client"] diff --git a/nym-gateway-probe/README.md b/nym-gateway-probe/README.md new file mode 100644 index 0000000000..eab109d13f --- /dev/null +++ b/nym-gateway-probe/README.md @@ -0,0 +1,83 @@ +# Nym Gateway Probe + +Probe IPv4 and IPv6 interfaces of available gateways to check for the +set that passes a set of minimum service guarantees. + +## Build + +These instructions assume a debian based system. Adjust accordingly for your +preferred platform. + +Install required dependencies + +```sh +sudo apt install libdbus-1-dev libmnl-dev libnftnl-dev protobuf-compiler llvm-dev libclang-dev clang +``` + +Build required libraries and executables + +```sh +# build the prober +cargo build -p nym-gateway-probe +``` + +## Usage + +```sh +Usage: nym-gateway-probe [OPTIONS] + +Options: + -c, --config-env-file + Path pointing to an env file describing the network + -g, --entry-gateway + The specific gateway specified by ID + -n, --node + Identity of the node to test + --min-gateway-mixnet-performance + + --min-gateway-vpn-performance + + --only-wireguard + + -i, --ignore-egress-epoch-role + Disable logging during probe + --no-log + + -a, --amnezia-args + Arguments to be appended to the wireguard config enabling amnezia-wg configuration + + --netstack-download-timeout-sec + [default: 180] + --netstack-v4-dns + [default: 1.1.1.1] + --netstack-v6-dns + [default: 2606:4700:4700::1111] + --netstack-num-ping + [default: 5] + --netstack-send-timeout-sec + [default: 3] + --netstack-recv-timeout-sec + [default: 3] + --netstack-ping-hosts-v4 + [default: nymtech.net] + --netstack-ping-ips-v4 + [default: 1.1.1.1] + --netstack-ping-hosts-v6 + [default: ipv6.google.com] + --netstack-ping-ips-v6 + [default: 2001:4860:4860::8888 2606:4700:4700::1111 2620:fe::fe] + -h, --help + Print help + -V, --version + Print version +``` + +Examples + +```sh +# Run a basic probe against the node with id "qj3GgGYg..." +nym-gateway-probe -g "qj3GgGYgGZZ3HkFrtD1GU9UJ5oNXME9eD2xtmPLqYYw" + +# Run a probe against the node with id "qj3GgGYg..." using amnezia with junk packets enabled. +nym-gateway-probe -g "qj3GgGYgGZZ3HkFrtD1GU9UJ5oNXME9eD2xtmPLqYYw" -a "jc=4\njmin=40\njmax=70\n" +``` diff --git a/nym-gateway-probe/build.rs b/nym-gateway-probe/build.rs new file mode 100644 index 0000000000..9588105290 --- /dev/null +++ b/nym-gateway-probe/build.rs @@ -0,0 +1,82 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +#![allow(clippy::panic)] + +use anyhow::{Context, bail}; +use std::{path::PathBuf, process::Command}; +use vergen_gitcl::{BuildBuilder, CargoBuilder, Emitter, GitclBuilder, RustcBuilder}; + +fn main() -> anyhow::Result<()> { + build_go()?; + + Emitter::default() + .add_instructions(&BuildBuilder::all_build()?)? + .add_instructions(&CargoBuilder::all_cargo()?)? + .add_instructions(&GitclBuilder::all_git()?)? + .add_instructions(&RustcBuilder::all_rustc()?)? + .emit() +} + +fn build_go() -> anyhow::Result<()> { + const LIB_NAME: &str = "netstack_ping"; + + let target_os = std::env::var("CARGO_CFG_TARGET_OS").context("target os is not set")?; + // Only build on macos and linux + if !matches!(target_os.as_str(), "macos" | "linux") { + return Ok(()); + } + + let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").context("target arch is not set")?; + let out_dir = PathBuf::from(std::env::var("OUT_DIR").context("OUT_DIR is not set")?); + let go_target = match target_os.as_str() { + "macos" => "darwin".to_owned(), + "linux" => target_os.to_owned(), + _ => panic!("unsupported target: {target_os}"), + }; + let go_arch = match target_arch.as_str() { + "x86_64" => "amd64", + "aarch64" => "arm64", + _ => panic!("unsupported architecture: {target_arch}"), + }; + let src_dir = PathBuf::from("netstack_ping").canonicalize()?; + let binary_out_path = out_dir.join(format!("lib{LIB_NAME}.a")); + + println!("cargo::rerun-if-changed={}", src_dir.display()); + + let mut command = Command::new("go"); + + if target_os == "macos" { + let deployment_target = + std::env::var_os("MACOSX_DEPLOYMENT_TARGET").unwrap_or("10.13".into()); + command.env("MACOSX_DEPLOYMENT_TARGET", deployment_target); + } + + let mut child = command + .env("CGO_ENABLED", "1") + .env("GOOS", go_target) + .env("GOARCH", go_arch) + .current_dir(src_dir) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .arg("build") + .arg("-ldflags=-buildid=") + .arg("-trimpath") + .arg("-buildvcs=false") + .arg("-v") + .arg("-o") + .arg(binary_out_path) + .arg("-buildmode") + .arg("c-archive") + .arg("lib.go") + .spawn()?; + let status = child.wait()?; + if !status.success() { + bail!("Failed to build {LIB_NAME}"); + } + + println!("cargo::rustc-link-search={}", out_dir.display()); + println!("cargo:rustc-link-lib=static={LIB_NAME}"); + + Ok(()) +} diff --git a/nym-gateway-probe/netstack_ping/README.md b/nym-gateway-probe/netstack_ping/README.md new file mode 100644 index 0000000000..cca9bfe5f1 --- /dev/null +++ b/nym-gateway-probe/netstack_ping/README.md @@ -0,0 +1,65 @@ +# Nym Gateway Probe (netstack) + +The gateway probe uses `netstack` to do various parts of the gateway test: + +- send ICMP pings +- download files +- check the top-up metadata endpoint + +## Running locally + +You will need: +- a Wireguard config +- be registered with a gateway +- have topped up your bandwidth with the gateway +- a mnemonic for an account with NYM tokens to issue `zk-nyms` + +You can get you Wireguard config by running the `nym-gateway-probe` locally: + +``` +SHOW_WG_CONFIG=true nym-gateway-probe -g ${IDENTITY KEY} run-local --mnemonic=${MNEMONIC} +``` + +In the probe logs you will see the Wireguard config: + +``` +private_key=... +listen_port=50239 +public_key=... +preshared_key=0000000000000000000000000000000000000000000000000000000000000000 +protocol_version=1 +endpoint=13.245.9.123:51822 +last_handshake_time_sec=0 +last_handshake_time_nsec=0 +tx_bytes=0 +rx_bytes=0 +persistent_keepalive_interval=0 +``` + +In the `main()` function, uncomment the lines and set your Wireguard config: + +```go +func main() { + var _, err = ping(NetstackRequestGo{ + WgIp: "10.1.155.153", + PrivateKey: "...", + PublicKey: "...", + Endpoint: "13.245.9.123:51822", + MetadataEndpoint: "http://10.1.0.1:51830", + Dns: "1.1.1.1", + IpVersion: 4, + //PingHosts: nil, + //PingIps: nil, + //NumPing: 0, + //SendTimeoutSec: 0, + //RecvTimeoutSec: 0, + //DownloadTimeoutSec: 0, + MetadataTimeoutSec: 5, + //AwgArgs: "", + }) + + if err != nil { + log.Fatal(err) + } +} +``` \ No newline at end of file diff --git a/nym-gateway-probe/netstack_ping/go.mod b/nym-gateway-probe/netstack_ping/go.mod new file mode 100644 index 0000000000..ac45bca5eb --- /dev/null +++ b/nym-gateway-probe/netstack_ping/go.mod @@ -0,0 +1,19 @@ +module github.com/nymtech/nym-vpn-client/nym-vpn-core/crates/nym-gateway-probe/netstack_ping + +go 1.24.4 + +require ( + github.com/amnezia-vpn/amneziawg-go v0.2.13 + golang.org/x/net v0.41.0 +) + +require ( + github.com/google/btree v1.1.3 // indirect + github.com/tevino/abool v1.2.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + golang.org/x/crypto v0.39.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/time v0.9.0 // indirect + golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect + gvisor.dev/gvisor v0.0.0-20250611222258-0fe9a4bf489c // indirect +) diff --git a/nym-gateway-probe/netstack_ping/go.sum b/nym-gateway-probe/netstack_ping/go.sum new file mode 100644 index 0000000000..f43212422f --- /dev/null +++ b/nym-gateway-probe/netstack_ping/go.sum @@ -0,0 +1,28 @@ +github.com/amnezia-vpn/amneziawg-go v0.2.13 h1:xFxCumnmtYTOMeg14MPG53p9RpmvSnjrDEB1bFma79A= +github.com/amnezia-vpn/amneziawg-go v0.2.13/go.mod h1:TB75yoG4yP6nVcJY3CPWstDcgOtlouC4xWyE7U9XqzU= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tevino/abool v1.2.0 h1:heAkClL8H6w+mK5md9dzsuohKeXHUpY7Vw0ZCKW+huA= +github.com/tevino/abool v1.2.0/go.mod h1:qc66Pna1RiIsPa7O4Egxxs9OqkuxDX55zznh9K07Tzg= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= +golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gvisor.dev/gvisor v0.0.0-20250611222258-0fe9a4bf489c h1:zeegxqAHXPEbeF+KlgmaQWwbc4V3NUZPjHog53ynS/4= +gvisor.dev/gvisor v0.0.0-20250611222258-0fe9a4bf489c/go.mod h1:3r5CMtNQMKIvBlrmM9xWUNamjKBYPOWyXOjmg5Kts3g= diff --git a/nym-gateway-probe/netstack_ping/lib.go b/nym-gateway-probe/netstack_ping/lib.go new file mode 100644 index 0000000000..ba41899e2a --- /dev/null +++ b/nym-gateway-probe/netstack_ping/lib.go @@ -0,0 +1,566 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2024 Nym Technologies SA . All Rights Reserved. + */ + +package main + +// #include +import "C" + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "log" + "math" + "math/rand" + "net" + "net/http" + "net/netip" + netUrl "net/url" + "os" + "strings" + "time" + "unsafe" + + "github.com/amnezia-vpn/amneziawg-go/conn" + "github.com/amnezia-vpn/amneziawg-go/device" + "github.com/amnezia-vpn/amneziawg-go/tun/netstack" + "golang.org/x/net/icmp" + "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" +) + +var fileUrls = []string{ + "https://proof.ovh.net/files/1Mb.dat", + "https://nym-bandwidth-monitoring.ops-d86.workers.dev/1mb.dat", + "https://nym-bandwidth-monitoring.ops-d86.workers.dev/10mb.dat", + // "https://nym-bandwidth-monitoring.ops-d86.workers.dev/100mb.dat", to be introduced later +} + +var fileUrlsV6 = []string{ + "https://proof.ovh.net/files/1Mb.dat", + "https://nym-bandwidth-monitoring.ops-d86.workers.dev/1mb.dat", + "https://nym-bandwidth-monitoring.ops-d86.workers.dev/10mb.dat", + // "https://nym-bandwidth-monitoring.ops-d86.workers.dev/100mb.dat", to be introduced later +} + +type NetstackRequestGo struct { + WgIp string `json:"wg_ip"` + PrivateKey string `json:"private_key"` + PublicKey string `json:"public_key"` + Endpoint string `json:"endpoint"` + MetadataEndpoint string `json:"metadata_endpoint"` + Dns string `json:"dns"` + IpVersion uint8 `json:"ip_version"` + PingHosts []string `json:"ping_hosts"` + PingIps []string `json:"ping_ips"` + NumPing uint8 `json:"num_ping"` + SendTimeoutSec uint64 `json:"send_timeout_sec"` + RecvTimeoutSec uint64 `json:"recv_timeout_sec"` + DownloadTimeoutSec uint64 `json:"download_timeout_sec"` + MetadataTimeoutSec uint64 `json:"metadata_timeout_sec"` + AwgArgs string `json:"awg_args"` +} + +type NetstackResponse struct { + CanHandshake bool `json:"can_handshake"` + CanQueryMetadata bool `json:"can_query_metadata"` + SentIps uint16 `json:"sent_ips"` + ReceivedIps uint16 `json:"received_ips"` + SentHosts uint16 `json:"sent_hosts"` + ReceivedHosts uint16 `json:"received_hosts"` + CanResolveDns bool `json:"can_resolve_dns"` + DownloadedFile string `json:"downloaded_file"` + DownloadedFileSizeBytes uint64 `json:"downloaded_file_size_bytes"` + DownloadDurationSec uint64 `json:"download_duration_sec"` + DownloadDurationMilliseconds uint64 `json:"download_duration_milliseconds"` + DownloadError string `json:"download_error"` +} + +type SuccessResult = struct { + Response NetstackResponse `json:"response"` +} + +type ErrorResult = struct { + Error string `json:"error"` +} + +func jsonResponse(response NetstackResponse) *C.char { + bytes, serializeErr := json.Marshal(SuccessResult{ + Response: response, + }) + if serializeErr == nil { + return C.CString(string(bytes)) + } else { + return C.CString("{\"error\":\"" + serializeErr.Error() + "\"}") + } +} + +func jsonError(err error) *C.char { + jsonErr := ErrorResult{ + Error: fmt.Sprintf("failed to parse request: %s", err.Error()), + } + bytes, serializeErr := json.Marshal(jsonErr) + if serializeErr == nil { + return C.CString(string(bytes)) + } else { + return C.CString("{\"error\":\"" + serializeErr.Error() + "\"}") + } +} + +//export wgPing +func wgPing(cReq *C.char) *C.char { + reqStr := C.GoString(cReq) + + var req NetstackRequestGo + err := json.Unmarshal([]byte(reqStr), &req) + if err != nil { + log.Printf("Failed to parse request: %s", err) + return jsonError(err) + } + + response, err := ping(req) + if err != nil { + log.Printf("Failed to ping: %s", err) + return jsonError(err) + } + + return jsonResponse(response) +} + +//export wgFreePtr +func wgFreePtr(ptr unsafe.Pointer) { + C.free(ptr) +} + +func ping(req NetstackRequestGo) (NetstackResponse, error) { + fmt.Printf("Endpoint: %s\n", req.Endpoint) + fmt.Printf("WireGuard IP: %s\n", req.WgIp) + fmt.Printf("IP version: %d\n", req.IpVersion) + + tun, tnet, err := netstack.CreateNetTUN( + []netip.Addr{netip.MustParseAddr(req.WgIp)}, + []netip.Addr{netip.MustParseAddr(req.Dns)}, + 1280) + + if err != nil { + return NetstackResponse{}, err + } + dev := device.NewDevice(tun, conn.NewDefaultBind(), device.NewLogger(device.LogLevelError, "")) + + var ipc strings.Builder + + ipc.WriteString("private_key=") + ipc.WriteString(req.PrivateKey) + if req.AwgArgs != "" { + awg := strings.ReplaceAll(req.AwgArgs, "\\n", "\n") + ipc.WriteString(fmt.Sprintf("\n%s", awg)) + } + ipc.WriteString("\npublic_key=") + ipc.WriteString(req.PublicKey) + ipc.WriteString("\nendpoint=") + ipc.WriteString(req.Endpoint) + if req.IpVersion == 4 { + ipc.WriteString("\nallowed_ip=0.0.0.0/0\n") + } else { + ipc.WriteString("\nallowed_ip=::/0\n") + } + + response := NetstackResponse{false, false, 0, 0, 0, 0, false, "", 0, 0, 0, ""} + + err = dev.IpcSet(ipc.String()) + if err != nil { + return NetstackResponse{}, err + } + + config, err := dev.IpcGet() + if err != nil { + return NetstackResponse{}, err + } + + // do not print the config by default, because it contains the wg private key + if os.Getenv("SHOW_WG_CONFIG") == "true" { + log.Printf("%s", config) + } + + err = dev.Up() + if err != nil { + return NetstackResponse{}, err + } + + response.CanHandshake = true + + version, duration, err := queryMetadata(req.MetadataEndpoint, req.MetadataTimeoutSec, tnet) + if err != nil { + log.Printf("Failed to query metadata URLs: %v\n", err) + response.CanQueryMetadata = false + } else { + log.Printf("Queried metadata endpoint with version: %v\n", version) + log.Printf("Query duration: %v\n", duration) + response.CanQueryMetadata = true + } + + for _, host := range req.PingHosts { + consecutiveFailures := 0 + maxConsecutiveFailures := 3 + + for i := uint8(0); i < req.NumPing; i++ { + log.Printf("Pinging %s seq=%d", host, i) + response.SentHosts += 1 + rt, err := sendPing(host, i, req.SendTimeoutSec, req.RecvTimeoutSec, tnet, req.IpVersion) + if err != nil { + log.Printf("Failed to send ping: %v\n", err) + consecutiveFailures++ + + // Early exit if too many consecutive failures + if consecutiveFailures >= maxConsecutiveFailures { + log.Printf("Too many consecutive failures (%d), stopping ping attempts for %s", consecutiveFailures, host) + break + } + continue + } + + // Reset failure counter on success + consecutiveFailures = 0 + response.ReceivedHosts += 1 + response.CanResolveDns = true + log.Printf("Ping latency: %v\n", rt) + } + } + + for _, ip := range req.PingIps { + consecutiveFailures := 0 + maxConsecutiveFailures := 3 + + for i := uint8(0); i < req.NumPing; i++ { + log.Printf("Pinging %s seq=%d", ip, i) + response.SentIps += 1 + rt, err := sendPing(ip, i, req.SendTimeoutSec, req.RecvTimeoutSec, tnet, req.IpVersion) + if err != nil { + log.Printf("Failed to send ping: %v\n", err) + consecutiveFailures++ + + // Early exit if too many consecutive failures + if consecutiveFailures >= maxConsecutiveFailures { + log.Printf("Too many consecutive failures (%d), stopping ping attempts for %s", consecutiveFailures, ip) + break + } + } else { + // Reset failure counter on success + consecutiveFailures = 0 + response.ReceivedIps += 1 + log.Printf("Ping latency: %v\n", rt) + } + + // Sleep between ping attempts (except for the last one) + if i < req.NumPing-1 { + time.Sleep(5 * time.Second) + } + } + } + + var urlsToTry []string + + if req.IpVersion == 4 { + urlsToTry = fileUrls + } else { + urlsToTry = fileUrlsV6 + } + + // Try URLs with retry logic + fileContent, downloadDuration, usedURL, err := downloadFileWithRetry(urlsToTry, req.DownloadTimeoutSec, tnet) + if err != nil { + log.Printf("Failed to download file from any URL: %v\n", err) + } else { + log.Printf("Downloaded file content length: %.2f MB\n", float64(len(fileContent))/1024/1024) + log.Printf("Download duration: %v\n", downloadDuration) + } + + response.DownloadDurationSec = uint64(downloadDuration.Seconds()) + response.DownloadDurationMilliseconds = uint64(downloadDuration.Milliseconds()) + response.DownloadedFile = usedURL + if err != nil { + response.DownloadError = err.Error() + response.DownloadedFileSizeBytes = 0 + } else { + response.DownloadError = "" + response.DownloadedFileSizeBytes = uint64(len(fileContent)) + } + + return response, nil +} + +func sendPing(address string, seq uint8, sendTtimeoutSecs uint64, receiveTimoutSecs uint64, tnet *netstack.Net, ipVersion uint8) (time.Duration, error) { + maxPingRetries := 2 + baseTimeout := receiveTimoutSecs + + for attempt := 0; attempt < maxPingRetries; attempt++ { + // Slightly increase timeout on retries, but keep it reasonable + adjustedTimeout := baseTimeout + uint64(attempt*1) // +1s per retry only + + duration, err := sendPingAttempt(address, seq, sendTtimeoutSecs, adjustedTimeout, tnet, ipVersion) + if err == nil { + return duration, nil + } + + log.Printf("Ping attempt %d/%d failed: %v", attempt+1, maxPingRetries, err) + if attempt < maxPingRetries-1 { + time.Sleep(200 * time.Millisecond) // Very brief delay between retries + } + } + + return 0, fmt.Errorf("ping failed after %d attempts", maxPingRetries) +} + +func sendPingAttempt(address string, seq uint8, sendTtimeoutSecs uint64, receiveTimoutSecs uint64, tnet *netstack.Net, ipVersion uint8) (time.Duration, error) { + var socket net.Conn + var err error + if ipVersion == 4 { + socket, err = tnet.Dial("ping4", address) + } else { + socket, err = tnet.Dial("ping6", address) + } + + if err != nil { + return 0, err + } + defer socket.Close() + + var icmpBytes []byte + + requestPing := icmp.Echo{ + ID: 1337, + Seq: int(seq), + Data: []byte("gopher burrow"), + } + + if ipVersion == 4 { + icmpBytes, _ = (&icmp.Message{Type: ipv4.ICMPTypeEcho, Code: 0, Body: &requestPing}).Marshal(nil) + } else { + icmpBytes, _ = (&icmp.Message{Type: ipv6.ICMPTypeEchoRequest, Code: 0, Body: &requestPing}).Marshal(nil) + } + + start := time.Now() + + socket.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(sendTtimeoutSecs))) + _, err = socket.Write(icmpBytes) + if err != nil { + return 0, err + } + + // Wait for reply with limited read attempts to avoid long delays + maxReadAttempts := 2 + for readAttempt := 0; readAttempt < maxReadAttempts; readAttempt++ { + socket.SetReadDeadline(time.Now().Add(time.Second * time.Duration(receiveTimoutSecs))) + n, err := socket.Read(icmpBytes[:]) + if err != nil { + if readAttempt < maxReadAttempts-1 { + log.Printf("Read attempt %d failed, retrying: %v", readAttempt+1, err) + continue + } + return 0, err + } + + var proto int + if ipVersion == 4 { + proto = 1 + } else { + proto = 58 + } + + replyPacket, err := icmp.ParseMessage(proto, icmpBytes[:n]) + if err != nil { + if readAttempt < maxReadAttempts-1 { + log.Printf("Parse attempt %d failed, retrying: %v", readAttempt+1, err) + continue + } + return 0, err + } + + var ok bool + replyPing, ok := replyPacket.Body.(*icmp.Echo) + + if !ok { + if readAttempt < maxReadAttempts-1 { + log.Printf("Invalid reply type attempt %d, retrying", readAttempt+1) + continue + } + return 0, fmt.Errorf("invalid reply type: %v", replyPacket) + } + + if bytes.Equal(replyPing.Data, requestPing.Data) { + // Accept sequence number matches or close matches (for out-of-order delivery) + if replyPing.Seq == requestPing.Seq || math.Abs(float64(replyPing.Seq-requestPing.Seq)) <= 1 { + return time.Since(start), nil + } + log.Printf("Sequence mismatch (expected %d, received %d), retrying", requestPing.Seq, replyPing.Seq) + } else { + if readAttempt < maxReadAttempts-1 { + log.Printf("Data mismatch attempt %d, retrying", readAttempt+1) + continue + } + return 0, fmt.Errorf("invalid ping reply: %v (request: %v)", replyPing, requestPing) + } + } + + return 0, fmt.Errorf("ping failed after %d read attempts", maxReadAttempts) +} + +func downloadFileWithRetry(urls []string, timeoutSecs uint64, tnet *netstack.Net) ([]byte, time.Duration, string, error) { + maxRetries := 3 + baseDelay := 1 * time.Second + consecutiveFailures := 0 + maxConsecutiveFailures := 3 + + for attempt := 0; attempt < maxRetries; attempt++ { + // Shuffle URLs for each attempt to try different ones + shuffledUrls := make([]string, len(urls)) + copy(shuffledUrls, urls) + rand.Shuffle(len(shuffledUrls), func(i, j int) { + shuffledUrls[i], shuffledUrls[j] = shuffledUrls[j], shuffledUrls[i] + }) + + for _, url := range shuffledUrls { + log.Printf("Attempting download from: %s (attempt %d/%d)", url, attempt+1, maxRetries) + // Increase timeout on retries to handle slow servers + adjustedTimeout := timeoutSecs + uint64(attempt*5) // +5s per retry + content, duration, err := downloadFile(url, adjustedTimeout, tnet) + if err == nil { + log.Printf("Successfully downloaded from: %s", url) + return content, duration, url, nil + } + log.Printf("Failed to download from %s: %v", url, err) + consecutiveFailures++ + + // Early exit if too many consecutive failures + if consecutiveFailures >= maxConsecutiveFailures { + log.Printf("Too many consecutive download failures (%d), stopping attempts", consecutiveFailures) + return nil, 0, "", fmt.Errorf("too many consecutive failures (%d), stopping download attempts", consecutiveFailures) + } + } + + if attempt < maxRetries-1 { + delay := baseDelay * time.Duration(attempt+1) + log.Printf("All URLs failed, retrying in %v...", delay) + time.Sleep(delay) + } + } + + return nil, 0, "", fmt.Errorf("failed to download from any URL after %d attempts", maxRetries) +} + +func downloadFile(url string, timeoutSecs uint64, tnet *netstack.Net) ([]byte, time.Duration, error) { + transport := &http.Transport{ + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + return tnet.Dial(network, addr) + }, + } + + client := &http.Client{ + Transport: transport, + Timeout: time.Second * time.Duration(timeoutSecs), + } + + start := time.Now() // Start timing + + resp, err := client.Get(url) + if err != nil { + return nil, 0, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, 0, fmt.Errorf("failed to download file: %s", resp.Status) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, resp.Body) + if err != nil { + return nil, 0, err + } + + duration := time.Since(start) // Calculate duration + + return buf.Bytes(), duration, nil +} + +func queryMetadata(url string, timeoutSecs uint64, tnet *netstack.Net) (int, time.Duration, error) { + transport := &http.Transport{ + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + return tnet.Dial(network, addr) + }, + } + + client := &http.Client{ + Transport: transport, + Timeout: time.Second * time.Duration(timeoutSecs), + } + + bandwidthVersionUrl, err := netUrl.JoinPath(url, "v1/bandwidth/version") + if err != nil { + return 0, 0, err + } + + start := time.Now() // Start timing + + log.Printf("Querying metadata encoding: url = %s", bandwidthVersionUrl) + resp, err := client.Get(bandwidthVersionUrl) + if err != nil { + return 0, 0, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return 0, 0, fmt.Errorf("failed to query metadata endpoint: %s", resp.Status) + } + + var contentType = resp.Header.Get("Content-Type") + + log.Printf("Metadata Content-Type: %s", contentType) + + var reader io.Reader = resp.Body + bodyBytes, err := io.ReadAll(reader) + if err != nil { + return 0, 0, err + } + + var version int + err = json.Unmarshal(bodyBytes, &version) + if err != nil { + return 0, 0, err + } + + duration := time.Since(start) // Calculate duration + + return version, duration, nil +} + +func main() { + // uncomment the lines below to run locally and see README.md for how to get the Wireguard config + /* var _, err = ping(NetstackRequestGo{ + WgIp: "10.1.155.153", + PrivateKey: "...", + PublicKey: "...", + Endpoint: "13.245.9.123:51822", + MetadataEndpoint: "http://10.1.0.1:51830", + Dns: "1.1.1.1", + IpVersion: 4, + //PingHosts: nil, + //PingIps: nil, + //NumPing: 0, + //SendTimeoutSec: 0, + //RecvTimeoutSec: 0, + //DownloadTimeoutSec: 0, + MetadataTimeoutSec: 5, + //AwgArgs: "", + }) + + if err != nil { + log.Fatal(err) + } + */ +} diff --git a/nym-gateway-probe/netstack_ping/lib_test.go b/nym-gateway-probe/netstack_ping/lib_test.go new file mode 100644 index 0000000000..29b7d7b272 --- /dev/null +++ b/nym-gateway-probe/netstack_ping/lib_test.go @@ -0,0 +1,319 @@ +package main + +import ( + "math" + "testing" +) + +// Test the abs helper function +func TestAbs(t *testing.T) { + tests := []struct { + input int + expected int + }{ + {5, 5}, + {-5, 5}, + {0, 0}, + {-1, 1}, + {1, 1}, + } + + for _, test := range tests { + result := int(math.Abs(float64(test.input))) + if result != test.expected { + t.Errorf("abs(%d) = %d, expected %d", test.input, result, test.expected) + } + } +} + +// Test URL shuffling behavior +func TestURLShuffling(t *testing.T) { + urls := []string{"url1", "url2", "url3"} + + shuffledUrls := make([]string, len(urls)) + copy(shuffledUrls, urls) + + if len(shuffledUrls) != len(urls) { + t.Error("Shuffled URLs length mismatch") + } + + // Test that all original URLs are still present + for _, originalURL := range urls { + found := false + for _, shuffledURL := range shuffledUrls { + if shuffledURL == originalURL { + found = true + break + } + } + if !found { + t.Errorf("URL %s not found in shuffled list", originalURL) + } + } +} + +// Test timeout progression logic +func TestTimeoutProgression(t *testing.T) { + baseTimeout := uint64(5) + + // Test ping timeout progression (+1s per retry) + for attempt := 0; attempt < 3; attempt++ { + expectedTimeout := baseTimeout + uint64(attempt*1) + actualTimeout := baseTimeout + uint64(attempt*1) + + if actualTimeout != expectedTimeout { + t.Errorf("Ping attempt %d: expected timeout %d, got %d", attempt, expectedTimeout, actualTimeout) + } + } + + // Test download timeout progression (+5s per retry) + for attempt := 0; attempt < 3; attempt++ { + expectedTimeout := baseTimeout + uint64(attempt*5) + actualTimeout := baseTimeout + uint64(attempt*5) + + if actualTimeout != expectedTimeout { + t.Errorf("Download attempt %d: expected timeout %d, got %d", attempt, expectedTimeout, actualTimeout) + } + } +} + +// Test consecutive failure counting logic +func TestConsecutiveFailures(t *testing.T) { + maxFailures := 3 + consecutiveFailures := 0 + + // Simulate failures + for i := 0; i < maxFailures; i++ { + consecutiveFailures++ + if consecutiveFailures >= maxFailures { + break + } + } + + if consecutiveFailures != maxFailures { + t.Errorf("Expected %d consecutive failures, got %d", maxFailures, consecutiveFailures) + } +} + +// Test early exit logic +func TestEarlyExitLogic(t *testing.T) { + maxConsecutiveFailures := 3 + consecutiveFailures := 0 + + // Simulate early exit after 3 failures + for i := 0; i < 5; i++ { // Try 5 times + consecutiveFailures++ + if consecutiveFailures >= maxConsecutiveFailures { + break // Early exit + } + } + + if consecutiveFailures != maxConsecutiveFailures { + t.Errorf("Expected early exit after %d failures, got %d", maxConsecutiveFailures, consecutiveFailures) + } +} + +// Test URL list selection logic +func TestURLListSelection(t *testing.T) { + // Test IPv4 URL selection + ipVersion := uint8(4) + var urlsToTry []string + + if ipVersion == 4 { + urlsToTry = fileUrls + } else { + urlsToTry = fileUrlsV6 + } + + if len(urlsToTry) == 0 { + t.Error("Expected non-empty URL list for IPv4") + } + + // Test IPv6 URL selection + ipVersion = uint8(6) + if ipVersion == 4 { + urlsToTry = fileUrls + } else { + urlsToTry = fileUrlsV6 + } + + if len(urlsToTry) == 0 { + t.Error("Expected non-empty URL list for IPv6") + } +} + +// Test NetstackResponse struct creation +func TestNetstackResponse(t *testing.T) { + response := NetstackResponse{ + CanHandshake: true, + SentIps: 5, + ReceivedIps: 5, + SentHosts: 5, + ReceivedHosts: 5, + CanResolveDns: true, + DownloadedFile: "test.dat", + DownloadDurationSec: 1, + DownloadError: "", + } + + // Test that all fields are set correctly + if !response.CanHandshake { + t.Error("CanHandshake should be true") + } + + if response.SentIps != 5 { + t.Error("SentIps should be 5") + } + + if response.ReceivedIps != 5 { + t.Error("ReceivedIps should be 5") + } + + if response.DownloadedFile != "test.dat" { + t.Error("DownloadedFile should be 'test.dat'") + } +} + +// Test NetstackRequestGo struct creation +func TestNetstackRequestGo(t *testing.T) { + request := NetstackRequestGo{ + WgIp: "10.0.0.1", + PrivateKey: "test-key", + PublicKey: "test-pub-key", + Endpoint: "1.1.1.1:51820", + Dns: "1.1.1.1", + IpVersion: 4, + PingHosts: []string{"example.com"}, + PingIps: []string{"1.1.1.1"}, + NumPing: 3, + SendTimeoutSec: 5, + RecvTimeoutSec: 10, + DownloadTimeoutSec: 30, + AwgArgs: "", + } + + // Test that all fields are set correctly + if request.WgIp != "10.0.0.1" { + t.Error("WgIp should be '10.0.0.1'") + } + + if request.IpVersion != 4 { + t.Error("IpVersion should be 4") + } + + if len(request.PingHosts) != 1 { + t.Error("PingHosts should have 1 element") + } + + if request.NumPing != 3 { + t.Error("NumPing should be 3") + } +} + +// Test the ping function with valid request (will fail due to network setup) +func TestPingFunction(t *testing.T) { + // Create a request with valid IP but will fail due to network setup + req := NetstackRequestGo{ + WgIp: "10.0.0.1", + PrivateKey: "test-key", + PublicKey: "test-pub-key", + Endpoint: "1.1.1.1:51820", + Dns: "1.1.1.1", + IpVersion: 4, + PingHosts: []string{"example.com"}, + PingIps: []string{"1.1.1.1"}, + NumPing: 1, + SendTimeoutSec: 1, + RecvTimeoutSec: 1, + DownloadTimeoutSec: 5, + AwgArgs: "", + } + + // This should complete (even with network timeouts) and not crash + response, err := ping(req) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + // Check that we got a valid response structure + if response.CanHandshake != true { + t.Error("Expected CanHandshake to be true") + } + + // The response should show the retry attempts worked + t.Logf("Response: CanHandshake=%v, SentHosts=%d, ReceivedHosts=%d, DownloadedFile=%s", + response.CanHandshake, response.SentHosts, response.ReceivedHosts, response.DownloadedFile) +} + +// Test the SuccessResult and ErrorResult structs +func TestResultStructs(t *testing.T) { + // Test SuccessResult + response := NetstackResponse{ + CanHandshake: true, + SentIps: 5, + ReceivedIps: 5, + SentHosts: 5, + ReceivedHosts: 5, + CanResolveDns: true, + DownloadedFile: "test.dat", + DownloadDurationSec: 1, + DownloadError: "", + } + + successResult := SuccessResult{Response: response} + if !successResult.Response.CanHandshake { + t.Error("SuccessResult should contain valid response") + } + + // Test ErrorResult + errorResult := ErrorResult{Error: "test error"} + if errorResult.Error != "test error" { + t.Error("ErrorResult should contain error message") + } +} + +// TestConsecutiveFailureExit validates that the ping loop exits cleanly after consecutive failures +func TestConsecutiveFailureExit(t *testing.T) { + // Create a test request that will trigger consecutive failures + req := NetstackRequestGo{ + WgIp: "10.0.0.1", + PrivateKey: "test-key", + PublicKey: "test-pub-key", + Endpoint: "1.1.1.1:51820", + Dns: "1.1.1.1", + IpVersion: 4, + PingHosts: []string{}, // No hosts to ping + PingIps: []string{"192.0.2.1"}, // RFC 5737 test IP that should fail + NumPing: 5, // Try 5 pings + SendTimeoutSec: 1, // Short timeout to ensure failures + RecvTimeoutSec: 1, + DownloadTimeoutSec: 1, + AwgArgs: "", + } + + // Execute the ping function - this should exit cleanly after consecutive failures + response, err := ping(req) + + // Verify the response shows we attempted pings but got failures + if response.SentIps == 0 { + t.Error("Should have attempted to send at least one ping") + } + + // Verify we received no successful pings (since we're using a test IP) + if response.ReceivedIps > 0 { + t.Logf("Unexpected success: received %d pings", response.ReceivedIps) + } + + // The key test: verify we don't hang and return cleanly + if err != nil { + t.Logf("Function returned with error (expected): %v", err) + } + + // Verify we didn't send all 5 pings due to early exit + // We should have sent at most 3 pings before hitting consecutive failure limit + if response.SentIps > 3 { + t.Errorf("Should have exited early after consecutive failures, but sent %d pings", response.SentIps) + } + + t.Logf("Test completed cleanly: sent %d pings, received %d pings", response.SentIps, response.ReceivedIps) +} diff --git a/nym-gateway-probe/src/bandwidth_helpers.rs b/nym-gateway-probe/src/bandwidth_helpers.rs new file mode 100644 index 0000000000..4753265166 --- /dev/null +++ b/nym-gateway-probe/src/bandwidth_helpers.rs @@ -0,0 +1,157 @@ +// Copyright 2025 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::{Context, bail}; +use nym_bandwidth_controller::error::BandwidthControllerError; +use nym_client_core::client::base_client::storage::OnDiskPersistent; +use nym_credentials_interface::TicketType; +use nym_node_status_client::models::AttachedTicketMaterials; +use nym_sdk::bandwidth::BandwidthImporter; +use nym_sdk::mixnet::{DisconnectedMixnetClient, EphemeralCredentialStorage}; +use nym_validator_client::nyxd::error::NyxdError; +use std::time::Duration; +use tracing::{error, info}; + +pub(crate) async fn import_bandwidth( + bandwidth_importer: BandwidthImporter<'_, EphemeralCredentialStorage>, + attached_ticket_materials: AttachedTicketMaterials, +) -> anyhow::Result<()> { + // 1. import all auxiliary data + for master_vk in attached_ticket_materials.master_verification_keys { + let key = master_vk.try_unpack()?; + info!( + "importing master verification key for epoch {}", + key.epoch_id + ); + bandwidth_importer + .import_master_verification_key(&key) + .await?; + } + for coin_index_signatures in attached_ticket_materials.coin_indices_signatures { + let sigs = coin_index_signatures.try_unpack()?; + info!("importing coin index signatures epoch {}", sigs.epoch_id); + bandwidth_importer + .import_coin_index_signatures(&sigs) + .await?; + } + for expiration_date_signatures in attached_ticket_materials.expiration_date_signatures { + let sigs = expiration_date_signatures.try_unpack()?; + info!( + "importing expiration date signatures epoch {} and expiration {}", + sigs.epoch_id, sigs.expiration_date + ); + bandwidth_importer + .import_expiration_date_signatures(&sigs) + .await?; + } + + // 2. import actual tickets + for ticket in attached_ticket_materials.attached_tickets { + let ticketbook = ticket.ticketbook.try_unpack()?; + info!( + "importing partial ticketbook {}. index to use: {}", + ticketbook.ticketbook_type(), + ticket.usable_index + ); + bandwidth_importer + .import_partial_ticketbook(&ticketbook, ticket.usable_index, ticket.usable_index) + .await?; + } + + Ok(()) +} + +pub(crate) async fn acquire_bandwidth( + mnemonic: &str, + disconnected_mixnet_client: &DisconnectedMixnetClient, + ticketbook_type: TicketType, +) -> anyhow::Result<()> { + // TODO: make it configurable + const MAX_RETRIES: usize = 50; + for i in 0..MAX_RETRIES { + let attempt = i + 1; // since humans usually don't count from 0 in this instance + info!( + "attempt {attempt}/{MAX_RETRIES} for attempting to acquire {ticketbook_type} bandwidth" + ); + let bw_client = disconnected_mixnet_client + .create_bandwidth_client(mnemonic.to_string(), ticketbook_type) + .await?; + info!("Calling bandwidth controller acquire() for {ticketbook_type}"); + match bw_client.acquire().await { + Ok(_) => { + if i > 0 { + info!( + "managed to acquire {ticketbook_type} bandwidth after {attempt} attempts", + ); + } + return Ok(()); + } + Err(nym_sdk::Error::CredentialIssuanceError { source }) => match source { + nym_credential_utils::errors::Error::BandwidthControllerError( + BandwidthControllerError::Nyxd(nyxd_error), + ) => match nyxd_error { + // happens when sequence issue occurs during tx delivery + NyxdError::BroadcastTxErrorDeliverTx { + hash, + height, + code, + raw_log, + } => { + // unfortunately at this point we have to do string matching as the log + // is returned from the go nyxd binary + if raw_log.contains("account sequence mismatch") { + error!( + "another process is using the same mnemonic. we failed to broadcast transaction {hash} due to mismatched sequence number" + ) + } else { + return Err(NyxdError::BroadcastTxErrorDeliverTx { + hash, + height, + code, + raw_log, + } + .into()); + } + } + // happens when sequence issue occurs during tx simulate + NyxdError::AbciError { + code, + log, + pretty_log, + } => { + // unfortunately at this point we have to do string matching as the log + // is returned from the go nyxd binary + if log.contains("account sequence mismatch") { + error!( + "another process is using the same mnemonic. we failed to simulate transaction due to mismatched sequence number" + ) + } else { + return Err(NyxdError::AbciError { + code, + log, + pretty_log, + } + .into()); + } + } + other => { + return Err(other) + .context("another nyxd failure during bandwidth acquisition"); + } + }, + other => { + return Err(other.into()); + } + }, + Err(other) => { + return Err(other.into()); + } + } + + // add a bit of backoff as if the rpc node is slightly out of sync, + // we might use our retry budget for abci queries to the simulate endpoint + tokio::time::sleep(Duration::from_secs(1)).await; + } + + bail!("failed to acquire bandwidth after {MAX_RETRIES} attempts") +} diff --git a/nym-gateway-probe/src/icmp.rs b/nym-gateway-probe/src/icmp.rs new file mode 100644 index 0000000000..ec757623f1 --- /dev/null +++ b/nym-gateway-probe/src/icmp.rs @@ -0,0 +1,120 @@ +use std::net::{Ipv4Addr, Ipv6Addr}; + +use bytes::Bytes; +use nym_connection_monitor::{ + ConnectionStatusEvent, IcmpBeaconReply, Icmpv6BeaconReply, is_icmp_beacon_reply, + is_icmp_v6_beacon_reply, + packet_helpers::{ + create_icmpv4_echo_request, create_icmpv6_echo_request, wrap_icmp_in_ipv4, + wrap_icmp_in_ipv6, + }, +}; +use nym_ip_packet_requests::{IpPair, codec::MultiIpPacketCodec, v8::request::IpPacketRequest}; +use nym_sdk::mixnet::{ + InputMessage, MixnetClient, MixnetMessageSender, Recipient, TransmissionLane, +}; +use pnet_packet::Packet; + +pub fn icmp_identifier() -> u16 { + 8475 +} + +pub async fn send_ping_v4( + mixnet_client: &MixnetClient, + our_ips: IpPair, + sequence_number: u16, + destination: Ipv4Addr, + exit_router_address: Recipient, +) -> anyhow::Result<()> { + let icmp_identifier = icmp_identifier(); + let icmp_echo_request = create_icmpv4_echo_request(sequence_number, icmp_identifier)?; + let ipv4_packet = wrap_icmp_in_ipv4(icmp_echo_request, our_ips.ipv4, destination)?; + + // Wrap the IPv4 packet in a MultiIpPacket + let bundled_packet = + 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)?; + + mixnet_client.send(mixnet_message).await?; + Ok(()) +} + +pub async fn send_ping_v6( + mixnet_client: &MixnetClient, + our_ips: IpPair, + sequence_number: u16, + destination: Ipv6Addr, + exit_router_address: Recipient, +) -> anyhow::Result<()> { + let icmp_identifier = icmp_identifier(); + let icmp_echo_request = create_icmpv6_echo_request( + sequence_number, + icmp_identifier, + &our_ips.ipv6, + &destination, + )?; + let ipv6_packet = wrap_icmp_in_ipv6(icmp_echo_request, our_ips.ipv6, destination)?; + + // Wrap the IPv6 packet in a MultiIpPacket + let bundled_packet = + 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)?; + + // Send across the mixnet + mixnet_client.send(mixnet_message).await?; + Ok(()) +} + +fn create_input_message( + recipient: impl Into, + bundled_packets: Bytes, +) -> anyhow::Result { + let packet = IpPacketRequest::new_data_request(bundled_packets).to_bytes()?; + + let lane = TransmissionLane::General; + let packet_type = None; + let surbs = 0; + Ok(InputMessage::new_anonymous( + recipient.into(), + packet, + surbs, + lane, + packet_type, + )) +} + +pub fn check_for_icmp_beacon_reply( + packet: &Bytes, + icmp_beacon_identifier: u16, + our_ips: IpPair, +) -> Option { + match is_icmp_beacon_reply(packet, icmp_beacon_identifier, our_ips.ipv4) { + Some(IcmpBeaconReply::TunDeviceReply) => { + tracing::debug!("Received ping response from ipr tun device"); + return Some(ConnectionStatusEvent::Icmpv4IprTunDevicePingReply); + } + Some(IcmpBeaconReply::ExternalPingReply(_source)) => { + tracing::debug!("Received ping response from an external ip through the ipr"); + return Some(ConnectionStatusEvent::Icmpv4IprExternalPingReply); + } + None => {} + } + + match is_icmp_v6_beacon_reply(packet, icmp_beacon_identifier, our_ips.ipv6) { + Some(Icmpv6BeaconReply::TunDeviceReply) => { + tracing::debug!("Received ping v6 response from ipr tun device"); + return Some(ConnectionStatusEvent::Icmpv6IprTunDevicePingReply); + } + Some(Icmpv6BeaconReply::ExternalPingReply(_source)) => { + tracing::debug!("Received ping v6 response from an external ip through the ipr"); + return Some(ConnectionStatusEvent::Icmpv6IprExternalPingReply); + } + None => {} + } + + None +} diff --git a/nym-gateway-probe/src/lib.rs b/nym-gateway-probe/src/lib.rs new file mode 100644 index 0000000000..2224c911e0 --- /dev/null +++ b/nym-gateway-probe/src/lib.rs @@ -0,0 +1,1085 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use std::{ + net::{IpAddr, Ipv4Addr, Ipv6Addr}, + sync::Arc, + time::Duration, +}; + +use crate::{netstack::NetstackResult, types::Entry}; +use anyhow::bail; +use base64::{Engine as _, engine::general_purpose}; +use bytes::BytesMut; +use clap::Args; +use futures::StreamExt; +use nym_authenticator_client::{AuthClientMixnetListener, AuthenticatorClient}; +use nym_authenticator_requests::{ + AuthenticatorVersion, client_message::ClientMessage, response::AuthenticatorResponse, v2, v3, + v4, v5, +}; +use nym_client_core::config::ForgetMe; +use nym_config::defaults::{ + NymNetworkDetails, WG_METADATA_PORT, WG_TUN_DEVICE_IP_ADDRESS_V4, + mixnet_vpn::{NYM_TUN_DEVICE_ADDRESS_V4, NYM_TUN_DEVICE_ADDRESS_V6}, +}; +use nym_connection_monitor::self_ping_and_wait; +use nym_credentials_interface::{CredentialSpendingData, TicketType}; +use nym_crypto::asymmetric::x25519::KeyPair; +use nym_ip_packet_client::IprClientConnect; +use nym_ip_packet_requests::{ + IpPair, + codec::MultiIpPacketCodec, + v8::response::{ + ControlResponse, DataResponse, InfoLevel, IpPacketResponse, IpPacketResponseData, + }, +}; +use nym_sdk::mixnet::{ + CredentialStorage, Ephemeral, KeyStore, MixnetClient, MixnetClientBuilder, MixnetClientStorage, + NodeIdentity, Recipient, ReconstructedMessage, StoragePaths, +}; +use rand::rngs::OsRng; +use std::path::PathBuf; + +use tokio_util::{codec::Decoder, sync::CancellationToken}; +use tracing::*; +use types::WgProbeResults; +use url::Url; + +use crate::{ + icmp::{check_for_icmp_beacon_reply, icmp_identifier, send_ping_v4, send_ping_v6}, + types::Exit, +}; + +use netstack::{NetstackRequest, NetstackRequestGo}; + +mod bandwidth_helpers; +mod icmp; +mod netstack; +pub mod nodes; +mod types; + +use crate::bandwidth_helpers::{acquire_bandwidth, import_bandwidth}; +use crate::nodes::NymApiDirectory; +use nym_node_status_client::models::AttachedTicketMaterials; +pub use types::{IpPingReplies, ProbeOutcome, ProbeResult}; + +#[derive(Args, Clone)] +pub struct NetstackArgs { + #[arg(long, default_value_t = 180)] + netstack_download_timeout_sec: u64, + + #[arg(long, default_value_t = 30)] + metadata_timeout_sec: u64, + + #[arg(long, default_value = "1.1.1.1")] + netstack_v4_dns: String, + + #[arg(long, default_value = "2606:4700:4700::1111")] + netstack_v6_dns: String, + + #[arg(long, default_value_t = 5)] + netstack_num_ping: u8, + + #[arg(long, default_value_t = 3)] + netstack_send_timeout_sec: u64, + + #[arg(long, default_value_t = 3)] + netstack_recv_timeout_sec: u64, + + #[arg(long, default_values_t = vec!["nym.com".to_string()])] + netstack_ping_hosts_v4: Vec, + + #[arg(long, default_values_t = vec!["1.1.1.1".to_string()])] + netstack_ping_ips_v4: Vec, + + #[arg(long, default_values_t = vec!["cloudflare.com".to_string()])] + netstack_ping_hosts_v6: Vec, + + #[arg(long, default_values_t = vec!["2001:4860:4860::8888".to_string(), "2606:4700:4700::1111".to_string(), "2620:fe::fe".to_string()])] + netstack_ping_ips_v6: Vec, +} + +#[derive(Args)] +pub struct CredentialArgs { + #[arg(long)] + ticket_materials: Option, + + #[arg(long, default_value_t = 1)] + ticket_materials_revision: u8, +} + +impl CredentialArgs { + fn decode_attached_ticket_materials(&self) -> anyhow::Result { + let ticket_materials = self + .ticket_materials + .as_ref() + .ok_or_else(|| anyhow::anyhow!("ticket_materials is required"))? + .clone(); + + Ok(AttachedTicketMaterials::from_serialised_string( + ticket_materials, + self.ticket_materials_revision, + )?) + } +} + +#[derive(Default, Debug)] +pub enum TestedNode { + #[default] + SameAsEntry, + Custom { + identity: NodeIdentity, + }, +} + +impl TestedNode { + pub fn is_same_as_entry(&self) -> bool { + matches!(self, TestedNode::SameAsEntry) + } +} + +#[derive(Debug)] +pub struct TestedNodeDetails { + identity: NodeIdentity, + exit_router_address: Option, + authenticator_address: Option, + authenticator_version: AuthenticatorVersion, + ip_address: Option, +} + +pub struct Probe { + entrypoint: NodeIdentity, + tested_node: TestedNode, + amnezia_args: String, + netstack_args: NetstackArgs, + credentials_args: CredentialArgs, +} + +impl Probe { + pub fn new( + entrypoint: NodeIdentity, + tested_node: TestedNode, + netstack_args: NetstackArgs, + credentials_args: CredentialArgs, + ) -> Self { + Self { + entrypoint, + tested_node, + amnezia_args: "".into(), + netstack_args, + credentials_args, + } + } + pub fn with_amnezia(&mut self, args: &str) -> &Self { + self.amnezia_args = args.to_string(); + self + } + + pub async fn probe( + self, + directory: NymApiDirectory, + nyxd_url: Url, + ignore_egress_epoch_role: bool, + only_wireguard: bool, + min_mixnet_performance: Option, + ) -> anyhow::Result { + let tickets_materials = self.credentials_args.decode_attached_ticket_materials()?; + + let tested_entry = self.tested_node.is_same_as_entry(); + let (mixnet_entry_gateway_id, node_info) = self.lookup_gateway(&directory).await?; + + let storage = Ephemeral::default(); + + // Connect to the mixnet via the entry gateway + let disconnected_mixnet_client = MixnetClientBuilder::new_with_storage(storage.clone()) + .request_gateway(mixnet_entry_gateway_id.to_string()) + .network_details(NymNetworkDetails::new_from_env()) + .debug_config(mixnet_debug_config( + min_mixnet_performance, + ignore_egress_epoch_role, + )) + .with_forget_me(ForgetMe::new_all()) + .credentials_mode(true) + .build()?; + + // in normal operation expects the ticket material to be provided as an argument + let bandwidth_import = disconnected_mixnet_client.begin_bandwidth_import(); + import_bandwidth(bandwidth_import, tickets_materials).await?; + + let mixnet_client = Box::pin(disconnected_mixnet_client.connect_to_mixnet()).await; + + self.do_probe_test( + mixnet_client, + storage, + mixnet_entry_gateway_id, + node_info, + nyxd_url, + tested_entry, + only_wireguard, + ) + .await + } + + #[allow(clippy::too_many_arguments)] + pub async fn probe_run_locally( + self, + config_dir: &PathBuf, + mnemonic: &str, + directory: NymApiDirectory, + nyxd_url: Url, + ignore_egress_epoch_role: bool, + only_wireguard: bool, + min_mixnet_performance: Option, + ) -> anyhow::Result { + let tested_entry = self.tested_node.is_same_as_entry(); + let (mixnet_entry_gateway_id, node_info) = self.lookup_gateway(&directory).await?; + + if config_dir.is_file() { + bail!("provided configuration directory is a file"); + } + + if !config_dir.exists() { + std::fs::create_dir_all(config_dir)?; + } + + let storage_paths = StoragePaths::new_from_dir(config_dir)?; + let storage = storage_paths + .initialise_default_persistent_storage() + .await?; + + // Connect to the mixnet via the entry gateway, without forget-me flag so that gateway remembers client + // and keeps its bandwidth between probe runs + let disconnected_mixnet_client = MixnetClientBuilder::new_with_storage(storage.clone()) + .request_gateway(mixnet_entry_gateway_id.to_string()) + .network_details(NymNetworkDetails::new_from_env()) + .debug_config(mixnet_debug_config( + min_mixnet_performance, + ignore_egress_epoch_role, + )) + .credentials_mode(true) + .build()?; + + let key_store = storage.key_store(); + let mut rng = OsRng; + + // WORKAROUND SINCE IT HASN'T MADE IT TO THE MONOREPO: + if key_store.load_keys().await.is_err() { + tracing::log::debug!("Generating new client keys"); + nym_client_core::init::generate_new_client_keys(&mut rng, key_store).await?; + } + + let ticketbook_count = storage + .credential_store() + .get_ticketbooks_info() + .await? + .len(); + + info!("Credential store contains {} ticketbooks", ticketbook_count); + + if ticketbook_count < 1 { + for ticketbook_type in [ + TicketType::V1MixnetEntry, + TicketType::V1WireguardEntry, + TicketType::V1WireguardExit, + ] { + acquire_bandwidth(mnemonic, &disconnected_mixnet_client, ticketbook_type).await?; + } + } + + let mixnet_client = Box::pin(disconnected_mixnet_client.connect_to_mixnet()).await; + + self.do_probe_test( + mixnet_client, + storage, + mixnet_entry_gateway_id, + node_info, + nyxd_url, + tested_entry, + only_wireguard, + ) + .await + } + + pub async fn lookup_gateway( + &self, + directory: &NymApiDirectory, + ) -> anyhow::Result<(NodeIdentity, TestedNodeDetails)> { + // Setup the entry gateways + let entry_gateway = directory.entry_gateway(&self.entrypoint)?; + + let node_info: TestedNodeDetails = match self.tested_node { + TestedNode::Custom { identity } => { + let node = directory.get_nym_node(identity)?; + info!( + "testing node {} (via entry {})", + node.identity(), + entry_gateway.identity() + ); + node.to_testable_node()? + } + TestedNode::SameAsEntry => entry_gateway.to_testable_node()?, + }; + + info!("connecting to entry gateway: {}", entry_gateway.identity()); + debug!( + "authenticator version: {:?}", + node_info.authenticator_version + ); + + Ok((self.entrypoint, node_info)) + } + + #[allow(clippy::too_many_arguments)] + pub async fn do_probe_test( + &self, + mixnet_client: nym_sdk::Result, + storage: T, + mixnet_entry_gateway_id: NodeIdentity, + node_info: TestedNodeDetails, + nyxd_url: Url, + tested_entry: bool, + only_wireguard: bool, + ) -> anyhow::Result + where + T: MixnetClientStorage + Clone + 'static, + ::StorageError: Send + Sync, + { + let mut rng = rand::thread_rng(); + let mixnet_client = match mixnet_client { + Ok(mixnet_client) => mixnet_client, + Err(err) => { + error!("Failed to connect to mixnet: {err}"); + return Ok(ProbeResult { + node: node_info.identity.to_string(), + used_entry: mixnet_entry_gateway_id.to_string(), + outcome: ProbeOutcome { + as_entry: if tested_entry { + Entry::fail_to_connect() + } else { + Entry::EntryFailure + }, + as_exit: None, + wg: None, + }, + }); + } + }; + + let nym_address = *mixnet_client.nym_address(); + let entry_gateway = nym_address.gateway().to_base58_string(); + + info!("Successfully connected to entry gateway: {entry_gateway}"); + info!("Our nym address: {nym_address}"); + + // Now that we have a connected mixnet client, we can start pinging + let (outcome, mixnet_client) = if only_wireguard { + ( + Ok(ProbeOutcome { + as_entry: if tested_entry { + Entry::success() + } else { + Entry::NotTested + }, + as_exit: None, + wg: None, + }), + mixnet_client, + ) + } else { + do_ping( + mixnet_client, + nym_address, + node_info.exit_router_address, + tested_entry, + ) + .await + }; + + let wg_outcome = if let (Some(authenticator), Some(ip_address)) = + (node_info.authenticator_address, node_info.ip_address) + { + // Start the mixnet listener that the auth clients use to receive messages. + let mixnet_listener_task = + AuthClientMixnetListener::new(mixnet_client, CancellationToken::new()).start(); + + let auth_client = AuthenticatorClient::new( + mixnet_listener_task.subscribe(), + mixnet_listener_task.mixnet_sender(), + nym_address, + authenticator, + node_info.authenticator_version, + Arc::new(KeyPair::new(&mut rng)), + ip_address, + ); + let config = nym_validator_client::nyxd::Config::try_from_nym_network_details( + &NymNetworkDetails::new_from_env(), + )?; + let client = + nym_validator_client::nyxd::NyxdClient::connect(config, nyxd_url.as_str())?; + let bw_controller = nym_bandwidth_controller::BandwidthController::new( + storage.credential_store().clone(), + client, + ); + let credential = bw_controller + .prepare_ecash_ticket( + TicketType::V1WireguardEntry, + nym_address.gateway().to_bytes(), + 1, + ) + .await? + .data; + + let outcome = wg_probe( + auth_client, + ip_address, + node_info.authenticator_version, + self.amnezia_args.clone(), + self.netstack_args.clone(), + credential, + ) + .await + .unwrap_or_default(); + + mixnet_listener_task.stop().await; + + outcome + } else { + mixnet_client.disconnect().await; + WgProbeResults::default() + }; + + // Disconnect the mixnet client gracefully + outcome.map(|mut outcome| { + outcome.wg = Some(wg_outcome); + ProbeResult { + node: node_info.identity.to_string(), + used_entry: mixnet_entry_gateway_id.to_string(), + outcome, + } + }) + } +} + +async fn wg_probe( + mut auth_client: AuthenticatorClient, + gateway_ip: IpAddr, + auth_version: AuthenticatorVersion, + awg_args: String, + netstack_args: NetstackArgs, + credential: CredentialSpendingData, +) -> anyhow::Result { + info!("attempting to use authenticator version {auth_version:?}"); + + let mut rng = rand::thread_rng(); + + // that's a long conversion chain + // (it should be simplified later...) + // nym x25519 -> dalek x25519 -> wireguard wrapper x25519 + let private_key = nym_crypto::asymmetric::encryption::PrivateKey::new(&mut rng); + let public_key = private_key.public_key(); + + let authenticator_pub_key = public_key.inner().into(); + let init_message = match auth_version { + AuthenticatorVersion::V2 => ClientMessage::Initial(Box::new( + v2::registration::InitMessage::new(authenticator_pub_key), + )), + AuthenticatorVersion::V3 => ClientMessage::Initial(Box::new( + v3::registration::InitMessage::new(authenticator_pub_key), + )), + AuthenticatorVersion::V4 => ClientMessage::Initial(Box::new( + v4::registration::InitMessage::new(authenticator_pub_key), + )), + AuthenticatorVersion::V5 => ClientMessage::Initial(Box::new( + v5::registration::InitMessage::new(authenticator_pub_key), + )), + AuthenticatorVersion::V1 | AuthenticatorVersion::UNKNOWN => bail!("unknown version number"), + }; + + let mut wg_outcome = WgProbeResults::default(); + + info!( + "connecting to authenticator: {}...", + auth_client.auth_recipient + ); + let response = auth_client + .send_and_wait_for_response(&init_message) + .await?; + + let registered_data = match response { + AuthenticatorResponse::PendingRegistration(pending_registration_response) => { + // Unwrap since we have already checked that we have the keypair. + debug!("Verifying data"); + pending_registration_response.verify(&private_key)?; + + let finalized_message = match auth_version { + AuthenticatorVersion::V2 => { + ClientMessage::Final(Box::new(v2::registration::FinalMessage { + gateway_client: v2::registration::GatewayClient::new( + &private_key, + pending_registration_response.pub_key().inner(), + pending_registration_response.private_ips().ipv4.into(), + pending_registration_response.nonce(), + ), + credential: Some(credential), + })) + } + AuthenticatorVersion::V3 => { + ClientMessage::Final(Box::new(v3::registration::FinalMessage { + gateway_client: v3::registration::GatewayClient::new( + &private_key, + pending_registration_response.pub_key().inner(), + pending_registration_response.private_ips().ipv4.into(), + pending_registration_response.nonce(), + ), + credential: Some(credential), + })) + } + AuthenticatorVersion::V4 => { + ClientMessage::Final(Box::new(v4::registration::FinalMessage { + gateway_client: v4::registration::GatewayClient::new( + &private_key, + pending_registration_response.pub_key().inner(), + pending_registration_response.private_ips().into(), + pending_registration_response.nonce(), + ), + credential: Some(credential), + })) + } + AuthenticatorVersion::V5 => { + ClientMessage::Final(Box::new(v5::registration::FinalMessage { + gateway_client: v5::registration::GatewayClient::new( + &private_key, + pending_registration_response.pub_key().inner(), + pending_registration_response.private_ips(), + pending_registration_response.nonce(), + ), + credential: Some(credential), + })) + } + AuthenticatorVersion::V1 | AuthenticatorVersion::UNKNOWN => { + bail!("Unknown version number") + } + }; + let response = auth_client + .send_and_wait_for_response(&finalized_message) + .await?; + let AuthenticatorResponse::Registered(registered_response) = response else { + bail!("Unexpected response"); + }; + registered_response + } + AuthenticatorResponse::Registered(registered_response) => registered_response, + _ => bail!("Unexpected response"), + }; + + let peer_public = registered_data.pub_key().inner(); + let static_private = x25519_dalek::StaticSecret::from(private_key.to_bytes()); + let public_key_bs64 = general_purpose::STANDARD.encode(peer_public.as_bytes()); + let private_key_hex = hex::encode(static_private.to_bytes()); + let public_key_hex = hex::encode(peer_public.as_bytes()); + + info!("WG connection details"); + info!("Peer public key: {}", public_key_bs64); + info!( + "ips {}(v4) {}(v6), port {}", + registered_data.private_ips().ipv4, + registered_data.private_ips().ipv6, + registered_data.wg_port(), + ); + + let wg_endpoint = format!("{gateway_ip}:{}", registered_data.wg_port()); + + info!("Successfully registered with the gateway"); + + wg_outcome.can_register = true; + + if wg_outcome.can_register { + let netstack_request = NetstackRequest::new( + ®istered_data.private_ips().ipv4.to_string(), + ®istered_data.private_ips().ipv6.to_string(), + &private_key_hex, + &public_key_hex, + &wg_endpoint, + &format!("http://{WG_TUN_DEVICE_IP_ADDRESS_V4}:{WG_METADATA_PORT}"), + netstack_args.netstack_download_timeout_sec, + &awg_args, + netstack_args, + ); + + // Perform IPv4 ping test + let ipv4_request = NetstackRequestGo::from_rust_v4(&netstack_request); + + match netstack::ping(&ipv4_request) { + Ok(NetstackResult::Response(netstack_response_v4)) => { + info!( + "Wireguard probe response for IPv4: {:#?}", + netstack_response_v4 + ); + wg_outcome.can_query_metadata_v4 = netstack_response_v4.can_query_metadata; + wg_outcome.can_handshake_v4 = netstack_response_v4.can_handshake; + wg_outcome.can_resolve_dns_v4 = netstack_response_v4.can_resolve_dns; + wg_outcome.ping_hosts_performance_v4 = netstack_response_v4.received_hosts as f32 + / netstack_response_v4.sent_hosts as f32; + wg_outcome.ping_ips_performance_v4 = + netstack_response_v4.received_ips as f32 / netstack_response_v4.sent_ips as f32; + + wg_outcome.download_duration_sec_v4 = netstack_response_v4.download_duration_sec; + wg_outcome.download_duration_milliseconds_v4 = + netstack_response_v4.download_duration_milliseconds; + wg_outcome.downloaded_file_size_bytes_v4 = + netstack_response_v4.downloaded_file_size_bytes; + wg_outcome.downloaded_file_v4 = netstack_response_v4.downloaded_file; + wg_outcome.download_error_v4 = netstack_response_v4.download_error; + } + Ok(NetstackResult::Error { error }) => { + error!("Netstack runtime error: {error}") + } + Err(error) => { + error!("Internal error: {error}") + } + } + + // Perform IPv6 ping test + let ipv6_request = NetstackRequestGo::from_rust_v6(&netstack_request); + + match netstack::ping(&ipv6_request) { + Ok(NetstackResult::Response(netstack_response_v6)) => { + info!( + "Wireguard probe response for IPv6: {:#?}", + netstack_response_v6 + ); + wg_outcome.can_handshake_v6 = netstack_response_v6.can_handshake; + wg_outcome.can_resolve_dns_v6 = netstack_response_v6.can_resolve_dns; + wg_outcome.ping_hosts_performance_v6 = netstack_response_v6.received_hosts as f32 + / netstack_response_v6.sent_hosts as f32; + wg_outcome.ping_ips_performance_v6 = + netstack_response_v6.received_ips as f32 / netstack_response_v6.sent_ips as f32; + + wg_outcome.download_duration_sec_v6 = netstack_response_v6.download_duration_sec; + wg_outcome.download_duration_milliseconds_v6 = + netstack_response_v6.download_duration_milliseconds; + wg_outcome.downloaded_file_size_bytes_v6 = + netstack_response_v6.downloaded_file_size_bytes; + wg_outcome.downloaded_file_v6 = netstack_response_v6.downloaded_file; + wg_outcome.download_error_v6 = netstack_response_v6.download_error; + } + Ok(NetstackResult::Error { error }) => { + error!("Netstack runtime error: {error}") + } + Err(error) => { + error!("Internal error: {error}") + } + } + } + + Ok(wg_outcome) +} + +fn mixnet_debug_config( + min_gateway_performance: Option, + ignore_egress_epoch_role: bool, +) -> nym_client_core::config::DebugConfig { + let mut debug_config = nym_client_core::config::DebugConfig::default(); + debug_config + .traffic + .disable_main_poisson_packet_distribution = true; + debug_config.cover_traffic.disable_loop_cover_traffic_stream = true; + if let Some(minimum_gateway_performance) = min_gateway_performance { + debug_config.topology.minimum_gateway_performance = minimum_gateway_performance; + } + if ignore_egress_epoch_role { + debug_config.topology.ignore_egress_epoch_role = ignore_egress_epoch_role; + } + + debug_config +} + +async fn do_ping( + mut mixnet_client: MixnetClient, + our_address: Recipient, + exit_router_address: Option, + tested_entry: bool, +) -> (anyhow::Result, MixnetClient) { + let entry = do_ping_entry(&mut mixnet_client, our_address, tested_entry).await; + + let (exit_result, mixnet_client) = if let Some(exit_router_address) = exit_router_address { + 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, + mixnet_client, + ), + None => (Ok(Some(Exit::fail_to_connect())), mixnet_client), + } + } else { + (Ok(None), mixnet_client) + }; + + ( + exit_result.map(|exit| ProbeOutcome { + as_entry: entry, + as_exit: exit, + wg: None, + }), + mixnet_client, + ) +} + +async fn do_ping_entry( + mixnet_client: &mut MixnetClient, + our_address: Recipient, + tested_entry: bool, +) -> Entry { + // Step 1: confirm that the entry gateway is routing our mixnet traffic + info!("Sending mixnet ping to ourselves to verify mixnet connection"); + + if self_ping_and_wait(our_address, mixnet_client) + .await + .is_err() + { + return if tested_entry { + Entry::fail_to_connect() + } else { + Entry::EntryFailure + }; + } + info!("Successfully mixnet pinged ourselves"); + + if tested_entry { + Entry::success() + } else { + Entry::NotTested + } +} + +async fn connect_exit( + mixnet_client: MixnetClient, + exit_router_address: Recipient, +) -> (Option, MixnetClient) { + // Step 2: connect to the exit gateway + info!( + "Connecting to exit gateway: {}", + exit_router_address.gateway().to_base58_string() + ); + // The IPR supports cancellation, but it's unused in the gateway probe + let cancel_token = CancellationToken::new(); + let mut ipr_client = IprClientConnect::new(mixnet_client, cancel_token).await; + + let maybe_ip_pair = ipr_client.connect(exit_router_address).await; + 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) + } else { + (None, mixnet_client) + } +} + +async fn do_ping_exit( + mixnet_client: &mut MixnetClient, + our_ips: IpPair, + 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?; + listen_for_icmp_ping_replies(mixnet_client, our_ips).await +} + +async fn send_icmp_pings( + mixnet_client: &MixnetClient, + our_ips: IpPair, + exit_router_address: Recipient, +) -> anyhow::Result<()> { + // ipv4 addresses for testing + let ipr_tun_ip_v4 = NYM_TUN_DEVICE_ADDRESS_V4; + let external_ip_v4 = Ipv4Addr::new(8, 8, 8, 8); + + // ipv6 addresses for testing + let ipr_tun_ip_v6 = NYM_TUN_DEVICE_ADDRESS_V6; + let external_ip_v6 = Ipv6Addr::new(0x2001, 0x4860, 0x4860, 0, 0, 0, 0, 0x8888); + + info!( + "Sending ICMP echo requests to: {ipr_tun_ip_v4}, {ipr_tun_ip_v6}, {external_ip_v4}, {external_ip_v6}" + ); + + // send ipv4 pings + for ii in 0..10 { + send_ping_v4( + mixnet_client, + our_ips, + ii, + ipr_tun_ip_v4, + exit_router_address, + ) + .await?; + send_ping_v4( + mixnet_client, + our_ips, + ii, + external_ip_v4, + exit_router_address, + ) + .await?; + } + + // send ipv6 pings + for ii in 0..10 { + send_ping_v6( + mixnet_client, + our_ips, + ii, + ipr_tun_ip_v6, + exit_router_address, + ) + .await?; + send_ping_v6( + mixnet_client, + our_ips, + ii, + external_ip_v6, + exit_router_address, + ) + .await?; + } + Ok(()) +} + +async fn listen_for_icmp_ping_replies( + mixnet_client: &mut MixnetClient, + our_ips: IpPair, +) -> anyhow::Result> { + let mut multi_ip_packet_decoder = MultiIpPacketCodec::new(); + let mut registered_replies = IpPingReplies::new(); + + loop { + tokio::select! { + _ = tokio::time::sleep(Duration::from_secs(2)) => { + info!("Finished waiting for ICMP echo reply from exit gateway"); + break; + } + Some(reconstructed_message) = mixnet_client.next() => { + let Some(data_response) = unpack_data_response(&reconstructed_message) else { + continue; + }; + + // IP packets are bundled together in a mixnet message + let mut bytes = BytesMut::from(&*data_response.ip_packet); + while let Ok(Some(packet)) = multi_ip_packet_decoder.decode(&mut bytes) { + if let Some(event) = check_for_icmp_beacon_reply(&packet.into_bytes(), icmp_identifier(), our_ips) { + info!("Received ICMP echo reply from exit gateway"); + info!("Connection event: {event:?}"); + registered_replies.register_event(&event); + } + } + } + } + } + + Ok(Some(Exit { + can_connect: true, + can_route_ip_v4: registered_replies.ipr_tun_ip_v4, + can_route_ip_external_v4: registered_replies.external_ip_v4, + can_route_ip_v6: registered_replies.ipr_tun_ip_v6, + can_route_ip_external_v6: registered_replies.external_ip_v6, + })) +} + +fn unpack_data_response(reconstructed_message: &ReconstructedMessage) -> Option { + match IpPacketResponse::from_reconstructed_message(reconstructed_message) { + Ok(response) => match response.data { + IpPacketResponseData::Data(data_response) => Some(data_response), + IpPacketResponseData::Control(control) => match *control { + ControlResponse::Info(info) => { + let msg = format!("Received info response from the mixnet: {}", info.reply); + match info.level { + InfoLevel::Info => info!("{msg}"), + InfoLevel::Warn => warn!("{msg}"), + InfoLevel::Error => error!("{msg}"), + } + None + } + _ => { + info!("Ignoring: {:?}", control); + None + } + }, + }, + Err(err) => { + warn!("Failed to parse mixnet message: {err}"); + None + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_netstack_args_default_values() { + // Test that the default values are correctly set in the struct definition + // This validates that our changes to the default values are correct + + // Create a default instance to test the values + let args = NetstackArgs { + netstack_download_timeout_sec: 180, + metadata_timeout_sec: 30, + netstack_v4_dns: "1.1.1.1".to_string(), + netstack_v6_dns: "2606:4700:4700::1111".to_string(), + netstack_num_ping: 5, + netstack_send_timeout_sec: 3, + netstack_recv_timeout_sec: 3, + netstack_ping_hosts_v4: vec!["nym.com".to_string()], + netstack_ping_ips_v4: vec!["1.1.1.1".to_string()], + netstack_ping_hosts_v6: vec!["cloudflare.com".to_string()], + netstack_ping_ips_v6: vec![ + "2001:4860:4860::8888".to_string(), + "2606:4700:4700::1111".to_string(), + "2620:fe::fe".to_string(), + ], + }; + + // Test IPv4 defaults + assert_eq!(args.netstack_ping_hosts_v4, vec!["nym.com"]); + assert_eq!(args.netstack_ping_ips_v4, vec!["1.1.1.1"]); + assert_eq!(args.netstack_v4_dns, "1.1.1.1"); + + // Test IPv6 defaults + assert_eq!(args.netstack_ping_hosts_v6, vec!["cloudflare.com"]); + assert_eq!( + args.netstack_ping_ips_v6, + vec![ + "2001:4860:4860::8888", + "2606:4700:4700::1111", + "2620:fe::fe" + ] + ); + assert_eq!(args.netstack_v6_dns, "2606:4700:4700::1111"); + + // Test other defaults + assert_eq!(args.netstack_download_timeout_sec, 180); + assert_eq!(args.netstack_num_ping, 5); + assert_eq!(args.netstack_send_timeout_sec, 3); + assert_eq!(args.netstack_recv_timeout_sec, 3); + } + + #[test] + fn test_netstack_args_custom_construction() { + // Test that we can create instances with custom values + let args = NetstackArgs { + netstack_download_timeout_sec: 300, + metadata_timeout_sec: 30, + netstack_v4_dns: "8.8.8.8".to_string(), + netstack_v6_dns: "2001:4860:4860::8888".to_string(), + netstack_num_ping: 10, + netstack_send_timeout_sec: 5, + netstack_recv_timeout_sec: 5, + netstack_ping_hosts_v4: vec!["example.com".to_string()], + netstack_ping_ips_v4: vec!["8.8.8.8".to_string()], + netstack_ping_hosts_v6: vec!["ipv6.example.com".to_string()], + netstack_ping_ips_v6: vec!["2001:4860:4860::8888".to_string()], + }; + + assert_eq!(args.netstack_ping_hosts_v4, vec!["example.com"]); + assert_eq!(args.netstack_ping_hosts_v6, vec!["ipv6.example.com"]); + assert_eq!(args.netstack_ping_ips_v4, vec!["8.8.8.8"]); + assert_eq!(args.netstack_ping_ips_v6, vec!["2001:4860:4860::8888"]); + assert_eq!(args.netstack_v4_dns, "8.8.8.8"); + assert_eq!(args.netstack_v6_dns, "2001:4860:4860::8888"); + assert_eq!(args.netstack_download_timeout_sec, 300); + assert_eq!(args.netstack_num_ping, 10); + assert_eq!(args.netstack_send_timeout_sec, 5); + assert_eq!(args.netstack_recv_timeout_sec, 5); + } + + #[test] + fn test_netstack_args_multiple_values() { + // Test that multiple hosts and IPs can be stored + let args = NetstackArgs { + netstack_download_timeout_sec: 180, + metadata_timeout_sec: 30, + netstack_v4_dns: "1.1.1.1".to_string(), + netstack_v6_dns: "2606:4700:4700::1111".to_string(), + netstack_num_ping: 5, + netstack_send_timeout_sec: 3, + netstack_recv_timeout_sec: 3, + netstack_ping_hosts_v4: vec!["nym.com".to_string(), "example.com".to_string()], + netstack_ping_ips_v4: vec!["1.1.1.1".to_string(), "8.8.8.8".to_string()], + netstack_ping_hosts_v6: vec![ + "cloudflare.com".to_string(), + "ipv6.example.com".to_string(), + ], + netstack_ping_ips_v6: vec![ + "2001:4860:4860::8888".to_string(), + "2606:4700:4700::1111".to_string(), + ], + }; + + assert_eq!(args.netstack_ping_hosts_v4, vec!["nym.com", "example.com"]); + assert_eq!( + args.netstack_ping_hosts_v6, + vec!["cloudflare.com", "ipv6.example.com"] + ); + assert_eq!(args.netstack_ping_ips_v4, vec!["1.1.1.1", "8.8.8.8"]); + assert_eq!( + args.netstack_ping_ips_v6, + vec!["2001:4860:4860::8888", "2606:4700:4700::1111"] + ); + } + + #[test] + fn test_netstack_args_edge_cases() { + // Test edge cases like zero values and empty vectors + let args = NetstackArgs { + netstack_download_timeout_sec: 0, + metadata_timeout_sec: 30, + netstack_v4_dns: "1.1.1.1".to_string(), + netstack_v6_dns: "2606:4700:4700::1111".to_string(), + netstack_num_ping: 0, + netstack_send_timeout_sec: 0, + netstack_recv_timeout_sec: 0, + netstack_ping_hosts_v4: vec![], + netstack_ping_ips_v4: vec![], + netstack_ping_hosts_v6: vec![], + netstack_ping_ips_v6: vec![], + }; + + assert_eq!(args.netstack_num_ping, 0); + assert_eq!(args.netstack_send_timeout_sec, 0); + assert_eq!(args.netstack_recv_timeout_sec, 0); + assert_eq!(args.netstack_download_timeout_sec, 0); + assert!(args.netstack_ping_hosts_v4.is_empty()); + assert!(args.netstack_ping_ips_v4.is_empty()); + assert!(args.netstack_ping_hosts_v6.is_empty()); + assert!(args.netstack_ping_ips_v6.is_empty()); + } + + #[test] + fn test_netstack_args_domain_validation() { + // Test that our domain choices are reasonable + let args = NetstackArgs { + netstack_download_timeout_sec: 180, + metadata_timeout_sec: 30, + netstack_v4_dns: "1.1.1.1".to_string(), + netstack_v6_dns: "2606:4700:4700::1111".to_string(), + netstack_num_ping: 5, + netstack_send_timeout_sec: 3, + netstack_recv_timeout_sec: 3, + netstack_ping_hosts_v4: vec!["nym.com".to_string()], + netstack_ping_ips_v4: vec!["1.1.1.1".to_string()], + netstack_ping_hosts_v6: vec!["cloudflare.com".to_string()], + netstack_ping_ips_v6: vec!["2001:4860:4860::8888".to_string()], + }; + + assert!(args.netstack_ping_hosts_v4[0].contains("nym")); + + assert!(args.netstack_ping_hosts_v6[0].contains("cloudflare")); + + assert_eq!(args.netstack_v4_dns, "1.1.1.1"); + assert_eq!(args.netstack_v6_dns, "2606:4700:4700::1111"); + } +} diff --git a/nym-gateway-probe/src/main.rs b/nym-gateway-probe/src/main.rs new file mode 100644 index 0000000000..d2237d4328 --- /dev/null +++ b/nym-gateway-probe/src/main.rs @@ -0,0 +1,37 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +#[cfg(unix)] +mod run; + +use nym_http_api_client_macro::client_defaults; +use std::time::Duration; + +client_defaults!( + priority = 10; + timeout = Duration::from_secs(300), + local_address = std::net::IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED), +); + +#[cfg(unix)] +#[tokio::main] +async fn main() -> anyhow::Result<()> { + match run::run().await { + Ok(ref result) => { + let json = serde_json::to_string_pretty(result)?; + println!("{json}"); + } + Err(err) => { + eprintln!("An error occurred: {err}"); + std::process::exit(1) + } + } + Ok(()) +} + +#[cfg(not(unix))] +#[tokio::main] +async fn main() -> anyhow::Result<()> { + eprintln!("This tool is only supported on Unix systems"); + std::process::exit(1) +} diff --git a/nym-gateway-probe/src/netstack.rs b/nym-gateway-probe/src/netstack.rs new file mode 100644 index 0000000000..d11c507cbf --- /dev/null +++ b/nym-gateway-probe/src/netstack.rs @@ -0,0 +1,213 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use anyhow::Context; +use serde::Deserialize; +use std::ffi::{CStr, CString}; + +mod sys { + use std::ffi::{c_char, c_void}; + + unsafe extern "C" { + pub unsafe fn wgPing(req: *const c_char) -> *const c_char; + pub unsafe fn wgFreePtr(ptr: *mut c_void); + } +} + +use crate::NetstackArgs; + +#[derive(serde::Serialize)] +pub struct NetstackRequest { + private_key: String, + public_key: String, + endpoint: String, + metadata_endpoint: String, + v4_ping_config: PingConfig, + v6_ping_config: PingConfig, + download_timeout_sec: u64, + awg_args: String, +} + +#[derive(serde::Serialize)] +pub struct PingConfig { + self_ip: String, + dns: String, + ping_hosts: Vec, + ping_ips: Vec, + num_ping: u8, + send_timeout_sec: u64, + recv_timeout_sec: u64, +} + +impl PingConfig { + pub fn from_netstack_args_v4(wg_ip4: &str, args: &NetstackArgs) -> Self { + Self { + self_ip: wg_ip4.to_string(), + dns: args.netstack_v4_dns.clone(), + ping_hosts: args.netstack_ping_hosts_v4.clone(), + ping_ips: args.netstack_ping_ips_v4.clone(), + num_ping: args.netstack_num_ping, + send_timeout_sec: args.netstack_send_timeout_sec, + recv_timeout_sec: args.netstack_recv_timeout_sec, + } + } + + pub fn from_netstack_args_v6(wg_ip6: &str, args: &NetstackArgs) -> Self { + Self { + self_ip: wg_ip6.to_string(), + dns: args.netstack_v6_dns.clone(), + ping_hosts: args.netstack_ping_hosts_v6.clone(), + ping_ips: args.netstack_ping_ips_v6.clone(), + num_ping: args.netstack_num_ping, + send_timeout_sec: args.netstack_send_timeout_sec, + recv_timeout_sec: args.netstack_recv_timeout_sec, + } + } +} + +impl NetstackRequest { + #[allow(clippy::too_many_arguments)] + pub fn new( + wg_ip4: &str, + wg_ip6: &str, + private_key: &str, + public_key: &str, + endpoint: &str, + metadata_endpoint: &str, + download_timeout_sec: u64, + awg_args: &str, + netstack_args: NetstackArgs, + ) -> Self { + Self { + private_key: private_key.to_string(), + public_key: public_key.to_string(), + endpoint: endpoint.to_string(), + metadata_endpoint: metadata_endpoint.to_string(), + awg_args: awg_args.to_string(), + v4_ping_config: PingConfig::from_netstack_args_v4(wg_ip4, &netstack_args), + v6_ping_config: PingConfig::from_netstack_args_v6(wg_ip6, &netstack_args), + download_timeout_sec, + } + } + + #[allow(dead_code)] + pub fn set_v4_config(&mut self, config: PingConfig) { + self.v4_ping_config = config; + } + + #[allow(dead_code)] + pub fn set_v6_config(&mut self, config: PingConfig) { + self.v6_ping_config = config; + } +} + +#[derive(Clone, Debug, serde::Serialize)] +pub struct NetstackRequestGo { + pub wg_ip: String, + private_key: String, + public_key: String, + endpoint: String, + metadata_endpoint: String, + pub dns: String, + ip_version: u8, + ping_hosts: Vec, + ping_ips: Vec, + num_ping: u8, + send_timeout_sec: u64, + recv_timeout_sec: u64, + download_timeout_sec: u64, + awg_args: String, +} + +impl NetstackRequestGo { + pub fn from_rust_v4(req: &NetstackRequest) -> Self { + NetstackRequestGo { + wg_ip: req.v4_ping_config.self_ip.clone(), + private_key: req.private_key.clone(), + public_key: req.public_key.clone(), + endpoint: req.endpoint.clone(), + metadata_endpoint: req.metadata_endpoint.clone(), + dns: req.v4_ping_config.dns.clone(), + ip_version: 4, + ping_hosts: req.v4_ping_config.ping_hosts.clone(), + ping_ips: req.v4_ping_config.ping_ips.clone(), + num_ping: req.v4_ping_config.num_ping, + send_timeout_sec: req.v4_ping_config.send_timeout_sec, + recv_timeout_sec: req.v4_ping_config.recv_timeout_sec, + download_timeout_sec: req.download_timeout_sec, + awg_args: req.awg_args.clone(), + } + } + + pub fn from_rust_v6(req: &NetstackRequest) -> Self { + NetstackRequestGo { + wg_ip: req.v6_ping_config.self_ip.clone(), + private_key: req.private_key.clone(), + public_key: req.public_key.clone(), + endpoint: req.endpoint.clone(), + metadata_endpoint: req.metadata_endpoint.clone(), + dns: req.v6_ping_config.dns.clone(), + ip_version: 6, + ping_hosts: req.v6_ping_config.ping_hosts.clone(), + ping_ips: req.v6_ping_config.ping_ips.clone(), + num_ping: req.v6_ping_config.num_ping, + send_timeout_sec: req.v6_ping_config.send_timeout_sec, + recv_timeout_sec: req.v6_ping_config.recv_timeout_sec, + download_timeout_sec: req.download_timeout_sec, + awg_args: req.awg_args.clone(), + } + } +} + +#[derive(Clone, Debug, serde::Deserialize)] +pub struct NetstackResponse { + pub can_handshake: bool, + pub can_query_metadata: bool, + pub sent_ips: u16, + pub received_ips: u16, + pub sent_hosts: u16, + pub received_hosts: u16, + pub can_resolve_dns: bool, + pub downloaded_file: String, + pub download_duration_sec: u64, + pub downloaded_file_size_bytes: u64, + pub download_duration_milliseconds: u64, + pub download_error: String, +} + +#[derive(Clone, Debug, serde::Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum NetstackResult { + Response(NetstackResponse), + Error { error: String }, +} + +pub fn ping(req: &NetstackRequestGo) -> anyhow::Result { + let req_json = serde_json::to_string_pretty(req)?; + let req_json_cstr = CString::new(req_json)?; + + // SAFETY: safety guarantees are upheld by CGO + let response_str_ptr = unsafe { sys::wgPing(req_json_cstr.as_ptr()) }; + if response_str_ptr.is_null() { + return Err(anyhow::anyhow!("wgPing() returned null")); + } + + // SAFETY: safety guarantees are upheld by CGO + let response_cstr = unsafe { CStr::from_ptr(response_str_ptr) }; + let result = match response_cstr.to_str() { + Ok(response_str) => { + let mut de = serde_json::Deserializer::from_str(response_str); + let response = NetstackResult::deserialize(&mut de); + + response.context("Failed to deserialize ffi response") + } + Err(err) => Err(anyhow::anyhow!( + "Failed to convert ffi response to utf8 string: {err}" + )), + }; + + // SAFETY: freeing the pointer returned by CGO + unsafe { sys::wgFreePtr(response_str_ptr as _) }; + + result +} diff --git a/nym-gateway-probe/src/nodes.rs b/nym-gateway-probe/src/nodes.rs new file mode 100644 index 0000000000..0726bb3b7d --- /dev/null +++ b/nym-gateway-probe/src/nodes.rs @@ -0,0 +1,218 @@ +// Copyright 2025 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::TestedNodeDetails; +use anyhow::{Context, anyhow, bail}; +use nym_authenticator_requests::AuthenticatorVersion; +use nym_http_api_client::UserAgent; +use nym_sdk::mixnet::NodeIdentity; +use nym_validator_client::client::NymApiClientExt; +use nym_validator_client::models::NymNodeDescription; +use rand::prelude::IteratorRandom; +use std::collections::HashMap; +use tracing::{debug, info}; +use url::Url; + +// in the old behaviour we were getting all skimmed nodes to retrieve performance +// that was ultimately unused +// should we want to use it again, the code is commented out below +// +// #[derive(Clone)] +// pub struct DescribedNodeWithPerformance { +// pub(crate) described: NymNodeDescription, +// // in old behaviour there was no filtering here, +// // but in case that ever changes, this value is available +// pub(crate) performance: u8, +// } +// +// impl DescribedNodeWithPerformance { +// pub fn identity(&self) -> NodeIdentity { +// self.described.ed25519_identity_key() +// } +// +// pub fn to_testable_node(&self) -> anyhow::Result { +// let exit_router_address = self +// .described +// .description +// .ip_packet_router +// .as_ref() +// .map(|ipr| ipr.address.parse().context("malformed ipr address")) +// .transpose()?; +// let authenticator_address = self +// .described +// .description +// .authenticator +// .as_ref() +// .map(|ipr| { +// ipr.address +// .parse() +// .context("malformed authenticator address") +// }) +// .transpose()?; +// let authenticator_version = AuthenticatorVersion::from( +// self.described +// .description +// .build_information +// .build_version +// .as_str(), +// ); +// let ip_address = self +// .described +// .description +// .host_information +// .ip_address +// .first() +// .copied(); +// +// Ok(TestedNodeDetails { +// identity: self.identity(), +// exit_router_address, +// authenticator_address, +// authenticator_version, +// ip_address, +// }) +// } +// } + +#[derive(Clone)] +pub struct DirectoryNode { + described: NymNodeDescription, +} + +impl DirectoryNode { + pub fn identity(&self) -> NodeIdentity { + self.described.ed25519_identity_key() + } + + pub fn to_testable_node(&self) -> anyhow::Result { + let exit_router_address = self + .described + .description + .ip_packet_router + .as_ref() + .map(|ipr| ipr.address.parse().context("malformed ipr address")) + .transpose()?; + let authenticator_address = self + .described + .description + .authenticator + .as_ref() + .map(|ipr| { + ipr.address + .parse() + .context("malformed authenticator address") + }) + .transpose()?; + let authenticator_version = AuthenticatorVersion::from( + self.described + .description + .build_information + .build_version + .as_str(), + ); + let ip_address = self + .described + .description + .host_information + .ip_address + .first() + .copied(); + + Ok(TestedNodeDetails { + identity: self.identity(), + exit_router_address, + authenticator_address, + authenticator_version, + ip_address, + }) + } +} + +pub struct NymApiDirectory { + // nodes: HashMap, + nodes: HashMap, +} + +impl NymApiDirectory { + // obtain all needed directory information on genesis + pub async fn new(api_url: Url) -> anyhow::Result { + let user_agent: UserAgent = nym_bin_common::bin_info_local_vergen!().into(); + let api_client = nym_http_api_client::Client::builder(api_url) + .context("malformed nym api url")? + .with_user_agent(user_agent) + .build() + .context("failed to build nym api client")?; + + debug!("Fetching all described nodes from nym-api..."); + let described_nodes = api_client + .get_all_described_nodes() + .await + .context("nym api query failure")?; + + // let skimmed_nodes = api_client + // .get_all_basic_nodes_with_metadata() + // .await + // .context("nym api query failure")?; + // + // let performances = skimmed_nodes + // .nodes + // .into_iter() + // .map(|n| (n.node_id, n.performance)) + // .collect::>(); + // + // let mut nodes = HashMap::new(); + // for described_node in described_nodes { + // let identity = described_node.ed25519_identity_key(); + // let Some(performance) = performances.get(&described_node.node_id) else { + // tracing::warn!( + // "Failed to append mixnet_performance, node {identity} not found among the skimmed nodes", + // ); + // continue; + // }; + // let info = DescribedNodeWithPerformance { + // described: described_node, + // performance: performance.round_to_integer(), + // }; + // nodes.insert(identity, info); + // } + + let nodes = described_nodes + .into_iter() + .map(|described| { + ( + described.ed25519_identity_key(), + DirectoryNode { described }, + ) + }) + .collect(); + + Ok(NymApiDirectory { nodes }) + } + + pub fn random_exit_with_ipr(&self) -> anyhow::Result { + info!("Selecting random gateway with IPR enabled"); + self.nodes + .iter() + .filter(|(_, n)| n.described.description.ip_packet_router.is_some()) + .choose(&mut rand::thread_rng()) + .ok_or(anyhow!("no gateways running IPR available")) + .map(|(id, _)| *id) + } + + pub fn get_nym_node(&self, identity: NodeIdentity) -> anyhow::Result { + self.nodes + .get(&identity) + .cloned() + .ok_or_else(|| anyhow!("did not find node {identity}")) + } + + pub fn entry_gateway(&self, identity: &NodeIdentity) -> anyhow::Result { + let Some(maybe_entry) = self.nodes.get(identity).cloned() else { + bail!("{identity} does not exist") + }; + if !maybe_entry.described.description.declared_role.entry { + bail!("{identity} is not an entry node") + }; + Ok(maybe_entry) + } +} diff --git a/nym-gateway-probe/src/run.rs b/nym-gateway-probe/src/run.rs new file mode 100644 index 0000000000..886ba7635b --- /dev/null +++ b/nym-gateway-probe/src/run.rs @@ -0,0 +1,169 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use clap::{Parser, Subcommand}; +use nym_bin_common::bin_info; +use nym_config::defaults::setup_env; +use nym_gateway_probe::nodes::NymApiDirectory; +use nym_gateway_probe::{CredentialArgs, NetstackArgs, ProbeResult, TestedNode}; +use nym_sdk::mixnet::NodeIdentity; +use std::{path::PathBuf, sync::OnceLock}; +use tracing::*; + +fn pretty_build_info_static() -> &'static str { + static PRETTY_BUILD_INFORMATION: OnceLock = OnceLock::new(); + PRETTY_BUILD_INFORMATION.get_or_init(|| bin_info!().pretty_print()) +} + +fn validate_node_identity(s: &str) -> Result { + match s.parse() { + Ok(cg) => Ok(cg), + Err(_) => Err(format!("failed to parse country group: {s}")), + } +} + +#[derive(Parser)] +#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)] +struct CliArgs { + #[command(subcommand)] + command: Option, + + /// Path pointing to an env file describing the network. + #[arg(short, long, global = true)] + config_env_file: Option, + + /// The specific gateway specified by ID. + #[arg(long, short = 'g', alias = "gateway", global = true)] + entry_gateway: Option, + + /// Identity of the node to test + #[arg(long, short, value_parser = validate_node_identity, global = true)] + node: Option, + + #[arg(long, global = true)] + min_gateway_mixnet_performance: Option, + + // this was a dead field + // #[arg(long, global = true)] + // min_gateway_vpn_performance: Option, + #[arg(long, global = true)] + only_wireguard: bool, + + /// Disable logging during probe + #[arg(long, global = true)] + ignore_egress_epoch_role: bool, + + #[arg(long, global = true)] + no_log: bool, + + /// Arguments to be appended to the wireguard config enabling amnezia-wg configuration + #[arg(long, short, global = true)] + amnezia_args: Option, + + /// Arguments to manage netstack downloads + #[command(flatten)] + netstack_args: NetstackArgs, + + /// Arguments to manage credentials + #[command(flatten)] + credential_args: CredentialArgs, +} + +#[derive(Subcommand, Debug)] +enum Commands { + /// Run the probe locally + RunLocal { + /// Provide a mnemonic to get credentials + #[arg(long)] + mnemonic: String, + + #[arg(long, default_value = "/tmp/nym-gateway-probe/config/")] + config_dir: PathBuf, + }, +} + +fn setup_logging() { + // SAFETY: those are valid directives + #[allow(clippy::unwrap_used)] + let filter = tracing_subscriber::EnvFilter::builder() + .with_default_directive(tracing_subscriber::filter::LevelFilter::INFO.into()) + .from_env() + .unwrap() + .add_directive("hyper::proto=info".parse().unwrap()) + .add_directive("netlink_proto=info".parse().unwrap()); + + tracing_subscriber::fmt() + .with_env_filter(filter) + .compact() + .init(); +} + +pub(crate) async fn run() -> anyhow::Result { + let args = CliArgs::parse(); + if !args.no_log { + setup_logging(); + } + debug!("{:?}", nym_bin_common::bin_info_local_vergen!()); + setup_env(args.config_env_file.as_ref()); + + let network = nym_sdk::NymNetworkDetails::new_from_env(); + + let nyxd_url = network + .endpoints + .first() + .map(|ep| ep.nyxd_url()) + .ok_or(anyhow::anyhow!("missing nyxd url"))?; + let api_url = network + .endpoints + .first() + .and_then(|ep| ep.api_url()) + .ok_or(anyhow::anyhow!("missing nyxd url"))?; + + let directory = NymApiDirectory::new(api_url).await?; + + let entry = if let Some(gateway) = &args.entry_gateway { + NodeIdentity::from_base58_string(gateway)? + } else { + directory.random_exit_with_ipr()? + }; + + let test_point = if let Some(node) = args.node { + TestedNode::Custom { identity: node } + } else { + TestedNode::SameAsEntry + }; + + let mut trial = + nym_gateway_probe::Probe::new(entry, test_point, args.netstack_args, args.credential_args); + if let Some(awg_args) = args.amnezia_args { + trial.with_amnezia(&awg_args); + } + + match &args.command { + Some(Commands::RunLocal { + mnemonic, + config_dir, + }) => { + Box::pin(trial.probe_run_locally( + config_dir, + mnemonic, + directory, + nyxd_url, + args.ignore_egress_epoch_role, + args.only_wireguard, + args.min_gateway_mixnet_performance, + )) + .await + } + None => { + Box::pin(trial.probe( + directory, + nyxd_url, + args.ignore_egress_epoch_role, + args.only_wireguard, + args.min_gateway_mixnet_performance, + )) + .await + } + } +} diff --git a/nym-gateway-probe/src/types.rs b/nym-gateway-probe/src/types.rs new file mode 100644 index 0000000000..17f02b40f8 --- /dev/null +++ b/nym-gateway-probe/src/types.rs @@ -0,0 +1,147 @@ +use nym_connection_monitor::ConnectionStatusEvent; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ProbeResult { + pub node: String, + pub used_entry: String, + pub outcome: ProbeOutcome, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ProbeOutcome { + pub as_entry: Entry, + pub as_exit: Option, + pub wg: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[serde(rename = "wg")] +pub struct WgProbeResults { + pub can_register: bool, + + pub can_query_metadata_v4: bool, + pub can_handshake_v4: bool, + pub can_resolve_dns_v4: bool, + pub ping_hosts_performance_v4: f32, + pub ping_ips_performance_v4: f32, + + pub can_handshake_v6: bool, + pub can_resolve_dns_v6: bool, + pub ping_hosts_performance_v6: f32, + pub ping_ips_performance_v6: f32, + + pub download_duration_sec_v4: u64, + pub download_duration_milliseconds_v4: u64, + pub downloaded_file_size_bytes_v4: u64, + pub downloaded_file_v4: String, + pub download_error_v4: String, + + pub download_duration_sec_v6: u64, + pub downloaded_file_size_bytes_v6: u64, + pub download_duration_milliseconds_v6: u64, + pub downloaded_file_v6: String, + pub download_error_v6: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +#[allow(clippy::enum_variant_names)] +pub enum Entry { + Tested(EntryTestResult), + NotTested, + EntryFailure, +} + +impl From for Entry { + fn from(value: EntryTestResult) -> Self { + Entry::Tested(value) + } +} + +impl Entry { + pub fn fail_to_connect() -> Self { + EntryTestResult { + can_connect: false, + can_route: false, + } + .into() + } + + pub fn fail_to_route() -> Self { + EntryTestResult { + can_connect: true, + can_route: false, + } + .into() + } + + pub fn success() -> Self { + EntryTestResult { + can_connect: true, + can_route: true, + } + .into() + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct EntryTestResult { + pub can_connect: bool, + pub can_route: bool, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Exit { + pub can_connect: bool, + pub can_route_ip_v4: bool, + pub can_route_ip_external_v4: bool, + pub can_route_ip_v6: bool, + pub can_route_ip_external_v6: bool, +} + +impl Exit { + pub fn fail_to_connect() -> Self { + Self { + can_connect: false, + can_route_ip_v4: false, + can_route_ip_external_v4: false, + can_route_ip_v6: false, + can_route_ip_external_v6: false, + } + } + + pub fn from_ping_replies(replies: &IpPingReplies) -> Self { + Self { + can_connect: true, + can_route_ip_v4: replies.ipr_tun_ip_v4, + can_route_ip_external_v4: replies.external_ip_v4, + can_route_ip_v6: replies.ipr_tun_ip_v6, + can_route_ip_external_v6: replies.external_ip_v6, + } + } +} + +#[derive(Debug, Clone, Default)] +pub struct IpPingReplies { + pub ipr_tun_ip_v4: bool, + pub ipr_tun_ip_v6: bool, + pub external_ip_v4: bool, + pub external_ip_v6: bool, +} + +impl IpPingReplies { + pub fn new() -> Self { + Self::default() + } + + pub fn register_event(&mut self, event: &ConnectionStatusEvent) { + match event { + ConnectionStatusEvent::MixnetSelfPing => {} + ConnectionStatusEvent::Icmpv4IprTunDevicePingReply => self.ipr_tun_ip_v4 = true, + ConnectionStatusEvent::Icmpv6IprTunDevicePingReply => self.ipr_tun_ip_v6 = true, + ConnectionStatusEvent::Icmpv4IprExternalPingReply => self.external_ip_v4 = true, + ConnectionStatusEvent::Icmpv6IprExternalPingReply => self.external_ip_v6 = true, + } + } +} diff --git a/nym-ip-packet-client/src/helpers.rs b/nym-ip-packet-client/src/helpers.rs index 2f1cf718cb..8198a8a7b7 100644 --- a/nym-ip-packet-client/src/helpers.rs +++ b/nym-ip-packet-client/src/helpers.rs @@ -5,7 +5,7 @@ use std::cmp::Ordering; use nym_sdk::mixnet::ReconstructedMessage; -use crate::{current::VERSION as CURRENT_VERSION, error::Result, Error}; +use crate::{Error, current::VERSION as CURRENT_VERSION, error::Result}; pub(crate) fn check_ipr_message_version(message: &ReconstructedMessage) -> Result<()> { // Assuming it's a IPR message, it will have a version as its first byte diff --git a/nym-network-monitor/src/accounting.rs b/nym-network-monitor/src/accounting.rs index caddfe1db6..04bb7b6db3 100644 --- a/nym-network-monitor/src/accounting.rs +++ b/nym-network-monitor/src/accounting.rs @@ -4,9 +4,9 @@ use std::{ }; use anyhow::Result; -use futures::{pin_mut, stream::FuturesUnordered, StreamExt}; +use futures::{StreamExt, pin_mut, stream::FuturesUnordered}; use log::{debug, error, info}; -use nym_sphinx::chunking::{monitoring, SentFragment}; +use nym_sphinx::chunking::{SentFragment, monitoring}; use nym_topology::{NymRouteProvider, RoutingNode}; use nym_types::monitoring::{MonitorMessage, NodeResult}; use nym_validator_client::nym_api::routes::{STATUS, SUBMIT_GATEWAY, SUBMIT_NODE, V1_API_VERSION}; @@ -14,7 +14,7 @@ use rand::SeedableRng; use rand_chacha::ChaCha8Rng; use serde::{Deserialize, Serialize}; use tokio::task::JoinHandle; -use tokio_postgres::{binary_copy::BinaryCopyInWriter, types::Type, Client, NoTls}; +use tokio_postgres::{Client, NoTls, binary_copy::BinaryCopyInWriter, types::Type}; use utoipa::ToSchema; use crate::{NYM_API_URL, PRIVATE_KEY, TOPOLOGY}; @@ -247,21 +247,21 @@ impl NetworkAccount { fn find_missing_fragments(&mut self) { let mut missing_fragments_map = HashMap::new(); for fragment_set_id in &self.incomplete_fragment_sets { - if let Some(fragment_ref) = monitoring::FRAGMENTS_RECEIVED.get(fragment_set_id) { - if let Some(ref_fragment) = fragment_ref.value().first() { - let ref_header = ref_fragment.header(); - let ref_id_set = (0..ref_header.total_fragments()).collect::>(); - let recieved_set = fragment_ref - .value() - .iter() - .map(|f| f.header().current_fragment()) - .collect::>(); - let missing_fragments = ref_id_set - .difference(&recieved_set) - .cloned() - .collect::>(); - missing_fragments_map.insert(*fragment_set_id, missing_fragments); - } + if let Some(fragment_ref) = monitoring::FRAGMENTS_RECEIVED.get(fragment_set_id) + && let Some(ref_fragment) = fragment_ref.value().first() + { + let ref_header = ref_fragment.header(); + let ref_id_set = (0..ref_header.total_fragments()).collect::>(); + let recieved_set = fragment_ref + .value() + .iter() + .map(|f| f.header().current_fragment()) + .collect::>(); + let missing_fragments = ref_id_set + .difference(&recieved_set) + .cloned() + .collect::>(); + missing_fragments_map.insert(*fragment_set_id, missing_fragments); }; } self.missing_fragments = missing_fragments_map; diff --git a/nym-network-monitor/src/handlers.rs b/nym-network-monitor/src/handlers.rs index dbdafc4700..3b848fdcdb 100644 --- a/nym-network-monitor/src/handlers.rs +++ b/nym-network-monitor/src/handlers.rs @@ -1,14 +1,14 @@ use axum::{ + Json, extract::{Path, State}, http::StatusCode, - Json, }; use futures::StreamExt; use log::{debug, error, warn}; use nym_sdk::mixnet::MixnetMessageSender; -use nym_sphinx::chunking::{monitoring, ReceivedFragment, SentFragment}; -use petgraph::{dot::Dot, Graph}; -use rand::{distributions::Alphanumeric, seq::SliceRandom, Rng}; +use nym_sphinx::chunking::{ReceivedFragment, SentFragment, monitoring}; +use petgraph::{Graph, dot::Dot}; +use rand::{Rng, distributions::Alphanumeric, seq::SliceRandom}; use serde::Serialize; use std::{ collections::{HashMap, HashSet}, @@ -19,9 +19,9 @@ use tokio::time::timeout; use utoipa::ToSchema; use crate::{ - accounting::{all_node_stats, NetworkAccount, NetworkAccountStats, NodeStats}, - http::AppState, MIXNET_TIMEOUT, + accounting::{NetworkAccount, NetworkAccountStats, NodeStats, all_node_stats}, + http::AppState, }; #[derive(ToSchema, Serialize)] diff --git a/nym-network-monitor/src/http.rs b/nym-network-monitor/src/http.rs index 6608345242..b2eedd53fc 100644 --- a/nym-network-monitor/src/http.rs +++ b/nym-network-monitor/src/http.rs @@ -1,11 +1,11 @@ use crate::accounting::{NetworkAccount, NetworkAccountStats, NodeStats}; use crate::handlers::{ - accounting_handler, all_nodes_stats_handler, graph_handler, mermaid_handler, mix_dot_handler, - node_stats_handler, recv_handler, send_handler, sent_handler, stats_handler, FragmentsReceived, - FragmentsSent, + FragmentsReceived, FragmentsSent, accounting_handler, all_nodes_stats_handler, graph_handler, + mermaid_handler, mix_dot_handler, node_stats_handler, recv_handler, send_handler, sent_handler, + stats_handler, }; -use axum::routing::{get, post}; use axum::Router; +use axum::routing::{get, post}; use log::info; use nym_sphinx::chunking::fragment::FragmentHeader; use nym_sphinx::chunking::{ReceivedFragment, SentFragment}; @@ -83,9 +83,15 @@ impl HttpServer { let server_future = axum::serve(listener, app).with_graceful_shutdown(self.cancel.cancelled_owned()); - info!("##########################################################################################"); - info!("######################### HTTP server running, with {n_clients} clients ############################################"); - info!("##########################################################################################"); + info!( + "##########################################################################################" + ); + info!( + "######################### HTTP server running, with {n_clients} clients ############################################" + ); + info!( + "##########################################################################################" + ); server_future.await?; diff --git a/nym-network-monitor/src/main.rs b/nym-network-monitor/src/main.rs index 4dc9980f00..963ce07379 100644 --- a/nym-network-monitor/src/main.rs +++ b/nym-network-monitor/src/main.rs @@ -13,8 +13,8 @@ use nym_sdk::mixnet::{self, MixnetClient}; use nym_sphinx::chunking::monitoring; use nym_topology::provider_trait::ToTopologyMetadata; use nym_topology::{HardcodedTopologyProvider, NymTopology}; -use nym_validator_client::nym_api::NymApiClientExt; use nym_validator_client::UserAgent; +use nym_validator_client::nym_api::NymApiClientExt; use std::fs::File; use std::io::Write; use std::sync::LazyLock; @@ -154,7 +154,9 @@ fn generate_key_pair() -> Result<()> { let mut private_key_file = File::create("network-monitor-private")?; private_key_file.write_all(keypair.private_key().to_base58_string().as_bytes())?; - info!("Generated keypair, public key to 'network-monitor-public', and private key to 'network-monitor-private', public key should be whitelisted with the nym-api"); + info!( + "Generated keypair, public key to 'network-monitor-public', and private key to 'network-monitor-private', public key should be whitelisted with the nym-api" + ); Ok(()) } diff --git a/nym-node-status-api/nym-node-status-agent/src/cli/run_probe.rs b/nym-node-status-api/nym-node-status-agent/src/cli/run_probe.rs index bee0c7be16..7d0e106b76 100644 --- a/nym-node-status-api/nym-node-status-agent/src/cli/run_probe.rs +++ b/nym-node-status-api/nym-node-status-agent/src/cli/run_probe.rs @@ -108,10 +108,14 @@ pub(crate) async fn run_probe( }; match result { Ok(()) => { - tracing::info!("✅ Successfully submitted {method} to server[{index}] {server_address}:{server_port}"); + tracing::info!( + "✅ Successfully submitted {method} to server[{index}] {server_address}:{server_port}" + ); } Err(e) => { - tracing::warn!("❌ Failed to submit {method} to server[{index}] {server_address}:{server_port} - {e}"); + tracing::warn!( + "❌ Failed to submit {method} to server[{index}] {server_address}:{server_port} - {e}" + ); } } } diff --git a/nym-node-status-api/nym-node-status-agent/src/main.rs b/nym-node-status-api/nym-node-status-agent/src/main.rs index 0415864d9f..9cdb340faa 100644 --- a/nym-node-status-api/nym-node-status-agent/src/main.rs +++ b/nym-node-status-api/nym-node-status-agent/src/main.rs @@ -1,7 +1,7 @@ use crate::cli::Args; use clap::Parser; use tracing::level_filters::LevelFilter; -use tracing_subscriber::{filter::Directive, EnvFilter}; +use tracing_subscriber::{EnvFilter, filter::Directive}; mod cli; mod probe; diff --git a/nym-node-status-api/nym-node-status-api/src/db/mod.rs b/nym-node-status-api/nym-node-status-api/src/db/mod.rs index 83b85d092f..fc948bee81 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/mod.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Result}; +use anyhow::{Result, anyhow}; use std::ops::{Deref, DerefMut}; use std::{str::FromStr, time::Duration}; @@ -9,7 +9,7 @@ pub(crate) mod queries; mod tests; use sqlx::{ - migrate::Migrator, postgres::PgConnectOptions, ConnectOptions, PgPool, Postgres, Transaction, + ConnectOptions, PgPool, Postgres, Transaction, migrate::Migrator, postgres::PgConnectOptions, }; static MIGRATOR: Migrator = sqlx::migrate!("./migrations_pg"); diff --git a/nym-node-status-api/nym-node-status-api/src/db/models.rs b/nym-node-status-api/nym-node-status-api/src/db/models.rs index 67ecf742e7..17c0425fd8 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/models.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/models.rs @@ -1,6 +1,6 @@ use crate::{ http::{self, models::SummaryHistory}, - utils::{decimal_to_i64, unix_timestamp_to_utc_rfc3339, NumericalCheckedCast}, + utils::{NumericalCheckedCast, decimal_to_i64, unix_timestamp_to_utc_rfc3339}, }; use anyhow::Context; use nym_contracts_common::Percent; diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/gateways.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/gateways.rs index aef5eb1c29..196d8623a5 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/gateways.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/gateways.rs @@ -2,8 +2,8 @@ use std::collections::HashSet; use crate::{ db::{ - models::{GatewayDto, GatewayInsertRecord}, DbConnection, DbPool, + models::{GatewayDto, GatewayInsertRecord}, }, http::models::Gateway, node_scraper::helpers::NodeDescriptionResponse, diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/gateways_stats.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/gateways_stats.rs index 7e82caaed7..3a925ae5dd 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/gateways_stats.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/gateways_stats.rs @@ -1,5 +1,5 @@ use crate::{ - db::{models::GatewaySessionsRecord, DbPool}, + db::{DbPool, models::GatewaySessionsRecord}, http::models::SessionStats, }; use futures_util::TryStreamExt; diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/misc.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/misc.rs index 6e4c5d18b8..0dcc6130b3 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/misc.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/misc.rs @@ -1,6 +1,6 @@ use time::UtcDateTime; -use crate::db::{models::NetworkSummary, DbPool}; +use crate::db::{DbPool, models::NetworkSummary}; /// take `last_updated` instead of calculating it so that `summary` matches /// `daily_summary` diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/nym_nodes.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/nym_nodes.rs index b74c09367d..b42f1301a8 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/nym_nodes.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/nym_nodes.rs @@ -12,8 +12,8 @@ use crate::db::DbConnection; use crate::http::models::DailyStats; use crate::{ db::{ - models::{NymNodeDto, NymNodeInsertRecord}, DbPool, + models::{NymNodeDto, NymNodeInsertRecord}, }, node_scraper::helpers::NodeDescriptionResponse, }; diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/packet_stats.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/packet_stats.rs index ca8eb42256..5acccfcceb 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/packet_stats.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/packet_stats.rs @@ -1,8 +1,8 @@ use crate::node_scraper::models::BridgeInformation; use crate::{ db::{ - models::{InsertNodeScraperRecords, NodeStats, ScrapeNodeKind}, DbPool, + models::{InsertNodeScraperRecords, NodeStats, ScrapeNodeKind}, }, node_scraper::helpers::update_daily_stats_uncommitted, utils::now_utc, diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/scraper.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/scraper.rs index ce8a5e7981..ade6163684 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/scraper.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/scraper.rs @@ -1,10 +1,10 @@ use crate::{ db::{ + DbPool, models::{ScrapeNodeKind, ScraperNodeInfo}, queries::{ self, gateways::insert_gateway_description, nym_nodes::insert_nym_node_description, }, - DbPool, }, node_scraper::helpers::NodeDescriptionResponse, utils::now_utc, diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/summary.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/summary.rs index 120c8acece..4f1134d3b0 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/summary.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/summary.rs @@ -4,15 +4,14 @@ use tracing::error; use crate::{ db::{ + DbPool, models::{ + ASSIGNED_ENTRY_COUNT, ASSIGNED_EXIT_COUNT, ASSIGNED_MIXING_COUNT, + GATEWAYS_BONDED_COUNT, GATEWAYS_HISTORICAL_COUNT, MIXNODES_HISTORICAL_COUNT, + NYMNODE_COUNT, NYMNODES_DESCRIBED_COUNT, NetworkSummary, SummaryDto, SummaryHistoryDto, gateway::{GatewaySummary, GatewaySummaryBonded, GatewaySummaryHistorical}, mixnode::{MixingNodesSummary, MixnodeSummary, MixnodeSummaryHistorical}, - NetworkSummary, SummaryDto, SummaryHistoryDto, ASSIGNED_ENTRY_COUNT, - ASSIGNED_EXIT_COUNT, ASSIGNED_MIXING_COUNT, GATEWAYS_BONDED_COUNT, - GATEWAYS_HISTORICAL_COUNT, MIXNODES_HISTORICAL_COUNT, NYMNODES_DESCRIBED_COUNT, - NYMNODE_COUNT, }, - DbPool, }, http::{ error::{HttpError, HttpResult}, diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/testruns.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/testruns.rs index 1f8aafed52..601598fd70 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/testruns.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/testruns.rs @@ -1,6 +1,6 @@ -use crate::db::models::{TestRunDto, TestRunStatus}; use crate::db::DbConnection; use crate::db::DbPool; +use crate::db::models::{TestRunDto, TestRunStatus}; use crate::http::models::TestrunAssignment; use crate::utils::now_utc; use time::Duration; diff --git a/nym-node-status-api/nym-node-status-api/src/db/tests.rs b/nym-node-status-api/nym-node-status-api/src/db/tests.rs index 9c4bca8b93..0c3ae93555 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/tests.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/tests.rs @@ -418,10 +418,12 @@ fn test_nym_node_dto_with_invalid_keys() { let result: Result = nym_node_dto.try_into(); assert!(result.is_err()); - assert!(result - .unwrap_err() - .to_string() - .contains("ed25519_identity_pubkey")); + assert!( + result + .unwrap_err() + .to_string() + .contains("ed25519_identity_pubkey") + ); } #[test] @@ -453,8 +455,10 @@ fn test_nym_node_dto_with_invalid_performance() { let result: Result = nym_node_dto.try_into(); assert!(result.is_err()); - assert!(result - .unwrap_err() - .to_string() - .contains("can't parse Percent")); + assert!( + result + .unwrap_err() + .to_string() + .contains("can't parse Percent") + ); } diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/country.rs b/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/country.rs index 290feff8e7..2d8edc4e2f 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/country.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/country.rs @@ -1,6 +1,6 @@ use axum::{ - extract::{Path, State}, Json, Router, + extract::{Path, State}, }; use itertools::Itertools; use serde::Deserialize; diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/entry.rs b/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/entry.rs index 0de1487f6e..85c8f66c49 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/entry.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/entry.rs @@ -1,11 +1,11 @@ use crate::http::{ - api::dvpn::{country::TwoLetterCountryCodeParam, MIN_SUPPORTED_VERSION}, + api::dvpn::{MIN_SUPPORTED_VERSION, country::TwoLetterCountryCodeParam}, models::DVpnGateway, }; use crate::http::{error::HttpResult, state::AppState}; use axum::{ - extract::{Path, State}, Json, Router, + extract::{Path, State}, }; use itertools::Itertools; use tracing::instrument; diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/exit.rs b/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/exit.rs index a512fe8ff4..5d8b2918f4 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/exit.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/exit.rs @@ -1,11 +1,11 @@ use crate::http::{ - api::dvpn::{country::TwoLetterCountryCodeParam, MIN_SUPPORTED_VERSION}, + api::dvpn::{MIN_SUPPORTED_VERSION, country::TwoLetterCountryCodeParam}, models::DVpnGateway, }; use crate::http::{error::HttpResult, state::AppState}; use axum::{ - extract::{Path, State}, Json, Router, + extract::{Path, State}, }; use itertools::Itertools; use tracing::instrument; diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/mod.rs b/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/mod.rs index 5f0f4cbe19..cf0a4da192 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/dvpn/mod.rs @@ -1,8 +1,8 @@ use crate::http::state::AppState; use axum::Router; use axum::{ - extract::{Query, State}, Json, + extract::{Query, State}, }; use semver::Version; use serde::Deserialize; diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/gateways.rs b/nym-node-status-api/nym-node-status-api/src/http/api/gateways.rs index bc5859fb1b..687e02ad34 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/gateways.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/gateways.rs @@ -1,15 +1,15 @@ use axum::{ - extract::{Path, Query, State}, Json, Router, + extract::{Path, Query, State}, }; use serde::Deserialize; use utoipa::IntoParams; use crate::http::{ + PagedResult, Pagination, error::{HttpError, HttpResult}, models::{Gateway, GatewaySkinny}, state::AppState, - PagedResult, Pagination, }; pub(crate) fn routes() -> Router { diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/metrics/sessions.rs b/nym-node-status-api/nym-node-status-api/src/http/api/metrics/sessions.rs index 6c229e94b4..f65389f8d8 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/metrics/sessions.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/metrics/sessions.rs @@ -1,15 +1,15 @@ use axum::{ - extract::{Query, State}, Json, Router, + extract::{Query, State}, }; use time::Date; use tracing::instrument; use crate::http::{ + PagedResult, Pagination, error::{HttpError, HttpResult}, models::SessionStats, state::AppState, - PagedResult, Pagination, }; pub(crate) fn routes() -> Router { diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/mixnodes.rs b/nym-node-status-api/nym-node-status-api/src/http/api/mixnodes.rs index 52f3f6cbf9..a58ed3c44b 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/mixnodes.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/mixnodes.rs @@ -1,6 +1,6 @@ use axum::{ - extract::{Query, State}, Json, Router, + extract::{Query, State}, }; use serde::Deserialize; use tracing::instrument; diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/mod.rs b/nym-node-status-api/nym-node-status-api/src/http/api/mod.rs index bc0a37d34e..54174e411e 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/mod.rs @@ -1,5 +1,5 @@ use anyhow::anyhow; -use axum::{response::Redirect, Router}; +use axum::{Router, response::Redirect}; use nym_http_api_common::middleware::logging::log_request_debug; use tokio::net::ToSocketAddrs; use tower_http::cors::CorsLayer; diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/nym_nodes.rs b/nym-node-status-api/nym-node-status-api/src/http/api/nym_nodes.rs index f829082ed4..ae551685a4 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/nym_nodes.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/nym_nodes.rs @@ -1,6 +1,6 @@ use axum::{ - extract::{Path, Query, State}, Json, Router, + extract::{Path, Query, State}, }; use nym_validator_client::client::NodeId; use serde::Deserialize; @@ -8,10 +8,10 @@ use tracing::instrument; use utoipa::IntoParams; use crate::http::{ + PagedResult, Pagination, error::{HttpError, HttpResult}, models::{ExtendedNymNode, NodeDelegation}, state::AppState, - PagedResult, Pagination, }; pub(crate) fn routes() -> Router { diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/services/mod.rs b/nym-node-status-api/nym-node-status-api/src/http/api/services/mod.rs index 1a63125b56..9658ab3614 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/services/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/services/mod.rs @@ -1,12 +1,12 @@ use crate::http::{ + PagedResult, Pagination, error::{HttpError, HttpResult}, models::Service, state::AppState, - PagedResult, Pagination, }; use axum::{ - extract::{Query, State}, Json, Router, + extract::{Query, State}, }; use json_path::{ParseJsonPaths, ParsedDetails}; use tracing::instrument; diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/status.rs b/nym-node-status-api/nym-node-status-api/src/http/api/status.rs index a269272e16..318e29813a 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/status.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/status.rs @@ -1,4 +1,4 @@ -use axum::{extract::State, Json, Router}; +use axum::{Json, Router, extract::State}; use nym_validator_client::models::BinaryBuildInformationOwned; use tracing::instrument; diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/summary.rs b/nym-node-status-api/nym-node-status-api/src/http/api/summary.rs index 3a01ee00d2..e1de59ef88 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/summary.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/summary.rs @@ -1,4 +1,4 @@ -use axum::{extract::State, Json, Router}; +use axum::{Json, Router, extract::State}; use tracing::instrument; use crate::{ diff --git a/nym-node-status-api/nym-node-status-api/src/http/api/testruns.rs b/nym-node-status-api/nym-node-status-api/src/http/api/testruns.rs index 30d1cd6d68..1b6c63de3f 100644 --- a/nym-node-status-api/nym-node-status-api/src/http/api/testruns.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/testruns.rs @@ -1,6 +1,6 @@ +use crate::db::DbConnection; use crate::db::models::{TestRunDto, TestRunStatus}; use crate::db::queries; -use crate::db::DbConnection; use crate::utils::{now_utc, unix_timestamp_to_utc_rfc3339}; use crate::{ db, @@ -9,14 +9,14 @@ use crate::{ state::AppState, }, }; -use axum::extract::DefaultBodyLimit; use axum::Json; +use axum::extract::DefaultBodyLimit; use axum::{ - extract::{Path, State}, Router, + extract::{Path, State}, }; use nym_node_status_client::models::{ - get_testrun, submit_results, submit_results_v2, TestrunAssignmentWithTickets, + TestrunAssignmentWithTickets, get_testrun, submit_results, submit_results_v2, }; use reqwest::StatusCode; use tracing::error; 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 58267c553f..f03bfe0398 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 @@ -1,6 +1,6 @@ use cosmwasm_std::Decimal; use itertools::Itertools; -use moka::{future::Cache, Entry}; +use moka::{Entry, future::Cache}; use nym_bin_common::bin_info_owned; use nym_contracts_common::NaiveFloat; use nym_crypto::asymmetric::ed25519::PublicKey; @@ -17,7 +17,7 @@ use utoipa::ToSchema; use super::models::SessionStats; use crate::{ - db::{queries, DbPool}, + db::{DbPool, queries}, http::{ error::{HttpError, HttpResult}, models::{DVpnGateway, DailyStats, ExtendedNymNode, Gateway, NodeGeoData, SummaryHistory}, @@ -302,8 +302,12 @@ impl HttpCache { nodes.insert(key, skimmed_node); } Err(err) => { - error!("CRITICAL: Failed to convert NymNodeDto to SkimmedNode: {err}"); - panic!("Cannot convert database record to SkimmedNode - this should never happen! Error: {err}"); + error!( + "CRITICAL: Failed to convert NymNodeDto to SkimmedNode: {err}" + ); + panic!( + "Cannot convert database record to SkimmedNode - this should never happen! Error: {err}" + ); } } } diff --git a/nym-node-status-api/nym-node-status-api/src/logging.rs b/nym-node-status-api/nym-node-status-api/src/logging.rs index c4581af169..7266632b14 100644 --- a/nym-node-status-api/nym-node-status-api/src/logging.rs +++ b/nym-node-status-api/nym-node-status-api/src/logging.rs @@ -1,5 +1,5 @@ use tracing::level_filters::LevelFilter; -use tracing_subscriber::{filter::Directive, EnvFilter}; +use tracing_subscriber::{EnvFilter, filter::Directive}; // TODO dz you can get the tracing-subscriber via basic-tracing feature on nym-bin-common pub(crate) fn setup_tracing_logger() -> anyhow::Result<()> { diff --git a/nym-node-status-api/nym-node-status-api/src/main.rs b/nym-node-status-api/nym-node-status-api/src/main.rs index f72274d17d..452d395b1d 100644 --- a/nym-node-status-api/nym-node-status-api/src/main.rs +++ b/nym-node-status-api/nym-node-status-api/src/main.rs @@ -1,6 +1,6 @@ use crate::monitor::DelegationsCache; -use crate::ticketbook_manager::state::TicketbookManagerState; use crate::ticketbook_manager::TicketbookManager; +use crate::ticketbook_manager::state::TicketbookManagerState; use clap::Parser; use nym_credential_proxy_lib::quorum_checker::QuorumStateChecker; use nym_credential_proxy_lib::shared_state::nyxd_client::ChainClient; diff --git a/nym-node-status-api/nym-node-status-api/src/metrics_scraper/error.rs b/nym-node-status-api/nym-node-status-api/src/metrics_scraper/error.rs index 86d28d7d08..26ff4a5d97 100644 --- a/nym-node-status-api/nym-node-status-api/src/metrics_scraper/error.rs +++ b/nym-node-status-api/nym-node-status-api/src/metrics_scraper/error.rs @@ -13,7 +13,10 @@ pub enum NodeScraperError { source: Box, }, - #[error("node {node_id} with host '{host}' doesn't seem to expose its declared http port nor any of the standard API ports, i.e.: 80, 443 or {}", DEFAULT_NYM_NODE_HTTP_PORT)] + #[error( + "node {node_id} with host '{host}' doesn't seem to expose its declared http port nor any of the standard API ports, i.e.: 80, 443 or {}", + DEFAULT_NYM_NODE_HTTP_PORT + )] NoHttpPortsAvailable { host: String, node_id: NodeId }, } diff --git a/nym-node-status-api/nym-node-status-api/src/metrics_scraper/mod.rs b/nym-node-status-api/nym-node-status-api/src/metrics_scraper/mod.rs index f94ed8fb00..55bf382308 100644 --- a/nym-node-status-api/nym-node-status-api/src/metrics_scraper/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/metrics_scraper/mod.rs @@ -1,6 +1,6 @@ -use crate::db::{models::GatewaySessionsRecord, queries, DbPool}; +use crate::db::{DbPool, models::GatewaySessionsRecord, queries}; use error::NodeScraperError; -use nym_network_defaults::{NymNetworkDetails, DEFAULT_NYM_NODE_HTTP_PORT}; +use nym_network_defaults::{DEFAULT_NYM_NODE_HTTP_PORT, NymNetworkDetails}; use nym_node_requests::api::{client::NymNodeApiClientExt, v1::metrics::models::SessionStats}; use nym_validator_client::{ client::{NodeId, NymNodeDetails}, diff --git a/nym-node-status-api/nym-node-status-api/src/monitor/mod.rs b/nym-node-status-api/nym-node-status-api/src/monitor/mod.rs index 3695680099..688e644af5 100644 --- a/nym-node-status-api/nym-node-status-api/src/monitor/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/monitor/mod.rs @@ -1,22 +1,22 @@ #![allow(deprecated)] use crate::db::models::{ - gateway, mixnode, GatewayInsertRecord, NetworkSummary, NymNodeInsertRecord, ASSIGNED_ENTRY_COUNT, ASSIGNED_EXIT_COUNT, ASSIGNED_MIXING_COUNT, GATEWAYS_BONDED_COUNT, - GATEWAYS_HISTORICAL_COUNT, MIXNODES_HISTORICAL_COUNT, NYMNODES_DESCRIBED_COUNT, NYMNODE_COUNT, + GATEWAYS_HISTORICAL_COUNT, GatewayInsertRecord, MIXNODES_HISTORICAL_COUNT, NYMNODE_COUNT, + NYMNODES_DESCRIBED_COUNT, NetworkSummary, NymNodeInsertRecord, gateway, mixnode, }; -use crate::db::{queries, DbPool}; +use crate::db::{DbPool, queries}; use crate::utils::now_utc; use crate::utils::{LogError, NumericalCheckedCast}; use moka::future::Cache; use nym_network_defaults::NymNetworkDetails; use nym_validator_client::{ - client::{NodeId, NymApiClientExt, NymNodeDetails}, - models::NymNodeDescription, + QueryHttpRpcNyxdClient, + nym_nodes::{NodeRole, SkimmedNode}, }; use nym_validator_client::{ - nym_nodes::{NodeRole, SkimmedNode}, - QueryHttpRpcNyxdClient, + client::{NodeId, NymApiClientExt, NymNodeDetails}, + models::NymNodeDescription, }; use std::{collections::HashMap, sync::Arc}; use tokio::{sync::RwLock, time::Duration}; diff --git a/nym-node-status-api/nym-node-status-api/src/monitor/node_delegations.rs b/nym-node-status-api/nym-node-status-api/src/monitor/node_delegations.rs index 66f91a6082..fce1aec51e 100644 --- a/nym-node-status-api/nym-node-status-api/src/monitor/node_delegations.rs +++ b/nym-node-status-api/nym-node-status-api/src/monitor/node_delegations.rs @@ -1,5 +1,5 @@ use nym_mixnet_contract_common::{NodeId, NymNodeDetails}; -use nym_validator_client::{nyxd::contract_traits::PagedMixnetQueryClient, QueryHttpRpcNyxdClient}; +use nym_validator_client::{QueryHttpRpcNyxdClient, nyxd::contract_traits::PagedMixnetQueryClient}; use std::{collections::HashMap, sync::Arc}; use tokio::{sync::RwLock, time::Instant}; use tracing::{info, warn}; diff --git a/nym-node-status-api/nym-node-status-api/src/node_scraper/description.rs b/nym-node-status-api/nym-node-status-api/src/node_scraper/description.rs index 311f0da141..82e3b27416 100644 --- a/nym-node-status-api/nym-node-status-api/src/node_scraper/description.rs +++ b/nym-node-status-api/nym-node-status-api/src/node_scraper/description.rs @@ -1,7 +1,7 @@ use super::helpers::scrape_and_store_description; +use crate::db::DbPool; use crate::db::models::ScraperNodeInfo; use crate::db::queries::get_nodes_for_scraping; -use crate::db::DbPool; use anyhow::Result; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; diff --git a/nym-node-status-api/nym-node-status-api/src/node_scraper/helpers.rs b/nym-node-status-api/nym-node-status-api/src/node_scraper/helpers.rs index 5d7f76f5da..4ec1e5d49b 100644 --- a/nym-node-status-api/nym-node-status-api/src/node_scraper/helpers.rs +++ b/nym-node-status-api/nym-node-status-api/src/node_scraper/helpers.rs @@ -1,14 +1,14 @@ use crate::node_scraper::models::BridgeInformation; use crate::{ db::{ + DbPool, models::{InsertNodeScraperRecords, NodeStats, ScrapeNodeKind, ScraperNodeInfo}, queries::insert_scraped_node_description, - DbPool, }, utils::{generate_node_name, now_utc}, }; use ammonia::Builder; -use anyhow::{anyhow, Result}; +use anyhow::{Result, anyhow}; use serde::{Deserialize, Serialize}; use sqlx::Transaction; use std::time::Duration; diff --git a/nym-node-status-api/nym-node-status-api/src/node_scraper/scraper.rs b/nym-node-status-api/nym-node-status-api/src/node_scraper/scraper.rs index 5d0e64ede9..a5cf763e99 100644 --- a/nym-node-status-api/nym-node-status-api/src/node_scraper/scraper.rs +++ b/nym-node-status-api/nym-node-status-api/src/node_scraper/scraper.rs @@ -1,7 +1,7 @@ use super::helpers::scrape_node; use crate::db::DbPool; -use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Duration; use tokio::sync::Mutex; use tokio::task::JoinSet; diff --git a/nym-node-status-api/nym-node-status-api/src/testruns/queue.rs b/nym-node-status-api/nym-node-status-api/src/testruns/queue.rs index 29d24c1b82..8a283f3464 100644 --- a/nym-node-status-api/nym-node-status-api/src/testruns/queue.rs +++ b/nym-node-status-api/nym-node-status-api/src/testruns/queue.rs @@ -1,5 +1,5 @@ -use crate::db::models::{GatewayInfoDto, TestRunDto, TestRunStatus}; use crate::db::DbConnection; +use crate::db::models::{GatewayInfoDto, TestRunDto, TestRunStatus}; use crate::testruns::models::TestRun; use crate::utils::now_utc; use anyhow::anyhow; diff --git a/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/mod.rs b/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/mod.rs index adc9304049..65c807e8a9 100644 --- a/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/ticketbook_manager/mod.rs @@ -5,7 +5,7 @@ use crate::ticketbook_manager::helpers::build_sha_short; use crate::ticketbook_manager::state::TicketbookManagerState; use futures_util::StreamExt; use nym_credential_proxy_lib::deposits_buffer::{ - make_deposits_request, split_deposits, BufferedDeposit, PerformedDeposits, + BufferedDeposit, PerformedDeposits, make_deposits_request, split_deposits, }; use nym_credential_proxy_lib::shared_state::ecash_state::{ IssuanceTicketBook, IssuedTicketBook, TicketType, 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 93dce9ed6e..288f14486b 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 @@ -13,15 +13,15 @@ use nym_credential_proxy_lib::shared_state::required_deposit_cache::RequiredDepo use nym_credential_proxy_lib::storage::traits::{ AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, }; -use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; use nym_credentials::EpochVerificationKey; +use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; use nym_ecash_time::ecash_default_expiration_date; use nym_node_status_client::models::AttachedTicketMaterials; +use nym_validator_client::EcashApiClient; use nym_validator_client::nym_api::EpochId; use nym_validator_client::nyxd::Coin; -use nym_validator_client::EcashApiClient; -use std::collections::hash_map::Entry; use std::collections::HashMap; +use std::collections::hash_map::Entry; use std::sync::Arc; use time::Date; use tokio::sync::RwLockReadGuard; @@ -71,7 +71,9 @@ impl TicketbookManagerState { let epoch_id = ticket.ticketbook.epoch_id(); let expiration_date = ticket.ticketbook.expiration_date(); - debug!("retrieved ticket corresponds to epoch {epoch_id} and expiration date {expiration_date}"); + debug!( + "retrieved ticket corresponds to epoch {epoch_id} and expiration date {expiration_date}" + ); debug!("attempting to attach master verification key..."); if let Entry::Vacant(e) = master_verification_keys.entry(epoch_id) { 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 63e66787d6..cdc757d637 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,8 +1,8 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; use nym_credentials::IssuedTicketBook; +use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; use nym_node_status_client::models::AttachedTicket; use sqlx::FromRow; use time::Date; 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 e8f87fc805..bf4da00b3c 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 @@ -3,7 +3,7 @@ use crate::db::Storage; use crate::ticketbook_manager::storage::auxiliary_models::RetrievedTicketbook; -use anyhow::{anyhow, Context}; +use anyhow::{Context, anyhow}; use nym_credential_proxy_lib::error::CredentialProxyError; use nym_credential_proxy_lib::shared_state::ecash_state::{ IssuanceTicketBook, IssuedTicketBook, TicketType, @@ -13,7 +13,7 @@ use nym_credential_proxy_lib::storage::traits::{ GlobalEcashDataCache, VersionedSerialise, }; use nym_crypto::aes::cipher::zeroize::Zeroizing; -use nym_ecash_time::{ecash_today, EcashTime}; +use nym_ecash_time::{EcashTime, ecash_today}; use nym_validator_client::nym_api::EpochId; use time::Date; diff --git a/nym-node-status-api/nym-node-status-api/src/utils.rs b/nym-node-status-api/nym-node-status-api/src/utils.rs index 044aee6c9d..f90e15fd03 100644 --- a/nym-node-status-api/nym-node-status-api/src/utils.rs +++ b/nym-node-status-api/nym-node-status-api/src/utils.rs @@ -1,7 +1,7 @@ use cosmwasm_std::Decimal; use itertools::Itertools; -use rand::prelude::SliceRandom; use rand::SeedableRng; +use rand::prelude::SliceRandom; use tracing::error; // pub(crate) fn generate_node_name(identity: ed25519::PublicKey) -> String { @@ -30,8 +30,8 @@ mod test { fn generate_node_name_should_be_deterministic() { let mut rng = rand::thread_rng(); - let node_id: i64 = rng.gen(); - let different_node_id: i64 = rng.gen(); + let node_id: i64 = rng.r#gen(); + let different_node_id: i64 = rng.r#gen(); let node_name = generate_node_name(node_id); let node_name_different = generate_node_name(different_node_id); diff --git a/nym-node-status-api/nym-node-status-client/src/lib.rs b/nym-node-status-api/nym-node-status-client/src/lib.rs index 06bec06cd9..0dc9a058ce 100644 --- a/nym-node-status-api/nym-node-status-client/src/lib.rs +++ b/nym-node-status-api/nym-node-status-client/src/lib.rs @@ -1,4 +1,4 @@ -use crate::models::{get_testrun, submit_results, submit_results_v2, TestrunAssignmentWithTickets}; +use crate::models::{TestrunAssignmentWithTickets, get_testrun, submit_results, submit_results_v2}; use anyhow::bail; use api::ApiPaths; use nym_crypto::asymmetric::ed25519::{PrivateKey, Signature}; diff --git a/nym-node/benches/benchmarks.rs b/nym-node/benches/benchmarks.rs index bf2975ec1a..267edd93d4 100644 --- a/nym-node/benches/benchmarks.rs +++ b/nym-node/benches/benchmarks.rs @@ -5,9 +5,9 @@ #![allow(clippy::unwrap_used)] use bloomfilter::Bloom; -use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion}; +use criterion::{BatchSize, Criterion, black_box, criterion_group, criterion_main}; use nym_sphinx_types::REPLAY_TAG_SIZE; -use rand::{thread_rng, Rng}; +use rand::{Rng, thread_rng}; use std::sync::Mutex; pub fn uncontested_bloomfilter_check(c: &mut Criterion) { diff --git a/nym-node/nym-node-metrics/src/network.rs b/nym-node/nym-node-metrics/src/network.rs index ea2b41ff52..74089dd58c 100644 --- a/nym-node/nym-node-metrics/src/network.rs +++ b/nym-node/nym-node-metrics/src/network.rs @@ -1,8 +1,8 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; #[derive(Default)] pub struct NetworkStats { diff --git a/nym-node/nym-node-metrics/src/prometheus_wrapper.rs b/nym-node/nym-node-metrics/src/prometheus_wrapper.rs index 3be0036d9a..4102e82c98 100644 --- a/nym-node/nym-node-metrics/src/prometheus_wrapper.rs +++ b/nym-node/nym-node-metrics/src/prometheus_wrapper.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::mixnet::PacketKind; -use nym_metrics::{metrics_registry, HistogramTimer, Metric}; +use nym_metrics::{HistogramTimer, Metric, metrics_registry}; use std::sync::LazyLock; use strum::{Display, EnumCount, EnumIter, EnumProperty, IntoEnumIterator}; @@ -298,11 +298,11 @@ impl PrometheusMetric { fn set(&self, value: i64) { let reg = metrics_registry(); - if !reg.set(&self.name(), value) { - if let Some(registrable) = self.to_registrable_metric() { - reg.register_metric(registrable); - reg.set(&self.name(), value); - } + if !reg.set(&self.name(), value) + && let Some(registrable) = self.to_registrable_metric() + { + reg.register_metric(registrable); + reg.set(&self.name(), value); } } @@ -320,11 +320,11 @@ impl PrometheusMetric { fn observe_histogram(&self, value: f64) { let reg = metrics_registry(); - if !reg.add_to_histogram(&self.name(), value) { - if let Some(registrable) = self.to_registrable_metric() { - reg.register_metric(registrable); - reg.add_to_histogram(&self.name(), value); - } + if !reg.add_to_histogram(&self.name(), value) + && let Some(registrable) = self.to_registrable_metric() + { + reg.register_metric(registrable); + reg.add_to_histogram(&self.name(), value); } } @@ -343,10 +343,10 @@ impl NymNodePrometheusMetrics { // we can't initialise complex metrics as their names will only be fully known at runtime for kind in PrometheusMetric::iter() { - if !kind.is_complex() { - if let Some(metric) = kind.to_registrable_metric() { - registry.register_metric(metric); - } + if !kind.is_complex() + && let Some(metric) = kind.to_registrable_metric() + { + registry.register_metric(metric); } } diff --git a/nym-node/src/cli/commands/debug/reset_providers_dbs.rs b/nym-node/src/cli/commands/debug/reset_providers_dbs.rs index 39130686ae..8e9eba41bb 100644 --- a/nym-node/src/cli/commands/debug/reset_providers_dbs.rs +++ b/nym-node/src/cli/commands/debug/reset_providers_dbs.rs @@ -3,8 +3,8 @@ use crate::cli::helpers::ConfigArgs; use crate::config::upgrade_helpers::try_load_current_config; -use crate::node::helpers::load_ed25519_identity_public_key; use crate::node::ServiceProvidersData; +use crate::node::helpers::load_ed25519_identity_public_key; use nym_network_requester::{CustomGatewayDetails, GatewayDetails, GatewayRegistration}; use std::fs; diff --git a/nym-node/src/cli/commands/run/mod.rs b/nym-node/src/cli/commands/run/mod.rs index 703e47662b..36f77c7b29 100644 --- a/nym-node/src/cli/commands/run/mod.rs +++ b/nym-node/src/cli/commands/run/mod.rs @@ -3,9 +3,9 @@ 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 crate::node::NymNode; use std::fs; use std::net::IpAddr; use tracing::{debug, info, trace, warn}; @@ -28,9 +28,11 @@ fn check_public_ips(ips: &[IpAddr], local: bool) -> Result<(), NymNodeError> { if !suspicious_ip.is_empty() { warn!("\n##### WARNING #####"); for ip in suspicious_ip { - warn!("The 'public' IP address you're trying to announce: {ip} may not be accessible to other clients.\ + warn!( + "The 'public' IP address you're trying to announce: {ip} may not be accessible to other clients.\ Please make sure this is what you intended to announce.\ - You can ignore this warning if you're running setup on a local network ") + You can ignore this warning if you're running setup on a local network " + ) } warn!("\n##### WARNING #####\n"); } @@ -49,7 +51,9 @@ pub(crate) async fn execute(mut args: Args) -> Result<(), NymNodeError> { if !accepted_operator_terms_and_conditions { warn!("you don't seem to have accepted the terms and conditions of a Nym node operator"); - warn!("please familiarise yourself with and run the binary with '--accept-operator-terms-and-conditions' flag if you agree with them"); + warn!( + "please familiarise yourself with and run the binary with '--accept-operator-terms-and-conditions' flag if you agree with them" + ); } let config = if !config_path.exists() { @@ -81,11 +85,15 @@ pub(crate) async fn execute(mut args: Args) -> Result<(), NymNodeError> { config.validate()?; if !config.modes.any_enabled() { - warn!("this node is going to run without mixnode or gateway support! consider providing `mode` value"); + warn!( + "this node is going to run without mixnode or gateway support! consider providing `mode` value" + ); } if config.modes.standalone_exit() { - warn!("this node is going to run in EXIT gateway mode only - it will not be able to accept client traffic and thus will NOT be eligible for any rewards. consider running it alongside `entry` (or `full-gateway`) mode") + warn!( + "this node is going to run in EXIT gateway mode only - it will not be able to accept client traffic and thus will NOT be eligible for any rewards. consider running it alongside `entry` (or `full-gateway`) mode" + ) } if config.host.public_ips.is_empty() { diff --git a/nym-node/src/cli/commands/sign.rs b/nym-node/src/cli/commands/sign.rs index a05db78c85..5393c00e78 100644 --- a/nym-node/src/cli/commands/sign.rs +++ b/nym-node/src/cli/commands/sign.rs @@ -44,7 +44,9 @@ fn print_signed_contract_msg( eprintln!(">>> attempting to sign {trimmed}"); let Ok(decoded) = bs58::decode(trimmed).into_vec() else { - println!("it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters"); + println!( + "it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters" + ); return; }; @@ -53,7 +55,9 @@ fn print_signed_contract_msg( // we don't really care about what particular information is embedded inside of it, // we just want to know if user correctly copied the string, i.e. whether it's a valid bs58 encoded json if serde_json::from_slice::(&decoded).is_err() { - println!("it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters"); + println!( + "it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters" + ); return; }; diff --git a/nym-node/src/cli/helpers.rs b/nym-node/src/cli/helpers.rs index cf6d18b683..5211696485 100644 --- a/nym-node/src/cli/helpers.rs +++ b/nym-node/src/cli/helpers.rs @@ -6,8 +6,8 @@ use crate::config; use crate::config::default_config_filepath; use crate::env::vars::*; use celes::Country; -use clap::builder::ArgPredicate; use clap::Args; +use clap::builder::ArgPredicate; use std::net::{IpAddr, SocketAddr}; use std::path::{Path, PathBuf}; use url::Url; diff --git a/nym-node/src/config/mod.rs b/nym-node/src/config/mod.rs index e401de4e20..3a20022a15 100644 --- a/nym-node/src/config/mod.rs +++ b/nym-node/src/config/mod.rs @@ -9,17 +9,17 @@ use clap::ValueEnum; use human_repr::HumanCount; use nym_bin_common::logging::LoggingSettings; use nym_config::defaults::{ - mainnet, var_names, DEFAULT_MIX_LISTENING_PORT, DEFAULT_NYM_NODE_HTTP_PORT, - DEFAULT_VERLOC_LISTENING_PORT, WG_METADATA_PORT, WG_TUNNEL_PORT, WG_TUN_DEVICE_IP_ADDRESS_V4, - WG_TUN_DEVICE_IP_ADDRESS_V6, + DEFAULT_MIX_LISTENING_PORT, DEFAULT_NYM_NODE_HTTP_PORT, DEFAULT_VERLOC_LISTENING_PORT, + WG_METADATA_PORT, WG_TUN_DEVICE_IP_ADDRESS_V4, WG_TUN_DEVICE_IP_ADDRESS_V6, WG_TUNNEL_PORT, + mainnet, var_names, }; use nym_config::defaults::{WG_TUN_DEVICE_NETMASK_V4, WG_TUN_DEVICE_NETMASK_V6}; use nym_config::helpers::{in6addr_any_init, inaddr_any}; use nym_config::serde_helpers::de_maybe_port; use nym_config::serde_helpers::de_maybe_stringified; use nym_config::{ + DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, NymConfigTemplate, must_get_home, parse_urls, read_config_from_toml_file, save_formatted_config_to_file, - NymConfigTemplate, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, }; use nym_gateway::nym_authenticator; use serde::{Deserialize, Serialize}; @@ -391,7 +391,8 @@ impl Config { if config_dir_name != DEFAULT_CONFIG_DIR { error!( "the parent directory of '{}' ({}) is not {DEFAULT_CONFIG_DIR}. currently this is not supported", - config_path.display(), config_dir_name.to_str().unwrap_or("UNKNOWN") + config_path.display(), + config_dir_name.to_str().unwrap_or("UNKNOWN") ); return Err(NymNodeError::DataDirDerivationFailure); } @@ -718,8 +719,11 @@ impl ReplayProtectionDebug { let memory = sys_info.available_memory(); if (memory as usize) < required_memory { - return Err(NymNodeError::config_validation_failure( - format!("system does not have sufficient memory to allocate required replay protection bloomfilters. {} is available whilst at least {} is needed",memory.human_count_bytes(), required_memory.human_count_bytes()))); + return Err(NymNodeError::config_validation_failure(format!( + "system does not have sufficient memory to allocate required replay protection bloomfilters. {} is available whilst at least {} is needed", + memory.human_count_bytes(), + required_memory.human_count_bytes() + ))); } Ok(()) diff --git a/nym-node/src/config/old_configs/mod.rs b/nym-node/src/config/old_configs/mod.rs index e67f2a83e9..f87c88a43a 100644 --- a/nym-node/src/config/old_configs/mod.rs +++ b/nym-node/src/config/old_configs/mod.rs @@ -13,7 +13,6 @@ mod old_config_v8; mod old_config_v9; pub use old_config_v1::try_upgrade_config_v1; -pub use old_config_v10::try_upgrade_config_v10; pub use old_config_v2::try_upgrade_config_v2; pub use old_config_v3::try_upgrade_config_v3; pub use old_config_v4::try_upgrade_config_v4; @@ -22,3 +21,4 @@ pub use old_config_v6::try_upgrade_config_v6; pub use old_config_v7::try_upgrade_config_v7; pub use old_config_v8::try_upgrade_config_v8; pub use old_config_v9::try_upgrade_config_v9; +pub use old_config_v10::try_upgrade_config_v10; diff --git a/nym-node/src/config/old_configs/old_config_v10.rs b/nym-node/src/config/old_configs/old_config_v10.rs index 3a86ebdd91..3a395685f5 100644 --- a/nym-node/src/config/old_configs/old_config_v10.rs +++ b/nym-node/src/config/old_configs/old_config_v10.rs @@ -13,9 +13,9 @@ use crate::config::service_providers::{ IpPacketRouter, IpPacketRouterDebug, NetworkRequester, NetworkRequesterDebug, }; use crate::config::{ - gateway_tasks, service_providers, Config, GatewayTasksConfig, Host, Http, KeyRotation, - KeyRotationDebug, Mixnet, MixnetDebug, NodeModes, ReplayProtection, ReplayProtectionDebug, - ServiceProvidersConfig, Verloc, VerlocDebug, Wireguard, DEFAULT_HTTP_PORT, + Config, DEFAULT_HTTP_PORT, GatewayTasksConfig, Host, Http, KeyRotation, KeyRotationDebug, + Mixnet, MixnetDebug, NodeModes, ReplayProtection, ReplayProtectionDebug, + ServiceProvidersConfig, Verloc, VerlocDebug, Wireguard, gateway_tasks, service_providers, }; use crate::error::NymNodeError; use celes::Country; diff --git a/nym-node/src/config/old_configs/old_config_v2.rs b/nym-node/src/config/old_configs/old_config_v2.rs index d1b1003caf..28eb441214 100644 --- a/nym-node/src/config/old_configs/old_config_v2.rs +++ b/nym-node/src/config/old_configs/old_config_v2.rs @@ -8,8 +8,8 @@ use nym_client_core_config_types::DebugConfig as ClientDebugConfig; use nym_config::serde_helpers::de_maybe_port; use nym_crypto::asymmetric::{ed25519, x25519}; use nym_network_requester::{ - set_active_gateway, setup_fs_gateways_storage, store_gateway_details, CustomGatewayDetails, - GatewayDetails, + CustomGatewayDetails, GatewayDetails, set_active_gateway, setup_fs_gateways_storage, + store_gateway_details, }; use nym_pemstore::{load_key, store_key, store_keypair}; use nym_sphinx_acknowledgements::AckKey; @@ -682,7 +682,8 @@ impl ConfigV2 { if config_dir_name != DEFAULT_CONFIG_DIR { error!( "the parent directory of '{}' ({}) is not {DEFAULT_CONFIG_DIR}. currently this is not supported", - config_path.display(), config_dir_name.to_str().unwrap_or("UNKNOWN") + config_path.display(), + config_dir_name.to_str().unwrap_or("UNKNOWN") ); return Err(NymNodeError::DataDirDerivationFailure); } diff --git a/nym-node/src/config/old_configs/old_config_v4.rs b/nym-node/src/config/old_configs/old_config_v4.rs index 98912cbb9e..1293424322 100644 --- a/nym-node/src/config/old_configs/old_config_v4.rs +++ b/nym-node/src/config/old_configs/old_config_v4.rs @@ -5,8 +5,8 @@ use crate::config::*; use nym_client_core_config_types::{ - disk_persistence::{ClientKeysPaths, CommonClientPaths}, DebugConfig as ClientDebugConfig, + disk_persistence::{ClientKeysPaths, CommonClientPaths}, }; use nym_config::{defaults::TICKETBOOK_VALIDITY_DAYS, serde_helpers::de_maybe_port}; use old_configs::old_config_v5::*; diff --git a/nym-node/src/config/old_configs/old_config_v5.rs b/nym-node/src/config/old_configs/old_config_v5.rs index 5dbacdaedb..ec22dbb111 100644 --- a/nym-node/src/config/old_configs/old_config_v5.rs +++ b/nym-node/src/config/old_configs/old_config_v5.rs @@ -5,8 +5,8 @@ use crate::config::*; use nym_client_core_config_types::{ - disk_persistence::{ClientKeysPaths, CommonClientPaths}, DebugConfig as ClientDebugConfig, + disk_persistence::{ClientKeysPaths, CommonClientPaths}, }; use nym_config::{defaults::TICKETBOOK_VALIDITY_DAYS, serde_helpers::de_maybe_port}; use old_configs::old_config_v6::*; diff --git a/nym-node/src/config/old_configs/old_config_v6.rs b/nym-node/src/config/old_configs/old_config_v6.rs index ebf3cc5b44..32c9fc41d7 100644 --- a/nym-node/src/config/old_configs/old_config_v6.rs +++ b/nym-node/src/config/old_configs/old_config_v6.rs @@ -8,8 +8,8 @@ use crate::error::NymNodeError; use celes::Country; use clap::ValueEnum; use nym_client_core_config_types::{ - disk_persistence::{ClientKeysPaths, CommonClientPaths}, DebugConfig as ClientDebugConfig, + disk_persistence::{ClientKeysPaths, CommonClientPaths}, }; use nym_config::defaults::{mainnet, var_names}; use nym_config::helpers::inaddr_any; diff --git a/nym-node/src/config/old_configs/old_config_v9.rs b/nym-node/src/config/old_configs/old_config_v9.rs index d30649d660..d14b89f31a 100644 --- a/nym-node/src/config/old_configs/old_config_v9.rs +++ b/nym-node/src/config/old_configs/old_config_v9.rs @@ -15,7 +15,7 @@ use crate::config::old_configs::old_config_v10::{ use crate::config::persistence::{ DEFAULT_PRIMARY_X25519_SPHINX_KEY_FILENAME, DEFAULT_SECONDARY_X25519_SPHINX_KEY_FILENAME, }; -use crate::config::{NodeModes, DEFAULT_HTTP_PORT}; +use crate::config::{DEFAULT_HTTP_PORT, NodeModes}; use crate::error::{KeyIOFailure, NymNodeError}; use crate::node::helpers::{get_current_rotation_id, load_key, store_key}; use crate::node::key_rotation::key::SphinxPrivateKey; diff --git a/nym-node/src/config/upgrade_helpers.rs b/nym-node/src/config/upgrade_helpers.rs index bdb10ec8b7..63dda0d6e8 100644 --- a/nym-node/src/config/upgrade_helpers.rs +++ b/nym-node/src/config/upgrade_helpers.rs @@ -1,8 +1,8 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::config::old_configs::*; use crate::config::Config; +use crate::config::old_configs::*; use crate::error::NymNodeError; use std::path::Path; use tracing::debug; diff --git a/nym-node/src/error.rs b/nym-node/src/error.rs index e199e3aef1..abe336dc44 100644 --- a/nym-node/src/error.rs +++ b/nym-node/src/error.rs @@ -5,8 +5,8 @@ use crate::node::http::error::NymNodeHttpError; use crate::wireguard::error::WireguardError; use nym_http_api_client::HttpClientError; use nym_ip_packet_router::error::ClientCoreError; -use nym_validator_client::nyxd::error::NyxdError; use nym_validator_client::ValidatorClientError; +use nym_validator_client::nyxd::error::NyxdError; use std::io; use std::net::IpAddr; use std::path::PathBuf; @@ -142,7 +142,9 @@ pub enum NymNodeError { source: io::Error, }, - #[error("this node hasn't set any valid public addresses to announce. Please modify [host.public_ips] section of your config")] + #[error( + "this node hasn't set any valid public addresses to announce. Please modify [host.public_ips] section of your config" + )] NoPublicIps, #[error("there are no available nym api endpoints")] @@ -162,7 +164,9 @@ pub enum NymNodeError { #[error("failed to resolve chain query: {0}")] NyxdFailure(#[from] NyxdError), - #[error("this node attempted to announce an invalid public address: {address}. Please modify [host.public_ips] section of your config. Alternatively, if you wanted to use it in the local setting, run the node with the '--local' flag.")] + #[error( + "this node attempted to announce an invalid public address: {address}. Please modify [host.public_ips] section of your config. Alternatively, if you wanted to use it in the local setting, run the node with the '--local' flag." + )] InvalidPublicIp { address: IpAddr }, #[error(transparent)] @@ -184,7 +188,9 @@ pub enum NymNodeError { #[error(transparent)] KeyFailure(#[from] KeyIOFailure), - #[error("could not initialise nym-node as '--{name}' has not been specified which is required for a first time setup. (config section: {section})")] + #[error( + "could not initialise nym-node as '--{name}' has not been specified which is required for a first time setup. (config section: {section})" + )] MissingInitArg { section: String, name: String }, #[error("there was an issue with wireguard IP network: {source}")] diff --git a/nym-node/src/main.rs b/nym-node/src/main.rs index 04ff85bb91..8c7a8aa2e2 100644 --- a/nym-node/src/main.rs +++ b/nym-node/src/main.rs @@ -5,7 +5,7 @@ #![warn(clippy::unwrap_used)] use crate::cli::Cli; -use clap::{crate_name, crate_version, Parser}; +use clap::{Parser, crate_name, crate_version}; use nym_bin_common::logging::maybe_print_banner; use nym_config::defaults::setup_env; diff --git a/nym-node/src/node/bonding_information.rs b/nym-node/src/node/bonding_information.rs index 94d151dd03..da61384717 100644 --- a/nym-node/src/node/bonding_information.rs +++ b/nym-node/src/node/bonding_information.rs @@ -18,7 +18,10 @@ impl Display for BondingInformation { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { writeln!(f, "Identity Key: {}", self.identity_key)?; writeln!(f, "Host: {}", self.host)?; - writeln!(f, "Custom HTTP Port: you might want to set it if your node won't be accessible on any of the ports: 80/443/8080")?; + writeln!( + f, + "Custom HTTP Port: you might want to set it if your node won't be accessible on any of the ports: 80/443/8080" + )?; Ok(()) } diff --git a/nym-node/src/node/helpers.rs b/nym-node/src/node/helpers.rs index dbd8b15086..b0112a7004 100644 --- a/nym-node/src/node/helpers.rs +++ b/nym-node/src/node/helpers.rs @@ -7,11 +7,11 @@ use crate::node::key_rotation::key::{SphinxPrivateKey, SphinxPublicKey}; use crate::node::nym_apis_client::NymApisClient; use nym_crypto::asymmetric::{ed25519, x25519}; use nym_node_requests::api::v1::node::models::NodeDescription; -use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair}; use nym_pemstore::KeyPairPath; +use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair}; use nym_task::ShutdownToken; -use nym_validator_client::nyxd::contract_traits::MixnetQueryClient; use nym_validator_client::QueryHttpRpcNyxdClient; +use nym_validator_client::nyxd::contract_traits::MixnetQueryClient; use serde::Serialize; use std::fmt::{Display, Formatter}; use std::path::Path; diff --git a/nym-node/src/node/http/mod.rs b/nym-node/src/node/http/mod.rs index 3b7f8d9b45..17943a71cd 100644 --- a/nym-node/src/node/http/mod.rs +++ b/nym-node/src/node/http/mod.rs @@ -1,14 +1,14 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use axum::extract::connect_info::IntoMakeServiceWithConnectInfo; +use axum::Router; use axum::extract::ConnectInfo; +use axum::extract::connect_info::IntoMakeServiceWithConnectInfo; use axum::middleware::AddExtension; use axum::serve::Serve; -use axum::Router; use std::net::SocketAddr; -pub use router::{api, HttpServerConfig, NymNodeRouter}; +pub use router::{HttpServerConfig, NymNodeRouter, api}; pub mod error; pub mod helpers; diff --git a/nym-node/src/node/http/router/api/v1/authenticator/mod.rs b/nym-node/src/node/http/router/api/v1/authenticator/mod.rs index ba86dfd272..cfd97b12aa 100644 --- a/nym-node/src/node/http/router/api/v1/authenticator/mod.rs +++ b/nym-node/src/node/http/router/api/v1/authenticator/mod.rs @@ -1,8 +1,8 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use axum::routing::get; use axum::Router; +use axum::routing::get; use nym_node_requests::api::v1::authenticator::models; pub mod root; diff --git a/nym-node/src/node/http/router/api/v1/gateway/client_interfaces/mod.rs b/nym-node/src/node/http/router/api/v1/gateway/client_interfaces/mod.rs index 6e2b5c57d2..703df8e7ff 100644 --- a/nym-node/src/node/http/router/api/v1/gateway/client_interfaces/mod.rs +++ b/nym-node/src/node/http/router/api/v1/gateway/client_interfaces/mod.rs @@ -1,10 +1,10 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only +use axum::Router; use axum::extract::Query; use axum::http::StatusCode; use axum::routing::get; -use axum::Router; use nym_http_api_common::{FormattedResponse, OutputParams}; use nym_node_requests::api::v1::gateway::models::{ClientInterfaces, WebSockets, Wireguard}; use nym_node_requests::routes::api::v1::gateway::client_interfaces; diff --git a/nym-node/src/node/http/router/api/v1/gateway/mod.rs b/nym-node/src/node/http/router/api/v1/gateway/mod.rs index bd8f5fef4b..1e23c000ca 100644 --- a/nym-node/src/node/http/router/api/v1/gateway/mod.rs +++ b/nym-node/src/node/http/router/api/v1/gateway/mod.rs @@ -1,8 +1,8 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use axum::routing::get; use axum::Router; +use axum::routing::get; use nym_node_requests::api::v1::gateway::models; use nym_node_requests::routes::api::v1::gateway; diff --git a/nym-node/src/node/http/router/api/v1/ip_packet_router/mod.rs b/nym-node/src/node/http/router/api/v1/ip_packet_router/mod.rs index ab6b2ed72e..d87b230b71 100644 --- a/nym-node/src/node/http/router/api/v1/ip_packet_router/mod.rs +++ b/nym-node/src/node/http/router/api/v1/ip_packet_router/mod.rs @@ -1,8 +1,8 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use axum::routing::get; use axum::Router; +use axum::routing::get; use nym_node_requests::api::v1::ip_packet_router::models; pub mod root; diff --git a/nym-node/src/node/http/router/api/v1/metrics/mod.rs b/nym-node/src/node/http/router/api/v1/metrics/mod.rs index 51af714434..0d1eeb836d 100644 --- a/nym-node/src/node/http/router/api/v1/metrics/mod.rs +++ b/nym-node/src/node/http/router/api/v1/metrics/mod.rs @@ -7,9 +7,9 @@ use crate::node::http::api::v1::metrics::sessions::sessions_stats; use crate::node::http::api::v1::metrics::verloc::verloc_stats; use crate::node::http::api::v1::metrics::wireguard::wireguard_stats; use crate::node::http::state::metrics::MetricsAppState; +use axum::Router; use axum::extract::FromRef; use axum::routing::get; -use axum::Router; use nym_http_api_common::middleware::bearer_auth::AuthLayer; use nym_node_requests::routes::api::v1::metrics; use nym_node_requests::routes::api::v1::metrics::prometheus_absolute; diff --git a/nym-node/src/node/http/router/api/v1/mixnode/mod.rs b/nym-node/src/node/http/router/api/v1/mixnode/mod.rs index 8072b5a822..aea6c65f71 100644 --- a/nym-node/src/node/http/router/api/v1/mixnode/mod.rs +++ b/nym-node/src/node/http/router/api/v1/mixnode/mod.rs @@ -1,8 +1,8 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use axum::routing::get; use axum::Router; +use axum::routing::get; use nym_node_requests::api::v1::mixnode::models; pub mod root; diff --git a/nym-node/src/node/http/router/api/v1/mod.rs b/nym-node/src/node/http/router/api/v1/mod.rs index 983c1a76f0..d0f2239f1d 100644 --- a/nym-node/src/node/http/router/api/v1/mod.rs +++ b/nym-node/src/node/http/router/api/v1/mod.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::node::http::state::AppState; -use axum::routing::get; use axum::Router; +use axum::routing::get; use nym_node_requests::routes::api::v1; pub mod authenticator; diff --git a/nym-node/src/node/http/router/api/v1/network_requester/mod.rs b/nym-node/src/node/http/router/api/v1/network_requester/mod.rs index 5524b51508..46b99e8b27 100644 --- a/nym-node/src/node/http/router/api/v1/network_requester/mod.rs +++ b/nym-node/src/node/http/router/api/v1/network_requester/mod.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::node::http::api::v1::network_requester::exit_policy::node_exit_policy; -use axum::routing::get; use axum::Router; +use axum::routing::get; use nym_node_requests::api::v1::network_requester::exit_policy::models::UsedExitPolicy; use nym_node_requests::api::v1::network_requester::models; use nym_node_requests::routes::api::v1::network_requester; diff --git a/nym-node/src/node/http/router/api/v1/node/host_information.rs b/nym-node/src/node/http/router/api/v1/node/host_information.rs index 7bb036ea1f..53427f0cdf 100644 --- a/nym-node/src/node/http/router/api/v1/node/host_information.rs +++ b/nym-node/src/node/http/router/api/v1/node/host_information.rs @@ -5,7 +5,7 @@ use crate::node::http::api::api_requests; use crate::node::http::state::AppState; use axum::extract::{Query, State}; use nym_http_api_common::{FormattedResponse, OutputParams}; -use nym_node_requests::api::{v1::node::models::SignedHostInformation, SignedDataHostInfo}; +use nym_node_requests::api::{SignedDataHostInfo, v1::node::models::SignedHostInformation}; /// Returns host information of this node. #[utoipa::path( diff --git a/nym-node/src/node/http/router/api/v1/node/mod.rs b/nym-node/src/node/http/router/api/v1/node/mod.rs index 3b115602b7..a877722d3a 100644 --- a/nym-node/src/node/http/router/api/v1/node/mod.rs +++ b/nym-node/src/node/http/router/api/v1/node/mod.rs @@ -8,8 +8,8 @@ use crate::node::http::api::v1::node::hardware::host_system; use crate::node::http::api::v1::node::host_information::host_information; use crate::node::http::api::v1::node::roles::roles; use crate::node::http::state::AppState; -use axum::routing::get; use axum::Router; +use axum::routing::get; use nym_node_requests::api::v1::node::models; use nym_node_requests::routes::api::v1; diff --git a/nym-node/src/node/http/router/api/v1/openapi.rs b/nym-node/src/node/http/router/api/v1/openapi.rs index 59de2ad6de..98835e4c59 100644 --- a/nym-node/src/node/http/router/api/v1/openapi.rs +++ b/nym-node/src/node/http/router/api/v1/openapi.rs @@ -6,7 +6,7 @@ use axum::Router; use nym_node_requests::api as api_requests; use nym_node_requests::routes::api::{v1, v1_absolute}; use utoipa::openapi::security::{Http, HttpAuthScheme}; -use utoipa::{openapi::security::SecurityScheme, Modify, OpenApi}; +use utoipa::{Modify, OpenApi, openapi::security::SecurityScheme}; use utoipa_swagger_ui::SwaggerUi; #[derive(OpenApi)] diff --git a/nym-node/src/node/http/router/landing_page.rs b/nym-node/src/node/http/router/landing_page.rs index 8a0f28b017..ed3536e371 100644 --- a/nym-node/src/node/http/router/landing_page.rs +++ b/nym-node/src/node/http/router/landing_page.rs @@ -1,9 +1,9 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only +use axum::Router; use axum::response::Html; use axum::routing::get; -use axum::Router; use std::path::PathBuf; use tower_http::services::ServeDir; diff --git a/nym-node/src/node/http/router/mod.rs b/nym-node/src/node/http/router/mod.rs index 0d0d326985..b849ac5a05 100644 --- a/nym-node/src/node/http/router/mod.rs +++ b/nym-node/src/node/http/router/mod.rs @@ -1,12 +1,12 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only +use crate::node::http::NymNodeHttpServer; use crate::node::http::error::NymNodeHttpError; use crate::node::http::state::AppState; -use crate::node::http::NymNodeHttpServer; +use axum::Router; use axum::response::Redirect; use axum::routing::get; -use axum::Router; use nym_bin_common::bin_info_owned; use nym_http_api_common::middleware::logging; use nym_node_requests::api::v1::authenticator::models::Authenticator; diff --git a/nym-node/src/node/http/router/types.rs b/nym-node/src/node/http/router/types.rs index c8b692bda9..f36351ceac 100644 --- a/nym-node/src/node/http/router/types.rs +++ b/nym-node/src/node/http/router/types.rs @@ -1,9 +1,9 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only +use axum::Json; use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; -use axum::Json; pub use nym_node_requests::api::ErrorResponse; #[derive(Debug, Clone)] diff --git a/nym-node/src/node/http/state/load.rs b/nym-node/src/node/http/state/load.rs index 96199426db..5a33aa04c9 100644 --- a/nym-node/src/node/http/state/load.rs +++ b/nym-node/src/node/http/state/load.rs @@ -3,8 +3,8 @@ use arc_swap::ArcSwap; use nym_node_requests::api::v1::node_load::models::{Load, NodeLoad}; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; use sysinfo::{CpuRefreshKind, MemoryRefreshKind, Networks, System}; use time::OffsetDateTime; diff --git a/nym-node/src/node/key_rotation/active_keys.rs b/nym-node/src/node/key_rotation/active_keys.rs index d018db4e88..8d96d69ea0 100644 --- a/nym-node/src/node/key_rotation/active_keys.rs +++ b/nym-node/src/node/key_rotation/active_keys.rs @@ -92,7 +92,9 @@ impl ActiveSphinxKeys { // and the current primary as the secondary (for the overlap epoch) pub(crate) fn rotate(&self, expected_new_rotation: u32) -> bool { let Some(pre_announced) = self.inner.secondary_key.load_full() else { - error!("sphinx key inconsistency - attempted to perform key rotation without having pre-announced new key"); + error!( + "sphinx key inconsistency - attempted to perform key rotation without having pre-announced new key" + ); return false; }; diff --git a/nym-node/src/node/key_rotation/controller.rs b/nym-node/src/node/key_rotation/controller.rs index c7aee7d671..0a84ed5579 100644 --- a/nym-node/src/node/key_rotation/controller.rs +++ b/nym-node/src/node/key_rotation/controller.rs @@ -10,7 +10,7 @@ use nym_task::ShutdownToken; use nym_validator_client::models::{KeyRotationDetails, KeyRotationInfoResponse, KeyRotationState}; use std::time::Duration; use time::OffsetDateTime; -use tokio::time::{interval, sleep, Instant}; +use tokio::time::{Instant, interval, sleep}; use tracing::{debug, error, info, trace, warn}; pub(crate) struct RotationConfig { @@ -154,7 +154,9 @@ impl KeyRotationController { let expected_current_rotation_id = key_rotation_info.expected_current_rotation_id(); if current_rotation_id != expected_current_rotation_id { - warn!("the current rotation is {current_rotation_id} whilst we expected {expected_current_rotation_id}"); + warn!( + "the current rotation is {current_rotation_id} whilst we expected {expected_current_rotation_id}" + ); // if we got here, it means epoch is most likely NOT stuck (we're within the threshold) // so probably we prematurely called this method before nym-api(s) got to advancing // the epoch and thus the rotation, so wait a bit instead. @@ -200,7 +202,9 @@ impl KeyRotationController { // pre-announce new key for the following rotation if primary_key_rotation_id != current_rotation_id { - warn!("current primary key does not correspond to the current rotation - immediately pre-announcing new key (rotates next epoch: {rotates_next_epoch}"); + warn!( + "current primary key does not correspond to the current rotation - immediately pre-announcing new key (rotates next epoch: {rotates_next_epoch}" + ); // we don't have a secondary key and our current key is already outdated - // preannounce a key for either this or the next rotation // (and next time this method is called, it will be promoted to primary) @@ -267,7 +271,9 @@ impl KeyRotationController { async fn try_get_key_rotation_info(&self) -> Option { let Ok(rotation_info) = self.client.get_key_rotation_info().await else { - warn!("failed to retrieve key rotation information from ANY nym-api - we might miss configuration changes"); + warn!( + "failed to retrieve key rotation information from ANY nym-api - we might miss configuration changes" + ); return None; }; diff --git a/nym-node/src/node/key_rotation/manager.rs b/nym-node/src/node/key_rotation/manager.rs index 0a4c0df27d..c969d235cb 100644 --- a/nym-node/src/node/key_rotation/manager.rs +++ b/nym-node/src/node/key_rotation/manager.rs @@ -154,21 +154,25 @@ impl SphinxKeyManager { let secondary_id = secondary.as_ref().map(|k| k.rotation_id()); // 1. check for failed (or missed) rotation, i.e. secondary > primary AND current_rotation > primary - if let Some(secondary_id) = secondary_id { - if secondary_id > primary_id && current_rotation_id > primary_id { - Self::swap_key_files(primary_key_path.as_ref(), secondary_key_path.as_ref())?; - // SAFETY: we just checked secondary exists - #[allow(clippy::unwrap_used)] - let tmp = secondary.take().unwrap(); - secondary = Some(primary); - primary = tmp; - } + if let Some(secondary_id) = secondary_id + && secondary_id > primary_id + && current_rotation_id > primary_id + { + Self::swap_key_files(primary_key_path.as_ref(), secondary_key_path.as_ref())?; + // SAFETY: we just checked secondary exists + #[allow(clippy::unwrap_used)] + let tmp = secondary.take().unwrap(); + secondary = Some(primary); + primary = tmp; } // if upon loading it turns out that the node has been inactive for a long time, // immediately rotate keys (but leave 1h grace period for current primary, i.e. set it as secondary) if primary.rotation_id() != current_rotation_id { - warn!("this node has been inactive for more than a key rotation duration. the current primary key was generated for rotation {} while the current rotation is {current_rotation_id}. new key will be generated now.", primary.rotation_id()); + warn!( + "this node has been inactive for more than a key rotation duration. the current primary key was generated for rotation {} while the current rotation is {current_rotation_id}. new key will be generated now.", + primary.rotation_id() + ); let this = SphinxKeyManager { keys: ActiveSphinxKeys::new_loaded(primary, None), primary_key_path: primary_key_path.as_ref().to_path_buf(), diff --git a/nym-node/src/node/metrics/aggregator.rs b/nym-node/src/node/metrics/aggregator.rs index 3be11cedcf..e8d7dfa885 100644 --- a/nym-node/src/node/metrics/aggregator.rs +++ b/nym-node/src/node/metrics/aggregator.rs @@ -4,7 +4,7 @@ use crate::node::metrics::handler::{HandlerWrapper, MetricsHandler, RegistrableHandler}; use futures::StreamExt; use nym_node_metrics::events::{ - events_channels, MetricEventsReceiver, MetricEventsSender, MetricsEvent, + MetricEventsReceiver, MetricEventsSender, MetricsEvent, events_channels, }; use nym_task::ShutdownToken; use std::any; @@ -12,7 +12,7 @@ use std::any::TypeId; use std::collections::HashMap; use std::ops::DerefMut; use std::time::Duration; -use tokio::time::{interval_at, Instant}; +use tokio::time::{Instant, interval_at}; use tracing::{debug, error, trace, warn}; pub(crate) struct MetricsAggregator { diff --git a/nym-node/src/node/metrics/console_logger.rs b/nym-node/src/node/metrics/console_logger.rs index 35b25ff153..49058beb28 100644 --- a/nym-node/src/node/metrics/console_logger.rs +++ b/nym-node/src/node/metrics/console_logger.rs @@ -7,7 +7,7 @@ use human_repr::HumanThroughput; use nym_node_metrics::NymNodeMetrics; use std::time::Duration; use time::OffsetDateTime; -use tokio::time::{interval_at, Instant}; +use tokio::time::{Instant, interval_at}; use tokio_stream::wrappers::IntervalStream; use tracing::{error, info, trace}; @@ -84,7 +84,8 @@ impl ConsoleLogger { let wg_tx_rate = (wg_tx - self.at_last_update.wg_tx) as f64 / delta_secs; let wg_rx_rate = (wg_rx - self.at_last_update.wg_rx) as f64 / delta_secs; - info!("↑↓ Packets sent [total] / sent [acks] / received [mix] / received [gw]: {} ({}) / {} ({}) / {} ({}) / {} ({})", + info!( + "↑↓ Packets sent [total] / sent [acks] / received [mix] / received [gw]: {} ({}) / {} ({}) / {} ({}) / {} ({})", forward_sent.human_count_bare(), forward_sent_rate.human_throughput_bare(), acks.human_count_bare(), diff --git a/nym-node/src/node/metrics/handler/client_sessions.rs b/nym-node/src/node/metrics/handler/client_sessions.rs index 19530440b3..cf4f056820 100644 --- a/nym-node/src/node/metrics/handler/client_sessions.rs +++ b/nym-node/src/node/metrics/handler/client_sessions.rs @@ -7,11 +7,11 @@ use crate::node::metrics::handler::{ use async_trait::async_trait; use nym_gateway::node::PersistentStatsStorage; use nym_gateway_stats_storage::error::StatsStorageError; +use nym_node_metrics::NymNodeMetrics; use nym_node_metrics::entry::{ActiveSession, ClientSessions, FinishedSession}; use nym_node_metrics::events::GatewaySessionEvent; -use nym_node_metrics::prometheus_wrapper::PrometheusMetric::EntryClientSessionsDurations; use nym_node_metrics::prometheus_wrapper::PROMETHEUS_METRICS; -use nym_node_metrics::NymNodeMetrics; +use nym_node_metrics::prometheus_wrapper::PrometheusMetric::EntryClientSessionsDurations; use nym_sphinx_types::DestinationAddressBytes; use nym_statistics_common::types::SessionType; use time::{Date, Duration, OffsetDateTime}; @@ -51,21 +51,21 @@ impl GatewaySessionStatsHandler { client: DestinationAddressBytes, ) -> Result<(), StatsStorageError> { if let Some(session) = self.storage.get_active_session(client).await? { - if session.remember { - if let Some(finished_session) = session.end_at(stop_time) { - PROMETHEUS_METRICS.observe_histogram( - EntryClientSessionsDurations { - typ: finished_session.typ.to_string(), - }, - finished_session.duration.as_secs_f64(), - ); - self.storage - .insert_unique_user(self.current_day, client.as_base58_string()) - .await?; - self.storage - .insert_finished_session(self.current_day, finished_session) - .await?; - } + if session.remember + && let Some(finished_session) = session.end_at(stop_time) + { + PROMETHEUS_METRICS.observe_histogram( + EntryClientSessionsDurations { + typ: finished_session.typ.to_string(), + }, + finished_session.duration.as_secs_f64(), + ); + self.storage + .insert_unique_user(self.current_day, client.as_base58_string()) + .await?; + self.storage + .insert_finished_session(self.current_day, finished_session) + .await?; } self.storage.delete_active_session(client).await?; } diff --git a/nym-node/src/node/metrics/handler/global_prometheus_updater/at_last_update.rs b/nym-node/src/node/metrics/handler/global_prometheus_updater/at_last_update.rs index af16be7ecb..89c68ea34c 100644 --- a/nym-node/src/node/metrics/handler/global_prometheus_updater/at_last_update.rs +++ b/nym-node/src/node/metrics/handler/global_prometheus_updater/at_last_update.rs @@ -1,9 +1,9 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only +use nym_node_metrics::NymNodeMetrics; use nym_node_metrics::mixnet::{EgressMixingStats, IngressMixingStats, MixingStats}; use nym_node_metrics::wireguard::WireguardStats; -use nym_node_metrics::NymNodeMetrics; use time::OffsetDateTime; // used to calculate traffic rates diff --git a/nym-node/src/node/metrics/handler/global_prometheus_updater/mod.rs b/nym-node/src/node/metrics/handler/global_prometheus_updater/mod.rs index 620dea3187..4578f6bd60 100644 --- a/nym-node/src/node/metrics/handler/global_prometheus_updater/mod.rs +++ b/nym-node/src/node/metrics/handler/global_prometheus_updater/mod.rs @@ -6,10 +6,10 @@ use crate::node::metrics::handler::{ MetricsHandler, OnStartMetricsHandler, OnUpdateMetricsHandler, }; use async_trait::async_trait; -use nym_node_metrics::prometheus_wrapper::{ - NymNodePrometheusMetrics, PrometheusMetric, PROMETHEUS_METRICS, -}; use nym_node_metrics::NymNodeMetrics; +use nym_node_metrics::prometheus_wrapper::{ + NymNodePrometheusMetrics, PROMETHEUS_METRICS, PrometheusMetric, +}; mod at_last_update; @@ -233,6 +233,8 @@ impl MetricsHandler for PrometheusGlobalNodeMetricsRegistryUpdater { // SAFETY: `PrometheusNodeMetricsRegistryUpdater` doesn't have any associated events #[allow(clippy::panic)] async fn handle_event(&mut self, _event: Self::Events) { - panic!("this should have never been called! MetricsHandler has been incorrectly called on PrometheusNodeMetricsRegistryUpdater") + panic!( + "this should have never been called! MetricsHandler has been incorrectly called on PrometheusNodeMetricsRegistryUpdater" + ) } } diff --git a/nym-node/src/node/metrics/handler/legacy_packet_data.rs b/nym-node/src/node/metrics/handler/legacy_packet_data.rs index d45536e587..698cc8ce0a 100644 --- a/nym-node/src/node/metrics/handler/legacy_packet_data.rs +++ b/nym-node/src/node/metrics/handler/legacy_packet_data.rs @@ -65,6 +65,8 @@ impl MetricsHandler for LegacyMixingStatsUpdater { // SAFETY: `LegacyMixingStatsUpdater` doesn't have any associated events #[allow(clippy::panic)] async fn handle_event(&mut self, _event: Self::Events) { - panic!("this should have never been called! MetricsHandler has been incorrectly called on LegacyMixingStatsUpdater") + panic!( + "this should have never been called! MetricsHandler has been incorrectly called on LegacyMixingStatsUpdater" + ) } } diff --git a/nym-node/src/node/metrics/handler/mixnet_data_cleaner.rs b/nym-node/src/node/metrics/handler/mixnet_data_cleaner.rs index 0c4db73333..556059bb55 100644 --- a/nym-node/src/node/metrics/handler/mixnet_data_cleaner.rs +++ b/nym-node/src/node/metrics/handler/mixnet_data_cleaner.rs @@ -5,8 +5,8 @@ use crate::node::metrics::handler::{ MetricsHandler, OnStartMetricsHandler, OnUpdateMetricsHandler, }; use async_trait::async_trait; -use nym_node_metrics::mixnet::{EgressRecipientStats, IngressRecipientStats}; use nym_node_metrics::NymNodeMetrics; +use nym_node_metrics::mixnet::{EgressRecipientStats, IngressRecipientStats}; use std::collections::HashMap; use std::net::{IpAddr, SocketAddr}; @@ -43,10 +43,10 @@ impl OnUpdateMetricsHandler for MixnetMetricsCleaner { let mut recipients_to_remove = Vec::new(); for sender_entry in self.metrics.mixnet.ingress.senders().iter() { - if let Some(last_seen) = self.last_seen.ingress_senders.get(sender_entry.key()) { - if sender_entry.value() == last_seen { - senders_to_remove.push(*sender_entry.key()); - } + if let Some(last_seen) = self.last_seen.ingress_senders.get(sender_entry.key()) + && sender_entry.value() == last_seen + { + senders_to_remove.push(*sender_entry.key()); } } @@ -55,10 +55,9 @@ impl OnUpdateMetricsHandler for MixnetMetricsCleaner { .last_seen .egress_forward_recipients .get(recipient_entry.key()) + && recipient_entry.value() == last_seen { - if recipient_entry.value() == last_seen { - recipients_to_remove.push(*recipient_entry.key()); - } + recipients_to_remove.push(*recipient_entry.key()); } } @@ -104,6 +103,8 @@ impl MetricsHandler for MixnetMetricsCleaner { // SAFETY: `MixnetMetricsCleaner` doesn't have any associated events #[allow(clippy::panic)] async fn handle_event(&mut self, _event: Self::Events) { - panic!("this should have never been called! MetricsHandler has been incorrectly called on MixnetMetricsCleaner") + panic!( + "this should have never been called! MetricsHandler has been incorrectly called on MixnetMetricsCleaner" + ) } } diff --git a/nym-node/src/node/metrics/handler/pending_egress_packets_updater.rs b/nym-node/src/node/metrics/handler/pending_egress_packets_updater.rs index f3a134cc37..3a9ec690e7 100644 --- a/nym-node/src/node/metrics/handler/pending_egress_packets_updater.rs +++ b/nym-node/src/node/metrics/handler/pending_egress_packets_updater.rs @@ -57,6 +57,8 @@ impl MetricsHandler for PendingEgressPacketsUpdater { // SAFETY: `PendingEgressPacketsUpdater` doesn't have any associated events #[allow(clippy::panic)] async fn handle_event(&mut self, _event: Self::Events) { - panic!("this should have never been called! MetricsHandler has been incorrectly called on PendingEgressPacketsUpdater") + panic!( + "this should have never been called! MetricsHandler has been incorrectly called on PendingEgressPacketsUpdater" + ) } } diff --git a/nym-node/src/node/mixnet/handler.rs b/nym-node/src/node/mixnet/handler.rs index 6a14277c1d..a2a50aa4f2 100644 --- a/nym-node/src/node/mixnet/handler.rs +++ b/nym-node/src/node/mixnet/handler.rs @@ -9,8 +9,8 @@ use nym_sphinx_forwarding::packet::MixPacket; use nym_sphinx_framing::codec::NymCodec; use nym_sphinx_framing::packet::FramedNymPacket; use nym_sphinx_framing::processing::{ - process_framed_packet, MixProcessingResult, MixProcessingResultData, PacketProcessingError, - PartiallyUnwrappedPacket, PartialyUnwrappedPacketWithKeyRotation, ProcessedFinalHop, + MixProcessingResult, MixProcessingResultData, PacketProcessingError, PartiallyUnwrappedPacket, + PartialyUnwrappedPacketWithKeyRotation, ProcessedFinalHop, process_framed_packet, }; use nym_sphinx_params::SphinxKeyRotation; use nym_sphinx_types::{Delay, REPLAY_TAG_SIZE}; diff --git a/nym-node/src/node/mixnet/listener.rs b/nym-node/src/node/mixnet/listener.rs index 7fdca155a7..f769176639 100644 --- a/nym-node/src/node/mixnet/listener.rs +++ b/nym-node/src/node/mixnet/listener.rs @@ -25,7 +25,10 @@ impl Listener { let tcp_listener = match tokio::net::TcpListener::bind(self.bind_address).await { Ok(listener) => listener, Err(err) => { - error!("Failed to bind to {}: {err}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.bind_address); + error!( + "Failed to bind to {}: {err}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", + self.bind_address + ); shutdown.cancel(); return; } diff --git a/nym-node/src/node/mixnet/mod.rs b/nym-node/src/node/mixnet/mod.rs index b4f9f7e4f6..7dcb7c855a 100644 --- a/nym-node/src/node/mixnet/mod.rs +++ b/nym-node/src/node/mixnet/mod.rs @@ -7,4 +7,4 @@ pub(crate) mod packet_forwarding; pub(crate) mod shared; pub(crate) use listener::Listener; -pub(crate) use shared::{final_hop::SharedFinalHopData, SharedData}; +pub(crate) use shared::{SharedData, final_hop::SharedFinalHopData}; diff --git a/nym-node/src/node/mixnet/packet_forwarding/mod.rs b/nym-node/src/node/mixnet/packet_forwarding/mod.rs index d76e4cea55..09055daacd 100644 --- a/nym-node/src/node/mixnet/packet_forwarding/mod.rs +++ b/nym-node/src/node/mixnet/packet_forwarding/mod.rs @@ -3,10 +3,10 @@ use crate::node::routing_filter::RoutingFilter; use futures::StreamExt; -use nym_mixnet_client::forwarder::{ - mix_forwarding_channels, MixForwardingReceiver, MixForwardingSender, PacketToForward, -}; use nym_mixnet_client::SendWithoutResponse; +use nym_mixnet_client::forwarder::{ + MixForwardingReceiver, MixForwardingSender, PacketToForward, mix_forwarding_channels, +}; use nym_node_metrics::NymNodeMetrics; use nym_nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue}; use nym_sphinx_forwarding::packet::MixPacket; diff --git a/nym-node/src/node/mixnet/shared/mod.rs b/nym-node/src/node/mixnet/shared/mod.rs index 67dea46a7a..ac8dd9ecc7 100644 --- a/nym-node/src/node/mixnet/shared/mod.rs +++ b/nym-node/src/node/mixnet/shared/mod.rs @@ -3,13 +3,13 @@ use crate::config::Config; use crate::node::key_rotation::active_keys::ActiveSphinxKeys; -use crate::node::mixnet::handler::ConnectionHandler; use crate::node::mixnet::SharedFinalHopData; +use crate::node::mixnet::handler::ConnectionHandler; use crate::node::replay_protection::bloomfilter::ReplayProtectionBloomfilters; use nym_gateway::node::GatewayStorageError; use nym_mixnet_client::forwarder::{MixForwardingSender, PacketToForward}; -use nym_node_metrics::mixnet::PacketKind; use nym_node_metrics::NymNodeMetrics; +use nym_node_metrics::mixnet::PacketKind; use nym_noise::config::NoiseConfig; use nym_sphinx_forwarding::packet::MixPacket; use nym_sphinx_framing::processing::{ @@ -150,10 +150,10 @@ impl SharedData { .ingress_received_forward_packet(source, packet_version); // check if the delay wasn't excessive - if let Some(delay) = delay { - if delay.to_duration() > self.processing_config.maximum_packet_delay { - self.metrics.mixnet.ingress_excessive_delay_packet() - } + if let Some(delay) = delay + && delay.to_duration() > self.processing_config.maximum_packet_delay + { + self.metrics.mixnet.ingress_excessive_delay_packet() } } MixProcessingResultData::FinalHop { .. } => { @@ -191,7 +191,9 @@ impl SharedData { .is_err() && !self.shutdown_token.is_cancelled() { - error!("failed to forward sphinx packet on the channel while the process is not going through the shutdown!"); + error!( + "failed to forward sphinx packet on the channel while the process is not going through the shutdown!" + ); self.shutdown_token.cancel(); } } diff --git a/nym-node/src/node/mod.rs b/nym-node/src/node/mod.rs index eac6e56c6e..44d35b5d41 100644 --- a/nym-node/src/node/mod.rs +++ b/nym-node/src/node/mod.rs @@ -4,14 +4,14 @@ use self::helpers::load_x25519_wireguard_keypair; use crate::config::helpers::gateway_tasks_config; use crate::config::{ - Config, GatewayTasksConfig, NodeModes, ServiceProvidersConfig, Wireguard, DEFAULT_MIXNET_PORT, + Config, DEFAULT_MIXNET_PORT, GatewayTasksConfig, NodeModes, ServiceProvidersConfig, Wireguard, }; use crate::error::{EntryGatewayError, NymNodeError, ServiceProvidersError}; use crate::node::description::{load_node_description, save_node_description}; use crate::node::helpers::{ - get_current_rotation_id, load_ed25519_identity_keypair, load_key, load_x25519_noise_keypair, - store_ed25519_identity_keypair, store_key, store_keypair, store_x25519_noise_keypair, - DisplayDetails, + DisplayDetails, get_current_rotation_id, load_ed25519_identity_keypair, load_key, + load_x25519_noise_keypair, store_ed25519_identity_keypair, store_key, store_keypair, + store_x25519_noise_keypair, }; use crate::node::http::api::api_requests; use crate::node::http::helpers::system_info::get_system_info; @@ -27,9 +27,9 @@ use crate::node::metrics::handler::global_prometheus_updater::PrometheusGlobalNo use crate::node::metrics::handler::legacy_packet_data::LegacyMixingStatsUpdater; use crate::node::metrics::handler::mixnet_data_cleaner::MixnetMetricsCleaner; use crate::node::metrics::handler::pending_egress_packets_updater::PendingEgressPacketsUpdater; +use crate::node::mixnet::SharedFinalHopData; use crate::node::mixnet::packet_forwarding::PacketForwarder; use crate::node::mixnet::shared::ProcessingConfig; -use crate::node::mixnet::SharedFinalHopData; use crate::node::nym_apis_client::NymApisClient; use crate::node::replay_protection::background_task::ReplayProtectionDiskFlush; use crate::node::replay_protection::bloomfilter::ReplayProtectionBloomfilters; @@ -44,11 +44,11 @@ use nym_gateway::node::{ActiveClientsStore, GatewayTasksBuilder}; use nym_mixnet_client::client::ActiveConnections; use nym_mixnet_client::forwarder::MixForwardingSender; use nym_network_requester::{ - set_active_gateway, setup_fs_gateways_storage, store_gateway_details, CustomGatewayDetails, - GatewayDetails, GatewayRegistration, + CustomGatewayDetails, GatewayDetails, GatewayRegistration, set_active_gateway, + setup_fs_gateways_storage, store_gateway_details, }; -use nym_node_metrics::events::MetricEventsSender; use nym_node_metrics::NymNodeMetrics; +use nym_node_metrics::events::MetricEventsSender; use nym_node_requests::api::v1::node::models::{AnnouncePorts, NodeDescription}; use nym_noise::config::{NoiseConfig, NoiseNetworkView}; use nym_noise_keys::VersionedNoiseKey; @@ -58,7 +58,7 @@ use nym_task::{ShutdownManager, ShutdownToken, ShutdownTracker}; use nym_validator_client::UserAgent; use nym_verloc::measurements::SharedVerlocStats; use nym_verloc::{self, measurements::VerlocMeasurer}; -use nym_wireguard::{peer_controller::PeerControlRequest, WireguardGatewayData}; +use nym_wireguard::{WireguardGatewayData, peer_controller::PeerControlRequest}; use rand::rngs::OsRng; use rand::{CryptoRng, RngCore}; use std::net::SocketAddr; @@ -660,13 +660,17 @@ impl NymNode { info!("started NR at: {}", started_nr.on_start_data.address); info!("started IPR at: {}", started_ipr.on_start_data.address); } else { - info!("node not running in exit mode: the exit service providers (NR + IPR) will remain unavailable"); + info!( + "node not running in exit mode: the exit service providers (NR + IPR) will remain unavailable" + ); } // if we're running wireguard, start the authenticator // and the actual wireguard listener if self.config.wireguard.enabled { - info!("starting the wireguard tasks: authenticator service provider + wireguard peer controller"); + info!( + "starting the wireguard tasks: authenticator service provider + wireguard peer controller" + ); gateway_tasks_builder.set_authenticator_opts(config.auth_opts); @@ -693,7 +697,9 @@ impl NymNode { .await .map_err(NymNodeError::GatewayTasksStartupFailure)?; } else { - info!("node not running with wireguard: authenticator service provider and wireguard will remain unavailable"); + info!( + "node not running with wireguard: authenticator service provider and wireguard will remain unavailable" + ); } // start task for removing stale and un-retrieved client messages @@ -1147,7 +1153,8 @@ impl NymNode { } async fn start_nym_node_tasks(mut self) -> Result { - info!("starting Nym Node {} with the following modes: mixnode: {}, entry: {}, exit: {}, wireguard: {}", + info!( + "starting Nym Node {} with the following modes: mixnode: {}, entry: {}, exit: {}, wireguard: {}", self.ed25519_identity_key(), self.config.modes.mixnode, self.config.modes.entry, diff --git a/nym-node/src/node/nym_apis_client.rs b/nym-node/src/node/nym_apis_client.rs index 869270f163..f9d97a93d9 100644 --- a/nym-node/src/node/nym_apis_client.rs +++ b/nym-node/src/node/nym_apis_client.rs @@ -3,7 +3,7 @@ use crate::error::NymNodeError; use crate::node::NymNode; -use futures::{stream, StreamExt}; +use futures::{StreamExt, stream}; use nym_crypto::asymmetric::ed25519; use nym_http_api_client::Client; use nym_task::ShutdownToken; diff --git a/nym-node/src/node/replay_protection/background_task.rs b/nym-node/src/node/replay_protection/background_task.rs index 68092e0208..4d50e2f1fd 100644 --- a/nym-node/src/node/replay_protection/background_task.rs +++ b/nym-node/src/node/replay_protection/background_task.rs @@ -1,10 +1,10 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only +use crate::config::Config; use crate::config::persistence::{ DEFAULT_RD_BLOOMFILTER_FILE_EXT, DEFAULT_RD_BLOOMFILTER_FLUSH_FILE_EXT, }; -use crate::config::Config; use crate::error::NymNodeError; use crate::node::replay_protection::bloomfilter::RotationFilter; use crate::node::replay_protection::helpers::parse_rotation_id_from_filename; @@ -19,7 +19,7 @@ use std::path::PathBuf; use std::time::Duration; use tokio::fs::File; use tokio::io::AsyncWriteExt; -use tokio::time::{interval, Instant}; +use tokio::time::{Instant, interval}; use tracing::{debug, error, info, trace, warn}; // background task responsible for periodically flushing the bloomfilters to disk @@ -73,15 +73,15 @@ impl ReplayProtectionDiskFlush { }; // if any bloomfilter has the temp extension, we can't trust its data as it hasn't completed the flush - if let Some(ext) = entry.path().extension() { - if ext == DEFAULT_RD_BLOOMFILTER_FLUSH_FILE_EXT { - error!( - "bloomfilter {rotation} didn't get successfully flushed to disk and its data got corrupted" - ); - fs::remove_file(&path) - .map_err(|source| NymNodeError::BloomfilterIoFailure { source, path })?; - continue; - } + if let Some(ext) = entry.path().extension() + && ext == DEFAULT_RD_BLOOMFILTER_FLUSH_FILE_EXT + { + error!( + "bloomfilter {rotation} didn't get successfully flushed to disk and its data got corrupted" + ); + fs::remove_file(&path) + .map_err(|source| NymNodeError::BloomfilterIoFailure { source, path })?; + continue; } filter_files.insert(rotation, path); @@ -245,7 +245,9 @@ impl ReplayProtectionDiskFlush { } } - info!("SHUTDOWN: flushing replay detection bloomfilter to disk. this might take a while. DO NOT INTERRUPT THIS PROCESS"); + info!( + "SHUTDOWN: flushing replay detection bloomfilter to disk. this might take a while. DO NOT INTERRUPT THIS PROCESS" + ); if let Err(err) = self.flush_filters_to_disk().await { warn!("failed to flush replay detection bloom filters on shutdown: {err}"); } diff --git a/nym-node/src/node/replay_protection/bloomfilter.rs b/nym-node/src/node/replay_protection/bloomfilter.rs index 7ae35875cb..5fe7ec9f3e 100644 --- a/nym-node/src/node/replay_protection/bloomfilter.rs +++ b/nym-node/src/node/replay_protection/bloomfilter.rs @@ -92,7 +92,9 @@ impl ReplayProtectionBloomfilters { } else if Some(secondary_id) == previous { (Some(secondary_filter), None) } else { - warn!("{secondary_id} is not valid for either pre_announced or overlap bloomfilter given primary rotation of {primary_id}"); + warn!( + "{secondary_id} is not valid for either pre_announced or overlap bloomfilter given primary rotation of {primary_id}" + ); (None, None) } } diff --git a/nym-node/src/node/shared_network.rs b/nym-node/src/node/shared_network.rs index b87475254e..da0ad97372 100644 --- a/nym-node/src/node/shared_network.rs +++ b/nym-node/src/node/shared_network.rs @@ -8,7 +8,7 @@ use async_trait::async_trait; use nym_crypto::asymmetric::ed25519; use nym_gateway::node::UserAgent; use nym_http_api_client::Client; -use nym_node_metrics::prometheus_wrapper::{PrometheusMetric, PROMETHEUS_METRICS}; +use nym_node_metrics::prometheus_wrapper::{PROMETHEUS_METRICS, PrometheusMetric}; use nym_noise::config::NoiseNetworkView; use nym_task::ShutdownToken; use nym_topology::node::RoutingNode; @@ -17,11 +17,11 @@ use nym_topology::{ EntryDetails, EpochRewardedSet, NodeId, NymTopology, NymTopologyMetadata, Role, TopologyProvider, }; +use nym_validator_client::ValidatorClientError; use nym_validator_client::nym_api::NymApiClientExt; use nym_validator_client::nym_nodes::{ NodesByAddressesResponse, SemiSkimmedNode, SemiSkimmedNodesWithMetadata, }; -use nym_validator_client::ValidatorClientError; use std::collections::{HashMap, HashSet}; use std::net::{IpAddr, SocketAddr}; use std::ops::Deref; @@ -44,7 +44,9 @@ struct NodesQuerier { impl NodesQuerier { fn use_next_nym_api(&mut self) { if self.nym_api_urls.len() == 1 { - warn!("There's only a single nym API available - it won't be possible to use a different one"); + warn!( + "There's only a single nym API available - it won't be possible to use a different one" + ); return; } diff --git a/nym-node/src/throughput_tester/client.rs b/nym-node/src/throughput_tester/client.rs index 32a0cf78f5..ed3657be00 100644 --- a/nym-node/src/throughput_tester/client.rs +++ b/nym-node/src/throughput_tester/client.rs @@ -7,7 +7,7 @@ use anyhow::bail; use arrayref::array_ref; use blake2::VarBlake2b; use chacha::ChaCha; -use futures::{stream, SinkExt, Stream, StreamExt}; +use futures::{SinkExt, Stream, StreamExt, stream}; use hkdf::Hkdf; use human_repr::{HumanCount, HumanDuration, HumanThroughput}; use lioness::Lioness; @@ -22,8 +22,8 @@ use nym_sphinx_types::constants::{ EXPANDED_SHARED_SECRET_LENGTH, }; use nym_sphinx_types::{ - Destination, DestinationAddressBytes, Node, NymPacket, PayloadKey, DESTINATION_ADDRESS_LENGTH, - IDENTIFIER_LENGTH, + DESTINATION_ADDRESS_LENGTH, Destination, DestinationAddressBytes, IDENTIFIER_LENGTH, Node, + NymPacket, PayloadKey, }; use nym_task::ShutdownToken; use rand::rngs::OsRng; @@ -36,9 +36,9 @@ use std::time::Duration; use time::OffsetDateTime; use tokio::net::{TcpListener, TcpStream}; use tokio::select; -use tokio::time::{interval, sleep, Instant}; +use tokio::time::{Instant, interval, sleep}; use tokio_util::codec::Framed; -use tracing::{debug, error, info, Span}; +use tracing::{Span, debug, error, info}; use tracing_indicatif::span_ext::IndicatifSpanExt; struct PacketTag { @@ -325,9 +325,13 @@ impl ThroughputTestingClient { let diff = 1. - saturation; if saturation > 1. { - debug!("saturation {saturation:.2}, packet latency over threshold: need to decrease sending rate"); + debug!( + "saturation {saturation:.2}, packet latency over threshold: need to decrease sending rate" + ); } else { - debug!("saturation {saturation:.2}, packet latency under threshold: can increase sending rate"); + debug!( + "saturation {saturation:.2}, packet latency under threshold: can increase sending rate" + ); } // be conservative and only apply 50% of the diff diff --git a/nym-node/src/throughput_tester/global_stats.rs b/nym-node/src/throughput_tester/global_stats.rs index e095c702c5..f31d76bb1f 100644 --- a/nym-node/src/throughput_tester/global_stats.rs +++ b/nym-node/src/throughput_tester/global_stats.rs @@ -13,8 +13,8 @@ use std::time::Duration; use sysinfo::System; use time::OffsetDateTime; use tokio::select; -use tokio::time::{interval, Instant}; -use tracing::{error, info, Span}; +use tokio::time::{Instant, interval}; +use tracing::{Span, error, info}; use tracing_indicatif::span_ext::IndicatifSpanExt; #[derive(Default, Serialize, Deserialize)] diff --git a/nym-node/src/throughput_tester/mod.rs b/nym-node/src/throughput_tester/mod.rs index 81b8f38c4d..ab5624d2fa 100644 --- a/nym-node/src/throughput_tester/mod.rs +++ b/nym-node/src/throughput_tester/mod.rs @@ -2,15 +2,15 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::config::upgrade_helpers::try_load_current_config; -use crate::node::key_rotation::active_keys::ActiveSphinxKeys; use crate::node::NymNode; +use crate::node::key_rotation::active_keys::ActiveSphinxKeys; use crate::throughput_tester::client::ThroughputTestingClient; use crate::throughput_tester::global_stats::GlobalStatsUpdater; use crate::throughput_tester::stats::ClientStats; use futures::future::join_all; use human_repr::HumanDuration; use nym_task::ShutdownToken; -use rand::{thread_rng, Rng}; +use rand::{Rng, thread_rng}; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::path::PathBuf; use std::time::Duration; diff --git a/nym-node/src/throughput_tester/stats.rs b/nym-node/src/throughput_tester/stats.rs index b28a8942e5..a3c893b07b 100644 --- a/nym-node/src/throughput_tester/stats.rs +++ b/nym-node/src/throughput_tester/stats.rs @@ -1,8 +1,8 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use std::time::Duration; #[derive(Clone, Default)] diff --git a/nym-outfox/src/format.rs b/nym-outfox/src/format.rs index 413352d630..e946c7a267 100644 --- a/nym-outfox/src/format.rs +++ b/nym-outfox/src/format.rs @@ -54,14 +54,14 @@ //! routing data for the layer, and the remaining Header; separately the master key is used to lion encrypt //! the payload. The process is repeated for each layer (from last to first) to construct the full message. -use crate::constants::groupelementbytes; -use crate::constants::tagbytes; use crate::constants::DEFAULT_HOPS; use crate::constants::DEFAULT_ROUTING_INFO_SIZE; use crate::constants::GROUPELEMENTBYTES; use crate::constants::MIX_PARAMS_LEN; use crate::constants::ROUTING_INFORMATION_LENGTH_BY_STAGE; use crate::constants::TAGBYTES; +use crate::constants::groupelementbytes; +use crate::constants::tagbytes; use crate::error::OutfoxError; use crate::lion::*; use chacha20poly1305::AeadInPlace; diff --git a/nym-outfox/src/lion.rs b/nym-outfox/src/lion.rs index 3e05c3613a..17b48b4630 100644 --- a/nym-outfox/src/lion.rs +++ b/nym-outfox/src/lion.rs @@ -30,10 +30,10 @@ //! a key schedule that is symmetric (such as [1, 2, 1]) to build a transform T(k,m) that has the //! property m = T(k, T(k, m)). -use chacha20::cipher::{KeyIvInit, StreamCipher}; use chacha20::Key; use chacha20::XChaCha20; use chacha20::XNonce; +use chacha20::cipher::{KeyIvInit, StreamCipher}; use zeroize::Zeroize; use crate::constants::{CONTEXT, MIN_MESSAGE_LEN, TAG_LEN}; diff --git a/nym-registration-client/src/builder/config.rs b/nym-registration-client/src/builder/config.rs index be26f9e692..494e3fb2a1 100644 --- a/nym-registration-client/src/builder/config.rs +++ b/nym-registration-client/src/builder/config.rs @@ -4,12 +4,11 @@ use nym_credential_storage::persistent_storage::PersistentStorage; use nym_registration_common::NymNode; use nym_sdk::{ - mixnet::{ - x25519::KeyPair, CredentialStorage, GatewaysDetailsStore, KeyStore, MixnetClient, - MixnetClientBuilder, MixnetClientStorage, OnDiskPersistent, ReplyStorageBackend, - StoragePaths, - }, DebugConfig, NymNetworkDetails, RememberMe, TopologyProvider, UserAgent, + mixnet::{ + CredentialStorage, GatewaysDetailsStore, KeyStore, MixnetClient, MixnetClientBuilder, + MixnetClientStorage, OnDiskPersistent, ReplyStorageBackend, StoragePaths, x25519::KeyPair, + }, }; #[cfg(unix)] @@ -205,9 +204,5 @@ fn log_mixnet_client_config(debug_config: &DebugConfig) { } fn true_to_disabled(val: bool) -> &'static str { - if val { - "disabled" - } else { - "enabled" - } + if val { "disabled" } else { "enabled" } } diff --git a/nym-registration-client/src/builder/mod.rs b/nym-registration-client/src/builder/mod.rs index 940d8f9f51..29278ea097 100644 --- a/nym-registration-client/src/builder/mod.rs +++ b/nym-registration-client/src/builder/mod.rs @@ -4,16 +4,16 @@ use nym_bandwidth_controller::{BandwidthController, BandwidthTicketProvider}; use nym_credential_storage::ephemeral_storage::EphemeralCredentialStorage; use nym_sdk::{ - mixnet::{MixnetClient, MixnetClientBuilder}, NymNetworkDetails, + mixnet::{MixnetClient, MixnetClientBuilder}, }; use nym_validator_client::{ - nyxd::{Config as NyxdClientConfig, NyxdClient}, QueryHttpRpcNyxdClient, + nyxd::{Config as NyxdClientConfig, NyxdClient}, }; use std::time::Duration; -use crate::{config::RegistrationClientConfig, error::RegistrationClientError, RegistrationClient}; +use crate::{RegistrationClient, config::RegistrationClientConfig, error::RegistrationClientError}; use config::BuilderConfig; pub(crate) mod config; diff --git a/nym-registration-client/src/lib.rs b/nym-registration-client/src/lib.rs index 49a99491a2..c9794fa9a0 100644 --- a/nym-registration-client/src/lib.rs +++ b/nym-registration-client/src/lib.rs @@ -17,11 +17,11 @@ mod config; mod error; mod types; +pub use builder::RegistrationClientBuilder; pub use builder::config::{ BuilderConfig as RegistrationClientBuilderConfig, MixnetClientConfig, NymNodeWithKeys as RegistrationNymNode, }; -pub use builder::RegistrationClientBuilder; pub use error::RegistrationClientError; pub use types::{MixnetRegistrationResult, RegistrationResult, WireguardRegistrationResult}; diff --git a/nym-signers-monitor/src/cli/run.rs b/nym-signers-monitor/src/cli/run.rs index b0b0855b49..c430e4bd8f 100644 --- a/nym-signers-monitor/src/cli/run.rs +++ b/nym-signers-monitor/src/cli/run.rs @@ -3,11 +3,11 @@ use crate::cli::env::vars::*; use crate::monitor::SignersMonitor; -use anyhow::{bail, Context}; +use anyhow::{Context, bail}; use clap::ArgGroup; -use nym_network_defaults::{setup_env, NymNetworkDetails}; -use nym_validator_client::nyxd::AccountId; +use nym_network_defaults::{NymNetworkDetails, setup_env}; use nym_validator_client::QueryHttpRpcNyxdClient; +use nym_validator_client::nyxd::AccountId; use std::time::Duration; use url::Url; @@ -50,7 +50,9 @@ impl NyxdConnectionArgs { if let Some(known_network_name) = &self.known_network_name { match known_network_name.as_str() { "mainnet" => return Ok(NymNetworkDetails::new_mainnet()), - other => bail!("{other} is not a known network name - please use another method of setting up chain connection"), + other => bail!( + "{other} is not a known network name - please use another method of setting up chain connection" + ), } } diff --git a/nym-statistics-api/src/http/api/mod.rs b/nym-statistics-api/src/http/api/mod.rs index 16e9763bd0..dd03791238 100644 --- a/nym-statistics-api/src/http/api/mod.rs +++ b/nym-statistics-api/src/http/api/mod.rs @@ -1,5 +1,5 @@ use anyhow::anyhow; -use axum::{response::Redirect, Router}; +use axum::{Router, response::Redirect}; use nym_http_api_common::middleware::logging::log_request_info; use tokio::net::ToSocketAddrs; use tower_http::cors::CorsLayer; diff --git a/nym-statistics-api/src/http/api/stats.rs b/nym-statistics-api/src/http/api/stats.rs index 3d079e0a30..ab6b69926d 100644 --- a/nym-statistics-api/src/http/api/stats.rs +++ b/nym-statistics-api/src/http/api/stats.rs @@ -1,6 +1,6 @@ -use axum::{extract::State, Json, Router}; +use axum::{Json, Router, extract::State}; use axum_client_ip::InsecureClientIp; -use axum_extra::{headers::UserAgent, TypedHeader}; +use axum_extra::{TypedHeader, headers::UserAgent}; use nym_statistics_common::report::vpn_client::VpnClientStatsReport; use tracing::debug; diff --git a/nym-statistics-api/src/logging.rs b/nym-statistics-api/src/logging.rs index 39c2810226..93791f80fd 100644 --- a/nym-statistics-api/src/logging.rs +++ b/nym-statistics-api/src/logging.rs @@ -1,5 +1,5 @@ use tracing::level_filters::LevelFilter; -use tracing_subscriber::{filter::Directive, EnvFilter}; +use tracing_subscriber::{EnvFilter, filter::Directive}; pub(crate) fn setup_tracing_logger() -> anyhow::Result<()> { fn directive_checked(directive: impl Into) -> anyhow::Result { diff --git a/nym-statistics-api/src/storage/mod.rs b/nym-statistics-api/src/storage/mod.rs index 82b0624f51..f6547da55c 100644 --- a/nym-statistics-api/src/storage/mod.rs +++ b/nym-statistics-api/src/storage/mod.rs @@ -1,9 +1,9 @@ -use anyhow::{anyhow, Result}; +use anyhow::{Result, anyhow}; use models::{ConnectionInfoDto, DailyActiveDeviceDto}; use sqlx::{ + Executor, migrate::Migrator, postgres::{PgConnectOptions, PgPoolOptions}, - Executor, }; use std::{path::PathBuf, str::FromStr}; diff --git a/nym-validator-rewarder/src/cli/dry_run_check_issuer.rs b/nym-validator-rewarder/src/cli/dry_run_check_issuer.rs index f8974bd601..2a147a4b40 100644 --- a/nym-validator-rewarder/src/cli/dry_run_check_issuer.rs +++ b/nym-validator-rewarder/src/cli/dry_run_check_issuer.rs @@ -1,19 +1,19 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::cli::{try_load_current_config, ConfigOverridableArgs}; +use crate::cli::{ConfigOverridableArgs, try_load_current_config}; +use crate::rewarder::Rewarder; use crate::rewarder::nyxd_client::NyxdClient; use crate::rewarder::storage::RewarderStorage; use crate::rewarder::ticketbook_issuance::types::CredentialIssuer; use crate::rewarder::ticketbook_issuance::verifier::TicketbookIssuanceVerifier; -use crate::rewarder::Rewarder; use anyhow::bail; use nym_ecash_time::ecash_default_expiration_date; use nym_validator_client::nym_api::NymApiClientExt; use std::collections::HashSet; use std::path::PathBuf; -use time::macros::format_description; use time::Date; +use time::macros::format_description; use tracing::info; fn parse_date(raw: &str) -> Result { diff --git a/nym-validator-rewarder/src/cli/init.rs b/nym-validator-rewarder/src/cli/init.rs index 991ecb3be6..eeecb39953 100644 --- a/nym-validator-rewarder/src/cli/init.rs +++ b/nym-validator-rewarder/src/cli/init.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::cli::ConfigOverridableArgs; -use crate::config::{default_config_directory, default_data_directory, Config}; +use crate::config::{Config, default_config_directory, default_data_directory}; use crate::error::NymRewarderError; use nym_crypto::asymmetric::ed25519; use nym_network_defaults::NymNetworkDetails; diff --git a/nym-validator-rewarder/src/cli/process_block.rs b/nym-validator-rewarder/src/cli/process_block.rs index c4f3563566..0174f1165c 100644 --- a/nym-validator-rewarder/src/cli/process_block.rs +++ b/nym-validator-rewarder/src/cli/process_block.rs @@ -1,7 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::cli::{try_load_current_config, ConfigOverridableArgs}; +use crate::cli::{ConfigOverridableArgs, try_load_current_config}; use crate::error::NymRewarderError; use nyxd_scraper::NyxdScraper; use std::path::PathBuf; diff --git a/nym-validator-rewarder/src/cli/process_until.rs b/nym-validator-rewarder/src/cli/process_until.rs index 04a5809caf..159f954e57 100644 --- a/nym-validator-rewarder/src/cli/process_until.rs +++ b/nym-validator-rewarder/src/cli/process_until.rs @@ -1,7 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::cli::{try_load_current_config, ConfigOverridableArgs}; +use crate::cli::{ConfigOverridableArgs, try_load_current_config}; use crate::error::NymRewarderError; use nyxd_scraper::NyxdScraper; use std::path::PathBuf; @@ -27,11 +27,11 @@ pub struct Args { } pub(crate) async fn execute(args: Args) -> Result<(), NymRewarderError> { - if let (Some(start), Some(end)) = (args.start_height, args.stop_height) { - if start > end { - eprintln!("the start height can't be larger than the stop height!"); - return Ok(()); - } + if let (Some(start), Some(end)) = (args.start_height, args.stop_height) + && start > end + { + eprintln!("the start height can't be larger than the stop height!"); + return Ok(()); } let config = diff --git a/nym-validator-rewarder/src/cli/regenerate_identity.rs b/nym-validator-rewarder/src/cli/regenerate_identity.rs index f0e0dcb4ee..19f1eb5f30 100644 --- a/nym-validator-rewarder/src/cli/regenerate_identity.rs +++ b/nym-validator-rewarder/src/cli/regenerate_identity.rs @@ -1,7 +1,7 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::cli::{try_load_current_config, ConfigOverridableArgs}; +use crate::cli::{ConfigOverridableArgs, try_load_current_config}; use crate::error::NymRewarderError; use nym_crypto::asymmetric::ed25519; use rand::rngs::OsRng; diff --git a/nym-validator-rewarder/src/cli/run.rs b/nym-validator-rewarder/src/cli/run.rs index a12ac965d8..675606667c 100644 --- a/nym-validator-rewarder/src/cli/run.rs +++ b/nym-validator-rewarder/src/cli/run.rs @@ -1,7 +1,7 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::cli::{try_load_current_config, ConfigOverridableArgs}; +use crate::cli::{ConfigOverridableArgs, try_load_current_config}; use crate::error::NymRewarderError; use crate::rewarder::Rewarder; use std::path::PathBuf; diff --git a/nym-validator-rewarder/src/config/mod.rs b/nym-validator-rewarder/src/config/mod.rs index e7681fdb64..618d4ef27a 100644 --- a/nym-validator-rewarder/src/config/mod.rs +++ b/nym-validator-rewarder/src/config/mod.rs @@ -1,20 +1,20 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::config::persistence::paths::ValidatorRewarderPaths; use crate::config::r#override::ConfigOverride; +use crate::config::persistence::paths::ValidatorRewarderPaths; use crate::config::template::CONFIG_TEMPLATE; use crate::error::NymRewarderError; use crate::rewarder::ticketbook_issuance; use cosmwasm_std::{Decimal, Uint128}; use nym_config::{ - must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate, - DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, + DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, NymConfigTemplate, + must_get_home, read_config_from_toml_file, save_formatted_config_to_file, }; use nym_validator_client::nyxd::{AccountId, Coin}; use nyxd_scraper::{PruningOptions, StartingBlockOpts}; use serde::{Deserialize, Serialize}; -use serde_with::{serde_as, DisplayFromStr}; +use serde_with::{DisplayFromStr, serde_as}; use std::io; use std::path::{Path, PathBuf}; use std::time::Duration; @@ -236,7 +236,9 @@ impl Config { let per_operator = Coin::new(amount.u128(), &ticketbook_total_budget.denom); let total_budget = &self.rewarding.daily_budget; - info!("ISSUANCE BUDGET: with the total daily budget of {total_budget} ({ticketbook_total_budget} for ticketbook issuance) and with whitelist size of {whitelist_size}, the per operator budget is set to {per_operator}"); + info!( + "ISSUANCE BUDGET: with the total daily budget of {total_budget} ({ticketbook_total_budget} for ticketbook issuance) and with whitelist size of {whitelist_size}, the per operator budget is set to {per_operator}" + ); per_operator } diff --git a/nym-validator-rewarder/src/error.rs b/nym-validator-rewarder/src/error.rs index 31bf710efb..8adbe9883f 100644 --- a/nym-validator-rewarder/src/error.rs +++ b/nym-validator-rewarder/src/error.rs @@ -132,7 +132,9 @@ pub enum NymRewarderError { #[error("failed to resolve nym-api query: {0}")] ApiQueryFailure(Box), - #[error("operator {runner_account} didn't return all requested credentials! requested {requested} but got only {received}")] + #[error( + "operator {runner_account} didn't return all requested credentials! requested {requested} but got only {received}" + )] IncompleteRequest { runner_account: AccountId, requested: usize, @@ -158,7 +160,9 @@ pub enum NymRewarderError { #[error("could not verify the blinded credential")] BlindVerificationFailure, - #[error("the same deposit ({deposit_id}) has been used for multiple issued credentials! {first} and {other}")] + #[error( + "the same deposit ({deposit_id}) has been used for multiple issued credentials! {first} and {other}" + )] DuplicateDepositId { deposit_id: u32, first: i64, @@ -168,14 +172,18 @@ pub enum NymRewarderError { #[error("could not find the deposit details for deposit id {deposit_id}")] DepositNotFound { deposit_id: u32 }, - #[error("the provided deposit value of deposit {deposit_id} is inconsistent. got '{request:?}' while the value on chain is '{on_chain}'")] + #[error( + "the provided deposit value of deposit {deposit_id} is inconsistent. got '{request:?}' while the value on chain is '{on_chain}'" + )] InconsistentDepositValue { deposit_id: u32, request: Option, on_chain: String, }, - #[error("the provided deposit info of deposit {deposit_id} is inconsistent. got '{request:?}' while the value on chain is '{on_chain}'")] + #[error( + "the provided deposit info of deposit {deposit_id} is inconsistent. got '{request:?}' while the value on chain is '{on_chain}'" + )] InconsistentDepositInfo { deposit_id: u32, request: Option, @@ -203,7 +211,9 @@ pub enum NymRewarderError { #[error("attempted to send an empty rewarding coin")] EmptyRewardingCoin, - #[error("the current pruning strategy is set to 'everything' - we won't have any block data for rewarding")] + #[error( + "the current pruning strategy is set to 'everything' - we won't have any block data for rewarding" + )] EverythingPruningStrategy, #[error("pruning.keep_recent must not be smaller than {min_to_keep}. got: {keep_recent}")] diff --git a/nym-validator-rewarder/src/main.rs b/nym-validator-rewarder/src/main.rs index e8945316a5..981b83b6b7 100644 --- a/nym-validator-rewarder/src/main.rs +++ b/nym-validator-rewarder/src/main.rs @@ -7,7 +7,7 @@ #![warn(clippy::dbg_macro)] use crate::cli::Cli; -use clap::{crate_name, crate_version, Parser}; +use clap::{Parser, crate_name, crate_version}; use nym_bin_common::logging::{maybe_print_banner, setup_tracing_logger}; use nym_network_defaults::setup_env; diff --git a/nym-validator-rewarder/src/rewarder/block_signing/mod.rs b/nym-validator-rewarder/src/rewarder/block_signing/mod.rs index 5a32069a04..57406c34cc 100644 --- a/nym-validator-rewarder/src/rewarder/block_signing/mod.rs +++ b/nym-validator-rewarder/src/rewarder/block_signing/mod.rs @@ -150,7 +150,9 @@ impl EpochSigning { .get_voting_power(&validator.consensus_address, vp_range.clone()) .await? else { - error!("failed to obtain voting power for validator {addr} for any block between heights {vp_range:?} - there were no stored pre-commits for that validator."); + error!( + "failed to obtain voting power for validator {addr} for any block between heights {vp_range:?} - there were no stored pre-commits for that validator." + ); continue; }; diff --git a/nym-validator-rewarder/src/rewarder/block_signing/types.rs b/nym-validator-rewarder/src/rewarder/block_signing/types.rs index 0a27e2258b..497d6546da 100644 --- a/nym-validator-rewarder/src/rewarder/block_signing/types.rs +++ b/nym-validator-rewarder/src/rewarder/block_signing/types.rs @@ -6,7 +6,7 @@ use crate::{ rewarder::helpers::{consensus_pubkey_to_address, operator_account_to_owner_account}, }; use cosmwasm_std::{Decimal, Uint128}; -use nym_validator_client::nyxd::{module_traits::staking, AccountId, Coin}; +use nym_validator_client::nyxd::{AccountId, Coin, module_traits::staking}; use nyxd_scraper::models; use std::collections::HashMap; use tracing::info; @@ -144,11 +144,11 @@ impl EpochSigningResults { for v in &self.validators { let amount = v.reward_amount(budget); info!( - "validator {} will receive {amount} at address {} for block signing work (whitelisted: {})", - v.moniker(), - v.operator_account, - v.whitelisted - ); + "validator {} will receive {amount} at address {} for block signing work (whitelisted: {})", + v.moniker(), + v.operator_account, + v.whitelisted + ); amounts.push((v.operator_account.clone(), vec![amount])) } diff --git a/nym-validator-rewarder/src/rewarder/epoch.rs b/nym-validator-rewarder/src/rewarder/epoch.rs index 7acc4977e9..60ef95f932 100644 --- a/nym-validator-rewarder/src/rewarder/epoch.rs +++ b/nym-validator-rewarder/src/rewarder/epoch.rs @@ -6,9 +6,9 @@ use sqlx::FromRow; use std::fmt::{Display, Formatter}; use std::ops::Add; use std::time::Duration; -use time::format_description::well_known::Rfc3339; use time::OffsetDateTime; -use tokio::time::{interval_at, Instant, Interval}; +use time::format_description::well_known::Rfc3339; +use tokio::time::{Instant, Interval, interval_at}; use tracing::info; const HOUR: Duration = Duration::from_secs(60 * 60); diff --git a/nym-validator-rewarder/src/rewarder/mod.rs b/nym-validator-rewarder/src/rewarder/mod.rs index 3674989fa2..e46dcc3e79 100644 --- a/nym-validator-rewarder/src/rewarder/mod.rs +++ b/nym-validator-rewarder/src/rewarder/mod.rs @@ -3,17 +3,17 @@ use crate::config::Config; use crate::error::{InsufficientBalance, NymRewarderError}; -use crate::rewarder::block_signing::types::EpochSigningResults; use crate::rewarder::block_signing::EpochSigning; +use crate::rewarder::block_signing::types::EpochSigningResults; use crate::rewarder::nyxd_client::NyxdClient; use crate::rewarder::storage::RewarderStorage; +use crate::rewarder::ticketbook_issuance::TicketbookIssuance; use crate::rewarder::ticketbook_issuance::helpers::end_of_day_ticker; use crate::rewarder::ticketbook_issuance::types::TicketbookIssuanceResults; -use crate::rewarder::ticketbook_issuance::TicketbookIssuance; -use futures::future::{FusedFuture, OptionFuture}; use futures::FutureExt; +use futures::future::{FusedFuture, OptionFuture}; use nym_crypto::asymmetric::ed25519; -use nym_ecash_time::{ecash_today, ecash_today_date, EcashTime}; +use nym_ecash_time::{EcashTime, ecash_today, ecash_today_date}; use nym_task::ShutdownManager; use nym_validator_client::nyxd::{AccountId, Coin, Hash}; use nyxd_scraper::NyxdScraper; @@ -523,7 +523,7 @@ impl Rewarder { Ok(()) } - async fn setup_tasks(&self) -> Result { + async fn setup_tasks(&self) -> Result, NymRewarderError> { let scraper_cancellation: OptionFuture<_> = if let Some(epoch_signing) = &self.epoch_signing { let cancellation_token = epoch_signing.nyxd_scraper.cancel_token(); @@ -587,13 +587,21 @@ impl Rewarder { if let Err(err) = self.startup_resync().await { error!("failed to perform startup sync: {err}"); - error!("if the failure was due to insufficient number of blocks, your course of action is as follows:"); - error!("(ideally it would have been automatically resolved in this very method, but that'd require some serious refactoring)"); + error!( + "if the failure was due to insufficient number of blocks, your course of action is as follows:" + ); + error!( + "(ideally it would have been automatically resolved in this very method, but that'd require some serious refactoring)" + ); error!( "1. determine height of the first block of the epoch (doesn't have to be exact)" ); - error!("2. run the following subcommand of the rewarder: `nym-validator-rewarder process-until --start-height=$STARTING_BLOCK"); - error!("3. !!IMPORTANT!! go to config.toml and temporarily disable block pruning, i.e. `pruning.strategy=nothing`"); + error!( + "2. run the following subcommand of the rewarder: `nym-validator-rewarder process-until --start-height=$STARTING_BLOCK" + ); + error!( + "3. !!IMPORTANT!! go to config.toml and temporarily disable block pruning, i.e. `pruning.strategy=nothing`" + ); error!("4. restart nym-validator-rewarder as normal until it sends missing rewards"); error!("5. re-enable pruning and restart the nym-validator rewarder"); return Err(err); diff --git a/nym-validator-rewarder/src/rewarder/nyxd_client.rs b/nym-validator-rewarder/src/rewarder/nyxd_client.rs index c5de2c37b1..6e111780c9 100644 --- a/nym-validator-rewarder/src/rewarder/nyxd_client.rs +++ b/nym-validator-rewarder/src/rewarder/nyxd_client.rs @@ -3,7 +3,7 @@ use crate::config::Config; use crate::error::NymRewarderError; -use crate::rewarder::ticketbook_issuance::types::{addr_to_account_id, CredentialIssuer}; +use crate::rewarder::ticketbook_issuance::types::{CredentialIssuer, addr_to_account_id}; use nym_coconut_dkg_common::types::Epoch; use nym_compact_ecash::{Base58, VerificationKeyAuth}; use nym_crypto::asymmetric::ed25519; @@ -15,7 +15,7 @@ use nym_validator_client::nyxd::module_traits::staking::{ use nym_validator_client::nyxd::{ AccountId, Coin, CosmWasmClient, Hash, PageRequest, StakingQueryClient, }; -use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient}; +use nym_validator_client::{DirectSigningHttpRpcNyxdClient, nyxd}; use std::collections::HashMap; use std::ops::Deref; use std::sync::Arc; diff --git a/nym-validator-rewarder/src/rewarder/storage/mod.rs b/nym-validator-rewarder/src/rewarder/storage/mod.rs index 876cb6d98d..a3e8f69bd7 100644 --- a/nym-validator-rewarder/src/rewarder/storage/mod.rs +++ b/nym-validator-rewarder/src/rewarder/storage/mod.rs @@ -1,14 +1,14 @@ // Copyright 2023-2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::rewarder::{extract_rewarding_results, BlockSigningDetails, TicketbookIssuanceDetails}; +use crate::rewarder::{BlockSigningDetails, TicketbookIssuanceDetails, extract_rewarding_results}; use crate::{ error::NymRewarderError, - rewarder::{epoch::Epoch, storage::manager::StorageManager, RewardingResult}, + rewarder::{RewardingResult, epoch::Epoch, storage::manager::StorageManager}, }; use nym_contracts_common::types::NaiveFloat; -use sqlx::sqlite::{SqliteAutoVacuum, SqliteSynchronous}; use sqlx::ConnectOptions; +use sqlx::sqlite::{SqliteAutoVacuum, SqliteSynchronous}; use std::{fmt::Debug, path::Path}; use time::{Date, OffsetDateTime}; use tracing::{error, info, instrument}; diff --git a/nym-validator-rewarder/src/rewarder/ticketbook_issuance/helpers.rs b/nym-validator-rewarder/src/rewarder/ticketbook_issuance/helpers.rs index e893ac6606..8abe36fae4 100644 --- a/nym-validator-rewarder/src/rewarder/ticketbook_issuance/helpers.rs +++ b/nym-validator-rewarder/src/rewarder/ticketbook_issuance/helpers.rs @@ -3,9 +3,9 @@ use std::ops::Add; use std::time::Duration; -use time::format_description::well_known::Rfc3339; use time::OffsetDateTime; -use tokio::time::{interval_at, Instant, Interval}; +use time::format_description::well_known::Rfc3339; +use tokio::time::{Instant, Interval, interval_at}; use tracing::info; pub fn end_of_day_ticker() -> Interval { diff --git a/nym-validator-rewarder/src/rewarder/ticketbook_issuance/types.rs b/nym-validator-rewarder/src/rewarder/ticketbook_issuance/types.rs index f677c0e9bc..89a5aeca5b 100644 --- a/nym-validator-rewarder/src/rewarder/ticketbook_issuance/types.rs +++ b/nym-validator-rewarder/src/rewarder/ticketbook_issuance/types.rs @@ -51,12 +51,12 @@ impl TicketbookIssuanceResults { for api_runner in &self.api_runners { let amount = api_runner.reward_amount(per_operator_budget); info!( - "operator {} will receive {amount} at address {} for ticketbook issuance work (whitelisted: {}, ticketbooks issued: {})", - api_runner.api_runner, - api_runner.runner_account, - api_runner.whitelisted, - api_runner.issued_ticketbooks - ); + "operator {} will receive {amount} at address {} for ticketbook issuance work (whitelisted: {}, ticketbooks issued: {})", + api_runner.api_runner, + api_runner.runner_account, + api_runner.whitelisted, + api_runner.issued_ticketbooks + ); amounts.push((api_runner.runner_account.clone(), vec![amount])) } diff --git a/nym-validator-rewarder/src/rewarder/ticketbook_issuance/verifier.rs b/nym-validator-rewarder/src/rewarder/ticketbook_issuance/verifier.rs index 38ccf2522b..ac75b29aea 100644 --- a/nym-validator-rewarder/src/rewarder/ticketbook_issuance/verifier.rs +++ b/nym-validator-rewarder/src/rewarder/ticketbook_issuance/verifier.rs @@ -6,7 +6,7 @@ use crate::rewarder::ticketbook_issuance::types::{ }; use cosmwasm_std::Decimal; use nym_compact_ecash::scheme::withdrawal::verify_partial_blind_signature; -use nym_compact_ecash::{date_scalar, type_scalar, CompactEcashError}; +use nym_compact_ecash::{CompactEcashError, date_scalar, type_scalar}; use nym_crypto::asymmetric::ed25519; use nym_ecash_time::EcashTime; use nym_network_defaults::MINIMUM_TICKETBOOK_DATA_REQUEST_SIZE; @@ -338,7 +338,10 @@ impl IssuerUnderTest { { Ok(res) => res, Err(err) => { - warn!("⚠️ failed to obtain issued ticketbooks information from {}. it might be running an outdated api. the error was: {err}", self.details); + warn!( + "⚠️ failed to obtain issued ticketbooks information from {}. it might be running an outdated api. the error was: {err}", + self.details + ); return; } }; @@ -511,7 +514,7 @@ impl IssuerUnderTest { Err(err) => { return Err( PartialTicketbookVerificationFailure::MalformedBlindedSignature(err), - ) + ); } }; @@ -525,7 +528,7 @@ impl IssuerUnderTest { PartialTicketbookVerificationFailure::MalformedPrivateAttributesCommitments( err, ), - ) + ); } }; @@ -793,7 +796,10 @@ impl<'a> TicketbookIssuanceVerifier<'a> { // and see if it's running a recent enough version to support subsequent queries let issued_count = tested_issuer.get_issued_count(self.expiration_date).await; if issued_count == 0 { - info!("{} hasn't issued any ticketbooks with expiration on {} (or is running an outdated api). it will not undergo any further testing", tested_issuer.details, self.expiration_date); + info!( + "{} hasn't issued any ticketbooks with expiration on {} (or is running an outdated api). it will not undergo any further testing", + tested_issuer.details, self.expiration_date + ); return None; } @@ -844,11 +850,12 @@ impl<'a> TicketbookIssuanceVerifier<'a> { tested_issuer.verify_challenge_response(self.expiration_date); // if issuer produced valid results, try to update global deposit ids - if !tested_issuer.caught_cheating() && tested_issuer.claimed_issued() > 0 { - if let Some(commitment) = &tested_issuer.issued_commitment { - for deposit in &commitment.body.deposits { - self.made_deposits.insert(deposit.deposit_id); - } + if !tested_issuer.caught_cheating() + && tested_issuer.claimed_issued() > 0 + && let Some(commitment) = &tested_issuer.issued_commitment + { + for deposit in &commitment.body.deposits { + self.made_deposits.insert(deposit.deposit_id); } } diff --git a/nym-wallet/nym-wallet-types/Cargo.toml b/nym-wallet/nym-wallet-types/Cargo.toml index d29f2467dd..9b869ec93f 100644 --- a/nym-wallet/nym-wallet-types/Cargo.toml +++ b/nym-wallet/nym-wallet-types/Cargo.toml @@ -2,7 +2,7 @@ name = "nym-wallet-types" version = "1.0.0" edition = "2021" -rust-version = "1.58" +rust-version = "1.85" license = "Apache-2.0" [dependencies] diff --git a/nym-wallet/nym-wallet-types/src/network.rs b/nym-wallet/nym-wallet-types/src/network.rs index b01c3768e3..8710ef6b33 100644 --- a/nym-wallet/nym-wallet-types/src/network.rs +++ b/nym-wallet/nym-wallet-types/src/network.rs @@ -15,9 +15,10 @@ mod sandbox; feature = "generate-ts", ts(export, export_to = "nym-wallet/src/types/rust/Network.ts") )] -#[derive(Copy, Clone, Debug, Deserialize, EnumIter, Eq, Hash, PartialEq, Serialize)] +#[derive(Copy, Clone, Default, Debug, Deserialize, EnumIter, Eq, Hash, PartialEq, Serialize)] pub enum Network { SANDBOX, + #[default] MAINNET, } @@ -52,12 +53,6 @@ impl Network { } } -impl Default for Network { - fn default() -> Self { - Network::MAINNET - } -} - impl fmt::Display for Network { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{self:?}") diff --git a/nyx-chain-watcher/build.rs b/nyx-chain-watcher/build.rs index a6dbb3c105..e36d6a43ff 100644 --- a/nyx-chain-watcher/build.rs +++ b/nyx-chain-watcher/build.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use sqlx::{sqlite::SqliteConnectOptions, Connection, SqliteConnection}; +use sqlx::{Connection, SqliteConnection, sqlite::SqliteConnectOptions}; use std::env::var; use std::io::Write; use std::{collections::HashMap, fs::File, path::PathBuf, str::FromStr}; diff --git a/nyx-chain-watcher/src/chain_scraper/mod.rs b/nyx-chain-watcher/src/chain_scraper/mod.rs index 21e716d580..6f2e493f31 100644 --- a/nyx-chain-watcher/src/chain_scraper/mod.rs +++ b/nyx-chain-watcher/src/chain_scraper/mod.rs @@ -7,8 +7,8 @@ use crate::http::state::BankScraperModuleState; use async_trait::async_trait; use nym_validator_client::nyxd::{Any, Coin, CosmosCoin, Hash, Msg, MsgSend, Name}; use nyxd_scraper::{ - error::ScraperError, storage::StorageTransaction, MsgModule, NyxdScraper, - ParsedTransactionResponse, PruningOptions, + MsgModule, NyxdScraper, ParsedTransactionResponse, PruningOptions, error::ScraperError, + storage::StorageTransaction, }; use sqlx::SqlitePool; use std::fs; diff --git a/nyx-chain-watcher/src/cli/commands/init.rs b/nyx-chain-watcher/src/cli/commands/init.rs index 50be4f056b..22431f725a 100644 --- a/nyx-chain-watcher/src/cli/commands/init.rs +++ b/nyx-chain-watcher/src/cli/commands/init.rs @@ -4,7 +4,7 @@ use crate::cli::DEFAULT_NYX_CHAIN_WATCHER_ID; use crate::config::payments_watcher::HttpAuthenticationOptions::AuthorizationBearerToken; use crate::config::payments_watcher::PaymentWatcherConfig; -use crate::config::{default_config_filepath, Config, ConfigBuilder, PaymentWatchersConfig}; +use crate::config::{Config, ConfigBuilder, PaymentWatchersConfig, default_config_filepath}; use crate::error::NyxChainWatcherError; use nym_config::save_unformatted_config_to_file; use nym_validator_client::nyxd::AccountId; @@ -22,10 +22,9 @@ pub(crate) async fn execute(_args: Args) -> Result<(), NyxChainWatcherError> { watchers: vec![PaymentWatcherConfig { id: DEFAULT_NYX_CHAIN_WATCHER_ID.to_string(), webhook_url: "https://webhook.site".to_string(), - watch_for_transfer_recipient_accounts: vec![AccountId::from_str( - "n17g9a2pwwkg8m60wf59pq6mv0c2wusg9ukparkz", - ) - .unwrap()], + watch_for_transfer_recipient_accounts: vec![ + AccountId::from_str("n17g9a2pwwkg8m60wf59pq6mv0c2wusg9ukparkz").unwrap(), + ], authentication: Some(AuthorizationBearerToken { token: "1234".to_string(), }), diff --git a/nyx-chain-watcher/src/cli/commands/run/config.rs b/nyx-chain-watcher/src/cli/commands/run/config.rs index 73e923a888..bc0adbecde 100644 --- a/nyx-chain-watcher/src/cli/commands/run/config.rs +++ b/nyx-chain-watcher/src/cli/commands/run/config.rs @@ -1,7 +1,7 @@ -use crate::cli::commands::run::args::Args; use crate::cli::DEFAULT_NYX_CHAIN_WATCHER_ID; +use crate::cli::commands::run::args::Args; use crate::config::payments_watcher::{HttpAuthenticationOptions, PaymentWatcherConfig}; -use crate::config::{default_config_filepath, Config, ConfigBuilder, PaymentWatchersConfig}; +use crate::config::{Config, ConfigBuilder, PaymentWatchersConfig, default_config_filepath}; use crate::error::NyxChainWatcherError; use tracing::{info, warn}; diff --git a/nyx-chain-watcher/src/config/mod.rs b/nyx-chain-watcher/src/config/mod.rs index ce4e9448a5..8647b22dbc 100644 --- a/nyx-chain-watcher/src/config/mod.rs +++ b/nyx-chain-watcher/src/config/mod.rs @@ -4,8 +4,8 @@ use crate::config::template::CONFIG_TEMPLATE; use nym_bin_common::logging::LoggingSettings; use nym_config::{ - must_get_home, read_config_from_toml_file, save_unformatted_config_to_file, NymConfigTemplate, - DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, + DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, NymConfigTemplate, + must_get_home, read_config_from_toml_file, save_unformatted_config_to_file, }; use serde::{Deserialize, Serialize}; use std::path::{Path, PathBuf}; @@ -182,7 +182,8 @@ impl Config { if config_dir_name != DEFAULT_CONFIG_DIR { error!( "the parent directory of '{}' ({}) is not {DEFAULT_CONFIG_DIR}. currently this is not supported", - config_path.display(), config_dir_name.to_str().unwrap_or("UNKNOWN") + config_path.display(), + config_dir_name.to_str().unwrap_or("UNKNOWN") ); return Err(NyxChainWatcherError::DataDirDerivationFailure); } diff --git a/nyx-chain-watcher/src/db/mod.rs b/nyx-chain-watcher/src/db/mod.rs index 00368afb6e..a32809f733 100644 --- a/nyx-chain-watcher/src/db/mod.rs +++ b/nyx-chain-watcher/src/db/mod.rs @@ -1,5 +1,5 @@ -use anyhow::{anyhow, Result}; -use sqlx::{migrate::Migrator, sqlite::SqliteConnectOptions, SqlitePool}; +use anyhow::{Result, anyhow}; +use sqlx::{SqlitePool, migrate::Migrator, sqlite::SqliteConnectOptions}; use std::str::FromStr; pub(crate) mod models; diff --git a/nyx-chain-watcher/src/db/queries/price.rs b/nyx-chain-watcher/src/db/queries/price.rs index 4a6ddbeea3..493a1031d7 100644 --- a/nyx-chain-watcher/src/db/queries/price.rs +++ b/nyx-chain-watcher/src/db/queries/price.rs @@ -1,5 +1,5 @@ -use crate::db::models::{PriceHistory, PriceRecord}; use crate::db::DbPool; +use crate::db::models::{PriceHistory, PriceRecord}; use chrono::Local; use std::ops::Sub; diff --git a/nyx-chain-watcher/src/helpers.rs b/nyx-chain-watcher/src/helpers.rs index 88f250cf68..e84fe5b3d5 100644 --- a/nyx-chain-watcher/src/helpers.rs +++ b/nyx-chain-watcher/src/helpers.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: GPL-3.0-only use serde::{Deserialize, Serialize}; -use std::collections::vec_deque::{IntoIter, Iter}; use std::collections::VecDeque; +use std::collections::vec_deque::{IntoIter, Iter}; #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) struct RingBuffer { diff --git a/nyx-chain-watcher/src/http/api/mod.rs b/nyx-chain-watcher/src/http/api/mod.rs index 6374f4ca9f..50f95d84ca 100644 --- a/nyx-chain-watcher/src/http/api/mod.rs +++ b/nyx-chain-watcher/src/http/api/mod.rs @@ -1,5 +1,5 @@ use anyhow::anyhow; -use axum::{response::Redirect, Router}; +use axum::{Router, response::Redirect}; use tokio::net::ToSocketAddrs; use tower_http::{cors::CorsLayer, trace::TraceLayer}; use utoipa::OpenApi; diff --git a/nyx-chain-watcher/src/http/api/price.rs b/nyx-chain-watcher/src/http/api/price.rs index 1971f35f7d..3a7829d598 100644 --- a/nyx-chain-watcher/src/http/api/price.rs +++ b/nyx-chain-watcher/src/http/api/price.rs @@ -3,7 +3,7 @@ use crate::db::queries::price::{get_average_price, get_latest_price}; use crate::http::error::Error; use crate::http::error::HttpResult; use crate::http::state::AppState; -use axum::{extract::State, Json, Router}; +use axum::{Json, Router, extract::State}; pub(crate) fn routes() -> Router { Router::new() diff --git a/nyx-chain-watcher/src/http/state.rs b/nyx-chain-watcher/src/http/state.rs index 3f0d813f44..8cb9d93e9f 100644 --- a/nyx-chain-watcher/src/http/state.rs +++ b/nyx-chain-watcher/src/http/state.rs @@ -1,5 +1,5 @@ -use crate::db::models::CoingeckoPriceResponse; use crate::db::DbPool; +use crate::db::models::CoingeckoPriceResponse; use crate::helpers::RingBuffer; use crate::http::models::status::PaymentWatcher; use crate::models::WebhookPayload; diff --git a/nyx-chain-watcher/src/logging.rs b/nyx-chain-watcher/src/logging.rs index 1c8cbeebb1..dfcdefaadf 100644 --- a/nyx-chain-watcher/src/logging.rs +++ b/nyx-chain-watcher/src/logging.rs @@ -1,5 +1,5 @@ use tracing::level_filters::LevelFilter; -use tracing_subscriber::{filter::Directive, EnvFilter}; +use tracing_subscriber::{EnvFilter, filter::Directive}; pub(crate) fn setup_tracing_logger() { fn directive_checked(directive: String) -> Directive { diff --git a/nyx-chain-watcher/src/main.rs b/nyx-chain-watcher/src/main.rs index 96b531ddba..725eee7a06 100644 --- a/nyx-chain-watcher/src/main.rs +++ b/nyx-chain-watcher/src/main.rs @@ -1,4 +1,4 @@ -use clap::{crate_name, crate_version, Parser}; +use clap::{Parser, crate_name, crate_version}; use nym_bin_common::bin_info_owned; use nym_bin_common::logging::maybe_print_banner; use nym_network_defaults::setup_env; diff --git a/service-providers/ip-packet-router/src/cli/add_gateway.rs b/service-providers/ip-packet-router/src/cli/add_gateway.rs index ef23413c68..1465f1a710 100644 --- a/service-providers/ip-packet-router/src/cli/add_gateway.rs +++ b/service-providers/ip-packet-router/src/cli/add_gateway.rs @@ -3,7 +3,7 @@ use crate::cli::CliIpPacketRouterClient; use nym_bin_common::output_format::OutputFormat; -use nym_client_core::cli_helpers::client_add_gateway::{add_gateway, CommonClientAddGatewayArgs}; +use nym_client_core::cli_helpers::client_add_gateway::{CommonClientAddGatewayArgs, add_gateway}; use nym_ip_packet_router::error::IpPacketRouterError; #[derive(clap::Args)] diff --git a/service-providers/ip-packet-router/src/cli/ecash/import_coin_index_signatures.rs b/service-providers/ip-packet-router/src/cli/ecash/import_coin_index_signatures.rs index 0a9a53dab5..fe2f9348f2 100644 --- a/service-providers/ip-packet-router/src/cli/ecash/import_coin_index_signatures.rs +++ b/service-providers/ip-packet-router/src/cli/ecash/import_coin_index_signatures.rs @@ -3,7 +3,7 @@ use crate::cli::CliIpPacketRouterClient; use nym_client_core::cli_helpers::client_import_coin_index_signatures::{ - import_coin_index_signatures, CommonClientImportCoinIndexSignaturesArgs, + CommonClientImportCoinIndexSignaturesArgs, import_coin_index_signatures, }; use nym_ip_packet_router::error::IpPacketRouterError; diff --git a/service-providers/ip-packet-router/src/cli/ecash/import_credential.rs b/service-providers/ip-packet-router/src/cli/ecash/import_credential.rs index 85209b933e..c376a82651 100644 --- a/service-providers/ip-packet-router/src/cli/ecash/import_credential.rs +++ b/service-providers/ip-packet-router/src/cli/ecash/import_credential.rs @@ -3,7 +3,7 @@ use crate::cli::CliIpPacketRouterClient; use nym_client_core::cli_helpers::client_import_credential::{ - import_credential, CommonClientImportTicketBookArgs, + CommonClientImportTicketBookArgs, import_credential, }; use nym_ip_packet_router::error::IpPacketRouterError; diff --git a/service-providers/ip-packet-router/src/cli/ecash/import_expiration_date_signatures.rs b/service-providers/ip-packet-router/src/cli/ecash/import_expiration_date_signatures.rs index 28ea667345..4b5d004ec7 100644 --- a/service-providers/ip-packet-router/src/cli/ecash/import_expiration_date_signatures.rs +++ b/service-providers/ip-packet-router/src/cli/ecash/import_expiration_date_signatures.rs @@ -3,7 +3,7 @@ use crate::cli::CliIpPacketRouterClient; use nym_client_core::cli_helpers::client_import_expiration_date_signatures::{ - import_expiration_date_signatures, CommonClientImportExpirationDateSignaturesArgs, + CommonClientImportExpirationDateSignaturesArgs, import_expiration_date_signatures, }; use nym_ip_packet_router::error::IpPacketRouterError; diff --git a/service-providers/ip-packet-router/src/cli/ecash/import_master_verification_key.rs b/service-providers/ip-packet-router/src/cli/ecash/import_master_verification_key.rs index bff9d3ea62..fdecaff6dc 100644 --- a/service-providers/ip-packet-router/src/cli/ecash/import_master_verification_key.rs +++ b/service-providers/ip-packet-router/src/cli/ecash/import_master_verification_key.rs @@ -3,7 +3,7 @@ use crate::cli::CliIpPacketRouterClient; use nym_client_core::cli_helpers::client_import_master_verification_key::{ - import_master_verification_key, CommonClientImportMasterVerificationKeyArgs, + CommonClientImportMasterVerificationKeyArgs, import_master_verification_key, }; use nym_ip_packet_router::error::IpPacketRouterError; diff --git a/service-providers/ip-packet-router/src/cli/ecash/show_ticketbooks.rs b/service-providers/ip-packet-router/src/cli/ecash/show_ticketbooks.rs index 0c9ebad722..f5ee15d717 100644 --- a/service-providers/ip-packet-router/src/cli/ecash/show_ticketbooks.rs +++ b/service-providers/ip-packet-router/src/cli/ecash/show_ticketbooks.rs @@ -4,7 +4,7 @@ use crate::cli::CliIpPacketRouterClient; use nym_bin_common::output_format::OutputFormat; use nym_client_core::cli_helpers::client_show_ticketbooks::{ - show_ticketbooks, CommonShowTicketbooksArgs, + CommonShowTicketbooksArgs, show_ticketbooks, }; use nym_ip_packet_router::error::IpPacketRouterError; diff --git a/service-providers/ip-packet-router/src/cli/init.rs b/service-providers/ip-packet-router/src/cli/init.rs index 024e1606fe..03c58b84d9 100644 --- a/service-providers/ip-packet-router/src/cli/init.rs +++ b/service-providers/ip-packet-router/src/cli/init.rs @@ -1,11 +1,11 @@ -use crate::cli::{override_config, CliIpPacketRouterClient, OverrideConfig}; +use crate::cli::{CliIpPacketRouterClient, OverrideConfig, override_config}; use clap::Args; use nym_bin_common::output_format::OutputFormat; use nym_client_core::cli_helpers::client_init::{ - initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient, + CommonClientInitArgs, InitResultsWithConfig, InitialisableClient, initialise_client, }; use nym_ip_packet_router::{ - config::{default_config_directory, default_config_filepath, default_data_directory, Config}, + config::{Config, default_config_directory, default_config_filepath, default_data_directory}, error::IpPacketRouterError, }; use serde::Serialize; diff --git a/service-providers/ip-packet-router/src/cli/list_gateways.rs b/service-providers/ip-packet-router/src/cli/list_gateways.rs index 8ddb9a985b..dc575bba67 100644 --- a/service-providers/ip-packet-router/src/cli/list_gateways.rs +++ b/service-providers/ip-packet-router/src/cli/list_gateways.rs @@ -4,7 +4,7 @@ use crate::cli::CliIpPacketRouterClient; use nym_bin_common::output_format::OutputFormat; use nym_client_core::cli_helpers::client_list_gateways::{ - list_gateways, CommonClientListGatewaysArgs, + CommonClientListGatewaysArgs, list_gateways, }; use nym_ip_packet_router::error::IpPacketRouterError; diff --git a/service-providers/ip-packet-router/src/cli/mod.rs b/service-providers/ip-packet-router/src/cli/mod.rs index d322984773..4cdcbeb398 100644 --- a/service-providers/ip-packet-router/src/cli/mod.rs +++ b/service-providers/ip-packet-router/src/cli/mod.rs @@ -2,7 +2,7 @@ use crate::cli::ecash::Ecash; use clap::{CommandFactory, Parser, Subcommand}; use log::error; use nym_bin_common::bin_info; -use nym_bin_common::completions::{fig_generate, ArgShell}; +use nym_bin_common::completions::{ArgShell, fig_generate}; use nym_client_core::cli_helpers::CliClient; use nym_ip_packet_router::config::helpers::{try_upgrade_config, try_upgrade_config_by_id}; use nym_ip_packet_router::config::{BaseClientConfig, Config}; @@ -156,7 +156,9 @@ async fn try_load_current_config(id: &str) -> Result cfg, Err(err) => { - error!("Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})"); + error!( + "Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})" + ); return Err(IpPacketRouterError::FailedToLoadConfig(id.to_string())); } }; diff --git a/service-providers/ip-packet-router/src/cli/run.rs b/service-providers/ip-packet-router/src/cli/run.rs index 2108efcc86..cfff98038e 100644 --- a/service-providers/ip-packet-router/src/cli/run.rs +++ b/service-providers/ip-packet-router/src/cli/run.rs @@ -1,5 +1,5 @@ use crate::cli::try_load_current_config; -use crate::cli::{override_config, OverrideConfig}; +use crate::cli::{OverrideConfig, override_config}; use clap::Args; use nym_client_core::cli_helpers::client_run::CommonClientRunArgs; use nym_ip_packet_router::error::IpPacketRouterError; diff --git a/service-providers/ip-packet-router/src/cli/sign.rs b/service-providers/ip-packet-router/src/cli/sign.rs index bfb9074035..be25d1fbf1 100644 --- a/service-providers/ip-packet-router/src/cli/sign.rs +++ b/service-providers/ip-packet-router/src/cli/sign.rs @@ -30,7 +30,9 @@ fn print_signed_contract_msg( eprintln!(">>> attempting to sign {trimmed}"); let Ok(decoded) = bs58::decode(trimmed).into_vec() else { - println!("it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters"); + println!( + "it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters" + ); return; }; @@ -39,7 +41,9 @@ fn print_signed_contract_msg( // we don't really care about what particular information is embedded inside of it, // we just want to know if user correctly copied the string, i.e. whether it's a valid bs58 encoded json if serde_json::from_slice::(&decoded).is_err() { - println!("it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters"); + println!( + "it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters" + ); return; }; diff --git a/service-providers/ip-packet-router/src/cli/switch_gateway.rs b/service-providers/ip-packet-router/src/cli/switch_gateway.rs index cb53983fb8..14bdb17ccf 100644 --- a/service-providers/ip-packet-router/src/cli/switch_gateway.rs +++ b/service-providers/ip-packet-router/src/cli/switch_gateway.rs @@ -3,7 +3,7 @@ use crate::cli::CliIpPacketRouterClient; use nym_client_core::cli_helpers::client_switch_gateway::{ - switch_gateway, CommonClientSwitchGatewaysArgs, + CommonClientSwitchGatewaysArgs, switch_gateway, }; use nym_ip_packet_router::error::IpPacketRouterError; 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 551518a062..ba9f9b3290 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 @@ -15,7 +15,7 @@ use nym_sdk::mixnet::{ }; use tokio::{ sync::{mpsc, oneshot}, - time::{interval, Interval}, + time::{Interval, interval}, }; use tokio_util::codec::Encoder; diff --git a/service-providers/ip-packet-router/src/clients/connected_clients.rs b/service-providers/ip-packet-router/src/clients/connected_clients.rs index 7100048dd8..25e4323073 100644 --- a/service-providers/ip-packet-router/src/clients/connected_clients.rs +++ b/service-providers/ip-packet-router/src/clients/connected_clients.rs @@ -9,7 +9,7 @@ use std::{ }; use nym_ip_packet_requests::IpPair; -use tokio::sync::{mpsc, oneshot, RwLock}; +use tokio::sync::{RwLock, mpsc, oneshot}; use crate::{ constants::CLIENT_MIXNET_INACTIVITY_TIMEOUT, diff --git a/service-providers/ip-packet-router/src/config/mod.rs b/service-providers/ip-packet-router/src/config/mod.rs index a3968200f3..30e53c6e6f 100644 --- a/service-providers/ip-packet-router/src/config/mod.rs +++ b/service-providers/ip-packet-router/src/config/mod.rs @@ -3,9 +3,9 @@ pub use nym_client_core::config::Config as BaseClientConfig; use nym_bin_common::logging::LoggingSettings; use nym_client_core::{cli_helpers::CliClientConfig, config::disk_persistence::CommonClientPaths}; use nym_config::{ - defaults::mainnet, must_get_home, save_formatted_config_to_file, - serde_helpers::de_maybe_stringified, NymConfigTemplate, OptionalSet, DEFAULT_CONFIG_DIR, - DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, + DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, NymConfigTemplate, + OptionalSet, defaults::mainnet, must_get_home, save_formatted_config_to_file, + serde_helpers::de_maybe_stringified, }; use nym_service_providers_common::DEFAULT_SERVICE_PROVIDERS_DIR; use serde::{Deserialize, Serialize}; 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 f6f2863085..8a5ffd8635 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 @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::config::persistence::IpPacketRouterPaths; -use crate::config::{default_config_filepath, IpPacketRouter}; +use crate::config::{IpPacketRouter, default_config_filepath}; use crate::error::IpPacketRouterError; use nym_bin_common::logging::LoggingSettings; use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33; diff --git a/service-providers/ip-packet-router/src/config/old_config_v2.rs b/service-providers/ip-packet-router/src/config/old_config_v2.rs index 9a1f91f11f..3cc3e3d9a3 100644 --- a/service-providers/ip-packet-router/src/config/old_config_v2.rs +++ b/service-providers/ip-packet-router/src/config/old_config_v2.rs @@ -6,7 +6,7 @@ use nym_client_core::config::old_config_v1_1_54::ConfigV1_1_54 as BaseConfigV1_1 use nym_config::read_config_from_toml_file; use serde::{Deserialize, Serialize}; -use super::{default_config_filepath, IpPacketRouter, IpPacketRouterPaths}; +use super::{IpPacketRouter, IpPacketRouterPaths, default_config_filepath}; #[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] diff --git a/service-providers/ip-packet-router/src/ip_packet_router.rs b/service-providers/ip-packet-router/src/ip_packet_router.rs index 1e38d33595..052636dae3 100644 --- a/service-providers/ip-packet-router/src/ip_packet_router.rs +++ b/service-providers/ip-packet-router/src/ip_packet_router.rs @@ -8,8 +8,8 @@ use std::path::Path; use futures::channel::oneshot; use nym_client_core::{ - client::mix_traffic::transceiver::GatewayTransceiver, HardcodedTopologyProvider, - TopologyProvider, + HardcodedTopologyProvider, TopologyProvider, + client::mix_traffic::transceiver::GatewayTransceiver, }; use nym_sdk::mixnet::Recipient; use nym_task::ShutdownTracker; @@ -175,14 +175,13 @@ impl IpPacketRouter { log::info!("The address of this client is: {self_address}"); log::info!("All systems go. Press CTRL-C to stop the server."); - if let Some(on_start) = self.on_start { - if on_start + if let Some(on_start) = self.on_start + && on_start .send(OnStartData::new(self_address, request_filter)) .is_err() - { - // the parent has dropped the channel before receiving the response - return Err(IpPacketRouterError::DisconnectedParent); - } + { + // the parent has dropped the channel before receiving the response + return Err(IpPacketRouterError::DisconnectedParent); } mixnet_listener.run().await diff --git a/service-providers/ip-packet-router/src/messages/request.rs b/service-providers/ip-packet-router/src/messages/request.rs index 665abe024a..9f5704fb40 100644 --- a/service-providers/ip-packet-router/src/messages/request.rs +++ b/service-providers/ip-packet-router/src/messages/request.rs @@ -6,9 +6,9 @@ mod v7; mod v8; use nym_ip_packet_requests::{ - v6::request::IpPacketRequest as IpPacketRequestV6, + IpPair, v6::request::IpPacketRequest as IpPacketRequestV6, v7::request::IpPacketRequest as IpPacketRequestV7, - v8::request::IpPacketRequest as IpPacketRequestV8, IpPair, + v8::request::IpPacketRequest as IpPacketRequestV8, }; use nym_sdk::mixnet::ReconstructedMessage; use nym_service_provider_requests_common::{Protocol, ServiceProviderType}; diff --git a/service-providers/ip-packet-router/src/messages/response.rs b/service-providers/ip-packet-router/src/messages/response.rs index d1bf0d08b4..5f3c655205 100644 --- a/service-providers/ip-packet-router/src/messages/response.rs +++ b/service-providers/ip-packet-router/src/messages/response.rs @@ -7,9 +7,9 @@ mod v8; use nym_bin_common::build_information::BinaryBuildInformationOwned; use nym_ip_packet_requests::{ - v6::response::IpPacketResponse as IpPacketResponseV6, + IpPair, v6::response::IpPacketResponse as IpPacketResponseV6, v7::response::IpPacketResponse as IpPacketResponseV7, - v8::response::IpPacketResponse as IpPacketResponseV8, IpPair, + v8::response::IpPacketResponse as IpPacketResponseV8, }; use crate::{ @@ -147,9 +147,7 @@ pub(crate) enum InfoResponseReply { Generic { msg: String }, #[allow(unused)] - #[error( - "version mismatch: response is v{request_version} and response is v{response_version}" - )] + #[error("version mismatch: response is v{request_version} and response is v{response_version}")] VersionMismatch { request_version: u8, response_version: u8, diff --git a/service-providers/ip-packet-router/src/messages/response/v8.rs b/service-providers/ip-packet-router/src/messages/response/v8.rs index 1d0b5a3413..1554d37b60 100644 --- a/service-providers/ip-packet-router/src/messages/response/v8.rs +++ b/service-providers/ip-packet-router/src/messages/response/v8.rs @@ -31,7 +31,7 @@ impl TryFrom for IpPacketResponseV8 { Response::StaticConnect { .. } => { return Err(IpPacketRouterError::UnsupportedResponse(format!( "Static connect response is not supported in version {version}" - ))) + ))); } Response::DynamicConnect { request_id, reply } => IpPacketResponseDataV8::Control( Box::new(ControlResponseV8::Connect(ConnectResponseV8 { diff --git a/service-providers/ip-packet-router/src/mixnet_client.rs b/service-providers/ip-packet-router/src/mixnet_client.rs index 8326a5854a..f3cd81a7c5 100644 --- a/service-providers/ip-packet-router/src/mixnet_client.rs +++ b/service-providers/ip-packet-router/src/mixnet_client.rs @@ -1,7 +1,7 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use nym_client_core::{config::disk_persistence::CommonClientPaths, TopologyProvider}; +use nym_client_core::{TopologyProvider, config::disk_persistence::CommonClientPaths}; use nym_sdk::{GatewayTransceiver, NymNetworkDetails}; use nym_task::ShutdownTracker; diff --git a/service-providers/ip-packet-router/src/mixnet_listener.rs b/service-providers/ip-packet-router/src/mixnet_listener.rs index b29493da8f..c0f36927bc 100644 --- a/service-providers/ip-packet-router/src/mixnet_listener.rs +++ b/service-providers/ip-packet-router/src/mixnet_listener.rs @@ -7,6 +7,7 @@ use crate::{ constants::DISCONNECT_TIMER_INTERVAL, error::{IpPacketRouterError, Result}, messages::{ + ClientVersion, request::{ ControlRequest, DataRequest, DisconnectRequest, DynamicConnectRequest, HealthRequest, IpPacketRequest, PingRequest, StaticConnectRequest, @@ -16,7 +17,6 @@ use crate::{ DynamicConnectSuccess, HealthResponse, InfoLevel, InfoResponse, InfoResponseReply, Response, StaticConnectFailureReason, StaticConnectResponse, VersionedResponse, }, - ClientVersion, }, request_filter::RequestFilter, util::parse_ip::ParsedPacket, @@ -114,7 +114,9 @@ impl MixnetListener { } } else { // If the client is not connected, just drop the packet silently - log::debug!("dropping packet from mixnet: no registered client for packet with source: {src_addr}"); + log::debug!( + "dropping packet from mixnet: no registered client for packet with source: {src_addr}" + ); Ok(None) } } 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 3ebc68e774..7baca7b5c5 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,8 +4,8 @@ use std::net::SocketAddr; use crate::error::IpPacketRouterError; -use nym_exit_policy::client::get_exit_policy; use nym_exit_policy::ExitPolicy; +use nym_exit_policy::client::get_exit_policy; use reqwest::IntoUrl; use url::Url; diff --git a/service-providers/ip-packet-router/src/tun_listener.rs b/service-providers/ip-packet-router/src/tun_listener.rs index f1b663fc03..2b0d574274 100644 --- a/service-providers/ip-packet-router/src/tun_listener.rs +++ b/service-providers/ip-packet-router/src/tun_listener.rs @@ -97,7 +97,9 @@ impl TunListener { { let packet = buf[..len].to_vec(); if forward_from_tun_tx.send(packet).is_err() { - log::warn!("Failed to forward packet to connected client {dst_addr}: disconnecting it from tun listener"); + log::warn!( + "Failed to forward packet to connected client {dst_addr}: disconnecting it from tun listener" + ); self.connected_clients .update(ConnectedClientEvent::Disconnect(DisconnectEvent(*ips))); } diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index d13c60bc1f..d894294ad1 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0" version = "1.1.64" authors.workspace = true edition.workspace = true -rust-version = "1.70" +rust-version = "1.85" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -20,7 +20,7 @@ anyhow = { workspace = true } addr = { workspace = true } async-trait = { workspace = true } bs58 = { workspace = true } -clap = { workspace = true, features = ["cargo", "derive"]} +clap = { workspace = true, features = ["cargo", "derive"] } dirs = { workspace = true } futures = { workspace = true } humantime-serde = { workspace = true } @@ -32,10 +32,10 @@ regex = { workspace = true } reqwest = { workspace = true, features = ["json"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -sqlx = { workspace = true, features = ["runtime-tokio-rustls", "chrono"]} +sqlx = { workspace = true, features = ["runtime-tokio-rustls", "chrono"] } tap = { workspace = true } thiserror = { workspace = true } -tokio = { workspace = true, features = [ "net", "rt-multi-thread", "macros" ] } +tokio = { workspace = true, features = ["net", "rt-multi-thread", "macros"] } tokio-tungstenite = { workspace = true } url = { workspace = true } time = { workspace = true } diff --git a/service-providers/network-requester/src/cli/add_gateway.rs b/service-providers/network-requester/src/cli/add_gateway.rs index 67595f7fd9..c55e86b2e0 100644 --- a/service-providers/network-requester/src/cli/add_gateway.rs +++ b/service-providers/network-requester/src/cli/add_gateway.rs @@ -4,7 +4,7 @@ use crate::cli::CliNetworkRequesterClient; use crate::error::NetworkRequesterError; use nym_bin_common::output_format::OutputFormat; -use nym_client_core::cli_helpers::client_add_gateway::{add_gateway, CommonClientAddGatewayArgs}; +use nym_client_core::cli_helpers::client_add_gateway::{CommonClientAddGatewayArgs, add_gateway}; #[derive(clap::Args)] pub(crate) struct Args { diff --git a/service-providers/network-requester/src/cli/ecash/import_coin_index_signatures.rs b/service-providers/network-requester/src/cli/ecash/import_coin_index_signatures.rs index d9fa9aad3c..e64995fe3a 100644 --- a/service-providers/network-requester/src/cli/ecash/import_coin_index_signatures.rs +++ b/service-providers/network-requester/src/cli/ecash/import_coin_index_signatures.rs @@ -4,7 +4,7 @@ use crate::cli::CliNetworkRequesterClient; use crate::error::NetworkRequesterError; use nym_client_core::cli_helpers::client_import_coin_index_signatures::{ - import_coin_index_signatures, CommonClientImportCoinIndexSignaturesArgs, + CommonClientImportCoinIndexSignaturesArgs, import_coin_index_signatures, }; pub(crate) async fn execute( diff --git a/service-providers/network-requester/src/cli/ecash/import_credential.rs b/service-providers/network-requester/src/cli/ecash/import_credential.rs index 28b9e39545..c54494bd37 100644 --- a/service-providers/network-requester/src/cli/ecash/import_credential.rs +++ b/service-providers/network-requester/src/cli/ecash/import_credential.rs @@ -4,7 +4,7 @@ use crate::cli::CliNetworkRequesterClient; use crate::error::NetworkRequesterError; use nym_client_core::cli_helpers::client_import_credential::{ - import_credential, CommonClientImportTicketBookArgs, + CommonClientImportTicketBookArgs, import_credential, }; pub async fn execute(args: CommonClientImportTicketBookArgs) -> Result<(), NetworkRequesterError> { diff --git a/service-providers/network-requester/src/cli/ecash/import_expiration_date_signatures.rs b/service-providers/network-requester/src/cli/ecash/import_expiration_date_signatures.rs index 059df07e76..eb2c1c8b18 100644 --- a/service-providers/network-requester/src/cli/ecash/import_expiration_date_signatures.rs +++ b/service-providers/network-requester/src/cli/ecash/import_expiration_date_signatures.rs @@ -4,7 +4,7 @@ use crate::cli::CliNetworkRequesterClient; use crate::error::NetworkRequesterError; use nym_client_core::cli_helpers::client_import_expiration_date_signatures::{ - import_expiration_date_signatures, CommonClientImportExpirationDateSignaturesArgs, + CommonClientImportExpirationDateSignaturesArgs, import_expiration_date_signatures, }; pub(crate) async fn execute( diff --git a/service-providers/network-requester/src/cli/ecash/import_master_verification_key.rs b/service-providers/network-requester/src/cli/ecash/import_master_verification_key.rs index 4283291b76..5b6ff16886 100644 --- a/service-providers/network-requester/src/cli/ecash/import_master_verification_key.rs +++ b/service-providers/network-requester/src/cli/ecash/import_master_verification_key.rs @@ -4,7 +4,7 @@ use crate::cli::CliNetworkRequesterClient; use crate::error::NetworkRequesterError; use nym_client_core::cli_helpers::client_import_master_verification_key::{ - import_master_verification_key, CommonClientImportMasterVerificationKeyArgs, + CommonClientImportMasterVerificationKeyArgs, import_master_verification_key, }; pub(crate) async fn execute( diff --git a/service-providers/network-requester/src/cli/ecash/show_ticketbooks.rs b/service-providers/network-requester/src/cli/ecash/show_ticketbooks.rs index b0e7f2febd..a95d74134a 100644 --- a/service-providers/network-requester/src/cli/ecash/show_ticketbooks.rs +++ b/service-providers/network-requester/src/cli/ecash/show_ticketbooks.rs @@ -5,7 +5,7 @@ use crate::cli::CliNetworkRequesterClient; use crate::error::NetworkRequesterError; use nym_bin_common::output_format::OutputFormat; use nym_client_core::cli_helpers::client_show_ticketbooks::{ - show_ticketbooks, CommonShowTicketbooksArgs, + CommonShowTicketbooksArgs, show_ticketbooks, }; #[derive(clap::Args)] diff --git a/service-providers/network-requester/src/cli/init.rs b/service-providers/network-requester/src/cli/init.rs index 9d6da8f3ea..f5e9d5a451 100644 --- a/service-providers/network-requester/src/cli/init.rs +++ b/service-providers/network-requester/src/cli/init.rs @@ -4,14 +4,14 @@ use crate::cli::CliNetworkRequesterClient; use crate::config::{default_config_directory, default_config_filepath, default_data_directory}; use crate::{ - cli::{override_config, OverrideConfig}, + cli::{OverrideConfig, override_config}, config::Config, error::NetworkRequesterError, }; use clap::Args; use nym_bin_common::output_format::OutputFormat; use nym_client_core::cli_helpers::client_init::{ - initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient, + CommonClientInitArgs, InitResultsWithConfig, InitialisableClient, initialise_client, }; use serde::Serialize; use std::fmt::Display; diff --git a/service-providers/network-requester/src/cli/list_gateways.rs b/service-providers/network-requester/src/cli/list_gateways.rs index ec4703045b..0f7b76468a 100644 --- a/service-providers/network-requester/src/cli/list_gateways.rs +++ b/service-providers/network-requester/src/cli/list_gateways.rs @@ -5,7 +5,7 @@ use crate::cli::CliNetworkRequesterClient; use crate::error::NetworkRequesterError; use nym_bin_common::output_format::OutputFormat; use nym_client_core::cli_helpers::client_list_gateways::{ - list_gateways, CommonClientListGatewaysArgs, + CommonClientListGatewaysArgs, list_gateways, }; #[derive(clap::Args)] diff --git a/service-providers/network-requester/src/cli/mod.rs b/service-providers/network-requester/src/cli/mod.rs index c647913ea6..98d008d3ac 100644 --- a/service-providers/network-requester/src/cli/mod.rs +++ b/service-providers/network-requester/src/cli/mod.rs @@ -10,7 +10,7 @@ use crate::{ use clap::{CommandFactory, Parser, Subcommand}; use log::error; use nym_bin_common::bin_info; -use nym_bin_common::completions::{fig_generate, ArgShell}; +use nym_bin_common::completions::{ArgShell, fig_generate}; use nym_client_core::cli_helpers::CliClient; use nym_config::OptionalSet; use std::sync::OnceLock; @@ -174,7 +174,9 @@ async fn try_load_current_config(id: &str) -> Result cfg, Err(err) => { - error!("Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})"); + error!( + "Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})" + ); return Err(NetworkRequesterError::FailedToLoadConfig(id.to_string())); } }; diff --git a/service-providers/network-requester/src/cli/run.rs b/service-providers/network-requester/src/cli/run.rs index 3cb96948d0..9933cbe160 100644 --- a/service-providers/network-requester/src/cli/run.rs +++ b/service-providers/network-requester/src/cli/run.rs @@ -3,7 +3,7 @@ use crate::cli::try_load_current_config; use crate::{ - cli::{override_config, OverrideConfig}, + cli::{OverrideConfig, override_config}, error::NetworkRequesterError, }; use clap::Args; diff --git a/service-providers/network-requester/src/cli/sign.rs b/service-providers/network-requester/src/cli/sign.rs index d74ac44af2..42d4c20b5d 100644 --- a/service-providers/network-requester/src/cli/sign.rs +++ b/service-providers/network-requester/src/cli/sign.rs @@ -33,7 +33,9 @@ fn print_signed_contract_msg( eprintln!(">>> attempting to sign {trimmed}"); let Ok(decoded) = bs58::decode(trimmed).into_vec() else { - println!("it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters"); + println!( + "it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters" + ); return; }; @@ -42,7 +44,9 @@ fn print_signed_contract_msg( // we don't really care about what particular information is embedded inside of it, // we just want to know if user correctly copied the string, i.e. whether it's a valid bs58 encoded json if serde_json::from_slice::(&decoded).is_err() { - println!("it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters"); + println!( + "it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters" + ); return; }; diff --git a/service-providers/network-requester/src/cli/switch_gateway.rs b/service-providers/network-requester/src/cli/switch_gateway.rs index 7496fc0018..e283fde096 100644 --- a/service-providers/network-requester/src/cli/switch_gateway.rs +++ b/service-providers/network-requester/src/cli/switch_gateway.rs @@ -4,7 +4,7 @@ use crate::cli::CliNetworkRequesterClient; use crate::error::NetworkRequesterError; use nym_client_core::cli_helpers::client_switch_gateway::{ - switch_gateway, CommonClientSwitchGatewaysArgs, + CommonClientSwitchGatewaysArgs, switch_gateway, }; #[derive(clap::Args, Clone, Debug)] diff --git a/service-providers/network-requester/src/config/helpers.rs b/service-providers/network-requester/src/config/helpers.rs index 3655b9ea76..8973dff06a 100644 --- a/service-providers/network-requester/src/config/helpers.rs +++ b/service-providers/network-requester/src/config/helpers.rs @@ -1,6 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::config::Config; use crate::config::default_config_filepath; use crate::config::old::v6::ConfigV6; use crate::config::old_config_v1_1_13::OldConfigV1; @@ -8,7 +9,6 @@ use crate::config::old_config_v1_1_20::ConfigV2; use crate::config::old_config_v1_1_20_2::ConfigV3; use crate::config::old_config_v1_1_33::ConfigV4; use crate::config::old_config_v1_1_54::ConfigV5; -use crate::config::Config; use crate::error::NetworkRequesterError; use log::{info, trace}; use nym_client_core::cli_helpers::CliClientConfig; diff --git a/service-providers/network-requester/src/config/mod.rs b/service-providers/network-requester/src/config/mod.rs index 6284186c95..635e7f16b0 100644 --- a/service-providers/network-requester/src/config/mod.rs +++ b/service-providers/network-requester/src/config/mod.rs @@ -6,9 +6,9 @@ use nym_bin_common::logging::LoggingSettings; use nym_client_core::cli_helpers::CliClientConfig; use nym_client_core::config::disk_persistence::CommonClientPaths; use nym_config::{ - must_get_home, read_config_from_toml_file, save_formatted_config_to_file, - serde_helpers::de_maybe_stringified, NymConfigTemplate, OptionalSet, DEFAULT_CONFIG_DIR, - DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, + DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, NymConfigTemplate, + OptionalSet, must_get_home, read_config_from_toml_file, save_formatted_config_to_file, + serde_helpers::de_maybe_stringified, }; use nym_network_defaults::mainnet; use nym_service_providers_common::DEFAULT_SERVICE_PROVIDERS_DIR; diff --git a/service-providers/network-requester/src/config/old/v3.rs b/service-providers/network-requester/src/config/old/v3.rs index aa86eb7819..d8bb03df40 100644 --- a/service-providers/network-requester/src/config/old/v3.rs +++ b/service-providers/network-requester/src/config/old/v3.rs @@ -3,7 +3,7 @@ use super::v4::{ConfigV4, DebugV4, NetworkRequesterV4}; use crate::config::persistence::old::v1::NetworkRequesterPathsV1; -use crate::config::persistence::old::v2::{NetworkRequesterPathsV2, DEFAULT_DESCRIPTION_FILENAME}; +use crate::config::persistence::old::v2::{DEFAULT_DESCRIPTION_FILENAME, NetworkRequesterPathsV2}; use crate::{config::default_config_filepath, error::NetworkRequesterError}; use log::trace; use nym_bin_common::logging::LoggingSettings; diff --git a/service-providers/network-requester/src/config/old/v5.rs b/service-providers/network-requester/src/config/old/v5.rs index d8b4c6d99d..6e6d5de055 100644 --- a/service-providers/network-requester/src/config/old/v5.rs +++ b/service-providers/network-requester/src/config/old/v5.rs @@ -1,9 +1,9 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::persistence::old::v3::NetworkRequesterPathsV3; use crate::config::persistence::NetworkRequesterPaths; -use crate::config::{default_config_filepath, Debug, NetworkRequester}; +use crate::config::persistence::old::v3::NetworkRequesterPathsV3; +use crate::config::{Debug, NetworkRequester, default_config_filepath}; use nym_bin_common::logging::LoggingSettings; use nym_client_core::config::old_config_v1_1_54::ConfigV1_1_54 as BaseConfigV1_1_54; use nym_config::read_config_from_toml_file; diff --git a/service-providers/network-requester/src/config/old/v6.rs b/service-providers/network-requester/src/config/old/v6.rs index f50e4ddb77..a70315ce2c 100644 --- a/service-providers/network-requester/src/config/old/v6.rs +++ b/service-providers/network-requester/src/config/old/v6.rs @@ -6,7 +6,7 @@ use nym_config::read_config_from_toml_file; use serde::{Deserialize, Serialize}; use crate::config::{ - default_config_filepath, Config, Debug, NetworkRequester, NetworkRequesterPaths, + Config, Debug, NetworkRequester, NetworkRequesterPaths, default_config_filepath, }; #[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index 3bf865a91b..6ca9b3b588 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -11,15 +11,15 @@ use futures::channel::{mpsc, oneshot}; use futures::stream::StreamExt; use log::{debug, error, warn}; use nym_bin_common::bin_info_owned; +use nym_client_core::HardcodedTopologyProvider; use nym_client_core::client::mix_traffic::transceiver::GatewayTransceiver; use nym_client_core::config::disk_persistence::CommonClientPaths; -use nym_client_core::HardcodedTopologyProvider; use nym_network_defaults::NymNetworkDetails; use nym_sdk::mixnet::{MixnetMessageSender, TopologyProvider}; +use nym_service_providers_common::ServiceProvider; use nym_service_providers_common::interface::{ BinaryInformation, ProviderInterfaceVersion, Request, RequestVersion, }; -use nym_service_providers_common::ServiceProvider; use nym_socks5_proxy_helpers::connection_controller::{ Controller, ControllerCommand, ControllerSender, }; @@ -33,8 +33,8 @@ use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx::params::{PacketSize, PacketType}; use nym_sphinx::receiver::ReconstructedMessage; -use nym_task::connections::LaneQueueLengths; use nym_task::ShutdownTracker; +use nym_task::connections::LaneQueueLengths; use std::path::Path; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -101,7 +101,9 @@ impl ServiceProvider for NRServiceProvider { .await .expect("InputMessageReceiver has stopped receiving!"); } else { - warn!("currently we can only send generic replies via reply surbs and we haven't got any : (") + warn!( + "currently we can only send generic replies via reply surbs and we haven't got any : (" + ) } } Ok(()) diff --git a/service-providers/network-requester/src/error.rs b/service-providers/network-requester/src/error.rs index e4870d64c8..5532f1ecca 100644 --- a/service-providers/network-requester/src/error.rs +++ b/service-providers/network-requester/src/error.rs @@ -49,7 +49,9 @@ pub enum NetworkRequesterError { source: std::io::Error, }, - #[error("the provided address: '{remote}' was somehow resolved to an empty list of socket addresses")] + #[error( + "the provided address: '{remote}' was somehow resolved to an empty list of socket addresses" + )] EmptyResolvedAddresses { remote: RemoteAddress }, #[error("failed to apply the exit policy: {source}")] diff --git a/service-providers/network-requester/src/lib.rs b/service-providers/network-requester/src/lib.rs index bd1f8582e9..a11606b942 100644 --- a/service-providers/network-requester/src/lib.rs +++ b/service-providers/network-requester/src/lib.rs @@ -15,11 +15,11 @@ pub use nym_client_core::{ base_client::{ non_wasm_helpers::{setup_fs_gateways_storage, setup_fs_reply_surb_backend}, storage::{ + GatewaysDetailsStore, OnDiskGatewaysDetails, OnDiskPersistent, gateways_storage::{ CustomGatewayDetails, GatewayDetails, GatewayRegistration, RemoteGatewayDetails, }, helpers::{set_active_gateway, store_gateway_details}, - GatewaysDetailsStore, OnDiskGatewaysDetails, OnDiskPersistent, }, }, key_manager::persistence::OnDiskKeys, diff --git a/service-providers/network-requester/src/main.rs b/service-providers/network-requester/src/main.rs index 686019b575..3d53d0fb93 100644 --- a/service-providers/network-requester/src/main.rs +++ b/service-providers/network-requester/src/main.rs @@ -1,7 +1,7 @@ // Copyright 2020 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use clap::{crate_name, crate_version, Parser}; +use clap::{Parser, crate_name, crate_version}; use nym_bin_common::logging::{maybe_print_banner, setup_tracing_logger}; use nym_network_defaults::setup_env; 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 d3c3a99681..140091625e 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 @@ -4,8 +4,8 @@ use crate::config::Config; use crate::error::NetworkRequesterError; use log::trace; -use nym_exit_policy::client::get_exit_policy; use nym_exit_policy::ExitPolicy; +use nym_exit_policy::client::get_exit_policy; use nym_socks5_requests::RemoteAddress; use reqwest::IntoUrl; use tokio::net::lookup_host; diff --git a/service-providers/network-requester/src/socks5/tcp.rs b/service-providers/network-requester/src/socks5/tcp.rs index 63f6f249f3..7eb593facd 100644 --- a/service-providers/network-requester/src/socks5/tcp.rs +++ b/service-providers/network-requester/src/socks5/tcp.rs @@ -8,8 +8,8 @@ use nym_socks5_proxy_helpers::connection_controller::ConnectionReceiver; use nym_socks5_proxy_helpers::proxy_runner::{MixProxySender, ProxyRunner}; use nym_socks5_requests::{ConnectionId, RemoteAddress, Socks5Request}; use nym_sphinx::params::PacketSize; -use nym_task::connections::LaneQueueLengths; use nym_task::ShutdownTracker; +use nym_task::connections::LaneQueueLengths; use std::io; use tokio::net::TcpStream; diff --git a/tools/echo-server/src/lib.rs b/tools/echo-server/src/lib.rs index 4630e979dd..0fdfc7c097 100644 --- a/tools/echo-server/src/lib.rs +++ b/tools/echo-server/src/lib.rs @@ -7,14 +7,14 @@ use nym_sdk::{mixnet::Recipient, tcp_proxy, tcp_proxy::NymProxyServer}; use std::{ fmt::Debug, sync::{ - atomic::{AtomicU64, Ordering}, Arc, + atomic::{AtomicU64, Ordering}, }, }; use tokio::{ io::AsyncWriteExt, net::{TcpListener, TcpStream}, - sync::{broadcast, Mutex}, + sync::{Mutex, broadcast}, task, }; use tokio_stream::StreamExt; diff --git a/tools/internal/contract-state-importer/importer-cli/src/commands/initialise_mixnet_vesting_with_states.rs b/tools/internal/contract-state-importer/importer-cli/src/commands/initialise_mixnet_vesting_with_states.rs index 9f4d8ee349..7b0169d9f2 100644 --- a/tools/internal/contract-state-importer/importer-cli/src/commands/initialise_mixnet_vesting_with_states.rs +++ b/tools/internal/contract-state-importer/importer-cli/src/commands/initialise_mixnet_vesting_with_states.rs @@ -8,8 +8,8 @@ use crate::helpers::{mixnet_contract_path, vesting_contract_path}; use clap::Args; use importer_contract::ExecuteMsg; use nym_mixnet_contract_common::{Addr, ContractState}; -use nym_validator_client::nyxd::{AccountId, CosmWasmClient}; use nym_validator_client::DirectSigningHttpRpcNyxdClient; +use nym_validator_client::nyxd::{AccountId, CosmWasmClient}; use serde::Serialize; use std::path::PathBuf; use tracing::info; diff --git a/tools/internal/contract-state-importer/importer-cli/src/commands/mod.rs b/tools/internal/contract-state-importer/importer-cli/src/commands/mod.rs index e7dacbbea1..e429c7a2aa 100644 --- a/tools/internal/contract-state-importer/importer-cli/src/commands/mod.rs +++ b/tools/internal/contract-state-importer/importer-cli/src/commands/mod.rs @@ -2,16 +2,16 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::commands::initialise_mixnet_vesting_with_states::{ - execute_initialise_mixnet_vesting_with_states, InitialiseMixnetVestingWithStatesArgs, + InitialiseMixnetVestingWithStatesArgs, execute_initialise_mixnet_vesting_with_states, }; -use crate::commands::initialise_with_state::{initialise_with_state, InitialiseWithStateArgs}; -use crate::commands::prepare::{execute_prepare_contract, PrepareArgs}; -use crate::commands::set_state::{execute_set_state, SetStateArgs}; -use crate::commands::swap_contract::{execute_swap_contract, SwapContractArgs}; +use crate::commands::initialise_with_state::{InitialiseWithStateArgs, initialise_with_state}; +use crate::commands::prepare::{PrepareArgs, execute_prepare_contract}; +use crate::commands::set_state::{SetStateArgs, execute_set_state}; +use crate::commands::swap_contract::{SwapContractArgs, execute_swap_contract}; use clap::{Parser, Subcommand}; use nym_bin_common::bin_info; use nym_network_defaults::NymNetworkDetails; -use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient}; +use nym_validator_client::{DirectSigningHttpRpcNyxdClient, nyxd}; use std::path::PathBuf; use std::sync::OnceLock; diff --git a/tools/internal/contract-state-importer/importer-cli/src/commands/prepare.rs b/tools/internal/contract-state-importer/importer-cli/src/commands/prepare.rs index 40856ff3f4..09106f35d3 100644 --- a/tools/internal/contract-state-importer/importer-cli/src/commands/prepare.rs +++ b/tools/internal/contract-state-importer/importer-cli/src/commands/prepare.rs @@ -5,9 +5,9 @@ use crate::helpers::importer_contract_path; use crate::state::CachedState; use clap::Args; use importer_contract::contract::EmptyMessage; -use nym_validator_client::nyxd::cosmwasm_client::types::InstantiateOptions; -use nym_validator_client::nyxd::AccountId; use nym_validator_client::DirectSigningHttpRpcNyxdClient; +use nym_validator_client::nyxd::AccountId; +use nym_validator_client::nyxd::cosmwasm_client::types::InstantiateOptions; use std::fs; use std::fs::File; use std::io::Read; diff --git a/tools/internal/contract-state-importer/importer-cli/src/commands/set_state.rs b/tools/internal/contract-state-importer/importer-cli/src/commands/set_state.rs index 0989243202..07026012b1 100644 --- a/tools/internal/contract-state-importer/importer-cli/src/commands/set_state.rs +++ b/tools/internal/contract-state-importer/importer-cli/src/commands/set_state.rs @@ -5,10 +5,10 @@ use crate::helpers::importer_contract_address; use crate::state::CachedState; use anyhow::bail; use clap::Args; -use importer_contract::{base85rs, ExecuteMsg}; -use nym_validator_client::nyxd::cosmwasm_client::types::Model; -use nym_validator_client::nyxd::AccountId; +use importer_contract::{ExecuteMsg, base85rs}; use nym_validator_client::DirectSigningHttpRpcNyxdClient; +use nym_validator_client::nyxd::AccountId; +use nym_validator_client::nyxd::cosmwasm_client::types::Model; use std::fs::File; use std::path::PathBuf; use tracing::info; diff --git a/tools/internal/contract-state-importer/importer-cli/src/commands/swap_contract.rs b/tools/internal/contract-state-importer/importer-cli/src/commands/swap_contract.rs index da969cab40..cf1686b140 100644 --- a/tools/internal/contract-state-importer/importer-cli/src/commands/swap_contract.rs +++ b/tools/internal/contract-state-importer/importer-cli/src/commands/swap_contract.rs @@ -6,8 +6,8 @@ use crate::state::CachedState; use anyhow::bail; use clap::ArgGroup; use clap::Args; -use nym_validator_client::nyxd::AccountId; use nym_validator_client::DirectSigningHttpRpcNyxdClient; +use nym_validator_client::nyxd::AccountId; use std::fs::File; use std::io::Read; use std::path::PathBuf; diff --git a/tools/internal/contract-state-importer/importer-cli/src/helpers.rs b/tools/internal/contract-state-importer/importer-cli/src/helpers.rs index ad25324f4b..8190556f55 100644 --- a/tools/internal/contract-state-importer/importer-cli/src/helpers.rs +++ b/tools/internal/contract-state-importer/importer-cli/src/helpers.rs @@ -3,10 +3,10 @@ use crate::state::CachedState; use anyhow::bail; -use nym_validator_client::nyxd::cosmwasm_client::types::Model; use nym_validator_client::nyxd::AccountId; -use serde::de::DeserializeOwned; +use nym_validator_client::nyxd::cosmwasm_client::types::Model; use serde::Serialize; +use serde::de::DeserializeOwned; use std::env::current_dir; use std::fs; use std::path::PathBuf; diff --git a/tools/internal/contract-state-importer/importer-cli/src/state.rs b/tools/internal/contract-state-importer/importer-cli/src/state.rs index 499632d543..7e839fe8d5 100644 --- a/tools/internal/contract-state-importer/importer-cli/src/state.rs +++ b/tools/internal/contract-state-importer/importer-cli/src/state.rs @@ -3,7 +3,7 @@ use nym_validator_client::nyxd::AccountId; use serde::{Deserialize, Serialize}; -use std::fs::{create_dir_all, File}; +use std::fs::{File, create_dir_all}; use std::path::PathBuf; use tracing::info; diff --git a/tools/internal/mixnet-connectivity-check/src/main.rs b/tools/internal/mixnet-connectivity-check/src/main.rs index 4dd68a61ab..79af693b0a 100644 --- a/tools/internal/mixnet-connectivity-check/src/main.rs +++ b/tools/internal/mixnet-connectivity-check/src/main.rs @@ -8,7 +8,7 @@ use nym_bin_common::{bin_info, bin_info_owned}; use nym_crypto::asymmetric::ed25519; use nym_network_defaults::setup_env; use nym_sdk::mixnet::MixnetMessageSender; -use nym_sdk::{mixnet, DebugConfig}; +use nym_sdk::{DebugConfig, mixnet}; use std::sync::OnceLock; use std::time::Duration; use tokio::time::timeout; diff --git a/tools/internal/testnet-manager/src/cli/load_network_details.rs b/tools/internal/testnet-manager/src/cli/load_network_details.rs index 657b68ce1a..414c7984e1 100644 --- a/tools/internal/testnet-manager/src/cli/load_network_details.rs +++ b/tools/internal/testnet-manager/src/cli/load_network_details.rs @@ -3,8 +3,8 @@ use crate::error::NetworkManagerError; use crate::helpers::default_db_file; -use crate::manager::env::Env; use crate::manager::NetworkManager; +use crate::manager::env::Env; use nym_bin_common::output_format::OutputFormat; use std::path::PathBuf; diff --git a/tools/internal/testnet-manager/src/error.rs b/tools/internal/testnet-manager/src/error.rs index 42dd29b2d6..0a656c068b 100644 --- a/tools/internal/testnet-manager/src/error.rs +++ b/tools/internal/testnet-manager/src/error.rs @@ -15,7 +15,9 @@ pub enum NetworkManagerError { #[error("failed to parse the url: {0}")] MalformedUrl(#[from] url::ParseError), - #[error("one of the account addresses was malformed - the developer was too lazy to propagate the actual error message with the address")] + #[error( + "one of the account addresses was malformed - the developer was too lazy to propagate the actual error message with the address" + )] MalformedAccountAddress, #[error(transparent)] @@ -48,7 +50,9 @@ pub enum NetworkManagerError { #[error("could not find build information for {name} contract")] ContractNotQueried { name: String }, - #[error("contract {name} has been build before build information got standarised. this is not supported")] + #[error( + "contract {name} has been build before build information got standarised. this is not supported" + )] MissingBuildInfo { name: String }, #[error("there aren't any initialised networks in the storage")] @@ -98,10 +102,14 @@ pub enum NetworkManagerError { #[error("the default, pre-generated, .env file does not have the nym-api endpoint set!")] NymApiEndpointMissing, - #[error("timed out while waiting for some gateway to appear in the directory (you don't need to run it)")] + #[error( + "timed out while waiting for some gateway to appear in the directory (you don't need to run it)" + )] ApiGatewayWaitTimeout, - #[error("timed out while waiting for the gateway to start receiving traffic (you need to actually run it!)")] + #[error( + "timed out while waiting for the gateway to start receiving traffic (you need to actually run it!)" + )] GatewayWaitTimeout, #[error("attempted to bond nodes on a non-empty network")] diff --git a/tools/internal/testnet-manager/src/helpers.rs b/tools/internal/testnet-manager/src/helpers.rs index 0c38c8238d..8f8c6eacb0 100644 --- a/tools/internal/testnet-manager/src/helpers.rs +++ b/tools/internal/testnet-manager/src/helpers.rs @@ -3,7 +3,7 @@ use crate::error::NetworkManagerError; use indicatif::{HumanDuration, ProgressBar}; -use nym_config::{must_get_home, NYM_DIR}; +use nym_config::{NYM_DIR, must_get_home}; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::fmt::{Display, Formatter}; diff --git a/tools/internal/testnet-manager/src/manager/contract.rs b/tools/internal/testnet-manager/src/manager/contract.rs index 6328dc0b10..5792dbd23e 100644 --- a/tools/internal/testnet-manager/src/manager/contract.rs +++ b/tools/internal/testnet-manager/src/manager/contract.rs @@ -2,11 +2,11 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::error::NetworkManagerError; use nym_mixnet_contract_common::ContractBuildInformation; +use nym_validator_client::DirectSecp256k1HdWallet; use nym_validator_client::nyxd::cosmwasm_client::types::{ ContractCodeId, InstantiateResult, MigrateResult, UploadResult, }; use nym_validator_client::nyxd::{AccountId, Hash}; -use nym_validator_client::DirectSecp256k1HdWallet; use serde::{Deserialize, Serialize}; use std::path::{Path, PathBuf}; diff --git a/tools/internal/testnet-manager/src/manager/dkg_skip.rs b/tools/internal/testnet-manager/src/manager/dkg_skip.rs index 9f87a468fa..13126125b2 100644 --- a/tools/internal/testnet-manager/src/manager/dkg_skip.rs +++ b/tools/internal/testnet-manager/src/manager/dkg_skip.rs @@ -3,23 +3,23 @@ use crate::error::NetworkManagerError; use crate::helpers::{ProgressCtx, ProgressTracker}; +use crate::manager::NetworkManager; use crate::manager::contract::Account; use crate::manager::network::LoadedNetwork; -use crate::manager::NetworkManager; use console::style; use dkg_bypass_contract::msg::FakeDealerData; -use nym_compact_ecash::{ttp_keygen, Base58, KeyPairAuth}; +use nym_compact_ecash::{Base58, KeyPairAuth, ttp_keygen}; use nym_crypto::asymmetric::ed25519; use nym_mixnet_contract_common::Addr; use nym_pemstore::traits::PemStorableKey; -use nym_pemstore::{store_key, store_keypair, KeyPairPath}; +use nym_pemstore::{KeyPairPath, store_key, store_keypair}; +use nym_validator_client::DirectSigningHttpRpcNyxdClient; use nym_validator_client::nyxd::contract_traits::{ DkgQueryClient, GroupSigningClient, PagedGroupQueryClient, }; use nym_validator_client::nyxd::cosmwasm::ContractCodeId; use nym_validator_client::nyxd::cw4::Member; use nym_validator_client::nyxd::{AccountId, CosmWasmClient}; -use nym_validator_client::DirectSigningHttpRpcNyxdClient; use rand::rngs::OsRng; use std::fs; use std::ops::Deref; diff --git a/tools/internal/testnet-manager/src/manager/local_apis.rs b/tools/internal/testnet-manager/src/manager/local_apis.rs index 7da09928c3..e54e458927 100644 --- a/tools/internal/testnet-manager/src/manager/local_apis.rs +++ b/tools/internal/testnet-manager/src/manager/local_apis.rs @@ -3,13 +3,13 @@ use crate::error::NetworkManagerError; use crate::helpers::{ProgressCtx, ProgressTracker, RunCommands}; +use crate::manager::NetworkManager; use crate::manager::dkg_skip::EcashSignerWithPaths; use crate::manager::env::Env; use crate::manager::network::LoadedNetwork; -use crate::manager::NetworkManager; use console::style; use nym_config::{ - must_get_home, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_NYM_APIS_DIR, NYM_DIR, + DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_NYM_APIS_DIR, NYM_DIR, must_get_home, }; use std::fs; use std::path::{Path, PathBuf}; diff --git a/tools/internal/testnet-manager/src/manager/local_client.rs b/tools/internal/testnet-manager/src/manager/local_client.rs index 8004c658df..8e3aff09c0 100644 --- a/tools/internal/testnet-manager/src/manager/local_client.rs +++ b/tools/internal/testnet-manager/src/manager/local_client.rs @@ -3,12 +3,12 @@ use crate::error::NetworkManagerError; use crate::helpers::{ProgressCtx, ProgressTracker}; -use crate::manager::network::LoadedNetwork; use crate::manager::NetworkManager; +use crate::manager::network::LoadedNetwork; use console::style; -use nym_config::{must_get_home, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, NYM_DIR}; +use nym_config::{DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, NYM_DIR, must_get_home}; use nym_validator_client::nym_api::NymApiClientExt; -use rand::{thread_rng, RngCore}; +use rand::{RngCore, thread_rng}; use std::fs; use std::fs::OpenOptions; use std::io::prelude::*; diff --git a/tools/internal/testnet-manager/src/manager/local_nodes.rs b/tools/internal/testnet-manager/src/manager/local_nodes.rs index e029e9f0f4..f710939248 100644 --- a/tools/internal/testnet-manager/src/manager/local_nodes.rs +++ b/tools/internal/testnet-manager/src/manager/local_nodes.rs @@ -3,17 +3,17 @@ use crate::error::NetworkManagerError; use crate::helpers::{ProgressCtx, ProgressTracker, RunCommands}; +use crate::manager::NetworkManager; use crate::manager::network::LoadedNetwork; use crate::manager::node::NymNode; -use crate::manager::NetworkManager; use console::style; use nym_crypto::asymmetric::ed25519; -use nym_mixnet_contract_common::nym_node::Role; use nym_mixnet_contract_common::RoleAssignment; +use nym_mixnet_contract_common::nym_node::Role; +use nym_validator_client::DirectSigningHttpRpcNyxdClient; use nym_validator_client::nyxd::contract_traits::{ MixnetQueryClient, MixnetSigningClient, PagedMixnetQueryClient, }; -use nym_validator_client::DirectSigningHttpRpcNyxdClient; use serde::{Deserialize, Serialize}; use std::fs; use std::ops::Deref; diff --git a/tools/internal/testnet-manager/src/manager/mod.rs b/tools/internal/testnet-manager/src/manager/mod.rs index d7499328e2..12b657bf24 100644 --- a/tools/internal/testnet-manager/src/manager/mod.rs +++ b/tools/internal/testnet-manager/src/manager/mod.rs @@ -9,8 +9,8 @@ use bip39::rand::prelude::SliceRandom; use bip39::rand::thread_rng; use indicatif::ProgressBar; use nym_config::defaults::NymNetworkDetails; -use nym_validator_client::nyxd::cosmwasm_client::types::UploadResult; use nym_validator_client::nyxd::Config; +use nym_validator_client::nyxd::cosmwasm_client::types::UploadResult; use nym_validator_client::{DirectSigningHttpRpcNyxdClient, QueryHttpRpcNyxdClient}; use std::path::{Path, PathBuf}; use url::Url; diff --git a/tools/internal/testnet-manager/src/manager/network_init.rs b/tools/internal/testnet-manager/src/manager/network_init.rs index 44c5a97335..a0be659d7d 100644 --- a/tools/internal/testnet-manager/src/manager/network_init.rs +++ b/tools/internal/testnet-manager/src/manager/network_init.rs @@ -2,10 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 use crate::error::NetworkManagerError; -use crate::helpers::{async_with_progress, ProgressCtx, ProgressTracker}; +use crate::helpers::{ProgressCtx, ProgressTracker, async_with_progress}; +use crate::manager::NetworkManager; use crate::manager::contract::Account; use crate::manager::network::Network; -use crate::manager::NetworkManager; use console::style; use cw_utils::Threshold; use indicatif::HumanDuration; @@ -13,14 +13,14 @@ use nym_coconut_dkg_common::types::TimeConfiguration; use nym_config::defaults::NymNetworkDetails; use nym_mixnet_contract_common::reward_params::RewardedSetParams; use nym_mixnet_contract_common::{Decimal, InitialRewardingParams, Percent}; -use nym_validator_client::nyxd::cosmwasm_client::types::InstantiateOptions; -use nym_validator_client::nyxd::Config; use nym_validator_client::DirectSigningHttpRpcNyxdClient; +use nym_validator_client::nyxd::Config; +use nym_validator_client::nyxd::cosmwasm_client::types::InstantiateOptions; use std::ops::Deref; use std::path::Path; use std::time::Duration; -use time::format_description::well_known::Rfc3339; use time::OffsetDateTime; +use time::format_description::well_known::Rfc3339; use url::Url; struct InitCtx { diff --git a/tools/internal/testnet-manager/src/manager/node.rs b/tools/internal/testnet-manager/src/manager/node.rs index 5728c8c871..8eab0c6499 100644 --- a/tools/internal/testnet-manager/src/manager/node.rs +++ b/tools/internal/testnet-manager/src/manager/node.rs @@ -3,9 +3,9 @@ use crate::manager::contract::Account; use nym_coconut_dkg_common::types::Addr; -use nym_contracts_common::signing::MessageSignature; use nym_contracts_common::Percent; -use nym_mixnet_contract_common::{construct_nym_node_bonding_sign_payload, NodeCostParams}; +use nym_contracts_common::signing::MessageSignature; +use nym_mixnet_contract_common::{NodeCostParams, construct_nym_node_bonding_sign_payload}; use nym_validator_client::nyxd::CosmWasmCoin; pub(crate) struct NymNode { diff --git a/tools/internal/testnet-manager/src/manager/storage/mod.rs b/tools/internal/testnet-manager/src/manager/storage/mod.rs index 21c85df32e..8067a9ea3c 100644 --- a/tools/internal/testnet-manager/src/manager/storage/mod.rs +++ b/tools/internal/testnet-manager/src/manager/storage/mod.rs @@ -11,8 +11,8 @@ use crate::{ }, }; use sqlx::{ - sqlite::{SqliteAutoVacuum, SqliteSynchronous}, ConnectOptions, + sqlite::{SqliteAutoVacuum, SqliteSynchronous}, }; use std::fs; use std::path::Path; diff --git a/tools/internal/validator-status-check/src/helpers.rs b/tools/internal/validator-status-check/src/helpers.rs index feb4dd488e..c61a493829 100644 --- a/tools/internal/validator-status-check/src/helpers.rs +++ b/tools/internal/validator-status-check/src/helpers.rs @@ -4,10 +4,10 @@ use crate::models::SignerStatus; use anyhow::bail; use nym_network_defaults::NymNetworkDetails; -use nym_validator_client::nyxd::contract_traits::dkg_query_client::DealerDetails; -use nym_validator_client::nyxd::contract_traits::PagedDkgQueryClient; -use nym_validator_client::nyxd::Config; use nym_validator_client::QueryHttpRpcNyxdClient; +use nym_validator_client::nyxd::Config; +use nym_validator_client::nyxd::contract_traits::PagedDkgQueryClient; +use nym_validator_client::nyxd::contract_traits::dkg_query_client::DealerDetails; use tracing::info; async fn get_query_client() -> anyhow::Result { diff --git a/tools/nymvisor/src/cli/add_upgrade.rs b/tools/nymvisor/src/cli/add_upgrade.rs index 06e1717ebd..6e1906e737 100644 --- a/tools/nymvisor/src/cli/add_upgrade.rs +++ b/tools/nymvisor/src/cli/add_upgrade.rs @@ -11,8 +11,8 @@ use crate::upgrades::types::{UpgradeInfo, UpgradePlan}; use nym_bin_common::output_format::OutputFormat; use std::path::PathBuf; use std::time::Duration; -use time::format_description::well_known::Rfc3339; use time::OffsetDateTime; +use time::format_description::well_known::Rfc3339; const DEFAULT_UPGRADE_DELAY: Duration = Duration::from_secs(15 * 60); diff --git a/tools/nymvisor/src/cli/init.rs b/tools/nymvisor/src/cli/init.rs index 1382a6d1b3..5fc7516ed0 100644 --- a/tools/nymvisor/src/cli/init.rs +++ b/tools/nymvisor/src/cli/init.rs @@ -3,7 +3,7 @@ use crate::cli::helpers::{copy_binary, daemon_home, use_logs}; use crate::config::{ - default_config_filepath, Config, BIN_DIR, CURRENT_VERSION_FILENAME, GENESIS_DIR, + BIN_DIR, CURRENT_VERSION_FILENAME, Config, GENESIS_DIR, default_config_filepath, }; use crate::daemon::Daemon; use crate::env::Env; @@ -260,7 +260,9 @@ fn setup_genesis( provided_genesis: Box::new(daemon_info.clone()), }) } else { - debug!("there was already a genesis daemon binary present, but it was the same as the one provided"); + debug!( + "there was already a genesis daemon binary present, but it was the same as the one provided" + ); Ok(()) }; } diff --git a/tools/nymvisor/src/cli/mod.rs b/tools/nymvisor/src/cli/mod.rs index bb90d2d15b..be1fa9a217 100644 --- a/tools/nymvisor/src/cli/mod.rs +++ b/tools/nymvisor/src/cli/mod.rs @@ -1,8 +1,8 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::{default_config_filepath, default_instances_directory, Config}; -use crate::env::{setup_env, Env}; +use crate::config::{Config, default_config_filepath, default_instances_directory}; +use crate::env::{Env, setup_env}; use crate::error::NymvisorError; use clap::{Parser, Subcommand}; use nym_bin_common::bin_info; @@ -98,7 +98,10 @@ fn open_config_file(env: &Env) -> Result { match Config::read_from_toml_file(&config_load_location) { Ok(cfg) => Ok(cfg), Err(source) => { - error!("Failed to load config from {}. Are you sure you have run `init` before? (Error was: {source})", config_load_location.display()); + error!( + "Failed to load config from {}. Are you sure you have run `init` before? (Error was: {source})", + config_load_location.display() + ); Err(NymvisorError::ConfigLoadFailure { id: env.nymvisor_id.clone().unwrap_or("UNKNOWN".to_string()), path: config_load_location, diff --git a/tools/nymvisor/src/config/mod.rs b/tools/nymvisor/src/config/mod.rs index cd907841b2..4559304c15 100644 --- a/tools/nymvisor/src/config/mod.rs +++ b/tools/nymvisor/src/config/mod.rs @@ -4,8 +4,8 @@ use crate::config::template::CONFIG_TEMPLATE; use nym_config::serde_helpers::de_maybe_stringified; use nym_config::{ - must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate, - DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, + DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, NymConfigTemplate, + must_get_home, read_config_from_toml_file, save_formatted_config_to_file, }; use serde::{Deserialize, Serialize}; use std::fmt::{Display, Formatter}; diff --git a/tools/nymvisor/src/daemon/mod.rs b/tools/nymvisor/src/daemon/mod.rs index 6c552e8238..0f7f02c50e 100644 --- a/tools/nymvisor/src/daemon/mod.rs +++ b/tools/nymvisor/src/daemon/mod.rs @@ -18,7 +18,7 @@ use std::sync::Arc; use std::task::{Context, Poll}; use std::time::Duration; use tokio::sync::Notify; -use tokio::time::{sleep, Sleep}; +use tokio::time::{Sleep, sleep}; use tracing::{debug, info, instrument, warn}; pub(crate) struct InterruptHandle(Arc); @@ -208,12 +208,14 @@ impl Future for ExecutingDaemon { } // 2. check if we reached the timeout to kill the child - if let Some(ref mut kill_timeout) = &mut self.kill_timeout { - if kill_timeout.as_mut().poll(cx).is_ready() { - warn!("reached the graceful shutdown timeout. the daemon still hasn't finished. sending SIGKILL"); - self.signal_child(Signal::SIGKILL)?; - self.kill_timeout = None; - } + if let Some(kill_timeout) = &mut self.kill_timeout + && kill_timeout.as_mut().poll(cx).is_ready() + { + warn!( + "reached the graceful shutdown timeout. the daemon still hasn't finished. sending SIGKILL" + ); + self.signal_child(Signal::SIGKILL)?; + self.kill_timeout = None; } // 3. check if we received a signal to interrupt the child diff --git a/tools/nymvisor/src/error.rs b/tools/nymvisor/src/error.rs index 5160bd3c00..9d8fbc4dac 100644 --- a/tools/nymvisor/src/error.rs +++ b/tools/nymvisor/src/error.rs @@ -139,7 +139,9 @@ While the stored info point to:\n{stored_info:#?}" stored_info: Box, }, - #[error("the daemon for upgrade '{upgrade_name}' has version {daemon_version} while {expected} was expected instead")] + #[error( + "the daemon for upgrade '{upgrade_name}' has version {daemon_version} while {expected} was expected instead" + )] UnexpectedUpgradeDaemonVersion { upgrade_name: String, daemon_version: String, @@ -226,13 +228,19 @@ While the stored info point to:\n{stored_info:#?}" source: dotenvy::Error, }, - #[error("the value provided for environmental variable '{variable}' was not valid unicode: {value:?}")] + #[error( + "the value provided for environmental variable '{variable}' was not valid unicode: {value:?}" + )] MalformedEnvVariable { variable: String, value: OsString }, - #[error("the value provided for environmental boolean variable '{variable}': '{value}' is not a valid boolean")] + #[error( + "the value provided for environmental boolean variable '{variable}': '{value}' is not a valid boolean" + )] MalformedBoolEnvVariable { variable: String, value: String }, - #[error("the value provided for environmental duration variable '{variable}': '{value}' is not a valid duration: {source}")] + #[error( + "the value provided for environmental duration variable '{variable}': '{value}' is not a valid duration: {source}" + )] MalformedDurationEnvVariable { variable: String, value: String, @@ -240,7 +248,9 @@ While the stored info point to:\n{stored_info:#?}" source: humantime::DurationError, }, - #[error("the value provided for environmental numerical variable '{variable}': '{value}' is not a valid number: {source}")] + #[error( + "the value provided for environmental numerical variable '{variable}': '{value}' is not a valid number: {source}" + )] MalformedNumberEnvVariable { variable: String, value: String, @@ -248,7 +258,9 @@ While the stored info point to:\n{stored_info:#?}" source: ParseIntError, }, - #[error("the value provided for environmental Url '{variable}': '{value}' is not a valid number: {source}")] + #[error( + "the value provided for environmental Url '{variable}': '{value}' is not a valid number: {source}" + )] MalformedUrlEnvVariable { variable: String, value: String, @@ -279,7 +291,9 @@ While the stored info point to:\n{stored_info:#?}" source: io::Error, }, - #[error("the value of daemon home has to be provided by either `--daemon-home` flag or `$DAEMON_HOME` environmental variable")] + #[error( + "the value of daemon home has to be provided by either `--daemon-home` flag or `$DAEMON_HOME` environmental variable" + )] DaemonHomeUnavailable, #[error("failed to obtain build information from the daemon executable ('{}'): {source}", binary_path.display())] @@ -295,7 +309,9 @@ While the stored info point to:\n{stored_info:#?}" source: serde_json::Error, }, - #[error("the daemon execution has failed with the following exit code: {exit_code:?}. the associated signal code: {signal_code:?}. the core was dumped: {core_dumped}")] + #[error( + "the daemon execution has failed with the following exit code: {exit_code:?}. the associated signal code: {signal_code:?}. the core was dumped: {core_dumped}" + )] DaemonExecutionFailure { // exit code of the process, if any exit_code: Option, @@ -311,7 +327,9 @@ While the stored info point to:\n{stored_info:#?}" source: io::Error, }, - #[error("there was already a genesis binary present for {daemon_name} which was different that the one provided.\nProvided:\n{provided_genesis:#?}\nExisting:\n{existing_info:#?}")] + #[error( + "there was already a genesis binary present for {daemon_name} which was different that the one provided.\nProvided:\n{provided_genesis:#?}\nExisting:\n{existing_info:#?}" + )] DuplicateDaemonGenesisBinary { daemon_name: String, existing_info: Box, @@ -324,7 +342,9 @@ While the stored info point to:\n{stored_info:#?}" #[error("there already exist upgrade information for '{name}' at: {}. if you want to overwrite its content, use --force flag", path.display())] ExistingUpgradeInfo { name: String, path: PathBuf }, - #[error("the current upgrade-plan.json has planned upgrade for '{name}', but no corresponding upgrade-info.json file could be found")] + #[error( + "the current upgrade-plan.json has planned upgrade for '{name}', but no corresponding upgrade-info.json file could be found" + )] UpgradePlanWithNoInfo { name: String }, #[error("there was already a symlink for the 'current' binary of {daemon_name}. it's pointing to {} while we needed to create one to {}", link.display(), expected_link.display())] @@ -362,7 +382,9 @@ While the stored info point to:\n{stored_info:#?}" #[error("could not find the upgrade binary at {} while the binary download is disabled", path.display())] NoUpgradeBinaryWithDisabledDownload { path: PathBuf }, - #[error("upgrade '{upgrade_name}' does not have any valid download URLs for the current arch '{arch}'. The available arches are: {available:?}")] + #[error( + "upgrade '{upgrade_name}' does not have any valid download URLs for the current arch '{arch}'. The available arches are: {available:?}" + )] NoDownloadUrls { upgrade_name: String, arch: String, @@ -376,7 +398,9 @@ While the stored info point to:\n{stored_info:#?}" source: reqwest::Error, }, - #[error("failed to verify checksum for upgrade '{upgrade_name}' using {algorithm}. Got '{encoded_checksum}' while expected '{expected_checksum}'")] + #[error( + "failed to verify checksum for upgrade '{upgrade_name}' using {algorithm}. Got '{encoded_checksum}' while expected '{expected_checksum}'" + )] DownloadChecksumFailure { upgrade_name: String, encoded_checksum: String, @@ -414,7 +438,9 @@ While the stored info point to:\n{stored_info:#?}" source: io::Error, }, - #[error("could not load the default config file as there isn't a single nymvisor instance initiated (there are {instances}). please specify either $NYMVISOR_CONFIG_PATH or $NYMVISOR_ID")] + #[error( + "could not load the default config file as there isn't a single nymvisor instance initiated (there are {instances}). please specify either $NYMVISOR_CONFIG_PATH or $NYMVISOR_ID" + )] NotSingleton { instances: usize }, #[error("failed to crate tokio's runtime: {source}")] diff --git a/tools/nymvisor/src/tasks/launcher/backup.rs b/tools/nymvisor/src/tasks/launcher/backup.rs index b63c10aecd..b3c8d539c8 100644 --- a/tools/nymvisor/src/tasks/launcher/backup.rs +++ b/tools/nymvisor/src/tasks/launcher/backup.rs @@ -4,12 +4,12 @@ use crate::config::NYMVISOR_DIR; use crate::error::NymvisorError; use crate::helpers::init_path; -use flate2::write::GzEncoder; use flate2::Compression; +use flate2::write::GzEncoder; use std::fs; use std::fs::{DirEntry, File}; use std::path::{Path, PathBuf}; -use time::{format_description, OffsetDateTime}; +use time::{OffsetDateTime, format_description}; use tracing::info; fn generate_backup_filename() -> String { diff --git a/tools/nymvisor/src/tasks/launcher/mod.rs b/tools/nymvisor/src/tasks/launcher/mod.rs index 83eb804140..a48f2e3201 100644 --- a/tools/nymvisor/src/tasks/launcher/mod.rs +++ b/tools/nymvisor/src/tasks/launcher/mod.rs @@ -6,7 +6,7 @@ use crate::daemon::Daemon; use crate::error::NymvisorError; use crate::tasks::launcher::backup::BackupBuilder; use crate::upgrades::types::{CurrentVersionInfo, UpgradeInfo}; -use crate::upgrades::{perform_upgrade, types::UpgradePlan, UpgradeResult}; +use crate::upgrades::{UpgradeResult, perform_upgrade, types::UpgradePlan}; use futures::future::{FusedFuture, OptionFuture}; use futures::{FutureExt, StreamExt}; use nym_async_file_watcher::FileWatcherEventReceiver; @@ -47,13 +47,17 @@ impl DaemonLauncher { match res { Ok(upgrade_result) => { if upgrade_result.requires_manual_intervention { - info!("this upgrade requires manual intervention. Please read the release notes carefully and follow the provided instructions before starting nymvisor again"); + info!( + "this upgrade requires manual intervention. Please read the release notes carefully and follow the provided instructions before starting nymvisor again" + ); return Ok(()); } if upgrade_result.binary_swapped { if !self.config.daemon.debug.restart_after_upgrade { - info!("upgrade detected, DAEMON_RESTART_AFTER_UPGRADE is off. Verify new upgrade and start nymvisor again"); + info!( + "upgrade detected, DAEMON_RESTART_AFTER_UPGRADE is off. Verify new upgrade and start nymvisor again" + ); return Ok(()); } // else - binary has been swapped and restarting is enabled: do restart diff --git a/tools/nymvisor/src/tasks/upstream_poller.rs b/tools/nymvisor/src/tasks/upstream_poller.rs index 21e1be8891..20a18196d3 100644 --- a/tools/nymvisor/src/tasks/upstream_poller.rs +++ b/tools/nymvisor/src/tasks/upstream_poller.rs @@ -70,7 +70,10 @@ impl UpstreamPoller { // note: first tick happens immediately interval.tick().await; if let Err(err) = self.check_upstream().await { - warn!("failed to check the upstream for new upgrade information: {err}. we will try to poll it again in {}", humantime::format_duration(interval.period())); + warn!( + "failed to check the upstream for new upgrade information: {err}. we will try to poll it again in {}", + humantime::format_duration(interval.period()) + ); } } } diff --git a/tools/nymvisor/src/upgrades/download.rs b/tools/nymvisor/src/upgrades/download.rs index 1be5cf5252..10ff753b35 100644 --- a/tools/nymvisor/src/upgrades/download.rs +++ b/tools/nymvisor/src/upgrades/download.rs @@ -75,11 +75,11 @@ async fn chunk_download( } })?; - if let Some(length) = maybe_length { - if last_logged.elapsed() > LOGGING_RATE { - log_progress_bar(downloaded, length); - last_logged = tokio::time::Instant::now(); - } + if let Some(length) = maybe_length + && last_logged.elapsed() > LOGGING_RATE + { + log_progress_bar(downloaded, length); + last_logged = tokio::time::Instant::now(); } } if let Some(length) = maybe_length { diff --git a/tools/nymvisor/src/upgrades/mod.rs b/tools/nymvisor/src/upgrades/mod.rs index bb8ae36d60..812ab741d2 100644 --- a/tools/nymvisor/src/upgrades/mod.rs +++ b/tools/nymvisor/src/upgrades/mod.rs @@ -6,7 +6,7 @@ use crate::daemon::Daemon; use crate::error::NymvisorError; use crate::upgrades::download::download_upgrade_binary; use crate::upgrades::types::{CurrentVersionInfo, UpgradeHistory, UpgradePlan}; -use nix::fcntl::{flock, FlockArg}; +use nix::fcntl::{FlockArg, flock}; use std::fs; use std::fs::File; use std::os::fd::AsRawFd; diff --git a/tools/nymvisor/src/upgrades/types.rs b/tools/nymvisor/src/upgrades/types.rs index 50b997be80..4b6f1dcdee 100644 --- a/tools/nymvisor/src/upgrades/types.rs +++ b/tools/nymvisor/src/upgrades/types.rs @@ -110,7 +110,10 @@ impl UpgradePlan { if planned.version == upgrade.version { if planned.name != upgrade.name { // TODO: should we maybe return a hard error here instead? - error!("we have already a planned upgrade for version {} under name '{}' which differs from provided '{}'", planned.version, planned.name, upgrade.name); + error!( + "we have already a planned upgrade for version {} under name '{}' which differs from provided '{}'", + planned.version, planned.name, upgrade.name + ); } return true; } @@ -307,13 +310,13 @@ impl UpgradeInfo { }); } - if let Some(bin_info) = &self.binary_details { - if bin_info != ¤t_info.binary_details { - return Err(NymvisorError::UnexpectedCurrentVersionInfo { - current_info: Box::new(self.clone()), - current_version_info: Box::new(current_info.clone()), - }); - } + if let Some(bin_info) = &self.binary_details + && bin_info != ¤t_info.binary_details + { + return Err(NymvisorError::UnexpectedCurrentVersionInfo { + current_info: Box::new(self.clone()), + current_version_info: Box::new(current_info.clone()), + }); } Ok(()) @@ -323,13 +326,13 @@ impl UpgradeInfo { &self, info: &BinaryBuildInformationOwned, ) -> Result<(), NymvisorError> { - if let Some(self_info) = &self.binary_details { - if self_info != info { - return Err(NymvisorError::UnexpectedDaemonBuild { - daemon_info: Box::new(info.clone()), - stored_info: Box::new(self_info.clone()), - }); - } + if let Some(self_info) = &self.binary_details + && self_info != info + { + return Err(NymvisorError::UnexpectedDaemonBuild { + daemon_info: Box::new(info.clone()), + stored_info: Box::new(self_info.clone()), + }); } if self.version != info.build_version { return Err(NymvisorError::UnexpectedUpgradeDaemonVersion { diff --git a/wasm/client/Cargo.toml b/wasm/client/Cargo.toml index 21a57bf32e..6ded8ee2d5 100644 --- a/wasm/client/Cargo.toml +++ b/wasm/client/Cargo.toml @@ -10,7 +10,7 @@ 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.76" +rust-version = "1.85" [lib] crate-type = ["cdylib", "rlib"] diff --git a/wasm/full-nym-wasm/Cargo.toml b/wasm/full-nym-wasm/Cargo.toml index 9ad01b8a17..3e98e42d24 100644 --- a/wasm/full-nym-wasm/Cargo.toml +++ b/wasm/full-nym-wasm/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"] license = "Apache-2.0" repository = "https://github.com/nymtech/nym" -rust-version = "1.56" +rust-version = "1.85" # 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 4f7ffe017f..d50239241c 100644 --- a/wasm/mix-fetch/Cargo.toml +++ b/wasm/mix-fetch/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" keywords = ["nym", "fetch", "wasm", "webassembly", "privacy"] license = "Apache-2.0" repository = "https://github.com/nymtech/nym" -rust-version = "1.70" +rust-version = "1.85" # 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 6d3cd6042e..05411e164f 100644 --- a/wasm/node-tester/Cargo.toml +++ b/wasm/node-tester/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" keywords = ["nym", "sphinx", "webassembly", "privacy", "tester"] license = "Apache-2.0" repository = "https://github.com/nymtech/nym" -rust-version = "1.64" +rust-version = "1.85" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/wasm/zknym-lib/src/error.rs b/wasm/zknym-lib/src/error.rs index 5fe8794262..b06ca52ef2 100644 --- a/wasm/zknym-lib/src/error.rs +++ b/wasm/zknym-lib/src/error.rs @@ -27,7 +27,9 @@ pub enum ZkNymError { #[error("global parameters have already been set before")] GlobalParamsAlreadySet, - #[error("no parameters were provided - they need to be provided either explicitly or a global ones need to be set")] + #[error( + "no parameters were provided - they need to be provided either explicitly or a global ones need to be set" + )] NoParametersProvided, #[error("failed to recover ed25519 private key from its base58 representation: {0}")] diff --git a/wasm/zknym-lib/src/vpn_api_client/client.rs b/wasm/zknym-lib/src/vpn_api_client/client.rs index 843753b7f0..6c0c06f897 100644 --- a/wasm/zknym-lib/src/vpn_api_client/client.rs +++ b/wasm/zknym-lib/src/vpn_api_client/client.rs @@ -7,7 +7,7 @@ use crate::vpn_api_client::types::{ use async_trait::async_trait; pub use nym_http_api_client::Client; use nym_http_api_client::{ - parse_response, ApiClient, HttpClientError, IntoUrl, PathSegments, NO_PARAMS, + ApiClient, HttpClientError, IntoUrl, NO_PARAMS, PathSegments, parse_response, }; use serde::de::DeserializeOwned;