diff --git a/Cargo.lock b/Cargo.lock index d004324f62a..e7c3b1f6222 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4752,12 +4752,14 @@ dependencies = [ "nym-coconut-dkg-common", "nym-config", "nym-contracts-common", + "nym-credential-proxy-requests", "nym-credential-storage", "nym-credential-utils", "nym-credentials", "nym-credentials-interface", "nym-crypto", "nym-ecash-contract-common", + "nym-ecash-time", "nym-id", "nym-mixnet-contract-common", "nym-multisig-contract-common", @@ -5007,16 +5009,6 @@ dependencies = [ "nym-multisig-contract-common", ] -[[package]] -name = "nym-common-models" -version = "0.1.0" -dependencies = [ - "anyhow", - "bincode", - "nym-crypto", - "serde", -] - [[package]] name = "nym-compact-ecash" version = "0.1.0" @@ -6056,19 +6048,13 @@ name = "nym-node-status-agent" version = "1.0.0-rc.1" dependencies = [ "anyhow", - "bincode", - "chrono", "clap 4.5.20", "nym-bin-common", - "nym-common-models", "nym-crypto", + "nym-node-status-client", "rand", - "reqwest 0.12.4", - "serde", - "serde_json", "tempfile", "tokio", - "tokio-util", "tracing", "tracing-subscriber", ] @@ -6079,7 +6065,6 @@ version = "1.0.0-rc.2" dependencies = [ "anyhow", "axum 0.7.7", - "bincode", "chrono", "clap 4.5.20", "cosmwasm-std", @@ -6087,11 +6072,11 @@ dependencies = [ "futures-util", "moka", "nym-bin-common", - "nym-common-models", "nym-crypto", "nym-explorer-client", "nym-network-defaults", "nym-node-requests", + "nym-node-status-client", "nym-task", "nym-validator-client", "regex", @@ -6114,6 +6099,21 @@ dependencies = [ "utoipauto", ] +[[package]] +name = "nym-node-status-client" +version = "0.1.0" +dependencies = [ + "anyhow", + "bincode", + "chrono", + "nym-crypto", + "nym-http-api-client", + "reqwest 0.12.4", + "serde", + "serde_json", + "tracing", +] + [[package]] name = "nym-node-tester-utils" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 7735cb8f59e..ae3f32e389d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,7 +61,6 @@ members = [ "common/ip-packet-requests", "common/ledger", "common/mixnode-common", - "common/models", "common/network-defaults", "common/node-tester-utils", "common/nonexhaustive-delayqueue", @@ -126,8 +125,9 @@ members = [ "nym-node", "nym-node/nym-node-http-api", "nym-node/nym-node-requests", - "nym-node-status-api", - "nym-node-status-agent", + "nym-node-status-api/nym-node-status-agent", + "nym-node-status-api/nym-node-status-api", + "nym-node-status-api/nym-node-status-client", "nym-outfox", "nym-validator-rewarder", "tools/echo-server", @@ -155,7 +155,6 @@ members = [ default-members = [ "clients/native", "clients/socks5", - "common/models", "explorer-api", "gateway", "mixnode", @@ -163,9 +162,9 @@ default-members = [ "nym-credential-proxy/nym-credential-proxy", "nym-data-observatory", "nym-node", - "nym-node-status-api", + "nym-node-status-api/nym-node-status-agent", + "nym-node-status-api/nym-node-status-api", "nym-validator-rewarder", - "nym-node-status-api", "service-providers/authenticator", "service-providers/ip-packet-router", "service-providers/network-requester", diff --git a/common/commands/Cargo.toml b/common/commands/Cargo.toml index c9bd11775db..d382cb696fc 100644 --- a/common/commands/Cargo.toml +++ b/common/commands/Cargo.toml @@ -48,6 +48,7 @@ nym-vesting-contract-common = { path = "../cosmwasm-smart-contracts/vesting-cont nym-coconut-dkg-common = { path = "../cosmwasm-smart-contracts/coconut-dkg" } nym-multisig-contract-common = { path = "../cosmwasm-smart-contracts/multisig-contract" } nym-ecash-contract-common = { path = "../cosmwasm-smart-contracts/ecash-contract" } +nym-ecash-time = { path = "../../common/ecash-time" } nym-sphinx = { path = "../../common/nymsphinx" } nym-client-core = { path = "../../common/client-core" } nym-config = { path = "../../common/config" } @@ -56,6 +57,7 @@ nym-credentials-interface = { path = "../../common/credentials-interface" } nym-credential-storage = { path = "../../common/credential-storage" } nym-credential-utils = { path = "../../common/credential-utils" } nym-id = { path = "../nym-id" } +nym-credential-proxy-requests = { path = "../../nym-credential-proxy/nym-credential-proxy-requests" } nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" } nym-types = { path = "../../common/types" } diff --git a/common/commands/src/internal/ecash/generate_keypair/mod.rs b/common/commands/src/internal/ecash/generate_keypair/mod.rs new file mode 100644 index 00000000000..7be40d986d5 --- /dev/null +++ b/common/commands/src/internal/ecash/generate_keypair/mod.rs @@ -0,0 +1,41 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use log::trace; +use nym_credentials_interface::{generate_keypair_user, generate_keypair_user_from_seed, Base58}; +use serde::{Deserialize, Serialize}; +use std::io::stdout; + +#[derive(Serialize, Deserialize)] +pub struct Bs58EncodedKeys { + pub secret_key: String, + pub public_key: String, +} + +#[derive(Debug, Parser)] +pub struct Args { + /// Secret value that's used for deriving underlying ecash keypair + #[clap(long)] + pub(crate) bs58_encoded_client_secret: Option, +} + +pub fn generate_ecash_keypair(args: Args) -> anyhow::Result<()> { + trace!("args: {args:?}"); + + let keypair = if let Some(secret) = args.bs58_encoded_client_secret { + let seed = bs58::decode(&secret).into_vec()?; + generate_keypair_user_from_seed(&seed) + } else { + generate_keypair_user() + }; + + let encoded = Bs58EncodedKeys { + secret_key: keypair.secret_key().to_bs58(), + public_key: keypair.public_key().to_bs58(), + }; + + serde_json::to_writer_pretty(stdout(), &encoded)?; + + Ok(()) +} diff --git a/common/commands/src/internal/ecash/mod.rs b/common/commands/src/internal/ecash/mod.rs new file mode 100644 index 00000000000..7a9ab05d9b9 --- /dev/null +++ b/common/commands/src/internal/ecash/mod.rs @@ -0,0 +1,23 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod generate_keypair; +pub mod withdrawal_request; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct InternalEcash { + #[clap(subcommand)] + pub command: InternalEcashCommands, +} + +#[derive(Debug, Subcommand)] +pub enum InternalEcashCommands { + /// Generate a dummy withdrawal request + GenerateWithdrawalRequest(withdrawal_request::Args), + + /// Generate dummy ecash keypair + GenerateKeypair(generate_keypair::Args), +} diff --git a/common/commands/src/internal/ecash/withdrawal_request.rs b/common/commands/src/internal/ecash/withdrawal_request.rs new file mode 100644 index 00000000000..bf56babdd9a --- /dev/null +++ b/common/commands/src/internal/ecash/withdrawal_request.rs @@ -0,0 +1,78 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use log::trace; +use nym_credential_proxy_requests::api::v1::ticketbook::models::TicketbookRequest; +use nym_credentials_interface::{ + generate_keypair_user, withdrawal_request, Base58, SecretKeyUser, TicketType, +}; +use nym_ecash_time::{ecash_default_expiration_date, EcashTime}; +use serde::{Deserialize, Serialize}; +use std::io::stdout; +use time::macros::format_description; +use time::Date; +use zeroize::Zeroizing; + +fn parse_date(raw: &str) -> Result { + let format = format_description!("[year]-[month]-[day]"); + Date::parse(raw, &format) +} + +#[derive(Serialize, Deserialize)] +pub struct Bs58EncodedOutput { + pub ecash_proxy_request: TicketbookRequest, + pub ecash_secret: String, + + /// Needed to later unblind shares + pub ecash_request_info_bs58: String, +} + +#[derive(Debug, Parser)] +pub struct Args { + /// Specify which type of ticketbook + #[clap(long, default_value_t = TicketType::V1MixnetEntry)] + pub(crate) ticketbook_type: TicketType, + + /// Set expiration date for the ticketbook + #[clap(long, value_parser = parse_date, default_value_t = ecash_default_expiration_date())] + pub(crate) expiration_date: Date, + + /// Provide ecash secret key (or generate a fresh one) + #[clap(long)] + pub(crate) ecash_secret_key_bs58: Option, +} + +pub async fn generate_withdrawal_request(args: Args) -> anyhow::Result<()> { + trace!("args: {args:?}"); + + let ecash_keypair = if let Some(secret_key) = args.ecash_secret_key_bs58 { + let secret_key = Zeroizing::new(bs58::decode(Zeroizing::new(secret_key)).into_vec()?); + let sk = SecretKeyUser::from_bytes(&secret_key)?; + sk.into() + } else { + generate_keypair_user() + }; + + let (withdrawal_request, request_info) = withdrawal_request( + ecash_keypair.secret_key(), + args.expiration_date.ecash_unix_timestamp(), + args.ticketbook_type.encode(), + )?; + + let encoded = Bs58EncodedOutput { + ecash_proxy_request: TicketbookRequest { + withdrawal_request: withdrawal_request.into(), + ecash_pubkey: ecash_keypair.public_key(), + expiration_date: args.expiration_date, + ticketbook_type: args.ticketbook_type, + is_freepass_request: false, + }, + ecash_secret: ecash_keypair.secret_key().to_bs58(), + ecash_request_info_bs58: request_info.to_bs58(), + }; + + serde_json::to_writer_pretty(stdout(), &encoded)?; + + Ok(()) +} diff --git a/common/commands/src/internal/mod.rs b/common/commands/src/internal/mod.rs new file mode 100644 index 00000000000..44fa4d26596 --- /dev/null +++ b/common/commands/src/internal/mod.rs @@ -0,0 +1,19 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod ecash; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct Internal { + #[clap(subcommand)] + pub command: InternalCommands, +} + +#[derive(Debug, Subcommand)] +pub enum InternalCommands { + /// Ecash related internal commands + Ecash(ecash::InternalEcash), +} diff --git a/common/commands/src/lib.rs b/common/commands/src/lib.rs index e3670ac5726..f48415d7a68 100644 --- a/common/commands/src/lib.rs +++ b/common/commands/src/lib.rs @@ -3,5 +3,6 @@ pub mod context; pub mod ecash; +pub mod internal; pub mod utils; pub mod validator; diff --git a/common/models/Cargo.toml b/common/models/Cargo.toml deleted file mode 100644 index 3192a83b532..00000000000 --- a/common/models/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "nym-common-models" -version = "0.1.0" -authors.workspace = true -repository.workspace = true -homepage.workspace = true -documentation.workspace = true -edition.workspace = true -license.workspace = true -rust-version.workspace = true -readme.workspace = true - -[dependencies] -anyhow = { workspace = true } -bincode = { workspace = true } -nym-crypto = { path = "../crypto", features = ["asymmetric", "serde"] } -serde = { workspace = true, features = ["derive"] } diff --git a/common/models/src/lib.rs b/common/models/src/lib.rs deleted file mode 100644 index 3d85e66947b..00000000000 --- a/common/models/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod ns_api; diff --git a/common/nym_offline_compact_ecash/src/scheme/keygen.rs b/common/nym_offline_compact_ecash/src/scheme/keygen.rs index f5926d9cb69..e49c6309df8 100644 --- a/common/nym_offline_compact_ecash/src/scheme/keygen.rs +++ b/common/nym_offline_compact_ecash/src/scheme/keygen.rs @@ -530,6 +530,15 @@ impl From for SecretKeyUser { } } +impl From for KeyPairUser { + fn from(value: SecretKeyUser) -> Self { + KeyPairUser { + public_key: value.public_key(), + secret_key: value, + } + } +} + impl KeyPairUser { #[allow(clippy::new_without_default)] pub fn new() -> Self { diff --git a/documentation/docs/components/outputs/api-scraping-outputs/time-now.md b/documentation/docs/components/outputs/api-scraping-outputs/time-now.md index a203dd666dc..1d7a6e3d3b5 100644 --- a/documentation/docs/components/outputs/api-scraping-outputs/time-now.md +++ b/documentation/docs/components/outputs/api-scraping-outputs/time-now.md @@ -1 +1 @@ -Wednesday, November 20th 2024, 15:53:00 UTC +Monday, November 25th 2024, 13:24:04 UTC diff --git a/documentation/docs/components/outputs/command-outputs/nym-api-help.md b/documentation/docs/components/outputs/command-outputs/nym-api-help.md index ca6467eb191..fcaf94ce6ba 100644 --- a/documentation/docs/components/outputs/command-outputs/nym-api-help.md +++ b/documentation/docs/components/outputs/command-outputs/nym-api-help.md @@ -1,5 +1,4 @@ ```sh -2024-11-20T15:53:01.702819Z  INFO nym-api/src/main.rs:40: Starting nym api... Usage: nym-api [OPTIONS] Commands: @@ -10,9 +9,9 @@ Commands: Options: -c, --config-env-file - Path pointing to an env file that configures the Nym API [env: NYMAPI_CONFIG_ENV_FILE_ARG=] + Path pointing to an env file that configures the Nym API --no-banner - A no-op flag included for consistency with other binaries (and compatibility with nymvisor, oops) [env: NYMAPI_NO_BANNER_ARG=] + A no-op flag included for consistency with other binaries (and compatibility with nymvisor, oops) -h, --help Print help -V, --version diff --git a/documentation/docs/components/outputs/command-outputs/nym-node-run-help.md b/documentation/docs/components/outputs/command-outputs/nym-node-run-help.md index 32508afe64e..0a5070b615a 100644 --- a/documentation/docs/components/outputs/command-outputs/nym-node-run-help.md +++ b/documentation/docs/components/outputs/command-outputs/nym-node-run-help.md @@ -44,8 +44,6 @@ Options: Specify whether detailed system crypto hardware information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_CRYPTO_HARDWARE=] [possible values: true, false] --mixnet-bind-address Address this node will bind to for listening for mixnet packets default: `0.0.0.0:1789` [env: NYMNODE_MIXNET_BIND_ADDRESS=] - --mixnet-announce-port - If applicable, custom port announced in the self-described API that other clients and nodes will use. Useful when the node is behind a proxy [env: NYMNODE_MIXNET_ANNOUNCE_PORT=] --nym-api-urls Addresses to nym APIs from which the node gets the view of the network [env: NYMNODE_NYM_APIS=] --nyxd-urls @@ -54,14 +52,14 @@ Options: Specifies whether the wireguard service is enabled on this node [env: NYMNODE_WG_ENABLED=] [possible values: true, false] --wireguard-bind-address Socket address this node will use for binding its wireguard interface. default: `0.0.0.0:51822` [env: NYMNODE_WG_BIND_ADDRESS=] + --wireguard-private-ip + Private IP address of the wireguard gateway. default: `10.1.0.1` [env: NYMNODE_WG_IP=] --wireguard-announced-port Port announced to external clients wishing to connect to the wireguard interface. Useful in the instances where the node is behind a proxy [env: NYMNODE_WG_ANNOUNCED_PORT=] --wireguard-private-network-prefix The prefix denoting the maximum number of the clients that can be connected via Wireguard. The maximum value for IPv4 is 32 and for IPv6 is 128 [env: NYMNODE_WG_PRIVATE_NETWORK_PREFIX=] --verloc-bind-address Socket address this node will use for binding its verloc API. default: `0.0.0.0:1790` [env: NYMNODE_VERLOC_BIND_ADDRESS=] - --verloc-announce-port - If applicable, custom port announced in the self-described API that other clients and nodes will use. Useful when the node is behind a proxy [env: NYMNODE_VERLOC_ANNOUNCE_PORT=] --entry-bind-address Socket address this node will use for binding its client websocket API. default: `0.0.0.0:9000` [env: NYMNODE_ENTRY_BIND_ADDRESS=] --announce-ws-port diff --git a/documentation/docs/pages/operators/changelog.mdx b/documentation/docs/pages/operators/changelog.mdx index ffcb57e8e0f..b498b5156c6 100644 --- a/documentation/docs/pages/operators/changelog.mdx +++ b/documentation/docs/pages/operators/changelog.mdx @@ -33,6 +33,136 @@ This page displays a full list of all the changes during our release cycle from + +## `v2024.13-magura-patched` + +- [Release binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.13-magura-patched) +- [`nym-node`](nodes/nym-node.mdx) version `1.1.11` + +```sh +nym-node +Binary Name: nym-node +Build Timestamp: 2024-11-22T14:30:48.067329245Z +Build Version: 1.1.11 +Commit SHA: 01c7b2819ee3d328deccd303b4113ff415d7e276 +Commit Date: 2024-11-22T10:50:59.000000000+01:00 +Commit Branch: HEAD +rustc Version: 1.82.0 +rustc Channel: stable +cargo Profile: release +``` + + + +After changes coming along with `v2024.13-magura` (`nym-node v1.1.10`), Nym Explorer is no longer picking all values correctly. Insstead of fixing this outdated explorer, we are working on a new one, coming out soon. + +[Nym Harbourmaster](https://harbourmaster.nymtech.net) has cache of 90min, expect your values to be updated with delay. We are aware of some issues with Nym Harbourmaster and working hard to resolve them in the upcoming explorer v2. To check your routing values in real time, you can use [`nym-gateway-probe`](nodes/performance-and-testing/gateway-probe). + + + +### Operators Updates & Tools + +- Updated [`network_tunnel_manager.sh`](https://github.com/nymtech/nym/blob/develop/scripts/network_tunnel_manager.sh) (moved to our monorepo) helps operators to configure their IP tables rules for `nymtun` and `wireguard` routing. + +- **Please re-run [routing configuration steps](https://nymtech.net/docs/operators/nodes/nym-node/configuration#routing-configuration) to update your routing settings.** + +- We found out that some operators have a wrong value for wireguard IP. Follow these steps to ensure your value is set to `10.1.0.1` (default on new nodes): + + +###### 1. Open your node config file: +```sh +nano $HOME/.nym/nym-nodes//config/config.toml + +# change for your local nym moniker for example: +# nano $HOME/.nym/nym-nodes/default-nym-node/config/config.toml +``` +###### 2. Control or change the value of wireguard private IP +- Scroll down to section starting with `[wireguard]` +- Find line `private_ip` and ensure it's set to value `10.1.0.1` +- The section will look like this: +```toml +[wireguard] +# Specifies whether the wireguard service is enabled on this node. +enabled = true + +# Socket address this node will use for binding its wireguard interface. +# default: `0.0.0.0:51822` +bind_address = '0.0.0.0:51822' + +# Private IP address of the wireguard gateway. +# default: `10.1.0.1` +private_ip = '10.1.0.1' +``` +###### 3. Save, exit and restart the service +- If you used `nano` editor - press `ctrl` + `x` and confirm the changes +- Run these commands to update the service with new values and restart your node process: +```sh +systemctl daemon-reload && service nym-node restart +``` + + +- New manual how to [run `nym-node` as non-root](nodes/nym-node/configuration#running-nym-node-as-a-non-root) + +- Since `v2024.13-magura`, operators do not update their node version in the wallet. [Manual upgrading steps](nodes/maintenance/manual-upgrade.mdx) has been updated accordingly. + +- CLI tool [`node_api_check.py`](nodes/performance-and-testing/node-api-check.mdx), helping operators to collect all API values about their nodes locally, is not up to date with the API changes introduced with `v2024.13-magura` release version. Please treat it as unstable before we fix it. + +#### Error Log + +In case you encounter this error: +``` +[ERROR] nym-node/src/node/mod.rs:628: the exit gateway subtask has failed with the following message: failed to start authenticator: internal wireguard error no private IP set for peer.. +``` + +You can follow these steps to make a workaround: + +
+ + + +###### 1. Find the error + +- In the node logs, locate the ERROR message which says `the exit gateway subtask has failed with the following message: failed to start authenticator: internal wireguard error no private IP set for peer KN5GPvkC+p6G/SM4PD2Z3ObAtRGiDjHPRnQOPpbdUQk=` + +- Copy the end part of that peer, later denoted as `` (in our example `GiDjHPRnQOPpbdUQk=`) to use later in the sql commands + +###### 2. Fix the issue in sqlite3 db + + +Be careful when running commands within sqlite database. + + +- Navigate to the data directory: +```sh +cd $HOME/.nym/nym-nodes//data +``` +- Enter the database: +```sh +sqlite3 clients.sqlite +``` + +- Run these commands: +```sh +# Change with your unique +select * from wireguard_peer where public_key like "%%" +# Make sure that only ONE line is returned and it contains the key + +delete from wireguard_peer where public_key like "%%"; +``` +- Confirm that peer has been removed by running this again: +```sh +select * from wireguard_peer where public_key like "%%"; +``` + +###### 3. Exit and restart the service + +Run `.quit` and: +```sh +systemctl restart nym-node.service +``` + + + ## `v2024.13-magura` Magura release represents a bigger milestone in [project Smoosh](archive/faq/smoosh-faq.mdx) development where `nym-node` is one binary able to perform any function in Nym Mixnet. This release is especially crucial for operators, please pay attention to the section [*Operators Updates & Tooling*](#operators-updates--tooling) below. @@ -70,15 +200,15 @@ cargo Profile: release - [Switch over the last set of jobs to arc runners](https://github.com/nymtech/nym/pull/4938): Switch over the remaining GH jobs using 16-core runners to self-hosted arc runners. Since we can't currently use Docker on the ubuntu-20.04 runners, remove the matrix notification steps -}> +}> Confirm that the deployment workflows work through manual testing - [x] cd-docs - [x] publish-sdk-npm -- [V2 performance monitoring feature flag](https://github.com/nymtech/nym/pull/4943): Feature flag to use v2 network monitor results in rewarding +- [V2 performance monitoring feature flag](https://github.com/nymtech/nym/pull/4943): Feature flag to use v2 network monitor results in rewarding -- [Add `utoipa` feature to nym-node](https://github.com/nymtech/nym/pull/4945): `cargo build -p nym-node` was failing, since its depending on `QueryParams` having `utoipa` traits derived +- [Add `utoipa` feature to nym-node](https://github.com/nymtech/nym/pull/4945): `cargo build -p nym-node` was failing, since its depending on `QueryParams` having `utoipa` traits derived - [Ticket type storage](https://github.com/nymtech/nym/pull/4947) @@ -103,8 +233,8 @@ Confirm that the deployment workflows work through manual testing - [chore: remove unused rocket code](https://github.com/nymtech/nym/pull/4968) - [add Dockerfile for nym node](https://github.com/nymtech/nym/pull/4972) - -- [`Product Data` Add session type based on ecash ticket received](https://github.com/nymtech/nym/pull/4974): Fire an `EcashTicket` event for the `GatewayStatisticsCollector`, when an Ecash ticket is being accepted. This allows to mark an active session as being a mixnet session or a vpn session. It also changes the format of the related self-described data, to accommodate that new session type. + +- [`Product Data` Add session type based on ecash ticket received](https://github.com/nymtech/nym/pull/4974): Fire an `EcashTicket` event for the `GatewayStatisticsCollector`, when an Ecash ticket is being accepted. This allows to mark an active session as being a mixnet session or a vpn session. It also changes the format of the related self-described data, to accommodate that new session type. - [Top up bandwidth](https://github.com/nymtech/nym/pull/4975) @@ -147,7 +277,7 @@ Confirm that the deployment workflows work through manual testing - log gw identity key - better agent testrun logging - log responses on server side - - change response code for agents + - change response code for agents - update sqlx data - fix agent - probe gw bug @@ -165,7 +295,7 @@ Confirm that the deployment workflows work through manual testing - [Allow custom http port to be reset](https://github.com/nymtech/nym/pull/5073) -- [Fix gateway decreasing bandwidth](https://github.com/nymtech/nym/pull/5075): Make sure to update the storage after each decrease with the new values. Also set the storage values to 0 on restart for existing peers, as kernel peers can't have those values set to 0 +- [Fix gateway decreasing bandwidth](https://github.com/nymtech/nym/pull/5075): Make sure to update the storage after each decrease with the new values. Also set the storage values to 0 on restart for existing peers, as kernel peers can't have those values set to 0 - [Fix expiration date as today + 7 days](https://github.com/nymtech/nym/pull/5076) @@ -187,7 +317,7 @@ Confirm that the deployment workflows work through manual testing - [Add NYM_VPN_API to env files](https://github.com/nymtech/nym/pull/5099) -- [Feature/force refresh node](https://github.com/nymtech/nym/pull/5101): currently if nodes update their role from say mixnode to entry-gateway, it might take quite a while for `nym-api` to pick up the change and thus they might be losing performance. With this change, the node will be force refreshed on its startup +- [Feature/force refresh node](https://github.com/nymtech/nym/pull/5101): currently if nodes update their role from say mixnode to entry-gateway, it might take quite a while for `nym-api` to pick up the change and thus they might be losing performance. With this change, the node will be force refreshed on its startup - [`nym-credential-proxy-requests`: reqwest use rustls-tls](https://github.com/nymtech/nym/pull/5116) @@ -205,7 +335,7 @@ Confirm that the deployment workflows work through manual testing - [Fix critical issues SI84 and SI85 from Cure53](https://github.com/nymtech/nym/pull/4758): This pull request fixes the following issues: - NYM-01-009 WP5: BLS12-381 EC signature bypasses in Coconut library (Critical) - NYM-01-014 WP5: Partial signature bypass in offline eCash (Critical) - + - [bugfix: correctly paginate through 'search_tx' endpoint](https://github.com/nymtech/nym/pull/4936): when `results.append(&mut res.txs);` was called, `res.txs` was always empty thus it was impossible to return more than page size number of results - [Fix broken build after merge](https://github.com/nymtech/nym/pull/4937) @@ -214,7 +344,7 @@ Confirm that the deployment workflows work through manual testing - dedicated commands to request specific blocks for processing - decreased websocket failure timeout - ensuring we do actually have sufficient number of blocks to process rewarding for given epoch - - additional error logging + - additional error logging - [bugfix: fix expected return type on /v1/gateways endpoint](https://github.com/nymtech/nym/pull/4965) @@ -224,7 +354,7 @@ Confirm that the deployment workflows work through manual testing - Faulty aggregation to invalid offline eCash signatures - Signature forgery of Pointcheval-Sanders schema -- [bugfix: client memory leak](https://github.com/nymtech/nym/pull/4991): This fixes memory leaks in all the clients. however, they were most prominent in `nym-api` during network monitoring due to the sheer amount of packets being pushed +- [bugfix: client memory leak](https://github.com/nymtech/nym/pull/4991): This fixes memory leaks in all the clients. however, they were most prominent in `nym-api` during network monitoring due to the sheer amount of packets being pushed - [Fix rustfmt in nym-credential-proxy](https://github.com/nymtech/nym/pull/4992) @@ -279,7 +409,7 @@ Confirm that the deployment workflows work through manual testing - [bugfix: make sure to assign correct node_id and identity during 'gateway_details' table migration](https://github.com/nymtech/nym/pull/5142) - [bugifx: assign 'node_id' when converting from 'GatewayDetails' to 'TestNode'](https://github.com/nymtech/nym/pull/5143) - + ### Operators Updates & Tooling @@ -292,7 +422,7 @@ Confirm that the deployment workflows work through manual testing - **[Operators release & rewards roadmap](tokenomics/mixnet-rewards.mdx#roadmap)** -- **New [Operators landing pag e](https://nymtech.net/operators) +- **New [Operators landing page](https://nymtech.net/operators)** - [Nym Harbourmaster](https://harbourmaster.nymtech.net) had a new tab `NODE SEARCH` where operators can easily search nodes by identity keys and owner accounts and get all public information listed. @@ -335,7 +465,7 @@ Confirm that the deployment workflows work through manual testing - Confirm the transaction -###### 5. Welcome to new episode of `nym-node`! +###### 5. Welcome to new episode of `nym-node`! @@ -360,13 +490,13 @@ Confirm that the deployment workflows work through manual testing - Currently in *Native rewarding*, the rewards are split equally across the [rewarded set of nodes](https://validator.nymtech.net/api/v1/epoch/reward_params) (which now = active set and it's size is 240 nodes) for both Mixnet mode and dVPN mode. Every node being assigned 1 / 240 work factor (hence *naive rewarding*). -#### Directory Services v2.1: API & Mixnet Contract Changes +#### Directory Services v2.1: API & Mixnet Contract Changes -Magura release brings [breaking changes on API](https://github.com/nymtech/nym/pull/4903) logic of Nym. New APIs will only communicate with `nym-node` from this release and newer. Also old version of APIs won't be able to communicate with the new version of `nym-node`. We are also moving towards completely removing Nym Explorer API, which now has been only used to report nodes location. +Magura release brings [breaking changes on API](https://github.com/nymtech/nym/pull/4903) logic of Nym. New APIs will only communicate with `nym-node` from this release and newer. Also old version of APIs won't be able to communicate with the new version of `nym-node`. We are also moving towards completely removing Nym Explorer API, which now has been only used to report nodes location. Any new bonded node will provide only the bare minimum information: host, identity key and optionally custom port of its HTTP api - we highly recommend to set that one up to `8080`. Everything else will be discovered via the self-described API for maximum flexibility. This also includes the sphinx key, meaning if the API is not exposed, the node will be unable to route any traffic. Furthermore, this allows to arbitrary change of `nym-node` from mixnode into a gateway modes (and vice versa) without losing any delegations. -The contract changes also mean any node functionality can get rewards. Rather than just with assigned mixing roles, gateways now also added into the pool. However, to be eligible for gateway rewarding, one must [migrate into a `nym-node`](#wallet-changes) on a smart contract level (or bond a new node). +The contract changes also mean any node functionality can get rewards. Rather than just with assigned mixing roles, gateways now also added into the pool. However, to be eligible for gateway rewarding, one must [migrate into a `nym-node`](#wallet-changes) on a smart contract level (or bond a new node). ##### API High Level Changes diff --git a/documentation/docs/pages/operators/nodes/maintenance/manual-upgrade.mdx b/documentation/docs/pages/operators/nodes/maintenance/manual-upgrade.mdx index 9139ebc7e92..a68d01b1fde 100644 --- a/documentation/docs/pages/operators/nodes/maintenance/manual-upgrade.mdx +++ b/documentation/docs/pages/operators/nodes/maintenance/manual-upgrade.mdx @@ -14,30 +14,27 @@ This page explains how to upgrade [`nym-node`](#nym-node-upgrade) or [`validator ## Nym node Upgrade -**Upgrading your node is a straight forward two-step process:** - - - -#### 1. Updating the binary and `~/.nym/nym-nodes//config/config.toml` on your VPS - -#### 2. Updating the node information in the [mixnet smart contract](https://nymtech.net/docs/nyx/mixnet-contract.html). This is the information that is present on the [mixnet explorer](https://explorer.nymtech.net). - - +Since `v2024.13-magura` (`nym-node v1.1.10`), **operators NO longer update node information in the Mixnet smart contract** (wallet version information), **only upgrade node binary** (on VPS), resulting in `~/.nym/nym-nodes//config/config.toml` update. Below are detailed steps how to do it: -###### 1. Upgrading node binary and information in config file +###### 1. Upgrade `nym-node` binary - Pause your node process. - If you run your node as `systemd` service (recommended), run: `service nym-node stop` - - Otherwise open the terminal window with your node logs and press `ctrl + c` + - Otherwise open the terminal window with your node logs and press once `ctrl + c` and wait for the node to terminate gracefully - Replace the existing `nym-node` binary with the newest binary (which you can either [compile yourself](../../binaries/building-nym.mdx) or [download](../../binaries/pre-built-binaries.mdx). +- To verify node version, run `./nym-node --version` + +###### 2. Restart the node + - [Re-run with the same values](../nym-node/setup.mdx#initialise--run) as you use to run your `nym-node`. If you want keep changes in your config file, use flag `-w` (`--write-changes`), **This will just update the config file, it will not overwrite existing keys**. - - If you automated your node with `systemd` (recommended) run: + +- If you automated your node with `systemd` (recommended), make sure you have all needed flags in `ExecStart` line of the service config file, and run: ```sh systemctl daemon-reload service nym-node start @@ -48,24 +45,18 @@ service nym-node start journalctl -f -u nym-node.service ``` -###### 2. Updating your node information in the smart contract -Follow these steps to update the information about your `nym-node` which is publicly available from the [`nym-api`](https://validator.nymtech.net/api/swagger/index.html) and information displayed on the [Mixnet explorer](https://explorer.nymtech.net). +###### 3. Check if your node is reporting the version correctly -You can either do this graphically via the Desktop Wallet, or the CLI. +- Open [Nym Harbourbourmaster](https://harbourmaster.nymtech.net), search your node and verify that everything is working as expected and your node shows expected version. + -
- Desktop Wallet (recommended), - CLI (superusers), - ]} defaultIndex="0"> - - - -
+ +After changes coming along with `v2024.13-magura` (`nym-node v1.1.10`), Nym Explorer is no longer picking all values correctly. Insstead of fixing this outdated explorer, we are working on a new one, coming out soon. - +[Nym Harbourmaster](https://harbourmaster.nymtech.net) has cache of 90min, expect your values to be updated with delay. We are aware of some issues with Nym Harbourmaster and working hard to resolve them in the upcoming explorer v2. To check your routing values in real time, you can use [`nym-gateway-probe`](../performance-and-testing/gateway-probe). + ## Validator Upgrade @@ -92,4 +83,3 @@ The most common reason for your validator being jailed is that it runs out of me Running the command `df -H` will return the size of the various partitions of your VPS. If the `/dev/sda` partition is almost full, try pruning some of the `.gz` syslog archives and restart your validator process. - diff --git a/documentation/docs/pages/operators/nodes/nym-node/configuration.mdx b/documentation/docs/pages/operators/nodes/nym-node/configuration.mdx index ac41036ce62..63ba5b3f0d6 100644 --- a/documentation/docs/pages/operators/nodes/nym-node/configuration.mdx +++ b/documentation/docs/pages/operators/nodes/nym-node/configuration.mdx @@ -426,6 +426,95 @@ journalctl -u nym-node.service -f -n 100 Make sure that you get the validation of all connectivity. If there are still any problems, please refer to [troubleshooting section](../../troubleshooting/vps-isp.mdx#incorrect-gateway-network-check). +## Running `nym-node` as a non-root + +Some operators prefer to run `nym-node` without root privileges. It's possible but still `nym-node` binary needs higher privileges for network-level operations demanding these permissions. Below is a guide how to go about such setup: + + +Copying nodes database and the `.nym/` directories from `/root/.nym` to `/home//.nym/` should be treated as experimental, therefore we would advise this section for operators starting new nodes, rather than tweaking an existing one. We will publish a detailed guide for changing permissions of an existing node soon. + + + +###### 1. Setup a new user + +- Define a variable `user_name` using your desired user name: +```sh +user_name="" +``` + +- Run: +```sh +user_home="/home/$user_name" + +if ! id "$user_name" &>/dev/null; then + sudo adduser --home "$user_home" --disabled-login --gecos "" "$user_name" +else + echo "user $user_name already exists" +fi +``` + +- And follow by: + +```sh +sudo usermod -aG sudo "$user_name" +``` + +- Optional: Add to sudoers group: +```sh +echo "$user_name ALL=(ALL) NOPASSWD:ALL" | sudo tee -a /etc/sudoers.d/$user_name +``` + +###### 2. Grant needed permissions for network-level operations + +While `nym-node` will be set as a user process, it requires higher privileges for network-level operations, set them up with this command: + +```sh +sudo setcap 'cap_net_bind_service=+ep cap_net_admin=+ep' nym-node +``` + +**After replacing or upgrading the binary, you must reapply these permissions each time!** + +###### 3. Edit service config file + +- Add these new lines to your `/etc/systemd/system/nym-node.service` [service config file](#systemd) + - `After=network.target` + - `Group=` + - `Type=simple` + +- Your service file will then look like this: + +```ini +[Unit] +Description=Nym Node +After=network.target +StartLimitInterval=350 +StartLimitBurst=10 + +[Service] +User= +Group= +Type=simple +LimitNOFILE=65536 +ExecStart=/nym-node run # add all the flags you use to run your node +KillSignal=SIGINT +Restart=on-failure +RestartSec=30 + +[Install] +WantedBy=multi-user.target +``` + +###### 4. Reload and restart the service + +```sh +systemctl daemon-reload && service nym-node restart +``` + +- If you want to follow the logs, run: +```sh +journalctl -u nym-node -f +``` + ## Next Steps diff --git a/documentation/docs/pages/operators/nodes/nym-node/setup.mdx b/documentation/docs/pages/operators/nodes/nym-node/setup.mdx index 8104e58fb33..31eb89308c2 100644 --- a/documentation/docs/pages/operators/nodes/nym-node/setup.mdx +++ b/documentation/docs/pages/operators/nodes/nym-node/setup.mdx @@ -17,15 +17,16 @@ This documentation page provides a guide on how to set up and run a [NYM NODE](. ```sh nym-node Binary Name: nym-node -Build Timestamp: 2024-11-18T17:02:50.947941194Z -Build Version: 1.1.10 -Commit SHA: b49ef643df86f0c670672429812c632fbbaf6cf1 -Commit Date: 2024-11-18T17:56:57.000000000+01:00 +Build Timestamp: 2024-11-22T14:30:48.067329245Z +Build Version: 1.1.11 +Commit SHA: 01c7b2819ee3d328deccd303b4113ff415d7e276 +Commit Date: 2024-11-22T10:50:59.000000000+01:00 Commit Branch: HEAD rustc Version: 1.82.0 rustc Channel: stable cargo Profile: release ``` + {/* COMMENTING THIS OUT ASS WE HAVE TO FIGURE OUT HOW TO SHOW THE LATEST VERSION FROM MASTER BRANCH */} diff --git a/documentation/docs/pages/operators/nodes/performance-and-testing/node-api-check.mdx b/documentation/docs/pages/operators/nodes/performance-and-testing/node-api-check.mdx index 34879843888..43867da0889 100644 --- a/documentation/docs/pages/operators/nodes/performance-and-testing/node-api-check.mdx +++ b/documentation/docs/pages/operators/nodes/performance-and-testing/node-api-check.mdx @@ -8,6 +8,10 @@ import NodeApiCheckQueryHelp from 'components/outputs/command-outputs/node-api-c # Node API Check + +CLI tool `node_api_check.py`, helping operators to collect all API values about their nodes locally, is not up to date with the API changes introduced with `v2024.13-magura` release version. Please treat it as unstable before we fix it. + + Operating a `nym-node` is not a *"set and forget"* endeavor, it takes some work. To diagnose node network performance through querying APIs, is a good knowledge to have. These are the main places to look for API endpoints regarding `nym-node`: @@ -93,9 +97,9 @@ python --version -###### 2. Install `node_api_check.py` and make executable +###### 2. Install `node_api_check.py` and make executable -To run the program you neet to have [`node_api_check.py`](https://github.com/nymtech/nym/tree/develop/scripts/node_api_check.py) and [`api_endpoints.json`](https://github.com/nymtech/nym/tree/develop/scripts/api_endpoints.json). +To run the program you neet to have [`node_api_check.py`](https://github.com/nymtech/nym/tree/develop/scripts/node_api_check.py) and [`api_endpoints.json`](https://github.com/nymtech/nym/tree/develop/scripts/api_endpoints.json). - If you [compiled from source](../../binaries/building-nym.mdx), you already have both of these files. Note that the latest version of this program may be on `develop` branch. @@ -159,4 +163,3 @@ Another command is `version_count` where at least one `nym-node` version is requ ```sh ./node_api_check version_count 1.1.0 1.1.1 1.1.2 1.1.3 --markdown ``` - diff --git a/documentation/docs/pages/operators/nodes/preliminary-steps/vps-setup.mdx b/documentation/docs/pages/operators/nodes/preliminary-steps/vps-setup.mdx index 940872c24e4..5864d3129de 100644 --- a/documentation/docs/pages/operators/nodes/preliminary-steps/vps-setup.mdx +++ b/documentation/docs/pages/operators/nodes/preliminary-steps/vps-setup.mdx @@ -232,6 +232,9 @@ username soft nofile 4096 Then reboot your server and restart your node. +## Running `nym-node` as a non-root + +Some operators prefer to run `nym-node` without root privileges. It's possible but still `nym-node` binary needs higher privileges for network-level operations demanding these permissions. If you are starting a new `nym-node` and want to run it as a non-root, follow [this guide](../nym-node/configuration#running-nym-node-as-a-non-root) before you proceed with the node setup sections. ## Ports reference tables diff --git a/documentation/docs/pages/operators/tokenomics.mdx b/documentation/docs/pages/operators/tokenomics.mdx index de8e2f66f84..0a65a0051f5 100644 --- a/documentation/docs/pages/operators/tokenomics.mdx +++ b/documentation/docs/pages/operators/tokenomics.mdx @@ -161,7 +161,7 @@ In dVPN (2-hop) mode every node which meets the performance criteria, including In both cases, the selection algorithm also looks whether the node runs with [Terms & Conditions](nodes/nym-node/setup.mdx#terms--conditions) accepted **AND** if it's not a legacy binary version. In case either of these criterias are not met, the node will have be excluded from the rewarded set selection. -To read more about rewards calculation, please see next page [*Nym Operators Rewards*](mixnet-rewards.md). +To read more about rewards calculation, please see next page [*Nym Operators Rewards*](tokenomics/mixnet-rewards.md). ## Query Validator API diff --git a/documentation/docs/pages/operators/tokenomics/mixnet-rewards.mdx b/documentation/docs/pages/operators/tokenomics/mixnet-rewards.mdx index 835339627a4..facd3860f30 100644 --- a/documentation/docs/pages/operators/tokenomics/mixnet-rewards.mdx +++ b/documentation/docs/pages/operators/tokenomics/mixnet-rewards.mdx @@ -153,7 +153,7 @@ The entire active set selection probablity: For a comparison we made an example with 5 nodes, where first number is node performance and second stake saturation (assuming all of them `config_score` = 1 and not 0):
- + > node_1 = 1.00 ^ 20 \* 1.0 = 1
> node_2 = 1.00 ^ 20 \* 0.5 = 0.5
> node_3 = 0.99 ^ 20 \* 1.0 = 0.818
diff --git a/nym-api/migrations/20241127100000_monitor_run_indexes.sql b/nym-api/migrations/20241127100000_monitor_run_indexes.sql new file mode 100644 index 00000000000..fd98b2613bc --- /dev/null +++ b/nym-api/migrations/20241127100000_monitor_run_indexes.sql @@ -0,0 +1,8 @@ +/* + * Copyright 2024 - Nym Technologies SA + * SPDX-License-Identifier: Apache-2.0 + */ + +CREATE INDEX IF NOT EXISTS monitor_run_timestamp on monitor_run(timestamp); +CREATE INDEX IF NOT EXISTS monitor_run_id on monitor_run(id); +CREATE INDEX IF NOT EXISTS testing_route_monitor_run_id on testing_route(monitor_run_id) diff --git a/nym-node-status-agent/.gitignore b/nym-node-status-agent/.gitignore deleted file mode 100644 index 4bb044ec5ef..00000000000 --- a/nym-node-status-agent/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -nym-gateway-probe -keys/ diff --git a/nym-node-status-api/.gitignore b/nym-node-status-api/.gitignore index 91459afabef..db7ea3635a7 100644 --- a/nym-node-status-api/.gitignore +++ b/nym-node-status-api/.gitignore @@ -1,6 +1,7 @@ +nym-node-status-agent/nym-gateway-probe +nym-node-status-agent/keys/ data/ enter_db.sh nym-gateway-probe -nym-node-status-api *.sqlite *.sqlite-journal diff --git a/nym-node-status-api/nym-node-status-agent/.gitignore b/nym-node-status-api/nym-node-status-agent/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/nym-node-status-agent/Cargo.toml b/nym-node-status-api/nym-node-status-agent/Cargo.toml similarity index 64% rename from nym-node-status-agent/Cargo.toml rename to nym-node-status-api/nym-node-status-agent/Cargo.toml index db64eeec993..d9f11f518ea 100644 --- a/nym-node-status-agent/Cargo.toml +++ b/nym-node-status-api/nym-node-status-agent/Cargo.toml @@ -1,7 +1,6 @@ # Copyright 2024 - Nym Technologies SA # SPDX-License-Identifier: Apache-2.0 - [package] name = "nym-node-status-agent" version = "1.0.0-rc.1" @@ -16,20 +15,14 @@ readme.workspace = true [dependencies] anyhow = { workspace = true} -bincode = { workspace = true } -chrono = { workspace = true } clap = { workspace = true, features = ["derive", "env"] } -nym-bin-common = { path = "../common/bin-common", features = ["models"]} -nym-common-models = { path = "../common/models" } -nym-crypto = { path = "../common/crypto", features = ["asymmetric", "rand"] } +nym-bin-common = { path = "../../common/bin-common", features = ["models"]} +nym-node-status-client = { path = "../nym-node-status-client" } +nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "rand"] } rand = { workspace = true } tokio = { workspace = true, features = ["macros", "rt-multi-thread", "process"] } -tokio-util = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } -reqwest = { workspace = true, features = ["json"] } -serde = { workspace = true } -serde_json = { workspace = true } [dev-dependencies] tempfile = { workspace = true } diff --git a/nym-node-status-agent/Dockerfile b/nym-node-status-api/nym-node-status-agent/Dockerfile similarity index 100% rename from nym-node-status-agent/Dockerfile rename to nym-node-status-api/nym-node-status-agent/Dockerfile diff --git a/nym-node-status-agent/gen_keypair.sh b/nym-node-status-api/nym-node-status-agent/gen_keypair.sh similarity index 100% rename from nym-node-status-agent/gen_keypair.sh rename to nym-node-status-api/nym-node-status-agent/gen_keypair.sh diff --git a/nym-node-status-agent/run.sh b/nym-node-status-api/nym-node-status-agent/run.sh similarity index 88% rename from nym-node-status-agent/run.sh rename to nym-node-status-api/nym-node-status-agent/run.sh index 0b384660319..680c87db8bd 100755 --- a/nym-node-status-agent/run.sh +++ b/nym-node-status-api/nym-node-status-agent/run.sh @@ -3,14 +3,14 @@ set -eu export ENVIRONMENT=${ENVIRONMENT:-"sandbox"} -probe_git_ref="nym-vpn-core-v1.0.0-rc.6" +probe_git_ref="nym-vpn-core-v1.0.0-rc.14" crate_root=$(dirname $(realpath "$0")) -monorepo_root=$(dirname "${crate_root}") +monorepo_root=$(realpath "${crate_root}/../..") + echo "Expecting nym-vpn-client repo at a sibling level of nym monorepo dir" gateway_probe_src=$(dirname "${monorepo_root}")/nym-vpn-client/nym-vpn-core echo "gateway_probe_src=$gateway_probe_src" -echo "crate_root=$crate_root" set -a source "${monorepo_root}/envs/${ENVIRONMENT}.env" @@ -30,9 +30,11 @@ function copy_gw_probe() { pushd $gateway_probe_src git fetch -a git checkout $probe_git_ref + cargo build --release --package nym-gateway-probe cp target/release/nym-gateway-probe "$crate_root" $crate_root/nym-gateway-probe --version + popd } @@ -44,7 +46,7 @@ function swarm() { local workers=$1 for ((i = 1; i <= workers; i++)); do - ../target/release/nym-node-status-agent run-probe & + ${monorepo_root}/target/release/nym-node-status-agent run-probe & done wait diff --git a/nym-node-status-agent/src/cli/generate_keypair.rs b/nym-node-status-api/nym-node-status-agent/src/cli/generate_keypair.rs similarity index 100% rename from nym-node-status-agent/src/cli/generate_keypair.rs rename to nym-node-status-api/nym-node-status-agent/src/cli/generate_keypair.rs diff --git a/nym-node-status-agent/src/cli/mod.rs b/nym-node-status-api/nym-node-status-agent/src/cli/mod.rs similarity index 100% rename from nym-node-status-agent/src/cli/mod.rs rename to nym-node-status-api/nym-node-status-agent/src/cli/mod.rs 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 new file mode 100644 index 00000000000..e9b7eaf44a6 --- /dev/null +++ b/nym-node-status-api/nym-node-status-agent/src/cli/run_probe.rs @@ -0,0 +1,32 @@ +use crate::cli::GwProbe; +use anyhow::Context; +use nym_crypto::asymmetric::ed25519::PrivateKey; + +pub(crate) async fn run_probe( + server_ip: &str, + server_port: u16, + ns_api_auth_key: &str, + probe_path: &str, +) -> anyhow::Result<()> { + let auth_key = PrivateKey::from_base58_string(ns_api_auth_key) + .context("Couldn't parse auth key, exiting")?; + + let ns_api_client = nym_node_status_client::NsApiClient::new(server_ip, server_port, auth_key); + + let probe = GwProbe::new(probe_path.to_string()); + + let version = probe.version().await; + tracing::info!("Probe version:\n{}", version); + + if let Some(testrun) = ns_api_client.request_testrun().await? { + let log = probe.run_and_get_log(&Some(testrun.gateway_identity_key)); + + ns_api_client + .submit_results(testrun.testrun_id, log, testrun.assigned_at_utc) + .await?; + } else { + tracing::info!("No testruns available, exiting") + } + + Ok(()) +} diff --git a/nym-node-status-agent/src/main.rs b/nym-node-status-api/nym-node-status-agent/src/main.rs similarity index 100% rename from nym-node-status-agent/src/main.rs rename to nym-node-status-api/nym-node-status-agent/src/main.rs diff --git a/nym-node-status-agent/src/probe.rs b/nym-node-status-api/nym-node-status-agent/src/probe.rs similarity index 100% rename from nym-node-status-agent/src/probe.rs rename to nym-node-status-api/nym-node-status-agent/src/probe.rs diff --git a/nym-node-status-api/.sqlx/query-06b17d1e5f61201a1b7542896ba55c69cd5c1a7e7d87073c94600c783a0a3984.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-06b17d1e5f61201a1b7542896ba55c69cd5c1a7e7d87073c94600c783a0a3984.json similarity index 100% rename from nym-node-status-api/.sqlx/query-06b17d1e5f61201a1b7542896ba55c69cd5c1a7e7d87073c94600c783a0a3984.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-06b17d1e5f61201a1b7542896ba55c69cd5c1a7e7d87073c94600c783a0a3984.json diff --git a/nym-node-status-api/.sqlx/query-1327b5118f9144dddbcf8edb11f7dc549cf503409fd6dfedcdc02dbcd61d5454.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-1327b5118f9144dddbcf8edb11f7dc549cf503409fd6dfedcdc02dbcd61d5454.json similarity index 100% rename from nym-node-status-api/.sqlx/query-1327b5118f9144dddbcf8edb11f7dc549cf503409fd6dfedcdc02dbcd61d5454.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-1327b5118f9144dddbcf8edb11f7dc549cf503409fd6dfedcdc02dbcd61d5454.json diff --git a/nym-node-status-api/.sqlx/query-18abc8fde56cf86baed7b4afa38f2c63cdf90f2f3b6d81afb9000bb0968dcaea.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-18abc8fde56cf86baed7b4afa38f2c63cdf90f2f3b6d81afb9000bb0968dcaea.json similarity index 100% rename from nym-node-status-api/.sqlx/query-18abc8fde56cf86baed7b4afa38f2c63cdf90f2f3b6d81afb9000bb0968dcaea.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-18abc8fde56cf86baed7b4afa38f2c63cdf90f2f3b6d81afb9000bb0968dcaea.json diff --git a/nym-node-status-api/.sqlx/query-2236299f9f691376db54cbd58ec5ceb89b9925cba46efcf4ed79ef0759a01129.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-2236299f9f691376db54cbd58ec5ceb89b9925cba46efcf4ed79ef0759a01129.json similarity index 100% rename from nym-node-status-api/.sqlx/query-2236299f9f691376db54cbd58ec5ceb89b9925cba46efcf4ed79ef0759a01129.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-2236299f9f691376db54cbd58ec5ceb89b9925cba46efcf4ed79ef0759a01129.json diff --git a/nym-node-status-api/.sqlx/query-3c584e211d07c511644c8079187965acf3bcfb3f84ba8d24ed645d79976cf784.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-3c584e211d07c511644c8079187965acf3bcfb3f84ba8d24ed645d79976cf784.json similarity index 100% rename from nym-node-status-api/.sqlx/query-3c584e211d07c511644c8079187965acf3bcfb3f84ba8d24ed645d79976cf784.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-3c584e211d07c511644c8079187965acf3bcfb3f84ba8d24ed645d79976cf784.json diff --git a/nym-node-status-api/.sqlx/query-3d3a1fa429e3090741c6b6a8e82e692afc04b51e8782bcbf59f1eb4116112536.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-3d3a1fa429e3090741c6b6a8e82e692afc04b51e8782bcbf59f1eb4116112536.json similarity index 100% rename from nym-node-status-api/.sqlx/query-3d3a1fa429e3090741c6b6a8e82e692afc04b51e8782bcbf59f1eb4116112536.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-3d3a1fa429e3090741c6b6a8e82e692afc04b51e8782bcbf59f1eb4116112536.json diff --git a/nym-node-status-api/.sqlx/query-3d5fc502f976f5081f01352856b8632c29c81bfafb043bb8744129cf9e0266ad.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-3d5fc502f976f5081f01352856b8632c29c81bfafb043bb8744129cf9e0266ad.json similarity index 100% rename from nym-node-status-api/.sqlx/query-3d5fc502f976f5081f01352856b8632c29c81bfafb043bb8744129cf9e0266ad.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-3d5fc502f976f5081f01352856b8632c29c81bfafb043bb8744129cf9e0266ad.json diff --git a/nym-node-status-api/.sqlx/query-418944f2eccb838cb3882f34469203c8569f03fdd39ce09d7b74177896e52a8c.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-418944f2eccb838cb3882f34469203c8569f03fdd39ce09d7b74177896e52a8c.json similarity index 100% rename from nym-node-status-api/.sqlx/query-418944f2eccb838cb3882f34469203c8569f03fdd39ce09d7b74177896e52a8c.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-418944f2eccb838cb3882f34469203c8569f03fdd39ce09d7b74177896e52a8c.json diff --git a/nym-node-status-api/.sqlx/query-46d76bc6d3fba2dae3b21511a36289dd776749dd7a20cda61b0480f2fba60889.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-46d76bc6d3fba2dae3b21511a36289dd776749dd7a20cda61b0480f2fba60889.json similarity index 100% rename from nym-node-status-api/.sqlx/query-46d76bc6d3fba2dae3b21511a36289dd776749dd7a20cda61b0480f2fba60889.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-46d76bc6d3fba2dae3b21511a36289dd776749dd7a20cda61b0480f2fba60889.json diff --git a/nym-node-status-api/.sqlx/query-4afcc6673890f795c2793f1e2f8570ee787fc7daf00fcb916f18d1cb7d6c8f08.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-4afcc6673890f795c2793f1e2f8570ee787fc7daf00fcb916f18d1cb7d6c8f08.json similarity index 100% rename from nym-node-status-api/.sqlx/query-4afcc6673890f795c2793f1e2f8570ee787fc7daf00fcb916f18d1cb7d6c8f08.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-4afcc6673890f795c2793f1e2f8570ee787fc7daf00fcb916f18d1cb7d6c8f08.json diff --git a/nym-node-status-api/.sqlx/query-4b61a4bc32333c92a8f5ad4ad0017b40dc01845f554b5479f37855d89b309e6f.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-4b61a4bc32333c92a8f5ad4ad0017b40dc01845f554b5479f37855d89b309e6f.json similarity index 100% rename from nym-node-status-api/.sqlx/query-4b61a4bc32333c92a8f5ad4ad0017b40dc01845f554b5479f37855d89b309e6f.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-4b61a4bc32333c92a8f5ad4ad0017b40dc01845f554b5479f37855d89b309e6f.json diff --git a/nym-node-status-api/.sqlx/query-670b7ed7d57a6986181b24be24ca667e8cacdf677ccb906415b3fe92be0c436b.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-670b7ed7d57a6986181b24be24ca667e8cacdf677ccb906415b3fe92be0c436b.json similarity index 100% rename from nym-node-status-api/.sqlx/query-670b7ed7d57a6986181b24be24ca667e8cacdf677ccb906415b3fe92be0c436b.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-670b7ed7d57a6986181b24be24ca667e8cacdf677ccb906415b3fe92be0c436b.json diff --git a/nym-node-status-api/.sqlx/query-6d7967b831b355d5f2c77950abc56f816956b0824c66a25da611dce688105d36.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-6d7967b831b355d5f2c77950abc56f816956b0824c66a25da611dce688105d36.json similarity index 100% rename from nym-node-status-api/.sqlx/query-6d7967b831b355d5f2c77950abc56f816956b0824c66a25da611dce688105d36.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-6d7967b831b355d5f2c77950abc56f816956b0824c66a25da611dce688105d36.json diff --git a/nym-node-status-api/.sqlx/query-6eb1a682cf13205cf701590021cdf795147ac3724e89df5b2f24f7215d87dce1.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-6eb1a682cf13205cf701590021cdf795147ac3724e89df5b2f24f7215d87dce1.json similarity index 100% rename from nym-node-status-api/.sqlx/query-6eb1a682cf13205cf701590021cdf795147ac3724e89df5b2f24f7215d87dce1.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-6eb1a682cf13205cf701590021cdf795147ac3724e89df5b2f24f7215d87dce1.json diff --git a/nym-node-status-api/.sqlx/query-6ef3efde571d46961244cd90420f3de5949a5ff2083453cb879af8a1689efe2f.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-6ef3efde571d46961244cd90420f3de5949a5ff2083453cb879af8a1689efe2f.json similarity index 100% rename from nym-node-status-api/.sqlx/query-6ef3efde571d46961244cd90420f3de5949a5ff2083453cb879af8a1689efe2f.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-6ef3efde571d46961244cd90420f3de5949a5ff2083453cb879af8a1689efe2f.json diff --git a/nym-node-status-api/.sqlx/query-71a455c705f9c25d3843ff2fb8629d1320a5eb10797cdb5a435455d22c6aeac1.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-71a455c705f9c25d3843ff2fb8629d1320a5eb10797cdb5a435455d22c6aeac1.json similarity index 100% rename from nym-node-status-api/.sqlx/query-71a455c705f9c25d3843ff2fb8629d1320a5eb10797cdb5a435455d22c6aeac1.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-71a455c705f9c25d3843ff2fb8629d1320a5eb10797cdb5a435455d22c6aeac1.json diff --git a/nym-node-status-api/.sqlx/query-7600823da7ce80b8ffda933608603a2752e28df775d1af8fd943a5fc8d7dc00d.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-7600823da7ce80b8ffda933608603a2752e28df775d1af8fd943a5fc8d7dc00d.json similarity index 100% rename from nym-node-status-api/.sqlx/query-7600823da7ce80b8ffda933608603a2752e28df775d1af8fd943a5fc8d7dc00d.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-7600823da7ce80b8ffda933608603a2752e28df775d1af8fd943a5fc8d7dc00d.json diff --git a/nym-node-status-api/.sqlx/query-788515c34588aec352773df4b6e6c5e41f3c0bb56a27648b5e25466b8634a578.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-788515c34588aec352773df4b6e6c5e41f3c0bb56a27648b5e25466b8634a578.json similarity index 100% rename from nym-node-status-api/.sqlx/query-788515c34588aec352773df4b6e6c5e41f3c0bb56a27648b5e25466b8634a578.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-788515c34588aec352773df4b6e6c5e41f3c0bb56a27648b5e25466b8634a578.json diff --git a/nym-node-status-api/.sqlx/query-8571faad2f66e08f24acfbfe036d17ca6eb090df7f6d52ef89c5d51564f8b45c.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-8571faad2f66e08f24acfbfe036d17ca6eb090df7f6d52ef89c5d51564f8b45c.json similarity index 100% rename from nym-node-status-api/.sqlx/query-8571faad2f66e08f24acfbfe036d17ca6eb090df7f6d52ef89c5d51564f8b45c.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-8571faad2f66e08f24acfbfe036d17ca6eb090df7f6d52ef89c5d51564f8b45c.json diff --git a/nym-node-status-api/.sqlx/query-86ff64db477a1d6235179b0b88d86b86d1b9be62336c9eac0eef44987a5451b5.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-86ff64db477a1d6235179b0b88d86b86d1b9be62336c9eac0eef44987a5451b5.json similarity index 100% rename from nym-node-status-api/.sqlx/query-86ff64db477a1d6235179b0b88d86b86d1b9be62336c9eac0eef44987a5451b5.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-86ff64db477a1d6235179b0b88d86b86d1b9be62336c9eac0eef44987a5451b5.json diff --git a/nym-node-status-api/.sqlx/query-930a41e612b4e964ae214843da190f6c66c14d4267a2cc2ca73354becc2c8bb8.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-930a41e612b4e964ae214843da190f6c66c14d4267a2cc2ca73354becc2c8bb8.json similarity index 100% rename from nym-node-status-api/.sqlx/query-930a41e612b4e964ae214843da190f6c66c14d4267a2cc2ca73354becc2c8bb8.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-930a41e612b4e964ae214843da190f6c66c14d4267a2cc2ca73354becc2c8bb8.json diff --git a/nym-node-status-api/.sqlx/query-c214c001acbbf79fa499816f36ec586c4c29c03efb4cf0c40b73a5c76159cf5c.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-c214c001acbbf79fa499816f36ec586c4c29c03efb4cf0c40b73a5c76159cf5c.json similarity index 100% rename from nym-node-status-api/.sqlx/query-c214c001acbbf79fa499816f36ec586c4c29c03efb4cf0c40b73a5c76159cf5c.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-c214c001acbbf79fa499816f36ec586c4c29c03efb4cf0c40b73a5c76159cf5c.json diff --git a/nym-node-status-api/.sqlx/query-c5e3cd7284b334df5aa979b1627ea1f6dc2aed00cedde25f2be3567e47064351.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-c5e3cd7284b334df5aa979b1627ea1f6dc2aed00cedde25f2be3567e47064351.json similarity index 100% rename from nym-node-status-api/.sqlx/query-c5e3cd7284b334df5aa979b1627ea1f6dc2aed00cedde25f2be3567e47064351.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-c5e3cd7284b334df5aa979b1627ea1f6dc2aed00cedde25f2be3567e47064351.json diff --git a/nym-node-status-api/.sqlx/query-c7ba2621becb9ac4b5dee0ce303dadfcf19095935867a51cbd5b8362d1505fcc.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-c7ba2621becb9ac4b5dee0ce303dadfcf19095935867a51cbd5b8362d1505fcc.json similarity index 100% rename from nym-node-status-api/.sqlx/query-c7ba2621becb9ac4b5dee0ce303dadfcf19095935867a51cbd5b8362d1505fcc.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-c7ba2621becb9ac4b5dee0ce303dadfcf19095935867a51cbd5b8362d1505fcc.json diff --git a/nym-node-status-api/.sqlx/query-d8ea93e781666e6267902170709ee2aa37f6163525bbdce1a4cebef4a285f8d9.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-d8ea93e781666e6267902170709ee2aa37f6163525bbdce1a4cebef4a285f8d9.json similarity index 100% rename from nym-node-status-api/.sqlx/query-d8ea93e781666e6267902170709ee2aa37f6163525bbdce1a4cebef4a285f8d9.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-d8ea93e781666e6267902170709ee2aa37f6163525bbdce1a4cebef4a285f8d9.json diff --git a/nym-node-status-api/.sqlx/query-e0c76a959276e3b0f44c720af9c74a5bf4912ee73468e62e7d0d96b1d9074cbe.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-e0c76a959276e3b0f44c720af9c74a5bf4912ee73468e62e7d0d96b1d9074cbe.json similarity index 100% rename from nym-node-status-api/.sqlx/query-e0c76a959276e3b0f44c720af9c74a5bf4912ee73468e62e7d0d96b1d9074cbe.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-e0c76a959276e3b0f44c720af9c74a5bf4912ee73468e62e7d0d96b1d9074cbe.json diff --git a/nym-node-status-api/.sqlx/query-f0a4316081d1be9444a87b95d933d31cb4bcc4071d31d8d2f7755e2d2c2e3e35.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-f0a4316081d1be9444a87b95d933d31cb4bcc4071d31d8d2f7755e2d2c2e3e35.json similarity index 100% rename from nym-node-status-api/.sqlx/query-f0a4316081d1be9444a87b95d933d31cb4bcc4071d31d8d2f7755e2d2c2e3e35.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-f0a4316081d1be9444a87b95d933d31cb4bcc4071d31d8d2f7755e2d2c2e3e35.json diff --git a/nym-node-status-api/.sqlx/query-f5048d9926a5f5329f7f3b96d43b925e033ceec4f8112258feb4ac9e96fc5924.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-f5048d9926a5f5329f7f3b96d43b925e033ceec4f8112258feb4ac9e96fc5924.json similarity index 100% rename from nym-node-status-api/.sqlx/query-f5048d9926a5f5329f7f3b96d43b925e033ceec4f8112258feb4ac9e96fc5924.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-f5048d9926a5f5329f7f3b96d43b925e033ceec4f8112258feb4ac9e96fc5924.json diff --git a/nym-node-status-api/.sqlx/query-ff9334ba7b670b218b2f9100e9ab5d2f2d08b2e53203aab9f07ea9b52acbd407.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-ff9334ba7b670b218b2f9100e9ab5d2f2d08b2e53203aab9f07ea9b52acbd407.json similarity index 100% rename from nym-node-status-api/.sqlx/query-ff9334ba7b670b218b2f9100e9ab5d2f2d08b2e53203aab9f07ea9b52acbd407.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-ff9334ba7b670b218b2f9100e9ab5d2f2d08b2e53203aab9f07ea9b52acbd407.json diff --git a/nym-node-status-api/Cargo.toml b/nym-node-status-api/nym-node-status-api/Cargo.toml similarity index 77% rename from nym-node-status-api/Cargo.toml rename to nym-node-status-api/nym-node-status-api/Cargo.toml index b7951996b8f..cc95396f866 100644 --- a/nym-node-status-api/Cargo.toml +++ b/nym-node-status-api/nym-node-status-api/Cargo.toml @@ -15,21 +15,20 @@ rust-version.workspace = true [dependencies] anyhow = { workspace = true } axum = { workspace = true, features = ["tokio", "macros"] } -bincode = { workspace = true } chrono = { workspace = true } clap = { workspace = true, features = ["cargo", "derive", "env", "string"] } cosmwasm-std = { workspace = true } envy = { workspace = true } futures-util = { workspace = true } moka = { workspace = true, features = ["future"] } -nym-bin-common = { path = "../common/bin-common", features = ["models"]} -nym-common-models = { path = "../common/models" } -nym-crypto = { path = "../common/crypto", features = ["asymmetric", "serde"] } -nym-explorer-client = { path = "../explorer-api/explorer-client" } -nym-network-defaults = { path = "../common/network-defaults" } -nym-validator-client = { path = "../common/client-libs/validator-client" } -nym-task = { path = "../common/task" } -nym-node-requests = { path = "../nym-node/nym-node-requests", features = ["openapi"] } +nym-bin-common = { path = "../../common/bin-common", features = ["models"]} +nym-node-status-client = { path = "../nym-node-status-client" } +nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "serde"] } +nym-explorer-client = { path = "../../explorer-api/explorer-client" } +nym-network-defaults = { path = "../../common/network-defaults" } +nym-validator-client = { path = "../../common/client-libs/validator-client" } +nym-task = { path = "../../common/task" } +nym-node-requests = { path = "../../nym-node/nym-node-requests", features = ["openapi"] } regex = { workspace = true } reqwest = { workspace = true } serde = { workspace = true, features = ["derive"] } diff --git a/nym-node-status-api/Dockerfile b/nym-node-status-api/nym-node-status-api/Dockerfile similarity index 100% rename from nym-node-status-api/Dockerfile rename to nym-node-status-api/nym-node-status-api/Dockerfile diff --git a/nym-node-status-api/Dockerfile.dev b/nym-node-status-api/nym-node-status-api/Dockerfile.dev similarity index 100% rename from nym-node-status-api/Dockerfile.dev rename to nym-node-status-api/nym-node-status-api/Dockerfile.dev diff --git a/nym-node-status-api/build.rs b/nym-node-status-api/nym-node-status-api/build.rs similarity index 100% rename from nym-node-status-api/build.rs rename to nym-node-status-api/nym-node-status-api/build.rs diff --git a/nym-node-status-api/launch_node_status_api.sh b/nym-node-status-api/nym-node-status-api/launch_node_status_api.sh similarity index 62% rename from nym-node-status-api/launch_node_status_api.sh rename to nym-node-status-api/nym-node-status-api/launch_node_status_api.sh index 26a97fcbabf..24b9a68ae8e 100755 --- a/nym-node-status-api/launch_node_status_api.sh +++ b/nym-node-status-api/nym-node-status-api/launch_node_status_api.sh @@ -2,29 +2,23 @@ set -e -export RUST_LOG=${RUST_LOG:-debug} - export NYM_API_CLIENT_TIMEOUT=60 export EXPLORER_CLIENT_TIMEOUT=60 export NODE_STATUS_API_TESTRUN_REFRESH_INTERVAL=120 -# public keys corresponding to the agents NS API is expecting to be contacted from -export NODE_STATUS_API_AGENT_KEY_LIST="H4z8kx5Kkf5JMQHhxaW1MwYndjKCDHC7HsVhHTFfBZ4J, -5c2GW61135DEr73DxGrR4DR22BLEujvm1k8GYEjRB9at, -3PSFDH2iSJ61KoDNyJpAiw42xS5smV5iBXWnRGTmk2du, -2AH7pJL5PErbSFhZdu3uH8cKa1h1tyCUfSRUm6E5EBz8, -6wQ9ifPFm2EB73BrwpGSd3Ek7GFA5kiAMQDP2ox6JKZw, -G1tevJBnzaQ6zCUsFsxtGJf45BqCTDgzpEz6Sgxks8EH, -FwjL2nGrtgQQ48fPqAUzUZ8UkQZtMtgehqTqj4PQopvh, -Eujj4GmvwQBgHZaNSyqUbjMFSsnXWPSjEYUPgAsKmx1A, -5ZnfSGxW6EKcFxB8jftb9V3f897VpwpZtf7kCPYzB595, -H9kuRd8BGjEUD8Grh5U9YUPN5ZaQmSYz8U44R72AffKM" + +# public counterpart of the agent's private key. +# For TESTING only. NOT used in any other environment +export NODE_STATUS_API_AGENT_KEY_LIST="H4z8kx5Kkf5JMQHhxaW1MwYndjKCDHC7HsVhHTFfBZ4J" export ENVIRONMENT=${ENVIRONMENT:-"sandbox"} +script_dir=$(dirname $(realpath "$0")) +monorepo_root=$(realpath "${script_dir}/../..") + function run_bare() { # export necessary env vars set -a - source ../envs/${ENVIRONMENT}.env + source "${monorepo_root}/envs/${ENVIRONMENT}.env" set +a export RUST_LOG=debug diff --git a/nym-node-status-api/migrations/000_init.sql b/nym-node-status-api/nym-node-status-api/migrations/000_init.sql similarity index 100% rename from nym-node-status-api/migrations/000_init.sql rename to nym-node-status-api/nym-node-status-api/migrations/000_init.sql diff --git a/nym-node-status-api/migrations/001_last_assigned_utc.sql b/nym-node-status-api/nym-node-status-api/migrations/001_last_assigned_utc.sql similarity index 100% rename from nym-node-status-api/migrations/001_last_assigned_utc.sql rename to nym-node-status-api/nym-node-status-api/migrations/001_last_assigned_utc.sql diff --git a/nym-node-status-api/src/cli/mod.rs b/nym-node-status-api/nym-node-status-api/src/cli/mod.rs similarity index 100% rename from nym-node-status-api/src/cli/mod.rs rename to nym-node-status-api/nym-node-status-api/src/cli/mod.rs diff --git a/nym-node-status-api/src/db/mod.rs b/nym-node-status-api/nym-node-status-api/src/db/mod.rs similarity index 100% rename from nym-node-status-api/src/db/mod.rs rename to nym-node-status-api/nym-node-status-api/src/db/mod.rs diff --git a/nym-node-status-api/src/db/models.rs b/nym-node-status-api/nym-node-status-api/src/db/models.rs similarity index 100% rename from nym-node-status-api/src/db/models.rs rename to nym-node-status-api/nym-node-status-api/src/db/models.rs diff --git a/nym-node-status-api/src/db/queries/gateways.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/gateways.rs similarity index 100% rename from nym-node-status-api/src/db/queries/gateways.rs rename to nym-node-status-api/nym-node-status-api/src/db/queries/gateways.rs diff --git a/nym-node-status-api/src/db/queries/misc.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/misc.rs similarity index 100% rename from nym-node-status-api/src/db/queries/misc.rs rename to nym-node-status-api/nym-node-status-api/src/db/queries/misc.rs diff --git a/nym-node-status-api/src/db/queries/mixnodes.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/mixnodes.rs similarity index 100% rename from nym-node-status-api/src/db/queries/mixnodes.rs rename to nym-node-status-api/nym-node-status-api/src/db/queries/mixnodes.rs diff --git a/nym-node-status-api/src/db/queries/mod.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/mod.rs similarity index 100% rename from nym-node-status-api/src/db/queries/mod.rs rename to nym-node-status-api/nym-node-status-api/src/db/queries/mod.rs diff --git a/nym-node-status-api/src/db/queries/summary.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/summary.rs similarity index 100% rename from nym-node-status-api/src/db/queries/summary.rs rename to nym-node-status-api/nym-node-status-api/src/db/queries/summary.rs diff --git a/nym-node-status-api/src/db/queries/testruns.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/testruns.rs similarity index 100% rename from nym-node-status-api/src/db/queries/testruns.rs rename to nym-node-status-api/nym-node-status-api/src/db/queries/testruns.rs diff --git a/nym-node-status-api/src/http/api/gateways.rs b/nym-node-status-api/nym-node-status-api/src/http/api/gateways.rs similarity index 100% rename from nym-node-status-api/src/http/api/gateways.rs rename to nym-node-status-api/nym-node-status-api/src/http/api/gateways.rs diff --git a/nym-node-status-api/src/http/api/mixnodes.rs b/nym-node-status-api/nym-node-status-api/src/http/api/mixnodes.rs similarity index 100% rename from nym-node-status-api/src/http/api/mixnodes.rs rename to nym-node-status-api/nym-node-status-api/src/http/api/mixnodes.rs diff --git a/nym-node-status-api/src/http/api/mod.rs b/nym-node-status-api/nym-node-status-api/src/http/api/mod.rs similarity index 100% rename from nym-node-status-api/src/http/api/mod.rs rename to nym-node-status-api/nym-node-status-api/src/http/api/mod.rs diff --git a/nym-node-status-api/src/http/api/services/json_path.rs b/nym-node-status-api/nym-node-status-api/src/http/api/services/json_path.rs similarity index 100% rename from nym-node-status-api/src/http/api/services/json_path.rs rename to nym-node-status-api/nym-node-status-api/src/http/api/services/json_path.rs diff --git a/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 similarity index 100% rename from nym-node-status-api/src/http/api/services/mod.rs rename to nym-node-status-api/nym-node-status-api/src/http/api/services/mod.rs diff --git a/nym-node-status-api/src/http/api/summary.rs b/nym-node-status-api/nym-node-status-api/src/http/api/summary.rs similarity index 100% rename from nym-node-status-api/src/http/api/summary.rs rename to nym-node-status-api/nym-node-status-api/src/http/api/summary.rs diff --git a/nym-node-status-api/src/http/api/testruns.rs b/nym-node-status-api/nym-node-status-api/src/http/api/testruns.rs similarity index 98% rename from nym-node-status-api/src/http/api/testruns.rs rename to nym-node-status-api/nym-node-status-api/src/http/api/testruns.rs index 6f5ab862eab..3e34c09ed61 100644 --- a/nym-node-status-api/src/http/api/testruns.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api/testruns.rs @@ -1,12 +1,3 @@ -use axum::extract::DefaultBodyLimit; -use axum::Json; -use axum::{ - extract::{Path, State}, - Router, -}; -use nym_common_models::ns_api::{get_testrun, submit_results, VerifiableRequest}; -use reqwest::StatusCode; - use crate::db::models::TestRunStatus; use crate::db::queries; use crate::testruns::now_utc; @@ -18,6 +9,17 @@ use crate::{ state::AppState, }, }; +use axum::extract::DefaultBodyLimit; +use axum::Json; +use axum::{ + extract::{Path, State}, + Router, +}; +use nym_node_status_client::{ + auth::VerifiableRequest, + models::{get_testrun, submit_results}, +}; +use reqwest::StatusCode; // TODO dz consider adding endpoint to trigger testrun scan for a given gateway_id // like in H< src/http/testruns.rs diff --git a/nym-node-status-api/src/http/api_docs.rs b/nym-node-status-api/nym-node-status-api/src/http/api_docs.rs similarity index 87% rename from nym-node-status-api/src/http/api_docs.rs rename to nym-node-status-api/nym-node-status-api/src/http/api_docs.rs index 9ac5238fc4d..aa86a56ab0a 100644 --- a/nym-node-status-api/src/http/api_docs.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/api_docs.rs @@ -5,7 +5,7 @@ use utoipauto::utoipauto; // manually import external structs which are behind feature flags because they // can't be automatically discovered // https://github.com/ProbablyClem/utoipauto/issues/13#issuecomment-1974911829 -#[utoipauto(paths = "./nym-node-status-api/src")] +#[utoipauto(paths = "./nym-node-status-api/nym-node-status-api/src")] #[derive(OpenApi)] #[openapi( info(title = "Node Status API"), diff --git a/nym-node-status-api/src/http/error.rs b/nym-node-status-api/nym-node-status-api/src/http/error.rs similarity index 100% rename from nym-node-status-api/src/http/error.rs rename to nym-node-status-api/nym-node-status-api/src/http/error.rs diff --git a/nym-node-status-api/src/http/mod.rs b/nym-node-status-api/nym-node-status-api/src/http/mod.rs similarity index 100% rename from nym-node-status-api/src/http/mod.rs rename to nym-node-status-api/nym-node-status-api/src/http/mod.rs diff --git a/nym-node-status-api/src/http/models.rs b/nym-node-status-api/nym-node-status-api/src/http/models.rs similarity index 97% rename from nym-node-status-api/src/http/models.rs rename to nym-node-status-api/nym-node-status-api/src/http/models.rs index 82011fc286c..aee2124b6c0 100644 --- a/nym-node-status-api/src/http/models.rs +++ b/nym-node-status-api/nym-node-status-api/src/http/models.rs @@ -2,7 +2,7 @@ use nym_node_requests::api::v1::node::models::NodeDescription; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; -pub(crate) use nym_common_models::ns_api::TestrunAssignment; +pub(crate) use nym_node_status_client::models::TestrunAssignment; #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct Gateway { diff --git a/nym-node-status-api/src/http/server.rs b/nym-node-status-api/nym-node-status-api/src/http/server.rs similarity index 100% rename from nym-node-status-api/src/http/server.rs rename to nym-node-status-api/nym-node-status-api/src/http/server.rs diff --git a/nym-node-status-api/src/http/state.rs b/nym-node-status-api/nym-node-status-api/src/http/state.rs similarity index 100% rename from nym-node-status-api/src/http/state.rs rename to nym-node-status-api/nym-node-status-api/src/http/state.rs diff --git a/nym-node-status-api/src/logging.rs b/nym-node-status-api/nym-node-status-api/src/logging.rs similarity index 100% rename from nym-node-status-api/src/logging.rs rename to nym-node-status-api/nym-node-status-api/src/logging.rs diff --git a/nym-node-status-api/src/main.rs b/nym-node-status-api/nym-node-status-api/src/main.rs similarity index 100% rename from nym-node-status-api/src/main.rs rename to nym-node-status-api/nym-node-status-api/src/main.rs diff --git a/nym-node-status-api/src/monitor/mod.rs b/nym-node-status-api/nym-node-status-api/src/monitor/mod.rs similarity index 100% rename from nym-node-status-api/src/monitor/mod.rs rename to nym-node-status-api/nym-node-status-api/src/monitor/mod.rs diff --git a/nym-node-status-api/src/testruns/mod.rs b/nym-node-status-api/nym-node-status-api/src/testruns/mod.rs similarity index 100% rename from nym-node-status-api/src/testruns/mod.rs rename to nym-node-status-api/nym-node-status-api/src/testruns/mod.rs diff --git a/nym-node-status-api/src/testruns/models.rs b/nym-node-status-api/nym-node-status-api/src/testruns/models.rs similarity index 100% rename from nym-node-status-api/src/testruns/models.rs rename to nym-node-status-api/nym-node-status-api/src/testruns/models.rs diff --git a/nym-node-status-api/src/testruns/queue.rs b/nym-node-status-api/nym-node-status-api/src/testruns/queue.rs similarity index 100% rename from nym-node-status-api/src/testruns/queue.rs rename to nym-node-status-api/nym-node-status-api/src/testruns/queue.rs diff --git a/nym-node-status-api/nym-node-status-client/Cargo.toml b/nym-node-status-api/nym-node-status-client/Cargo.toml new file mode 100644 index 00000000000..a7dc5899fb7 --- /dev/null +++ b/nym-node-status-api/nym-node-status-client/Cargo.toml @@ -0,0 +1,25 @@ +# Copyright 2024 - Nym Technologies SA +# SPDX-License-Identifier: Apache-2.0 + +[package] +name = "nym-node-status-client" +version = "0.1.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true +rust-version.workspace = true +readme.workspace = true + +[dependencies] +anyhow = { workspace = true } +chrono = { workspace = true } +bincode = { workspace = true } +nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "serde"] } +nym-http-api-client = { path = "../../common/http-api-client" } +reqwest = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +tracing = { workspace = true } diff --git a/nym-node-status-api/nym-node-status-client/src/api.rs b/nym-node-status-api/nym-node-status-client/src/api.rs new file mode 100644 index 00000000000..46d2fb7cd46 --- /dev/null +++ b/nym-node-status-api/nym-node-status-client/src/api.rs @@ -0,0 +1,18 @@ +use std::fmt::Display; + +pub(super) struct ApiPaths { + server_address: String, +} + +impl ApiPaths { + pub(super) fn new(server_address: String) -> Self { + Self { server_address } + } + pub(super) fn request_testrun(&self) -> String { + format!("{}/internal/testruns", self.server_address) + } + + pub(super) fn submit_results(&self, testrun_id: impl Display) -> String { + format!("{}/internal/testruns/{}", self.server_address, testrun_id) + } +} diff --git a/nym-node-status-api/nym-node-status-client/src/auth.rs b/nym-node-status-api/nym-node-status-client/src/auth.rs new file mode 100644 index 00000000000..263079dcc66 --- /dev/null +++ b/nym-node-status-api/nym-node-status-client/src/auth.rs @@ -0,0 +1,30 @@ +use nym_crypto::asymmetric::ed25519::{PublicKey, Signature, SignatureError}; + +pub trait SignedRequest { + type Payload: serde::Serialize; + + fn public_key(&self) -> &PublicKey; + fn signature(&self) -> &Signature; + fn payload(&self) -> &Self::Payload; +} + +pub trait VerifiableRequest: SignedRequest { + type Error: From + From; + + fn verify_signature(&self) -> Result<(), Self::Error> { + bincode::serialize(self.payload()) + .map_err(Self::Error::from) + .and_then(|serialized| { + self.public_key() + .verify(serialized, self.signature()) + .map_err(Self::Error::from) + }) + } +} + +impl VerifiableRequest for T +where + T: SignedRequest, +{ + type Error = anyhow::Error; +} diff --git a/nym-node-status-agent/src/cli/run_probe.rs b/nym-node-status-api/nym-node-status-client/src/lib.rs similarity index 61% rename from nym-node-status-agent/src/cli/run_probe.rs rename to nym-node-status-api/nym-node-status-client/src/lib.rs index 3ffd90d46c4..260b1b510d3 100644 --- a/nym-node-status-agent/src/cli/run_probe.rs +++ b/nym-node-status-api/nym-node-status-client/src/lib.rs @@ -1,62 +1,35 @@ -use anyhow::{bail, Context}; -use nym_common_models::ns_api::{get_testrun, submit_results, TestrunAssignment}; +use crate::models::{get_testrun, submit_results, TestrunAssignment}; +use anyhow::bail; +use api::ApiPaths; use nym_crypto::asymmetric::ed25519::{PrivateKey, Signature}; -use std::fmt::Display; use tracing::instrument; -use crate::cli::GwProbe; +mod api; +pub mod auth; +pub mod models; -const INTERNAL_TESTRUNS: &str = "internal/testruns"; - -pub(crate) async fn run_probe( - server_ip: &str, - server_port: u16, - ns_api_auth_key: &str, - probe_path: &str, -) -> anyhow::Result<()> { - let auth_key = PrivateKey::from_base58_string(ns_api_auth_key) - .context("Couldn't parse auth key, exiting")?; - let ns_api_client = Client::new(server_ip, server_port, auth_key); - - let probe = GwProbe::new(probe_path.to_string()); - - let version = probe.version().await; - tracing::info!("Probe version:\n{}", version); - - if let Some(testrun) = ns_api_client.request_testrun().await? { - let log = probe.run_and_get_log(&Some(testrun.gateway_identity_key)); - - ns_api_client - .submit_results(testrun.testrun_id, log, testrun.assigned_at_utc) - .await?; - } else { - tracing::info!("No testruns available, exiting") - } - - Ok(()) -} - -struct Client { - server_address: String, +pub struct NsApiClient { + api: ApiPaths, client: reqwest::Client, auth_key: PrivateKey, } -impl Client { +impl NsApiClient { pub fn new(server_ip: &str, server_port: u16, auth_key: PrivateKey) -> Self { let server_address = format!("{}:{}", server_ip, server_port); + let api = ApiPaths::new(server_address); let client = reqwest::Client::new(); Self { - server_address, + api, client, auth_key, } } #[instrument(level = "debug", skip_all)] - pub(crate) async fn request_testrun(&self) -> anyhow::Result> { - let target_url = self.api_with_subpath(None::); + pub async fn request_testrun(&self) -> anyhow::Result> { + let target_url = self.api.request_testrun(); let payload = get_testrun::Payload { agent_public_key: self.auth_key.public_key(), @@ -93,13 +66,13 @@ impl Client { } #[instrument(level = "debug", skip(self, probe_result))] - pub(crate) async fn submit_results( + pub async fn submit_results( &self, testrun_id: i64, probe_result: String, assigned_at_utc: i64, ) -> anyhow::Result<()> { - let target_url = self.api_with_subpath(Some(testrun_id)); + let target_url = self.api.submit_results(testrun_id); let payload = submit_results::Payload { probe_result, @@ -129,12 +102,4 @@ impl Client { let signed = self.auth_key.sign(&serialized); Ok(signed) } - - fn api_with_subpath(&self, subpath: Option) -> String { - if let Some(subpath) = subpath { - format!("{}/{}/{}", self.server_address, INTERNAL_TESTRUNS, subpath) - } else { - format!("{}/{}", self.server_address, INTERNAL_TESTRUNS) - } - } } diff --git a/common/models/src/ns_api.rs b/nym-node-status-api/nym-node-status-client/src/models.rs similarity index 67% rename from common/models/src/ns_api.rs rename to nym-node-status-api/nym-node-status-client/src/models.rs index 6f4b00a888c..05860259ba4 100644 --- a/common/models/src/ns_api.rs +++ b/nym-node-status-api/nym-node-status-client/src/models.rs @@ -1,7 +1,9 @@ -use nym_crypto::asymmetric::ed25519::{PublicKey, Signature, SignatureError}; +use nym_crypto::asymmetric::ed25519::{PublicKey, Signature}; use serde::{Deserialize, Serialize}; pub mod get_testrun { + use crate::auth::SignedRequest; + use super::*; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Payload { @@ -40,6 +42,8 @@ pub struct TestrunAssignment { } pub mod submit_results { + use crate::auth::SignedRequest; + use super::*; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Payload { @@ -70,32 +74,3 @@ pub mod submit_results { } } } - -pub trait SignedRequest { - type Payload: serde::Serialize; - - fn public_key(&self) -> &PublicKey; - fn signature(&self) -> &Signature; - fn payload(&self) -> &Self::Payload; -} - -pub trait VerifiableRequest: SignedRequest { - type Error: From + From; - - fn verify_signature(&self) -> Result<(), Self::Error> { - bincode::serialize(self.payload()) - .map_err(Self::Error::from) - .and_then(|serialized| { - self.public_key() - .verify(serialized, self.signature()) - .map_err(Self::Error::from) - }) - } -} - -impl VerifiableRequest for T -where - T: SignedRequest, -{ - type Error = anyhow::Error; -} diff --git a/scripts/network_tunnel_manager.sh b/scripts/network_tunnel_manager.sh index 54ca4e653ca..6bb7d1275d2 100644 --- a/scripts/network_tunnel_manager.sh +++ b/scripts/network_tunnel_manager.sh @@ -11,11 +11,12 @@ else echo "iptables-persistent is already installed." fi -fetch_ipv6_address_nym_tun() { - ipv6_global_address=$(ip -6 addr show $tunnel_interface scope global | grep inet6 | awk '{print $2}' | head -n 1) +fetch_ipv6_address() { + local interface=$1 + ipv6_global_address=$(ip -6 addr show "$interface" scope global | grep inet6 | awk '{print $2}' | head -n 1) if [[ -z "$ipv6_global_address" ]]; then - echo "no globally routable IPv6 address found on $tunnel_interface. please configure IPv6 or check your network settings." + echo "no globally routable IPv6 address found on $interface. Please configure IPv6 or check your network settings." exit 1 else echo "using IPv6 address: $ipv6_global_address" @@ -23,88 +24,88 @@ fetch_ipv6_address_nym_tun() { } fetch_and_display_ipv6() { - ipv6_address=$(ip -6 addr show ${network_device} scope global | grep inet6 | awk '{print $2}') + ipv6_address=$(ip -6 addr show "$network_device" scope global | grep inet6 | awk '{print $2}') if [[ -z "$ipv6_address" ]]; then - echo "no global IPv6 address found on ${network_device}." - else - echo "IPv6 address on ${network_device}: $ipv6_address" + echo "no global IPv6 address found on $network_device." + elsen + echo "IPv6 address on $network_device: $ipv6_address" fi } adjust_ip_forwarding() { - ipv6_forwarding_setting="net.ipv6.conf.all.forwarding=1" - ipv4_forwarding_setting="net.ipv4.ip_forward=1" - echo "$ipv6_forwarding_setting" | sudo tee -a /etc/sysctl.conf - echo "$ipv4_forwarding_setting" | sudo tee -a /etc/sysctl.conf - sysctl -p /etc/sysctl.conf + echo "adjusting IP forwarding settings..." + sudo sysctl -w net.ipv6.conf.all.forwarding=1 + sudo sysctl -w net.ipv4.ip_forward=1 } -apply_iptables_rules_wg() { - echo "applying IPtables rules..." - echo "network device: ${network_device}" - echo "tunnel_interface: ${wg_tunnel_interface}" +apply_iptables_rules() { + local interface=$1 + echo "applying IPtables rules for $interface..." sleep 2 - sudo iptables -A FORWARD -i "$wg_tunnel_interface" -o "$network_device" -j ACCEPT - sudo iptables -A FORWARD -i "$network_device" -o "$wg_tunnel_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT - sudo ip6tables -A FORWARD -i "$network_device" -o "$wg_tunnel_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT - sudo ip6tables -A FORWARD -i "$wg_tunnel_interface" -o "$network_device" -j ACCEPT - sudo iptables-save | sudo tee /etc/iptables/rules.v4 - sudo ip6tables-save | sudo tee /etc/iptables/rules.v6 -} -remove_iptables_rules_wg() { - echo "removing IPtables rules..." - echo "network device: ${network_device}" - echo "tunnel_interface: ${wg_tunnel_interface}" - sleep 2 + # remove duplicates for IPv4 + sudo iptables -D FORWARD -i "$interface" -o "$network_device" -j ACCEPT 2>/dev/null || true + sudo iptables -D FORWARD -i "$network_device" -o "$interface" -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true + sudo iptables -t nat -D POSTROUTING -o "$network_device" -j MASQUERADE 2>/dev/null || true - # IPv4 rules removal wg - sudo iptables -D FORWARD -i "$wg_tunnel_interface" -o "$network_device" -j ACCEPT - sudo iptables -D FORWARD -i "$network_device" -o "$wg_tunnel_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT + # remove duplicates for IPv6 + sudo ip6tables -D FORWARD -i "$interface" -o "$network_device" -j ACCEPT 2>/dev/null || true + sudo ip6tables -D FORWARD -i "$network_device" -o "$interface" -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true + sudo ip6tables -t nat -D POSTROUTING -o "$network_device" -j MASQUERADE 2>/dev/null || true + + # add new rules for IPv4 + sudo iptables -t nat -A POSTROUTING -o "$network_device" -j MASQUERADE + sudo iptables -A FORWARD -i "$interface" -o "$network_device" -j ACCEPT + sudo iptables -A FORWARD -i "$network_device" -o "$interface" -m state --state RELATED,ESTABLISHED -j ACCEPT - # IPv6 rules removal wg - sudo ip6tables -t nat -D POSTROUTING -o "$network_device" -j MASQUERADE - sudo ip6tables -D FORWARD -i "$network_device" -o "$wg_tunnel_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT - sudo ip6tables -D FORWARD -i "$wg_tunnel_interface" -o "$network_device" -j ACCEPT + # add new rules for IPv6 + sudo ip6tables -t nat -A POSTROUTING -o "$network_device" -j MASQUERADE + sudo ip6tables -A FORWARD -i "$interface" -o "$network_device" -j ACCEPT + sudo ip6tables -A FORWARD -i "$network_device" -o "$interface" -m state --state RELATED,ESTABLISHED -j ACCEPT sudo iptables-save | sudo tee /etc/iptables/rules.v4 sudo ip6tables-save | sudo tee /etc/iptables/rules.v6 } -apply_iptables_rules() { - echo "applying IPtables rules..." - echo "network device: ${network_device}" - echo "tunnel_interface: ${tunnel_interface}" +apply_iptables_rules_wg() { + local interface=$wg_tunnel_interface + echo "applying IPtables rules for WireGuard ($interface)..." sleep 2 + + # remove duplicates for IPv4 + sudo iptables -D FORWARD -i "$interface" -o "$network_device" -j ACCEPT 2>/dev/null || true + sudo iptables -D FORWARD -i "$network_device" -o "$interface" -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true + sudo iptables -t nat -D POSTROUTING -o "$network_device" -j MASQUERADE 2>/dev/null || true + + # remove duplicates for IPv6 + sudo ip6tables -D FORWARD -i "$interface" -o "$network_device" -j ACCEPT 2>/dev/null || true + sudo ip6tables -D FORWARD -i "$network_device" -o "$interface" -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true + sudo ip6tables -t nat -D POSTROUTING -o "$network_device" -j MASQUERADE 2>/dev/null || true + + # add new rules for IPv4 sudo iptables -t nat -A POSTROUTING -o "$network_device" -j MASQUERADE - sudo iptables -A FORWARD -i "$tunnel_interface" -o "$network_device" -j ACCEPT - sudo iptables -A FORWARD -i "$network_device" -o "$tunnel_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT + sudo iptables -A FORWARD -i "$interface" -o "$network_device" -j ACCEPT + sudo iptables -A FORWARD -i "$network_device" -o "$interface" -m state --state RELATED,ESTABLISHED -j ACCEPT + + # add new rules for IPv6 sudo ip6tables -t nat -A POSTROUTING -o "$network_device" -j MASQUERADE - sudo ip6tables -A FORWARD -i "$network_device" -o "$tunnel_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT - sudo ip6tables -A FORWARD -i "$tunnel_interface" -o "$network_device" -j ACCEPT - adjust_ip_forwarding + sudo ip6tables -A FORWARD -i "$interface" -o "$network_device" -j ACCEPT + sudo ip6tables -A FORWARD -i "$network_device" -o "$interface" -m state --state RELATED,ESTABLISHED -j ACCEPT + sudo iptables-save | sudo tee /etc/iptables/rules.v4 sudo ip6tables-save | sudo tee /etc/iptables/rules.v6 } -remove_iptables_rules() { - echo "removing IPtables rules..." - echo "network device: ${network_device}" - echo "tunnel_interface: ${tunnel_interface}" - sleep 2 - # IPv4 rules removal - sudo iptables -t nat -D POSTROUTING -o "$network_device" -j MASQUERADE - sudo iptables -D FORWARD -i "$tunnel_interface" -o "$network_device" -j ACCEPT - sudo iptables -D FORWARD -i "$network_device" -o "$tunnel_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT - - # IPv6 rules removal - sudo ip6tables -t nat -D POSTROUTING -o "$network_device" -j MASQUERADE - sudo ip6tables -D FORWARD -i "$network_device" -o "$tunnel_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT - sudo ip6tables -D FORWARD -i "$tunnel_interface" -o "$network_device" -j ACCEPT - - sudo iptables-save | sudo tee /etc/iptables/rules.v4 - sudo ip6tables-save | sudo tee /etc/iptables/rules.v6 +check_tunnel_iptables() { + local interface=$1 + echo "inspecting IPtables rules for $interface..." + echo "---------------------------------------" + echo "IPv4 rules:" + iptables -L FORWARD -v -n | awk -v dev="$interface" '/^Chain FORWARD/ || $0 ~ dev || $0 ~ "ufw-reject-forward"' + echo "---------------------------------------" + echo "IPv6 rules:" + ip6tables -L FORWARD -v -n | awk -v dev="$interface" '/^Chain FORWARD/ || $0 ~ dev || $0 ~ "ufw6-reject-forward"' } check_ipv6_ipv4_forwarding() { @@ -114,79 +115,42 @@ check_ipv6_ipv4_forwarding() { echo "IPv6 forwarding is $([ "$result_ipv6" == "1" ] && echo "enabled" || echo "not enabled")." } -check_nymtun_iptables() { - echo "network Device: $network_device" +check_ip_routing() { + echo "IPv4 routing table:" + ip route echo "---------------------------------------" - echo - echo "inspecting IPv4 firewall rules..." - iptables -L FORWARD -v -n | awk -v dev="$network_device" '/^Chain FORWARD/ || /nymtun0/ && dev || dev && /nymtun0/ || /ufw-reject-forward/' + echo "IPv6 routing table:" + ip -6 route +} +perform_pings() { + echo "performing IPv4 ping to google.com..." + ping -c 4 google.com echo "---------------------------------------" - echo - echo "inspecting IPv6 firewall rules..." - ip6tables -L FORWARD -v -n | awk -v dev="$network_device" '/^Chain FORWARD/ || /nymtun0/ && dev || dev && /nymtun0/ || /ufw6-reject-forward/' + echo "performing IPv6 ping to google.com..." + ping6 -c 4 google.com } -joke_through_the_mixnet() { - echo "checking Internet and mixnet connectivity (IPv4) via nymtun0..." - ipv4_address=$(ip addr show nymtun0 | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1) +joke_through_tunnel() { + local interface=$1 + echo "checking tunnel connectivity and fetching a joke for $interface..." + ipv4_address=$(ip addr show "$interface" | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1) + ipv6_address=$(ip addr show "$interface" | grep 'inet6 ' | awk '{print $2}' | grep -v '^fe80:' | cut -d'/' -f1) - if [ -z "$ipv4_address" ]; then - echo - echo "no IPv4 address found on nymtun0." - echo "please ensure IPv4 is configured correctly on your device." - echo "unfortunately, there's no joke for you :( and you might not be able to route IPv4 traffic through your gateway to the internet." - else - joke=$(curl -s -H "Accept: application/json" --interface "$ipv4_address" https://icanhazdadjoke.com/ | jq -c .joke) - - if [ -z "$joke" ] || [ "$joke" = "null" ]; then - echo "failed to fetch a joke. there might be an issue with the Internet connectivity or the joke service." - else - echo "joke fetched successfully:" - echo "$joke" - fi + if [[ -z "$ipv4_address" && -z "$ipv6_address" ]]; then + echo "no IP address found on $interface. Unable to fetch a joke." + return fi - echo "checking Internet and mixnet connectivity (IPv6) via nymtun0..." - ipv6_address=$(ip addr show nymtun0 | grep 'inet6 ' | awk '{print $2}' | cut -d'/' -f1 | grep -v '^fe80:') - - if [ -z "$ipv6_address" ]; then - echo - echo "no globally routable IPv6 address found on nymtun0." - echo "please ensure IPv6 is enabled on your VPS or configure your security groups/firewall settings appropriately." - echo "unfortunately there's no joke fo you :( and you can't route ipv6 traffic through your gateway to the internet" - else - joke=$(curl -s -H "Accept: application/json" --interface "$ipv6_address" https://icanhazdadjoke.com/ | jq -c .joke) - - if [ -z "$joke" ] || [ "$joke" = "null" ]; then - echo "failed to fetch a joke. there might be an issue with the Internet connectivity or the joke service." - else - echo "joke fetched successfully:" - echo "$joke" - fi + if [[ -n "$ipv4_address" ]]; then + joke=$(curl -s -H "Accept: application/json" --interface "$ipv4_address" https://icanhazdadjoke.com/ | jq -r .joke) + [[ -n "$joke" && "$joke" != "null" ]] && echo "IPv4 joke: $joke" || echo "Failed to fetch a joke via IPv4." fi -} -check_ip6_ipv4_routing() { - echo "---------------------------------------" - echo "examining IPv4 routing table..." - ip route - echo "---------------------------------------" - echo - echo "examining IPv6 routing table..." - ip -6 route - echo -} - -perform_ipv4_ipv6_pings() { - echo "---------------------------------------" - echo "checking IPv4 connectivity (example: google.com)..." - ping -c 4 google.com - echo "---------------------------------------" - echo - echo "checking IPv6 connectivity (example: google.com)..." - ping6 -c 4 google.com - echo + if [[ -n "$ipv6_address" ]]; then + joke=$(curl -s -H "Accept: application/json" --interface "$ipv6_address" https://icanhazdadjoke.com/ | jq -r .joke) + [[ -n "$joke" && "$joke" != "null" ]] && echo "IPv6 joke: $joke" || echo "Failed to fetch a joke via IPv6." + fi } configure_dns_and_icmp_wg() { @@ -199,119 +163,65 @@ configure_dns_and_icmp_wg() { echo "allowing dns over tcp (port 53)..." sudo iptables -A INPUT -p tcp --dport 53 -j ACCEPT - + echo "saving iptables rules..." sudo iptables-save > /etc/iptables/rules.v4 echo "dns and icmp configuration completed." } -joke_through_wg_tunnel() { - echo "checking nymwg tunnel status..." - - tunnel_status=$(ip link show nymwg | grep -o "state [A-Z]*") - - if [[ $tunnel_status == "state UNKNOWN" ]]; then - echo "nymwg tunnel is up." - else - echo "nymwg tunnel is down." - echo "please check your nymwg tunnel configuration." - return - fi - - echo "checking internet and mixnet connectivity (ipv4) via nymwg..." - ipv4_address=$(ip addr show nymwg | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1) - - if [ -z "$ipv4_address" ]; then - echo - echo "no ipv4 address found on nymwg." - echo "please ensure ipv4 is configured correctly on your device." - echo "unfortunately, there's no joke for you :( and you might not be able to route ipv4 traffic through your gateway to the internet." - else - joke=$(curl -s -H "accept: application/json" --interface "$ipv4_address" https://icanhazdadjoke.com/ | jq -c .joke) - - if [ -z "$joke" ] || [ "$joke" = "null" ]; then - echo "failed to fetch a joke. there might be an issue with the internet connectivity or the joke service." - else - echo "joke fetched successfully:" - echo "$joke" - fi - fi - - echo "checking internet and mixnet connectivity (ipv6) via nymwg..." - ipv6_address=$(ip addr show nymwg | grep 'inet6 ' | awk '{print $2}' | cut -d'/' -f1 | grep -v '^fe80:') - - if [ -z "$ipv6_address" ]; then - echo - echo "no globally routable ipv6 address found on nymwg." - echo "please ensure ipv6 is enabled on your vps or configure your security groups/firewall settings appropriately." - echo "unfortunately, there's no joke for you :( and you can't route ipv6 traffic through your gateway to the internet." - else - joke=$(curl -s -H "accept: application/json" --interface "$ipv6_address" https://icanhazdadjoke.com/ | jq -c .joke) - - if [ -z "$joke" ] || [ "$joke" = "null" ]; then - echo "failed to fetch a joke. there might be an issue with the internet connectivity or the joke service." - else - echo "joke fetched successfully:" - echo "$joke" - fi - fi -} - case "$1" in fetch_ipv6_address_nym_tun) - fetch_ipv6_address_nym_tun + fetch_ipv6_address "$tunnel_interface" ;; fetch_and_display_ipv6) fetch_and_display_ipv6 ;; -check_nymtun_iptables) - check_nymtun_iptables - ;; apply_iptables_rules) - apply_iptables_rules + apply_iptables_rules "$tunnel_interface" + ;; +apply_iptables_rules_wg) + apply_iptables_rules "$wg_tunnel_interface" ;; -remove_iptables_rules) - remove_iptables_rules +check_nymtun_iptables) + check_tunnel_iptables "$tunnel_interface" + ;; +check_nym_wg_tun) + check_tunnel_iptables "$wg_tunnel_interface" ;; check_ipv6_ipv4_forwarding) check_ipv6_ipv4_forwarding ;; -check_ip6_ipv4_routing) - check_ip6_ipv4_routing +check_ip_routing) + check_ip_routing ;; -perform_ipv4_ipv6_pings) - perform_ipv4_ipv6_pings +perform_pings) + perform_pings ;; joke_through_the_mixnet) - joke_through_the_mixnet - ;; -apply_iptables_rules_wg) - apply_iptables_rules_wg + joke_through_tunnel "$tunnel_interface" ;; joke_through_wg_tunnel) - joke_through_wg_tunnel + joke_through_tunnel "$wg_tunnel_interface" ;; configure_dns_and_icmp_wg) configure_dns_and_icmp_wg ;; *) - echo "usage: $0 [command]" - echo "commands:" - echo " fetch_ipv6_address_nym_tun - Fetches the IPv6 address assigned to the '$tunnel_interface'." - echo " fetch_and_display_ipv6 - Displays the IPv6 address on the default network device." - echo " apply_iptables_rules - Applies necessary IPv4 and IPv6 iptables rules." - echo " apply_iptables_rules_wg - Applies iptable rules for IPv4 and IPv6 for Wireguard." - echo " remove_iptables_rules - Removes applied IPv4 and IPv6 iptables rules." - echo " remove_iptables_rules_wg - Removes applied IPv4 and IPv6 iptables rules for Wireguard." - echo " check_ipv6_ipv4_forwarding - Checks if IPv4 and IPv6 forwarding are enabled." - echo " check_nymtun_iptables - Check nymtun0 device." - echo " perform_ipv4_ipv6_pings - Perform IPv4 and IPv6 pings to google." - echo " check_ip6_ipv4_routing - Check IPv6 and IPv4 routing." - echo " joke_through_the_mixnet - Run a joke through the mixnet via IPv4 and IPv6." - echo " joke_through_wg_tunnel - Run a wg test, and get a joke through the wg tunnel." - echo " configure_dns_and_icmp_wg - Allows icmp ping tests for probes alongside configuring dns" - echo "please provide one of the above commands." + echo "Usage: $0 [command]" + echo "Commands:" + echo " fetch_ipv6_address_nym_tun - Fetch IPv6 for nymtun0." + echo " fetch_and_display_ipv6 - Show IPv6 on default device." + echo " apply_iptables_rules - Apply IPtables rules for nymtun0." + echo " apply_iptables_rules_wg - Apply IPtables rules for nymwg." + echo " check_nymtun_iptables - Check IPtables for nymtun0." + echo " check_nym_wg_tun - Check IPtables for nymwg." + echo " check_ipv6_ipv4_forwarding - Check IPv4 and IPv6 forwarding." + echo " check_ip_routing - Display IP routing tables." + echo " perform_pings - Test IPv4 and IPv6 connectivity." + echo " joke_through_the_mixnet - Fetch a joke via nymtun0." + echo " joke_through_wg_tunnel - Fetch a joke via nymwg." + echo " configure_dns_and_icmp_wg - Allows icmp ping tests for probes alongside configuring dns" exit 1 ;; esac diff --git a/tools/nym-cli/src/internal/ecash/mod.rs b/tools/nym-cli/src/internal/ecash/mod.rs new file mode 100644 index 00000000000..ee9f8ef47c4 --- /dev/null +++ b/tools/nym-cli/src/internal/ecash/mod.rs @@ -0,0 +1,26 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use nym_cli_commands::context::ClientArgs; +use nym_cli_commands::internal::ecash::InternalEcashCommands; +use nym_network_defaults::NymNetworkDetails; + +pub(super) async fn execute( + global_args: ClientArgs, + ecash: nym_cli_commands::internal::ecash::InternalEcash, + nym_network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + // I reckon those will be needed later + let _ = global_args; + let _ = nym_network_details; + + match ecash.command { + InternalEcashCommands::GenerateWithdrawalRequest(args) => { + nym_cli_commands::internal::ecash::withdrawal_request::generate_withdrawal_request(args) + .await + } + InternalEcashCommands::GenerateKeypair(args) => { + nym_cli_commands::internal::ecash::generate_keypair::generate_ecash_keypair(args) + } + } +} diff --git a/tools/nym-cli/src/internal/mod.rs b/tools/nym-cli/src/internal/mod.rs new file mode 100644 index 00000000000..253c45b2274 --- /dev/null +++ b/tools/nym-cli/src/internal/mod.rs @@ -0,0 +1,20 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use nym_cli_commands::context::ClientArgs; +use nym_cli_commands::internal::InternalCommands; +use nym_network_defaults::NymNetworkDetails; + +mod ecash; + +pub(super) async fn execute( + global_args: ClientArgs, + internal: nym_cli_commands::internal::Internal, + nym_network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match internal.command { + InternalCommands::Ecash(ecash_commands) => { + ecash::execute(global_args, ecash_commands, nym_network_details).await + } + } +} diff --git a/tools/nym-cli/src/main.rs b/tools/nym-cli/src/main.rs index c5b4cc51e31..7854dbb0d28 100644 --- a/tools/nym-cli/src/main.rs +++ b/tools/nym-cli/src/main.rs @@ -9,6 +9,7 @@ use nym_validator_client::nyxd::AccountId; mod completion; mod ecash; +mod internal; mod validator; #[derive(Debug, Parser)] @@ -74,6 +75,11 @@ pub(crate) enum Commands { VestingSchedule(nym_cli_commands::validator::vesting::VestingSchedule), /// Manage your mixnet infrastructure, delegate stake or query the directory Mixnet(nym_cli_commands::validator::mixnet::Mixnet), + + #[clap(hide = true)] + /// Internal commands used for testing and debugging + Internal(nym_cli_commands::internal::Internal), + /// Generates shell completion GenerateFig, } @@ -118,6 +124,9 @@ async fn execute(cli: Cli) -> anyhow::Result<()> { Commands::Mixnet(mixnet) => { validator::mixnet::execute(args, mixnet, &network_details).await? } + Commands::Internal(internal_commands) => { + internal::execute(args, internal_commands, &network_details).await? + } Commands::GenerateFig => { let mut cmd = Cli::command(); completion::print_fig(&mut cmd);