From 85604e830577a7e2820c77679949f297569101d7 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Wed, 23 Jul 2025 10:18:45 +0200 Subject: [PATCH 1/2] bump versions --- Cargo.lock | 14 +++++++------- clients/native/Cargo.toml | 2 +- clients/socks5/Cargo.toml | 2 +- nym-api/Cargo.toml | 2 +- nym-node/Cargo.toml | 2 +- service-providers/network-requester/Cargo.toml | 2 +- tools/nym-cli/Cargo.toml | 2 +- tools/nymvisor/Cargo.toml | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db6b1431bf..c8ffca72d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4895,7 +4895,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "nym-api" -version = "1.1.62" +version = "1.1.63" dependencies = [ "anyhow", "async-trait", @@ -5184,7 +5184,7 @@ dependencies = [ [[package]] name = "nym-cli" -version = "1.1.59" +version = "1.1.60" dependencies = [ "anyhow", "base64 0.22.1", @@ -5266,7 +5266,7 @@ dependencies = [ [[package]] name = "nym-client" -version = "1.1.59" +version = "1.1.60" dependencies = [ "bs58", "clap", @@ -6551,7 +6551,7 @@ dependencies = [ [[package]] name = "nym-network-requester" -version = "1.1.60" +version = "1.1.61" dependencies = [ "addr", "anyhow", @@ -6601,7 +6601,7 @@ dependencies = [ [[package]] name = "nym-node" -version = "1.15.0" +version = "1.16.0" dependencies = [ "anyhow", "arc-swap", @@ -7125,7 +7125,7 @@ dependencies = [ [[package]] name = "nym-socks5-client" -version = "1.1.59" +version = "1.1.60" dependencies = [ "bs58", "clap", @@ -8081,7 +8081,7 @@ dependencies = [ [[package]] name = "nymvisor" -version = "0.1.24" +version = "0.1.25" dependencies = [ "anyhow", "bytes", diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 22e8312b20..b3083d7f8d 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-client" -version = "1.1.59" +version = "1.1.60" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] description = "Implementation of the Nym Client" edition = "2021" diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index c2e035c8a2..0a4d5f8cd1 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-socks5-client" -version = "1.1.59" +version = "1.1.60" authors = ["Dave Hrycyszyn "] description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" edition = "2021" diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 7ca23637cb..1906ef30ba 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "nym-api" license = "GPL-3.0" -version = "1.1.62" +version = "1.1.63" authors.workspace = true edition = "2021" rust-version.workspace = true diff --git a/nym-node/Cargo.toml b/nym-node/Cargo.toml index 96be330954..38bad1d5d7 100644 --- a/nym-node/Cargo.toml +++ b/nym-node/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-node" -version = "1.15.0" +version = "1.16.0" authors.workspace = true repository.workspace = true homepage.workspace = true diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 1ee3da46c4..82570fa878 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "nym-network-requester" license = "GPL-3.0" -version = "1.1.60" +version = "1.1.61" authors.workspace = true edition.workspace = true rust-version = "1.70" diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index 6967b19afb..6fd47a0d13 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-cli" -version = "1.1.59" +version = "1.1.60" authors.workspace = true edition = "2021" license.workspace = true diff --git a/tools/nymvisor/Cargo.toml b/tools/nymvisor/Cargo.toml index a9c760c5fe..d84276ed3d 100644 --- a/tools/nymvisor/Cargo.toml +++ b/tools/nymvisor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nymvisor" -version = "0.1.24" +version = "0.1.25" authors.workspace = true repository.workspace = true homepage.workspace = true From 7f97f13799342f864e1b106e8cafc9f6d6c24c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Thu, 24 Jul 2025 11:00:58 +0100 Subject: [PATCH 2/2] chore: nym node tokio console (#5909) * conditionally enable console-subscriber within nym-node * Update ci-build-upload-binaries.yml * Update ci-build-upload-binaries.yml add features console * updated feature name * fixed filtering on tracing layers * add track_caller when spawning futures for better tokio-console support * allow [client] tasks to specify their names when used within tokio console * clippy * pre-emptively fix wasm clippy --------- Co-authored-by: Tommy Verrall <60836166+tommyv1987@users.noreply.github.com> --- .../workflows/ci-build-upload-binaries.yml | 8 +- Cargo.lock | 150 +++++------------- Cargo.toml | 6 +- clients/native/src/client/mod.rs | 2 +- common/client-core/Cargo.toml | 4 + .../client_import_coin_index_signatures.rs | 1 + .../cli_helpers/client_import_credential.rs | 1 + ...lient_import_expiration_date_signatures.rs | 1 + .../client_import_master_verification_key.rs | 1 + .../client-core/src/client/base_client/mod.rs | 19 ++- .../client/base_client/non_wasm_helpers.rs | 31 ++-- .../src/client/cover_traffic_stream.rs | 40 ++--- .../client-core/src/client/mix_traffic/mod.rs | 79 ++++----- .../src/client/mix_traffic/transceiver.rs | 2 + .../action_controller.rs | 4 +- .../input_message_listener.rs | 5 +- .../acknowledgement_control/mod.rs | 55 ++++--- .../real_messages_control/message_handler.rs | 14 ++ .../src/client/real_messages_control/mod.rs | 22 ++- .../real_traffic_stream.rs | 6 + .../client-core/src/client/received_buffer.rs | 26 +-- .../reply_controller/receiver_controller.rs | 4 +- .../src/client/statistics_control.rs | 9 +- .../src/client/topology_control/mod.rs | 55 ++++--- common/client-core/src/error.rs | 16 +- common/client-core/src/init/helpers.rs | 2 +- common/client-core/src/lib.rs | 40 ++++- common/socks5-client-core/src/lib.rs | 2 +- common/task/src/cancellation.rs | 5 + nym-node/Cargo.toml | 6 +- nym-node/src/cli/mod.rs | 3 +- nym-node/src/logging.rs | 26 ++- 32 files changed, 363 insertions(+), 282 deletions(-) diff --git a/.github/workflows/ci-build-upload-binaries.yml b/.github/workflows/ci-build-upload-binaries.yml index 7df2cd4ad4..3986f1ddae 100644 --- a/.github/workflows/ci-build-upload-binaries.yml +++ b/.github/workflows/ci-build-upload-binaries.yml @@ -38,15 +38,14 @@ jobs: rm -rf ci-builds || true mkdir -p $OUTPUT_DIR echo $OUTPUT_DIR - - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get -y install libudev-dev - name: Sets env vars for tokio if set in manual dispatch inputs - run: | - echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true - + run: | + echo "RUSTFLAGS=--cfg tokio_unstable" >> $GITHUB_ENV + echo "CARGO_FEATURES=--features tokio-console" >> $GITHUB_ENV - name: Install Rust stable uses: actions-rs/toolchain@v1 with: @@ -103,7 +102,6 @@ jobs: if [ ${{ github.event_name == 'workflow_dispatch' && inputs.enable_deb == true }} = true ]; then cp target/debian/*.deb $OUTPUT_DIR fi - - name: Deploy branch to CI www continue-on-error: true uses: easingthemes/ssh-deploy@main diff --git a/Cargo.lock b/Cargo.lock index c8ffca72d1..b315759900 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -556,34 +556,6 @@ dependencies = [ "log", ] -[[package]] -name = "axum" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" -dependencies = [ - "async-trait", - "axum-core 0.3.4", - "bitflags 1.3.2", - "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.32", - "itoa", - "matchit 0.7.3", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper 0.1.2", - "tower 0.4.13", - "tower-layer", - "tower-service", -] - [[package]] name = "axum" version = "0.7.9" @@ -664,23 +636,6 @@ dependencies = [ "serde", ] -[[package]] -name = "axum-core" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - [[package]] name = "axum-core" version = "0.4.5" @@ -1441,11 +1396,12 @@ dependencies = [ [[package]] name = "console-api" -version = "0.5.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2895653b4d9f1538a83970077cb01dfc77a4810524e51a110944688e916b18e" +checksum = "8030735ecb0d128428b64cd379809817e620a40e5001c54465b99ec5feec2857" dependencies = [ - "prost 0.11.9", + "futures-core", + "prost", "prost-types", "tonic", "tracing-core", @@ -1453,16 +1409,18 @@ dependencies = [ [[package]] name = "console-subscriber" -version = "0.1.10" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4cf42660ac07fcebed809cfe561dd8730bcd35b075215e6479c516bcd0d11cb" +checksum = "6539aa9c6a4cd31f4b1c040f860a1eac9aa80e7df6b05d506a6e7179936d6a01" dependencies = [ "console-api", "crossbeam-channel", "crossbeam-utils", - "futures", + "futures-task", "hdrhistogram", "humantime", + "hyper-util", + "prost", "prost-types", "serde", "serde_json", @@ -1555,7 +1513,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "462e1f6a8e005acc8835d32d60cbd7973ed65ea2a8d8473830e675f050956427" dependencies = [ - "prost 0.13.5", + "prost", "tendermint-proto", ] @@ -2028,7 +1986,7 @@ dependencies = [ "cw-storage-plus", "cw-utils", "itertools 0.14.0", - "prost 0.13.5", + "prost", "schemars 0.8.22", "serde", "sha2 0.10.9", @@ -3580,6 +3538,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", + "h2 0.4.11", "http 1.3.1", "http-body 1.0.1", "httparse", @@ -3624,14 +3583,15 @@ dependencies = [ [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 0.14.32", + "hyper 1.6.0", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] @@ -5308,6 +5268,7 @@ dependencies = [ "async-trait", "base64 0.22.1", "bs58", + "cfg-if", "clap", "comfy-table", "futures", @@ -6614,9 +6575,11 @@ dependencies = [ "bs58", "cargo_metadata 0.19.2", "celes", + "cfg-if", "chacha", "clap", "colored", + "console-subscriber", "criterion", "csv", "cupid", @@ -7825,7 +7788,7 @@ dependencies = [ "nym-performance-contract-common", "nym-serde-helpers 0.1.0", "nym-vesting-contract-common 0.7.0", - "prost 0.13.5", + "prost", "reqwest 0.12.22", "serde", "serde_json", @@ -7875,7 +7838,7 @@ dependencies = [ "nym-network-defaults 0.1.0 (git+https://github.com/nymtech/nym.git?branch=release/2025.11-cheddar)", "nym-serde-helpers 0.1.0 (git+https://github.com/nymtech/nym.git?branch=release/2025.11-cheddar)", "nym-vesting-contract-common 0.7.0 (git+https://github.com/nymtech/nym.git?branch=release/2025.11-cheddar)", - "prost 0.13.5", + "prost", "reqwest 0.12.22", "serde", "serde_json", @@ -8842,16 +8805,6 @@ dependencies = [ "thiserror 2.0.12", ] -[[package]] -name = "prost" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes", - "prost-derive 0.11.9", -] - [[package]] name = "prost" version = "0.13.5" @@ -8859,20 +8812,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ "bytes", - "prost-derive 0.13.5", -] - -[[package]] -name = "prost-derive" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", + "prost-derive", ] [[package]] @@ -8890,11 +8830,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.11.9" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" dependencies = [ - "prost 0.11.9", + "prost", ] [[package]] @@ -10809,7 +10749,7 @@ dependencies = [ "k256", "num-traits", "once_cell", - "prost 0.13.5", + "prost", "ripemd", "serde", "serde_bytes", @@ -10846,7 +10786,7 @@ checksum = "d2c40e13d39ca19082d8a7ed22de7595979350319833698f8b1080f29620a094" dependencies = [ "bytes", "flex-error", - "prost 0.13.5", + "prost", "serde", "serde_bytes", "subtle-encoding", @@ -11118,16 +11058,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "tokio-io-timeout" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd86198d9ee903fedd2f9a2e72014287c0d9167e4ae43b5853007205dda1b76" -dependencies = [ - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-macros" version = "2.5.0" @@ -11316,24 +11246,26 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tonic" -version = "0.9.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ + "async-stream", "async-trait", - "axum 0.6.20", - "base64 0.21.7", + "axum 0.7.9", + "base64 0.22.1", "bytes", - "futures-core", - "futures-util", - "h2 0.3.27", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.32", + "h2 0.4.11", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "hyper 1.6.0", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", - "prost 0.11.9", + "prost", + "socket2", "tokio", "tokio-stream", "tower 0.4.13", diff --git a/Cargo.toml b/Cargo.toml index 8b3404c545..672a690c05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -218,7 +218,7 @@ clap_complete_fig = "4.5" colored = "2.2" comfy-table = "7.1.4" console = "0.15.11" -console-subscriber = "0.1.1" +console-subscriber = "0.4.1" console_error_panic_hook = "0.1" const-str = "0.5.6" const_format = "0.2.34" @@ -434,6 +434,9 @@ opt-level = 'z' # lto = true opt-level = 'z' +[workspace.lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tokio_unstable)'] } + [workspace.lints.clippy] unwrap_used = "deny" expect_used = "deny" @@ -443,3 +446,4 @@ exit = "deny" panic = "deny" unimplemented = "deny" unreachable = "deny" + diff --git a/clients/native/src/client/mod.rs b/clients/native/src/client/mod.rs index d32e3e835f..ce36a5eb84 100644 --- a/clients/native/src/client/mod.rs +++ b/clients/native/src/client/mod.rs @@ -111,7 +111,7 @@ impl SocketClient { let dkg_query_client = if self.config.base.client.disabled_credentials_mode { None } else { - Some(default_query_dkg_client_from_config(&self.config.base)) + Some(default_query_dkg_client_from_config(&self.config.base)?) }; let storage = self.initialise_storage().await?; diff --git a/common/client-core/Cargo.toml b/common/client-core/Cargo.toml index 7cca47759f..74663fe807 100644 --- a/common/client-core/Cargo.toml +++ b/common/client-core/Cargo.toml @@ -13,6 +13,7 @@ async-trait = { workspace = true } base64 = { workspace = true } bs58 = { workspace = true } clap = { workspace = true, optional = true } +cfg-if = { workspace = true } comfy-table = { workspace = true, optional = true } futures = { workspace = true } humantime = { workspace = true } @@ -123,3 +124,6 @@ fs-surb-storage = ["nym-client-core-surb-storage/fs-surb-storage"] fs-gateways-storage = ["nym-client-core-gateways-storage/fs-gateways-storage"] wasm = ["nym-gateway-client/wasm"] metrics-server = [] + +[lints] +workspace = true diff --git a/common/client-core/src/cli_helpers/client_import_coin_index_signatures.rs b/common/client-core/src/cli_helpers/client_import_coin_index_signatures.rs index 5625250ce3..ce282ef9d1 100644 --- a/common/client-core/src/cli_helpers/client_import_coin_index_signatures.rs +++ b/common/client-core/src/cli_helpers/client_import_coin_index_signatures.rs @@ -58,6 +58,7 @@ where Some(data) => data, None => { // SAFETY: one of those arguments must have been set + #[allow(clippy::unwrap_used)] fs::read(common_args.signatures_path.unwrap())? } }; diff --git a/common/client-core/src/cli_helpers/client_import_credential.rs b/common/client-core/src/cli_helpers/client_import_credential.rs index 77c6dc16f4..30799167ce 100644 --- a/common/client-core/src/cli_helpers/client_import_credential.rs +++ b/common/client-core/src/cli_helpers/client_import_credential.rs @@ -64,6 +64,7 @@ where Some(data) => data, None => { // SAFETY: one of those arguments must have been set + #[allow(clippy::unwrap_used)] fs::read(common_args.credential_path.unwrap())? } }; diff --git a/common/client-core/src/cli_helpers/client_import_expiration_date_signatures.rs b/common/client-core/src/cli_helpers/client_import_expiration_date_signatures.rs index 4dc875e75c..f3752587ab 100644 --- a/common/client-core/src/cli_helpers/client_import_expiration_date_signatures.rs +++ b/common/client-core/src/cli_helpers/client_import_expiration_date_signatures.rs @@ -58,6 +58,7 @@ where Some(data) => data, None => { // SAFETY: one of those arguments must have been set + #[allow(clippy::unwrap_used)] fs::read(common_args.signatures_path.unwrap())? } }; diff --git a/common/client-core/src/cli_helpers/client_import_master_verification_key.rs b/common/client-core/src/cli_helpers/client_import_master_verification_key.rs index b44334b49e..677018226b 100644 --- a/common/client-core/src/cli_helpers/client_import_master_verification_key.rs +++ b/common/client-core/src/cli_helpers/client_import_master_verification_key.rs @@ -58,6 +58,7 @@ where Some(data) => data, None => { // SAFETY: one of those arguments must have been set + #[allow(clippy::unwrap_used)] fs::read(common_args.key_path.unwrap())? } }; diff --git a/common/client-core/src/client/base_client/mod.rs b/common/client-core/src/client/base_client/mod.rs index 2331b5de68..36cb427780 100644 --- a/common/client-core/src/client/base_client/mod.rs +++ b/common/client-core/src/client/base_client/mod.rs @@ -135,9 +135,11 @@ pub enum ClientInputStatus { } impl ClientInputStatus { + #[allow(clippy::panic)] pub fn register_producer(&mut self) -> ClientInput { match std::mem::replace(self, ClientInputStatus::Connected) { ClientInputStatus::AwaitingProducer { client_input } => client_input, + // critical failure implying misuse of software ClientInputStatus::Connected => panic!("producer was already registered before"), } } @@ -149,9 +151,11 @@ pub enum ClientOutputStatus { } impl ClientOutputStatus { + #[allow(clippy::panic)] pub fn register_consumer(&mut self) -> ClientOutput { match std::mem::replace(self, ClientOutputStatus::Connected) { ClientOutputStatus::AwaitingConsumer { client_output } => client_output, + // critical failure implying misuse of software ClientOutputStatus::Connected => panic!("consumer was already registered before"), } } @@ -707,11 +711,14 @@ where })?; let store_clone = mem_store.clone(); - spawn_future(async move { - persistent_storage - .flush_on_shutdown(store_clone, shutdown) - .await - }); + spawn_future!( + async move { + persistent_storage + .flush_on_shutdown(store_clone, shutdown) + .await + }, + "PersistentReplyStorage::flush_on_shutdown" + ); Ok(mem_store) } @@ -732,7 +739,7 @@ where let mut rng = OsRng; let keys = if let Some(derivation_material) = derivation_material { ClientKeys::from_master_key(&mut rng, &derivation_material) - .map_err(|_| ClientCoreError::HkdfDerivationError {})? + .map_err(|_| ClientCoreError::HkdfDerivationError)? } else { ClientKeys::generate_new(&mut rng) }; diff --git a/common/client-core/src/client/base_client/non_wasm_helpers.rs b/common/client-core/src/client/base_client/non_wasm_helpers.rs index 87e7fb62a2..365aabd0e8 100644 --- a/common/client-core/src/client/base_client/non_wasm_helpers.rs +++ b/common/client-core/src/client/base_client/non_wasm_helpers.rs @@ -114,41 +114,32 @@ pub async fn setup_fs_gateways_storage>( }) } -pub fn create_bandwidth_controller( - config: &Config, - storage: St, -) -> BandwidthController { - let nyxd_url = config - .get_validator_endpoints() - .pop() - .expect("No nyxd validator endpoint provided"); - - create_bandwidth_controller_with_urls(nyxd_url, storage) -} - pub fn create_bandwidth_controller_with_urls( nyxd_url: Url, storage: St, -) -> BandwidthController { - let client = default_query_dkg_client(nyxd_url); +) -> Result, ClientCoreError> { + let client = default_query_dkg_client(nyxd_url)?; - BandwidthController::new(storage, client) + Ok(BandwidthController::new(storage, client)) } -pub fn default_query_dkg_client_from_config(config: &Config) -> QueryHttpRpcNyxdClient { +pub fn default_query_dkg_client_from_config( + config: &Config, +) -> Result { let nyxd_url = config .get_validator_endpoints() .pop() - .expect("No nyxd validator endpoint provided"); + .ok_or(ClientCoreError::RpcClientMissingUrl)?; default_query_dkg_client(nyxd_url) } -pub fn default_query_dkg_client(nyxd_url: Url) -> QueryHttpRpcNyxdClient { +pub fn default_query_dkg_client(nyxd_url: Url) -> Result { let details = nym_network_defaults::NymNetworkDetails::new_from_env(); let client_config = nyxd::Config::try_from_nym_network_details(&details) - .expect("failed to construct validator client config"); + .map_err(|source| ClientCoreError::InvalidNetworkDetails { source })?; // overwrite env configuration with config URLs + QueryHttpRpcNyxdClient::connect(client_config, nyxd_url.as_str()) - .expect("Could not construct query client") + .map_err(|source| ClientCoreError::RpcClientCreationFailure { source }) } diff --git a/common/client-core/src/client/cover_traffic_stream.rs b/common/client-core/src/client/cover_traffic_stream.rs index a5c08cca0c..d635fc20c6 100644 --- a/common/client-core/src/client/cover_traffic_stream.rs +++ b/common/client-core/src/client/cover_traffic_stream.rs @@ -235,6 +235,7 @@ impl LoopCoverTrafficStream { tokio::task::yield_now().await; } + #[allow(clippy::panic)] pub fn start(mut self) { if self.cover_traffic.disable_loop_cover_traffic_stream { // we should have never got here in the first place - the task should have never been created to begin with @@ -251,27 +252,30 @@ impl LoopCoverTrafficStream { let mut shutdown = self.task_client.fork("select"); - spawn_future(async move { - debug!("Started LoopCoverTrafficStream with graceful shutdown support"); + spawn_future!( + async move { + debug!("Started LoopCoverTrafficStream with graceful shutdown support"); - while !shutdown.is_shutdown() { - tokio::select! { - biased; - _ = shutdown.recv() => { - tracing::trace!("LoopCoverTrafficStream: Received shutdown"); - } - next = self.next() => { - if next.is_some() { - self.on_new_message().await; - } else { - tracing::trace!("LoopCoverTrafficStream: Stopping since channel closed"); - break; + while !shutdown.is_shutdown() { + tokio::select! { + biased; + _ = shutdown.recv() => { + tracing::trace!("LoopCoverTrafficStream: Received shutdown"); + } + next = self.next() => { + if next.is_some() { + self.on_new_message().await; + } else { + tracing::trace!("LoopCoverTrafficStream: Stopping since channel closed"); + break; + } } } } - } - shutdown.recv_timeout().await; - tracing::debug!("LoopCoverTrafficStream: Exiting"); - }) + shutdown.recv_timeout().await; + tracing::debug!("LoopCoverTrafficStream: Exiting"); + }, + "LoopCoverTrafficStream" + ) } } diff --git a/common/client-core/src/client/mix_traffic/mod.rs b/common/client-core/src/client/mix_traffic/mod.rs index 5b7e5ab7bd..be7a517f57 100644 --- a/common/client-core/src/client/mix_traffic/mod.rs +++ b/common/client-core/src/client/mix_traffic/mod.rs @@ -98,6 +98,8 @@ impl MixTrafficController { debug_assert!(!mix_packets.is_empty()); let result = if mix_packets.len() == 1 { + // SAFETY: we just checked we have one packet + #[allow(clippy::unwrap_used)] let mix_packet = mix_packets.pop().unwrap(); self.gateway_transceiver.send_mix_packet(mix_packet).await } else { @@ -117,51 +119,54 @@ impl MixTrafficController { } pub fn start(mut self) { - spawn_future(async move { - debug!("Started MixTrafficController with graceful shutdown support"); + spawn_future!( + async move { + debug!("Started MixTrafficController with graceful shutdown support"); - while !self.task_client.is_shutdown() { - tokio::select! { - mix_packets = self.mix_rx.recv() => match mix_packets { - Some(mix_packets) => { - if let Err(err) = self.on_messages(mix_packets).await { - error!("Failed to send sphinx packet(s) to the gateway: {err}"); - if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT { - // Disconnect from the gateway. If we should try to re-connect - // is handled at a higher layer. - error!("Failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead"); - // Do we need to handle the embedded mixnet client case - // separately? - self.task_client.send_we_stopped(Box::new(ClientCoreError::GatewayFailedToForwardMessages)); - break; + while !self.task_client.is_shutdown() { + tokio::select! { + mix_packets = self.mix_rx.recv() => match mix_packets { + Some(mix_packets) => { + if let Err(err) = self.on_messages(mix_packets).await { + error!("Failed to send sphinx packet(s) to the gateway: {err}"); + if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT { + // Disconnect from the gateway. If we should try to re-connect + // is handled at a higher layer. + error!("Failed to send sphinx packet to the gateway {MAX_FAILURE_COUNT} times in a row - assuming the gateway is dead"); + // Do we need to handle the embedded mixnet client case + // separately? + self.task_client.send_we_stopped(Box::new(ClientCoreError::GatewayFailedToForwardMessages)); + break; + } } + }, + None => { + tracing::trace!("MixTrafficController: Stopping since channel closed"); + break; } }, - None => { - tracing::trace!("MixTrafficController: Stopping since channel closed"); + client_request = self.client_rx.recv() => match client_request { + Some(client_request) => { + match self.gateway_transceiver.send_client_request(client_request).await { + Ok(_) => (), + Err(e) => error!("Failed to send client request: {e}"), + }; + }, + None => { + tracing::trace!("MixTrafficController, client request channel closed"); + } + }, + _ = self.task_client.recv() => { + tracing::trace!("MixTrafficController: Received shutdown"); break; } - }, - client_request = self.client_rx.recv() => match client_request { - Some(client_request) => { - match self.gateway_transceiver.send_client_request(client_request).await { - Ok(_) => (), - Err(e) => error!("Failed to send client request: {e}"), - }; - }, - None => { - tracing::trace!("MixTrafficController, client request channel closed"); - } - }, - _ = self.task_client.recv() => { - tracing::trace!("MixTrafficController: Received shutdown"); - break; } } - } - self.task_client.recv_timeout().await; + self.task_client.recv_timeout().await; - tracing::debug!("MixTrafficController: Exiting"); - }); + tracing::debug!("MixTrafficController: Exiting"); + }, + "MixTrafficController" + ); } } diff --git a/common/client-core/src/client/mix_traffic/transceiver.rs b/common/client-core/src/client/mix_traffic/transceiver.rs index 3bcc209e05..f749700ab2 100644 --- a/common/client-core/src/client/mix_traffic/transceiver.rs +++ b/common/client-core/src/client/mix_traffic/transceiver.rs @@ -269,6 +269,8 @@ pub struct MockGateway { } impl Default for MockGateway { + // test code + #[allow(clippy::unwrap_used)] fn default() -> Self { MockGateway { dummy_identity: "3ebjp1Fb9hdcS1AR6AZihgeJiMHkB5jjJUsvqNnfQwU7" diff --git a/common/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs b/common/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs index ad2fa1a3c2..350b400e46 100644 --- a/common/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs +++ b/common/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs @@ -194,10 +194,11 @@ impl ActionController { trace!("{frag_id} is updating its delay"); // TODO: is it possible to solve this without either locking or temporarily removing the value? if let Some((pending_ack_data, queue_key)) = self.pending_acks_data.remove(&frag_id) { - // this Action is triggered by `RetransmissionRequestListener` (for 'normal' packets) + // SAFETY: this Action is triggered by `RetransmissionRequestListener` (for 'normal' packets) // or `ReplyController` (for 'reply' packets) which held the other potential // reference to this Arc. HOWEVER, before the Action was pushed onto the queue, the reference // was dropped hence this unwrap is safe. + #[allow(clippy::unwrap_used)] let mut inner_data = Arc::try_unwrap(pending_ack_data).unwrap(); inner_data.update_retransmitted(delay); @@ -209,6 +210,7 @@ impl ActionController { } // note: when the entry expires it's automatically removed from pending_acks_timers + #[allow(clippy::panic)] fn handle_expired_ack_timer(&mut self, expired_ack: Expired) { let frag_id = expired_ack.into_inner(); diff --git a/common/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs b/common/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs index 9414b3a2fe..8185eb5a0a 100644 --- a/common/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs +++ b/common/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs @@ -120,6 +120,7 @@ where } } + #[allow(clippy::panic)] async fn on_input_message(&mut self, msg: InputMessage) { match msg { InputMessage::Regular { @@ -213,7 +214,9 @@ where self.handle_premade_packets(msgs, lane).await } // MessageWrappers can't be nested - InputMessage::MessageWrapper { .. } => unimplemented!(), + InputMessage::MessageWrapper { .. } => { + panic!("attempted to use nested MessageWrapper") + } }, }; } diff --git a/common/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs b/common/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs index 2cad9ef2c2..ea332ebdaf 100644 --- a/common/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs +++ b/common/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs @@ -298,29 +298,44 @@ where let mut sent_notification_listener = self.sent_notification_listener; let mut action_controller = self.action_controller; - spawn_future(async move { - acknowledgement_listener.run().await; - debug!("The acknowledgement listener has finished execution!"); - }); + spawn_future!( + async move { + acknowledgement_listener.run().await; + debug!("The acknowledgement listener has finished execution!"); + }, + "AcknowledgementController::AcknowledgementListener" + ); - spawn_future(async move { - input_message_listener.run().await; - debug!("The input listener has finished execution!"); - }); + spawn_future!( + async move { + input_message_listener.run().await; + debug!("The input listener has finished execution!"); + }, + "AcknowledgementController::InputMessageListener" + ); - spawn_future(async move { - retransmission_request_listener.run(packet_type).await; - debug!("The retransmission request listener has finished execution!"); - }); + spawn_future!( + async move { + retransmission_request_listener.run(packet_type).await; + debug!("The retransmission request listener has finished execution!"); + }, + "AcknowledgementController::RetransmissionRequestListener" + ); - spawn_future(async move { - sent_notification_listener.run().await; - debug!("The sent notification listener has finished execution!"); - }); + spawn_future!( + async move { + sent_notification_listener.run().await; + debug!("The sent notification listener has finished execution!"); + }, + "AcknowledgementController::SentNotificationListener" + ); - spawn_future(async move { - action_controller.run().await; - debug!("The controller has finished execution!"); - }); + spawn_future!( + async move { + action_controller.run().await; + debug!("The controller has finished execution!"); + }, + "AcknowledgementController::ActionController" + ); } } diff --git a/common/client-core/src/client/real_messages_control/message_handler.rs b/common/client-core/src/client/real_messages_control/message_handler.rs index 694f56d762..942d88c77a 100644 --- a/common/client-core/src/client/real_messages_control/message_handler.rs +++ b/common/client-core/src/client/real_messages_control/message_handler.rs @@ -35,6 +35,9 @@ pub enum PreparationError { #[error(transparent)] NymTopologyError(#[from] NymTopologyError), + #[error("message wasn't split into any fragments!")] + EmptyFragments, + #[error("message too long for a single SURB, splitting into {fragments} fragments.")] MessageTooLongForSingleSurb { fragments: usize }, @@ -320,6 +323,16 @@ where }); } + if fragment.is_empty() { + error!("CRITICAL FAILURE: our split message didn't result in any sendable fragments"); + return Err(SurbWrappedPreparationError { + source: PreparationError::EmptyFragments, + returned_surbs: Some(vec![reply_surb]), + }); + } + + // SAFETY: we just checked we have one fragment + #[allow(clippy::unwrap_used)] let chunk = fragment.pop().unwrap(); let chunk_clone = chunk.clone(); let prepared_fragment = self @@ -657,6 +670,7 @@ where .zip(reply_surbs.into_iter()) .map(|(fragment, reply_surb)| { // unwrap here is fine as we know we have a valid topology + #[allow(clippy::unwrap_used)] self.message_preparer .prepare_reply_chunk_for_sending( fragment, diff --git a/common/client-core/src/client/real_messages_control/mod.rs b/common/client-core/src/client/real_messages_control/mod.rs index a30b28fc41..b169a9bff8 100644 --- a/common/client-core/src/client/real_messages_control/mod.rs +++ b/common/client-core/src/client/real_messages_control/mod.rs @@ -224,14 +224,20 @@ impl RealMessagesController { let ack_control = self.ack_control; let mut reply_control = self.reply_control; - spawn_future(async move { - out_queue_control.run().await; - debug!("The out queue controller has finished execution!"); - }); - spawn_future(async move { - reply_control.run().await; - debug!("The reply controller has finished execution!"); - }); + spawn_future!( + async move { + out_queue_control.run().await; + debug!("The out queue controller has finished execution!"); + }, + "RealMessagesController::OutQueueControl)" + ); + spawn_future!( + async move { + reply_control.run().await; + debug!("The reply controller has finished execution!"); + }, + "RealMessagesController::ReplyController" + ); ack_control.start(packet_type); } diff --git a/common/client-core/src/client/real_messages_control/real_traffic_stream.rs b/common/client-core/src/client/real_messages_control/real_traffic_stream.rs index 8c77c1152c..d24947c9d2 100644 --- a/common/client-core/src/client/real_messages_control/real_traffic_stream.rs +++ b/common/client-core/src/client/real_messages_control/real_traffic_stream.rs @@ -249,6 +249,8 @@ where } }; + // SAFETY: our topology must be valid at this point + #[allow(clippy::expect_used)] ( generate_loop_cover_packet( &mut self.rng, @@ -439,6 +441,8 @@ where tracing::trace!("handling real_messages: size: {}", real_messages.len()); self.transmission_buffer.store(&conn_id, real_messages); + // SAFETY: we just stored the message + #[allow(clippy::expect_used)] let real_next = self.pop_next_message().expect("Just stored one"); Poll::Ready(Some(StreamMessage::Real(Box::new(real_next)))) @@ -487,6 +491,8 @@ where // First store what we got for the given connection id self.transmission_buffer.store(&conn_id, real_messages); + // SAFETY: we just stored the message + #[allow(clippy::expect_used)] let real_next = self.pop_next_message().expect("we just added one"); Poll::Ready(Some(StreamMessage::Real(Box::new(real_next)))) diff --git a/common/client-core/src/client/received_buffer.rs b/common/client-core/src/client/received_buffer.rs index 743fc79653..9ed1101867 100644 --- a/common/client-core/src/client/received_buffer.rs +++ b/common/client-core/src/client/received_buffer.rs @@ -198,6 +198,7 @@ impl ReceivedMessagesBuffer { } } + #[allow(clippy::panic)] async fn disconnect_sender(&mut self) { let mut guard = self.inner.lock().await; if guard.message_sender.is_none() { @@ -208,6 +209,7 @@ impl ReceivedMessagesBuffer { guard.message_sender = None; } + #[allow(clippy::panic)] async fn connect_sender(&mut self, sender: ReconstructedMessagesSender) { let mut guard = self.inner.lock().await; if guard.message_sender.is_some() { @@ -599,14 +601,20 @@ impl ReceivedMessagesBufferControll let mut fragmented_message_receiver = self.fragmented_message_receiver; let mut request_receiver = self.request_receiver; - spawn_future(async move { - match fragmented_message_receiver.run().await { - Ok(_) => {} - Err(e) => error!("{e}"), - } - }); - spawn_future(async move { - request_receiver.run().await; - }); + spawn_future!( + async move { + match fragmented_message_receiver.run().await { + Ok(_) => {} + Err(e) => error!("{e}"), + } + }, + "ReceivedMessagesBufferController::FragmentedMessageReceiver" + ); + spawn_future!( + async move { + request_receiver.run().await; + }, + "ReceivedMessagesBufferController::RequestReceiver" + ); } } diff --git a/common/client-core/src/client/replies/reply_controller/receiver_controller.rs b/common/client-core/src/client/replies/reply_controller/receiver_controller.rs index d8bbce9aac..11905c3a85 100644 --- a/common/client-core/src/client/replies/reply_controller/receiver_controller.rs +++ b/common/client-core/src/client/replies/reply_controller/receiver_controller.rs @@ -155,8 +155,9 @@ where data: Vec>, ) { trace!("re-inserting pending retransmissions for {recipient}"); - // the underlying entry MUST exist as we've just got data from there + // SAFETY: the underlying entry MUST exist as we've just got data from there // and we hold a mut reference + #[allow(clippy::expect_used)] let map_entry = &mut self .surb_senders .get_mut(recipient) @@ -429,6 +430,7 @@ where .pop_at_most_n_next_messages_at_random(amount) } + #[allow(clippy::panic)] async fn try_clear_pending_queue(&mut self, target: AnonymousSenderTag) { trace!("trying to clear pending queue"); let available_surbs = self.surbs_storage.available_surbs(&target); diff --git a/common/client-core/src/client/statistics_control.rs b/common/client-core/src/client/statistics_control.rs index 98897ae6b9..6d315f4eb2 100644 --- a/common/client-core/src/client/statistics_control.rs +++ b/common/client-core/src/client/statistics_control.rs @@ -165,9 +165,12 @@ impl StatisticsControl { } pub(crate) fn start(mut self) { - spawn_future(async move { - self.run().await; - }) + spawn_future!( + async move { + self.run().await; + }, + "StatisticsControl" + ) } pub(crate) fn create_and_start( diff --git a/common/client-core/src/client/topology_control/mod.rs b/common/client-core/src/client/topology_control/mod.rs index 1aaff25120..b3c4d61f3f 100644 --- a/common/client-core/src/client/topology_control/mod.rs +++ b/common/client-core/src/client/topology_control/mod.rs @@ -145,36 +145,39 @@ impl TopologyRefresher { } pub fn start(mut self) { - spawn_future(async move { - debug!("Started TopologyRefresher with graceful shutdown support"); + spawn_future!( + async move { + debug!("Started TopologyRefresher with graceful shutdown support"); - #[cfg(not(target_arch = "wasm32"))] - let mut interval = tokio_stream::wrappers::IntervalStream::new(tokio::time::interval( - self.refresh_rate, - )); + #[cfg(not(target_arch = "wasm32"))] + let mut interval = tokio_stream::wrappers::IntervalStream::new( + tokio::time::interval(self.refresh_rate), + ); - #[cfg(target_arch = "wasm32")] - let mut interval = - gloo_timers::future::IntervalStream::new(self.refresh_rate.as_millis() as u32); + #[cfg(target_arch = "wasm32")] + let mut interval = + gloo_timers::future::IntervalStream::new(self.refresh_rate.as_millis() as u32); - // We already have an initial topology, so no need to refresh it immediately. - // My understanding is that js setInterval does not fire immediately, so it's not - // needed there. - #[cfg(not(target_arch = "wasm32"))] - interval.next().await; + // We already have an initial topology, so no need to refresh it immediately. + // My understanding is that js setInterval does not fire immediately, so it's not + // needed there. + #[cfg(not(target_arch = "wasm32"))] + interval.next().await; - while !self.task_client.is_shutdown() { - tokio::select! { - _ = interval.next() => { - self.try_refresh().await; - }, - _ = self.task_client.recv() => { - tracing::trace!("TopologyRefresher: Received shutdown"); - }, + while !self.task_client.is_shutdown() { + tokio::select! { + _ = interval.next() => { + self.try_refresh().await; + }, + _ = self.task_client.recv() => { + tracing::trace!("TopologyRefresher: Received shutdown"); + }, + } } - } - self.task_client.recv_timeout().await; - tracing::debug!("TopologyRefresher: Exiting"); - }) + self.task_client.recv_timeout().await; + tracing::debug!("TopologyRefresher: Exiting"); + }, + "TopologyRefresher" + ) } } diff --git a/common/client-core/src/error.rs b/common/client-core/src/error.rs index a97030a24e..1c26e96dfb 100644 --- a/common/client-core/src/error.rs +++ b/common/client-core/src/error.rs @@ -7,7 +7,9 @@ use nym_gateway_client::error::GatewayClientError; use nym_topology::node::RoutingNodeError; use nym_topology::{NodeId, NymTopologyError}; use nym_validator_client::nym_api::error::NymAPIError; +use nym_validator_client::nyxd::error::NyxdError; use nym_validator_client::ValidatorClientError; +use rand::distributions::WeightedError; use std::error::Error; use std::path::PathBuf; @@ -230,7 +232,19 @@ pub enum ClientCoreError { UnexpectedKeyUpgrade { gateway_id: String }, #[error("failed to derive keys from master key")] - HkdfDerivationError {}, + HkdfDerivationError, + + #[error("missing url for constructing RPC client")] + RpcClientMissingUrl, + + #[error("provided nym network details were malformed: {source}")] + InvalidNetworkDetails { source: NyxdError }, + + #[error("failed to construct RPC client: {source}")] + RpcClientCreationFailure { source: NyxdError }, + + #[error("failed to select valid gateway due to incomputable latency")] + GatewaySelectionFailure { source: WeightedError }, } impl From for ClientCoreError { diff --git a/common/client-core/src/init/helpers.rs b/common/client-core/src/init/helpers.rs index d099431ded..97c3be13b7 100644 --- a/common/client-core/src/init/helpers.rs +++ b/common/client-core/src/init/helpers.rs @@ -245,7 +245,7 @@ pub async fn choose_gateway_by_latency( let gateways_with_latency = gateways_with_latency.lock().await; let chosen = gateways_with_latency .choose_weighted(rng, |item| 1. / item.latency.as_secs_f32()) - .expect("invalid selection weight!"); + .map_err(|source| ClientCoreError::GatewaySelectionFailure { source })?; info!( "chose gateway {} with average latency of {:?}", diff --git a/common/client-core/src/lib.rs b/common/client-core/src/lib.rs index ba1d80f4c4..8be8b10133 100644 --- a/common/client-core/src/lib.rs +++ b/common/client-core/src/lib.rs @@ -18,18 +18,54 @@ pub use nym_topology::{ }; #[cfg(target_arch = "wasm32")] -pub(crate) fn spawn_future(future: F) +pub fn spawn_future(future: F) where F: Future + 'static, { wasm_bindgen_futures::spawn_local(future); } +// TODO: expose similar API to the rest of the codebase, +// perhaps with some simple trait for a task to define its name + #[cfg(not(target_arch = "wasm32"))] -pub(crate) fn spawn_future(future: F) +#[track_caller] +pub fn spawn_future(future: F) where F: Future + Send + 'static, F::Output: Send + 'static, { tokio::spawn(future); } + +#[cfg(not(target_arch = "wasm32"))] +#[track_caller] +pub fn spawn_named_future(future: F, name: &str) +where + F: Future + Send + 'static, + F::Output: Send + 'static, +{ + cfg_if::cfg_if! {if #[cfg(tokio_unstable)] { + #[allow(clippy::expect_used)] + tokio::task::Builder::new().name(name).spawn(future).expect("failed to spawn future"); + } else { + let _ = name; + tracing::debug!(r#"the underlying binary hasn't been built with `RUSTFLAGS="--cfg tokio_unstable"` - the future naming won't do anything"#); + spawn_future(future); + }} +} + +#[macro_export] +macro_rules! spawn_future { + ($future:expr) => {{ + $crate::spawn_future($future) + }}; + ($future:expr, $name:expr) => {{ + cfg_if::cfg_if! {if #[cfg(not(target_arch = "wasm32"))] { + $crate::spawn_named_future($future, $name) + } else { + let _ = $name; + $crate::spawn_future($future) + }} + }}; +} diff --git a/common/socks5-client-core/src/lib.rs b/common/socks5-client-core/src/lib.rs index 17140d39fc..3c7a4b658d 100644 --- a/common/socks5-client-core/src/lib.rs +++ b/common/socks5-client-core/src/lib.rs @@ -233,7 +233,7 @@ where let dkg_query_client = if self.config.base.client.disabled_credentials_mode { None } else { - Some(default_query_dkg_client_from_config(&self.config.base)) + Some(default_query_dkg_client_from_config(&self.config.base)?) }; let mut base_builder = diff --git a/common/task/src/cancellation.rs b/common/task/src/cancellation.rs index 35009cc18e..d45296caca 100644 --- a/common/task/src/cancellation.rs +++ b/common/task/src/cancellation.rs @@ -265,6 +265,7 @@ impl ShutdownManager { } #[must_use] + #[track_caller] pub fn with_shutdown(mut self, shutdown: F) -> Self where F: Future, @@ -281,6 +282,7 @@ impl ShutdownManager { } #[cfg(unix)] + #[track_caller] pub fn with_shutdown_signal(self, signal_kind: SignalKind) -> std::io::Result { let mut sig = signal(signal_kind)?; Ok(self.with_shutdown(async move { @@ -289,6 +291,7 @@ impl ShutdownManager { } #[cfg(not(target_arch = "wasm32"))] + #[track_caller] pub fn with_interrupt_signal(self) -> Self { self.with_shutdown(async move { let _ = tokio::signal::ctrl_c().await; @@ -296,11 +299,13 @@ impl ShutdownManager { } #[cfg(unix)] + #[track_caller] pub fn with_terminate_signal(self) -> std::io::Result { self.with_shutdown_signal(SignalKind::terminate()) } #[cfg(unix)] + #[track_caller] pub fn with_quit_signal(self) -> std::io::Result { self.with_shutdown_signal(SignalKind::quit()) } diff --git a/nym-node/Cargo.toml b/nym-node/Cargo.toml index 38bad1d5d7..ba4f7fbaea 100644 --- a/nym-node/Cargo.toml +++ b/nym-node/Cargo.toml @@ -20,8 +20,10 @@ arc-swap = { workspace = true } bip39 = { workspace = true, features = ["zeroize"] } bs58.workspace = true bloomfilter = { workspace = true } -celes = { workspace = true } # country codes +celes = { workspace = true } +cfg-if = { workspace = true }# country codes colored = { workspace = true } +console-subscriber = { workspace = true, optional = true } csv = { workspace = true } clap = { workspace = true, features = ["cargo", "env"] } futures = { workspace = true } @@ -127,6 +129,8 @@ cargo_metadata = { workspace = true } criterion = { workspace = true, features = ["async_tokio"] } rand_chacha = { workspace = true } +[features] +tokio-console = ["console-subscriber"] [lints] workspace = true diff --git a/nym-node/src/cli/mod.rs b/nym-node/src/cli/mod.rs index 37e79bcd8f..eb51abc817 100644 --- a/nym-node/src/cli/mod.rs +++ b/nym-node/src/cli/mod.rs @@ -6,7 +6,6 @@ use crate::cli::commands::{ test_throughput, }; use crate::env::vars::{NYMNODE_CONFIG_ENV_FILE_ARG, NYMNODE_NO_BANNER_ARG}; -use crate::logging::setup_tracing_logger; use clap::{Parser, Subcommand}; use nym_bin_common::bin_info; use std::future::Future; @@ -56,7 +55,7 @@ impl Cli { pub(crate) fn execute(self) -> anyhow::Result<()> { // NOTE: `test_throughput` sets up its own logger as it has to include additional layers if !matches!(self.command, Commands::TestThroughput(..)) { - setup_tracing_logger()?; + crate::logging::setup_tracing_logger()?; } match self.command { diff --git a/nym-node/src/logging.rs b/nym-node/src/logging.rs index 4852b68635..e1812059be 100644 --- a/nym-node/src/logging.rs +++ b/nym-node/src/logging.rs @@ -5,8 +5,9 @@ use nym_bin_common::logging::{default_tracing_env_filter, default_tracing_fmt_la use tracing_subscriber::filter::Directive; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; +use tracing_subscriber::{EnvFilter, Layer}; -pub(crate) fn granual_filtered_env() -> anyhow::Result { +pub(crate) fn granual_filtered_env() -> anyhow::Result { fn directive_checked(directive: impl Into) -> anyhow::Result { directive.into().parse().map_err(From::from) } @@ -21,14 +22,23 @@ pub(crate) fn granual_filtered_env() -> anyhow::Result anyhow::Result { - Ok(tracing_subscriber::registry() - .with(default_tracing_fmt_layer(std::io::stderr)) - .with(granual_filtered_env()?)) -} - pub(crate) fn setup_tracing_logger() -> anyhow::Result<()> { - build_tracing_logger()?.init(); + let stderr_layer = + default_tracing_fmt_layer(std::io::stderr).with_filter(granual_filtered_env()?); + + cfg_if::cfg_if! {if #[cfg(feature = "tokio-console")] { + // instrument tokio console subscriber needs RUSTFLAGS="--cfg tokio_unstable" at build time + let console_layer = console_subscriber::spawn(); + + tracing_subscriber::registry() + .with(console_layer) + .with(stderr_layer) + .init(); + } else { + tracing_subscriber::registry() + .with(stderr_layer) + .init(); + }} Ok(()) }