Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7644a48c23 |
@@ -4,38 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2024.7-doubledecker] (2024-07-04)
|
||||
|
||||
- Add an early return in `parse_raw_str_logs` for empty raw log strings. ([#4686])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /wasm/mix-fetch/internal-dev ([#4672])
|
||||
- add expiry returned on import ([#4670])
|
||||
- [bugfix] missing rustls feature ([#4666])
|
||||
- Bump ws from 8.13.0 to 8.17.1 in /wasm/client/internal-dev-node ([#4665])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /clients/native/examples/js-examples/websocket ([#4663])
|
||||
- Bump ws from 8.14.2 to 8.17.1 in /sdk/typescript/packages/nodejs-client ([#4662])
|
||||
- Update setup.md ([#4661])
|
||||
- New clippy lints ([#4660])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /nym-api/tests ([#4659])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /docker/typescript_client/upload_contract ([#4658])
|
||||
- Update vps-setup.md ([#4656])
|
||||
- Update configuration.md ([#4655])
|
||||
- Remove old PR template ([#4639])
|
||||
|
||||
[#4686]: https://github.com/nymtech/nym/pull/4686
|
||||
[#4672]: https://github.com/nymtech/nym/pull/4672
|
||||
[#4670]: https://github.com/nymtech/nym/pull/4670
|
||||
[#4666]: https://github.com/nymtech/nym/pull/4666
|
||||
[#4665]: https://github.com/nymtech/nym/pull/4665
|
||||
[#4663]: https://github.com/nymtech/nym/pull/4663
|
||||
[#4662]: https://github.com/nymtech/nym/pull/4662
|
||||
[#4661]: https://github.com/nymtech/nym/pull/4661
|
||||
[#4660]: https://github.com/nymtech/nym/pull/4660
|
||||
[#4659]: https://github.com/nymtech/nym/pull/4659
|
||||
[#4658]: https://github.com/nymtech/nym/pull/4658
|
||||
[#4656]: https://github.com/nymtech/nym/pull/4656
|
||||
[#4655]: https://github.com/nymtech/nym/pull/4655
|
||||
[#4639]: https://github.com/nymtech/nym/pull/4639
|
||||
|
||||
## [2024.6-chomp] (2024-06-25)
|
||||
|
||||
- Remove additional code as part of Ephemera Purge and SP and contracts ([#4650])
|
||||
|
||||
Generated
+8
-75
@@ -2093,7 +2093,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||
|
||||
[[package]]
|
||||
name = "explorer-api"
|
||||
version = "1.1.36"
|
||||
version = "1.1.35"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap 4.5.4",
|
||||
@@ -3849,7 +3849,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-api"
|
||||
version = "1.1.40"
|
||||
version = "1.1.39"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3950,54 +3950,6 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-authenticator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"bs58 0.5.1",
|
||||
"bytes",
|
||||
"clap 4.5.4",
|
||||
"fastrand 2.1.0",
|
||||
"futures",
|
||||
"ipnetwork 0.16.0",
|
||||
"log",
|
||||
"nym-authenticator-requests",
|
||||
"nym-bin-common",
|
||||
"nym-client-core",
|
||||
"nym-config",
|
||||
"nym-crypto",
|
||||
"nym-id",
|
||||
"nym-network-defaults",
|
||||
"nym-sdk",
|
||||
"nym-service-providers-common",
|
||||
"nym-sphinx",
|
||||
"nym-task",
|
||||
"nym-types",
|
||||
"nym-wireguard",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-authenticator-requests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"nym-sphinx",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-bandwidth-controller"
|
||||
version = "0.1.0"
|
||||
@@ -4057,7 +4009,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-cli"
|
||||
version = "1.1.38"
|
||||
version = "1.1.37"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.13.1",
|
||||
@@ -4136,7 +4088,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-client"
|
||||
version = "1.1.37"
|
||||
version = "1.1.36"
|
||||
dependencies = [
|
||||
"bs58 0.5.1",
|
||||
"clap 4.5.4",
|
||||
@@ -4562,7 +4514,6 @@ dependencies = [
|
||||
"ipnetwork 0.16.0",
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
"nym-authenticator",
|
||||
"nym-bin-common",
|
||||
"nym-config",
|
||||
"nym-credentials",
|
||||
@@ -4950,7 +4901,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-requester"
|
||||
version = "1.1.38"
|
||||
version = "1.1.37"
|
||||
dependencies = [
|
||||
"addr",
|
||||
"anyhow",
|
||||
@@ -4999,26 +4950,9 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-statistics"
|
||||
version = "1.1.34"
|
||||
dependencies = [
|
||||
"dirs 4.0.0",
|
||||
"log",
|
||||
"nym-bin-common",
|
||||
"nym-statistics-common",
|
||||
"nym-task",
|
||||
"pretty_env_logger",
|
||||
"rocket",
|
||||
"serde",
|
||||
"sqlx",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-node"
|
||||
version = "1.1.4"
|
||||
version = "1.1.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bip39",
|
||||
@@ -5030,7 +4964,6 @@ dependencies = [
|
||||
"cupid",
|
||||
"humantime-serde",
|
||||
"ipnetwork 0.16.0",
|
||||
"nym-authenticator",
|
||||
"nym-bin-common",
|
||||
"nym-client-core-config-types",
|
||||
"nym-config",
|
||||
@@ -5281,7 +5214,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.37"
|
||||
version = "1.1.36"
|
||||
dependencies = [
|
||||
"bs58 0.5.1",
|
||||
"clap 4.5.4",
|
||||
@@ -5794,7 +5727,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nymvisor"
|
||||
version = "0.1.3"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
||||
@@ -20,7 +20,6 @@ members = [
|
||||
"clients/native",
|
||||
"clients/native/websocket-requests",
|
||||
"clients/socks5",
|
||||
"common/authenticator-requests",
|
||||
"common/async-file-watcher",
|
||||
"common/bandwidth-controller",
|
||||
"common/bin-common",
|
||||
@@ -96,7 +95,6 @@ members = [
|
||||
"mixnode",
|
||||
"sdk/lib/socks5-listener",
|
||||
"sdk/rust/nym-sdk",
|
||||
"service-providers/authenticator",
|
||||
"service-providers/common",
|
||||
"service-providers/ip-packet-router",
|
||||
"service-providers/network-requester",
|
||||
|
||||
@@ -52,7 +52,7 @@ References for developers:
|
||||
|
||||
You can chat to us in two places:
|
||||
* The #dev channel on [Matrix](https://matrix.to/#/#dev:nymtech.chat)
|
||||
* The various developer channels on [Discord](https://discord.gg/FaTJb8q8)
|
||||
* The various developer channels on [Discord](discord.gg/nymproject)
|
||||
|
||||
### Tokenomics & Rewards
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.37"
|
||||
version = "1.1.36"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.37"
|
||||
version = "1.1.36"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
[package]
|
||||
name = "nym-authenticator-requests"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
bincode = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
nym-wireguard-types = { path = "../wireguard-types" }
|
||||
@@ -1,13 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod v1;
|
||||
|
||||
pub const CURRENT_VERSION: u8 = 1;
|
||||
|
||||
fn make_bincode_serializer() -> impl bincode::Options {
|
||||
use bincode::Options;
|
||||
bincode::DefaultOptions::new()
|
||||
.with_big_endian()
|
||||
.with_varint_encoding()
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
|
||||
const VERSION: u8 = 1;
|
||||
@@ -1,70 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_wireguard_types::{GatewayClient, InitMessage};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::make_bincode_serializer;
|
||||
|
||||
use super::VERSION;
|
||||
|
||||
fn generate_random() -> u64 {
|
||||
use rand::RngCore;
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
rng.next_u64()
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthenticatorRequest {
|
||||
pub version: u8,
|
||||
pub data: AuthenticatorRequestData,
|
||||
pub reply_to: Recipient,
|
||||
pub request_id: u64,
|
||||
}
|
||||
|
||||
impl AuthenticatorRequest {
|
||||
pub fn from_reconstructed_message(
|
||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
||||
) -> Result<Self, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().deserialize(&message.message)
|
||||
}
|
||||
|
||||
pub fn new_initial_request(init_message: InitMessage, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorRequestData::Initial(init_message),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_final_request(gateway_client: GatewayClient, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorRequestData::Final(gateway_client),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().serialize(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum AuthenticatorRequestData {
|
||||
Initial(InitMessage),
|
||||
Final(GatewayClient),
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_wireguard_types::registration::RegistrationData;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::make_bincode_serializer;
|
||||
|
||||
use super::VERSION;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthenticatorResponse {
|
||||
pub version: u8,
|
||||
pub data: AuthenticatorResponseData,
|
||||
pub reply_to: Recipient,
|
||||
}
|
||||
|
||||
impl AuthenticatorResponse {
|
||||
pub fn new_pending_registration_success(
|
||||
registration_data: RegistrationData,
|
||||
request_id: u64,
|
||||
reply_to: Recipient,
|
||||
) -> Self {
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
|
||||
reply: registration_data,
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_registered(reply_to: Recipient, request_id: u64) -> Self {
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorResponseData::Registered(RegisteredResponse {
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recipient(&self) -> Recipient {
|
||||
self.reply_to
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().serialize(self)
|
||||
}
|
||||
|
||||
pub fn from_reconstructed_message(
|
||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
||||
) -> Result<Self, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().deserialize(&message.message)
|
||||
}
|
||||
|
||||
pub fn id(&self) -> Option<u64> {
|
||||
match &self.data {
|
||||
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
|
||||
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum AuthenticatorResponseData {
|
||||
PendingRegistration(PendingRegistrationResponse),
|
||||
Registered(RegisteredResponse),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct PendingRegistrationResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
pub reply: RegistrationData,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RegisteredResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// See other comments for other TaskStatus message enumds about abusing the Error trait when we
|
||||
// should have a new trait for TaskStatus messages
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum BandwidthStatusMessage {
|
||||
#[error("remaining bandwidth: {0}")]
|
||||
RemainingBandwidth(i64),
|
||||
|
||||
#[error("no bandwidth left")]
|
||||
NoBandwidth,
|
||||
}
|
||||
@@ -14,11 +14,8 @@ use nym_validator_client::coconut::all_coconut_api_clients;
|
||||
use nym_validator_client::nym_api::EpochId;
|
||||
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
||||
|
||||
pub use event::BandwidthStatusMessage;
|
||||
|
||||
pub mod acquire;
|
||||
pub mod error;
|
||||
mod event;
|
||||
mod utils;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::traits::GatewayPacketRouter;
|
||||
use crate::{cleanup_socket_message, try_decrypt_binary_message};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use log::*;
|
||||
use nym_bandwidth_controller::{BandwidthController, BandwidthStatusMessage};
|
||||
use nym_bandwidth_controller::BandwidthController;
|
||||
use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
|
||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||
use nym_credentials::CredentialSpendingData;
|
||||
@@ -105,8 +105,8 @@ pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
|
||||
// currently unused (but populated)
|
||||
negotiated_protocol: Option<u8>,
|
||||
|
||||
/// Listen to shutdown messages and send notifications back to the task manager
|
||||
task_client: TaskClient,
|
||||
/// Listen to shutdown messages.
|
||||
shutdown: TaskClient,
|
||||
}
|
||||
|
||||
impl<C, St> GatewayClient<C, St> {
|
||||
@@ -117,7 +117,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
shared_key: Option<Arc<SharedKeys>>,
|
||||
packet_router: PacketRouter,
|
||||
bandwidth_controller: Option<BandwidthController<C, St>>,
|
||||
task_client: TaskClient,
|
||||
shutdown: TaskClient,
|
||||
) -> Self {
|
||||
GatewayClient {
|
||||
authenticated: false,
|
||||
@@ -135,7 +135,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS,
|
||||
reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF,
|
||||
negotiated_protocol: None,
|
||||
task_client,
|
||||
shutdown,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = self.task_client.recv() => {
|
||||
_ = self.shutdown.recv() => {
|
||||
log::trace!("GatewayClient control response: Received shutdown");
|
||||
log::debug!("GatewayClient control response: Exiting");
|
||||
break Err(GatewayClientError::ConnectionClosedGatewayShutdown);
|
||||
@@ -540,9 +540,6 @@ impl<C, St> GatewayClient<C, St> {
|
||||
self.bandwidth_remaining = bandwidth_remaining;
|
||||
self.negotiated_protocol = protocol_version;
|
||||
log::debug!("authenticated: {status}, bandwidth remaining: {bandwidth_remaining}");
|
||||
self.task_client.send_status_msg(Box::new(
|
||||
BandwidthStatusMessage::RemainingBandwidth(bandwidth_remaining),
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
ServerResponse::Error { message } => Err(GatewayClientError::GatewayError(message)),
|
||||
@@ -808,7 +805,7 @@ impl<C, St> GatewayClient<C, St> {
|
||||
.as_ref()
|
||||
.expect("no shared key present even though we're authenticated!"),
|
||||
),
|
||||
self.task_client.clone(),
|
||||
self.shutdown.clone(),
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@@ -882,8 +879,8 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
// perfectly fine here, because it's not meant to be used
|
||||
let (ack_tx, _) = mpsc::unbounded();
|
||||
let (mix_tx, _) = mpsc::unbounded();
|
||||
let task_client = TaskClient::dummy();
|
||||
let packet_router = PacketRouter::new(ack_tx, mix_tx, task_client.clone());
|
||||
let shutdown = TaskClient::dummy();
|
||||
let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone());
|
||||
|
||||
GatewayClient {
|
||||
authenticated: false,
|
||||
@@ -901,7 +898,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS,
|
||||
reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF,
|
||||
negotiated_protocol: None,
|
||||
task_client,
|
||||
shutdown,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -909,7 +906,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
self,
|
||||
packet_router: PacketRouter,
|
||||
bandwidth_controller: Option<BandwidthController<C, St>>,
|
||||
task_client: TaskClient,
|
||||
shutdown: TaskClient,
|
||||
) -> GatewayClient<C, St> {
|
||||
// invariants that can't be broken
|
||||
// (unless somebody decided to expose some field that wasn't meant to be exposed)
|
||||
@@ -933,7 +930,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
|
||||
reconnection_attempts: self.reconnection_attempts,
|
||||
reconnection_backoff: self.reconnection_backoff,
|
||||
negotiated_protocol: self.negotiated_protocol,
|
||||
task_client,
|
||||
shutdown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-27
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::nyxd::cosmwasm_client::client_traits::CosmWasmClient;
|
||||
use crate::nyxd::cosmwasm_client::helpers::{compress_wasm_code, CheckResponse};
|
||||
use crate::nyxd::cosmwasm_client::logs::parse_raw_logs;
|
||||
use crate::nyxd::cosmwasm_client::logs::{self, parse_raw_logs};
|
||||
use crate::nyxd::cosmwasm_client::types::*;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER};
|
||||
@@ -19,7 +19,6 @@ use cosmrs::feegrant::{
|
||||
};
|
||||
use cosmrs::proto::cosmos::tx::signing::v1beta1::SignMode;
|
||||
use cosmrs::staking::{MsgDelegate, MsgUndelegate};
|
||||
use cosmrs::tendermint::abci::{Event, EventAttribute};
|
||||
use cosmrs::tx::{self, Msg};
|
||||
use cosmrs::{cosmwasm, AccountId, Any, Tx};
|
||||
use log::debug;
|
||||
@@ -52,20 +51,6 @@ fn single_unspecified_signer_auth(
|
||||
}
|
||||
.auth_info(empty_fee())
|
||||
}
|
||||
// Searches in events for an event of the given event type which contains an
|
||||
// attribute for with the given key.
|
||||
fn find_attribute<'a>(
|
||||
events: &'a [Event],
|
||||
event_type: &str,
|
||||
attr_key: &str,
|
||||
) -> Option<&'a EventAttribute> {
|
||||
events
|
||||
.iter()
|
||||
.find(|attr| attr.kind == event_type)?
|
||||
.attributes
|
||||
.iter()
|
||||
.find(|attr| attr.key == attr_key)
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
@@ -133,7 +118,6 @@ where
|
||||
.check_response()?;
|
||||
|
||||
let logs = parse_raw_logs(tx_res.tx_result.log)?;
|
||||
let events = tx_res.tx_result.events;
|
||||
let gas_info = GasInfo {
|
||||
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
|
||||
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
|
||||
@@ -143,7 +127,7 @@ where
|
||||
// the reason I think unwrap here is fine is that if the transaction succeeded and those
|
||||
// fields do not exist or code_id is not a number, there's no way we can recover, we're probably connected
|
||||
// to wrong validator or something
|
||||
let code_id = find_attribute(&events, "store_code", "code_id")
|
||||
let code_id = logs::find_attribute(&logs, "store_code", "code_id")
|
||||
.unwrap()
|
||||
.value
|
||||
.parse()
|
||||
@@ -156,7 +140,6 @@ where
|
||||
compressed_checksum,
|
||||
code_id,
|
||||
logs,
|
||||
events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -199,7 +182,6 @@ where
|
||||
.check_response()?;
|
||||
|
||||
let logs = parse_raw_logs(tx_res.tx_result.log)?;
|
||||
let events = tx_res.tx_result.events;
|
||||
let gas_info = GasInfo {
|
||||
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
|
||||
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
|
||||
@@ -208,7 +190,7 @@ where
|
||||
// the reason I think unwrap here is fine is that if the transaction succeeded and those
|
||||
// fields do not exist or address is malformed, there's no way we can recover, we're probably connected
|
||||
// to wrong validator or something
|
||||
let contract_address = find_attribute(&events, "instantiate", "_contract_address")
|
||||
let contract_address = logs::find_attribute(&logs, "instantiate", "_contract_address")
|
||||
.unwrap()
|
||||
.value
|
||||
.parse()
|
||||
@@ -217,7 +199,6 @@ where
|
||||
Ok(InstantiateResult {
|
||||
contract_address,
|
||||
logs,
|
||||
events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -250,7 +231,6 @@ where
|
||||
};
|
||||
Ok(ChangeAdminResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -281,7 +261,6 @@ where
|
||||
};
|
||||
Ok(ChangeAdminResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -319,7 +298,6 @@ where
|
||||
};
|
||||
Ok(MigrateResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
@@ -357,7 +335,6 @@ where
|
||||
};
|
||||
Ok(ExecuteResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
data: tx_res.tx_result.data.into(),
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
@@ -401,7 +378,6 @@ where
|
||||
};
|
||||
Ok(ExecuteResult {
|
||||
logs: parse_raw_logs(tx_res.tx_result.log)?,
|
||||
events: tx_res.tx_result.events,
|
||||
data: tx_res.tx_result.data.into(),
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
|
||||
@@ -9,12 +9,16 @@ pub use nym_coconut_bandwidth_contract_common::event_attributes::*;
|
||||
pub use nym_coconut_dkg_common::event_attributes::*;
|
||||
|
||||
// it seems that currently validators just emit stringified events (which are also returned as part of deliverTx response)
|
||||
// as their logs
|
||||
// as theirs logs
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Log {
|
||||
#[serde(default)]
|
||||
// weird thing is that the first msg_index seems to always be undefined on the raw logs
|
||||
pub msg_index: usize,
|
||||
// unless I'm missing something obvious, the "log" type in cosmjs is always an empty string
|
||||
// and launchpad cosmos validator was setting it to what essentially is just the raw version of what
|
||||
// we received (and we don't care about launchpad, we, as the time of writing this, work on the stargate)
|
||||
// log: String,
|
||||
pub events: Vec<cosmwasm_std::Event>,
|
||||
}
|
||||
|
||||
@@ -33,13 +37,8 @@ pub fn find_attribute<'a>(
|
||||
.find(|attr| attr.key == attribute_key)
|
||||
}
|
||||
|
||||
// these two functions were separated so that the internal logic could actually be tested
|
||||
// those two functions were separated so that the internal logic could actually be tested
|
||||
fn parse_raw_str_logs(raw: &str) -> Result<Vec<Log>, NyxdError> {
|
||||
// From Cosmos SDK > 0.50 onwards, log field is not populated
|
||||
if raw.is_empty() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
let logs: Vec<Log> = serde_json::from_str(raw).map_err(|_| NyxdError::MalformedLogString)?;
|
||||
if logs.len() != logs.iter().unique_by(|log| log.msg_index).count() {
|
||||
// this check is only here because I don't yet fully understand raw log string generation and
|
||||
|
||||
@@ -232,8 +232,6 @@ pub struct UploadResult {
|
||||
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -271,8 +269,6 @@ pub struct InstantiateResult {
|
||||
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -283,8 +279,6 @@ pub struct InstantiateResult {
|
||||
pub struct ChangeAdminResult {
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -295,8 +289,6 @@ pub struct ChangeAdminResult {
|
||||
pub struct MigrateResult {
|
||||
pub logs: Vec<Log>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
@@ -309,8 +301,6 @@ pub struct ExecuteResult {
|
||||
|
||||
pub data: Vec<u8>,
|
||||
|
||||
pub events: Vec<abci::Event>,
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: Hash,
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ bytes = { workspace = true }
|
||||
nym-bin-common = { path = "../bin-common" }
|
||||
nym-crypto = { path = "../crypto" }
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
rand = { workspace = true }
|
||||
rand = "0.8.5"
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
time = { workspace = true }
|
||||
|
||||
@@ -10,7 +10,8 @@ pub use config::Config;
|
||||
pub use error::Error;
|
||||
pub use public_key::PeerPublicKey;
|
||||
pub use registration::{
|
||||
ClientMac, ClientMessage, GatewayClient, GatewayClientRegistry, InitMessage, Nonce,
|
||||
ClientMac, ClientMessage, ClientRegistrationResponse, GatewayClient, GatewayClientRegistry,
|
||||
InitMessage, Nonce,
|
||||
};
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
|
||||
@@ -7,7 +7,6 @@ use base64::{engine::general_purpose, Engine};
|
||||
use dashmap::DashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::net::IpAddr;
|
||||
use std::time::SystemTime;
|
||||
use std::{fmt, ops::Deref, str::FromStr};
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
@@ -19,13 +18,13 @@ use sha2::Sha256;
|
||||
|
||||
pub type GatewayClientRegistry = DashMap<PeerPublicKey, GatewayClient>;
|
||||
pub type PendingRegistrations = DashMap<PeerPublicKey, RegistrationData>;
|
||||
pub type PrivateIPs = DashMap<IpAddr, Taken>;
|
||||
pub type PrivateIPs = DashMap<IpAddr, Free>;
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
pub type HmacSha256 = Hmac<Sha256>;
|
||||
|
||||
pub type Nonce = u64;
|
||||
pub type Taken = Option<SystemTime>;
|
||||
pub type Free = bool;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
@@ -54,6 +53,15 @@ impl InitMessage {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub enum ClientRegistrationResponse {
|
||||
PendingRegistration(RegistrationData),
|
||||
Registered,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub struct RegistrationData {
|
||||
pub nonce: u64,
|
||||
pub gateway_data: GatewayClient,
|
||||
|
||||
@@ -3,7 +3,7 @@ title = "Nym Docs"
|
||||
authors = ["Max Hampshire, Serinko, Alexia Lorenza Martinel"]
|
||||
description = "Nym technical documentation"
|
||||
language = "en"
|
||||
multilingual = false # for the moment - ideally work on chinese, brazillian ,portugese spanish next
|
||||
multilingual = false # for the moment - ideally work on chinese, brazillian ,portugese spanish next
|
||||
src = "src"
|
||||
|
||||
[rust]
|
||||
@@ -14,19 +14,17 @@ edition = "2018"
|
||||
#################
|
||||
|
||||
[preprocessor.theme]
|
||||
pagetoc = true
|
||||
sidebar-width = "280px"
|
||||
content-max-width = "80%"
|
||||
root-font-size = "70%"
|
||||
# if you need to change anything in the index.hbs file you need to turn this to `false`, rebuild the book,
|
||||
# probably remove the additional `comment` that gets appended to the header, and then change this back to `true`.
|
||||
# this is because of a bug in the `mdbook-theme` plugin
|
||||
turn-off = true
|
||||
|
||||
sidebar-width = "280px"
|
||||
content-max-width = "70%"
|
||||
content-main-margin-left = "5%"
|
||||
content-main-margin-right = "5%"
|
||||
root-font-size = "70%"
|
||||
# DO NOT CHANGE or you might overwrite the custom hbs file
|
||||
turn-off = false
|
||||
|
||||
[preprocessor.admonish]
|
||||
command = "mdbook-admonish"
|
||||
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
|
||||
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
|
||||
|
||||
# https://gitlab.com/tglman/mdbook-variables/
|
||||
[preprocessor.variables.variables]
|
||||
@@ -55,56 +53,52 @@ renderer = ["html"]
|
||||
#########
|
||||
|
||||
[build]
|
||||
build-dir = "book" # the directory where the output is placed
|
||||
create-missing = true # whether or not to create missing pages
|
||||
use-default-preprocessors = true # use the default preprocessors
|
||||
extra-watch-dirs = [] # directories to watch for triggering builds
|
||||
build-dir = "book" # the directory where the output is placed
|
||||
create-missing = true # whether or not to create missing pages
|
||||
use-default-preprocessors = true # use the default preprocessors
|
||||
extra-watch-dirs = [] # directories to watch for triggering builds
|
||||
|
||||
##########
|
||||
# OUTPUT #
|
||||
##########
|
||||
|
||||
[output.html]
|
||||
theme = "themes"
|
||||
theme = "nym_themes"
|
||||
default-theme = "coal"
|
||||
preferred-dark-theme = "coal"
|
||||
curly-quotes = true
|
||||
copy-fonts = true
|
||||
no-section-label = false
|
||||
additional-css = [
|
||||
"./themes/custom.css",
|
||||
"./themes/mdbook-admonish.css",
|
||||
"./themes/pagetoc.css",
|
||||
]
|
||||
additional-js = ["./themes/pagetoc.js"]
|
||||
additional-css = ["./nym_themes/custom.css", "./nym_themes/mdbook-admonish.css", "./nym_themes/pagetoc.css"]
|
||||
additional-js = ["./nym_themes/pagetoc.js"]
|
||||
git-repository-url = "https://github.com/nymtech/nym"
|
||||
git-repository-icon = "fa-github"
|
||||
input-404 = "not-found.md"
|
||||
|
||||
[output.html.fold]
|
||||
enable = true # whether or not to enable section folding
|
||||
level = 0 # the depth to start folding
|
||||
enable = true # whether or not to enable section folding
|
||||
level = 0 # the depth to start folding
|
||||
|
||||
# controlling rust sample code blocks
|
||||
[output.html.playground]
|
||||
editable = false # allows editing the source code
|
||||
copyable = true # include the copy button for copying code snippets
|
||||
copy-js = true # includes the JavaScript for the code editor
|
||||
line-numbers = true # displays line numbers for editable code
|
||||
runnable = true # displays a run button for rust code
|
||||
editable = false # allows editing the source code
|
||||
copyable = true # include the copy button for copying code snippets
|
||||
copy-js = true # includes the JavaScript for the code editor
|
||||
line-numbers = true # displays line numbers for editable code
|
||||
runnable = true # displays a run button for rust code
|
||||
|
||||
# options for the built in text search
|
||||
[output.html.search]
|
||||
enable = true # enables the search feature
|
||||
limit-results = 30 # maximum number of search results
|
||||
teaser-word-count = 30 # number of words used for a search result teaser
|
||||
use-boolean-and = true # multiple search terms must all match
|
||||
boost-title = 2 # ranking boost factor for matches in headers
|
||||
boost-hierarchy = 1 # ranking boost factor for matches in page names
|
||||
boost-paragraph = 1 # ranking boost factor for matches in text
|
||||
expand = true # partial words will match longer terms
|
||||
heading-split-level = 3 # link results to heading levels
|
||||
copy-js = true # include Javascript code for search
|
||||
enable = true # enables the search feature
|
||||
limit-results = 30 # maximum number of search results
|
||||
teaser-word-count = 30 # number of words used for a search result teaser
|
||||
use-boolean-and = true # multiple search terms must all match
|
||||
boost-title = 2 # ranking boost factor for matches in headers
|
||||
boost-hierarchy = 1 # ranking boost factor for matches in page names
|
||||
boost-paragraph = 1 # ranking boost factor for matches in text
|
||||
expand = true # partial words will match longer terms
|
||||
heading-split-level = 3 # link results to heading levels
|
||||
copy-js = true # include Javascript code for search
|
||||
|
||||
[output.linkcheck]
|
||||
warning-policy = "warn"
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
--sidebar-resize-indicator-width: 8px;
|
||||
--sidebar-resize-indicator-space: 2px;
|
||||
--page-padding: 15px;
|
||||
--content-max-width: 80%;
|
||||
--content-max-width: 70%;
|
||||
--menu-bar-height: 40px;
|
||||
--mono-font: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace;
|
||||
--code-font-size: 0.875em /* please adjust the ace font size accordingly in editor.js */
|
||||
+3
-6
@@ -8,12 +8,10 @@
|
||||
--sidebar-active: #fb6e4e;
|
||||
--icons-hover: #fb6e4e;
|
||||
--links: #fb6e4e;
|
||||
|
||||
::selection {
|
||||
color: #121726;
|
||||
background-color: #c5573d;
|
||||
}
|
||||
|
||||
select option {
|
||||
background-color: #121726;
|
||||
}
|
||||
@@ -23,18 +21,17 @@
|
||||
--sidebar-active: #fb6e4e;
|
||||
--icons-hover: #fb6e4e;
|
||||
--links: #fb6e4e;
|
||||
|
||||
::selection {
|
||||
color: #f2f2f2;
|
||||
color:#f2f2f2;
|
||||
background-color: #c5573d;
|
||||
}
|
||||
}
|
||||
|
||||
/*properly centering the title given the additional header items*/
|
||||
.menu-title {
|
||||
left: 45%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.menu-bar .a:hover,
|
||||
|
||||
/*necessary because of ^*/
|
||||
+28
-6
@@ -159,14 +159,20 @@
|
||||
</ul>
|
||||
|
||||
<!-- CUSTOM -->
|
||||
<select id="dropdown-menu" class="icon-button">
|
||||
<select id="dropdown-menu3" class="icon-button">
|
||||
<option value="">Network Protocol</option>
|
||||
<option value="https://nymtech.net/docs">Network Docs</option>
|
||||
<option value="https://nymtech.net/learn/papers">Academic Papers</option>
|
||||
<option value="">--------</option>
|
||||
</select>
|
||||
|
||||
<select id="dropdown-menu" class="icon-button">
|
||||
<option value="">Developer Docs</option>
|
||||
<option value="https://nymtech.net/developers">Dev Portal</option>
|
||||
<option value="https://nymtech.net/docs/sdk/rust/rust.html">Rust SDK</option>
|
||||
<option value="https://sdk.nymtech.net">Typescript SDK</option>
|
||||
<option value="">--------</option>
|
||||
</select>
|
||||
|
||||
<select id="dropdown-menu2" class="icon-button">
|
||||
<option value="">Setup Guides</option>
|
||||
<option value="https://nymtech.net/operators">Operators</option>
|
||||
<option value="https://nymtech.net/developers/nymvpn/intro.html">NymVPN Testing</option>
|
||||
@@ -180,7 +186,24 @@
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
document.getElementById('dropdown-menu2').addEventListener('change', function() {
|
||||
const selected = this.options[this.selectedIndex];
|
||||
if (selected.value !== '') {
|
||||
window.location.href = selected.value;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.getElementById('dropdown-menu3').addEventListener('change', function() {
|
||||
const selected = this.options[this.selectedIndex];
|
||||
if (selected.value !== '') {
|
||||
window.location.href = selected.value;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<!-- END CUSTOM -->
|
||||
</div>
|
||||
|
||||
@@ -240,8 +263,7 @@
|
||||
<nav class="pagetoc"></nav>
|
||||
</div>
|
||||
<div class="content-wrap">
|
||||
|
||||
{{{ content }}}
|
||||
{{{ content }}}
|
||||
</div>
|
||||
</main>
|
||||
</main>
|
||||
@@ -46,4 +46,4 @@ If you have successfully completed KYC on Synaps earlier and provided your Nym w
|
||||
|
||||
Using the Nym network is free for now, but user fees will be introduced in the future and those will be paid in NYM tokens, so set them aside! And until then, you can contribute to running our decentralized infrastructure and earn mix mining rewards by setting up Nym mix nodes and bonding your tokens to them. You don't need to run nodes to contribute to the security and performance of the Nym network though. You can pledge your trust in someone else's node by delegating your NYM tokens to it, and receive a share of their mix mining rewards.
|
||||
|
||||
You can find out more about how staking works in [this](https://www.youtube.com/watch?v=PcNGcTwlm0I) video from our Chief Scientist Claudia Diaz and if you need help setting up your mix node, choosing one to delegate your tokens to, or anything else, our community is there to help on [Discord](https://discord.gg/FaTJb8q8) and [Telegram](https://t.me/nymchan).
|
||||
You can find out more about how staking works in [this](https://www.youtube.com/watch?v=PcNGcTwlm0I) video from our Chief Scientist Claudia Diaz and if you need help setting up your mix node, choosing one to delegate your tokens to, or anything else, our community is there to help on [Discord](https://discord.gg/nym) and [Telegram](https://t.me/nymchan).
|
||||
|
||||
@@ -39,5 +39,5 @@ Follow this [video](https://youtu.be/quj8H2qeOwY?t=97) to see the steps on Teleg
|
||||
|
||||
**Now your Telegram runs over NymConnect.**
|
||||
|
||||
NymConnect is currently available for several applications and service providers. Support for more apps is on the way. For any bug reports or feedback please reach out to us on Telegram or our [Discord](http://discord.gg/FaTJb8q8) server.
|
||||
NymConnect is currently available for several applications and service providers. Support for more apps is on the way. For any bug reports or feedback please reach out to us on Telegram or our [Discord](http://discord.gg/nym) server.
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# mdbook files
|
||||
book/
|
||||
theme/
|
||||
|
||||
# Compiled assets
|
||||
.sass-cache
|
||||
|
||||
@@ -11,7 +11,7 @@ Since these docs autogenerate command output and import docs from binaries in `t
|
||||
Changes merged to `master` will be autodeployed to the production site.
|
||||
|
||||
### Contributing a new translation
|
||||
To contribute tranlsations in a new language, please get in touch via [Matrix](https://matrix.to/#/#general:nymtech.chat) or [Discord](https://discord.gg/FaTJb8q8).
|
||||
To contribute tranlsations in a new language, please get in touch via [Matrix](https://matrix.to/#/#general:nymtech.chat) or [Discord](discord.gg/nym).
|
||||
|
||||
### Variables
|
||||
There are some variables that are shared across the entire docs site, such as the current latest software version.
|
||||
|
||||
@@ -3,7 +3,7 @@ title = "Nym Docs"
|
||||
authors = ["Max Hampshire, Serinko, Alexia Lorenza Martinel"]
|
||||
description = "Nym technical documentation"
|
||||
language = "en"
|
||||
multilingual = false # for the moment - ideally work on chinese, brazillian portugese, spanish next
|
||||
multilingual = false # for the moment - ideally work on chinese, brazillian portugese, spanish next
|
||||
src = "src"
|
||||
|
||||
[rust]
|
||||
@@ -14,18 +14,18 @@ edition = "2018"
|
||||
#################
|
||||
|
||||
[preprocessor.theme]
|
||||
pagetoc = true
|
||||
sidebar-width = "280px"
|
||||
content-max-width = "80%"
|
||||
root-font-size = "70%"
|
||||
# if you need to change anything in the index.hbs file you need to turn this to `false`, rebuild the book,
|
||||
# probably remove the additional `comment` that gets appended to the header, and then change this back to `true`.
|
||||
# this is because of a bug in the `mdbook-theme` plugin
|
||||
pagetoc = true
|
||||
sidebar-width = "280px"
|
||||
content-max-width = "70%"
|
||||
content-main-margin-left = "5%"
|
||||
content-main-margin-right = "5%"
|
||||
root-font-size = "70%"
|
||||
# DO NOT CHANGE or you might overwrite the custom hbs file
|
||||
turn-off = true
|
||||
|
||||
[preprocessor.admonish]
|
||||
command = "mdbook-admonish"
|
||||
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
|
||||
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
|
||||
|
||||
# https://gitlab.com/tglman/mdbook-variables/
|
||||
[preprocessor.variables.variables]
|
||||
@@ -50,56 +50,52 @@ renderer = ["html"]
|
||||
#########
|
||||
|
||||
[build]
|
||||
build-dir = "book" # the directory where the output is placed
|
||||
create-missing = true # whether or not to create missing pages
|
||||
use-default-preprocessors = true # use the default preprocessors
|
||||
extra-watch-dirs = [] # directories to watch for triggering builds
|
||||
build-dir = "book" # the directory where the output is placed
|
||||
create-missing = true # whether or not to create missing pages
|
||||
use-default-preprocessors = true # use the default preprocessors
|
||||
extra-watch-dirs = [] # directories to watch for triggering builds
|
||||
|
||||
##########
|
||||
# OUTPUT #
|
||||
##########
|
||||
|
||||
[output.html]
|
||||
theme = "themes"
|
||||
theme = "nym_themes"
|
||||
default-theme = "coal"
|
||||
preferred-dark-theme = "coal"
|
||||
curly-quotes = true
|
||||
copy-fonts = true
|
||||
no-section-label = false
|
||||
additional-css = [
|
||||
"./themes/custom.css",
|
||||
"./themes/mdbook-admonish.css",
|
||||
"./themes/pagetoc.css",
|
||||
]
|
||||
additional-js = ["./themes/pagetoc.js"]
|
||||
git-repository-url = "https://github.com/nymtech/nym/documentation/"
|
||||
additional-css = ["./nym_themes/custom.css", "./nym_themes/mdbook-admonish.css", "./nym_themes/pagetoc.css"]
|
||||
additional-js = ["./nym_themes/pagetoc.js"]
|
||||
git-repository-url = "https://github.com/nymtech/nym"
|
||||
git-repository-icon = "fa-github"
|
||||
input-404 = "not-found.md"
|
||||
|
||||
[output.html.fold]
|
||||
enable = true # whether or not to enable section folding
|
||||
level = 0 # the depth to start folding
|
||||
enable = true # whether or not to enable section folding
|
||||
level = 0 # the depth to start folding
|
||||
|
||||
# controlling rust sample code blocks
|
||||
[output.html.playground]
|
||||
editable = false # allows editing the source code
|
||||
copyable = true # include the copy button for copying code snippets
|
||||
copy-js = true # includes the JavaScript for the code editor
|
||||
line-numbers = true # displays line numbers for editable code
|
||||
runnable = true # displays a run button for rust code
|
||||
editable = false # allows editing the source code
|
||||
copyable = true # include the copy button for copying code snippets
|
||||
copy-js = true # includes the JavaScript for the code editor
|
||||
line-numbers = true # displays line numbers for editable code
|
||||
runnable = true # displays a run button for rust code
|
||||
|
||||
# options for the built in text search
|
||||
[output.html.search]
|
||||
enable = true # enables the search feature
|
||||
limit-results = 30 # maximum number of search results
|
||||
teaser-word-count = 30 # number of words used for a search result teaser
|
||||
use-boolean-and = true # multiple search terms must all match
|
||||
boost-title = 2 # ranking boost factor for matches in headers
|
||||
boost-hierarchy = 1 # ranking boost factor for matches in page names
|
||||
boost-paragraph = 1 # ranking boost factor for matches in text
|
||||
expand = true # partial words will match longer terms
|
||||
heading-split-level = 3 # link results to heading levels
|
||||
copy-js = true # include Javascript code for search
|
||||
enable = true # enables the search feature
|
||||
limit-results = 30 # maximum number of search results
|
||||
teaser-word-count = 30 # number of words used for a search result teaser
|
||||
use-boolean-and = true # multiple search terms must all match
|
||||
boost-title = 2 # ranking boost factor for matches in headers
|
||||
boost-hierarchy = 1 # ranking boost factor for matches in page names
|
||||
boost-paragraph = 1 # ranking boost factor for matches in text
|
||||
expand = true # partial words will match longer terms
|
||||
heading-split-level = 3 # link results to heading levels
|
||||
copy-js = true # include Javascript code for search
|
||||
|
||||
[output.linkcheck]
|
||||
warning-policy = "warn"
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
--sidebar-resize-indicator-width: 8px;
|
||||
--sidebar-resize-indicator-space: 2px;
|
||||
--page-padding: 15px;
|
||||
--content-max-width: 80%;
|
||||
--content-max-width: 70%;
|
||||
--menu-bar-height: 40px;
|
||||
--mono-font: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace;
|
||||
--code-font-size: 0.875em /* please adjust the ace font size accordingly in editor.js */
|
||||
+3
-6
@@ -8,12 +8,10 @@
|
||||
--sidebar-active: #fb6e4e;
|
||||
--icons-hover: #fb6e4e;
|
||||
--links: #fb6e4e;
|
||||
|
||||
::selection {
|
||||
color: #121726;
|
||||
background-color: #c5573d;
|
||||
}
|
||||
|
||||
select option {
|
||||
background-color: #121726;
|
||||
}
|
||||
@@ -23,18 +21,17 @@
|
||||
--sidebar-active: #fb6e4e;
|
||||
--icons-hover: #fb6e4e;
|
||||
--links: #fb6e4e;
|
||||
|
||||
::selection {
|
||||
color: #f2f2f2;
|
||||
color:#f2f2f2;
|
||||
background-color: #c5573d;
|
||||
}
|
||||
}
|
||||
|
||||
/*properly centering the title given the additional header items*/
|
||||
.menu-title {
|
||||
left: 45%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.menu-bar .a:hover,
|
||||
|
||||
/*necessary because of ^*/
|
||||
@@ -159,14 +159,20 @@
|
||||
</ul>
|
||||
|
||||
<!-- CUSTOM -->
|
||||
<select id="dropdown-menu" class="icon-button">
|
||||
<select id="dropdown-menu3" class="icon-button">
|
||||
<option value="">Network Protocol</option>
|
||||
<option value="https://nymtech.net/docs">Network Docs</option>
|
||||
<option value="https://nymtech.net/learn/papers">Academic Papers</option>
|
||||
<option value="">--------</option>
|
||||
</select>
|
||||
|
||||
<select id="dropdown-menu" class="icon-button">
|
||||
<option value="">Developer Docs</option>
|
||||
<option value="https://nymtech.net/developers">Dev Portal</option>
|
||||
<option value="https://nymtech.net/docs/sdk/rust/rust.html">Rust SDK</option>
|
||||
<option value="https://sdk.nymtech.net">Typescript SDK</option>
|
||||
<option value="">--------</option>
|
||||
</select>
|
||||
|
||||
<select id="dropdown-menu2" class="icon-button">
|
||||
<option value="">Setup Guides</option>
|
||||
<option value="https://nymtech.net/operators">Operators</option>
|
||||
<option value="https://nymtech.net/developers/nymvpn/intro.html">NymVPN Testing</option>
|
||||
@@ -180,7 +186,24 @@
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
document.getElementById('dropdown-menu2').addEventListener('change', function() {
|
||||
const selected = this.options[this.selectedIndex];
|
||||
if (selected.value !== '') {
|
||||
window.location.href = selected.value;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.getElementById('dropdown-menu3').addEventListener('change', function() {
|
||||
const selected = this.options[this.selectedIndex];
|
||||
if (selected.value !== '') {
|
||||
window.location.href = selected.value;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<!-- END CUSTOM -->
|
||||
</div>
|
||||
|
||||
@@ -240,8 +263,7 @@
|
||||
<nav class="pagetoc"></nav>
|
||||
</div>
|
||||
<div class="content-wrap">
|
||||
|
||||
{{{ content }}}
|
||||
{{{ content }}}
|
||||
</div>
|
||||
</main>
|
||||
</main>
|
||||
@@ -36,7 +36,7 @@ Create an account on Sandbox using the nym-cli:
|
||||
|
||||
```./nym-cli --config-env-file <path-to>sandbox.env account create```
|
||||
|
||||
You will need `nymt` funds sent to this account. Get in touch via Nym [Telegram](https://t.me/nymchan) or [Discord](https://discord.gg/FaTJb8q8) and we can send them to you.
|
||||
You will need `nymt` funds sent to this account. Get in touch via Nym [Telegram](https://t.me/nymchan) or [Discord](https://discord.com/invite/nym) and we can send them to you.
|
||||
|
||||
Next, you init the nym-client with the enabled credentials mode set to true:
|
||||
|
||||
|
||||
@@ -15,26 +15,27 @@ declare -a plugins=("admonish" "linkcheck" "last-changed" "theme" "variables" "c
|
||||
install_mdbook_deps() {
|
||||
printf "\ninstalling mdbook..."
|
||||
# installing mdbook with only specific features for speed
|
||||
# cargo install mdbook --no-default-features --features search --vers "^$MINOR_VERSION"
|
||||
cargo install mdbook --no-default-features --vers "^$MINOR_VERSION"
|
||||
# cargo install mdbook --no-default-features --features search --vers "^$MINOR_VERSION"
|
||||
cargo install mdbook --vers "^$MINOR_VERSION"
|
||||
|
||||
printf "\ninstalling plugins..."
|
||||
for i in "${plugins[@]}"; do
|
||||
for i in "${plugins[@]}"
|
||||
do
|
||||
cargo install mdbook-$i
|
||||
done
|
||||
|
||||
# mdbook-admonish config
|
||||
# if [ $(pwd | awk -F/ '{print $NF}') != "documentation" ]; then
|
||||
# printf "not in documentation/ - changing dir but something isn't right in the workflow file"
|
||||
# cd documentation/
|
||||
# mdbook-admonish install dev-portal
|
||||
# mdbook-admonish install docs
|
||||
# mdbook-admonish install operators
|
||||
# else
|
||||
# mdbook-admonish install dev-portal
|
||||
# mdbook-admonish install docs
|
||||
# mdbook-admonish install operators
|
||||
# fi
|
||||
# mdbook-admonish config
|
||||
# if [ $(pwd | awk -F/ '{print $NF}') != "documentation" ]; then
|
||||
# printf "not in documentation/ - changing dir but something isn't right in the workflow file"
|
||||
# cd documentation/
|
||||
# mdbook-admonish install dev-portal
|
||||
# mdbook-admonish install docs
|
||||
# mdbook-admonish install operators
|
||||
# else
|
||||
# mdbook-admonish install dev-portal
|
||||
# mdbook-admonish install docs
|
||||
# mdbook-admonish install operators
|
||||
# fi
|
||||
}
|
||||
|
||||
# uninstall mdbook + plugins
|
||||
@@ -52,27 +53,28 @@ uninstall_mdbook_deps() {
|
||||
|
||||
# plugins
|
||||
printf "\nuninstalling existing plugins...\n"
|
||||
for i in "${plugins[@]}"; do
|
||||
for i in "${plugins[@]}"
|
||||
do
|
||||
cargo uninstall mdbook-$i
|
||||
# check it worked
|
||||
if [ $? -ne 0 ]; then
|
||||
printf "\nsomething went wrong, exiting"
|
||||
exit 1
|
||||
else
|
||||
printf "\nmdbook-$i deleted\n"
|
||||
fi
|
||||
printf "\nmdbook-$i deleted\n"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
if test -f ~/.cargo/bin/mdbook; then
|
||||
printf "mdbook already installed (located at: $(which mdbook))"
|
||||
uninstall_mdbook_deps
|
||||
install_mdbook_deps
|
||||
uninstall_mdbook_deps;
|
||||
install_mdbook_deps;
|
||||
else
|
||||
printf "mdbook not installed"
|
||||
install_mdbook_deps
|
||||
install_mdbook_deps;
|
||||
fi
|
||||
}
|
||||
|
||||
main
|
||||
main;
|
||||
|
||||
@@ -3,7 +3,7 @@ title = "Nym Operators Guide"
|
||||
authors = ["Max Hampshire, Serinko, Alexia Lorenza Martinel"]
|
||||
description = "Everything needed to run Nym Mixnet components"
|
||||
language = "en"
|
||||
multilingual = false # for the moment - ideally work on chinese, brazillian portugese, spanish next
|
||||
multilingual = false # for the moment - ideally work on chinese, brazillian portugese, spanish next
|
||||
src = "src"
|
||||
|
||||
[rust]
|
||||
@@ -14,18 +14,17 @@ edition = "2018"
|
||||
#################
|
||||
|
||||
[preprocessor.theme]
|
||||
pagetoc = true
|
||||
sidebar-width = "280px"
|
||||
content-max-width = "80%"
|
||||
root-font-size = "70%"
|
||||
# if you need to change anything in the index.hbs file you need to turn this to `false`, rebuild the book,
|
||||
# probably remove the additional `comment` that gets appended to the header, and then change this back to `true`.
|
||||
# this is because of a bug in the `mdbook-theme` plugin
|
||||
sidebar-width = "280px"
|
||||
content-max-width = "70%"
|
||||
content-main-margin-left = "5%"
|
||||
content-main-margin-right = "5%"
|
||||
root-font-size = "70%"
|
||||
# DO NOT CHANGE or you might overwrite the custom hbs file
|
||||
turn-off = true
|
||||
|
||||
[preprocessor.admonish]
|
||||
command = "mdbook-admonish"
|
||||
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
|
||||
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
|
||||
|
||||
# https://gitlab.com/tglman/mdbook-variables/
|
||||
[preprocessor.variables.variables]
|
||||
@@ -56,57 +55,53 @@ renderer = ["html"]
|
||||
#########
|
||||
|
||||
[build]
|
||||
build-dir = "book" # the directory where the output is placed
|
||||
create-missing = true # whether or not to create missing pages
|
||||
use-default-preprocessors = true # use the default preprocessors
|
||||
extra-watch-dirs = [] # directories to watch for triggering builds
|
||||
build-dir = "book" # the directory where the output is placed
|
||||
create-missing = true # whether or not to create missing pages
|
||||
use-default-preprocessors = true # use the default preprocessors
|
||||
extra-watch-dirs = [] # directories to watch for triggering builds
|
||||
|
||||
##########
|
||||
# OUTPUT #
|
||||
##########
|
||||
|
||||
[output.html]
|
||||
theme = "themes"
|
||||
theme = "nym_themes"
|
||||
default-theme = "coal"
|
||||
preferred-dark-theme = "coal"
|
||||
#curly-quotes = true
|
||||
smart-punctuation = true
|
||||
copy-fonts = true
|
||||
no-section-label = false
|
||||
additional-css = [
|
||||
"./themes/custom.css",
|
||||
"./themes/mdbook-admonish.css",
|
||||
"./themes/pagetoc.css",
|
||||
]
|
||||
additional-js = ["./themes/pagetoc.js"]
|
||||
additional-css = ["./nym_themes/custom.css", "./nym_themes/mdbook-admonish.css", "./nym_themes/pagetoc.css"]
|
||||
additional-js = ["./nym_themes/pagetoc.js"]
|
||||
git-repository-url = "https://github.com/nymtech/nym"
|
||||
git-repository-icon = "fa-github"
|
||||
input-404 = "not-found.md"
|
||||
|
||||
[output.html.fold]
|
||||
enable = true # whether or not to enable section folding
|
||||
level = 0 # the depth to start folding
|
||||
enable = true # whether or not to enable section folding
|
||||
level = 0 # the depth to start folding
|
||||
|
||||
# controlling rust sample code blocks
|
||||
[output.html.playground]
|
||||
editable = false # allows editing the source code
|
||||
copyable = true # include the copy button for copying code snippets
|
||||
copy-js = true # includes the JavaScript for the code editor
|
||||
line-numbers = true # displays line numbers for editable code
|
||||
runnable = true # displays a run button for rust code
|
||||
editable = false # allows editing the source code
|
||||
copyable = true # include the copy button for copying code snippets
|
||||
copy-js = true # includes the JavaScript for the code editor
|
||||
line-numbers = true # displays line numbers for editable code
|
||||
runnable = true # displays a run button for rust code
|
||||
|
||||
# options for the built in text search
|
||||
[output.html.search]
|
||||
enable = true # enables the search feature
|
||||
limit-results = 30 # maximum number of search results
|
||||
teaser-word-count = 30 # number of words used for a search result teaser
|
||||
use-boolean-and = true # multiple search terms must all match
|
||||
boost-title = 2 # ranking boost factor for matches in headers
|
||||
boost-hierarchy = 1 # ranking boost factor for matches in page names
|
||||
boost-paragraph = 1 # ranking boost factor for matches in text
|
||||
expand = true # partial words will match longer terms
|
||||
heading-split-level = 3 # link results to heading levels
|
||||
copy-js = true # include Javascript code for search
|
||||
enable = true # enables the search feature
|
||||
limit-results = 30 # maximum number of search results
|
||||
teaser-word-count = 30 # number of words used for a search result teaser
|
||||
use-boolean-and = true # multiple search terms must all match
|
||||
boost-title = 2 # ranking boost factor for matches in headers
|
||||
boost-hierarchy = 1 # ranking boost factor for matches in page names
|
||||
boost-paragraph = 1 # ranking boost factor for matches in text
|
||||
expand = true # partial words will match longer terms
|
||||
heading-split-level = 3 # link results to heading levels
|
||||
copy-js = true # include Javascript code for search
|
||||
|
||||
[output.linkcheck]
|
||||
warning-policy = "warn"
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
--sidebar-resize-indicator-width: 8px;
|
||||
--sidebar-resize-indicator-space: 2px;
|
||||
--page-padding: 15px;
|
||||
--content-max-width: 80%;
|
||||
--content-max-width: 70%;
|
||||
--menu-bar-height: 40px;
|
||||
--mono-font: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace;
|
||||
--code-font-size: 0.875em /* please adjust the ace font size accordingly in editor.js */
|
||||
+5
-6
@@ -8,12 +8,10 @@
|
||||
--sidebar-active: #fb6e4e;
|
||||
--icons-hover: #fb6e4e;
|
||||
--links: #fb6e4e;
|
||||
|
||||
::selection {
|
||||
color: #121726;
|
||||
background-color: #c5573d;
|
||||
}
|
||||
|
||||
select option {
|
||||
background-color: #121726;
|
||||
}
|
||||
@@ -23,18 +21,17 @@
|
||||
--sidebar-active: #fb6e4e;
|
||||
--icons-hover: #fb6e4e;
|
||||
--links: #fb6e4e;
|
||||
|
||||
::selection {
|
||||
color: #f2f2f2;
|
||||
color:#f2f2f2;
|
||||
background-color: #c5573d;
|
||||
}
|
||||
}
|
||||
|
||||
/*properly centering the title given the additional header items*/
|
||||
.menu-title {
|
||||
left: 45%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.menu-bar .a:hover,
|
||||
|
||||
/*necessary because of ^*/
|
||||
@@ -47,6 +44,8 @@ select {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
footer {
|
||||
font-size: 0.8em;
|
||||
text-align: center;
|
||||
+28
-6
@@ -159,14 +159,20 @@
|
||||
</ul>
|
||||
|
||||
<!-- CUSTOM -->
|
||||
<select id="dropdown-menu" class="icon-button">
|
||||
<select id="dropdown-menu3" class="icon-button">
|
||||
<option value="">Network Protocol</option>
|
||||
<option value="https://nymtech.net/docs">Network Docs</option>
|
||||
<option value="https://nymtech.net/learn/papers">Academic Papers</option>
|
||||
<option value="">--------</option>
|
||||
</select>
|
||||
|
||||
<select id="dropdown-menu" class="icon-button">
|
||||
<option value="">Developer Docs</option>
|
||||
<option value="https://nymtech.net/developers">Dev Portal</option>
|
||||
<option value="https://nymtech.net/docs/sdk/rust/rust.html">Rust SDK</option>
|
||||
<option value="https://sdk.nymtech.net">Typescript SDK</option>
|
||||
<option value="">--------</option>
|
||||
</select>
|
||||
|
||||
<select id="dropdown-menu2" class="icon-button">
|
||||
<option value="">Setup Guides</option>
|
||||
<option value="https://nymtech.net/operators">Operators</option>
|
||||
<option value="https://nymtech.net/developers/nymvpn/intro.html">NymVPN Testing</option>
|
||||
@@ -180,7 +186,24 @@
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
document.getElementById('dropdown-menu2').addEventListener('change', function() {
|
||||
const selected = this.options[this.selectedIndex];
|
||||
if (selected.value !== '') {
|
||||
window.location.href = selected.value;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.getElementById('dropdown-menu3').addEventListener('change', function() {
|
||||
const selected = this.options[this.selectedIndex];
|
||||
if (selected.value !== '') {
|
||||
window.location.href = selected.value;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<!-- END CUSTOM -->
|
||||
</div>
|
||||
|
||||
@@ -240,8 +263,7 @@
|
||||
<nav class="pagetoc"></nav>
|
||||
</div>
|
||||
<div class="content-wrap">
|
||||
|
||||
{{{ content }}}
|
||||
{{{ content }}}
|
||||
</div>
|
||||
</main>
|
||||
</main>
|
||||
@@ -11,7 +11,7 @@ This document presents an initiative to further support Nym’s mission of allow
|
||||
All the technical changes on the side of Nym nodes - ***Project Smoosh*** - are described in the [FAQ section](../archive/faq/smoosh-faq.md).
|
||||
|
||||
```admonish warning
|
||||
Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the operator channels ([Element](https://matrix.to/#/#operators:nymtech.chat), [Discord](https://discord.gg/FaTJb8q8), [Telegram](https://t.me/nymchan_help_chat)) to share best practices and experiences.
|
||||
Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the operator channels ([Element](https://matrix.to/#/#operators:nymtech.chat), [Discord](https://discord.com/invite/nym), [Telegram](https://t.me/nymchan_help_chat)) to share best practices and experiences.
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,6 @@ If the `/dev/sda` partition is almost full, try pruning some of the `.gz` syslog
|
||||
|
||||
## Where can I get more help?
|
||||
|
||||
The fastest way to reach one of us or get a help from the community, visit our [Telegram Node Setup Help Chat](https://t.me/nymchan_help_chat) or head to our [Discord](https://discord.gg/FaTJb8q8).
|
||||
The fastest way to reach one of us or get a help from the community, visit our [Telegram Node Setup Help Chat](https://t.me/nymchan_help_chat) or head to our [Discord](https://Discord.gg/nym).
|
||||
|
||||
For more tech heavy question join our [Matrix core community channel](https://matrix.to/#/#general:nymtech.chat), where you can meet other builders and Nym core team members.
|
||||
|
||||
@@ -8,80 +8,81 @@ import fs from "fs";
|
||||
import { glob } from "glob";
|
||||
|
||||
async function main() {
|
||||
const distDir = "../../../dist/docs";
|
||||
const distDir = "../../../dist/docs";
|
||||
|
||||
const items = [];
|
||||
const items = [];
|
||||
|
||||
const books = [
|
||||
'developers',
|
||||
'docs',
|
||||
'operators',
|
||||
];
|
||||
const books = [
|
||||
'developers',
|
||||
'docs',
|
||||
'operators',
|
||||
];
|
||||
|
||||
for (const book of books) {
|
||||
// only process the root `index.html` files, because they have absolute paths instead of relative paths
|
||||
const filenames = [path.resolve(distDir, book, 'index.html')];
|
||||
for(const book of books)
|
||||
{
|
||||
// only process the root `index.html` files, because they have absolute paths instead of relative paths
|
||||
const filenames = [ path.resolve(distDir, book, 'index.html') ];
|
||||
|
||||
// leaving this here for a future where other files need to be processed
|
||||
// const filenames = await glob(path.resolve(distDir, book) + '/**/*.html');
|
||||
// leaving this here for a future where other files need to be processed
|
||||
// const filenames = await glob(path.resolve(distDir, book) + '/**/*.html');
|
||||
|
||||
for (const f of filenames) {
|
||||
// Create a Rehype processor with the inspectUrls plugin
|
||||
const processor = unified()
|
||||
.use(parse)
|
||||
.use(inspectUrls, {
|
||||
inspectEach(args) {
|
||||
const { url: rawUrl, propertyName } = args;
|
||||
const { tagName } = args.node;
|
||||
const filename = args.file.history[0];
|
||||
for (const f of filenames) {
|
||||
// Create a Rehype processor with the inspectUrls plugin
|
||||
const processor = unified()
|
||||
.use(parse)
|
||||
.use(inspectUrls, {
|
||||
inspectEach(args) {
|
||||
const { url: rawUrl, propertyName } = args;
|
||||
const { tagName } = args.node;
|
||||
const filename = args.file.history[0];
|
||||
|
||||
const relativeFilename = path.relative(distDir, filename);
|
||||
const relativeDirectory = path.dirname(relativeFilename);
|
||||
const relativeFilename = path.relative(distDir, filename);
|
||||
const relativeDirectory = path.dirname(relativeFilename);
|
||||
|
||||
// remove relative paths from URL
|
||||
const bareUrl = rawUrl.split('/').filter(c => c !== '.' && c !== '..').join('/');
|
||||
let url;
|
||||
// remove relative paths from URL
|
||||
const bareUrl = rawUrl.split('/').filter(c => c !== '.' && c !== '..').join('/');
|
||||
let url;
|
||||
|
||||
if (rawUrl.includes('.html#')) {
|
||||
url = path.join(`/${relativeDirectory}`, bareUrl);
|
||||
} else if (rawUrl.startsWith('#')) {
|
||||
url = path.join(`/`, relativeFilename + bareUrl);
|
||||
} else {
|
||||
url = path.join(`/${book}`, bareUrl);
|
||||
}
|
||||
if(rawUrl.includes('.html#')) {
|
||||
url = path.join(`/${relativeDirectory}`, bareUrl);
|
||||
} else if(rawUrl.startsWith('#')) {
|
||||
url = path.join(`/`, relativeFilename + bareUrl);
|
||||
} else {
|
||||
url = path.join(`/${book}`, bareUrl);
|
||||
}
|
||||
|
||||
// const item = { filename, relativeDirectory, tagName, propertyName, rawUrl, url };
|
||||
const item = { tagName, rawUrl, url };
|
||||
// const item = { filename, relativeDirectory, tagName, propertyName, rawUrl, url };
|
||||
const item = { tagName, rawUrl, url };
|
||||
|
||||
// if (tagName === 'a') {
|
||||
// console.log(`tagName = a, args are: $args`);
|
||||
// }
|
||||
// if(tagName === 'a') {
|
||||
// console.log(args);
|
||||
// }
|
||||
|
||||
if (!rawUrl.startsWith('http')) {
|
||||
if (tagName === 'link' || tagName === 'script' || tagName === 'a') {
|
||||
args.node.properties[propertyName] = url;
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.use(stringify);
|
||||
if(!rawUrl.startsWith('http')) {
|
||||
if (tagName === 'link' || tagName === 'script' || tagName === 'a') {
|
||||
args.node.properties[propertyName] = url;
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.use(stringify);
|
||||
|
||||
// Read the example HTML file
|
||||
const filename = path.resolve(distDir, f);
|
||||
console.log(`${filename}...`);
|
||||
// Read the example HTML file
|
||||
const filename = path.resolve(distDir, f);
|
||||
console.log(`${filename}...`);
|
||||
|
||||
let file = await read(filename);
|
||||
let file = await read(filename);
|
||||
|
||||
// Crawl the HTML file and find all the URLs
|
||||
const res = await processor.process(file);
|
||||
// Crawl the HTML file and find all the URLs
|
||||
const res = await processor.process(file);
|
||||
|
||||
fs.writeFileSync(filename, res.value);
|
||||
fs.writeFileSync(filename, res.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// console.table(items);
|
||||
// console.log();
|
||||
// console.table(items);
|
||||
// console.log();
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "explorer-api"
|
||||
version = "1.1.36"
|
||||
version = "1.1.35"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { DiscordIcon } from '../icons/socials/DiscordIcon'
|
||||
export const TELEGRAM_LINK = 'https://t.me/nymchan'
|
||||
export const TWITTER_LINK = 'https://twitter.com/nymproject'
|
||||
export const GITHUB_LINK = 'https://github.com/nymtech'
|
||||
export const DISCORD_LINK = 'https://discord.gg/FaTJb8q8'
|
||||
export const DISCORD_LINK = 'https://discord.gg/nym'
|
||||
|
||||
export const Socials: FCWithChildren<{ isFooter?: boolean }> = ({
|
||||
isFooter = false,
|
||||
|
||||
@@ -10,7 +10,7 @@ import { DiscordIcon } from '../icons/socials/DiscordIcon';
|
||||
export const TELEGRAM_LINK = 'https://t.me/nymchan';
|
||||
export const TWITTER_LINK = 'https://twitter.com/nymproject';
|
||||
export const GITHUB_LINK = 'https://github.com/nymtech';
|
||||
export const DISCORD_LINK = 'https://discord.gg/FaTJb8q8';
|
||||
export const DISCORD_LINK = 'https://discord.gg/nym';
|
||||
|
||||
export const Socials: FCWithChildren<{ isFooter?: boolean }> = ({ isFooter }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
@@ -58,7 +58,6 @@ zeroize = { workspace = true }
|
||||
|
||||
# internal
|
||||
|
||||
nym-authenticator = { path = "../service-providers/authenticator" }
|
||||
nym-api-requests = { path = "../nym-api/nym-api-requests" }
|
||||
nym-bin-common = { path = "../common/bin-common", features = ["output_format"] }
|
||||
nym-config = { path = "../common/config" }
|
||||
|
||||
+3
-22
@@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::node::storage::error::StorageError;
|
||||
use nym_authenticator::error::AuthenticatorError;
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
use nym_network_requester::error::{ClientCoreError, NetworkRequesterError};
|
||||
use nym_validator_client::nyxd::error::NyxdError;
|
||||
@@ -61,16 +60,6 @@ pub enum GatewayError {
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"failed to load config file for authenticator (gateway-id: '{id}') using path '{}'. detailed message: {source}",
|
||||
path.display()
|
||||
)]
|
||||
AuthenticatorConfigLoadFailure {
|
||||
id: String,
|
||||
path: PathBuf,
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"failed to load config file for wireguard (gateway-id: '{id}') using path '{}'. detailed message: {source}",
|
||||
path.display()
|
||||
@@ -121,9 +110,6 @@ pub enum GatewayError {
|
||||
#[error("Path to ip packet router configuration file hasn't been specified. Perhaps try to run `setup-ip-packet-router`?")]
|
||||
UnspecifiedIpPacketRouterConfig,
|
||||
|
||||
#[error("Path to authenticator configuration file hasn't been specified. Perhaps try to run `setup-authenticator`?")]
|
||||
UnspecifiedAuthenticatorConfig,
|
||||
|
||||
#[error("there was an issue with the local network requester: {source}")]
|
||||
NetworkRequesterFailure {
|
||||
#[from]
|
||||
@@ -136,12 +122,6 @@ pub enum GatewayError {
|
||||
source: IpPacketRouterError,
|
||||
},
|
||||
|
||||
#[error("there was an issue with the local authenticator: {source}")]
|
||||
AuthenticatorFailure {
|
||||
#[from]
|
||||
source: AuthenticatorError,
|
||||
},
|
||||
|
||||
#[error("failed to startup local network requester")]
|
||||
NetworkRequesterStartupFailure,
|
||||
|
||||
@@ -194,8 +174,9 @@ pub enum GatewayError {
|
||||
#[error("wireguard not set")]
|
||||
WireguardNotSet,
|
||||
|
||||
#[error("failed to start authenticator: {source}")]
|
||||
AuthenticatorStartError {
|
||||
#[cfg(all(feature = "wireguard", target_os = "linux"))]
|
||||
#[error("failed to catch an interrupt: {source}")]
|
||||
StdError {
|
||||
source: Box<dyn std::error::Error + Send + Sync>,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ impl<'a> HttpApiBuilder<'a> {
|
||||
}
|
||||
|
||||
let bind_address = self.gateway_config.http.bind_address;
|
||||
let router = nym_node_http_api::NymNodeRouter::new(config, None);
|
||||
let router = nym_node_http_api::NymNodeRouter::new(config, None, None);
|
||||
|
||||
tokio::spawn(async move {
|
||||
let server = match router.build_server(&bind_address).await {
|
||||
|
||||
+15
-40
@@ -89,7 +89,7 @@ pub async fn create_gateway(
|
||||
|
||||
let ip_opts = ip_packet_router_config.map(|config| LocalIpPacketRouterOpts {
|
||||
config,
|
||||
custom_mixnet_path: custom_mixnet.clone(),
|
||||
custom_mixnet_path: custom_mixnet,
|
||||
});
|
||||
|
||||
Gateway::new(config, nr_opts, ip_opts, storage)
|
||||
@@ -109,13 +109,6 @@ pub struct LocalIpPacketRouterOpts {
|
||||
pub custom_mixnet_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LocalAuthenticatorOpts {
|
||||
pub config: nym_authenticator::Config,
|
||||
|
||||
pub custom_mixnet_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub struct Gateway<St = PersistentStorage> {
|
||||
config: Config,
|
||||
|
||||
@@ -123,10 +116,6 @@ pub struct Gateway<St = PersistentStorage> {
|
||||
|
||||
ip_packet_router_opts: Option<LocalIpPacketRouterOpts>,
|
||||
|
||||
// Use None when wireguard feature is not enabled too
|
||||
#[allow(dead_code)]
|
||||
authenticator_opts: Option<LocalAuthenticatorOpts>,
|
||||
|
||||
/// ed25519 keypair used to assert one's identity.
|
||||
identity_keypair: Arc<identity::KeyPair>,
|
||||
|
||||
@@ -157,7 +146,6 @@ impl<St> Gateway<St> {
|
||||
config,
|
||||
network_requester_opts,
|
||||
ip_packet_router_opts,
|
||||
authenticator_opts: None,
|
||||
#[cfg(all(feature = "wireguard", target_os = "linux"))]
|
||||
wireguard_data: None,
|
||||
run_http_server: true,
|
||||
@@ -169,7 +157,6 @@ impl<St> Gateway<St> {
|
||||
config: Config,
|
||||
network_requester_opts: Option<LocalNetworkRequesterOpts>,
|
||||
ip_packet_router_opts: Option<LocalIpPacketRouterOpts>,
|
||||
authenticator_opts: Option<LocalAuthenticatorOpts>,
|
||||
identity_keypair: Arc<identity::KeyPair>,
|
||||
sphinx_keypair: Arc<encryption::KeyPair>,
|
||||
storage: St,
|
||||
@@ -178,7 +165,6 @@ impl<St> Gateway<St> {
|
||||
config,
|
||||
network_requester_opts,
|
||||
ip_packet_router_opts,
|
||||
authenticator_opts,
|
||||
identity_keypair,
|
||||
sphinx_keypair,
|
||||
storage,
|
||||
@@ -236,18 +222,11 @@ impl<St> Gateway<St> {
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "wireguard", target_os = "linux"))]
|
||||
async fn start_authenticator(
|
||||
async fn start_wireguard(
|
||||
&mut self,
|
||||
opts: &LocalAuthenticatorOpts,
|
||||
shutdown: TaskClient,
|
||||
) -> Result<Arc<nym_wireguard::WgApiWrapper>, Box<dyn std::error::Error + Send + Sync>> {
|
||||
if let Some(wireguard_data) = self.wireguard_data.take() {
|
||||
let authenticator_server = nym_authenticator::Authenticator::new(
|
||||
opts.config.clone(),
|
||||
wireguard_data.inner.clone(),
|
||||
)
|
||||
.with_shutdown(shutdown.fork("authenticator"));
|
||||
tokio::spawn(async move { authenticator_server.run_service_provider().await });
|
||||
nym_wireguard::start_wireguard(shutdown, wireguard_data).await
|
||||
} else {
|
||||
Err(Box::new(GatewayError::WireguardNotSet))
|
||||
@@ -255,12 +234,8 @@ impl<St> Gateway<St> {
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "wireguard", not(target_os = "linux")))]
|
||||
async fn start_authenticator(
|
||||
&self,
|
||||
_opts: &LocalAuthenticatorOpts,
|
||||
_shutdown: TaskClient,
|
||||
) -> Result<Arc<nym_wireguard::WgApiWrapper>, Box<dyn std::error::Error + Send + Sync>> {
|
||||
todo!("Authenticator is currently only supported on Linux");
|
||||
async fn start_wireguard(&self, _shutdown: TaskClient) {
|
||||
nym_wireguard::start_wireguard().await
|
||||
}
|
||||
|
||||
fn start_client_websocket_listener(
|
||||
@@ -563,17 +538,6 @@ impl<St> Gateway<St> {
|
||||
info!("embedded ip packet router is disabled");
|
||||
};
|
||||
|
||||
#[cfg(feature = "wireguard")]
|
||||
let _wg_api = if let Some(opts) = self.authenticator_opts.clone() {
|
||||
Some(
|
||||
self.start_authenticator(&opts, shutdown.fork("wireguard"))
|
||||
.await
|
||||
.map_err(|source| GatewayError::AuthenticatorStartError { source })?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if self.run_http_server {
|
||||
HttpApiBuilder::new(
|
||||
&self.config,
|
||||
@@ -586,6 +550,17 @@ impl<St> Gateway<St> {
|
||||
.start(shutdown.fork("http-api"))?;
|
||||
}
|
||||
|
||||
// Once this is a bit more mature, make this a commandline flag instead of a compile time
|
||||
// flag
|
||||
#[cfg(all(feature = "wireguard", target_os = "linux"))]
|
||||
let _wg_api = self
|
||||
.start_wireguard(shutdown.fork("wireguard"))
|
||||
.await
|
||||
.map_err(|source| GatewayError::StdError { source })?;
|
||||
|
||||
#[cfg(all(feature = "wireguard", not(target_os = "linux")))]
|
||||
self.start_wireguard(shutdown.fork("wireguard")).await;
|
||||
|
||||
info!("Finished nym gateway startup procedure - it should now be able to receive mix and client traffic!");
|
||||
|
||||
info!(
|
||||
|
||||
@@ -103,7 +103,7 @@ impl<'a> HttpApiBuilder<'a> {
|
||||
.with_mixnode(load_mixnode_details(self.mixnode_config)?)
|
||||
.with_landing_page_assets(self.mixnode_config.http.landing_page_assets_path.as_ref());
|
||||
|
||||
let router = nym_node_http_api::NymNodeRouter::new(config, None);
|
||||
let router = nym_node_http_api::NymNodeRouter::new(config, None, None);
|
||||
|
||||
tokio::spawn(async move {
|
||||
let server = match router.build_server(&bind_address).await {
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
[package]
|
||||
name = "nym-api"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.40"
|
||||
version = "1.1.39"
|
||||
authors = [
|
||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nym_nodes::NodeRole;
|
||||
use crate::pagination::PaginatedResponse;
|
||||
use cosmwasm_std::{Addr, Coin, Decimal};
|
||||
use nym_mixnet_contract_common::families::FamilyHead;
|
||||
@@ -9,7 +8,7 @@ use nym_mixnet_contract_common::mixnode::MixNodeDetails;
|
||||
use nym_mixnet_contract_common::reward_params::{Performance, RewardingParams};
|
||||
use nym_mixnet_contract_common::rewarding::RewardEstimate;
|
||||
use nym_mixnet_contract_common::{
|
||||
GatewayBond, IdentityKey, Interval, MixId, MixNode, MixNodeBond, Percent, RewardedSetNodeStatus,
|
||||
GatewayBond, IdentityKey, Interval, MixId, MixNode, Percent, RewardedSetNodeStatus,
|
||||
};
|
||||
use nym_node_requests::api::v1::node::models::{AuxiliaryDetails, BinaryBuildInformationOwned};
|
||||
use schemars::gen::SchemaGenerator;
|
||||
@@ -606,13 +605,8 @@ pub struct NymNodeDescription {
|
||||
#[serde(default)]
|
||||
pub ip_packet_router: Option<IpPacketRouterDetails>,
|
||||
|
||||
#[serde(default)]
|
||||
pub authenticator: Option<AuthenticatorDetails>,
|
||||
|
||||
// for now we only care about their ws/wss situation, nothing more
|
||||
pub mixnet_websockets: WebSockets,
|
||||
|
||||
pub role: NodeRole,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)]
|
||||
@@ -630,21 +624,6 @@ impl From<GatewayBond> for DescribedGateway {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)]
|
||||
pub struct DescribedMixNode {
|
||||
pub bond: MixNodeBond,
|
||||
pub self_described: Option<NymNodeDescription>,
|
||||
}
|
||||
|
||||
impl From<MixNodeBond> for DescribedMixNode {
|
||||
fn from(bond: MixNodeBond) -> Self {
|
||||
DescribedMixNode {
|
||||
bond,
|
||||
self_described: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)]
|
||||
pub struct NetworkRequesterDetails {
|
||||
/// address of the embedded network requester
|
||||
@@ -660,12 +639,6 @@ pub struct IpPacketRouterDetails {
|
||||
pub address: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)]
|
||||
pub struct AuthenticatorDetails {
|
||||
/// address of the embedded authenticator
|
||||
pub address: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, schemars::JsonSchema)]
|
||||
pub struct ApiHealthResponse {
|
||||
pub status: ApiStatus,
|
||||
|
||||
@@ -1034,7 +1034,6 @@ impl super::client::Client for DummyClient {
|
||||
events: vec![cosmwasm_std::Event::new("wasm")
|
||||
.add_attribute(NODE_INDEX, assigned_index.to_string())],
|
||||
}],
|
||||
events: Default::default(),
|
||||
data: Default::default(),
|
||||
transaction_hash,
|
||||
gas_info: Default::default(),
|
||||
@@ -1068,7 +1067,6 @@ impl super::client::Client for DummyClient {
|
||||
|
||||
Ok(ExecuteResult {
|
||||
logs: vec![],
|
||||
events: Default::default(),
|
||||
data: Default::default(),
|
||||
transaction_hash,
|
||||
gas_info: Default::default(),
|
||||
@@ -1103,7 +1101,6 @@ impl super::client::Client for DummyClient {
|
||||
|
||||
Ok(ExecuteResult {
|
||||
logs: vec![],
|
||||
events: Default::default(),
|
||||
data: Default::default(),
|
||||
transaction_hash,
|
||||
gas_info: Default::default(),
|
||||
@@ -1180,7 +1177,6 @@ impl super::client::Client for DummyClient {
|
||||
events: vec![cosmwasm_std::Event::new("wasm")
|
||||
.add_attribute(DKG_PROPOSAL_ID, proposal_id.to_string())],
|
||||
}],
|
||||
events: Default::default(),
|
||||
data: Default::default(),
|
||||
transaction_hash,
|
||||
gas_info: Default::default(),
|
||||
|
||||
@@ -8,11 +8,11 @@ use crate::support::config;
|
||||
use crate::support::config::DEFAULT_NODE_DESCRIBE_BATCH_SIZE;
|
||||
use futures::{stream, StreamExt};
|
||||
use nym_api_requests::models::{
|
||||
AuthenticatorDetails, IpPacketRouterDetails, NetworkRequesterDetails, NymNodeDescription,
|
||||
IpPacketRouterDetails, NetworkRequesterDetails, NymNodeDescription,
|
||||
};
|
||||
use nym_api_requests::nym_nodes::NodeRole;
|
||||
use nym_config::defaults::{mainnet, DEFAULT_NYM_NODE_HTTP_PORT};
|
||||
use nym_contracts_common::IdentityKey;
|
||||
use nym_mixnet_contract_common::Gateway;
|
||||
use nym_node_requests::api::client::{NymNodeApiClientError, NymNodeApiClientExt};
|
||||
use std::collections::HashMap;
|
||||
use thiserror::Error;
|
||||
@@ -56,6 +56,8 @@ pub enum NodeDescribeCacheError {
|
||||
}
|
||||
|
||||
pub struct NodeDescriptionProvider {
|
||||
// for now we only care about gateways, nothing more
|
||||
// network_gateways: SharedCache<Vec<GatewayBond>>,
|
||||
contract_cache: NymContractCache,
|
||||
|
||||
batch_size: usize,
|
||||
@@ -77,32 +79,27 @@ impl NodeDescriptionProvider {
|
||||
}
|
||||
|
||||
async fn try_get_client(
|
||||
host: &str,
|
||||
identity_key: &IdentityKey,
|
||||
port: Option<u16>,
|
||||
gateway: &Gateway,
|
||||
) -> Result<nym_node_requests::api::Client, NodeDescribeCacheError> {
|
||||
let gateway_host = &gateway.host;
|
||||
|
||||
// first try the standard port in case the operator didn't put the node behind the proxy,
|
||||
// then default https (443)
|
||||
// finally default http (80)
|
||||
let mut addresses_to_try = vec![
|
||||
format!("http://{host}:{DEFAULT_NYM_NODE_HTTP_PORT}"),
|
||||
format!("http://{host}:8000"),
|
||||
format!("https://{host}"),
|
||||
format!("http://{host}"),
|
||||
let addresses_to_try = vec![
|
||||
format!("http://{gateway_host}:{DEFAULT_NYM_NODE_HTTP_PORT}"),
|
||||
format!("https://{gateway_host}"),
|
||||
format!("http://{gateway_host}"),
|
||||
];
|
||||
|
||||
if let Some(port) = port {
|
||||
addresses_to_try.insert(0, format!("http://{host}:{port}"));
|
||||
}
|
||||
|
||||
for address in addresses_to_try {
|
||||
// if provided host was malformed, no point in continuing
|
||||
let client = match nym_node_requests::api::Client::new_url(address, None) {
|
||||
Ok(client) => client,
|
||||
Err(err) => {
|
||||
return Err(NodeDescribeCacheError::MalformedHost {
|
||||
host: host.to_string(),
|
||||
gateway: identity_key.clone(),
|
||||
host: gateway_host.clone(),
|
||||
gateway: gateway.identity_key.clone(),
|
||||
source: err,
|
||||
});
|
||||
}
|
||||
@@ -115,28 +112,28 @@ async fn try_get_client(
|
||||
}
|
||||
|
||||
Err(NodeDescribeCacheError::NoHttpPortsAvailable {
|
||||
host: host.to_string(),
|
||||
gateway: identity_key.to_string(),
|
||||
host: gateway_host.clone(),
|
||||
gateway: gateway.identity_key.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn try_get_description(
|
||||
data: RefreshData,
|
||||
async fn get_gateway_description(
|
||||
gateway: Gateway,
|
||||
) -> Result<(IdentityKey, NymNodeDescription), NodeDescribeCacheError> {
|
||||
let client = try_get_client(&data.host(), &data.identity_key(), data.port()).await?;
|
||||
let client = try_get_client(&gateway).await?;
|
||||
|
||||
let host_info =
|
||||
client
|
||||
.get_host_information()
|
||||
.await
|
||||
.map_err(|err| NodeDescribeCacheError::ApiFailure {
|
||||
gateway: data.identity_key().to_string(),
|
||||
gateway: gateway.identity_key.clone(),
|
||||
source: err,
|
||||
})?;
|
||||
|
||||
if !host_info.verify_host_information() {
|
||||
return Err(NodeDescribeCacheError::MissignedHostInformation {
|
||||
gateway: data.identity_key().clone(),
|
||||
gateway: gateway.identity_key,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -145,13 +142,13 @@ async fn try_get_description(
|
||||
.get_build_information()
|
||||
.await
|
||||
.map_err(|err| NodeDescribeCacheError::ApiFailure {
|
||||
gateway: data.identity_key().clone(),
|
||||
gateway: gateway.identity_key.clone(),
|
||||
source: err,
|
||||
})?;
|
||||
|
||||
// this can be an old node that hasn't yet exposed this
|
||||
let auxiliary_details = client.get_auxiliary_details().await.inspect_err(|err| {
|
||||
debug!("could not obtain auxiliary details of node {}: {err} is it running an old version?", data.identity_key());
|
||||
debug!("could not obtain auxiliary details of gateway {}: {err} is it running an old version?", gateway.identity_key);
|
||||
}).unwrap_or_default();
|
||||
|
||||
let websockets =
|
||||
@@ -159,7 +156,7 @@ async fn try_get_description(
|
||||
.get_mixnet_websockets()
|
||||
.await
|
||||
.map_err(|err| NodeDescribeCacheError::ApiFailure {
|
||||
gateway: data.identity_key().clone(),
|
||||
gateway: gateway.identity_key.clone(),
|
||||
source: err,
|
||||
})?;
|
||||
|
||||
@@ -167,7 +164,7 @@ async fn try_get_description(
|
||||
if let Ok(nr) = client.get_network_requester().await {
|
||||
let exit_policy = client.get_exit_policy().await.map_err(|err| {
|
||||
NodeDescribeCacheError::ApiFailure {
|
||||
gateway: data.identity_key().clone(),
|
||||
gateway: gateway.identity_key.clone(),
|
||||
source: err,
|
||||
}
|
||||
})?;
|
||||
@@ -189,61 +186,17 @@ async fn try_get_description(
|
||||
None
|
||||
};
|
||||
|
||||
let authenticator = if let Ok(auth) = client.get_authenticator().await {
|
||||
Some(AuthenticatorDetails {
|
||||
address: auth.address,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let description = NymNodeDescription {
|
||||
host_information: host_info.data.into(),
|
||||
last_polled: OffsetDateTime::now_utc().into(),
|
||||
build_information: build_info,
|
||||
network_requester,
|
||||
ip_packet_router,
|
||||
authenticator,
|
||||
mixnet_websockets: websockets.into(),
|
||||
auxiliary_details,
|
||||
role: data.role(),
|
||||
};
|
||||
|
||||
Ok((data.identity_key().clone(), description))
|
||||
}
|
||||
|
||||
struct RefreshData {
|
||||
host: String,
|
||||
identity_key: IdentityKey,
|
||||
role: NodeRole,
|
||||
port: Option<u16>,
|
||||
}
|
||||
|
||||
impl RefreshData {
|
||||
pub fn new(host: String, identity_key: IdentityKey, role: NodeRole, port: Option<u16>) -> Self {
|
||||
RefreshData {
|
||||
host,
|
||||
identity_key,
|
||||
role,
|
||||
port,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn host(&self) -> String {
|
||||
self.host.clone()
|
||||
}
|
||||
|
||||
pub fn identity_key(&self) -> IdentityKey {
|
||||
self.identity_key.clone()
|
||||
}
|
||||
|
||||
pub fn port(&self) -> Option<u16> {
|
||||
self.port
|
||||
}
|
||||
|
||||
pub fn role(&self) -> NodeRole {
|
||||
self.role.clone()
|
||||
}
|
||||
Ok((gateway.identity_key, description))
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@@ -256,56 +209,36 @@ impl CacheItemProvider for NodeDescriptionProvider {
|
||||
}
|
||||
|
||||
async fn try_refresh(&self) -> Result<Self::Item, Self::Error> {
|
||||
let mut host_id_pairs = self
|
||||
.contract_cache
|
||||
.gateways_all()
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|full| {
|
||||
RefreshData::new(
|
||||
full.gateway.host,
|
||||
full.gateway.identity_key,
|
||||
NodeRole::EntryGateway,
|
||||
None,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<RefreshData>>();
|
||||
let gateways = self.contract_cache.gateways_all().await;
|
||||
|
||||
host_id_pairs.extend(
|
||||
self.contract_cache
|
||||
.mixnodes_all()
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|full| {
|
||||
RefreshData::new(
|
||||
full.bond_information.mix_node.host,
|
||||
full.bond_information.mix_node.identity_key,
|
||||
NodeRole::Mixnode {
|
||||
layer: full.bond_information.layer.into(),
|
||||
},
|
||||
Some(full.bond_information.mix_node.mix_port),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<RefreshData>>(),
|
||||
);
|
||||
// let guard = self.network_gateways.get().await?;
|
||||
// let gateways = &*guard;
|
||||
|
||||
if host_id_pairs.is_empty() {
|
||||
if gateways.is_empty() {
|
||||
return Ok(HashMap::new());
|
||||
}
|
||||
|
||||
let node_description = stream::iter(host_id_pairs.into_iter().map(try_get_description))
|
||||
.buffer_unordered(self.batch_size)
|
||||
.filter_map(|res| async move {
|
||||
match res {
|
||||
Ok((identity, description)) => Some((identity, description)),
|
||||
Err(err) => {
|
||||
debug!("failed to obtain gateway self-described data: {err}");
|
||||
None
|
||||
}
|
||||
// TODO: somehow bypass the 'higher-ranked lifetime error' and remove that redundant clone
|
||||
let node_description = stream::iter(
|
||||
gateways
|
||||
// .deref()
|
||||
// .clone()
|
||||
.into_iter()
|
||||
.map(|bond| bond.gateway)
|
||||
.map(get_gateway_description),
|
||||
)
|
||||
.buffer_unordered(self.batch_size)
|
||||
.filter_map(|res| async move {
|
||||
match res {
|
||||
Ok((identity, description)) => Some((identity, description)),
|
||||
Err(err) => {
|
||||
debug!("failed to obtain gateway self-described data: {err}");
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<HashMap<_, _>>()
|
||||
.await;
|
||||
}
|
||||
})
|
||||
.collect::<HashMap<_, _>>()
|
||||
.await;
|
||||
|
||||
Ok(node_description)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ mod unstable_routes;
|
||||
/// Merges the routes with http information and returns it to Rocket for serving
|
||||
pub(crate) fn nym_node_routes(settings: &OpenApiSettings) -> (Vec<Route>, OpenApi) {
|
||||
openapi_get_routes_spec![
|
||||
settings: routes::get_gateways_described, routes::get_mixnodes_described
|
||||
settings: routes::get_gateways_described
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
use crate::node_describe_cache::DescribedNodes;
|
||||
use crate::nym_contract_cache::cache::NymContractCache;
|
||||
use crate::support::caching::cache::SharedCache;
|
||||
use nym_api_requests::models::{DescribedGateway, DescribedMixNode};
|
||||
use nym_mixnet_contract_common::MixNodeBond;
|
||||
use nym_api_requests::models::DescribedGateway;
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::State;
|
||||
use rocket_okapi::openapi;
|
||||
@@ -43,38 +42,3 @@ pub async fn get_gateways_described(
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
#[openapi(tag = "Nym Nodes")]
|
||||
#[get("/mixnodes/described")]
|
||||
pub async fn get_mixnodes_described(
|
||||
contract_cache: &State<NymContractCache>,
|
||||
describe_cache: &State<SharedCache<DescribedNodes>>,
|
||||
) -> Json<Vec<DescribedMixNode>> {
|
||||
let mixnodes = contract_cache
|
||||
.mixnodes_filtered()
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|m| m.bond_information)
|
||||
.collect::<Vec<MixNodeBond>>();
|
||||
if mixnodes.is_empty() {
|
||||
return Json(Vec::new());
|
||||
}
|
||||
|
||||
// if the self describe cache is unavailable, well, don't attach describe data
|
||||
let Ok(self_descriptions) = describe_cache.get().await else {
|
||||
return Json(mixnodes.into_iter().map(Into::into).collect());
|
||||
};
|
||||
|
||||
// TODO: this is extremely inefficient, but given we don't have many gateways,
|
||||
// it shouldn't be too much of a problem until we go ahead with directory v3 / the smoosh 2: electric smoosharoo,
|
||||
// but at that point (I hope) the whole caching situation should get refactored
|
||||
Json(
|
||||
mixnodes
|
||||
.into_iter()
|
||||
.map(|bond| DescribedMixNode {
|
||||
self_described: self_descriptions.deref().get(bond.identity()).cloned(),
|
||||
bond,
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
+1
-2
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-node"
|
||||
version = "1.1.4"
|
||||
version = "1.1.3"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
@@ -55,7 +55,6 @@ nym-wireguard-types = { path = "../common/wireguard-types", default-features = f
|
||||
# nodes:
|
||||
nym-mixnode = { path = "../mixnode" }
|
||||
nym-gateway = { path = "../gateway" }
|
||||
nym-authenticator = { path = "../service-providers/authenticator" }
|
||||
nym-network-requester = { path = "../service-providers/network-requester" }
|
||||
nym-ip-packet-router = { path = "../service-providers/ip-packet-router" }
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::api::v1::gateway::client_interfaces::wireguard::WireguardAppState;
|
||||
use crate::state::AppState;
|
||||
use axum::Router;
|
||||
use nym_node_requests::routes;
|
||||
@@ -16,6 +17,9 @@ pub struct Config {
|
||||
pub v1_config: v1::Config,
|
||||
}
|
||||
|
||||
pub(super) fn routes(config: Config) -> Router<AppState> {
|
||||
Router::new().nest(routes::api::V1, v1::routes(config.v1_config))
|
||||
pub(super) fn routes(config: Config, initial_wg_state: WireguardAppState) -> Router<AppState> {
|
||||
Router::new().nest(
|
||||
routes::api::V1,
|
||||
v1::routes(config.v1_config, initial_wg_state),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use nym_node_requests::api::v1::authenticator::models;
|
||||
|
||||
pub mod root;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Config {
|
||||
pub details: Option<models::Authenticator>,
|
||||
}
|
||||
|
||||
pub(crate) fn routes<S: Send + Sync + 'static + Clone>(config: Config) -> Router<S> {
|
||||
Router::new().route(
|
||||
"/",
|
||||
get({
|
||||
let authenticator_details = config.details;
|
||||
move |query| root::root_authenticator(authenticator_details, query)
|
||||
}),
|
||||
)
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::router::api::{FormattedResponse, OutputParams};
|
||||
use axum::extract::Query;
|
||||
use axum::http::StatusCode;
|
||||
use nym_node_requests::api::v1::authenticator::models::Authenticator;
|
||||
|
||||
/// Returns root authenticator information
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "",
|
||||
context_path = "/api/v1/authenticator",
|
||||
tag = "Authenticator",
|
||||
responses(
|
||||
(status = 501, description = "the endpoint hasn't been implemented yet"),
|
||||
(status = 200, content(
|
||||
("application/json" = Authenticator),
|
||||
("application/yaml" = Authenticator)
|
||||
))
|
||||
),
|
||||
params(OutputParams)
|
||||
)]
|
||||
pub(crate) async fn root_authenticator(
|
||||
details: Option<Authenticator>,
|
||||
Query(output): Query<OutputParams>,
|
||||
) -> Result<AuthenticatorResponse, StatusCode> {
|
||||
let details = details.ok_or(StatusCode::NOT_IMPLEMENTED)?;
|
||||
let output = output.output.unwrap_or_default();
|
||||
Ok(output.to_response(details))
|
||||
}
|
||||
|
||||
pub type AuthenticatorResponse = FormattedResponse<Authenticator>;
|
||||
@@ -1,16 +1,20 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::api::v1::gateway::client_interfaces::wireguard::WireguardAppState;
|
||||
use crate::api::{FormattedResponse, OutputParams};
|
||||
use axum::extract::Query;
|
||||
use axum::http::StatusCode;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use nym_node_requests::api::v1::gateway::models::{ClientInterfaces, WebSockets};
|
||||
use nym_node_requests::api::v1::gateway::models::{ClientInterfaces, WebSockets, Wireguard};
|
||||
use nym_node_requests::routes::api::v1::gateway::client_interfaces;
|
||||
|
||||
pub(crate) mod wireguard;
|
||||
|
||||
pub(crate) fn routes<S: Send + Sync + 'static + Clone>(
|
||||
interfaces: Option<ClientInterfaces>,
|
||||
initial_wg_state: WireguardAppState,
|
||||
) -> Router<S> {
|
||||
Router::new()
|
||||
.route(
|
||||
@@ -27,6 +31,17 @@ pub(crate) fn routes<S: Send + Sync + 'static + Clone>(
|
||||
move |query| mixnet_websockets(websockets, query)
|
||||
}),
|
||||
)
|
||||
.nest(
|
||||
client_interfaces::WIREGUARD,
|
||||
wireguard::routes(initial_wg_state),
|
||||
)
|
||||
.route(
|
||||
client_interfaces::WIREGUARD,
|
||||
get({
|
||||
let wireguard_cfg_info = interfaces.and_then(|i| i.wireguard);
|
||||
move |query| wireguard_info(wireguard_cfg_info, query)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns client interfaces supported by this gateway.
|
||||
@@ -55,6 +70,32 @@ pub(crate) async fn client_interfaces(
|
||||
|
||||
pub type ClientInterfacesResponse = FormattedResponse<ClientInterfaces>;
|
||||
|
||||
/// Returns client interfaces supported by this gateway.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/wireguard",
|
||||
context_path = "/api/v1/gateway/client-interfaces",
|
||||
tag = "Gateway",
|
||||
responses(
|
||||
(status = 501, description = "the endpoint hasn't been implemented yet"),
|
||||
(status = 200, content(
|
||||
("application/json" = Wireguard),
|
||||
("application/yaml" = Wireguard)
|
||||
))
|
||||
),
|
||||
params(OutputParams)
|
||||
)]
|
||||
pub(crate) async fn wireguard_info(
|
||||
wireguard: Option<Wireguard>,
|
||||
Query(output): Query<OutputParams>,
|
||||
) -> Result<WireguardResponse, StatusCode> {
|
||||
let wireguard = wireguard.ok_or(StatusCode::NOT_IMPLEMENTED)?;
|
||||
let output = output.output.unwrap_or_default();
|
||||
Ok(output.to_response(wireguard))
|
||||
}
|
||||
|
||||
pub type WireguardResponse = FormattedResponse<Wireguard>;
|
||||
|
||||
/// Returns client interfaces supported by this gateway.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use super::error::WireguardError;
|
||||
use crate::api::v1::gateway::client_interfaces::wireguard::{
|
||||
WireguardAppState, WireguardAppStateInner,
|
||||
};
|
||||
use crate::api::{FormattedResponse, OutputParams};
|
||||
use crate::router::types::RequestError;
|
||||
use axum::extract::{Path, Query, State};
|
||||
use axum::http::StatusCode;
|
||||
use axum::Json;
|
||||
use nym_node_requests::api::v1::gateway::client_interfaces::wireguard::models::{
|
||||
ClientMessage, ClientRegistrationResponse, GatewayClient, InitMessage, PeerPublicKey,
|
||||
};
|
||||
use nym_wireguard_types::registration::RegistrationData;
|
||||
use rand::{prelude::IteratorRandom, thread_rng};
|
||||
|
||||
fn remove_from_registry(
|
||||
state: &WireguardAppStateInner,
|
||||
remote_public: &PeerPublicKey,
|
||||
gateway_client: &GatewayClient,
|
||||
) -> Result<(), RequestError> {
|
||||
state
|
||||
.wireguard_gateway_data
|
||||
.remove_peer(gateway_client)
|
||||
.map_err(|err| RequestError::from_err(err, StatusCode::INTERNAL_SERVER_ERROR))?;
|
||||
state
|
||||
.wireguard_gateway_data
|
||||
.client_registry()
|
||||
.remove(remote_public);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn process_final_message(
|
||||
client: GatewayClient,
|
||||
state: &WireguardAppStateInner,
|
||||
) -> Result<ClientRegistrationResponse, RequestError> {
|
||||
let registration_data = state
|
||||
.registration_in_progress
|
||||
.get(&client.pub_key())
|
||||
.ok_or(RequestError::from_err(
|
||||
WireguardError::RegistrationNotInProgress,
|
||||
StatusCode::BAD_REQUEST,
|
||||
))?
|
||||
.value()
|
||||
.clone();
|
||||
|
||||
if client
|
||||
.verify(
|
||||
state.wireguard_gateway_data.keypair().private_key(),
|
||||
registration_data.nonce,
|
||||
)
|
||||
.is_ok()
|
||||
{
|
||||
state
|
||||
.wireguard_gateway_data
|
||||
.add_peer(&client)
|
||||
.map_err(|err| RequestError::from_err(err, StatusCode::INTERNAL_SERVER_ERROR))?;
|
||||
state.registration_in_progress.remove(&client.pub_key());
|
||||
state
|
||||
.wireguard_gateway_data
|
||||
.client_registry()
|
||||
.insert(client.pub_key(), client);
|
||||
|
||||
Ok(ClientRegistrationResponse::Registered)
|
||||
} else {
|
||||
Err(RequestError::from_err(
|
||||
WireguardError::MacVerificationFailure,
|
||||
StatusCode::BAD_REQUEST,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
async fn process_init_message(
|
||||
init_message: InitMessage,
|
||||
state: &WireguardAppStateInner,
|
||||
) -> Result<ClientRegistrationResponse, RequestError> {
|
||||
let remote_public = init_message.pub_key();
|
||||
let nonce: u64 = fastrand::u64(..);
|
||||
if let Some(registration_data) = state.registration_in_progress.get(&remote_public) {
|
||||
return Ok(ClientRegistrationResponse::PendingRegistration(
|
||||
registration_data.value().clone(),
|
||||
));
|
||||
}
|
||||
let gateway_client_opt = if let Some(gateway_client) = state
|
||||
.wireguard_gateway_data
|
||||
.client_registry()
|
||||
.get(&remote_public)
|
||||
{
|
||||
let mut private_ip_ref = state
|
||||
.free_private_network_ips
|
||||
.get_mut(&gateway_client.private_ip)
|
||||
.ok_or(RequestError::new(
|
||||
"Internal data corruption",
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
))?;
|
||||
*private_ip_ref = true;
|
||||
Some(gateway_client.clone())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(gateway_client) = gateway_client_opt {
|
||||
remove_from_registry(state, &remote_public, &gateway_client)?;
|
||||
}
|
||||
let mut private_ip_ref = state
|
||||
.free_private_network_ips
|
||||
.iter_mut()
|
||||
.filter(|r| **r)
|
||||
.choose(&mut thread_rng())
|
||||
.ok_or(RequestError::new(
|
||||
"No more space in the network",
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
))?;
|
||||
// mark it as used, even though it's not final
|
||||
*private_ip_ref = false;
|
||||
let gateway_data = GatewayClient::new(
|
||||
state.wireguard_gateway_data.keypair().private_key(),
|
||||
remote_public.inner(),
|
||||
*private_ip_ref.key(),
|
||||
nonce,
|
||||
);
|
||||
let registration_data = RegistrationData {
|
||||
nonce,
|
||||
gateway_data,
|
||||
wg_port: state.binding_port,
|
||||
};
|
||||
state
|
||||
.registration_in_progress
|
||||
.insert(remote_public, registration_data.clone());
|
||||
Ok(ClientRegistrationResponse::PendingRegistration(
|
||||
registration_data,
|
||||
))
|
||||
}
|
||||
|
||||
/// Perform wireguard client registration.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/client",
|
||||
context_path = "/api/v1/gateway/client-interfaces/wireguard",
|
||||
tag = "Wireguard (EXPERIMENTAL AND UNSTABLE)",
|
||||
request_body(
|
||||
content = ClientMessage,
|
||||
description = "Data used for proceeding with client wireguard registration",
|
||||
content_type = "application/json"
|
||||
),
|
||||
responses(
|
||||
(status = 501, body = ErrorResponse, description = "the endpoint hasn't been implemented yet"),
|
||||
(status = 400, body = ErrorResponse),
|
||||
(status = 200, content(
|
||||
("application/json" = ClientRegistrationResponse),
|
||||
("application/yaml" = ClientRegistrationResponse)
|
||||
))
|
||||
),
|
||||
params(OutputParams)
|
||||
)]
|
||||
pub(crate) async fn register_client(
|
||||
State(state): State<WireguardAppState>,
|
||||
Query(output): Query<OutputParams>,
|
||||
Json(payload): Json<ClientMessage>,
|
||||
) -> Result<RegisterClientResponse, RequestError> {
|
||||
let output = output.output.unwrap_or_default();
|
||||
|
||||
let Some(state) = state.inner() else {
|
||||
return Err(RequestError::new_status(StatusCode::NOT_IMPLEMENTED));
|
||||
};
|
||||
|
||||
let response = match payload {
|
||||
ClientMessage::Initial(init) => process_init_message(init, state).await?,
|
||||
ClientMessage::Final(finalize) => process_final_message(finalize, state).await?,
|
||||
};
|
||||
Ok(output.to_response(response))
|
||||
}
|
||||
|
||||
pub type RegisterClientResponse = FormattedResponse<ClientRegistrationResponse>;
|
||||
|
||||
/// Get public keys of all registered wireguard clients.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/clients",
|
||||
context_path = "/api/v1/gateway/client-interfaces/wireguard",
|
||||
tag = "Wireguard (EXPERIMENTAL AND UNSTABLE)",
|
||||
responses(
|
||||
(status = 501, body = ErrorResponse, description = "the endpoint hasn't been implemented yet"),
|
||||
(status = 200, content(
|
||||
("application/json" = Vec<String>),
|
||||
("application/yaml" = Vec<String>)
|
||||
))
|
||||
),
|
||||
params(OutputParams)
|
||||
)]
|
||||
pub(crate) async fn get_all_clients(
|
||||
Query(output): Query<OutputParams>,
|
||||
State(state): State<WireguardAppState>,
|
||||
) -> Result<AllClientsResponse, RequestError> {
|
||||
let output = output.output.unwrap_or_default();
|
||||
|
||||
let Some(state) = state.inner() else {
|
||||
return Err(RequestError::new_status(StatusCode::NOT_IMPLEMENTED));
|
||||
};
|
||||
|
||||
let clients = state
|
||||
.wireguard_gateway_data
|
||||
.client_registry()
|
||||
.iter()
|
||||
.map(|c| c.pub_key())
|
||||
.collect::<Vec<PeerPublicKey>>();
|
||||
|
||||
Ok(output.to_response(clients))
|
||||
}
|
||||
|
||||
pub type AllClientsResponse = FormattedResponse<Vec<PeerPublicKey>>;
|
||||
|
||||
/// Get client details of the registered wireguard client by its public key.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/client/{pub_key}",
|
||||
context_path = "/api/v1/gateway/client-interfaces/wireguard",
|
||||
tag = "Wireguard (EXPERIMENTAL AND UNSTABLE)",
|
||||
params(
|
||||
("pub_key", Path, description = "The public key of the client"),
|
||||
OutputParams
|
||||
),
|
||||
responses(
|
||||
(status = 501, body = ErrorResponse, description = "the endpoint hasn't been implemented yet"),
|
||||
(status = 404, body = ErrorResponse, description = "there are no clients with the provided public key"),
|
||||
(status = 400, body = ErrorResponse),
|
||||
(status = 200, content(
|
||||
("application/json" = Vec<GatewayClient>),
|
||||
("application/yaml" = Vec<GatewayClient>)
|
||||
))
|
||||
),
|
||||
)]
|
||||
pub(crate) async fn get_client(
|
||||
Path(pub_key): Path<PeerPublicKey>,
|
||||
Query(output): Query<OutputParams>,
|
||||
State(state): State<WireguardAppState>,
|
||||
) -> Result<ClientResponse, RequestError> {
|
||||
let output = output.output.unwrap_or_default();
|
||||
|
||||
let Some(state) = state.inner() else {
|
||||
return Err(RequestError::new_status(StatusCode::NOT_IMPLEMENTED));
|
||||
};
|
||||
|
||||
let clients = state
|
||||
.wireguard_gateway_data
|
||||
.client_registry()
|
||||
.iter()
|
||||
.filter_map(|c| {
|
||||
if c.pub_key() == pub_key {
|
||||
Some(c.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<GatewayClient>>();
|
||||
|
||||
if clients.is_empty() {
|
||||
return Err(RequestError::new_status(StatusCode::NOT_FOUND));
|
||||
}
|
||||
|
||||
Ok(output.to_response(clients))
|
||||
}
|
||||
|
||||
pub type ClientResponse = FormattedResponse<Vec<GatewayClient>>;
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WireguardError {
|
||||
#[error("the client is currently not in the process of being registered")]
|
||||
RegistrationNotInProgress,
|
||||
|
||||
#[error("the client mac failed to get verified correctly")]
|
||||
MacVerificationFailure,
|
||||
}
|
||||
+296
@@ -0,0 +1,296 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::api::v1::gateway::client_interfaces::wireguard::client_registry::{
|
||||
get_all_clients, get_client, register_client,
|
||||
};
|
||||
use crate::error::NymNodeHttpError;
|
||||
use axum::routing::{get, post};
|
||||
use axum::Router;
|
||||
use ipnetwork::IpNetwork;
|
||||
use nym_node_requests::routes::api::v1::gateway::client_interfaces::wireguard;
|
||||
use nym_wireguard::WireguardGatewayData;
|
||||
use nym_wireguard_types::registration::PendingRegistrations;
|
||||
use nym_wireguard_types::registration::PrivateIPs;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub(crate) mod client_registry;
|
||||
mod error;
|
||||
|
||||
// I don't see any reason why this state should be accessible to any routes outside /wireguard
|
||||
// if anyone finds compelling reason, it could be moved to the `AppState` struct instead
|
||||
#[derive(Clone, Default)]
|
||||
pub struct WireguardAppState {
|
||||
inner: Option<WireguardAppStateInner>,
|
||||
}
|
||||
|
||||
impl WireguardAppState {
|
||||
pub fn new(
|
||||
wireguard_gateway_data: WireguardGatewayData,
|
||||
registration_in_progress: Arc<PendingRegistrations>,
|
||||
binding_port: u16,
|
||||
private_ip_network: IpNetwork,
|
||||
) -> Result<Self, NymNodeHttpError> {
|
||||
Ok(WireguardAppState {
|
||||
inner: Some(WireguardAppStateInner {
|
||||
wireguard_gateway_data,
|
||||
registration_in_progress,
|
||||
binding_port,
|
||||
free_private_network_ips: Arc::new(
|
||||
private_ip_network.iter().map(|ip| (ip, true)).collect(),
|
||||
),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
// #[allow(dead_code)]
|
||||
// pub(crate) fn dh_keypair(&self) -> Option<&encryption::KeyPair> {
|
||||
// self.inner.as_ref().map(|s| s.dh_keypair.as_ref())
|
||||
// }
|
||||
//
|
||||
// #[allow(dead_code)]
|
||||
// pub(crate) fn client_registry(&self) -> Option<&RwLock<ClientRegistry>> {
|
||||
// self.inner.as_ref().map(|s| s.client_registry.as_ref())
|
||||
// }
|
||||
//
|
||||
// #[allow(dead_code)]
|
||||
// pub(crate) fn registration_in_progress(&self) -> Option<&RwLock<PendingRegistrations>> {
|
||||
// self.inner
|
||||
// .as_ref()
|
||||
// .map(|s| s.registration_in_progress.as_ref())
|
||||
// }
|
||||
|
||||
// not sure what to feel about exposing this method
|
||||
pub(crate) fn inner(&self) -> Option<&WireguardAppStateInner> {
|
||||
self.inner.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
// helper macro to deal with missing wg state (if not being exposed by the node)
|
||||
#[macro_export]
|
||||
macro_rules! get_state {
|
||||
( $state: ident, $field: ident ) => {{
|
||||
let Some(ref inner) = $state.inner else {
|
||||
return ::axum::http::StatusCode::NOT_IMPLEMENTED;
|
||||
};
|
||||
inner.$field.as_ref()
|
||||
}};
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct WireguardAppStateInner {
|
||||
wireguard_gateway_data: WireguardGatewayData,
|
||||
registration_in_progress: Arc<PendingRegistrations>,
|
||||
binding_port: u16,
|
||||
free_private_network_ips: Arc<PrivateIPs>,
|
||||
}
|
||||
|
||||
pub(crate) fn routes<S>(initial_state: WireguardAppState) -> Router<S> {
|
||||
Router::new()
|
||||
// .route("/", get())
|
||||
.route(wireguard::CLIENTS, get(get_all_clients))
|
||||
.route(wireguard::CLIENT, post(register_client))
|
||||
.route(&format!("{}/:pub_key", wireguard::CLIENT), get(get_client))
|
||||
.with_state(initial_state)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::api::v1::gateway::client_interfaces::wireguard::{
|
||||
routes, WireguardAppState, WireguardAppStateInner,
|
||||
};
|
||||
use axum::body::to_bytes;
|
||||
use axum::body::Body;
|
||||
use axum::http::Request;
|
||||
use axum::http::StatusCode;
|
||||
use base64::{engine::general_purpose, Engine as _};
|
||||
use dashmap::DashMap;
|
||||
use hmac::Mac;
|
||||
use ipnetwork::IpNetwork;
|
||||
use nym_crypto::asymmetric::encryption;
|
||||
use nym_node_requests::api::v1::gateway::client_interfaces::wireguard::models::{
|
||||
ClientMac, ClientMessage, ClientRegistrationResponse, GatewayClient, InitMessage,
|
||||
PeerPublicKey,
|
||||
};
|
||||
use nym_node_requests::routes::api::v1::gateway::client_interfaces::wireguard;
|
||||
use nym_wireguard::{peer_controller::PeerControlMessage, WireguardGatewayData};
|
||||
use nym_wireguard_types::registration::{HmacSha256, RegistrationData};
|
||||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use tower::Service;
|
||||
use tower::ServiceExt;
|
||||
use x25519_dalek::{PublicKey, StaticSecret};
|
||||
|
||||
const PRIVATE_KEY: &str = "AEqXrLFT4qjYq3wmX0456iv94uM6nDj5ugp6Jedcflg=";
|
||||
|
||||
fn decode_base64_key(base64_key: &str) -> [u8; 32] {
|
||||
general_purpose::STANDARD
|
||||
.decode(base64_key)
|
||||
.unwrap()
|
||||
.try_into()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn server_static_private_key() -> x25519_dalek::StaticSecret {
|
||||
// TODO: this is a temporary solution for development
|
||||
let static_private_bytes: [u8; 32] = decode_base64_key(PRIVATE_KEY);
|
||||
x25519_dalek::StaticSecret::from(static_private_bytes)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn registration() {
|
||||
// 1. Provision random keys for gateway and client
|
||||
// 2. Generate DH shared secret
|
||||
// 3. Client submits its public key to the gateway to start the handshake process, gateway responds with nonce
|
||||
// 4. Client generates mac digest using DH shared secret, its own public key, socket address and port, and nonce
|
||||
// 5. Client sends its public key, socket address and port, nonce and mac digest to the gateway
|
||||
// 6. Gateway verifies mac digest and nonce, and stores client's public key and socket address and port
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let gateway_private_key =
|
||||
encryption::PrivateKey::from_bytes(server_static_private_key().as_bytes()).unwrap();
|
||||
let gateway_public_key = encryption::PublicKey::from(&gateway_private_key);
|
||||
|
||||
let gateway_key_pair = encryption::KeyPair::from_bytes(
|
||||
&gateway_private_key.to_bytes(),
|
||||
&gateway_public_key.to_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
||||
|
||||
let gateway_static_public = PublicKey::from(gateway_key_pair.public_key().to_bytes());
|
||||
|
||||
let client_static_private = StaticSecret::from(client_key_pair.private_key().to_bytes());
|
||||
let client_static_public = PublicKey::from(client_key_pair.public_key().to_bytes());
|
||||
|
||||
let client_dh = client_static_private.diffie_hellman(&gateway_static_public);
|
||||
|
||||
let registration_in_progress = Arc::new(DashMap::new());
|
||||
let free_private_network_ips = Arc::new(
|
||||
IpNetwork::from_str("10.1.0.0/24")
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|ip| (ip, true))
|
||||
.collect(),
|
||||
);
|
||||
let client_private_ip = IpAddr::from_str("10.1.0.42").unwrap();
|
||||
let (wireguard_gateway_data, mut peer_rx) = WireguardGatewayData::new(
|
||||
nym_wireguard_types::Config {
|
||||
bind_address: "0.0.0.0:51822".parse().unwrap(),
|
||||
private_ip: "10.1.0.1".parse().unwrap(),
|
||||
announced_port: 51822,
|
||||
private_network_prefix: 16,
|
||||
},
|
||||
Arc::new(gateway_key_pair),
|
||||
);
|
||||
|
||||
let state = WireguardAppState {
|
||||
inner: Some(WireguardAppStateInner {
|
||||
wireguard_gateway_data: wireguard_gateway_data.clone(),
|
||||
registration_in_progress: Arc::clone(®istration_in_progress),
|
||||
binding_port: 8080,
|
||||
free_private_network_ips,
|
||||
}),
|
||||
};
|
||||
|
||||
// `Router` implements `tower::Service<Request<Body>>` so we can
|
||||
// call it like any tower service, no need to run an HTTP server.
|
||||
let mut app = routes(state);
|
||||
|
||||
let init_message = ClientMessage::Initial(InitMessage {
|
||||
pub_key: PeerPublicKey::new(client_static_public),
|
||||
});
|
||||
|
||||
let init_request = Request::builder()
|
||||
.method("POST")
|
||||
.uri(wireguard::CLIENT)
|
||||
.header("Content-type", "application/json")
|
||||
.body(Body::from(serde_json::to_vec(&init_message).unwrap()))
|
||||
.unwrap();
|
||||
|
||||
let response = ServiceExt::<Request<Body>>::ready(&mut app)
|
||||
.await
|
||||
.unwrap()
|
||||
.call(init_request)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert!(!registration_in_progress.is_empty());
|
||||
|
||||
let ClientRegistrationResponse::PendingRegistration(RegistrationData {
|
||||
nonce,
|
||||
gateway_data,
|
||||
wg_port: 8080,
|
||||
}) = serde_json::from_slice(&to_bytes(response.into_body(), usize::MAX).await.unwrap())
|
||||
.unwrap()
|
||||
else {
|
||||
panic!("invalid response")
|
||||
};
|
||||
assert!(gateway_data
|
||||
.verify(client_key_pair.private_key(), nonce)
|
||||
.is_ok());
|
||||
|
||||
let mut mac = HmacSha256::new_from_slice(client_dh.as_bytes()).unwrap();
|
||||
mac.update(client_static_public.as_bytes());
|
||||
mac.update(client_private_ip.to_string().as_bytes());
|
||||
mac.update(&nonce.to_le_bytes());
|
||||
let mac = mac.finalize().into_bytes();
|
||||
|
||||
let finalized_message = ClientMessage::Final(GatewayClient {
|
||||
pub_key: PeerPublicKey::new(client_static_public),
|
||||
private_ip: client_private_ip,
|
||||
mac: ClientMac::new(mac.as_slice().to_vec()),
|
||||
});
|
||||
|
||||
let final_request = Request::builder()
|
||||
.method("POST")
|
||||
.uri(wireguard::CLIENT)
|
||||
.header("Content-type", "application/json")
|
||||
.body(Body::from(serde_json::to_vec(&finalized_message).unwrap()))
|
||||
.unwrap();
|
||||
|
||||
let response = ServiceExt::<Request<Body>>::ready(&mut app)
|
||||
.await
|
||||
.unwrap()
|
||||
.call(final_request)
|
||||
.await
|
||||
.unwrap();
|
||||
let msg = peer_rx.recv().await.unwrap();
|
||||
|
||||
assert!(matches!(msg, PeerControlMessage::AddPeer(_)));
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert!(!wireguard_gateway_data.client_registry().is_empty());
|
||||
|
||||
let clients_request = Request::builder()
|
||||
.method("GET")
|
||||
.uri(wireguard::CLIENTS)
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
let response = ServiceExt::<Request<Body>>::ready(&mut app)
|
||||
.await
|
||||
.unwrap()
|
||||
.call(clients_request)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
|
||||
let clients: Vec<PeerPublicKey> =
|
||||
serde_json::from_slice(&to_bytes(response.into_body(), usize::MAX).await.unwrap())
|
||||
.unwrap();
|
||||
|
||||
assert!(!clients.is_empty());
|
||||
|
||||
assert_eq!(
|
||||
wireguard_gateway_data
|
||||
.client_registry()
|
||||
.iter()
|
||||
.map(|c| c.value().pub_key())
|
||||
.collect::<Vec<PeerPublicKey>>(),
|
||||
clients
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::api::v1::gateway::client_interfaces::wireguard::WireguardAppState;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use nym_node_requests::api::v1::gateway::models;
|
||||
@@ -14,7 +15,10 @@ pub struct Config {
|
||||
pub details: Option<models::Gateway>,
|
||||
}
|
||||
|
||||
pub(crate) fn routes<S: Send + Sync + 'static + Clone>(config: Config) -> Router<S> {
|
||||
pub(crate) fn routes<S: Send + Sync + 'static + Clone>(
|
||||
config: Config,
|
||||
initial_wg_state: WireguardAppState,
|
||||
) -> Router<S> {
|
||||
Router::new()
|
||||
.route(
|
||||
"/",
|
||||
@@ -25,6 +29,9 @@ pub(crate) fn routes<S: Send + Sync + 'static + Clone>(config: Config) -> Router
|
||||
)
|
||||
.nest(
|
||||
gateway::CLIENT_INTERFACES,
|
||||
client_interfaces::routes(config.details.map(|g| g.client_interfaces)),
|
||||
client_interfaces::routes(
|
||||
config.details.map(|g| g.client_interfaces),
|
||||
initial_wg_state,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::api::v1::gateway::client_interfaces::wireguard::WireguardAppState;
|
||||
use crate::state::AppState;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use nym_node_requests::routes::api::v1;
|
||||
|
||||
pub mod authenticator;
|
||||
pub mod gateway;
|
||||
pub mod health;
|
||||
pub mod ip_packet_router;
|
||||
@@ -24,14 +24,16 @@ pub struct Config {
|
||||
pub mixnode: mixnode::Config,
|
||||
pub network_requester: network_requester::Config,
|
||||
pub ip_packet_router: ip_packet_router::Config,
|
||||
pub authenticator: authenticator::Config,
|
||||
}
|
||||
|
||||
pub(super) fn routes(config: Config) -> Router<AppState> {
|
||||
pub(super) fn routes(config: Config, initial_wg_state: WireguardAppState) -> Router<AppState> {
|
||||
Router::new()
|
||||
.route(v1::HEALTH, get(health::root_health))
|
||||
.nest(v1::METRICS, metrics::routes(config.metrics))
|
||||
.nest(v1::GATEWAY, gateway::routes(config.gateway))
|
||||
.nest(
|
||||
v1::GATEWAY,
|
||||
gateway::routes(config.gateway, initial_wg_state),
|
||||
)
|
||||
.nest(v1::MIXNODE, mixnode::routes(config.mixnode))
|
||||
.nest(
|
||||
v1::NETWORK_REQUESTER,
|
||||
@@ -41,10 +43,6 @@ pub(super) fn routes(config: Config) -> Router<AppState> {
|
||||
v1::IP_PACKET_ROUTER,
|
||||
ip_packet_router::routes(config.ip_packet_router),
|
||||
)
|
||||
.nest(
|
||||
v1::AUTHENTICATOR,
|
||||
authenticator::routes(config.authenticator),
|
||||
)
|
||||
.merge(node::routes(config.node))
|
||||
.merge(openapi::route())
|
||||
}
|
||||
|
||||
@@ -26,7 +26,11 @@ use utoipa_swagger_ui::SwaggerUi;
|
||||
api::v1::health::root_health,
|
||||
api::v1::gateway::root::root_gateway,
|
||||
api::v1::gateway::client_interfaces::client_interfaces,
|
||||
api::v1::gateway::client_interfaces::wireguard_info,
|
||||
api::v1::gateway::client_interfaces::mixnet_websockets,
|
||||
api::v1::gateway::client_interfaces::wireguard::client_registry::register_client,
|
||||
api::v1::gateway::client_interfaces::wireguard::client_registry::get_all_clients,
|
||||
api::v1::gateway::client_interfaces::wireguard::client_registry::get_client,
|
||||
api::v1::mixnode::root::root_mixnode,
|
||||
api::v1::network_requester::root::root_network_requester,
|
||||
api::v1::network_requester::exit_policy::node_exit_policy,
|
||||
@@ -63,6 +67,7 @@ use utoipa_swagger_ui::SwaggerUi;
|
||||
api_requests::v1::gateway::client_interfaces::wireguard::models::ClientMessage,
|
||||
api_requests::v1::gateway::client_interfaces::wireguard::models::InitMessage,
|
||||
api_requests::v1::gateway::client_interfaces::wireguard::models::GatewayClient,
|
||||
api_requests::v1::gateway::client_interfaces::wireguard::models::ClientRegistrationResponse,
|
||||
api_requests::v1::mixnode::models::Mixnode,
|
||||
api_requests::v1::network_requester::models::NetworkRequester,
|
||||
api_requests::v1::network_requester::exit_policy::models::AddressPolicy,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
pub use crate::api::v1::gateway::client_interfaces::wireguard::WireguardAppState;
|
||||
use crate::error::NymNodeHttpError;
|
||||
use crate::middleware::logging;
|
||||
use crate::state::AppState;
|
||||
@@ -8,7 +9,6 @@ use crate::NymNodeHTTPServer;
|
||||
use axum::response::Redirect;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use nym_node_requests::api::v1::authenticator::models::Authenticator;
|
||||
use nym_node_requests::api::v1::gateway::models::{Gateway, Wireguard};
|
||||
use nym_node_requests::api::v1::ip_packet_router::models::IpPacketRouter;
|
||||
use nym_node_requests::api::v1::mixnode::models::Mixnode;
|
||||
@@ -54,7 +54,6 @@ impl Config {
|
||||
mixnode: Default::default(),
|
||||
network_requester: Default::default(),
|
||||
ip_packet_router: Default::default(),
|
||||
authenticator: Default::default(),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -149,12 +148,6 @@ impl Config {
|
||||
self.api.v1_config.ip_packet_router.details = Some(ip_packet_router);
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_authenticator_details(mut self, authenticator: Authenticator) -> Self {
|
||||
self.api.v1_config.authenticator.details = Some(authenticator);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NymNodeRouter {
|
||||
@@ -163,7 +156,11 @@ pub struct NymNodeRouter {
|
||||
|
||||
impl NymNodeRouter {
|
||||
// TODO: move the wg state to a builder
|
||||
pub fn new(config: Config, app_state: Option<AppState>) -> NymNodeRouter {
|
||||
pub fn new(
|
||||
config: Config,
|
||||
app_state: Option<AppState>,
|
||||
initial_wg_state: Option<WireguardAppState>,
|
||||
) -> NymNodeRouter {
|
||||
let state = app_state.unwrap_or(AppState::new());
|
||||
|
||||
NymNodeRouter {
|
||||
@@ -192,7 +189,10 @@ impl NymNodeRouter {
|
||||
}),
|
||||
)
|
||||
.nest(routes::LANDING_PAGE, landing_page::routes(config.landing))
|
||||
.nest(routes::API, api::routes(config.api))
|
||||
.nest(
|
||||
routes::API,
|
||||
api::routes(config.api, initial_wg_state.unwrap_or_default()),
|
||||
)
|
||||
.layer(axum::middleware::from_fn(logging::logger))
|
||||
.with_state(state),
|
||||
}
|
||||
|
||||
@@ -24,6 +24,19 @@ impl RequestError {
|
||||
status,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new_status(status: StatusCode) -> Self {
|
||||
RequestError {
|
||||
inner: ErrorResponse {
|
||||
message: String::new(),
|
||||
},
|
||||
status,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_err<E: std::error::Error>(err: E, status: StatusCode) -> Self {
|
||||
Self::new(err.to_string(), status)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for RequestError {
|
||||
|
||||
@@ -8,8 +8,8 @@ use crate::routes;
|
||||
use async_trait::async_trait;
|
||||
use nym_bin_common::build_information::BinaryBuildInformationOwned;
|
||||
use nym_http_api_client::{ApiClient, HttpClientError};
|
||||
use nym_wireguard_types::{ClientMessage, ClientRegistrationResponse};
|
||||
|
||||
use crate::api::v1::authenticator::models::Authenticator;
|
||||
use crate::api::v1::health::models::NodeHealth;
|
||||
use crate::api::v1::ip_packet_router::models::IpPacketRouter;
|
||||
use crate::api::v1::network_requester::exit_policy::models::UsedExitPolicy;
|
||||
@@ -65,9 +65,15 @@ pub trait NymNodeApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_authenticator(&self) -> Result<Authenticator, NymNodeApiClientError> {
|
||||
self.get_json_from(routes::api::v1::authenticator_absolute())
|
||||
.await
|
||||
async fn post_gateway_register_client(
|
||||
&self,
|
||||
client_message: &ClientMessage,
|
||||
) -> Result<ClientRegistrationResponse, NymNodeApiClientError> {
|
||||
self.post_json_data_to(
|
||||
routes::api::v1::gateway::client_interfaces::wireguard::client_absolute(),
|
||||
client_message,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod models;
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub struct Authenticator {
|
||||
/// Base58 encoded ed25519 EdDSA public key of the authenticator.
|
||||
pub encoded_identity_key: String,
|
||||
|
||||
/// Base58-encoded x25519 public key used for performing key exchange with remote clients.
|
||||
pub encoded_x25519_key: String,
|
||||
|
||||
/// Nym address of this ip packet router.
|
||||
pub address: String,
|
||||
}
|
||||
@@ -2,5 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub use nym_wireguard_types::{
|
||||
ClientMac, ClientMessage, GatewayClient, InitMessage, Nonce, PeerPublicKey,
|
||||
ClientMac, ClientMessage, ClientRegistrationResponse, GatewayClient, InitMessage, Nonce,
|
||||
PeerPublicKey,
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod authenticator;
|
||||
pub mod gateway;
|
||||
pub mod health;
|
||||
pub mod ip_packet_router;
|
||||
|
||||
@@ -42,7 +42,6 @@ pub mod routes {
|
||||
pub const METRICS: &str = "/metrics";
|
||||
pub const NETWORK_REQUESTER: &str = "/network-requester";
|
||||
pub const IP_PACKET_ROUTER: &str = "/ip-packet-router";
|
||||
pub const AUTHENTICATOR: &str = "/authenticator";
|
||||
|
||||
// define helper functions to get absolute routes
|
||||
absolute_route!(health_absolute, v1_absolute(), HEALTH);
|
||||
@@ -58,7 +57,6 @@ pub mod routes {
|
||||
absolute_route!(metrics_absolute, v1_absolute(), METRICS);
|
||||
absolute_route!(network_requester_absolute, v1_absolute(), NETWORK_REQUESTER);
|
||||
absolute_route!(ip_packet_router_absolute, v1_absolute(), IP_PACKET_ROUTER);
|
||||
absolute_route!(authenticator_absolute, v1_absolute(), AUTHENTICATOR);
|
||||
absolute_route!(swagger_absolute, v1_absolute(), SWAGGER);
|
||||
|
||||
pub mod metrics {
|
||||
|
||||
@@ -409,9 +409,6 @@ async fn migrate_gateway(mut args: Args) -> Result<(), NymNodeError> {
|
||||
bind_address: SocketAddr::new(ip, cfg.gateway.clients_port),
|
||||
announce_ws_port: None,
|
||||
announce_wss_port: cfg.gateway.clients_wss_port,
|
||||
authenticator: config::authenticator::Authenticator {
|
||||
debug: Default::default(),
|
||||
},
|
||||
debug: config::entry_gateway::Debug {
|
||||
message_retrieval_limit: cfg.debug.message_retrieval_limit,
|
||||
},
|
||||
@@ -457,9 +454,6 @@ async fn migrate_gateway(mut args: Args) -> Result<(), NymNodeError> {
|
||||
.unwrap_or_default(),
|
||||
},
|
||||
},
|
||||
authenticator: config::authenticator::Authenticator {
|
||||
debug: Default::default(),
|
||||
},
|
||||
}),
|
||||
)
|
||||
.build();
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use nym_client_core_config_types::DebugConfig as ClientDebugConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
pub struct Authenticator {
|
||||
#[serde(default)]
|
||||
pub debug: AuthenticatorDebug,
|
||||
}
|
||||
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for Authenticator {
|
||||
fn default() -> Self {
|
||||
Authenticator {
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct AuthenticatorDebug {
|
||||
/// Specifies whether authenticator service is enabled in this process.
|
||||
/// This is only here for debugging purposes as exit gateway should always run
|
||||
/// the authenticator.
|
||||
pub enabled: bool,
|
||||
|
||||
/// Disable Poisson sending rate.
|
||||
/// This is equivalent to setting client_debug.traffic.disable_main_poisson_packet_distribution = true
|
||||
/// (or is it (?))
|
||||
pub disable_poisson_rate: bool,
|
||||
|
||||
/// Shared detailed client configuration options
|
||||
#[serde(flatten)]
|
||||
pub client_debug: ClientDebugConfig,
|
||||
}
|
||||
|
||||
impl Default for AuthenticatorDebug {
|
||||
fn default() -> Self {
|
||||
AuthenticatorDebug {
|
||||
enabled: true,
|
||||
disable_poisson_rate: true,
|
||||
client_debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,6 @@ use serde::{Deserialize, Serialize};
|
||||
use std::net::SocketAddr;
|
||||
use std::path::Path;
|
||||
|
||||
use super::authenticator::Authenticator;
|
||||
|
||||
pub const DEFAULT_WS_PORT: u16 = DEFAULT_CLIENT_LISTENING_PORT;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -40,8 +38,6 @@ pub struct EntryGatewayConfig {
|
||||
#[serde(deserialize_with = "de_maybe_port")]
|
||||
pub announce_wss_port: Option<u16>,
|
||||
|
||||
pub authenticator: Authenticator,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: Debug,
|
||||
}
|
||||
@@ -73,7 +69,6 @@ impl EntryGatewayConfig {
|
||||
bind_address: SocketAddr::new(inaddr_any(), DEFAULT_WS_PORT),
|
||||
announce_ws_port: None,
|
||||
announce_wss_port: None,
|
||||
authenticator: Default::default(),
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,12 @@ use crate::error::ExitGatewayError;
|
||||
use clap::crate_version;
|
||||
use nym_client_core_config_types::DebugConfig as ClientDebugConfig;
|
||||
use nym_config::defaults::mainnet;
|
||||
use nym_gateway::node::{
|
||||
LocalAuthenticatorOpts, LocalIpPacketRouterOpts, LocalNetworkRequesterOpts,
|
||||
};
|
||||
use nym_gateway::node::{LocalIpPacketRouterOpts, LocalNetworkRequesterOpts};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::Path;
|
||||
use url::Url;
|
||||
|
||||
use super::{authenticator::Authenticator, LocalWireguardOpts};
|
||||
use super::LocalWireguardOpts;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
@@ -32,8 +30,6 @@ pub struct ExitGatewayConfig {
|
||||
pub network_requester: NetworkRequester,
|
||||
|
||||
pub ip_packet_router: IpPacketRouter,
|
||||
|
||||
pub authenticator: Authenticator,
|
||||
}
|
||||
|
||||
impl ExitGatewayConfig {
|
||||
@@ -49,7 +45,6 @@ impl ExitGatewayConfig {
|
||||
.expect("invalid default exit policy URL"),
|
||||
network_requester: Default::default(),
|
||||
ip_packet_router: Default::default(),
|
||||
authenticator: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,7 +138,6 @@ pub struct EphemeralConfig {
|
||||
pub gateway: nym_gateway::config::Config,
|
||||
pub nr_opts: LocalNetworkRequesterOpts,
|
||||
pub ipr_opts: LocalIpPacketRouterOpts,
|
||||
pub auth_opts: LocalAuthenticatorOpts,
|
||||
pub wg_opts: LocalWireguardOpts,
|
||||
}
|
||||
|
||||
@@ -240,26 +234,6 @@ pub fn ephemeral_exit_gateway_config(
|
||||
ipr_opts.config.base.set_no_poisson_process()
|
||||
}
|
||||
|
||||
let auth_opts = LocalAuthenticatorOpts {
|
||||
config: nym_authenticator::Config {
|
||||
base: nym_client_core_config_types::Config {
|
||||
client: base_client_config(&config),
|
||||
debug: config.exit_gateway.authenticator.debug.client_debug,
|
||||
},
|
||||
authenticator: config.wireguard.clone().into(),
|
||||
storage_paths: nym_authenticator::config::AuthenticatorPaths {
|
||||
common_paths: config
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.authenticator
|
||||
.to_common_client_paths(),
|
||||
authenticator_description: Default::default(),
|
||||
},
|
||||
logging: config.logging,
|
||||
},
|
||||
custom_mixnet_path: None,
|
||||
};
|
||||
|
||||
let pub_id_path = config
|
||||
.storage_paths
|
||||
.keys
|
||||
@@ -292,7 +266,6 @@ pub fn ephemeral_exit_gateway_config(
|
||||
Ok(EphemeralConfig {
|
||||
nr_opts,
|
||||
ipr_opts,
|
||||
auth_opts,
|
||||
wg_opts,
|
||||
gateway,
|
||||
})
|
||||
|
||||
@@ -25,12 +25,10 @@ use std::time::Duration;
|
||||
use tracing::{debug, error};
|
||||
use url::Url;
|
||||
|
||||
pub mod authenticator;
|
||||
pub mod entry_gateway;
|
||||
pub mod exit_gateway;
|
||||
pub mod helpers;
|
||||
pub mod mixnode;
|
||||
mod old_configs;
|
||||
pub mod persistence;
|
||||
mod template;
|
||||
pub mod upgrade_helpers;
|
||||
@@ -545,17 +543,6 @@ impl From<Wireguard> for nym_wireguard_types::Config {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Wireguard> for nym_authenticator::config::Authenticator {
|
||||
fn from(value: Wireguard) -> Self {
|
||||
nym_authenticator::config::Authenticator {
|
||||
bind_address: value.bind_address,
|
||||
private_ip: value.private_ip,
|
||||
announced_port: value.announced_port,
|
||||
private_network_prefix: value.private_network_prefix,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LocalWireguardOpts {
|
||||
pub config: Wireguard,
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
mod old_config_1_1_2;
|
||||
mod old_config_1_1_3;
|
||||
|
||||
pub use old_config_1_1_2::try_upgrade_config_1_1_2;
|
||||
pub use old_config_1_1_3::try_upgrade_config_1_1_3;
|
||||
@@ -1,978 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
#![allow(dead_code)]
|
||||
use crate::config::*;
|
||||
use crate::error::KeyIOFailure;
|
||||
use nym_client_core_config_types::DebugConfig as ClientDebugConfig;
|
||||
use nym_config::serde_helpers::de_maybe_port;
|
||||
use nym_crypto::asymmetric::encryption::KeyPair;
|
||||
use nym_pemstore::store_keypair;
|
||||
use old_configs::old_config_1_1_3::*;
|
||||
use rand::rngs::OsRng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WireguardPaths1_1_2 {
|
||||
pub private_diffie_hellman_key_file: PathBuf,
|
||||
pub public_diffie_hellman_key_file: PathBuf,
|
||||
}
|
||||
|
||||
impl WireguardPaths1_1_2 {
|
||||
pub fn new<P: AsRef<Path>>(data_dir: P) -> Self {
|
||||
let data_dir = data_dir.as_ref();
|
||||
WireguardPaths1_1_2 {
|
||||
private_diffie_hellman_key_file: data_dir
|
||||
.join(persistence::DEFAULT_X25519_WG_DH_KEY_FILENAME),
|
||||
public_diffie_hellman_key_file: data_dir
|
||||
.join(persistence::DEFAULT_X25519_WG_PUBLIC_DH_KEY_FILENAME),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn x25519_wireguard_storage_paths(&self) -> nym_pemstore::KeyPairPath {
|
||||
nym_pemstore::KeyPairPath::new(
|
||||
&self.private_diffie_hellman_key_file,
|
||||
&self.public_diffie_hellman_key_file,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Wireguard1_1_2 {
|
||||
/// Specifies whether the wireguard service is enabled on this node.
|
||||
pub enabled: bool,
|
||||
|
||||
/// Socket address this node will use for binding its wireguard interface.
|
||||
/// default: `0.0.0.0:51822`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Ip address of the private wireguard network.
|
||||
/// default: `10.1.0.0`
|
||||
pub private_network_ip: IpAddr,
|
||||
|
||||
/// Port announced to external clients wishing to connect to the wireguard interface.
|
||||
/// Useful in the instances where the node is behind a proxy.
|
||||
pub announced_port: u16,
|
||||
|
||||
/// 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
|
||||
pub private_network_prefix: u8,
|
||||
|
||||
/// Paths for wireguard keys, client registries, etc.
|
||||
pub storage_paths: WireguardPaths1_1_2,
|
||||
}
|
||||
|
||||
// a temporary solution until all "types" are run at the same time
|
||||
#[derive(Debug, Default, Serialize, Deserialize, ValueEnum, Clone, Copy)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum NodeMode1_1_2 {
|
||||
#[default]
|
||||
#[clap(alias = "mix")]
|
||||
Mixnode,
|
||||
|
||||
#[clap(alias = "entry", alias = "gateway")]
|
||||
EntryGateway,
|
||||
|
||||
#[clap(alias = "exit")]
|
||||
ExitGateway,
|
||||
}
|
||||
|
||||
impl From<NodeMode1_1_2> for NodeMode1_1_3 {
|
||||
fn from(config: NodeMode1_1_2) -> Self {
|
||||
match config {
|
||||
NodeMode1_1_2::Mixnode => NodeMode1_1_3::Mixnode,
|
||||
NodeMode1_1_2::EntryGateway => NodeMode1_1_3::EntryGateway,
|
||||
NodeMode1_1_2::ExitGateway => NodeMode1_1_3::ExitGateway,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this is very much a WIP. we need proper ssl certificate support here
|
||||
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Host1_1_2 {
|
||||
/// Ip address(es) of this host, such as 1.1.1.1 that external clients will use for connections.
|
||||
/// If no values are provided, when this node gets included in the network,
|
||||
/// its ip addresses will be populated by whatever value is resolved by associated nym-api.
|
||||
pub public_ips: Vec<IpAddr>,
|
||||
|
||||
/// Optional hostname of this node, for example nymtech.net.
|
||||
// TODO: this is temporary. to be replaced by pulling the data directly from the certs.
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
pub hostname: Option<String>,
|
||||
|
||||
/// Optional ISO 3166 alpha-2 two-letter country code of the node's **physical** location
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
pub location: Option<Country>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct MixnetDebug1_1_2 {
|
||||
/// Initial value of an exponential backoff to reconnect to dropped TCP connection when
|
||||
/// forwarding sphinx packets.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub packet_forwarding_initial_backoff: Duration,
|
||||
|
||||
/// Maximum value of an exponential backoff to reconnect to dropped TCP connection when
|
||||
/// forwarding sphinx packets.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub packet_forwarding_maximum_backoff: Duration,
|
||||
|
||||
/// Timeout for establishing initial connection when trying to forward a sphinx packet.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub initial_connection_timeout: Duration,
|
||||
|
||||
/// Maximum number of packets that can be stored waiting to get sent to a particular connection.
|
||||
pub maximum_connection_buffer_size: usize,
|
||||
|
||||
/// Specifies whether this node should **NOT** use noise protocol in the connections (currently not implemented)
|
||||
pub unsafe_disable_noise: bool,
|
||||
}
|
||||
|
||||
impl MixnetDebug1_1_2 {
|
||||
const DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF: Duration = Duration::from_millis(10_000);
|
||||
const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: Duration = Duration::from_millis(300_000);
|
||||
const DEFAULT_INITIAL_CONNECTION_TIMEOUT: Duration = Duration::from_millis(1_500);
|
||||
const DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE: usize = 2000;
|
||||
}
|
||||
|
||||
impl Default for MixnetDebug1_1_2 {
|
||||
fn default() -> Self {
|
||||
MixnetDebug1_1_2 {
|
||||
packet_forwarding_initial_backoff: Self::DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF,
|
||||
packet_forwarding_maximum_backoff: Self::DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF,
|
||||
initial_connection_timeout: Self::DEFAULT_INITIAL_CONNECTION_TIMEOUT,
|
||||
maximum_connection_buffer_size: Self::DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE,
|
||||
// to be changed by @SW once the implementation is there
|
||||
unsafe_disable_noise: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Mixnet1_1_2 {
|
||||
fn default() -> Self {
|
||||
// SAFETY:
|
||||
// our hardcoded values should always be valid
|
||||
#[allow(clippy::expect_used)]
|
||||
// is if there's anything set in the environment, otherwise fallback to mainnet
|
||||
let nym_api_urls = if let Ok(env_value) = env::var(var_names::NYM_API) {
|
||||
parse_urls(&env_value)
|
||||
} else {
|
||||
vec![mainnet::NYM_API.parse().expect("Invalid default API URL")]
|
||||
};
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
let nyxd_urls = if let Ok(env_value) = env::var(var_names::NYXD) {
|
||||
parse_urls(&env_value)
|
||||
} else {
|
||||
vec![mainnet::NYXD_URL.parse().expect("Invalid default nyxd URL")]
|
||||
};
|
||||
|
||||
Mixnet1_1_2 {
|
||||
bind_address: SocketAddr::new(inaddr_any(), DEFAULT_MIXNET_PORT),
|
||||
nym_api_urls,
|
||||
nyxd_urls,
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Mixnet1_1_2 {
|
||||
/// Address this node will bind to for listening for mixnet packets
|
||||
/// default: `0.0.0.0:1789`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Addresses to nym APIs from which the node gets the view of the network.
|
||||
pub nym_api_urls: Vec<Url>,
|
||||
|
||||
/// Addresses to nyxd which the node uses to interact with the nyx chain.
|
||||
pub nyxd_urls: Vec<Url>,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: MixnetDebug1_1_2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct KeysPaths1_1_2 {
|
||||
/// Path to file containing ed25519 identity private key.
|
||||
pub private_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing ed25519 identity public key.
|
||||
pub public_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing x25519 sphinx private key.
|
||||
pub private_x25519_sphinx_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing x25519 sphinx public key.
|
||||
pub public_x25519_sphinx_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing x25519 noise private key.
|
||||
pub private_x25519_noise_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing x25519 noise public key.
|
||||
pub public_x25519_noise_key_file: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NymNodePaths1_1_2 {
|
||||
pub keys: KeysPaths1_1_2,
|
||||
|
||||
/// Path to a file containing basic node description: human-readable name, website, details, etc.
|
||||
pub description: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Http1_1_2 {
|
||||
/// Socket address this node will use for binding its http API.
|
||||
/// default: `0.0.0.0:8080`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Path to assets directory of custom landing page of this node.
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
pub landing_page_assets_path: Option<PathBuf>,
|
||||
|
||||
/// An optional bearer token for accessing certain http endpoints.
|
||||
/// Currently only used for obtaining mixnode's stats.
|
||||
#[serde(default)]
|
||||
pub access_token: Option<String>,
|
||||
|
||||
/// Specify whether basic system information should be exposed.
|
||||
/// default: true
|
||||
pub expose_system_info: bool,
|
||||
|
||||
/// Specify whether basic system hardware information should be exposed.
|
||||
/// This option is superseded by `expose_system_info`
|
||||
/// default: true
|
||||
pub expose_system_hardware: bool,
|
||||
|
||||
/// Specify whether detailed system crypto hardware information should be exposed.
|
||||
/// This option is superseded by `expose_system_hardware`
|
||||
/// default: true
|
||||
pub expose_crypto_hardware: bool,
|
||||
}
|
||||
|
||||
impl Default for Http1_1_2 {
|
||||
fn default() -> Self {
|
||||
Http1_1_2 {
|
||||
bind_address: SocketAddr::new(inaddr_any(), DEFAULT_HTTP_PORT),
|
||||
landing_page_assets_path: None,
|
||||
access_token: None,
|
||||
expose_system_info: true,
|
||||
expose_system_hardware: true,
|
||||
expose_crypto_hardware: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct MixnodePaths1_1_2 {}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Debug1_1_2 {
|
||||
/// Delay between each subsequent node statistics being logged to the console
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub node_stats_logging_delay: Duration,
|
||||
|
||||
/// Delay between each subsequent node statistics being updated
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub node_stats_updating_delay: Duration,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct VerlocDebug1_1_2 {
|
||||
/// Specifies number of echo packets sent to each node during a measurement run.
|
||||
pub packets_per_node: usize,
|
||||
|
||||
/// Specifies maximum amount of time to wait for the connection to get established.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub connection_timeout: Duration,
|
||||
|
||||
/// Specifies maximum amount of time to wait for the reply packet to arrive before abandoning the test.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub packet_timeout: Duration,
|
||||
|
||||
/// Specifies delay between subsequent test packets being sent (after receiving a reply).
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub delay_between_packets: Duration,
|
||||
|
||||
/// Specifies number of nodes being tested at once.
|
||||
pub tested_nodes_batch_size: usize,
|
||||
|
||||
/// Specifies delay between subsequent test runs.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub testing_interval: Duration,
|
||||
|
||||
/// Specifies delay between attempting to run the measurement again if the previous run failed
|
||||
/// due to being unable to get the list of nodes.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub retry_timeout: Duration,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Verloc1_1_2 {
|
||||
/// Socket address this node will use for binding its verloc API.
|
||||
/// default: `0.0.0.0:1790`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: VerlocDebug1_1_2,
|
||||
}
|
||||
|
||||
impl VerlocDebug1_1_2 {
|
||||
const DEFAULT_PACKETS_PER_NODE: usize = 100;
|
||||
const DEFAULT_CONNECTION_TIMEOUT: Duration = Duration::from_millis(5000);
|
||||
const DEFAULT_PACKET_TIMEOUT: Duration = Duration::from_millis(1500);
|
||||
const DEFAULT_DELAY_BETWEEN_PACKETS: Duration = Duration::from_millis(50);
|
||||
const DEFAULT_BATCH_SIZE: usize = 50;
|
||||
const DEFAULT_TESTING_INTERVAL: Duration = Duration::from_secs(60 * 60 * 12);
|
||||
const DEFAULT_RETRY_TIMEOUT: Duration = Duration::from_secs(60 * 30);
|
||||
}
|
||||
|
||||
impl Default for VerlocDebug1_1_2 {
|
||||
fn default() -> Self {
|
||||
VerlocDebug1_1_2 {
|
||||
packets_per_node: Self::DEFAULT_PACKETS_PER_NODE,
|
||||
connection_timeout: Self::DEFAULT_CONNECTION_TIMEOUT,
|
||||
packet_timeout: Self::DEFAULT_PACKET_TIMEOUT,
|
||||
delay_between_packets: Self::DEFAULT_DELAY_BETWEEN_PACKETS,
|
||||
tested_nodes_batch_size: Self::DEFAULT_BATCH_SIZE,
|
||||
testing_interval: Self::DEFAULT_TESTING_INTERVAL,
|
||||
retry_timeout: Self::DEFAULT_RETRY_TIMEOUT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct MixnodeConfig1_1_2 {
|
||||
pub storage_paths: MixnodePaths1_1_2,
|
||||
|
||||
pub verloc: Verloc1_1_2,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: Debug1_1_2,
|
||||
}
|
||||
|
||||
impl Debug1_1_2 {
|
||||
const DEFAULT_NODE_STATS_LOGGING_DELAY: Duration = Duration::from_millis(60_000);
|
||||
const DEFAULT_NODE_STATS_UPDATING_DELAY: Duration = Duration::from_millis(30_000);
|
||||
}
|
||||
|
||||
impl Default for Debug1_1_2 {
|
||||
fn default() -> Self {
|
||||
Debug1_1_2 {
|
||||
node_stats_logging_delay: Self::DEFAULT_NODE_STATS_LOGGING_DELAY,
|
||||
node_stats_updating_delay: Self::DEFAULT_NODE_STATS_UPDATING_DELAY,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct EntryGatewayPaths1_1_2 {
|
||||
/// Path to sqlite database containing all persistent data: messages for offline clients,
|
||||
/// derived shared keys and available client bandwidths.
|
||||
pub clients_storage: PathBuf,
|
||||
|
||||
/// Path to file containing cosmos account mnemonic used for zk-nym redemption.
|
||||
pub cosmos_mnemonic: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct EntryGatewayConfigDebug1_1_2 {
|
||||
/// Number of messages from offline client that can be pulled at once (i.e. with a single SQL query) from the storage.
|
||||
pub message_retrieval_limit: i64,
|
||||
}
|
||||
|
||||
impl EntryGatewayConfigDebug1_1_2 {
|
||||
const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100;
|
||||
}
|
||||
|
||||
impl Default for EntryGatewayConfigDebug1_1_2 {
|
||||
fn default() -> Self {
|
||||
EntryGatewayConfigDebug1_1_2 {
|
||||
message_retrieval_limit: Self::DEFAULT_MESSAGE_RETRIEVAL_LIMIT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct EntryGatewayConfig1_1_2 {
|
||||
pub storage_paths: EntryGatewayPaths1_1_2,
|
||||
|
||||
/// Indicates whether this gateway is accepting only coconut credentials for accessing the mixnet
|
||||
/// or if it also accepts non-paying clients
|
||||
pub enforce_zk_nyms: bool,
|
||||
|
||||
/// Socket address this node will use for binding its client websocket API.
|
||||
/// default: `0.0.0.0:9000`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Custom announced port for listening for websocket client traffic.
|
||||
/// If unspecified, the value from the `bind_address` will be used instead
|
||||
/// default: None
|
||||
#[serde(deserialize_with = "de_maybe_port")]
|
||||
pub announce_ws_port: Option<u16>,
|
||||
|
||||
/// If applicable, announced port for listening for secure websocket client traffic.
|
||||
/// (default: None)
|
||||
#[serde(deserialize_with = "de_maybe_port")]
|
||||
pub announce_wss_port: Option<u16>,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: EntryGatewayConfigDebug1_1_2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NetworkRequesterPaths1_1_2 {
|
||||
/// Path to file containing network requester ed25519 identity private key.
|
||||
pub private_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing network requester ed25519 identity public key.
|
||||
pub public_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing network requester x25519 diffie hellman private key.
|
||||
pub private_x25519_diffie_hellman_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing network requester x25519 diffie hellman public key.
|
||||
pub public_x25519_diffie_hellman_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing key used for encrypting and decrypting the content of an
|
||||
/// acknowledgement so that nobody besides the client knows which packet it refers to.
|
||||
pub ack_key_file: PathBuf,
|
||||
|
||||
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
|
||||
pub reply_surb_database: PathBuf,
|
||||
|
||||
/// Normally this is a path to the file containing information about gateways used by this client,
|
||||
/// i.e. details such as their public keys, owner addresses or the network information.
|
||||
/// but in this case it just has the basic information of "we're using custom gateway".
|
||||
/// Due to how clients are started up, this file has to exist.
|
||||
pub gateway_registrations: PathBuf,
|
||||
// it's possible we might have to add credential storage here for return tickets
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct IpPacketRouterPaths1_1_2 {
|
||||
/// Path to file containing ip packet router ed25519 identity private key.
|
||||
pub private_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing ip packet router ed25519 identity public key.
|
||||
pub public_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing ip packet router x25519 diffie hellman private key.
|
||||
pub private_x25519_diffie_hellman_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing ip packet router x25519 diffie hellman public key.
|
||||
pub public_x25519_diffie_hellman_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing key used for encrypting and decrypting the content of an
|
||||
/// acknowledgement so that nobody besides the client knows which packet it refers to.
|
||||
pub ack_key_file: PathBuf,
|
||||
|
||||
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
|
||||
pub reply_surb_database: PathBuf,
|
||||
|
||||
/// Normally this is a path to the file containing information about gateways used by this client,
|
||||
/// i.e. details such as their public keys, owner addresses or the network information.
|
||||
/// but in this case it just has the basic information of "we're using custom gateway".
|
||||
/// Due to how clients are started up, this file has to exist.
|
||||
pub gateway_registrations: PathBuf,
|
||||
// it's possible we might have to add credential storage here for return tickets
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ExitGatewayPaths1_1_2 {
|
||||
pub network_requester: NetworkRequesterPaths1_1_2,
|
||||
|
||||
pub ip_packet_router: IpPacketRouterPaths1_1_2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct IpPacketRouterDebug1_1_2 {
|
||||
/// Specifies whether ip packet routing service is enabled in this process.
|
||||
/// This is only here for debugging purposes as exit gateway should always run **both**
|
||||
/// network requester and an ip packet router.
|
||||
pub enabled: bool,
|
||||
|
||||
/// Disable Poisson sending rate.
|
||||
/// This is equivalent to setting client_debug.traffic.disable_main_poisson_packet_distribution = true
|
||||
/// (or is it (?))
|
||||
pub disable_poisson_rate: bool,
|
||||
|
||||
/// Shared detailed client configuration options
|
||||
#[serde(flatten)]
|
||||
pub client_debug: ClientDebugConfig,
|
||||
}
|
||||
|
||||
impl Default for IpPacketRouterDebug1_1_2 {
|
||||
fn default() -> Self {
|
||||
IpPacketRouterDebug1_1_2 {
|
||||
enabled: true,
|
||||
disable_poisson_rate: true,
|
||||
client_debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
pub struct IpPacketRouter1_1_2 {
|
||||
#[serde(default)]
|
||||
pub debug: IpPacketRouterDebug1_1_2,
|
||||
}
|
||||
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for IpPacketRouter1_1_2 {
|
||||
fn default() -> Self {
|
||||
IpPacketRouter1_1_2 {
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
pub struct NetworkRequesterDebug1_1_2 {
|
||||
/// Specifies whether network requester service is enabled in this process.
|
||||
/// This is only here for debugging purposes as exit gateway should always run **both**
|
||||
/// network requester and an ip packet router.
|
||||
pub enabled: bool,
|
||||
|
||||
/// Disable Poisson sending rate.
|
||||
/// This is equivalent to setting client_debug.traffic.disable_main_poisson_packet_distribution = true
|
||||
/// (or is it (?))
|
||||
pub disable_poisson_rate: bool,
|
||||
|
||||
/// Shared detailed client configuration options
|
||||
#[serde(flatten)]
|
||||
pub client_debug: ClientDebugConfig,
|
||||
}
|
||||
|
||||
impl Default for NetworkRequesterDebug1_1_2 {
|
||||
fn default() -> Self {
|
||||
NetworkRequesterDebug1_1_2 {
|
||||
enabled: true,
|
||||
disable_poisson_rate: true,
|
||||
client_debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
pub struct NetworkRequester1_1_2 {
|
||||
#[serde(default)]
|
||||
pub debug: NetworkRequesterDebug1_1_2,
|
||||
}
|
||||
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for NetworkRequester1_1_2 {
|
||||
fn default() -> Self {
|
||||
NetworkRequester1_1_2 {
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ExitGatewayConfig1_1_2 {
|
||||
pub storage_paths: ExitGatewayPaths1_1_2,
|
||||
|
||||
/// specifies whether this exit node should run in 'open-proxy' mode
|
||||
/// and thus would attempt to resolve **ANY** request it receives.
|
||||
pub open_proxy: bool,
|
||||
|
||||
/// Specifies the url for an upstream source of the exit policy used by this node.
|
||||
pub upstream_exit_policy_url: Url,
|
||||
|
||||
pub network_requester: NetworkRequester1_1_2,
|
||||
|
||||
pub ip_packet_router: IpPacketRouter1_1_2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct LoggingSettings1_1_2 {
|
||||
// well, we need to implement something here at some point...
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Config1_1_2 {
|
||||
// additional metadata holding on-disk location of this config file
|
||||
#[serde(skip)]
|
||||
pub(crate) save_path: Option<PathBuf>,
|
||||
|
||||
/// Human-readable ID of this particular node.
|
||||
pub id: String,
|
||||
|
||||
/// Current mode of this nym-node.
|
||||
/// Expect this field to be changed in the future to allow running the node in multiple modes (i.e. mixnode + gateway)
|
||||
pub mode: NodeMode1_1_2,
|
||||
|
||||
pub host: Host1_1_2,
|
||||
|
||||
pub mixnet: Mixnet1_1_2,
|
||||
|
||||
/// Storage paths to persistent nym-node data, such as its long term keys.
|
||||
pub storage_paths: NymNodePaths1_1_2,
|
||||
|
||||
#[serde(default)]
|
||||
pub http: Http1_1_2,
|
||||
|
||||
pub wireguard: Wireguard1_1_2,
|
||||
|
||||
pub mixnode: MixnodeConfig1_1_2,
|
||||
|
||||
pub entry_gateway: EntryGatewayConfig1_1_2,
|
||||
|
||||
pub exit_gateway: ExitGatewayConfig1_1_2,
|
||||
|
||||
#[serde(default)]
|
||||
pub logging: LoggingSettings1_1_2,
|
||||
}
|
||||
|
||||
impl NymConfigTemplate for Config1_1_2 {
|
||||
fn template(&self) -> &'static str {
|
||||
CONFIG_TEMPLATE
|
||||
}
|
||||
}
|
||||
|
||||
impl Config1_1_2 {
|
||||
pub fn save(&self) -> Result<(), NymNodeError> {
|
||||
let save_location = self.save_location();
|
||||
debug!(
|
||||
"attempting to save config file to '{}'",
|
||||
save_location.display()
|
||||
);
|
||||
save_formatted_config_to_file(self, &save_location).map_err(|source| {
|
||||
NymNodeError::ConfigSaveFailure {
|
||||
id: self.id.clone(),
|
||||
path: save_location,
|
||||
source,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn save_location(&self) -> PathBuf {
|
||||
self.save_path
|
||||
.clone()
|
||||
.unwrap_or(self.default_save_location())
|
||||
}
|
||||
|
||||
pub fn default_save_location(&self) -> PathBuf {
|
||||
default_config_filepath(&self.id)
|
||||
}
|
||||
|
||||
pub fn default_data_directory<P: AsRef<Path>>(config_path: P) -> Result<PathBuf, NymNodeError> {
|
||||
let config_path = config_path.as_ref();
|
||||
|
||||
// we got a proper path to the .toml file
|
||||
let Some(config_dir) = config_path.parent() else {
|
||||
error!(
|
||||
"'{}' does not have a parent directory. Have you pointed to the fs root?",
|
||||
config_path.display()
|
||||
);
|
||||
return Err(NymNodeError::DataDirDerivationFailure);
|
||||
};
|
||||
|
||||
let Some(config_dir_name) = config_dir.file_name() else {
|
||||
error!(
|
||||
"could not obtain parent directory name of '{}'. Have you used relative paths?",
|
||||
config_path.display()
|
||||
);
|
||||
return Err(NymNodeError::DataDirDerivationFailure);
|
||||
};
|
||||
|
||||
if config_dir_name != DEFAULT_CONFIG_DIR {
|
||||
error!(
|
||||
"the parent directory of '{}' ({}) is not {DEFAULT_CONFIG_DIR}. currently this is not supported",
|
||||
config_path.display(), config_dir_name.to_str().unwrap_or("UNKNOWN")
|
||||
);
|
||||
return Err(NymNodeError::DataDirDerivationFailure);
|
||||
}
|
||||
|
||||
let Some(node_dir) = config_dir.parent() else {
|
||||
error!(
|
||||
"'{}' does not have a parent directory. Have you pointed to the fs root?",
|
||||
config_dir.display()
|
||||
);
|
||||
return Err(NymNodeError::DataDirDerivationFailure);
|
||||
};
|
||||
|
||||
Ok(node_dir.join(DEFAULT_DATA_DIR))
|
||||
}
|
||||
|
||||
// simple wrapper that reads config file and assigns path location
|
||||
fn read_from_path<P: AsRef<Path>>(path: P) -> Result<Self, NymNodeError> {
|
||||
let path = path.as_ref();
|
||||
let mut loaded: Config1_1_2 =
|
||||
read_config_from_toml_file(path).map_err(|source| NymNodeError::ConfigLoadFailure {
|
||||
path: path.to_path_buf(),
|
||||
source,
|
||||
})?;
|
||||
loaded.save_path = Some(path.to_path_buf());
|
||||
debug!("loaded config file from {}", path.display());
|
||||
Ok(loaded)
|
||||
}
|
||||
|
||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> Result<Self, NymNodeError> {
|
||||
Self::read_from_path(path)
|
||||
}
|
||||
}
|
||||
|
||||
fn initialise(config: &Wireguard1_1_3) -> std::io::Result<()> {
|
||||
let mut rng = OsRng;
|
||||
let x25519_keys = KeyPair::new(&mut rng);
|
||||
|
||||
store_keypair(
|
||||
&x25519_keys,
|
||||
&config.storage_paths.x25519_wireguard_storage_paths(),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// currently there are no upgrades
|
||||
pub async fn try_upgrade_config_1_1_2<P: AsRef<Path>>(path: P) -> Result<(), NymNodeError> {
|
||||
let old_cfg = Config1_1_2::read_from_path(&path)?;
|
||||
let wireguard = Wireguard1_1_3 {
|
||||
enabled: old_cfg.wireguard.enabled,
|
||||
bind_address: old_cfg.wireguard.bind_address,
|
||||
private_ip: old_cfg.wireguard.private_network_ip,
|
||||
announced_port: old_cfg.wireguard.announced_port,
|
||||
private_network_prefix: old_cfg.wireguard.private_network_prefix,
|
||||
storage_paths: WireguardPaths1_1_3::new(Config1_1_3::default_data_directory(path)?),
|
||||
};
|
||||
initialise(&wireguard).map_err(|err| KeyIOFailure::KeyPairStoreFailure {
|
||||
keys: "wg-x25519-dh".to_string(),
|
||||
paths: wireguard.storage_paths.x25519_wireguard_storage_paths(),
|
||||
err,
|
||||
})?;
|
||||
let cfg = Config1_1_3 {
|
||||
save_path: old_cfg.save_path,
|
||||
id: old_cfg.id,
|
||||
mode: old_cfg.mode.into(),
|
||||
host: Host1_1_3 {
|
||||
public_ips: old_cfg.host.public_ips,
|
||||
hostname: old_cfg.host.hostname,
|
||||
location: old_cfg.host.location,
|
||||
},
|
||||
mixnet: Mixnet1_1_3 {
|
||||
bind_address: old_cfg.mixnet.bind_address,
|
||||
nym_api_urls: old_cfg.mixnet.nym_api_urls,
|
||||
nyxd_urls: old_cfg.mixnet.nyxd_urls,
|
||||
debug: MixnetDebug1_1_3 {
|
||||
packet_forwarding_initial_backoff: old_cfg
|
||||
.mixnet
|
||||
.debug
|
||||
.packet_forwarding_initial_backoff,
|
||||
packet_forwarding_maximum_backoff: old_cfg
|
||||
.mixnet
|
||||
.debug
|
||||
.packet_forwarding_maximum_backoff,
|
||||
initial_connection_timeout: old_cfg.mixnet.debug.initial_connection_timeout,
|
||||
maximum_connection_buffer_size: old_cfg.mixnet.debug.maximum_connection_buffer_size,
|
||||
unsafe_disable_noise: old_cfg.mixnet.debug.unsafe_disable_noise,
|
||||
},
|
||||
},
|
||||
storage_paths: NymNodePaths1_1_3 {
|
||||
keys: KeysPaths1_1_3 {
|
||||
private_ed25519_identity_key_file: old_cfg
|
||||
.storage_paths
|
||||
.keys
|
||||
.private_ed25519_identity_key_file,
|
||||
public_ed25519_identity_key_file: old_cfg
|
||||
.storage_paths
|
||||
.keys
|
||||
.public_ed25519_identity_key_file,
|
||||
private_x25519_sphinx_key_file: old_cfg
|
||||
.storage_paths
|
||||
.keys
|
||||
.private_x25519_sphinx_key_file,
|
||||
public_x25519_sphinx_key_file: old_cfg
|
||||
.storage_paths
|
||||
.keys
|
||||
.public_x25519_sphinx_key_file,
|
||||
private_x25519_noise_key_file: old_cfg
|
||||
.storage_paths
|
||||
.keys
|
||||
.private_x25519_noise_key_file,
|
||||
public_x25519_noise_key_file: old_cfg
|
||||
.storage_paths
|
||||
.keys
|
||||
.public_x25519_noise_key_file,
|
||||
},
|
||||
description: old_cfg.storage_paths.description,
|
||||
},
|
||||
http: Http1_1_3 {
|
||||
bind_address: old_cfg.http.bind_address,
|
||||
landing_page_assets_path: old_cfg.http.landing_page_assets_path,
|
||||
access_token: old_cfg.http.access_token,
|
||||
expose_system_info: old_cfg.http.expose_system_info,
|
||||
expose_system_hardware: old_cfg.http.expose_system_hardware,
|
||||
expose_crypto_hardware: old_cfg.http.expose_crypto_hardware,
|
||||
},
|
||||
wireguard,
|
||||
mixnode: MixnodeConfig1_1_3 {
|
||||
storage_paths: MixnodePaths1_1_3 {},
|
||||
verloc: Verloc1_1_3 {
|
||||
bind_address: old_cfg.mixnode.verloc.bind_address,
|
||||
debug: VerlocDebug1_1_3 {
|
||||
packets_per_node: old_cfg.mixnode.verloc.debug.packets_per_node,
|
||||
connection_timeout: old_cfg.mixnode.verloc.debug.connection_timeout,
|
||||
packet_timeout: old_cfg.mixnode.verloc.debug.packet_timeout,
|
||||
delay_between_packets: old_cfg.mixnode.verloc.debug.delay_between_packets,
|
||||
tested_nodes_batch_size: old_cfg.mixnode.verloc.debug.tested_nodes_batch_size,
|
||||
testing_interval: old_cfg.mixnode.verloc.debug.testing_interval,
|
||||
retry_timeout: old_cfg.mixnode.verloc.debug.retry_timeout,
|
||||
},
|
||||
},
|
||||
debug: Debug1_1_3 {
|
||||
node_stats_logging_delay: old_cfg.mixnode.debug.node_stats_logging_delay,
|
||||
node_stats_updating_delay: old_cfg.mixnode.debug.node_stats_updating_delay,
|
||||
},
|
||||
},
|
||||
entry_gateway: EntryGatewayConfig1_1_3 {
|
||||
storage_paths: EntryGatewayPaths1_1_3 {
|
||||
clients_storage: old_cfg.entry_gateway.storage_paths.clients_storage,
|
||||
cosmos_mnemonic: old_cfg.entry_gateway.storage_paths.cosmos_mnemonic,
|
||||
},
|
||||
enforce_zk_nyms: old_cfg.entry_gateway.enforce_zk_nyms,
|
||||
bind_address: old_cfg.entry_gateway.bind_address,
|
||||
announce_ws_port: old_cfg.entry_gateway.announce_ws_port,
|
||||
announce_wss_port: old_cfg.entry_gateway.announce_wss_port,
|
||||
debug: EntryGatewayConfigDebug1_1_3 {
|
||||
message_retrieval_limit: old_cfg.entry_gateway.debug.message_retrieval_limit,
|
||||
},
|
||||
},
|
||||
exit_gateway: ExitGatewayConfig1_1_3 {
|
||||
storage_paths: ExitGatewayPaths1_1_3 {
|
||||
network_requester: NetworkRequesterPaths1_1_3 {
|
||||
private_ed25519_identity_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.network_requester
|
||||
.private_ed25519_identity_key_file,
|
||||
public_ed25519_identity_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.network_requester
|
||||
.public_ed25519_identity_key_file,
|
||||
private_x25519_diffie_hellman_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.network_requester
|
||||
.private_x25519_diffie_hellman_key_file,
|
||||
public_x25519_diffie_hellman_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.network_requester
|
||||
.public_x25519_diffie_hellman_key_file,
|
||||
ack_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.network_requester
|
||||
.ack_key_file,
|
||||
reply_surb_database: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.network_requester
|
||||
.reply_surb_database,
|
||||
gateway_registrations: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.network_requester
|
||||
.gateway_registrations,
|
||||
},
|
||||
ip_packet_router: IpPacketRouterPaths1_1_3 {
|
||||
private_ed25519_identity_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.ip_packet_router
|
||||
.private_ed25519_identity_key_file,
|
||||
public_ed25519_identity_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.ip_packet_router
|
||||
.public_ed25519_identity_key_file,
|
||||
private_x25519_diffie_hellman_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.ip_packet_router
|
||||
.private_x25519_diffie_hellman_key_file,
|
||||
public_x25519_diffie_hellman_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.ip_packet_router
|
||||
.public_x25519_diffie_hellman_key_file,
|
||||
ack_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.ip_packet_router
|
||||
.ack_key_file,
|
||||
reply_surb_database: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.ip_packet_router
|
||||
.reply_surb_database,
|
||||
gateway_registrations: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
.ip_packet_router
|
||||
.gateway_registrations,
|
||||
},
|
||||
},
|
||||
open_proxy: old_cfg.exit_gateway.open_proxy,
|
||||
upstream_exit_policy_url: old_cfg.exit_gateway.upstream_exit_policy_url,
|
||||
network_requester: NetworkRequester1_1_3 {
|
||||
debug: NetworkRequesterDebug1_1_3 {
|
||||
enabled: old_cfg.exit_gateway.network_requester.debug.enabled,
|
||||
disable_poisson_rate: old_cfg
|
||||
.exit_gateway
|
||||
.network_requester
|
||||
.debug
|
||||
.disable_poisson_rate,
|
||||
client_debug: old_cfg.exit_gateway.network_requester.debug.client_debug,
|
||||
},
|
||||
},
|
||||
ip_packet_router: IpPacketRouter1_1_3 {
|
||||
debug: IpPacketRouterDebug1_1_3 {
|
||||
enabled: old_cfg.exit_gateway.ip_packet_router.debug.enabled,
|
||||
disable_poisson_rate: old_cfg
|
||||
.exit_gateway
|
||||
.ip_packet_router
|
||||
.debug
|
||||
.disable_poisson_rate,
|
||||
client_debug: old_cfg.exit_gateway.ip_packet_router.debug.client_debug,
|
||||
},
|
||||
},
|
||||
},
|
||||
logging: LoggingSettings1_1_3 {},
|
||||
};
|
||||
|
||||
cfg.save()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,766 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
#![allow(dead_code)]
|
||||
use crate::config::*;
|
||||
use nym_client_core_config_types::DebugConfig as ClientDebugConfig;
|
||||
use nym_config::serde_helpers::de_maybe_port;
|
||||
use nym_crypto::asymmetric::encryption::KeyPair;
|
||||
use nym_pemstore::store_keypair;
|
||||
use rand::rngs::OsRng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WireguardPaths1_1_3 {
|
||||
pub private_diffie_hellman_key_file: PathBuf,
|
||||
pub public_diffie_hellman_key_file: PathBuf,
|
||||
}
|
||||
|
||||
impl WireguardPaths1_1_3 {
|
||||
pub fn new<P: AsRef<Path>>(data_dir: P) -> Self {
|
||||
let data_dir = data_dir.as_ref();
|
||||
WireguardPaths1_1_3 {
|
||||
private_diffie_hellman_key_file: data_dir
|
||||
.join(persistence::DEFAULT_X25519_WG_DH_KEY_FILENAME),
|
||||
public_diffie_hellman_key_file: data_dir
|
||||
.join(persistence::DEFAULT_X25519_WG_PUBLIC_DH_KEY_FILENAME),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn x25519_wireguard_storage_paths(&self) -> nym_pemstore::KeyPairPath {
|
||||
nym_pemstore::KeyPairPath::new(
|
||||
&self.private_diffie_hellman_key_file,
|
||||
&self.public_diffie_hellman_key_file,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Wireguard1_1_3 {
|
||||
/// Specifies whether the wireguard service is enabled on this node.
|
||||
pub enabled: bool,
|
||||
|
||||
/// Socket address this node will use for binding its wireguard interface.
|
||||
/// default: `0.0.0.0:51822`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Ip address of the private wireguard network.
|
||||
/// default: `10.1.0.0`
|
||||
pub private_ip: IpAddr,
|
||||
|
||||
/// Port announced to external clients wishing to connect to the wireguard interface.
|
||||
/// Useful in the instances where the node is behind a proxy.
|
||||
pub announced_port: u16,
|
||||
|
||||
/// 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
|
||||
pub private_network_prefix: u8,
|
||||
|
||||
/// Paths for wireguard keys, client registries, etc.
|
||||
pub storage_paths: WireguardPaths1_1_3,
|
||||
}
|
||||
|
||||
// a temporary solution until all "types" are run at the same time
|
||||
#[derive(Debug, Default, Serialize, Deserialize, ValueEnum, Clone, Copy)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum NodeMode1_1_3 {
|
||||
#[default]
|
||||
#[clap(alias = "mix")]
|
||||
Mixnode,
|
||||
|
||||
#[clap(alias = "entry", alias = "gateway")]
|
||||
EntryGateway,
|
||||
|
||||
#[clap(alias = "exit")]
|
||||
ExitGateway,
|
||||
}
|
||||
|
||||
// TODO: this is very much a WIP. we need proper ssl certificate support here
|
||||
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Host1_1_3 {
|
||||
/// Ip address(es) of this host, such as 1.1.1.1 that external clients will use for connections.
|
||||
/// If no values are provided, when this node gets included in the network,
|
||||
/// its ip addresses will be populated by whatever value is resolved by associated nym-api.
|
||||
pub public_ips: Vec<IpAddr>,
|
||||
|
||||
/// Optional hostname of this node, for example nymtech.net.
|
||||
// TODO: this is temporary. to be replaced by pulling the data directly from the certs.
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
pub hostname: Option<String>,
|
||||
|
||||
/// Optional ISO 3166 alpha-2 two-letter country code of the node's **physical** location
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
pub location: Option<Country>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct MixnetDebug1_1_3 {
|
||||
/// Initial value of an exponential backoff to reconnect to dropped TCP connection when
|
||||
/// forwarding sphinx packets.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub packet_forwarding_initial_backoff: Duration,
|
||||
|
||||
/// Maximum value of an exponential backoff to reconnect to dropped TCP connection when
|
||||
/// forwarding sphinx packets.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub packet_forwarding_maximum_backoff: Duration,
|
||||
|
||||
/// Timeout for establishing initial connection when trying to forward a sphinx packet.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub initial_connection_timeout: Duration,
|
||||
|
||||
/// Maximum number of packets that can be stored waiting to get sent to a particular connection.
|
||||
pub maximum_connection_buffer_size: usize,
|
||||
|
||||
/// Specifies whether this node should **NOT** use noise protocol in the connections (currently not implemented)
|
||||
pub unsafe_disable_noise: bool,
|
||||
}
|
||||
|
||||
impl MixnetDebug1_1_3 {
|
||||
const DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF: Duration = Duration::from_millis(10_000);
|
||||
const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: Duration = Duration::from_millis(300_000);
|
||||
const DEFAULT_INITIAL_CONNECTION_TIMEOUT: Duration = Duration::from_millis(1_500);
|
||||
const DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE: usize = 2000;
|
||||
}
|
||||
|
||||
impl Default for MixnetDebug1_1_3 {
|
||||
fn default() -> Self {
|
||||
MixnetDebug1_1_3 {
|
||||
packet_forwarding_initial_backoff: Self::DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF,
|
||||
packet_forwarding_maximum_backoff: Self::DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF,
|
||||
initial_connection_timeout: Self::DEFAULT_INITIAL_CONNECTION_TIMEOUT,
|
||||
maximum_connection_buffer_size: Self::DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE,
|
||||
// to be changed by @SW once the implementation is there
|
||||
unsafe_disable_noise: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Mixnet1_1_3 {
|
||||
fn default() -> Self {
|
||||
// SAFETY:
|
||||
// our hardcoded values should always be valid
|
||||
#[allow(clippy::expect_used)]
|
||||
// is if there's anything set in the environment, otherwise fallback to mainnet
|
||||
let nym_api_urls = if let Ok(env_value) = env::var(var_names::NYM_API) {
|
||||
parse_urls(&env_value)
|
||||
} else {
|
||||
vec![mainnet::NYM_API.parse().expect("Invalid default API URL")]
|
||||
};
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
let nyxd_urls = if let Ok(env_value) = env::var(var_names::NYXD) {
|
||||
parse_urls(&env_value)
|
||||
} else {
|
||||
vec![mainnet::NYXD_URL.parse().expect("Invalid default nyxd URL")]
|
||||
};
|
||||
|
||||
Mixnet1_1_3 {
|
||||
bind_address: SocketAddr::new(inaddr_any(), DEFAULT_MIXNET_PORT),
|
||||
nym_api_urls,
|
||||
nyxd_urls,
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Mixnet1_1_3 {
|
||||
/// Address this node will bind to for listening for mixnet packets
|
||||
/// default: `0.0.0.0:1789`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Addresses to nym APIs from which the node gets the view of the network.
|
||||
pub nym_api_urls: Vec<Url>,
|
||||
|
||||
/// Addresses to nyxd which the node uses to interact with the nyx chain.
|
||||
pub nyxd_urls: Vec<Url>,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: MixnetDebug1_1_3,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct KeysPaths1_1_3 {
|
||||
/// Path to file containing ed25519 identity private key.
|
||||
pub private_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing ed25519 identity public key.
|
||||
pub public_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing x25519 sphinx private key.
|
||||
pub private_x25519_sphinx_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing x25519 sphinx public key.
|
||||
pub public_x25519_sphinx_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing x25519 noise private key.
|
||||
pub private_x25519_noise_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing x25519 noise public key.
|
||||
pub public_x25519_noise_key_file: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NymNodePaths1_1_3 {
|
||||
pub keys: KeysPaths1_1_3,
|
||||
|
||||
/// Path to a file containing basic node description: human-readable name, website, details, etc.
|
||||
pub description: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Http1_1_3 {
|
||||
/// Socket address this node will use for binding its http API.
|
||||
/// default: `0.0.0.0:8080`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Path to assets directory of custom landing page of this node.
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
pub landing_page_assets_path: Option<PathBuf>,
|
||||
|
||||
/// An optional bearer token for accessing certain http endpoints.
|
||||
/// Currently only used for obtaining mixnode's stats.
|
||||
#[serde(default)]
|
||||
pub access_token: Option<String>,
|
||||
|
||||
/// Specify whether basic system information should be exposed.
|
||||
/// default: true
|
||||
pub expose_system_info: bool,
|
||||
|
||||
/// Specify whether basic system hardware information should be exposed.
|
||||
/// This option is superseded by `expose_system_info`
|
||||
/// default: true
|
||||
pub expose_system_hardware: bool,
|
||||
|
||||
/// Specify whether detailed system crypto hardware information should be exposed.
|
||||
/// This option is superseded by `expose_system_hardware`
|
||||
/// default: true
|
||||
pub expose_crypto_hardware: bool,
|
||||
}
|
||||
|
||||
impl Default for Http1_1_3 {
|
||||
fn default() -> Self {
|
||||
Http1_1_3 {
|
||||
bind_address: SocketAddr::new(inaddr_any(), DEFAULT_HTTP_PORT),
|
||||
landing_page_assets_path: None,
|
||||
access_token: None,
|
||||
expose_system_info: true,
|
||||
expose_system_hardware: true,
|
||||
expose_crypto_hardware: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct MixnodePaths1_1_3 {}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Debug1_1_3 {
|
||||
/// Delay between each subsequent node statistics being logged to the console
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub node_stats_logging_delay: Duration,
|
||||
|
||||
/// Delay between each subsequent node statistics being updated
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub node_stats_updating_delay: Duration,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct VerlocDebug1_1_3 {
|
||||
/// Specifies number of echo packets sent to each node during a measurement run.
|
||||
pub packets_per_node: usize,
|
||||
|
||||
/// Specifies maximum amount of time to wait for the connection to get established.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub connection_timeout: Duration,
|
||||
|
||||
/// Specifies maximum amount of time to wait for the reply packet to arrive before abandoning the test.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub packet_timeout: Duration,
|
||||
|
||||
/// Specifies delay between subsequent test packets being sent (after receiving a reply).
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub delay_between_packets: Duration,
|
||||
|
||||
/// Specifies number of nodes being tested at once.
|
||||
pub tested_nodes_batch_size: usize,
|
||||
|
||||
/// Specifies delay between subsequent test runs.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub testing_interval: Duration,
|
||||
|
||||
/// Specifies delay between attempting to run the measurement again if the previous run failed
|
||||
/// due to being unable to get the list of nodes.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub retry_timeout: Duration,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Verloc1_1_3 {
|
||||
/// Socket address this node will use for binding its verloc API.
|
||||
/// default: `0.0.0.0:1790`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: VerlocDebug1_1_3,
|
||||
}
|
||||
|
||||
impl VerlocDebug1_1_3 {
|
||||
const DEFAULT_PACKETS_PER_NODE: usize = 100;
|
||||
const DEFAULT_CONNECTION_TIMEOUT: Duration = Duration::from_millis(5000);
|
||||
const DEFAULT_PACKET_TIMEOUT: Duration = Duration::from_millis(1500);
|
||||
const DEFAULT_DELAY_BETWEEN_PACKETS: Duration = Duration::from_millis(50);
|
||||
const DEFAULT_BATCH_SIZE: usize = 50;
|
||||
const DEFAULT_TESTING_INTERVAL: Duration = Duration::from_secs(60 * 60 * 12);
|
||||
const DEFAULT_RETRY_TIMEOUT: Duration = Duration::from_secs(60 * 30);
|
||||
}
|
||||
|
||||
impl Default for VerlocDebug1_1_3 {
|
||||
fn default() -> Self {
|
||||
VerlocDebug1_1_3 {
|
||||
packets_per_node: Self::DEFAULT_PACKETS_PER_NODE,
|
||||
connection_timeout: Self::DEFAULT_CONNECTION_TIMEOUT,
|
||||
packet_timeout: Self::DEFAULT_PACKET_TIMEOUT,
|
||||
delay_between_packets: Self::DEFAULT_DELAY_BETWEEN_PACKETS,
|
||||
tested_nodes_batch_size: Self::DEFAULT_BATCH_SIZE,
|
||||
testing_interval: Self::DEFAULT_TESTING_INTERVAL,
|
||||
retry_timeout: Self::DEFAULT_RETRY_TIMEOUT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct MixnodeConfig1_1_3 {
|
||||
pub storage_paths: MixnodePaths1_1_3,
|
||||
|
||||
pub verloc: Verloc1_1_3,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: Debug1_1_3,
|
||||
}
|
||||
|
||||
impl Debug1_1_3 {
|
||||
const DEFAULT_NODE_STATS_LOGGING_DELAY: Duration = Duration::from_millis(60_000);
|
||||
const DEFAULT_NODE_STATS_UPDATING_DELAY: Duration = Duration::from_millis(30_000);
|
||||
}
|
||||
|
||||
impl Default for Debug1_1_3 {
|
||||
fn default() -> Self {
|
||||
Debug1_1_3 {
|
||||
node_stats_logging_delay: Self::DEFAULT_NODE_STATS_LOGGING_DELAY,
|
||||
node_stats_updating_delay: Self::DEFAULT_NODE_STATS_UPDATING_DELAY,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct EntryGatewayPaths1_1_3 {
|
||||
/// Path to sqlite database containing all persistent data: messages for offline clients,
|
||||
/// derived shared keys and available client bandwidths.
|
||||
pub clients_storage: PathBuf,
|
||||
|
||||
/// Path to file containing cosmos account mnemonic used for zk-nym redemption.
|
||||
pub cosmos_mnemonic: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct EntryGatewayConfigDebug1_1_3 {
|
||||
/// Number of messages from offline client that can be pulled at once (i.e. with a single SQL query) from the storage.
|
||||
pub message_retrieval_limit: i64,
|
||||
}
|
||||
|
||||
impl EntryGatewayConfigDebug1_1_3 {
|
||||
const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100;
|
||||
}
|
||||
|
||||
impl Default for EntryGatewayConfigDebug1_1_3 {
|
||||
fn default() -> Self {
|
||||
EntryGatewayConfigDebug1_1_3 {
|
||||
message_retrieval_limit: Self::DEFAULT_MESSAGE_RETRIEVAL_LIMIT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct EntryGatewayConfig1_1_3 {
|
||||
pub storage_paths: EntryGatewayPaths1_1_3,
|
||||
|
||||
/// Indicates whether this gateway is accepting only coconut credentials for accessing the mixnet
|
||||
/// or if it also accepts non-paying clients
|
||||
pub enforce_zk_nyms: bool,
|
||||
|
||||
/// Socket address this node will use for binding its client websocket API.
|
||||
/// default: `0.0.0.0:9000`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Custom announced port for listening for websocket client traffic.
|
||||
/// If unspecified, the value from the `bind_address` will be used instead
|
||||
/// default: None
|
||||
#[serde(deserialize_with = "de_maybe_port")]
|
||||
pub announce_ws_port: Option<u16>,
|
||||
|
||||
/// If applicable, announced port for listening for secure websocket client traffic.
|
||||
/// (default: None)
|
||||
#[serde(deserialize_with = "de_maybe_port")]
|
||||
pub announce_wss_port: Option<u16>,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: EntryGatewayConfigDebug1_1_3,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NetworkRequesterPaths1_1_3 {
|
||||
/// Path to file containing network requester ed25519 identity private key.
|
||||
pub private_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing network requester ed25519 identity public key.
|
||||
pub public_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing network requester x25519 diffie hellman private key.
|
||||
pub private_x25519_diffie_hellman_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing network requester x25519 diffie hellman public key.
|
||||
pub public_x25519_diffie_hellman_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing key used for encrypting and decrypting the content of an
|
||||
/// acknowledgement so that nobody besides the client knows which packet it refers to.
|
||||
pub ack_key_file: PathBuf,
|
||||
|
||||
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
|
||||
pub reply_surb_database: PathBuf,
|
||||
|
||||
/// Normally this is a path to the file containing information about gateways used by this client,
|
||||
/// i.e. details such as their public keys, owner addresses or the network information.
|
||||
/// but in this case it just has the basic information of "we're using custom gateway".
|
||||
/// Due to how clients are started up, this file has to exist.
|
||||
pub gateway_registrations: PathBuf,
|
||||
// it's possible we might have to add credential storage here for return tickets
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct IpPacketRouterPaths1_1_3 {
|
||||
/// Path to file containing ip packet router ed25519 identity private key.
|
||||
pub private_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing ip packet router ed25519 identity public key.
|
||||
pub public_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing ip packet router x25519 diffie hellman private key.
|
||||
pub private_x25519_diffie_hellman_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing ip packet router x25519 diffie hellman public key.
|
||||
pub public_x25519_diffie_hellman_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing key used for encrypting and decrypting the content of an
|
||||
/// acknowledgement so that nobody besides the client knows which packet it refers to.
|
||||
pub ack_key_file: PathBuf,
|
||||
|
||||
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
|
||||
pub reply_surb_database: PathBuf,
|
||||
|
||||
/// Normally this is a path to the file containing information about gateways used by this client,
|
||||
/// i.e. details such as their public keys, owner addresses or the network information.
|
||||
/// but in this case it just has the basic information of "we're using custom gateway".
|
||||
/// Due to how clients are started up, this file has to exist.
|
||||
pub gateway_registrations: PathBuf,
|
||||
// it's possible we might have to add credential storage here for return tickets
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ExitGatewayPaths1_1_3 {
|
||||
pub network_requester: NetworkRequesterPaths1_1_3,
|
||||
|
||||
pub ip_packet_router: IpPacketRouterPaths1_1_3,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct IpPacketRouterDebug1_1_3 {
|
||||
/// Specifies whether ip packet routing service is enabled in this process.
|
||||
/// This is only here for debugging purposes as exit gateway should always run **both**
|
||||
/// network requester and an ip packet router.
|
||||
pub enabled: bool,
|
||||
|
||||
/// Disable Poisson sending rate.
|
||||
/// This is equivalent to setting client_debug.traffic.disable_main_poisson_packet_distribution = true
|
||||
/// (or is it (?))
|
||||
pub disable_poisson_rate: bool,
|
||||
|
||||
/// Shared detailed client configuration options
|
||||
#[serde(flatten)]
|
||||
pub client_debug: ClientDebugConfig,
|
||||
}
|
||||
|
||||
impl Default for IpPacketRouterDebug1_1_3 {
|
||||
fn default() -> Self {
|
||||
IpPacketRouterDebug1_1_3 {
|
||||
enabled: true,
|
||||
disable_poisson_rate: true,
|
||||
client_debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
pub struct IpPacketRouter1_1_3 {
|
||||
#[serde(default)]
|
||||
pub debug: IpPacketRouterDebug1_1_3,
|
||||
}
|
||||
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for IpPacketRouter1_1_3 {
|
||||
fn default() -> Self {
|
||||
IpPacketRouter1_1_3 {
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
pub struct NetworkRequesterDebug1_1_3 {
|
||||
/// Specifies whether network requester service is enabled in this process.
|
||||
/// This is only here for debugging purposes as exit gateway should always run **both**
|
||||
/// network requester and an ip packet router.
|
||||
pub enabled: bool,
|
||||
|
||||
/// Disable Poisson sending rate.
|
||||
/// This is equivalent to setting client_debug.traffic.disable_main_poisson_packet_distribution = true
|
||||
/// (or is it (?))
|
||||
pub disable_poisson_rate: bool,
|
||||
|
||||
/// Shared detailed client configuration options
|
||||
#[serde(flatten)]
|
||||
pub client_debug: ClientDebugConfig,
|
||||
}
|
||||
|
||||
impl Default for NetworkRequesterDebug1_1_3 {
|
||||
fn default() -> Self {
|
||||
NetworkRequesterDebug1_1_3 {
|
||||
enabled: true,
|
||||
disable_poisson_rate: true,
|
||||
client_debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
pub struct NetworkRequester1_1_3 {
|
||||
#[serde(default)]
|
||||
pub debug: NetworkRequesterDebug1_1_3,
|
||||
}
|
||||
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for NetworkRequester1_1_3 {
|
||||
fn default() -> Self {
|
||||
NetworkRequester1_1_3 {
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ExitGatewayConfig1_1_3 {
|
||||
pub storage_paths: ExitGatewayPaths1_1_3,
|
||||
|
||||
/// specifies whether this exit node should run in 'open-proxy' mode
|
||||
/// and thus would attempt to resolve **ANY** request it receives.
|
||||
pub open_proxy: bool,
|
||||
|
||||
/// Specifies the url for an upstream source of the exit policy used by this node.
|
||||
pub upstream_exit_policy_url: Url,
|
||||
|
||||
pub network_requester: NetworkRequester1_1_3,
|
||||
|
||||
pub ip_packet_router: IpPacketRouter1_1_3,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct LoggingSettings1_1_3 {
|
||||
// well, we need to implement something here at some point...
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Config1_1_3 {
|
||||
// additional metadata holding on-disk location of this config file
|
||||
#[serde(skip)]
|
||||
pub(crate) save_path: Option<PathBuf>,
|
||||
|
||||
/// Human-readable ID of this particular node.
|
||||
pub id: String,
|
||||
|
||||
/// Current mode of this nym-node.
|
||||
/// Expect this field to be changed in the future to allow running the node in multiple modes (i.e. mixnode + gateway)
|
||||
pub mode: NodeMode1_1_3,
|
||||
|
||||
pub host: Host1_1_3,
|
||||
|
||||
pub mixnet: Mixnet1_1_3,
|
||||
|
||||
/// Storage paths to persistent nym-node data, such as its long term keys.
|
||||
pub storage_paths: NymNodePaths1_1_3,
|
||||
|
||||
#[serde(default)]
|
||||
pub http: Http1_1_3,
|
||||
|
||||
pub wireguard: Wireguard1_1_3,
|
||||
|
||||
pub mixnode: MixnodeConfig1_1_3,
|
||||
|
||||
pub entry_gateway: EntryGatewayConfig1_1_3,
|
||||
|
||||
pub exit_gateway: ExitGatewayConfig1_1_3,
|
||||
|
||||
#[serde(default)]
|
||||
pub logging: LoggingSettings1_1_3,
|
||||
}
|
||||
|
||||
impl NymConfigTemplate for Config1_1_3 {
|
||||
fn template(&self) -> &'static str {
|
||||
CONFIG_TEMPLATE
|
||||
}
|
||||
}
|
||||
|
||||
impl Config1_1_3 {
|
||||
pub fn save(&self) -> Result<(), NymNodeError> {
|
||||
let save_location = self.save_location();
|
||||
debug!(
|
||||
"attempting to save config file to '{}'",
|
||||
save_location.display()
|
||||
);
|
||||
save_formatted_config_to_file(self, &save_location).map_err(|source| {
|
||||
NymNodeError::ConfigSaveFailure {
|
||||
id: self.id.clone(),
|
||||
path: save_location,
|
||||
source,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn save_location(&self) -> PathBuf {
|
||||
self.save_path
|
||||
.clone()
|
||||
.unwrap_or(self.default_save_location())
|
||||
}
|
||||
|
||||
pub fn default_save_location(&self) -> PathBuf {
|
||||
default_config_filepath(&self.id)
|
||||
}
|
||||
|
||||
pub fn default_data_directory<P: AsRef<Path>>(config_path: P) -> Result<PathBuf, NymNodeError> {
|
||||
let config_path = config_path.as_ref();
|
||||
|
||||
// we got a proper path to the .toml file
|
||||
let Some(config_dir) = config_path.parent() else {
|
||||
error!(
|
||||
"'{}' does not have a parent directory. Have you pointed to the fs root?",
|
||||
config_path.display()
|
||||
);
|
||||
return Err(NymNodeError::DataDirDerivationFailure);
|
||||
};
|
||||
|
||||
let Some(config_dir_name) = config_dir.file_name() else {
|
||||
error!(
|
||||
"could not obtain parent directory name of '{}'. Have you used relative paths?",
|
||||
config_path.display()
|
||||
);
|
||||
return Err(NymNodeError::DataDirDerivationFailure);
|
||||
};
|
||||
|
||||
if config_dir_name != DEFAULT_CONFIG_DIR {
|
||||
error!(
|
||||
"the parent directory of '{}' ({}) is not {DEFAULT_CONFIG_DIR}. currently this is not supported",
|
||||
config_path.display(), config_dir_name.to_str().unwrap_or("UNKNOWN")
|
||||
);
|
||||
return Err(NymNodeError::DataDirDerivationFailure);
|
||||
}
|
||||
|
||||
let Some(node_dir) = config_dir.parent() else {
|
||||
error!(
|
||||
"'{}' does not have a parent directory. Have you pointed to the fs root?",
|
||||
config_dir.display()
|
||||
);
|
||||
return Err(NymNodeError::DataDirDerivationFailure);
|
||||
};
|
||||
|
||||
Ok(node_dir.join(DEFAULT_DATA_DIR))
|
||||
}
|
||||
|
||||
// simple wrapper that reads config file and assigns path location
|
||||
fn read_from_path<P: AsRef<Path>>(path: P) -> Result<Self, NymNodeError> {
|
||||
let path = path.as_ref();
|
||||
let mut loaded: Config1_1_3 =
|
||||
read_config_from_toml_file(path).map_err(|source| NymNodeError::ConfigLoadFailure {
|
||||
path: path.to_path_buf(),
|
||||
source,
|
||||
})?;
|
||||
loaded.save_path = Some(path.to_path_buf());
|
||||
debug!("loaded config file from {}", path.display());
|
||||
Ok(loaded)
|
||||
}
|
||||
|
||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> Result<Self, NymNodeError> {
|
||||
Self::read_from_path(path)
|
||||
}
|
||||
}
|
||||
|
||||
fn initialise(config: &Wireguard1_1_3) -> std::io::Result<()> {
|
||||
let mut rng = OsRng;
|
||||
let x25519_keys = KeyPair::new(&mut rng);
|
||||
|
||||
store_keypair(
|
||||
&x25519_keys,
|
||||
&config.storage_paths.x25519_wireguard_storage_paths(),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// currently there are no upgrades
|
||||
pub async fn try_upgrade_config_1_1_3<P: AsRef<Path>>(path: P) -> Result<(), NymNodeError> {
|
||||
let old_cfg = Config::read_from_path(&path)?;
|
||||
let cfg = Config {
|
||||
save_path: old_cfg.save_path,
|
||||
id: old_cfg.id,
|
||||
mode: old_cfg.mode,
|
||||
host: old_cfg.host,
|
||||
mixnet: old_cfg.mixnet,
|
||||
storage_paths: old_cfg.storage_paths,
|
||||
http: old_cfg.http,
|
||||
wireguard: old_cfg.wireguard,
|
||||
mixnode: old_cfg.mixnode,
|
||||
entry_gateway: old_cfg.entry_gateway,
|
||||
exit_gateway: old_cfg.exit_gateway,
|
||||
logging: old_cfg.logging,
|
||||
};
|
||||
|
||||
cfg.save()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -43,14 +43,6 @@ pub const DEFAULT_IPR_ACK_KEY_FILENAME: &str = "aes128ctr_ipr_ack";
|
||||
pub const DEFAULT_IPR_REPLY_SURB_DB_FILENAME: &str = "ipr_persistent_reply_store.sqlite";
|
||||
pub const DEFAULT_IPR_GATEWAYS_DB_FILENAME: &str = "ipr_gateways_info_store.sqlite";
|
||||
|
||||
pub const DEFAULT_ED25519_AUTH_PRIVATE_IDENTITY_KEY_FILENAME: &str = "ed25519_auth_identity";
|
||||
pub const DEFAULT_ED25519_AUTH_PUBLIC_IDENTITY_KEY_FILENAME: &str = "ed25519_auth_identity.pub";
|
||||
pub const DEFAULT_X25519_AUTH_PRIVATE_DH_KEY_FILENAME: &str = "x25519_auth_dh";
|
||||
pub const DEFAULT_X25519_AUTH_PUBLIC_DH_KEY_FILENAME: &str = "x25519_auth_dh.pub";
|
||||
pub const DEFAULT_AUTH_ACK_KEY_FILENAME: &str = "aes128ctr_auth_ack";
|
||||
pub const DEFAULT_AUTH_REPLY_SURB_DB_FILENAME: &str = "auth_persistent_reply_store.sqlite";
|
||||
pub const DEFAULT_AUTH_GATEWAYS_DB_FILENAME: &str = "auth_gateways_info_store.sqlite";
|
||||
|
||||
// Wireguard
|
||||
pub const DEFAULT_X25519_WG_DH_KEY_FILENAME: &str = "x25519_wg_dh";
|
||||
pub const DEFAULT_X25519_WG_PUBLIC_DH_KEY_FILENAME: &str = "x25519_wg_dh.pub";
|
||||
@@ -203,8 +195,6 @@ pub struct ExitGatewayPaths {
|
||||
pub network_requester: NetworkRequesterPaths,
|
||||
|
||||
pub ip_packet_router: IpPacketRouterPaths,
|
||||
|
||||
pub authenticator: AuthenticatorPaths,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
@@ -367,93 +357,12 @@ impl IpPacketRouterPaths {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct AuthenticatorPaths {
|
||||
/// Path to file containing authenticator ed25519 identity private key.
|
||||
pub private_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing authenticator ed25519 identity public key.
|
||||
pub public_ed25519_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing authenticator x25519 diffie hellman private key.
|
||||
pub private_x25519_diffie_hellman_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing authenticator x25519 diffie hellman public key.
|
||||
pub public_x25519_diffie_hellman_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing key used for encrypting and decrypting the content of an
|
||||
/// acknowledgement so that nobody besides the client knows which packet it refers to.
|
||||
pub ack_key_file: PathBuf,
|
||||
|
||||
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
|
||||
pub reply_surb_database: PathBuf,
|
||||
|
||||
/// Normally this is a path to the file containing information about gateways used by this client,
|
||||
/// i.e. details such as their public keys, owner addresses or the network information.
|
||||
/// but in this case it just has the basic information of "we're using custom gateway".
|
||||
/// Due to how clients are started up, this file has to exist.
|
||||
pub gateway_registrations: PathBuf,
|
||||
// it's possible we might have to add credential storage here for return tickets
|
||||
}
|
||||
|
||||
impl AuthenticatorPaths {
|
||||
pub fn new<P: AsRef<Path>>(data_dir: P) -> Self {
|
||||
let data_dir = data_dir.as_ref();
|
||||
AuthenticatorPaths {
|
||||
private_ed25519_identity_key_file: data_dir
|
||||
.join(DEFAULT_ED25519_AUTH_PRIVATE_IDENTITY_KEY_FILENAME),
|
||||
public_ed25519_identity_key_file: data_dir
|
||||
.join(DEFAULT_ED25519_AUTH_PUBLIC_IDENTITY_KEY_FILENAME),
|
||||
private_x25519_diffie_hellman_key_file: data_dir
|
||||
.join(DEFAULT_X25519_AUTH_PRIVATE_DH_KEY_FILENAME),
|
||||
public_x25519_diffie_hellman_key_file: data_dir
|
||||
.join(DEFAULT_X25519_AUTH_PUBLIC_DH_KEY_FILENAME),
|
||||
ack_key_file: data_dir.join(DEFAULT_AUTH_ACK_KEY_FILENAME),
|
||||
reply_surb_database: data_dir.join(DEFAULT_AUTH_REPLY_SURB_DB_FILENAME),
|
||||
gateway_registrations: data_dir.join(DEFAULT_AUTH_GATEWAYS_DB_FILENAME),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_common_client_paths(&self) -> CommonClientPaths {
|
||||
CommonClientPaths {
|
||||
keys: ClientKeysPaths {
|
||||
private_identity_key_file: self.private_ed25519_identity_key_file.clone(),
|
||||
public_identity_key_file: self.public_ed25519_identity_key_file.clone(),
|
||||
private_encryption_key_file: self.private_x25519_diffie_hellman_key_file.clone(),
|
||||
public_encryption_key_file: self.public_x25519_diffie_hellman_key_file.clone(),
|
||||
ack_key_file: self.ack_key_file.clone(),
|
||||
},
|
||||
gateway_registrations: self.gateway_registrations.clone(),
|
||||
|
||||
// not needed for embedded providers
|
||||
credentials_database: Default::default(),
|
||||
reply_surb_database: self.reply_surb_database.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ed25519_identity_storage_paths(&self) -> nym_pemstore::KeyPairPath {
|
||||
nym_pemstore::KeyPairPath::new(
|
||||
&self.private_ed25519_identity_key_file,
|
||||
&self.public_ed25519_identity_key_file,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn x25519_diffie_hellman_storage_paths(&self) -> nym_pemstore::KeyPairPath {
|
||||
nym_pemstore::KeyPairPath::new(
|
||||
&self.private_x25519_diffie_hellman_key_file,
|
||||
&self.public_x25519_diffie_hellman_key_file,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ExitGatewayPaths {
|
||||
pub fn new<P: AsRef<Path>>(data_dir: P) -> Self {
|
||||
let data_dir = data_dir.as_ref();
|
||||
ExitGatewayPaths {
|
||||
network_requester: NetworkRequesterPaths::new(data_dir),
|
||||
ip_packet_router: IpPacketRouterPaths::new(data_dir),
|
||||
authenticator: AuthenticatorPaths::new(data_dir),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,151 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use tracing::debug;
|
||||
|
||||
use crate::config::old_configs::*;
|
||||
use crate::config::persistence::WireguardPaths;
|
||||
use crate::config::Config;
|
||||
use crate::error::NymNodeError;
|
||||
use std::path::Path;
|
||||
|
||||
// currently there are no upgrades
|
||||
async fn try_upgrade_config(path: &Path) -> Result<(), NymNodeError> {
|
||||
if try_upgrade_config_1_1_2(path).await.is_ok() {
|
||||
debug!("Updated from 1.1.2 or previous");
|
||||
async fn try_upgrade_config<P: AsRef<Path>>(path: P) -> Result<(), NymNodeError> {
|
||||
use crate::config::*;
|
||||
use crate::error::KeyIOFailure;
|
||||
use nym_crypto::asymmetric::encryption::KeyPair;
|
||||
use nym_pemstore::store_keypair;
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct OldWireguardPaths {
|
||||
// pub keys:
|
||||
}
|
||||
if try_upgrade_config_1_1_3(path).await.is_ok() {
|
||||
debug!("Updated from 1.1.3");
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct OldWireguard {
|
||||
/// Specifies whether the wireguard service is enabled on this node.
|
||||
pub enabled: bool,
|
||||
|
||||
/// Socket address this node will use for binding its wireguard interface.
|
||||
/// default: `0.0.0.0:51822`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Ip address of the private wireguard network.
|
||||
/// default: `10.1.0.0`
|
||||
pub private_network_ip: IpAddr,
|
||||
|
||||
/// Port announced to external clients wishing to connect to the wireguard interface.
|
||||
/// Useful in the instances where the node is behind a proxy.
|
||||
pub announced_port: u16,
|
||||
|
||||
/// 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
|
||||
pub private_network_prefix: u8,
|
||||
|
||||
/// Paths for wireguard keys, client registries, etc.
|
||||
pub storage_paths: OldWireguardPaths,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct OldConfig {
|
||||
// additional metadata holding on-disk location of this config file
|
||||
#[serde(skip)]
|
||||
pub(crate) save_path: Option<PathBuf>,
|
||||
|
||||
/// Human-readable ID of this particular node.
|
||||
pub id: String,
|
||||
|
||||
/// Current mode of this nym-node.
|
||||
/// Expect this field to be changed in the future to allow running the node in multiple modes (i.e. mixnode + gateway)
|
||||
pub mode: NodeMode,
|
||||
|
||||
pub host: Host,
|
||||
|
||||
pub mixnet: Mixnet,
|
||||
|
||||
/// Storage paths to persistent nym-node data, such as its long term keys.
|
||||
pub storage_paths: NymNodePaths,
|
||||
|
||||
#[serde(default)]
|
||||
pub http: Http,
|
||||
|
||||
pub wireguard: OldWireguard,
|
||||
|
||||
pub mixnode: MixnodeConfig,
|
||||
|
||||
pub entry_gateway: EntryGatewayConfig,
|
||||
|
||||
pub exit_gateway: ExitGatewayConfig,
|
||||
|
||||
#[serde(default)]
|
||||
pub logging: LoggingSettings,
|
||||
}
|
||||
|
||||
impl NymConfigTemplate for OldConfig {
|
||||
fn template(&self) -> &'static str {
|
||||
CONFIG_TEMPLATE
|
||||
}
|
||||
}
|
||||
|
||||
impl OldConfig {
|
||||
fn read_from_path<P: AsRef<Path>>(path: P) -> Result<Self, NymNodeError> {
|
||||
let path = path.as_ref();
|
||||
let mut loaded: OldConfig = read_config_from_toml_file(path).map_err(|source| {
|
||||
NymNodeError::ConfigLoadFailure {
|
||||
path: path.to_path_buf(),
|
||||
source,
|
||||
}
|
||||
})?;
|
||||
loaded.save_path = Some(path.to_path_buf());
|
||||
debug!("loaded config file from {}", path.display());
|
||||
Ok(loaded)
|
||||
}
|
||||
}
|
||||
|
||||
fn initialise(config: &Wireguard) -> std::io::Result<()> {
|
||||
let mut rng = OsRng;
|
||||
let x25519_keys = KeyPair::new(&mut rng);
|
||||
|
||||
store_keypair(
|
||||
&x25519_keys,
|
||||
&config.storage_paths.x25519_wireguard_storage_paths(),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let old_cfg = OldConfig::read_from_path(&path)?;
|
||||
let wireguard = Wireguard {
|
||||
enabled: old_cfg.wireguard.enabled,
|
||||
bind_address: old_cfg.wireguard.bind_address,
|
||||
private_ip: old_cfg.wireguard.private_network_ip,
|
||||
announced_port: old_cfg.wireguard.announced_port,
|
||||
private_network_prefix: old_cfg.wireguard.private_network_prefix,
|
||||
storage_paths: WireguardPaths::new(Config::default_data_directory(path)?),
|
||||
};
|
||||
initialise(&wireguard).map_err(|err| KeyIOFailure::KeyPairStoreFailure {
|
||||
keys: "wg-x25519-dh".to_string(),
|
||||
paths: wireguard.storage_paths.x25519_wireguard_storage_paths(),
|
||||
err,
|
||||
})?;
|
||||
let cfg = Config {
|
||||
save_path: old_cfg.save_path,
|
||||
id: old_cfg.id,
|
||||
mode: old_cfg.mode,
|
||||
host: old_cfg.host,
|
||||
mixnet: old_cfg.mixnet,
|
||||
storage_paths: old_cfg.storage_paths,
|
||||
http: old_cfg.http,
|
||||
wireguard,
|
||||
mixnode: old_cfg.mixnode,
|
||||
entry_gateway: old_cfg.entry_gateway,
|
||||
exit_gateway: old_cfg.exit_gateway,
|
||||
logging: old_cfg.logging,
|
||||
};
|
||||
|
||||
cfg.save()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
+26
-37
@@ -8,6 +8,7 @@ use crate::node::helpers::{
|
||||
store_x25519_sphinx_keypair, DisplayDetails,
|
||||
};
|
||||
use crate::node::http::{sign_host_details, system_info::get_system_info};
|
||||
use ipnetwork::IpNetwork;
|
||||
use nym_bin_common::bin_info_owned;
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_gateway::Gateway;
|
||||
@@ -25,6 +26,7 @@ use nym_node::config::{
|
||||
use nym_node::error::{EntryGatewayError, ExitGatewayError, MixnodeError, NymNodeError};
|
||||
use nym_node_http_api::api::api_requests;
|
||||
use nym_node_http_api::api::api_requests::v1::node::models::NodeDescription;
|
||||
use nym_node_http_api::router::WireguardAppState;
|
||||
use nym_node_http_api::state::metrics::{SharedMixingStats, SharedVerlocStats};
|
||||
use nym_node_http_api::state::AppState;
|
||||
use nym_node_http_api::{NymNodeHTTPServer, NymNodeRouter};
|
||||
@@ -66,6 +68,7 @@ impl MixnodeData {
|
||||
pub struct EntryGatewayData {
|
||||
mnemonic: Zeroizing<bip39::Mnemonic>,
|
||||
client_storage: nym_gateway::node::PersistentStorage,
|
||||
wireguard_data: WireguardGatewayData,
|
||||
}
|
||||
|
||||
impl EntryGatewayData {
|
||||
@@ -83,7 +86,10 @@ impl EntryGatewayData {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn new(config: &EntryGatewayConfig) -> Result<EntryGatewayData, EntryGatewayError> {
|
||||
async fn new(
|
||||
config: &EntryGatewayConfig,
|
||||
wireguard_data: WireguardGatewayData,
|
||||
) -> Result<EntryGatewayData, EntryGatewayError> {
|
||||
Ok(EntryGatewayData {
|
||||
mnemonic: config.storage_paths.load_mnemonic_from_file()?,
|
||||
client_storage: nym_gateway::node::PersistentStorage::init(
|
||||
@@ -92,6 +98,7 @@ impl EntryGatewayData {
|
||||
)
|
||||
.await
|
||||
.map_err(nym_gateway::GatewayError::from)?,
|
||||
wireguard_data: wireguard_data.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -106,9 +113,6 @@ pub struct ExitGatewayData {
|
||||
|
||||
ipr_ed25519: ed25519::PublicKey,
|
||||
ipr_x25519: x25519::PublicKey,
|
||||
|
||||
auth_ed25519: ed25519::PublicKey,
|
||||
auth_x25519: x25519::PublicKey,
|
||||
}
|
||||
|
||||
impl ExitGatewayData {
|
||||
@@ -239,24 +243,11 @@ impl ExitGatewayData {
|
||||
"ip packet router x25519",
|
||||
)?;
|
||||
|
||||
let auth_paths = &config.storage_paths.authenticator;
|
||||
let auth_ed25519 = load_key(
|
||||
&auth_paths.public_ed25519_identity_key_file,
|
||||
"authenticator ed25519",
|
||||
)?;
|
||||
|
||||
let auth_x25519 = load_key(
|
||||
&auth_paths.public_x25519_diffie_hellman_key_file,
|
||||
"authenticator x25519",
|
||||
)?;
|
||||
|
||||
Ok(ExitGatewayData {
|
||||
nr_ed25519,
|
||||
nr_x25519,
|
||||
ipr_ed25519,
|
||||
ipr_x25519,
|
||||
auth_ed25519,
|
||||
auth_x25519,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -395,7 +386,11 @@ impl NymNode {
|
||||
description: load_node_description(&config.storage_paths.description)?,
|
||||
verloc_stats: Default::default(),
|
||||
mixnode: MixnodeData::new(&config.mixnode)?,
|
||||
entry_gateway: EntryGatewayData::new(&config.entry_gateway).await?,
|
||||
entry_gateway: EntryGatewayData::new(
|
||||
&config.entry_gateway,
|
||||
wireguard_data.inner.clone(),
|
||||
)
|
||||
.await?,
|
||||
exit_gateway: ExitGatewayData::new(&config.exit_gateway)?,
|
||||
wireguard: wireguard_data,
|
||||
config,
|
||||
@@ -427,14 +422,6 @@ impl NymNode {
|
||||
)
|
||||
}
|
||||
|
||||
fn exit_authenticator_address(&self) -> Recipient {
|
||||
Recipient::new(
|
||||
self.exit_gateway.auth_ed25519,
|
||||
self.exit_gateway.auth_x25519,
|
||||
*self.ed25519_identity_keys.public_key(),
|
||||
)
|
||||
}
|
||||
|
||||
fn x25519_wireguard_key(&self) -> &x25519::PublicKey {
|
||||
self.wireguard.inner.keypair().public_key()
|
||||
}
|
||||
@@ -500,7 +487,6 @@ impl NymNode {
|
||||
config,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
self.ed25519_identity_keys.clone(),
|
||||
self.x25519_sphinx_keys.clone(),
|
||||
self.entry_gateway.client_storage.clone(),
|
||||
@@ -528,7 +514,6 @@ impl NymNode {
|
||||
config.gateway,
|
||||
Some(config.nr_opts),
|
||||
Some(config.ipr_opts),
|
||||
Some(config.auth_opts),
|
||||
self.ed25519_identity_keys.clone(),
|
||||
self.x25519_sphinx_keys.clone(),
|
||||
self.entry_gateway.client_storage.clone(),
|
||||
@@ -599,13 +584,6 @@ impl NymNode {
|
||||
encoded_x25519_key: self.exit_gateway.ipr_x25519.to_base58_string(),
|
||||
address: self.exit_ip_packet_router_address().to_string(),
|
||||
};
|
||||
|
||||
let auth_details = api_requests::v1::authenticator::models::Authenticator {
|
||||
encoded_identity_key: self.exit_gateway.auth_ed25519.to_base58_string(),
|
||||
encoded_x25519_key: self.exit_gateway.auth_x25519.to_base58_string(),
|
||||
address: self.exit_authenticator_address().to_string(),
|
||||
};
|
||||
|
||||
let exit_policy_details =
|
||||
api_requests::v1::network_requester::exit_policy::models::UsedExitPolicy {
|
||||
enabled: true,
|
||||
@@ -619,13 +597,24 @@ impl NymNode {
|
||||
policy: None,
|
||||
};
|
||||
|
||||
let wireguard_private_network = IpNetwork::new(
|
||||
self.config.wireguard.private_ip,
|
||||
self.config.wireguard.private_network_prefix,
|
||||
)?;
|
||||
|
||||
let wg_state = WireguardAppState::new(
|
||||
self.entry_gateway.wireguard_data.clone(),
|
||||
Default::default(),
|
||||
self.config.wireguard.bind_address.port(),
|
||||
wireguard_private_network,
|
||||
)?;
|
||||
|
||||
let mut config = nym_node_http_api::Config::new(bin_info_owned!(), host_details)
|
||||
.with_landing_page_assets(self.config.http.landing_page_assets_path.as_ref())
|
||||
.with_mixnode_details(mixnode_details)
|
||||
.with_gateway_details(gateway_details)
|
||||
.with_network_requester_details(nr_details)
|
||||
.with_ip_packet_router_details(ipr_details)
|
||||
.with_authenticator_details(auth_details)
|
||||
.with_used_exit_policy(exit_policy_details)
|
||||
.with_description(self.description.clone())
|
||||
.with_auxiliary_details(auxiliary_details);
|
||||
@@ -651,7 +640,7 @@ impl NymNode {
|
||||
.with_verloc_stats(self.verloc_stats.clone())
|
||||
.with_metrics_key(self.config.http.access_token.clone());
|
||||
|
||||
Ok(NymNodeRouter::new(config, Some(app_state))
|
||||
Ok(NymNodeRouter::new(config, Some(app_state), Some(wg_state))
|
||||
.build_server(&self.config.http.bind_address)
|
||||
.await?)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user