Add upgrades to nym-node for authenticator changes (#4703) (#4710)

* Add iterative upgrades to nym-node

* Authenticator correct configuration

* Add info log

* Enable auth opts on entry gw

* Move ephemeral config from exit_gateway

* Fix fmt

* Fix clippy

* Pass custom transceiver for authenticator

* Fix non-linux build

* Feature gate wg_api

* Change naming from semver to simple incremental

* Move opts unwrap inside the mutable function

* Remove unneeded authenticator_description
This commit is contained in:
Bogdan-Ștefan Neacşu
2024-07-12 14:45:59 +02:00
committed by GitHub
parent eec1895acc
commit 1f144690da
18 changed files with 853 additions and 316 deletions
+3
View File
@@ -148,6 +148,9 @@ pub enum GatewayError {
#[error("failed to startup local ip packet router")]
IpPacketRouterStartupFailure,
#[error("failed to startup local authenticator")]
AuthenticatorStartupFailure,
#[error("there are no nym API endpoints available")]
NoNymApisAvailable,
+72 -17
View File
@@ -47,6 +47,16 @@ struct StartedNetworkRequester {
handle: LocalEmbeddedClientHandle,
}
// TODO: should this struct live here?
#[allow(unused)]
struct StartedAuthenticator {
#[cfg(feature = "wireguard")]
wg_api: Arc<nym_wireguard::WgApiWrapper>,
/// Handle to interact with the local authenticator
handle: LocalEmbeddedClientHandle,
}
/// Wire up and create Gateway instance
pub async fn create_gateway(
config: Config,
@@ -238,17 +248,63 @@ impl<St> Gateway<St> {
#[cfg(all(feature = "wireguard", target_os = "linux"))]
async fn start_authenticator(
&mut self,
opts: &LocalAuthenticatorOpts,
forwarding_channel: MixForwardingSender,
shutdown: TaskClient,
) -> Result<Arc<nym_wireguard::WgApiWrapper>, Box<dyn std::error::Error + Send + Sync>> {
) -> Result<StartedAuthenticator, Box<dyn std::error::Error + Send + Sync>> {
let opts = self
.authenticator_opts
.as_ref()
.ok_or(GatewayError::UnspecifiedAuthenticatorConfig)?;
let (router_tx, mut router_rx) = oneshot::channel();
let (auth_mix_sender, auth_mix_receiver) = mpsc::unbounded();
let router_shutdown = shutdown.fork("message_router");
let transceiver = LocalGateway::new(
*self.identity_keypair.public_key(),
forwarding_channel,
router_tx,
);
if let Some(wireguard_data) = self.wireguard_data.take() {
let authenticator_server = nym_authenticator::Authenticator::new(
let (on_start_tx, on_start_rx) = oneshot::channel();
let mut 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
.with_custom_gateway_transceiver(Box::new(transceiver))
.with_shutdown(shutdown.fork("authenticator"))
.with_wait_for_gateway(true)
.with_minimum_gateway_performance(0)
.with_on_start(on_start_tx);
if let Some(custom_mixnet) = &opts.custom_mixnet_path {
authenticator_server = authenticator_server.with_stored_topology(custom_mixnet)?
}
tokio::spawn(async move {
if let Err(e) = authenticator_server.run_service_provider().await {
log::error!("Run authenticator server - {e}");
}
});
let start_data = on_start_rx
.await
.map_err(|_| GatewayError::AuthenticatorStartupFailure)?;
// this should be instantaneous since the data is sent on this channel before the on start is called;
// the failure should be impossible
let Ok(Some(packet_router)) = router_rx.try_recv() else {
return Err(Box::new(GatewayError::AuthenticatorStartupFailure));
};
MessageRouter::new(auth_mix_receiver, packet_router)
.start_with_shutdown(router_shutdown);
let wg_api = nym_wireguard::start_wireguard(shutdown, wireguard_data).await?;
Ok(StartedAuthenticator {
wg_api,
handle: LocalEmbeddedClientHandle::new(start_data.address, auth_mix_sender),
})
} else {
Err(Box::new(GatewayError::WireguardNotSet))
}
@@ -257,9 +313,9 @@ impl<St> Gateway<St> {
#[cfg(all(feature = "wireguard", not(target_os = "linux")))]
async fn start_authenticator(
&self,
_opts: &LocalAuthenticatorOpts,
_forwarding_channel: MixForwardingSender,
_shutdown: TaskClient,
) -> Result<Arc<nym_wireguard::WgApiWrapper>, Box<dyn std::error::Error + Send + Sync>> {
) -> Result<StartedAuthenticator, Box<dyn std::error::Error + Send + Sync>> {
todo!("Authenticator is currently only supported on Linux");
}
@@ -554,7 +610,7 @@ impl<St> Gateway<St> {
if self.config.ip_packet_router.enabled {
let embedded_ip_sp = self
.start_ip_packet_router(
mix_forwarding_channel,
mix_forwarding_channel.clone(),
shutdown.fork("ip_service_provider"),
)
.await?;
@@ -564,14 +620,13 @@ impl<St> Gateway<St> {
};
#[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
let _wg_api = {
let embedded_auth = self
.start_authenticator(mix_forwarding_channel, shutdown.fork("authenticator"))
.await
.map_err(|source| GatewayError::AuthenticatorStartError { source })?;
active_clients_store.insert_embedded(embedded_auth.handle);
Some(embedded_auth.wg_api)
};
if self.run_http_server {
-6
View File
@@ -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();
+43 -6
View File
@@ -8,11 +8,13 @@ use crate::error::EntryGatewayError;
use nym_config::defaults::DEFAULT_CLIENT_LISTENING_PORT;
use nym_config::helpers::inaddr_any;
use nym_config::serde_helpers::de_maybe_port;
use nym_gateway::node::LocalAuthenticatorOpts;
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;
use std::path::Path;
use super::authenticator::Authenticator;
use super::helpers::{base_client_config, EphemeralConfig};
use super::LocalWireguardOpts;
pub const DEFAULT_WS_PORT: u16 = DEFAULT_CLIENT_LISTENING_PORT;
@@ -40,8 +42,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 +73,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(),
}
}
@@ -83,6 +82,44 @@ impl EntryGatewayConfig {
pub fn ephemeral_entry_gateway_config(
config: Config,
mnemonic: &bip39::Mnemonic,
) -> Result<nym_gateway::config::Config, EntryGatewayError> {
Ok(ephemeral_gateway_config(config, mnemonic)?)
) -> Result<EphemeralConfig, EntryGatewayError> {
let auth_opts = LocalAuthenticatorOpts {
config: nym_authenticator::Config {
base: nym_client_core_config_types::Config {
client: base_client_config(&config),
debug: config.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(),
},
logging: config.logging,
},
custom_mixnet_path: None,
};
let wg_opts = LocalWireguardOpts {
config: super::Wireguard {
enabled: config.wireguard.enabled,
bind_address: config.wireguard.bind_address,
private_ip: config.wireguard.private_ip,
announced_port: config.wireguard.announced_port,
private_network_prefix: config.wireguard.private_network_prefix,
storage_paths: config.wireguard.storage_paths.clone(),
},
custom_mixnet_path: None,
};
let gateway = ephemeral_gateway_config(config, mnemonic)?;
Ok(EphemeralConfig {
nr_opts: None,
ipr_opts: None,
auth_opts,
wg_opts,
gateway,
})
}
+7 -28
View File
@@ -5,7 +5,6 @@ use crate::config::helpers::ephemeral_gateway_config;
use crate::config::persistence::ExitGatewayPaths;
use crate::config::Config;
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::{
@@ -15,7 +14,10 @@ use serde::{Deserialize, Serialize};
use std::path::Path;
use url::Url;
use super::{authenticator::Authenticator, LocalWireguardOpts};
use super::{
helpers::{base_client_config, EphemeralConfig},
LocalWireguardOpts,
};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
@@ -32,8 +34,6 @@ pub struct ExitGatewayConfig {
pub network_requester: NetworkRequester,
pub ip_packet_router: IpPacketRouter,
pub authenticator: Authenticator,
}
impl ExitGatewayConfig {
@@ -49,7 +49,6 @@ impl ExitGatewayConfig {
.expect("invalid default exit policy URL"),
network_requester: Default::default(),
ip_packet_router: Default::default(),
authenticator: Default::default(),
}
}
}
@@ -139,25 +138,6 @@ impl Default for IpPacketRouterDebug {
}
}
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,
}
fn base_client_config(config: &Config) -> nym_client_core_config_types::Client {
nym_client_core_config_types::Client {
version: format!("{}-nym-node", crate_version!()),
id: config.id.clone(),
// irrelevant field - no need for credentials in embedded mode
disabled_credentials_mode: true,
nyxd_urls: config.mixnet.nyxd_urls.clone(),
nym_api_urls: config.mixnet.nym_api_urls.clone(),
}
}
// that function is rather disgusting, but I hope it's not going to live for too long
pub fn ephemeral_exit_gateway_config(
config: Config,
@@ -244,7 +224,7 @@ pub fn ephemeral_exit_gateway_config(
config: nym_authenticator::Config {
base: nym_client_core_config_types::Config {
client: base_client_config(&config),
debug: config.exit_gateway.authenticator.debug.client_debug,
debug: config.authenticator.debug.client_debug,
},
authenticator: config.wireguard.clone().into(),
storage_paths: nym_authenticator::config::AuthenticatorPaths {
@@ -253,7 +233,6 @@ pub fn ephemeral_exit_gateway_config(
.storage_paths
.authenticator
.to_common_client_paths(),
authenticator_description: Default::default(),
},
logging: config.logging,
},
@@ -290,8 +269,8 @@ pub fn ephemeral_exit_gateway_config(
gateway.storage_paths.keys.public_identity_key_file = pub_id_path;
Ok(EphemeralConfig {
nr_opts,
ipr_opts,
nr_opts: Some(nr_opts),
ipr_opts: Some(ipr_opts),
auth_opts,
wg_opts,
gateway,
+24
View File
@@ -3,9 +3,14 @@
use crate::config::Config;
use clap::crate_version;
use nym_gateway::node::{
LocalAuthenticatorOpts, LocalIpPacketRouterOpts, LocalNetworkRequesterOpts,
};
use std::net::IpAddr;
use thiserror::Error;
use super::LocalWireguardOpts;
#[derive(Debug, Error)]
#[error("currently it's not supported to have different ip addresses for clients and mixnet ({clients_bind_ip} and {mix_bind_ip} were used)")]
pub struct UnsupportedGatewayAddresses {
@@ -80,3 +85,22 @@ pub fn ephemeral_gateway_config(
},
))
}
pub fn base_client_config(config: &Config) -> nym_client_core_config_types::Client {
nym_client_core_config_types::Client {
version: format!("{}-nym-node", crate_version!()),
id: config.id.clone(),
// irrelevant field - no need for credentials in embedded mode
disabled_credentials_mode: true,
nyxd_urls: config.mixnet.nyxd_urls.clone(),
nym_api_urls: config.mixnet.nym_api_urls.clone(),
}
}
pub struct EphemeralConfig {
pub gateway: nym_gateway::config::Config,
pub nr_opts: Option<LocalNetworkRequesterOpts>,
pub ipr_opts: Option<LocalIpPacketRouterOpts>,
pub auth_opts: LocalAuthenticatorOpts,
pub wg_opts: LocalWireguardOpts,
}
+7
View File
@@ -4,6 +4,7 @@
use crate::config::persistence::NymNodePaths;
use crate::config::template::CONFIG_TEMPLATE;
use crate::error::NymNodeError;
use authenticator::Authenticator;
use celes::Country;
use clap::ValueEnum;
use nym_bin_common::logging::LoggingSettings;
@@ -113,6 +114,8 @@ pub struct ConfigBuilder {
pub exit_gateway: Option<ExitGatewayConfig>,
pub authenticator: Option<Authenticator>,
pub logging: Option<LoggingSettings>,
}
@@ -131,6 +134,7 @@ impl ConfigBuilder {
mixnode: None,
entry_gateway: None,
exit_gateway: None,
authenticator: None,
logging: None,
}
}
@@ -207,6 +211,7 @@ impl ConfigBuilder {
.unwrap_or_else(|| ExitGatewayConfig::new_default(&self.data_dir)),
logging: self.logging.unwrap_or_default(),
save_path: Some(self.config_path),
authenticator: self.authenticator.unwrap_or_default(),
}
}
}
@@ -243,6 +248,8 @@ pub struct Config {
pub exit_gateway: ExitGatewayConfig,
pub authenticator: Authenticator,
#[serde(default)]
pub logging: LoggingSettings,
}
+4 -4
View File
@@ -1,8 +1,8 @@
// 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;
mod old_config_v1;
mod old_config_v2;
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;
pub use old_config_v1::try_upgrade_config_v1;
pub use old_config_v2::try_upgrade_config_v2;
@@ -8,21 +8,21 @@ 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 old_configs::old_config_v2::*;
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 struct WireguardPathsV1 {
pub private_diffie_hellman_key_file: PathBuf,
pub public_diffie_hellman_key_file: PathBuf,
}
impl WireguardPaths1_1_2 {
impl WireguardPathsV1 {
pub fn new<P: AsRef<Path>>(data_dir: P) -> Self {
let data_dir = data_dir.as_ref();
WireguardPaths1_1_2 {
WireguardPathsV1 {
private_diffie_hellman_key_file: data_dir
.join(persistence::DEFAULT_X25519_WG_DH_KEY_FILENAME),
public_diffie_hellman_key_file: data_dir
@@ -40,7 +40,7 @@ impl WireguardPaths1_1_2 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Wireguard1_1_2 {
pub struct WireguardV1 {
/// Specifies whether the wireguard service is enabled on this node.
pub enabled: bool,
@@ -61,13 +61,13 @@ pub struct Wireguard1_1_2 {
pub private_network_prefix: u8,
/// Paths for wireguard keys, client registries, etc.
pub storage_paths: WireguardPaths1_1_2,
pub storage_paths: WireguardPathsV1,
}
// 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 {
pub enum NodeModeV1 {
#[default]
#[clap(alias = "mix")]
Mixnode,
@@ -79,12 +79,12 @@ pub enum NodeMode1_1_2 {
ExitGateway,
}
impl From<NodeMode1_1_2> for NodeMode1_1_3 {
fn from(config: NodeMode1_1_2) -> Self {
impl From<NodeModeV1> for NodeModeV2 {
fn from(config: NodeModeV1) -> 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,
NodeModeV1::Mixnode => NodeModeV2::Mixnode,
NodeModeV1::EntryGateway => NodeModeV2::EntryGateway,
NodeModeV1::ExitGateway => NodeModeV2::ExitGateway,
}
}
}
@@ -93,7 +93,7 @@ impl From<NodeMode1_1_2> for NodeMode1_1_3 {
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Serialize)]
#[serde(default)]
#[serde(deny_unknown_fields)]
pub struct Host1_1_2 {
pub struct HostV1 {
/// 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.
@@ -112,7 +112,7 @@ pub struct Host1_1_2 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(default)]
#[serde(deny_unknown_fields)]
pub struct MixnetDebug1_1_2 {
pub struct MixnetDebugV1 {
/// Initial value of an exponential backoff to reconnect to dropped TCP connection when
/// forwarding sphinx packets.
#[serde(with = "humantime_serde")]
@@ -134,16 +134,16 @@ pub struct MixnetDebug1_1_2 {
pub unsafe_disable_noise: bool,
}
impl MixnetDebug1_1_2 {
impl MixnetDebugV1 {
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 {
impl Default for MixnetDebugV1 {
fn default() -> Self {
MixnetDebug1_1_2 {
MixnetDebugV1 {
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,
@@ -154,7 +154,7 @@ impl Default for MixnetDebug1_1_2 {
}
}
impl Default for Mixnet1_1_2 {
impl Default for MixnetV1 {
fn default() -> Self {
// SAFETY:
// our hardcoded values should always be valid
@@ -173,7 +173,7 @@ impl Default for Mixnet1_1_2 {
vec![mainnet::NYXD_URL.parse().expect("Invalid default nyxd URL")]
};
Mixnet1_1_2 {
MixnetV1 {
bind_address: SocketAddr::new(inaddr_any(), DEFAULT_MIXNET_PORT),
nym_api_urls,
nyxd_urls,
@@ -185,7 +185,7 @@ impl Default for Mixnet1_1_2 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(default)]
#[serde(deny_unknown_fields)]
pub struct Mixnet1_1_2 {
pub struct MixnetV1 {
/// Address this node will bind to for listening for mixnet packets
/// default: `0.0.0.0:1789`
pub bind_address: SocketAddr,
@@ -197,12 +197,12 @@ pub struct Mixnet1_1_2 {
pub nyxd_urls: Vec<Url>,
#[serde(default)]
pub debug: MixnetDebug1_1_2,
pub debug: MixnetDebugV1,
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct KeysPaths1_1_2 {
pub struct KeysPathsV1 {
/// Path to file containing ed25519 identity private key.
pub private_ed25519_identity_key_file: PathBuf,
@@ -224,8 +224,8 @@ pub struct KeysPaths1_1_2 {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct NymNodePaths1_1_2 {
pub keys: KeysPaths1_1_2,
pub struct NymNodePathsV1 {
pub keys: KeysPathsV1,
/// Path to a file containing basic node description: human-readable name, website, details, etc.
pub description: PathBuf,
@@ -234,7 +234,7 @@ pub struct NymNodePaths1_1_2 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(default)]
#[serde(deny_unknown_fields)]
pub struct Http1_1_2 {
pub struct HttpV1 {
/// Socket address this node will use for binding its http API.
/// default: `0.0.0.0:8080`
pub bind_address: SocketAddr,
@@ -263,9 +263,9 @@ pub struct Http1_1_2 {
pub expose_crypto_hardware: bool,
}
impl Default for Http1_1_2 {
impl Default for HttpV1 {
fn default() -> Self {
Http1_1_2 {
HttpV1 {
bind_address: SocketAddr::new(inaddr_any(), DEFAULT_HTTP_PORT),
landing_page_assets_path: None,
access_token: None,
@@ -278,11 +278,11 @@ impl Default for Http1_1_2 {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct MixnodePaths1_1_2 {}
pub struct MixnodePathsV1 {}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Debug1_1_2 {
pub struct DebugV1 {
/// Delay between each subsequent node statistics being logged to the console
#[serde(with = "humantime_serde")]
pub node_stats_logging_delay: Duration,
@@ -294,7 +294,7 @@ pub struct Debug1_1_2 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct VerlocDebug1_1_2 {
pub struct VerlocDebugV1 {
/// Specifies number of echo packets sent to each node during a measurement run.
pub packets_per_node: usize,
@@ -325,16 +325,16 @@ pub struct VerlocDebug1_1_2 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Verloc1_1_2 {
pub struct VerlocV1 {
/// 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,
pub debug: VerlocDebugV1,
}
impl VerlocDebug1_1_2 {
impl VerlocDebugV1 {
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);
@@ -344,9 +344,9 @@ impl VerlocDebug1_1_2 {
const DEFAULT_RETRY_TIMEOUT: Duration = Duration::from_secs(60 * 30);
}
impl Default for VerlocDebug1_1_2 {
impl Default for VerlocDebugV1 {
fn default() -> Self {
VerlocDebug1_1_2 {
VerlocDebugV1 {
packets_per_node: Self::DEFAULT_PACKETS_PER_NODE,
connection_timeout: Self::DEFAULT_CONNECTION_TIMEOUT,
packet_timeout: Self::DEFAULT_PACKET_TIMEOUT,
@@ -360,23 +360,23 @@ impl Default for VerlocDebug1_1_2 {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct MixnodeConfig1_1_2 {
pub storage_paths: MixnodePaths1_1_2,
pub struct MixnodeConfigV1 {
pub storage_paths: MixnodePathsV1,
pub verloc: Verloc1_1_2,
pub verloc: VerlocV1,
#[serde(default)]
pub debug: Debug1_1_2,
pub debug: DebugV1,
}
impl Debug1_1_2 {
impl DebugV1 {
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 {
impl Default for DebugV1 {
fn default() -> Self {
Debug1_1_2 {
DebugV1 {
node_stats_logging_delay: Self::DEFAULT_NODE_STATS_LOGGING_DELAY,
node_stats_updating_delay: Self::DEFAULT_NODE_STATS_UPDATING_DELAY,
}
@@ -385,7 +385,7 @@ impl Default for Debug1_1_2 {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct EntryGatewayPaths1_1_2 {
pub struct EntryGatewayPathsV1 {
/// Path to sqlite database containing all persistent data: messages for offline clients,
/// derived shared keys and available client bandwidths.
pub clients_storage: PathBuf,
@@ -396,18 +396,18 @@ pub struct EntryGatewayPaths1_1_2 {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct EntryGatewayConfigDebug1_1_2 {
pub struct EntryGatewayConfigDebugV1 {
/// 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 {
impl EntryGatewayConfigDebugV1 {
const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100;
}
impl Default for EntryGatewayConfigDebug1_1_2 {
impl Default for EntryGatewayConfigDebugV1 {
fn default() -> Self {
EntryGatewayConfigDebug1_1_2 {
EntryGatewayConfigDebugV1 {
message_retrieval_limit: Self::DEFAULT_MESSAGE_RETRIEVAL_LIMIT,
}
}
@@ -415,8 +415,8 @@ impl Default for EntryGatewayConfigDebug1_1_2 {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct EntryGatewayConfig1_1_2 {
pub storage_paths: EntryGatewayPaths1_1_2,
pub struct EntryGatewayConfigV1 {
pub storage_paths: EntryGatewayPathsV1,
/// Indicates whether this gateway is accepting only coconut credentials for accessing the mixnet
/// or if it also accepts non-paying clients
@@ -438,12 +438,12 @@ pub struct EntryGatewayConfig1_1_2 {
pub announce_wss_port: Option<u16>,
#[serde(default)]
pub debug: EntryGatewayConfigDebug1_1_2,
pub debug: EntryGatewayConfigDebugV1,
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct NetworkRequesterPaths1_1_2 {
pub struct NetworkRequesterPathsV1 {
/// Path to file containing network requester ed25519 identity private key.
pub private_ed25519_identity_key_file: PathBuf,
@@ -473,7 +473,7 @@ pub struct NetworkRequesterPaths1_1_2 {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct IpPacketRouterPaths1_1_2 {
pub struct IpPacketRouterPathsV1 {
/// Path to file containing ip packet router ed25519 identity private key.
pub private_ed25519_identity_key_file: PathBuf,
@@ -503,15 +503,15 @@ pub struct IpPacketRouterPaths1_1_2 {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ExitGatewayPaths1_1_2 {
pub network_requester: NetworkRequesterPaths1_1_2,
pub struct ExitGatewayPathsV1 {
pub network_requester: NetworkRequesterPathsV1,
pub ip_packet_router: IpPacketRouterPaths1_1_2,
pub ip_packet_router: IpPacketRouterPathsV1,
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct IpPacketRouterDebug1_1_2 {
pub struct IpPacketRouterDebugV1 {
/// 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.
@@ -527,9 +527,9 @@ pub struct IpPacketRouterDebug1_1_2 {
pub client_debug: ClientDebugConfig,
}
impl Default for IpPacketRouterDebug1_1_2 {
impl Default for IpPacketRouterDebugV1 {
fn default() -> Self {
IpPacketRouterDebug1_1_2 {
IpPacketRouterDebugV1 {
enabled: true,
disable_poisson_rate: true,
client_debug: Default::default(),
@@ -538,22 +538,22 @@ impl Default for IpPacketRouterDebug1_1_2 {
}
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
pub struct IpPacketRouter1_1_2 {
pub struct IpPacketRouterV1 {
#[serde(default)]
pub debug: IpPacketRouterDebug1_1_2,
pub debug: IpPacketRouterDebugV1,
}
#[allow(clippy::derivable_impls)]
impl Default for IpPacketRouter1_1_2 {
impl Default for IpPacketRouterV1 {
fn default() -> Self {
IpPacketRouter1_1_2 {
IpPacketRouterV1 {
debug: Default::default(),
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
pub struct NetworkRequesterDebug1_1_2 {
pub struct NetworkRequesterDebugV1 {
/// 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.
@@ -569,9 +569,9 @@ pub struct NetworkRequesterDebug1_1_2 {
pub client_debug: ClientDebugConfig,
}
impl Default for NetworkRequesterDebug1_1_2 {
impl Default for NetworkRequesterDebugV1 {
fn default() -> Self {
NetworkRequesterDebug1_1_2 {
NetworkRequesterDebugV1 {
enabled: true,
disable_poisson_rate: true,
client_debug: Default::default(),
@@ -580,15 +580,15 @@ impl Default for NetworkRequesterDebug1_1_2 {
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
pub struct NetworkRequester1_1_2 {
pub struct NetworkRequesterV1 {
#[serde(default)]
pub debug: NetworkRequesterDebug1_1_2,
pub debug: NetworkRequesterDebugV1,
}
#[allow(clippy::derivable_impls)]
impl Default for NetworkRequester1_1_2 {
impl Default for NetworkRequesterV1 {
fn default() -> Self {
NetworkRequester1_1_2 {
NetworkRequesterV1 {
debug: Default::default(),
}
}
@@ -596,8 +596,8 @@ impl Default for NetworkRequester1_1_2 {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ExitGatewayConfig1_1_2 {
pub storage_paths: ExitGatewayPaths1_1_2,
pub struct ExitGatewayConfigV1 {
pub storage_paths: ExitGatewayPathsV1,
/// specifies whether this exit node should run in 'open-proxy' mode
/// and thus would attempt to resolve **ANY** request it receives.
@@ -606,20 +606,20 @@ pub struct ExitGatewayConfig1_1_2 {
/// 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 network_requester: NetworkRequesterV1,
pub ip_packet_router: IpPacketRouter1_1_2,
pub ip_packet_router: IpPacketRouterV1,
}
#[derive(Debug, Default, Copy, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LoggingSettings1_1_2 {
pub struct LoggingSettingsV1 {
// well, we need to implement something here at some point...
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Config1_1_2 {
pub struct ConfigV1 {
// additional metadata holding on-disk location of this config file
#[serde(skip)]
pub(crate) save_path: Option<PathBuf>,
@@ -629,37 +629,37 @@ pub struct Config1_1_2 {
/// 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 mode: NodeModeV1,
pub host: Host1_1_2,
pub host: HostV1,
pub mixnet: Mixnet1_1_2,
pub mixnet: MixnetV1,
/// Storage paths to persistent nym-node data, such as its long term keys.
pub storage_paths: NymNodePaths1_1_2,
pub storage_paths: NymNodePathsV1,
#[serde(default)]
pub http: Http1_1_2,
pub http: HttpV1,
pub wireguard: Wireguard1_1_2,
pub wireguard: WireguardV1,
pub mixnode: MixnodeConfig1_1_2,
pub mixnode: MixnodeConfigV1,
pub entry_gateway: EntryGatewayConfig1_1_2,
pub entry_gateway: EntryGatewayConfigV1,
pub exit_gateway: ExitGatewayConfig1_1_2,
pub exit_gateway: ExitGatewayConfigV1,
#[serde(default)]
pub logging: LoggingSettings1_1_2,
pub logging: LoggingSettingsV1,
}
impl NymConfigTemplate for Config1_1_2 {
impl NymConfigTemplate for ConfigV1 {
fn template(&self) -> &'static str {
CONFIG_TEMPLATE
}
}
impl Config1_1_2 {
impl ConfigV1 {
pub fn save(&self) -> Result<(), NymNodeError> {
let save_location = self.save_location();
debug!(
@@ -727,7 +727,7 @@ impl Config1_1_2 {
// 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 =
let mut loaded: ConfigV1 =
read_config_from_toml_file(path).map_err(|source| NymNodeError::ConfigLoadFailure {
path: path.to_path_buf(),
source,
@@ -742,7 +742,7 @@ impl Config1_1_2 {
}
}
fn initialise(config: &Wireguard1_1_3) -> std::io::Result<()> {
fn initialise(config: &WireguardV2) -> std::io::Result<()> {
let mut rng = OsRng;
let x25519_keys = KeyPair::new(&mut rng);
@@ -754,36 +754,43 @@ fn initialise(config: &Wireguard1_1_3) -> std::io::Result<()> {
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 {
pub async fn try_upgrade_config_v1<P: AsRef<Path>>(
path: P,
prev_config: Option<ConfigV1>,
) -> Result<ConfigV2, NymNodeError> {
tracing::debug!("Updating from 1.1.2");
let old_cfg = if let Some(prev_config) = prev_config {
prev_config
} else {
ConfigV1::read_from_path(&path)?
};
let wireguard = WireguardV2 {
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)?),
storage_paths: WireguardPathsV2::new(ConfigV2::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 {
let cfg = ConfigV2 {
save_path: old_cfg.save_path,
id: old_cfg.id,
mode: old_cfg.mode.into(),
host: Host1_1_3 {
host: HostV2 {
public_ips: old_cfg.host.public_ips,
hostname: old_cfg.host.hostname,
location: old_cfg.host.location,
},
mixnet: Mixnet1_1_3 {
mixnet: MixnetV2 {
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 {
debug: MixnetDebugV2 {
packet_forwarding_initial_backoff: old_cfg
.mixnet
.debug
@@ -797,8 +804,8 @@ pub async fn try_upgrade_config_1_1_2<P: AsRef<Path>>(path: P) -> Result<(), Nym
unsafe_disable_noise: old_cfg.mixnet.debug.unsafe_disable_noise,
},
},
storage_paths: NymNodePaths1_1_3 {
keys: KeysPaths1_1_3 {
storage_paths: NymNodePathsV2 {
keys: KeysPathsV2 {
private_ed25519_identity_key_file: old_cfg
.storage_paths
.keys
@@ -826,7 +833,7 @@ pub async fn try_upgrade_config_1_1_2<P: AsRef<Path>>(path: P) -> Result<(), Nym
},
description: old_cfg.storage_paths.description,
},
http: Http1_1_3 {
http: HttpV2 {
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,
@@ -835,11 +842,11 @@ pub async fn try_upgrade_config_1_1_2<P: AsRef<Path>>(path: P) -> Result<(), Nym
expose_crypto_hardware: old_cfg.http.expose_crypto_hardware,
},
wireguard,
mixnode: MixnodeConfig1_1_3 {
storage_paths: MixnodePaths1_1_3 {},
verloc: Verloc1_1_3 {
mixnode: MixnodeConfigV2 {
storage_paths: MixnodePathsV2 {},
verloc: VerlocV2 {
bind_address: old_cfg.mixnode.verloc.bind_address,
debug: VerlocDebug1_1_3 {
debug: VerlocDebugV2 {
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,
@@ -849,13 +856,13 @@ pub async fn try_upgrade_config_1_1_2<P: AsRef<Path>>(path: P) -> Result<(), Nym
retry_timeout: old_cfg.mixnode.verloc.debug.retry_timeout,
},
},
debug: Debug1_1_3 {
debug: DebugV2 {
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 {
entry_gateway: EntryGatewayConfigV2 {
storage_paths: EntryGatewayPathsV2 {
clients_storage: old_cfg.entry_gateway.storage_paths.clients_storage,
cosmos_mnemonic: old_cfg.entry_gateway.storage_paths.cosmos_mnemonic,
},
@@ -863,13 +870,13 @@ pub async fn try_upgrade_config_1_1_2<P: AsRef<Path>>(path: P) -> Result<(), Nym
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 {
debug: EntryGatewayConfigDebugV2 {
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 {
exit_gateway: ExitGatewayConfigV2 {
storage_paths: ExitGatewayPathsV2 {
network_requester: NetworkRequesterPathsV2 {
private_ed25519_identity_key_file: old_cfg
.exit_gateway
.storage_paths
@@ -906,7 +913,7 @@ pub async fn try_upgrade_config_1_1_2<P: AsRef<Path>>(path: P) -> Result<(), Nym
.network_requester
.gateway_registrations,
},
ip_packet_router: IpPacketRouterPaths1_1_3 {
ip_packet_router: IpPacketRouterPathsV2 {
private_ed25519_identity_key_file: old_cfg
.exit_gateway
.storage_paths
@@ -946,8 +953,8 @@ pub async fn try_upgrade_config_1_1_2<P: AsRef<Path>>(path: P) -> Result<(), Nym
},
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 {
network_requester: NetworkRequesterV2 {
debug: NetworkRequesterDebugV2 {
enabled: old_cfg.exit_gateway.network_requester.debug.enabled,
disable_poisson_rate: old_cfg
.exit_gateway
@@ -957,8 +964,8 @@ pub async fn try_upgrade_config_1_1_2<P: AsRef<Path>>(path: P) -> Result<(), Nym
client_debug: old_cfg.exit_gateway.network_requester.debug.client_debug,
},
},
ip_packet_router: IpPacketRouter1_1_3 {
debug: IpPacketRouterDebug1_1_3 {
ip_packet_router: IpPacketRouterV2 {
debug: IpPacketRouterDebugV2 {
enabled: old_cfg.exit_gateway.ip_packet_router.debug.enabled,
disable_poisson_rate: old_cfg
.exit_gateway
@@ -969,10 +976,8 @@ pub async fn try_upgrade_config_1_1_2<P: AsRef<Path>>(path: P) -> Result<(), Nym
},
},
},
logging: LoggingSettings1_1_3 {},
logging: LoggingSettingsV2 {},
};
cfg.save()?;
Ok(())
Ok(cfg)
}
@@ -2,25 +2,38 @@
// SPDX-License-Identifier: GPL-3.0-only
#![allow(dead_code)]
use crate::config::*;
use crate::{config::*, error::KeyIOFailure};
use entry_gateway::Debug as EntryGatewayConfigDebug;
use exit_gateway::{IpPacketRouter, IpPacketRouterDebug, NetworkRequester, NetworkRequesterDebug};
use mixnode::{Verloc, VerlocDebug};
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 nym_crypto::asymmetric::{ed25519, x25519};
use nym_network_requester::{
set_active_gateway, setup_fs_gateways_storage, store_gateway_details, CustomGatewayDetails,
GatewayDetails,
};
use nym_pemstore::{load_key, store_key, store_keypair};
use nym_sphinx_acknowledgements::AckKey;
use persistence::{
AuthenticatorPaths, EntryGatewayPaths, ExitGatewayPaths, IpPacketRouterPaths, KeysPaths,
MixnodePaths, NetworkRequesterPaths, WireguardPaths,
};
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 struct WireguardPathsV2 {
pub private_diffie_hellman_key_file: PathBuf,
pub public_diffie_hellman_key_file: PathBuf,
}
impl WireguardPaths1_1_3 {
impl WireguardPathsV2 {
pub fn new<P: AsRef<Path>>(data_dir: P) -> Self {
let data_dir = data_dir.as_ref();
WireguardPaths1_1_3 {
WireguardPathsV2 {
private_diffie_hellman_key_file: data_dir
.join(persistence::DEFAULT_X25519_WG_DH_KEY_FILENAME),
public_diffie_hellman_key_file: data_dir
@@ -38,7 +51,7 @@ impl WireguardPaths1_1_3 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Wireguard1_1_3 {
pub struct WireguardV2 {
/// Specifies whether the wireguard service is enabled on this node.
pub enabled: bool,
@@ -59,13 +72,13 @@ pub struct Wireguard1_1_3 {
pub private_network_prefix: u8,
/// Paths for wireguard keys, client registries, etc.
pub storage_paths: WireguardPaths1_1_3,
pub storage_paths: WireguardPathsV2,
}
// 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 {
pub enum NodeModeV2 {
#[default]
#[clap(alias = "mix")]
Mixnode,
@@ -77,11 +90,21 @@ pub enum NodeMode1_1_3 {
ExitGateway,
}
impl From<NodeModeV2> for NodeMode {
fn from(config: NodeModeV2) -> Self {
match config {
NodeModeV2::Mixnode => NodeMode::Mixnode,
NodeModeV2::EntryGateway => NodeMode::EntryGateway,
NodeModeV2::ExitGateway => NodeMode::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 {
pub struct HostV2 {
/// 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.
@@ -100,7 +123,7 @@ pub struct Host1_1_3 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(default)]
#[serde(deny_unknown_fields)]
pub struct MixnetDebug1_1_3 {
pub struct MixnetDebugV2 {
/// Initial value of an exponential backoff to reconnect to dropped TCP connection when
/// forwarding sphinx packets.
#[serde(with = "humantime_serde")]
@@ -122,16 +145,16 @@ pub struct MixnetDebug1_1_3 {
pub unsafe_disable_noise: bool,
}
impl MixnetDebug1_1_3 {
impl MixnetDebugV2 {
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 {
impl Default for MixnetDebugV2 {
fn default() -> Self {
MixnetDebug1_1_3 {
MixnetDebugV2 {
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,
@@ -142,7 +165,7 @@ impl Default for MixnetDebug1_1_3 {
}
}
impl Default for Mixnet1_1_3 {
impl Default for MixnetV2 {
fn default() -> Self {
// SAFETY:
// our hardcoded values should always be valid
@@ -161,7 +184,7 @@ impl Default for Mixnet1_1_3 {
vec![mainnet::NYXD_URL.parse().expect("Invalid default nyxd URL")]
};
Mixnet1_1_3 {
MixnetV2 {
bind_address: SocketAddr::new(inaddr_any(), DEFAULT_MIXNET_PORT),
nym_api_urls,
nyxd_urls,
@@ -173,7 +196,7 @@ impl Default for Mixnet1_1_3 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(default)]
#[serde(deny_unknown_fields)]
pub struct Mixnet1_1_3 {
pub struct MixnetV2 {
/// Address this node will bind to for listening for mixnet packets
/// default: `0.0.0.0:1789`
pub bind_address: SocketAddr,
@@ -185,12 +208,12 @@ pub struct Mixnet1_1_3 {
pub nyxd_urls: Vec<Url>,
#[serde(default)]
pub debug: MixnetDebug1_1_3,
pub debug: MixnetDebugV2,
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct KeysPaths1_1_3 {
pub struct KeysPathsV2 {
/// Path to file containing ed25519 identity private key.
pub private_ed25519_identity_key_file: PathBuf,
@@ -212,8 +235,8 @@ pub struct KeysPaths1_1_3 {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct NymNodePaths1_1_3 {
pub keys: KeysPaths1_1_3,
pub struct NymNodePathsV2 {
pub keys: KeysPathsV2,
/// Path to a file containing basic node description: human-readable name, website, details, etc.
pub description: PathBuf,
@@ -222,7 +245,7 @@ pub struct NymNodePaths1_1_3 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(default)]
#[serde(deny_unknown_fields)]
pub struct Http1_1_3 {
pub struct HttpV2 {
/// Socket address this node will use for binding its http API.
/// default: `0.0.0.0:8080`
pub bind_address: SocketAddr,
@@ -251,9 +274,9 @@ pub struct Http1_1_3 {
pub expose_crypto_hardware: bool,
}
impl Default for Http1_1_3 {
impl Default for HttpV2 {
fn default() -> Self {
Http1_1_3 {
HttpV2 {
bind_address: SocketAddr::new(inaddr_any(), DEFAULT_HTTP_PORT),
landing_page_assets_path: None,
access_token: None,
@@ -266,11 +289,11 @@ impl Default for Http1_1_3 {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct MixnodePaths1_1_3 {}
pub struct MixnodePathsV2 {}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Debug1_1_3 {
pub struct DebugV2 {
/// Delay between each subsequent node statistics being logged to the console
#[serde(with = "humantime_serde")]
pub node_stats_logging_delay: Duration,
@@ -282,7 +305,7 @@ pub struct Debug1_1_3 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct VerlocDebug1_1_3 {
pub struct VerlocDebugV2 {
/// Specifies number of echo packets sent to each node during a measurement run.
pub packets_per_node: usize,
@@ -313,16 +336,16 @@ pub struct VerlocDebug1_1_3 {
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Verloc1_1_3 {
pub struct VerlocV2 {
/// 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,
pub debug: VerlocDebugV2,
}
impl VerlocDebug1_1_3 {
impl VerlocDebugV2 {
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);
@@ -332,9 +355,9 @@ impl VerlocDebug1_1_3 {
const DEFAULT_RETRY_TIMEOUT: Duration = Duration::from_secs(60 * 30);
}
impl Default for VerlocDebug1_1_3 {
impl Default for VerlocDebugV2 {
fn default() -> Self {
VerlocDebug1_1_3 {
VerlocDebugV2 {
packets_per_node: Self::DEFAULT_PACKETS_PER_NODE,
connection_timeout: Self::DEFAULT_CONNECTION_TIMEOUT,
packet_timeout: Self::DEFAULT_PACKET_TIMEOUT,
@@ -348,23 +371,23 @@ impl Default for VerlocDebug1_1_3 {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct MixnodeConfig1_1_3 {
pub storage_paths: MixnodePaths1_1_3,
pub struct MixnodeConfigV2 {
pub storage_paths: MixnodePathsV2,
pub verloc: Verloc1_1_3,
pub verloc: VerlocV2,
#[serde(default)]
pub debug: Debug1_1_3,
pub debug: DebugV2,
}
impl Debug1_1_3 {
impl DebugV2 {
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 {
impl Default for DebugV2 {
fn default() -> Self {
Debug1_1_3 {
DebugV2 {
node_stats_logging_delay: Self::DEFAULT_NODE_STATS_LOGGING_DELAY,
node_stats_updating_delay: Self::DEFAULT_NODE_STATS_UPDATING_DELAY,
}
@@ -373,7 +396,7 @@ impl Default for Debug1_1_3 {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct EntryGatewayPaths1_1_3 {
pub struct EntryGatewayPathsV2 {
/// Path to sqlite database containing all persistent data: messages for offline clients,
/// derived shared keys and available client bandwidths.
pub clients_storage: PathBuf,
@@ -384,18 +407,18 @@ pub struct EntryGatewayPaths1_1_3 {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct EntryGatewayConfigDebug1_1_3 {
pub struct EntryGatewayConfigDebugV2 {
/// 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 {
impl EntryGatewayConfigDebugV2 {
const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100;
}
impl Default for EntryGatewayConfigDebug1_1_3 {
impl Default for EntryGatewayConfigDebugV2 {
fn default() -> Self {
EntryGatewayConfigDebug1_1_3 {
EntryGatewayConfigDebugV2 {
message_retrieval_limit: Self::DEFAULT_MESSAGE_RETRIEVAL_LIMIT,
}
}
@@ -403,8 +426,8 @@ impl Default for EntryGatewayConfigDebug1_1_3 {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct EntryGatewayConfig1_1_3 {
pub storage_paths: EntryGatewayPaths1_1_3,
pub struct EntryGatewayConfigV2 {
pub storage_paths: EntryGatewayPathsV2,
/// Indicates whether this gateway is accepting only coconut credentials for accessing the mixnet
/// or if it also accepts non-paying clients
@@ -426,12 +449,12 @@ pub struct EntryGatewayConfig1_1_3 {
pub announce_wss_port: Option<u16>,
#[serde(default)]
pub debug: EntryGatewayConfigDebug1_1_3,
pub debug: EntryGatewayConfigDebugV2,
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct NetworkRequesterPaths1_1_3 {
pub struct NetworkRequesterPathsV2 {
/// Path to file containing network requester ed25519 identity private key.
pub private_ed25519_identity_key_file: PathBuf,
@@ -461,7 +484,7 @@ pub struct NetworkRequesterPaths1_1_3 {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct IpPacketRouterPaths1_1_3 {
pub struct IpPacketRouterPathsV2 {
/// Path to file containing ip packet router ed25519 identity private key.
pub private_ed25519_identity_key_file: PathBuf,
@@ -491,15 +514,15 @@ pub struct IpPacketRouterPaths1_1_3 {
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ExitGatewayPaths1_1_3 {
pub network_requester: NetworkRequesterPaths1_1_3,
pub struct ExitGatewayPathsV2 {
pub network_requester: NetworkRequesterPathsV2,
pub ip_packet_router: IpPacketRouterPaths1_1_3,
pub ip_packet_router: IpPacketRouterPathsV2,
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct IpPacketRouterDebug1_1_3 {
pub struct IpPacketRouterDebugV2 {
/// 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.
@@ -515,9 +538,9 @@ pub struct IpPacketRouterDebug1_1_3 {
pub client_debug: ClientDebugConfig,
}
impl Default for IpPacketRouterDebug1_1_3 {
impl Default for IpPacketRouterDebugV2 {
fn default() -> Self {
IpPacketRouterDebug1_1_3 {
IpPacketRouterDebugV2 {
enabled: true,
disable_poisson_rate: true,
client_debug: Default::default(),
@@ -526,22 +549,22 @@ impl Default for IpPacketRouterDebug1_1_3 {
}
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
pub struct IpPacketRouter1_1_3 {
pub struct IpPacketRouterV2 {
#[serde(default)]
pub debug: IpPacketRouterDebug1_1_3,
pub debug: IpPacketRouterDebugV2,
}
#[allow(clippy::derivable_impls)]
impl Default for IpPacketRouter1_1_3 {
impl Default for IpPacketRouterV2 {
fn default() -> Self {
IpPacketRouter1_1_3 {
IpPacketRouterV2 {
debug: Default::default(),
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
pub struct NetworkRequesterDebug1_1_3 {
pub struct NetworkRequesterDebugV2 {
/// 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.
@@ -557,9 +580,9 @@ pub struct NetworkRequesterDebug1_1_3 {
pub client_debug: ClientDebugConfig,
}
impl Default for NetworkRequesterDebug1_1_3 {
impl Default for NetworkRequesterDebugV2 {
fn default() -> Self {
NetworkRequesterDebug1_1_3 {
NetworkRequesterDebugV2 {
enabled: true,
disable_poisson_rate: true,
client_debug: Default::default(),
@@ -568,15 +591,15 @@ impl Default for NetworkRequesterDebug1_1_3 {
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
pub struct NetworkRequester1_1_3 {
pub struct NetworkRequesterV2 {
#[serde(default)]
pub debug: NetworkRequesterDebug1_1_3,
pub debug: NetworkRequesterDebugV2,
}
#[allow(clippy::derivable_impls)]
impl Default for NetworkRequester1_1_3 {
impl Default for NetworkRequesterV2 {
fn default() -> Self {
NetworkRequester1_1_3 {
NetworkRequesterV2 {
debug: Default::default(),
}
}
@@ -584,8 +607,8 @@ impl Default for NetworkRequester1_1_3 {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ExitGatewayConfig1_1_3 {
pub storage_paths: ExitGatewayPaths1_1_3,
pub struct ExitGatewayConfigV2 {
pub storage_paths: ExitGatewayPathsV2,
/// specifies whether this exit node should run in 'open-proxy' mode
/// and thus would attempt to resolve **ANY** request it receives.
@@ -594,20 +617,20 @@ pub struct ExitGatewayConfig1_1_3 {
/// 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 network_requester: NetworkRequesterV2,
pub ip_packet_router: IpPacketRouter1_1_3,
pub ip_packet_router: IpPacketRouterV2,
}
#[derive(Debug, Default, Copy, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LoggingSettings1_1_3 {
pub struct LoggingSettingsV2 {
// well, we need to implement something here at some point...
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Config1_1_3 {
pub struct ConfigV2 {
// additional metadata holding on-disk location of this config file
#[serde(skip)]
pub(crate) save_path: Option<PathBuf>,
@@ -617,37 +640,37 @@ pub struct Config1_1_3 {
/// 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 mode: NodeModeV2,
pub host: Host1_1_3,
pub host: HostV2,
pub mixnet: Mixnet1_1_3,
pub mixnet: MixnetV2,
/// Storage paths to persistent nym-node data, such as its long term keys.
pub storage_paths: NymNodePaths1_1_3,
pub storage_paths: NymNodePathsV2,
#[serde(default)]
pub http: Http1_1_3,
pub http: HttpV2,
pub wireguard: Wireguard1_1_3,
pub wireguard: WireguardV2,
pub mixnode: MixnodeConfig1_1_3,
pub mixnode: MixnodeConfigV2,
pub entry_gateway: EntryGatewayConfig1_1_3,
pub entry_gateway: EntryGatewayConfigV2,
pub exit_gateway: ExitGatewayConfig1_1_3,
pub exit_gateway: ExitGatewayConfigV2,
#[serde(default)]
pub logging: LoggingSettings1_1_3,
pub logging: LoggingSettingsV2,
}
impl NymConfigTemplate for Config1_1_3 {
impl NymConfigTemplate for ConfigV2 {
fn template(&self) -> &'static str {
CONFIG_TEMPLATE
}
}
impl Config1_1_3 {
impl ConfigV2 {
pub fn save(&self) -> Result<(), NymNodeError> {
let save_location = self.save_location();
debug!(
@@ -715,7 +738,7 @@ impl Config1_1_3 {
// 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 =
let mut loaded: ConfigV2 =
read_config_from_toml_file(path).map_err(|source| NymNodeError::ConfigLoadFailure {
path: path.to_path_buf(),
source,
@@ -730,37 +753,303 @@ impl Config1_1_3 {
}
}
fn initialise(config: &Wireguard1_1_3) -> std::io::Result<()> {
pub async fn initialise(
paths: &AuthenticatorPaths,
public_key: nym_crypto::asymmetric::identity::PublicKey,
) -> Result<(), NymNodeError> {
let mut rng = OsRng;
let x25519_keys = KeyPair::new(&mut rng);
let ed25519_keys = ed25519::KeyPair::new(&mut rng);
let x25519_keys = x25519::KeyPair::new(&mut rng);
let aes128ctr_key = AckKey::new(&mut rng);
let gateway_details = GatewayDetails::Custom(CustomGatewayDetails::new(public_key)).into();
store_keypair(
&x25519_keys,
&config.storage_paths.x25519_wireguard_storage_paths(),
)?;
store_keypair(&ed25519_keys, &paths.ed25519_identity_storage_paths()).map_err(|e| {
KeyIOFailure::KeyPairStoreFailure {
keys: "ed25519-identity".to_string(),
paths: paths.ed25519_identity_storage_paths(),
err: e,
}
})?;
store_keypair(&x25519_keys, &paths.x25519_diffie_hellman_storage_paths()).map_err(|e| {
KeyIOFailure::KeyPairStoreFailure {
keys: "x25519-dh".to_string(),
paths: paths.x25519_diffie_hellman_storage_paths(),
err: e,
}
})?;
store_key(&aes128ctr_key, &paths.ack_key_file).map_err(|e| KeyIOFailure::KeyStoreFailure {
key: "ack".to_string(),
path: paths.ack_key_file.clone(),
err: e,
})?;
// insert all required information into the gateways store
// (I hate that we have to do it, but that's currently the simplest thing to do)
let storage = setup_fs_gateways_storage(&paths.gateway_registrations).await?;
store_gateway_details(&storage, &gateway_details).await?;
set_active_gateway(&storage, &gateway_details.gateway_id().to_base58_string()).await?;
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)?;
pub async fn try_upgrade_config_v2<P: AsRef<Path>>(
path: P,
prev_config: Option<ConfigV2>,
) -> Result<Config, NymNodeError> {
tracing::debug!("Updating from 1.1.3");
let old_cfg = if let Some(prev_config) = prev_config {
prev_config
} else {
ConfigV2::read_from_path(&path)?
};
let authenticator_paths = AuthenticatorPaths::new(
old_cfg
.exit_gateway
.storage_paths
.ip_packet_router
.private_ed25519_identity_key_file
.parent()
.ok_or(NymNodeError::DataDirDerivationFailure)?,
);
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,
mode: old_cfg.mode.into(),
host: Host {
public_ips: old_cfg.host.public_ips,
hostname: old_cfg.host.hostname,
location: old_cfg.host.location,
},
mixnet: Mixnet {
bind_address: old_cfg.mixnet.bind_address,
nym_api_urls: old_cfg.mixnet.nym_api_urls,
nyxd_urls: old_cfg.mixnet.nyxd_urls,
debug: MixnetDebug {
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: NymNodePaths {
keys: KeysPaths {
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: Http {
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: Wireguard {
enabled: old_cfg.wireguard.enabled,
bind_address: old_cfg.wireguard.bind_address,
private_ip: old_cfg.wireguard.private_ip,
announced_port: old_cfg.wireguard.announced_port,
private_network_prefix: old_cfg.wireguard.private_network_prefix,
storage_paths: WireguardPaths {
private_diffie_hellman_key_file: old_cfg
.wireguard
.storage_paths
.private_diffie_hellman_key_file,
public_diffie_hellman_key_file: old_cfg
.wireguard
.storage_paths
.public_diffie_hellman_key_file,
},
},
mixnode: MixnodeConfig {
storage_paths: MixnodePaths {},
verloc: Verloc {
bind_address: old_cfg.mixnode.verloc.bind_address,
debug: VerlocDebug {
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: mixnode::Debug {
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: EntryGatewayConfig {
storage_paths: EntryGatewayPaths {
clients_storage: old_cfg.entry_gateway.storage_paths.clients_storage,
cosmos_mnemonic: old_cfg.entry_gateway.storage_paths.cosmos_mnemonic,
authenticator: authenticator_paths.clone(),
},
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: EntryGatewayConfigDebug {
message_retrieval_limit: old_cfg.entry_gateway.debug.message_retrieval_limit,
},
},
exit_gateway: ExitGatewayConfig {
storage_paths: ExitGatewayPaths {
network_requester: NetworkRequesterPaths {
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: IpPacketRouterPaths {
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,
},
authenticator: authenticator_paths.clone(),
},
open_proxy: old_cfg.exit_gateway.open_proxy,
upstream_exit_policy_url: old_cfg.exit_gateway.upstream_exit_policy_url,
network_requester: NetworkRequester {
debug: NetworkRequesterDebug {
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: IpPacketRouter {
debug: IpPacketRouterDebug {
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,
},
},
},
authenticator: Default::default(),
logging: LoggingSettings {},
};
cfg.save()?;
let public_key = load_key(
cfg.storage_paths
.keys
.ed25519_identity_storage_paths()
.public_key_path,
)
.map_err(|source| NymNodeError::DescriptionLoadFailure {
path: cfg
.storage_paths
.keys
.ed25519_identity_storage_paths()
.public_key_path,
source,
})?;
Ok(())
initialise(&authenticator_paths, public_key).await?;
Ok(cfg)
}
+3
View File
@@ -149,6 +149,8 @@ pub struct EntryGatewayPaths {
/// Path to file containing cosmos account mnemonic used for zk-nym redemption.
pub cosmos_mnemonic: PathBuf,
pub authenticator: AuthenticatorPaths,
}
impl EntryGatewayPaths {
@@ -156,6 +158,7 @@ impl EntryGatewayPaths {
EntryGatewayPaths {
clients_storage: data_dir.as_ref().join(DEFAULT_CLIENTS_STORAGE_FILENAME),
cosmos_mnemonic: data_dir.as_ref().join(DEFAULT_MNEMONIC_FILENAME),
authenticator: AuthenticatorPaths::new(data_dir),
}
}
+57
View File
@@ -167,6 +167,7 @@ announce_ws_port = {{#if entry_gateway.announce_ws_port }} {{ entry_gateway.anno
# (default: 0 - disabled)
announce_wss_port = {{#if entry_gateway.announce_wss_port }} {{ entry_gateway.announce_wss_port }} {{else}} 0 {{/if}}
[entry_gateway.storage_paths]
# Path to sqlite database containing all persistent data: messages for offline clients,
# derived shared keys and available client bandwidths.
@@ -175,6 +176,32 @@ clients_storage = '{{ entry_gateway.storage_paths.clients_storage }}'
# Path to file containing cosmos account mnemonic used for zk-nym redemption.
cosmos_mnemonic = '{{ entry_gateway.storage_paths.cosmos_mnemonic }}'
[entry_gateway.storage_paths.authenticator]
# Path to file containing authenticator ed25519 identity private key.
private_ed25519_identity_key_file = '{{ entry_gateway.storage_paths.authenticator.private_ed25519_identity_key_file }}'
# Path to file containing authenticator ed25519 identity public key.
public_ed25519_identity_key_file = '{{ entry_gateway.storage_paths.authenticator.public_ed25519_identity_key_file }}'
# Path to file containing authenticator x25519 diffie hellman private key.
private_x25519_diffie_hellman_key_file = '{{ entry_gateway.storage_paths.authenticator.private_x25519_diffie_hellman_key_file }}'
# Path to file containing authenticator x25519 diffie hellman public key.
public_x25519_diffie_hellman_key_file = '{{ entry_gateway.storage_paths.authenticator.public_x25519_diffie_hellman_key_file }}'
# 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.
ack_key_file = '{{ entry_gateway.storage_paths.authenticator.ack_key_file }}'
# Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
reply_surb_database = '{{ entry_gateway.storage_paths.authenticator.reply_surb_database }}'
# 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.
gateway_registrations = '{{ entry_gateway.storage_paths.authenticator.gateway_registrations }}'
##### exit-gateway mode nym-node config options #####
[exit_gateway]
@@ -246,6 +273,36 @@ reply_surb_database = '{{ exit_gateway.storage_paths.ip_packet_router.reply_surb
# Due to how clients are started up, this file has to exist.
gateway_registrations = '{{ exit_gateway.storage_paths.ip_packet_router.gateway_registrations }}'
[exit_gateway.storage_paths.authenticator]
# Path to file containing authenticator ed25519 identity private key.
private_ed25519_identity_key_file = '{{ exit_gateway.storage_paths.authenticator.private_ed25519_identity_key_file }}'
# Path to file containing authenticator ed25519 identity public key.
public_ed25519_identity_key_file = '{{ exit_gateway.storage_paths.authenticator.public_ed25519_identity_key_file }}'
# Path to file containing authenticator x25519 diffie hellman private key.
private_x25519_diffie_hellman_key_file = '{{ exit_gateway.storage_paths.authenticator.private_x25519_diffie_hellman_key_file }}'
# Path to file containing authenticator x25519 diffie hellman public key.
public_x25519_diffie_hellman_key_file = '{{ exit_gateway.storage_paths.authenticator.public_x25519_diffie_hellman_key_file }}'
# 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.
ack_key_file = '{{ exit_gateway.storage_paths.authenticator.ack_key_file }}'
# Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
reply_surb_database = '{{ exit_gateway.storage_paths.authenticator.reply_surb_database }}'
# 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.
gateway_registrations = '{{ exit_gateway.storage_paths.authenticator.gateway_registrations }}'
[authenticator]
# currently empty (there are some debug options one might want to configure)
##### logging configuration options #####
[logging]
+7 -9
View File
@@ -1,8 +1,6 @@
// 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::Config;
use crate::error::NymNodeError;
@@ -10,14 +8,14 @@ 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");
let cfg = try_upgrade_config_v1(path, None).await.ok();
match try_upgrade_config_v2(path, cfg).await {
Ok(cfg) => cfg.save(),
Err(e) => {
tracing::error!("Failed to finish upgrade - {e}");
Err(NymNodeError::FailedUpgrade)
}
}
if try_upgrade_config_1_1_3(path).await.is_ok() {
debug!("Updated from 1.1.3");
}
Ok(())
}
pub async fn try_load_current_config<P: AsRef<Path>>(
+14
View File
@@ -143,6 +143,13 @@ pub enum NymNodeError {
#[error(transparent)]
ExitGatewayFailure(#[from] ExitGatewayError),
// TODO: more granular errors
#[error(transparent)]
ExternalClientCore(#[from] ClientCoreError),
#[error("failed upgrade")]
FailedUpgrade,
}
impl From<nym_mixnode::error::MixnodeError> for NymNodeError {
@@ -172,6 +179,13 @@ pub enum MixnodeError {
#[derive(Debug, Error)]
pub enum EntryGatewayError {
#[error(transparent)]
KeyFailure(#[from] KeyIOFailure),
// TODO: more granular errors
#[error(transparent)]
ExternalClientCore(#[from] ClientCoreError),
#[error("failed to load entry gateway account mnemonic from {}: {source}", path.display())]
MnemonicLoadFailure {
path: PathBuf,
+70 -7
View File
@@ -19,6 +19,7 @@ use nym_network_requester::{
use nym_node::config::entry_gateway::ephemeral_entry_gateway_config;
use nym_node::config::exit_gateway::ephemeral_exit_gateway_config;
use nym_node::config::mixnode::ephemeral_mixnode_config;
use nym_node::config::persistence::AuthenticatorPaths;
use nym_node::config::{
Config, EntryGatewayConfig, ExitGatewayConfig, MixnodeConfig, NodeMode, Wireguard,
};
@@ -202,7 +203,7 @@ impl ExitGatewayData {
config: &ExitGatewayConfig,
public_key: ed25519::PublicKey,
) -> Result<(), ExitGatewayError> {
// generate all the keys for NR and IPR
// generate all the keys for NR, IPR and AUTH
let mut rng = OsRng;
let gateway_details = GatewayDetails::Custom(CustomGatewayDetails::new(public_key)).into();
@@ -328,6 +329,57 @@ pub(crate) struct NymNode {
}
impl NymNode {
fn initialise_client_keys<R: RngCore + CryptoRng>(
rng: &mut R,
typ: &str,
ed25519_paths: nym_pemstore::KeyPairPath,
x25519_paths: nym_pemstore::KeyPairPath,
ack_key_path: &Path,
) -> Result<(), EntryGatewayError> {
let ed25519_keys = ed25519::KeyPair::new(rng);
let x25519_keys = x25519::KeyPair::new(rng);
let aes128ctr_key = AckKey::new(rng);
store_keypair(
&ed25519_keys,
ed25519_paths,
format!("{typ}-ed25519-identity"),
)?;
store_keypair(&x25519_keys, x25519_paths, format!("{typ}-x25519-dh"))?;
store_key(&aes128ctr_key, ack_key_path, format!("{typ}-ack-key"))?;
Ok(())
}
async fn initialise_client_gateway_storage(
storage_path: &Path,
registration: &GatewayRegistration,
) -> Result<(), EntryGatewayError> {
// insert all required information into the gateways store
// (I hate that we have to do it, but that's currently the simplest thing to do)
let storage = setup_fs_gateways_storage(storage_path).await?;
store_gateway_details(&storage, registration).await?;
set_active_gateway(&storage, &registration.gateway_id().to_base58_string()).await?;
Ok(())
}
pub async fn initialise_authenticator<R: RngCore + CryptoRng>(
rng: &mut R,
paths: &AuthenticatorPaths,
registration: &GatewayRegistration,
) -> Result<(), NymNodeError> {
trace!("initialising authenticator keys");
Self::initialise_client_keys(
rng,
"authenticator",
paths.ed25519_identity_storage_paths(),
paths.x25519_diffie_hellman_storage_paths(),
&paths.ack_key_file,
)?;
Self::initialise_client_gateway_storage(&paths.gateway_registrations, registration).await?;
Ok(())
}
pub(crate) async fn initialise(
config: &Config,
custom_mnemonic: Option<Zeroizing<bip39::Mnemonic>>,
@@ -374,6 +426,17 @@ impl NymNode {
ExitGatewayData::initialise(&config.exit_gateway, *ed25519_identity_keys.public_key())
.await?;
// authenticator initialization:
Self::initialise_authenticator(
&mut rng,
&config.entry_gateway.storage_paths.authenticator,
&GatewayDetails::Custom(CustomGatewayDetails::new(
*ed25519_identity_keys.public_key(),
))
.into(),
)
.await?;
// wireguard initialisation
WireguardData::initialise(&config.wireguard)?;
@@ -497,10 +560,10 @@ impl NymNode {
let config =
ephemeral_entry_gateway_config(self.config.clone(), &self.entry_gateway.mnemonic)?;
let mut entry_gateway = Gateway::new_loaded(
config,
None,
None,
None,
config.gateway,
config.nr_opts,
config.ipr_opts,
Some(config.auth_opts),
self.ed25519_identity_keys.clone(),
self.x25519_sphinx_keys.clone(),
self.entry_gateway.client_storage.clone(),
@@ -526,8 +589,8 @@ impl NymNode {
let mut exit_gateway = Gateway::new_loaded(
config.gateway,
Some(config.nr_opts),
Some(config.ipr_opts),
config.nr_opts,
config.ipr_opts,
Some(config.auth_opts),
self.ed25519_identity_keys.clone(),
self.x25519_sphinx_keys.clone(),
@@ -6,7 +6,7 @@ use std::path::Path;
use futures::channel::oneshot;
use ipnetwork::IpNetwork;
use nym_client_core::{HardcodedTopologyProvider, TopologyProvider};
use nym_sdk::mixnet::Recipient;
use nym_sdk::{mixnet::Recipient, GatewayTransceiver};
use nym_task::{TaskClient, TaskHandle};
use nym_wireguard::WireguardGatewayData;
@@ -28,6 +28,7 @@ pub struct Authenticator {
config: Config,
wait_for_gateway: bool,
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send + Sync>>,
wireguard_gateway_data: WireguardGatewayData,
shutdown: Option<TaskClient>,
on_start: Option<oneshot::Sender<OnStartData>>,
@@ -39,6 +40,7 @@ impl Authenticator {
config,
wait_for_gateway: false,
custom_topology_provider: None,
custom_gateway_transceiver: None,
wireguard_gateway_data,
shutdown: None,
on_start: None,
@@ -59,6 +61,12 @@ impl Authenticator {
self
}
#[must_use]
pub fn with_minimum_gateway_performance(mut self, minimum_gateway_performance: u8) -> Self {
self.config.base.debug.topology.minimum_gateway_performance = minimum_gateway_performance;
self
}
#[must_use]
#[allow(unused)]
pub fn with_on_start(mut self, on_start: oneshot::Sender<OnStartData>) -> Self {
@@ -66,6 +74,16 @@ impl Authenticator {
self
}
#[must_use]
#[allow(unused)]
pub fn with_custom_gateway_transceiver(
mut self,
gateway_transceiver: Box<dyn GatewayTransceiver + Send + Sync>,
) -> Self {
self.custom_gateway_transceiver = Some(gateway_transceiver);
self
}
#[must_use]
#[allow(unused)]
pub fn with_custom_topology_provider(
@@ -94,7 +112,7 @@ impl Authenticator {
let mixnet_client = crate::mixnet_client::create_mixnet_client(
&self.config.base,
task_handle.get_handle().named("nym_sdk::MixnetClient"),
None,
self.custom_gateway_transceiver,
self.custom_topology_provider,
self.wait_for_gateway,
&self.config.storage_paths.common_paths,
@@ -3,17 +3,12 @@
use nym_client_core::config::disk_persistence::CommonClientPaths;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
pub const DEFAULT_DESCRIPTION_FILENAME: &str = "description.toml";
use std::path::Path;
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
pub struct AuthenticatorPaths {
#[serde(flatten)]
pub common_paths: CommonClientPaths,
/// Location of the file containing our description
pub authenticator_description: PathBuf,
}
impl AuthenticatorPaths {
@@ -22,7 +17,6 @@ impl AuthenticatorPaths {
Self {
common_paths: CommonClientPaths::new_base(base_dir),
authenticator_description: base_dir.join(DEFAULT_DESCRIPTION_FILENAME),
}
}
}
@@ -71,9 +71,6 @@ allowed_list_location = '{{ storage_paths.allowed_list_location }}'
# Location of the file containing our unknown.list
unknown_list_location = '{{ storage_paths.unknown_list_location }}'
# Path to file containing description of this authenticator.
authenticator_description = '{{ storage_paths.authenticator_description }}'
##### logging configuration options #####