moved LP to nym-node crate
This commit is contained in:
Generated
+7
-4
@@ -4121,10 +4121,11 @@ dependencies = [
|
||||
"nym-credential-verification",
|
||||
"nym-credentials-interface",
|
||||
"nym-crypto",
|
||||
"nym-gateway",
|
||||
"nym-kkt",
|
||||
"nym-kkt-ciphersuite",
|
||||
"nym-lp",
|
||||
"nym-lp-transport",
|
||||
"nym-node",
|
||||
"nym-registration-client",
|
||||
"nym-test-utils",
|
||||
"nym-wireguard",
|
||||
@@ -6392,7 +6393,6 @@ dependencies = [
|
||||
"bincode",
|
||||
"bip39",
|
||||
"bs58",
|
||||
"bytes",
|
||||
"dashmap",
|
||||
"defguard_wireguard_rs",
|
||||
"fastrand",
|
||||
@@ -6412,9 +6412,7 @@ dependencies = [
|
||||
"nym-gateway-storage",
|
||||
"nym-id",
|
||||
"nym-ip-packet-router",
|
||||
"nym-kcp",
|
||||
"nym-lp",
|
||||
"nym-lp-transport",
|
||||
"nym-metrics",
|
||||
"nym-mixnet-client",
|
||||
"nym-network-defaults",
|
||||
@@ -7166,6 +7164,7 @@ dependencies = [
|
||||
"arrayref",
|
||||
"async-trait",
|
||||
"axum 0.7.9",
|
||||
"bincode",
|
||||
"bip39",
|
||||
"blake2 0.8.1",
|
||||
"bloomfilter",
|
||||
@@ -7180,6 +7179,7 @@ dependencies = [
|
||||
"criterion",
|
||||
"csv",
|
||||
"cupid",
|
||||
"dashmap",
|
||||
"futures",
|
||||
"hex",
|
||||
"hkdf",
|
||||
@@ -7199,6 +7199,8 @@ dependencies = [
|
||||
"nym-http-api-common",
|
||||
"nym-ip-packet-router",
|
||||
"nym-kkt",
|
||||
"nym-lp",
|
||||
"nym-lp-transport",
|
||||
"nym-metrics",
|
||||
"nym-mixnet-client",
|
||||
"nym-network-requester",
|
||||
@@ -7208,6 +7210,7 @@ dependencies = [
|
||||
"nym-noise-keys",
|
||||
"nym-nonexhaustive-delayqueue",
|
||||
"nym-pemstore",
|
||||
"nym-registration-common",
|
||||
"nym-sphinx-acknowledgements",
|
||||
"nym-sphinx-addressing",
|
||||
"nym-sphinx-forwarding",
|
||||
|
||||
@@ -119,7 +119,8 @@ sdk-typescript-build:
|
||||
yarn --cwd sdk/typescript/codegen/contract-clients build
|
||||
|
||||
# NOTE: These targets are part of the main workspace (but not as wasm32-unknown-unknown)
|
||||
WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm zknym-lib
|
||||
# WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm zknym-lib
|
||||
WASM_CRATES = nym-client-wasm nym-node-tester-wasm
|
||||
|
||||
sdk-wasm-test:
|
||||
#cargo test $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings
|
||||
|
||||
@@ -78,13 +78,7 @@ nym-authenticator-requests = { workspace = true }
|
||||
nym-client-core = { workspace = true, features = ["cli"] }
|
||||
nym-id = { workspace = true }
|
||||
nym-service-provider-requests-common = { workspace = true }
|
||||
|
||||
# LP dependencies
|
||||
nym-lp = { path = "../common/nym-lp" }
|
||||
nym-lp-transport = { path = "../common/nym-lp-transport" }
|
||||
nym-kcp = { path = "../common/nym-kcp" }
|
||||
nym-registration-common = { path = "../common/registration" }
|
||||
bytes = { workspace = true }
|
||||
|
||||
defguard_wireguard_rs = { workspace = true }
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@ pub struct Config {
|
||||
|
||||
pub upgrade_mode_watcher: UpgradeModeWatcher,
|
||||
|
||||
pub lp: crate::node::lp_listener::LpConfig,
|
||||
|
||||
pub debug: Debug,
|
||||
}
|
||||
|
||||
@@ -26,7 +24,6 @@ impl Config {
|
||||
network_requester: impl Into<NetworkRequester>,
|
||||
ip_packet_router: impl Into<IpPacketRouter>,
|
||||
upgrade_mode_watcher: impl Into<UpgradeModeWatcher>,
|
||||
lp: impl Into<crate::node::lp_listener::LpConfig>,
|
||||
debug: impl Into<Debug>,
|
||||
) -> Self {
|
||||
Config {
|
||||
@@ -34,7 +31,6 @@ impl Config {
|
||||
network_requester: network_requester.into(),
|
||||
ip_packet_router: ip_packet_router.into(),
|
||||
upgrade_mode_watcher: upgrade_mode_watcher.into(),
|
||||
lp: lp.into(),
|
||||
debug: debug.into(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
pub use crate::node::client_handling::websocket::connection_handler::authenticated::RequestHandlingError;
|
||||
use crate::node::internal_service_providers::authenticator::error::AuthenticatorError;
|
||||
use crate::node::lp_listener::error::LpHandlerError;
|
||||
use crate::node::wireguard::GatewayWireguardError;
|
||||
use nym_credential_verification::upgrade_mode::UpgradeModeEnableError;
|
||||
use nym_gateway_stats_storage::error::StatsStorageError;
|
||||
@@ -134,12 +133,6 @@ pub enum GatewayError {
|
||||
#[error("Internal error: {0}")]
|
||||
InternalError(String),
|
||||
|
||||
#[error("Failed to bind listener to {address}: {source}")]
|
||||
ListenerBindFailure {
|
||||
address: String,
|
||||
source: Box<dyn std::error::Error + Send + Sync>,
|
||||
},
|
||||
|
||||
#[error("Failed to parse ip address: {source}")]
|
||||
IpAddrParseError {
|
||||
#[from]
|
||||
@@ -154,9 +147,6 @@ pub enum GatewayError {
|
||||
|
||||
#[error(transparent)]
|
||||
WireguardFailure(#[from] GatewayWireguardError),
|
||||
|
||||
#[error(transparent)]
|
||||
LpFailure(#[from] LpHandlerError),
|
||||
}
|
||||
|
||||
impl From<ClientCoreError> for GatewayError {
|
||||
|
||||
+5
-46
@@ -18,7 +18,6 @@ use nym_credential_verification::upgrade_mode::{
|
||||
};
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_ip_packet_router::IpPacketRouter;
|
||||
use nym_lp::peer::{DHKeyPair, KEMKeys, LpLocalPeer};
|
||||
use nym_mixnet_client::forwarder::MixForwardingSender;
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use nym_network_requester::NRServiceProviderBuilder;
|
||||
@@ -33,14 +32,12 @@ use rand::thread_rng;
|
||||
use std::net::IpAddr;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Semaphore;
|
||||
use tracing::*;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
pub use crate::node::upgrade_mode::watcher::UpgradeModeWatcher;
|
||||
use crate::node::wireguard::{PeerManager, PeerRegistrator};
|
||||
pub use client_handling::active_clients::ActiveClientsStore;
|
||||
pub use lp_listener::LpConfig;
|
||||
pub use nym_credential_verification::upgrade_mode::UpgradeModeCheckRequestSender;
|
||||
pub use nym_gateway_stats_storage::PersistentStatsStorage;
|
||||
pub use nym_gateway_storage::{
|
||||
@@ -48,12 +45,10 @@ pub use nym_gateway_storage::{
|
||||
traits::{BandwidthGatewayStorage, InboxGatewayStorage},
|
||||
GatewayStorage,
|
||||
};
|
||||
use nym_lp::LpSession;
|
||||
pub use nym_sdk::{NymApiTopologyProvider, NymApiTopologyProviderConfig, UserAgent};
|
||||
|
||||
pub(crate) mod client_handling;
|
||||
pub(crate) mod internal_service_providers;
|
||||
pub mod lp_listener;
|
||||
mod stale_data_cleaner;
|
||||
pub mod upgrade_mode;
|
||||
pub mod wireguard;
|
||||
@@ -96,12 +91,6 @@ pub struct GatewayTasksBuilder {
|
||||
/// ed25519 keypair used to assert one's identity.
|
||||
identity_keypair: Arc<ed25519::KeyPair>,
|
||||
|
||||
/// x25519 keypair used within KTT exchange
|
||||
x25519_keypair: Arc<DHKeyPair>,
|
||||
|
||||
/// x25519 (for now, to be changed into MlKem) keypair used for the PSQ derivation
|
||||
kem_psq_keys: KEMKeys,
|
||||
|
||||
storage: GatewayStorage,
|
||||
|
||||
mix_packet_sender: MixForwardingSender,
|
||||
@@ -117,6 +106,8 @@ pub struct GatewayTasksBuilder {
|
||||
shutdown_tracker: ShutdownTracker,
|
||||
|
||||
// populated and cached as necessary
|
||||
use_mock_ecash: bool,
|
||||
|
||||
ecash_manager:
|
||||
Option<Arc<dyn nym_credential_verification::ecash::traits::EcashManager + Send + Sync>>,
|
||||
|
||||
@@ -130,8 +121,6 @@ impl GatewayTasksBuilder {
|
||||
pub fn new(
|
||||
config: Config,
|
||||
identity: Arc<ed25519::KeyPair>,
|
||||
x25519: Arc<DHKeyPair>,
|
||||
kem_psq_keys: KEMKeys,
|
||||
storage: GatewayStorage,
|
||||
mix_packet_sender: MixForwardingSender,
|
||||
metrics_sender: MetricEventsSender,
|
||||
@@ -139,6 +128,7 @@ impl GatewayTasksBuilder {
|
||||
mnemonic: Arc<Zeroizing<bip39::Mnemonic>>,
|
||||
user_agent: UserAgent,
|
||||
upgrade_mode_state: UpgradeModeState,
|
||||
use_mock_ecash: bool,
|
||||
shutdown_tracker: ShutdownTracker,
|
||||
) -> GatewayTasksBuilder {
|
||||
GatewayTasksBuilder {
|
||||
@@ -149,8 +139,6 @@ impl GatewayTasksBuilder {
|
||||
wireguard_data: None,
|
||||
user_agent,
|
||||
identity_keypair: identity,
|
||||
x25519_keypair: x25519,
|
||||
kem_psq_keys,
|
||||
storage,
|
||||
mix_packet_sender,
|
||||
metrics_sender,
|
||||
@@ -158,6 +146,7 @@ impl GatewayTasksBuilder {
|
||||
upgrade_mode_state,
|
||||
mnemonic,
|
||||
shutdown_tracker,
|
||||
use_mock_ecash,
|
||||
ecash_manager: None,
|
||||
wireguard_peers: None,
|
||||
wireguard_networks: None,
|
||||
@@ -236,7 +225,7 @@ impl GatewayTasksBuilder {
|
||||
GatewayError,
|
||||
> {
|
||||
// Check if we should use mock ecash for testing
|
||||
if self.config.lp.debug.use_mock_ecash {
|
||||
if self.use_mock_ecash {
|
||||
warn!("Using MockEcashManager for LP testing (credentials NOT verified)");
|
||||
let mock_manager = MockEcashManager::new(Box::new(self.storage.clone()));
|
||||
return Ok(Arc::new(mock_manager)
|
||||
@@ -345,36 +334,6 @@ impl GatewayTasksBuilder {
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn build_lp_listener(
|
||||
&mut self,
|
||||
peer_registrator: Option<PeerRegistrator>,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
) -> Result<lp_listener::LpListener, GatewayError> {
|
||||
let handler_state = lp_listener::LpHandlerState {
|
||||
ecash_verifier: self.ecash_manager().await?,
|
||||
storage: self.storage.clone(),
|
||||
local_lp_peer: LpLocalPeer::new(
|
||||
LpSession::default_ciphersuite(),
|
||||
self.x25519_keypair.clone(),
|
||||
)
|
||||
.with_kem_keys(self.kem_psq_keys.clone()),
|
||||
metrics: self.metrics.clone(),
|
||||
active_clients_store,
|
||||
peer_registrator,
|
||||
lp_config: self.config.lp,
|
||||
outbound_mix_sender: self.mix_packet_sender.clone(),
|
||||
session_states: Arc::new(dashmap::DashMap::new()),
|
||||
forward_semaphore: Arc::new(Semaphore::new(
|
||||
self.config.lp.debug.max_concurrent_forwards,
|
||||
)),
|
||||
};
|
||||
|
||||
Ok(lp_listener::LpListener::new(
|
||||
handler_state,
|
||||
self.shutdown_tracker.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
fn build_network_requester(
|
||||
&mut self,
|
||||
topology_provider: Box<dyn TopologyProvider + Send + Sync>,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::node::lp_listener::ReceiverIndex;
|
||||
use crate::node::wireguard::new_peer_registration::pending::{
|
||||
PendingRegistration, PendingRegistrationData,
|
||||
};
|
||||
@@ -58,9 +57,10 @@ impl PeerRegistrator {
|
||||
|
||||
pub(super) async fn check_pending_lp_registration(
|
||||
&self,
|
||||
sender: ReceiverIndex,
|
||||
receiver_index: u64,
|
||||
) -> Result<Option<LpRegistrationResponse>, GatewayWireguardError> {
|
||||
let Some(pending_registration) = self.pending_registrations.check_lp(sender).await else {
|
||||
let Some(pending_registration) = self.pending_registrations.check_lp(receiver_index).await
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
@@ -104,7 +104,7 @@ impl PeerRegistrator {
|
||||
|
||||
pub(super) async fn process_fresh_initial_lp_registration(
|
||||
&self,
|
||||
sender: ReceiverIndex,
|
||||
receiver_index: u64,
|
||||
remote_public: PeerPublicKey,
|
||||
psk: Key,
|
||||
) -> Result<LpRegistrationResponse, GatewayWireguardError> {
|
||||
@@ -121,7 +121,7 @@ impl PeerRegistrator {
|
||||
.lp
|
||||
.write()
|
||||
.await
|
||||
.insert(sender, pending);
|
||||
.insert(receiver_index, pending);
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
//! 2. Finalisation request message is received, where credential has to be attached is verified.
|
||||
//! Upon successful completion, pending registration is transformed into a properly inserted peer.
|
||||
|
||||
use crate::node::lp_listener::ReceiverIndex;
|
||||
use crate::node::wireguard::new_peer_registration::pending::{
|
||||
PendingRegistration, PendingRegistrations,
|
||||
};
|
||||
@@ -225,7 +224,7 @@ impl PeerRegistrator {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn on_initial_authenticator_request(
|
||||
pub async fn on_initial_authenticator_request(
|
||||
&mut self,
|
||||
init_message: Box<dyn InitMessage + Send + Sync + 'static>,
|
||||
protocol: Protocol,
|
||||
@@ -262,7 +261,7 @@ impl PeerRegistrator {
|
||||
.await
|
||||
}
|
||||
|
||||
pub(crate) async fn on_final_authenticator_request(
|
||||
pub async fn on_final_authenticator_request(
|
||||
&mut self,
|
||||
final_message: Box<dyn FinalMessage + Send + Sync + 'static>,
|
||||
protocol: Protocol,
|
||||
@@ -307,10 +306,10 @@ impl PeerRegistrator {
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) async fn on_initial_lp_request(
|
||||
pub async fn on_initial_lp_request(
|
||||
&self,
|
||||
init_msg: LpDvpnRegistrationInitialRequest,
|
||||
sender: ReceiverIndex,
|
||||
receiver_index: u64,
|
||||
) -> Result<LpRegistrationResponse, GatewayWireguardError> {
|
||||
let remote_public = init_msg.wg_public_key;
|
||||
let psk = Key::new(init_msg.psk);
|
||||
@@ -318,7 +317,9 @@ impl PeerRegistrator {
|
||||
// 1. check if there's any pending registration already in progress,
|
||||
// if so, return the same data again without additional processing,
|
||||
// but update stored PSK
|
||||
if let Some(pending_registration) = self.check_pending_lp_registration(sender).await? {
|
||||
if let Some(pending_registration) =
|
||||
self.check_pending_lp_registration(receiver_index).await?
|
||||
{
|
||||
self.update_peer_psk(remote_public, psk).await?;
|
||||
return Ok(pending_registration);
|
||||
}
|
||||
@@ -332,19 +333,19 @@ impl PeerRegistrator {
|
||||
}
|
||||
|
||||
// 3. process fresh registration request
|
||||
self.process_fresh_initial_lp_registration(sender, remote_public, psk)
|
||||
self.process_fresh_initial_lp_registration(receiver_index, remote_public, psk)
|
||||
.await
|
||||
}
|
||||
|
||||
pub(crate) async fn on_final_lp_request(
|
||||
pub async fn on_final_lp_request(
|
||||
&self,
|
||||
final_msg: LpDvpnRegistrationFinalisation,
|
||||
sender: ReceiverIndex,
|
||||
receiver_index: u64,
|
||||
) -> Result<LpRegistrationResponse, GatewayWireguardError> {
|
||||
// 1. check if there's any pending registration associated with this peer
|
||||
let pending_data = self
|
||||
.pending_registrations
|
||||
.check_lp(sender)
|
||||
.check_lp(receiver_index)
|
||||
.await
|
||||
.ok_or(GatewayWireguardError::RegistrationNotInProgress)?
|
||||
.clone();
|
||||
@@ -356,7 +357,7 @@ impl PeerRegistrator {
|
||||
.await?;
|
||||
|
||||
// 3 remove pending registration
|
||||
self.pending_registrations.remove_lp(sender).await;
|
||||
self.pending_registrations.remove_lp(receiver_index).await;
|
||||
|
||||
// 4. construct and return the response
|
||||
Ok(pending_data.to_registered_lp_response(self.upgrade_mode_enabled()))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::node::lp_listener::ReceiverIndex;
|
||||
use crate::node::wireguard::new_peer_registration::helpers::{
|
||||
build_final_authenticator_response, build_pending_authenticator_response,
|
||||
};
|
||||
@@ -116,9 +115,8 @@ pub(crate) struct PendingRegistrations {
|
||||
pub(crate) authenticator: Arc<RwLock<HashMap<PeerPublicKey, PendingRegistration>>>,
|
||||
|
||||
/// Registrations in progress received from the LP Listener via the
|
||||
/// [`crate::node::lp_listener::handler::LpConnectionHandler`] and handle through
|
||||
/// [`crate::node::lp_listener::registration::LpHandlerState`]
|
||||
pub(crate) lp: Arc<RwLock<HashMap<ReceiverIndex, PendingRegistration>>>,
|
||||
/// `LpConnectionHandler` and handle through `LpHandlerState`
|
||||
pub(crate) lp: Arc<RwLock<HashMap<u64, PendingRegistration>>>,
|
||||
}
|
||||
|
||||
impl PendingRegistrations {
|
||||
@@ -133,14 +131,11 @@ impl PendingRegistrations {
|
||||
self.authenticator.write().await.remove(peer);
|
||||
}
|
||||
|
||||
pub(crate) async fn remove_lp(&self, receiver_index: ReceiverIndex) {
|
||||
pub(crate) async fn remove_lp(&self, receiver_index: u64) {
|
||||
self.lp.write().await.remove(&receiver_index);
|
||||
}
|
||||
|
||||
pub(crate) async fn check_lp(
|
||||
&self,
|
||||
receiver_index: ReceiverIndex,
|
||||
) -> Option<PendingRegistration> {
|
||||
pub(crate) async fn check_lp(&self, receiver_index: u64) -> Option<PendingRegistration> {
|
||||
self.lp.read().await.get(&receiver_index).cloned()
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ nym-credentials-interface = { path = "../common/credentials-interface" }
|
||||
nym-test-utils = { path = "../common/test-utils" }
|
||||
nym-registration-client = { path = "../nym-registration-client" }
|
||||
nym-lp-transport = { path = "../common/nym-lp-transport", features = ["io-mocks"] }
|
||||
nym-gateway = { path = "../gateway" }
|
||||
nym-node = { path = "../nym-node" }
|
||||
nym-lp = { path = "../common/nym-lp" }
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite"] }
|
||||
tracing = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
|
||||
@@ -9,18 +9,18 @@ mod tests {
|
||||
use nym_credential_verification::upgrade_mode::testing::mock_dummy_upgrade_mode_details;
|
||||
use nym_credentials_interface::TicketType;
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_gateway::node::lp_listener::error::LpHandlerError;
|
||||
use nym_gateway::node::lp_listener::handler::LpConnectionHandler;
|
||||
use nym_gateway::node::lp_listener::{
|
||||
KEMKeys, LpDebug, LpHandlerState, LpLocalPeer, MixForwardingReceiver, PeerControlRequest,
|
||||
WireguardGatewayData, mix_forwarding_channels,
|
||||
};
|
||||
use nym_gateway::node::wireguard::{PeerManager, PeerRegistrator};
|
||||
use nym_gateway::node::{ActiveClientsStore, GatewayStorage, LpConfig};
|
||||
use nym_kkt::key_utils::{
|
||||
generate_keypair_mceliece, generate_keypair_mlkem, generate_lp_keypair_x25519,
|
||||
};
|
||||
use nym_kkt::keys::KEMKeys;
|
||||
use nym_kkt_ciphersuite::Ciphersuite;
|
||||
use nym_lp::peer::LpLocalPeer;
|
||||
use nym_node::config::{LpConfig, LpDebug};
|
||||
use nym_node::node::GatewayStorage;
|
||||
use nym_node::node::lp::error::LpHandlerError;
|
||||
use nym_node::node::lp::handler::LpConnectionHandler;
|
||||
use nym_node::node::lp::{LpHandlerState, MixForwardingReceiver, mix_forwarding_channels};
|
||||
use nym_node::wireguard::{PeerManager, PeerRegistrator};
|
||||
use nym_registration_client::{LpClientError, LpRegistrationClient};
|
||||
use nym_test_utils::helpers::{CryptoRng09, seeded_rng};
|
||||
use nym_test_utils::mocks::async_read_write::MockIOStream;
|
||||
@@ -30,7 +30,7 @@ mod tests {
|
||||
Key, KeyWrapper, MockPeerController, MockPeerControllerState, PeerControlRequestType,
|
||||
RegisteredResponse, mock_peer_controller,
|
||||
};
|
||||
use nym_wireguard::{IpPool, WireguardConfig};
|
||||
use nym_wireguard::{IpPool, PeerControlRequest, WireguardConfig, WireguardGatewayData};
|
||||
use std::mem;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
use std::sync::Arc;
|
||||
@@ -232,19 +232,10 @@ mod tests {
|
||||
);
|
||||
|
||||
let lp_state = LpHandlerState {
|
||||
// use mock instance of ecash verifier
|
||||
ecash_verifier,
|
||||
|
||||
// use in-memory database (no need for persistency)
|
||||
storage,
|
||||
|
||||
local_lp_peer: base.peer.clone(),
|
||||
|
||||
metrics: Default::default(),
|
||||
|
||||
// no clients at the beginning
|
||||
active_clients_store: ActiveClientsStore::new(),
|
||||
|
||||
// use default lp config (with enabled flag)
|
||||
lp_config,
|
||||
|
||||
@@ -570,7 +561,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_basic_lp_exit_registration() -> anyhow::Result<()> {
|
||||
nym_test_utils::helpers::setup_test_logger();
|
||||
// nym_test_utils::helpers::setup_test_logger();
|
||||
|
||||
// TODO: update the test once mceliece works
|
||||
let kem = KEM::MlKem768;
|
||||
|
||||
@@ -13,6 +13,8 @@ license = "GPL-3.0"
|
||||
publish = false
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
async-trait = { workspace = true }
|
||||
@@ -27,6 +29,7 @@ colored = { workspace = true }
|
||||
console-subscriber = { workspace = true, optional = true }
|
||||
csv = { workspace = true }
|
||||
clap = { workspace = true, features = ["cargo", "env"] }
|
||||
dashmap = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
humantime-serde = { workspace = true }
|
||||
@@ -113,6 +116,12 @@ nym-gateway = { path = "../gateway" }
|
||||
nym-network-requester = { path = "../service-providers/network-requester" }
|
||||
nym-ip-packet-router = { path = "../service-providers/ip-packet-router" }
|
||||
|
||||
# LP dependencies
|
||||
nym-lp = { path = "../common/nym-lp" }
|
||||
nym-lp-transport = { path = "../common/nym-lp-transport" }
|
||||
nym-registration-common = { path = "../common/registration" }
|
||||
bincode = { workspace = true }
|
||||
|
||||
|
||||
# throughput tester to recreate lioness
|
||||
# we don't care about particular versions - just pull whatever is used by sphinx
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::helpers::{
|
||||
ConfigArgs, EntryGatewayArgs, ExitGatewayArgs, HostArgs, HttpArgs, MetricsArgs, MixnetArgs,
|
||||
VerlocArgs, WireguardArgs,
|
||||
ConfigArgs, EntryGatewayArgs, ExitGatewayArgs, HostArgs, HttpArgs, LpArgs, MetricsArgs,
|
||||
MixnetArgs, VerlocArgs, WireguardArgs,
|
||||
};
|
||||
use crate::config::persistence::NymNodePaths;
|
||||
use crate::config::{Config, ConfigBuilder, NodeMode, NodeModes};
|
||||
@@ -125,6 +125,9 @@ pub(crate) struct Args {
|
||||
|
||||
#[clap(flatten)]
|
||||
exit_gateway: ExitGatewayArgs,
|
||||
|
||||
#[clap(flatten)]
|
||||
lp: LpArgs,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
@@ -174,6 +177,7 @@ impl Args {
|
||||
.with_metrics(self.metrics.build_config_section())
|
||||
.with_gateway_tasks(self.entry_gateway.build_config_section(&data_dir)?)
|
||||
.with_service_providers(self.exit_gateway.build_config_section(&data_dir))
|
||||
.with_lp(self.lp.build_config_section())
|
||||
.build()
|
||||
}
|
||||
|
||||
@@ -193,6 +197,7 @@ impl Args {
|
||||
config.service_providers = self
|
||||
.exit_gateway
|
||||
.override_config_section(config.service_providers);
|
||||
config.lp = self.lp.override_config_section(config.lp);
|
||||
config
|
||||
}
|
||||
}
|
||||
|
||||
+59
-12
@@ -458,15 +458,6 @@ pub(crate) struct EntryGatewayArgs {
|
||||
)]
|
||||
#[zeroize(skip)]
|
||||
pub(crate) upgrade_mode_attester_public_key: Option<ed25519::PublicKey>,
|
||||
|
||||
/// Use mock ecash manager for LP testing.
|
||||
/// WARNING: Only use this for local testing! Never enable in production.
|
||||
/// When enabled, the LP listener will accept any credential without blockchain verification.
|
||||
#[clap(
|
||||
long,
|
||||
env = NYMNODE_LP_USE_MOCK_ECASH_ARG
|
||||
)]
|
||||
pub(crate) lp_use_mock_ecash: Option<bool>,
|
||||
}
|
||||
|
||||
impl EntryGatewayArgs {
|
||||
@@ -500,9 +491,6 @@ impl EntryGatewayArgs {
|
||||
if let Some(upgrade_mode_attester_public_key) = self.upgrade_mode_attester_public_key {
|
||||
section.upgrade_mode.attester_public_key = upgrade_mode_attester_public_key
|
||||
}
|
||||
if let Some(use_mock_ecash) = self.lp_use_mock_ecash {
|
||||
section.lp.debug.use_mock_ecash = use_mock_ecash
|
||||
}
|
||||
|
||||
section
|
||||
}
|
||||
@@ -549,3 +537,62 @@ impl ExitGatewayArgs {
|
||||
section
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(clap::Args, Debug)]
|
||||
pub(crate) struct LpArgs {
|
||||
/// Bind address for the TCP LP control traffic.
|
||||
/// default: `[::]:41264`
|
||||
#[clap(
|
||||
long,
|
||||
env = NYMNODE_LP_CONTROL_BIND_ADDRESS_ARG
|
||||
)]
|
||||
pub(crate) lp_control_bind_address: Option<SocketAddr>,
|
||||
|
||||
/// Custom announced port for listening for the TCP LP control traffic.
|
||||
/// If unspecified, the value from the `lp_control_bind_address` will be used instead
|
||||
#[clap(
|
||||
long,
|
||||
env = NYMNODE_LP_CONTROL_ANNOUNCE_PORT_ARG
|
||||
)]
|
||||
pub(crate) lp_control_announce_port: Option<u16>,
|
||||
|
||||
/// Bind address for the UDP LP data traffic.
|
||||
/// default: `[::]:51264`
|
||||
#[clap(
|
||||
long,
|
||||
env = NYMNODE_LP_DATA_BIND_ADDRESS_ARG
|
||||
)]
|
||||
pub(crate) lp_data_bind_address: Option<SocketAddr>,
|
||||
|
||||
/// Custom announced port for listening for the UDP LP data traffic.
|
||||
/// If unspecified, the value from the `lp_data_bind_address` will be used instead
|
||||
#[clap(
|
||||
long,
|
||||
env = NYMNODE_LP_DATA_ANNOUNCE_PORT_ARG
|
||||
)]
|
||||
pub(crate) lp_data_announce_port: Option<u16>,
|
||||
|
||||
/// Use mock ecash manager for LP testing.
|
||||
/// WARNING: Only use this for local testing! Never enable in production.
|
||||
/// When enabled, the LP listener will accept any credential without blockchain verification.
|
||||
#[clap(
|
||||
long,
|
||||
env = NYMNODE_LP_USE_MOCK_ECASH_ARG
|
||||
)]
|
||||
pub(crate) lp_use_mock_ecash: Option<bool>,
|
||||
}
|
||||
|
||||
impl LpArgs {
|
||||
// TODO: could we perhaps make a clap error here and call `safe_exit` instead?
|
||||
pub(crate) fn build_config_section(self) -> config::LpConfig {
|
||||
self.override_config_section(config::LpConfig::default())
|
||||
}
|
||||
|
||||
pub(crate) fn override_config_section(self, mut section: config::LpConfig) -> config::LpConfig {
|
||||
if let Some(use_mock_ecash) = self.lp_use_mock_ecash {
|
||||
section.debug.use_mock_ecash = use_mock_ecash
|
||||
}
|
||||
|
||||
section
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,9 +46,6 @@ pub struct GatewayTasksConfig {
|
||||
|
||||
pub upgrade_mode: UpgradeModeWatcher,
|
||||
|
||||
#[serde(default)]
|
||||
pub lp: nym_gateway::node::LpConfig,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: Debug,
|
||||
}
|
||||
@@ -228,7 +225,6 @@ impl GatewayTasksConfig {
|
||||
announce_ws_port: None,
|
||||
announce_wss_port: None,
|
||||
upgrade_mode: UpgradeModeWatcher::new()?,
|
||||
lp: Default::default(),
|
||||
debug: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ fn ephemeral_gateway_config(config: &Config) -> nym_gateway::config::Config {
|
||||
enabled: config.service_providers.network_requester.debug.enabled,
|
||||
},
|
||||
config.gateway_tasks.upgrade_mode.clone(),
|
||||
config.gateway_tasks.lp,
|
||||
nym_gateway::config::Debug {
|
||||
client_bandwidth_max_flushing_rate: config
|
||||
.gateway_tasks
|
||||
@@ -92,8 +91,6 @@ pub struct GatewayTasksConfig {
|
||||
pub auth_opts: Option<LocalAuthenticatorOpts>,
|
||||
#[allow(dead_code)]
|
||||
pub wg_opts: LocalWireguardOpts,
|
||||
#[allow(dead_code)]
|
||||
pub lp: nym_gateway::node::LpConfig,
|
||||
}
|
||||
|
||||
// that function is rather disgusting, but I hope it's not going to live for too long
|
||||
@@ -227,7 +224,6 @@ pub fn gateway_tasks_config(config: &Config) -> GatewayTasksConfig {
|
||||
ipr_opts: Some(ipr_opts),
|
||||
auth_opts: Some(auth_opts),
|
||||
wg_opts,
|
||||
lp: config.gateway_tasks.lp,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use nym_config::serde_helpers::de_maybe_port;
|
||||
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Configuration for LP listener
|
||||
#[derive(Debug, Clone, Copy, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct LpConfig {
|
||||
/// Bind address for the TCP LP control traffic.
|
||||
/// default: `[::]:41264`
|
||||
pub control_bind_address: SocketAddr,
|
||||
|
||||
/// Bind address for the UDP LP data traffic.
|
||||
/// default: `[::]:51264`
|
||||
pub data_bind_address: SocketAddr,
|
||||
|
||||
/// Custom announced port for listening for the TCP LP control traffic.
|
||||
/// If unspecified, the value from the `control_bind_address` will be used instead
|
||||
/// (default: None)
|
||||
#[serde(deserialize_with = "de_maybe_port")]
|
||||
pub announce_control_port: Option<u16>,
|
||||
|
||||
/// Custom announced port for listening for the UDP LP data traffic.
|
||||
/// If unspecified, the value from the `data_bind_address` will be used instead
|
||||
/// (default: None)
|
||||
#[serde(deserialize_with = "de_maybe_port")]
|
||||
pub announce_data_port: Option<u16>,
|
||||
|
||||
/// Auxiliary configuration
|
||||
#[serde(default)]
|
||||
pub debug: LpDebug,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct LpDebug {
|
||||
/// Maximum concurrent connections
|
||||
pub max_connections: usize,
|
||||
|
||||
/// Use mock ecash manager for testing (default: false)
|
||||
///
|
||||
/// When enabled, the LP listener will use a mock ecash verifier that
|
||||
/// accepts any credential without blockchain verification. This is
|
||||
/// useful for testing the LP protocol implementation without requiring
|
||||
/// a full blockchain/contract setup.
|
||||
///
|
||||
/// WARNING: Only use this for local testing! Never enable in production.
|
||||
pub use_mock_ecash: bool,
|
||||
|
||||
/// Maximum age of in-progress handshakes before cleanup (default: 90s)
|
||||
///
|
||||
/// Handshakes should complete quickly (3-5 packets). This TTL accounts for:
|
||||
/// - Network latency and retransmits
|
||||
/// - Slow clients
|
||||
/// - Clock skew tolerance
|
||||
///
|
||||
/// Stale handshakes are removed by the cleanup task to prevent memory leaks.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub handshake_ttl: Duration,
|
||||
|
||||
/// Maximum age of established sessions before cleanup (default: 24h)
|
||||
///
|
||||
/// Sessions can be long-lived for dVPN tunnels. This TTL should be set
|
||||
/// high enough to accommodate expected usage patterns:
|
||||
/// - dVPN sessions: hours to days
|
||||
/// - Registration: minutes
|
||||
///
|
||||
/// Sessions with no activity for this duration are removed by the cleanup task.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub session_ttl: Duration,
|
||||
|
||||
/// How often to run the state cleanup task (default: 5 minutes)
|
||||
///
|
||||
/// The cleanup task scans for and removes stale handshakes and sessions.
|
||||
/// Lower values = more frequent cleanup but higher overhead.
|
||||
/// Higher values = less overhead but slower memory reclamation.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub state_cleanup_interval: Duration,
|
||||
|
||||
/// Maximum concurrent forward connections (default: 1000)
|
||||
///
|
||||
/// Limits simultaneous outbound connections when forwarding LP packets to other gateways
|
||||
/// during telescope setup. This prevents file descriptor exhaustion under high load.
|
||||
///
|
||||
/// When at capacity, new forward requests return an error, signaling the client
|
||||
/// to choose a different gateway.
|
||||
pub max_concurrent_forwards: usize,
|
||||
}
|
||||
|
||||
impl LpConfig {
|
||||
pub const DEFAULT_CONTROL_PORT: u16 = 41264;
|
||||
pub const DEFAULT_DATA_PORT: u16 = 51264;
|
||||
|
||||
pub fn announced_control_port(&self) -> u16 {
|
||||
self.announce_control_port
|
||||
.unwrap_or(self.control_bind_address.port())
|
||||
}
|
||||
|
||||
pub fn announced_data_port(&self) -> u16 {
|
||||
self.announce_data_port
|
||||
.unwrap_or(self.data_bind_address.port())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LpConfig {
|
||||
fn default() -> Self {
|
||||
LpConfig {
|
||||
control_bind_address: SocketAddr::new(
|
||||
IpAddr::V6(Ipv6Addr::UNSPECIFIED),
|
||||
Self::DEFAULT_CONTROL_PORT,
|
||||
),
|
||||
data_bind_address: SocketAddr::new(
|
||||
IpAddr::V6(Ipv6Addr::UNSPECIFIED),
|
||||
Self::DEFAULT_DATA_PORT,
|
||||
),
|
||||
announce_control_port: None,
|
||||
announce_data_port: None,
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LpDebug {
|
||||
pub const DEFAULT_MAX_CONNECTIONS: usize = 10000;
|
||||
|
||||
// 90 seconds - handshakes should complete quickly
|
||||
pub const DEFAULT_HANDSHAKE_TTL: Duration = Duration::from_secs(90);
|
||||
|
||||
// 24 hours - for long-lived dVPN sessions
|
||||
pub const DEFAULT_SESSION_TTL: Duration = Duration::from_secs(86400);
|
||||
|
||||
// 5 minutes - balances memory reclamation with task overhead
|
||||
pub const DEFAULT_STATE_CLEANUP_INTERVAL: Duration = Duration::from_secs(300);
|
||||
|
||||
// Limits concurrent outbound connections to prevent fd exhaustion
|
||||
pub const DEFAULT_MAX_CONCURRENT_FORWARDS: usize = 1000;
|
||||
}
|
||||
|
||||
impl Default for LpDebug {
|
||||
fn default() -> Self {
|
||||
LpDebug {
|
||||
max_connections: Self::DEFAULT_MAX_CONNECTIONS,
|
||||
use_mock_ecash: false,
|
||||
handshake_ttl: Self::DEFAULT_HANDSHAKE_TTL,
|
||||
session_ttl: Self::DEFAULT_SESSION_TTL,
|
||||
state_cleanup_interval: Self::DEFAULT_STATE_CLEANUP_INTERVAL,
|
||||
max_concurrent_forwards: Self::DEFAULT_MAX_CONCURRENT_FORWARDS,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
use crate::config::persistence::{NymNodePaths, ReplayProtectionPaths};
|
||||
use crate::config::template::CONFIG_TEMPLATE;
|
||||
use crate::error::NymNodeError;
|
||||
use crate::node::replay_protection::{bitmap_size, items_in_bloomfilter};
|
||||
use celes::Country;
|
||||
use clap::ValueEnum;
|
||||
use human_repr::HumanCount;
|
||||
@@ -35,6 +36,7 @@ use url::Url;
|
||||
pub mod authenticator;
|
||||
pub mod gateway_tasks;
|
||||
pub mod helpers;
|
||||
pub mod lp;
|
||||
pub mod metrics;
|
||||
mod old_configs;
|
||||
pub mod persistence;
|
||||
@@ -43,9 +45,9 @@ mod template;
|
||||
pub mod upgrade_helpers;
|
||||
|
||||
pub use crate::config::gateway_tasks::GatewayTasksConfig;
|
||||
pub use crate::config::lp::{LpConfig, LpDebug};
|
||||
pub use crate::config::metrics::MetricsConfig;
|
||||
pub use crate::config::service_providers::ServiceProvidersConfig;
|
||||
use crate::node::replay_protection::{bitmap_size, items_in_bloomfilter};
|
||||
|
||||
const DEFAULT_NYMNODES_DIR: &str = "nym-nodes";
|
||||
|
||||
@@ -186,6 +188,8 @@ pub struct ConfigBuilder {
|
||||
|
||||
pub metrics: Option<MetricsConfig>,
|
||||
|
||||
pub lp: Option<LpConfig>,
|
||||
|
||||
pub logging: Option<LoggingSettings>,
|
||||
}
|
||||
|
||||
@@ -205,6 +209,7 @@ impl ConfigBuilder {
|
||||
gateway_tasks: None,
|
||||
service_providers: None,
|
||||
metrics: None,
|
||||
lp: None,
|
||||
logging: None,
|
||||
}
|
||||
}
|
||||
@@ -234,6 +239,11 @@ impl ConfigBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_lp(mut self, section: impl Into<Option<LpConfig>>) -> Self {
|
||||
self.lp = section.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_wireguard(mut self, section: impl Into<Option<Wireguard>>) -> Self {
|
||||
self.wireguard = section.into();
|
||||
self
|
||||
@@ -284,6 +294,7 @@ impl ConfigBuilder {
|
||||
.storage_paths
|
||||
.unwrap_or_else(|| NymNodePaths::new(&self.data_dir)),
|
||||
metrics: self.metrics.unwrap_or_default(),
|
||||
lp: self.lp.unwrap_or_default(),
|
||||
gateway_tasks,
|
||||
service_providers: self
|
||||
.service_providers
|
||||
@@ -323,6 +334,9 @@ pub struct Config {
|
||||
|
||||
pub wireguard: Wireguard,
|
||||
|
||||
#[serde(default)]
|
||||
pub lp: LpConfig,
|
||||
|
||||
#[serde(alias = "entry_gateway")]
|
||||
pub gateway_tasks: GatewayTasksConfig,
|
||||
|
||||
|
||||
@@ -34,8 +34,6 @@ use nym_config::read_config_from_toml_file;
|
||||
use nym_config::serde_helpers::de_maybe_port;
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_crypto::asymmetric::ed25519::serde_helpers::bs58_ed25519_pubkey;
|
||||
use nym_gateway::node::LpConfig;
|
||||
use nym_gateway::node::lp_listener::LpDebug;
|
||||
use nym_kkt::key_utils::{
|
||||
generate_keypair_mceliece, generate_keypair_mlkem, generate_lp_keypair_x25519,
|
||||
};
|
||||
@@ -48,6 +46,7 @@ use std::time::Duration;
|
||||
use tracing::{debug, info, instrument};
|
||||
use url::Url;
|
||||
|
||||
use crate::config::lp::{LpConfig, LpDebug};
|
||||
pub use unchanged_v12_types::*;
|
||||
|
||||
// (while some of those are technically unused, they might be needed in future migrations,
|
||||
@@ -720,6 +719,20 @@ pub async fn try_upgrade_config_v12<P: AsRef<Path>>(
|
||||
.public_diffie_hellman_key_file,
|
||||
},
|
||||
},
|
||||
lp: LpConfig {
|
||||
control_bind_address: old_cfg.gateway_tasks.lp.control_bind_address,
|
||||
data_bind_address: old_cfg.gateway_tasks.lp.data_bind_address,
|
||||
announce_control_port: old_cfg.gateway_tasks.lp.announce_control_port,
|
||||
announce_data_port: old_cfg.gateway_tasks.lp.announce_data_port,
|
||||
debug: LpDebug {
|
||||
max_connections: old_cfg.gateway_tasks.lp.debug.max_connections,
|
||||
use_mock_ecash: old_cfg.gateway_tasks.lp.debug.use_mock_ecash,
|
||||
handshake_ttl: old_cfg.gateway_tasks.lp.debug.handshake_ttl,
|
||||
session_ttl: old_cfg.gateway_tasks.lp.debug.session_ttl,
|
||||
state_cleanup_interval: old_cfg.gateway_tasks.lp.debug.state_cleanup_interval,
|
||||
max_concurrent_forwards: old_cfg.gateway_tasks.lp.debug.max_concurrent_forwards,
|
||||
},
|
||||
},
|
||||
gateway_tasks: GatewayTasksConfig {
|
||||
storage_paths: GatewayTasksPaths {
|
||||
clients_storage: old_cfg.gateway_tasks.storage_paths.clients_storage,
|
||||
@@ -748,20 +761,6 @@ pub async fn try_upgrade_config_v12<P: AsRef<Path>>(
|
||||
.expedited_poll_interval,
|
||||
},
|
||||
},
|
||||
lp: LpConfig {
|
||||
control_bind_address: old_cfg.gateway_tasks.lp.control_bind_address,
|
||||
data_bind_address: old_cfg.gateway_tasks.lp.data_bind_address,
|
||||
announce_control_port: old_cfg.gateway_tasks.lp.announce_control_port,
|
||||
announce_data_port: old_cfg.gateway_tasks.lp.announce_data_port,
|
||||
debug: LpDebug {
|
||||
max_connections: old_cfg.gateway_tasks.lp.debug.max_connections,
|
||||
use_mock_ecash: old_cfg.gateway_tasks.lp.debug.use_mock_ecash,
|
||||
handshake_ttl: old_cfg.gateway_tasks.lp.debug.handshake_ttl,
|
||||
session_ttl: old_cfg.gateway_tasks.lp.debug.session_ttl,
|
||||
state_cleanup_interval: old_cfg.gateway_tasks.lp.debug.state_cleanup_interval,
|
||||
max_concurrent_forwards: old_cfg.gateway_tasks.lp.debug.max_concurrent_forwards,
|
||||
},
|
||||
},
|
||||
debug: gateway_tasks::Debug {
|
||||
message_retrieval_limit: old_cfg.gateway_tasks.debug.message_retrieval_limit,
|
||||
maximum_open_connections: old_cfg.gateway_tasks.debug.maximum_open_connections,
|
||||
|
||||
+7
-1
@@ -66,9 +66,15 @@ pub mod vars {
|
||||
"NYMNODE_UPGRADE_MODE_ATTESTATION_URL";
|
||||
pub const NYMNODE_UPGRADE_MODE_ATTESTER_PUBKEY_ARG: &str =
|
||||
"NYMNODE_UPGRADE_MODE_ATTESTER_PUBKEY";
|
||||
pub const NYMNODE_LP_USE_MOCK_ECASH_ARG: &str = "NYMNODE_LP_USE_MOCK_ECASH";
|
||||
|
||||
// exit gateway:
|
||||
pub const NYMNODE_UPSTREAM_EXIT_POLICY_ARG: &str = "NYMNODE_UPSTREAM_EXIT_POLICY";
|
||||
pub const NYMNODE_OPEN_PROXY_ARG: &str = "NYMNODE_OPEN_PROXY";
|
||||
|
||||
// LP:
|
||||
pub const NYMNODE_LP_CONTROL_BIND_ADDRESS_ARG: &str = "NYMNODE_LP_CONTROL_BIND_ADDRESS";
|
||||
pub const NYMNODE_LP_CONTROL_ANNOUNCE_PORT_ARG: &str = "NYMNODE_LP_CONTROL_ANNOUNCE_PORT";
|
||||
pub const NYMNODE_LP_DATA_BIND_ADDRESS_ARG: &str = "NYMNODE_LP_DATA_BIND_ADDRESS";
|
||||
pub const NYMNODE_LP_DATA_ANNOUNCE_PORT_ARG: &str = "NYMNODE_LP_DATA_ANNOUNCE_PORT";
|
||||
pub const NYMNODE_LP_USE_MOCK_ECASH_ARG: &str = "NYMNODE_LP_USE_MOCK_ECASH";
|
||||
}
|
||||
|
||||
+11
-1
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::node::http::error::NymNodeHttpError;
|
||||
use crate::node::lp::error::LpHandlerError;
|
||||
use crate::wireguard::error::WireguardError;
|
||||
use nym_http_api_client::HttpClientError;
|
||||
use nym_ip_packet_router::error::ClientCoreError;
|
||||
@@ -9,7 +10,7 @@ use nym_kkt::keys::storage_wrappers::MalformedStoredKeyError;
|
||||
use nym_validator_client::ValidatorClientError;
|
||||
use nym_validator_client::nyxd::error::NyxdError;
|
||||
use std::io;
|
||||
use std::net::IpAddr;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::path::PathBuf;
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -235,6 +236,15 @@ pub enum NymNodeError {
|
||||
|
||||
#[error(transparent)]
|
||||
MalformedStoredKey(#[from] MalformedStoredKeyError),
|
||||
|
||||
#[error("failed to bind LP to {address}: {source}")]
|
||||
LpBindFailure {
|
||||
address: SocketAddr,
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error(transparent)]
|
||||
LpFailure(#[from] LpHandlerError),
|
||||
}
|
||||
|
||||
impl From<EntryGatewayError> for NymNodeError {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// allow dead code in the lib imports
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod node;
|
||||
pub mod wireguard;
|
||||
@@ -10,13 +10,13 @@ use nym_bin_common::logging::maybe_print_banner;
|
||||
use nym_config::defaults::setup_env;
|
||||
|
||||
mod cli;
|
||||
pub(crate) mod config;
|
||||
pub mod config;
|
||||
mod env;
|
||||
pub(crate) mod error;
|
||||
pub mod error;
|
||||
mod logging;
|
||||
pub(crate) mod node;
|
||||
pub mod node;
|
||||
pub(crate) mod throughput_tester;
|
||||
pub(crate) mod wireguard;
|
||||
pub mod wireguard;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
// std::env::set_var(
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
//!
|
||||
|
||||
use super::LpHandlerState;
|
||||
use crate::node::lp_listener::error::LpHandlerError;
|
||||
use crate::GatewayError;
|
||||
use crate::error::NymNodeError;
|
||||
use crate::node::lp::error::LpHandlerError;
|
||||
use nym_lp::OuterHeader;
|
||||
use nym_metrics::inc;
|
||||
use std::net::SocketAddr;
|
||||
@@ -48,12 +48,12 @@ impl LpDataHandler {
|
||||
bind_addr: SocketAddr,
|
||||
state: LpHandlerState,
|
||||
shutdown: nym_task::ShutdownToken,
|
||||
) -> Result<Self, GatewayError> {
|
||||
let socket = UdpSocket::bind(bind_addr).await.map_err(|e| {
|
||||
error!("Failed to bind LP data socket to {bind_addr}: {e}");
|
||||
GatewayError::ListenerBindFailure {
|
||||
address: bind_addr.to_string(),
|
||||
source: Box::new(e),
|
||||
) -> Result<Self, NymNodeError> {
|
||||
let socket = UdpSocket::bind(bind_addr).await.map_err(|source| {
|
||||
error!("Failed to bind LP data socket to {bind_addr}: {source}");
|
||||
NymNodeError::LpBindFailure {
|
||||
address: bind_addr,
|
||||
source,
|
||||
}
|
||||
})?;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::node::lp_listener::ReceiverIndex;
|
||||
use crate::node::lp::ReceiverIndex;
|
||||
use nym_lp::state_machine::{LpAction, LpDataKind};
|
||||
use nym_lp::{LpError, MalformedLpPacketError};
|
||||
use nym_lp_transport::LpTransportError;
|
||||
@@ -2,13 +2,13 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use super::{LpHandlerState, ReceiverIndex, TimestampedState};
|
||||
use crate::node::lp_listener::error::LpHandlerError;
|
||||
use crate::node::lp::error::LpHandlerError;
|
||||
use nym_lp::state_machine::{LpAction, LpData, LpDataKind, LpInput};
|
||||
use nym_lp::{
|
||||
EncryptedLpPacket, ExpectedResponseSize, ForwardPacketData, LpSession, LpStateMachine,
|
||||
};
|
||||
use nym_lp_transport::traits::LpTransportChannel;
|
||||
use nym_lp_transport::LpHandshakeChannel;
|
||||
use nym_lp_transport::traits::LpTransportChannel;
|
||||
use nym_metrics::{add_histogram_obs, inc};
|
||||
use nym_registration_common::{LpRegistrationRequest, RegistrationStatus};
|
||||
use std::net::SocketAddr;
|
||||
@@ -305,7 +305,8 @@ where
|
||||
|
||||
debug!(
|
||||
"LP registration request from {remote} (receiver_idx={receiver_idx}): mode={:?}",
|
||||
request.mode());
|
||||
request.mode()
|
||||
);
|
||||
|
||||
self.handle_registration_request(receiver_idx, request)
|
||||
.await
|
||||
@@ -318,7 +319,10 @@ where
|
||||
}
|
||||
typ @ LpDataKind::Opaque => {
|
||||
// Neither registration nor forwarding - unknown payload type
|
||||
warn!("Unknown transport payload type from {remote} (receiver_idx={receiver_idx}). dropping {} bytes", bytes.len());
|
||||
warn!(
|
||||
"Unknown transport payload type from {remote} (receiver_idx={receiver_idx}). dropping {} bytes",
|
||||
bytes.len()
|
||||
);
|
||||
inc!("lp_errors_unknown_payload_type");
|
||||
Err(LpHandlerError::UnexpectedLpPayload { typ })
|
||||
}
|
||||
@@ -420,6 +424,7 @@ where
|
||||
}
|
||||
|
||||
/// Returns reference to the established forwarding channel to the exit.
|
||||
#[allow(dead_code)]
|
||||
pub fn forwarding_channel(&self) -> &Option<(S, SocketAddr)> {
|
||||
&self.exit_stream
|
||||
}
|
||||
@@ -658,10 +663,10 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::node::lp_listener::{LpConfig, LpDebug};
|
||||
use crate::node::ActiveClientsStore;
|
||||
use nym_lp::peer::{generate_keypair_mceliece, generate_keypair_mlkem, KEMKeys, LpLocalPeer};
|
||||
use nym_lp::{sessions_for_tests, Ciphersuite, SessionManager};
|
||||
use crate::config::lp::LpDebug;
|
||||
use crate::node::lp::LpConfig;
|
||||
use nym_lp::peer::{KEMKeys, LpLocalPeer, generate_keypair_mceliece, generate_keypair_mlkem};
|
||||
use nym_lp::{Ciphersuite, SessionManager, sessions_for_tests};
|
||||
use nym_test_utils::helpers::{deterministic_rng, deterministic_rng_09};
|
||||
use std::sync::Arc;
|
||||
// ==================== Test Helpers ====================
|
||||
@@ -673,15 +678,6 @@ mod tests {
|
||||
let mut rng = deterministic_rng();
|
||||
let mut rng09 = deterministic_rng_09();
|
||||
|
||||
// Create in-memory storage for testing
|
||||
let storage = nym_gateway_storage::GatewayStorage::init(":memory:", 100)
|
||||
.await
|
||||
.expect("Failed to create test storage");
|
||||
|
||||
// Create mock ecash manager for testing
|
||||
let ecash_verifier =
|
||||
nym_credential_verification::ecash::MockEcashManager::new(Box::new(storage.clone()));
|
||||
|
||||
let lp_config = LpConfig {
|
||||
debug: LpDebug {
|
||||
..Default::default()
|
||||
@@ -706,12 +702,8 @@ mod tests {
|
||||
|
||||
LpHandlerState {
|
||||
lp_config,
|
||||
ecash_verifier: Arc::new(ecash_verifier)
|
||||
as Arc<dyn nym_credential_verification::ecash::traits::EcashManager + Send + Sync>,
|
||||
storage,
|
||||
local_lp_peer: lp_peer,
|
||||
metrics: nym_node_metrics::NymNodeMetrics::default(),
|
||||
active_clients_store: ActiveClientsStore::new(),
|
||||
outbound_mix_sender: mix_sender,
|
||||
session_states: Arc::new(dashmap::DashMap::new()),
|
||||
peer_registrator: None,
|
||||
@@ -67,28 +67,23 @@
|
||||
// To view metrics, the nym-metrics registry automatically collects all metrics.
|
||||
// They can be exported via Prometheus format using the metrics endpoint.
|
||||
|
||||
use crate::error::GatewayError;
|
||||
use crate::node::wireguard::PeerRegistrator;
|
||||
use crate::node::ActiveClientsStore;
|
||||
use crate::config::lp::LpConfig;
|
||||
use crate::error::NymNodeError;
|
||||
use dashmap::DashMap;
|
||||
use nym_config::serde_helpers::de_maybe_port;
|
||||
use nym_credential_verification::ecash::traits::EcashManager;
|
||||
use nym_gateway_storage::GatewayStorage;
|
||||
use nym_gateway::node::wireguard::PeerRegistrator;
|
||||
use nym_lp::peer::LpLocalPeer;
|
||||
use nym_lp::state_machine::LpStateMachine;
|
||||
use nym_mixnet_client::forwarder::MixForwardingSender;
|
||||
use nym_node_metrics::NymNodeMetrics;
|
||||
use nym_task::ShutdownTracker;
|
||||
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::sync::Semaphore;
|
||||
use tracing::*;
|
||||
|
||||
pub use nym_lp::peer::{DHKeyPair, DHPublicKey, KEMKeys, LpLocalPeer};
|
||||
pub use nym_mixnet_client::forwarder::{
|
||||
mix_forwarding_channels, MixForwardingReceiver, MixForwardingSender,
|
||||
};
|
||||
pub use nym_wireguard::{PeerControlRequest, WireguardGatewayData};
|
||||
pub use nym_mixnet_client::forwarder::{MixForwardingReceiver, mix_forwarding_channels};
|
||||
|
||||
mod data_handler;
|
||||
pub mod error;
|
||||
@@ -97,153 +92,6 @@ mod registration;
|
||||
|
||||
pub type ReceiverIndex = u64;
|
||||
|
||||
/// Configuration for LP listener
|
||||
#[derive(Debug, Clone, Copy, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct LpConfig {
|
||||
/// Bind address for the TCP LP control traffic.
|
||||
/// default: `[::]:41264`
|
||||
pub control_bind_address: SocketAddr,
|
||||
|
||||
/// Bind address for the UDP LP data traffic.
|
||||
/// default: `[::]:51264`
|
||||
pub data_bind_address: SocketAddr,
|
||||
|
||||
/// Custom announced port for listening for the TCP LP control traffic.
|
||||
/// If unspecified, the value from the `control_bind_address` will be used instead
|
||||
/// (default: None)
|
||||
#[serde(deserialize_with = "de_maybe_port")]
|
||||
pub announce_control_port: Option<u16>,
|
||||
|
||||
/// Custom announced port for listening for the UDP LP data traffic.
|
||||
/// If unspecified, the value from the `data_bind_address` will be used instead
|
||||
/// (default: None)
|
||||
#[serde(deserialize_with = "de_maybe_port")]
|
||||
pub announce_data_port: Option<u16>,
|
||||
|
||||
/// Auxiliary configuration
|
||||
#[serde(default)]
|
||||
pub debug: LpDebug,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct LpDebug {
|
||||
/// Maximum concurrent connections
|
||||
pub max_connections: usize,
|
||||
|
||||
/// Use mock ecash manager for testing (default: false)
|
||||
///
|
||||
/// When enabled, the LP listener will use a mock ecash verifier that
|
||||
/// accepts any credential without blockchain verification. This is
|
||||
/// useful for testing the LP protocol implementation without requiring
|
||||
/// a full blockchain/contract setup.
|
||||
///
|
||||
/// WARNING: Only use this for local testing! Never enable in production.
|
||||
pub use_mock_ecash: bool,
|
||||
|
||||
/// Maximum age of in-progress handshakes before cleanup (default: 90s)
|
||||
///
|
||||
/// Handshakes should complete quickly (3-5 packets). This TTL accounts for:
|
||||
/// - Network latency and retransmits
|
||||
/// - Slow clients
|
||||
/// - Clock skew tolerance
|
||||
///
|
||||
/// Stale handshakes are removed by the cleanup task to prevent memory leaks.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub handshake_ttl: Duration,
|
||||
|
||||
/// Maximum age of established sessions before cleanup (default: 24h)
|
||||
///
|
||||
/// Sessions can be long-lived for dVPN tunnels. This TTL should be set
|
||||
/// high enough to accommodate expected usage patterns:
|
||||
/// - dVPN sessions: hours to days
|
||||
/// - Registration: minutes
|
||||
///
|
||||
/// Sessions with no activity for this duration are removed by the cleanup task.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub session_ttl: Duration,
|
||||
|
||||
/// How often to run the state cleanup task (default: 5 minutes)
|
||||
///
|
||||
/// The cleanup task scans for and removes stale handshakes and sessions.
|
||||
/// Lower values = more frequent cleanup but higher overhead.
|
||||
/// Higher values = less overhead but slower memory reclamation.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub state_cleanup_interval: Duration,
|
||||
|
||||
/// Maximum concurrent forward connections (default: 1000)
|
||||
///
|
||||
/// Limits simultaneous outbound connections when forwarding LP packets to other gateways
|
||||
/// during telescope setup. This prevents file descriptor exhaustion under high load.
|
||||
///
|
||||
/// When at capacity, new forward requests return an error, signaling the client
|
||||
/// to choose a different gateway.
|
||||
pub max_concurrent_forwards: usize,
|
||||
}
|
||||
|
||||
impl LpConfig {
|
||||
pub const DEFAULT_CONTROL_PORT: u16 = 41264;
|
||||
pub const DEFAULT_DATA_PORT: u16 = 51264;
|
||||
|
||||
pub fn announced_control_port(&self) -> u16 {
|
||||
self.announce_control_port
|
||||
.unwrap_or(self.control_bind_address.port())
|
||||
}
|
||||
|
||||
pub fn announced_data_port(&self) -> u16 {
|
||||
self.announce_data_port
|
||||
.unwrap_or(self.data_bind_address.port())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LpConfig {
|
||||
fn default() -> Self {
|
||||
LpConfig {
|
||||
control_bind_address: SocketAddr::new(
|
||||
IpAddr::V6(Ipv6Addr::UNSPECIFIED),
|
||||
Self::DEFAULT_CONTROL_PORT,
|
||||
),
|
||||
data_bind_address: SocketAddr::new(
|
||||
IpAddr::V6(Ipv6Addr::UNSPECIFIED),
|
||||
Self::DEFAULT_DATA_PORT,
|
||||
),
|
||||
announce_control_port: None,
|
||||
announce_data_port: None,
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LpDebug {
|
||||
pub const DEFAULT_MAX_CONNECTIONS: usize = 10000;
|
||||
|
||||
// 90 seconds - handshakes should complete quickly
|
||||
pub const DEFAULT_HANDSHAKE_TTL: Duration = Duration::from_secs(90);
|
||||
|
||||
// 24 hours - for long-lived dVPN sessions
|
||||
pub const DEFAULT_SESSION_TTL: Duration = Duration::from_secs(86400);
|
||||
|
||||
// 5 minutes - balances memory reclamation with task overhead
|
||||
pub const DEFAULT_STATE_CLEANUP_INTERVAL: Duration = Duration::from_secs(300);
|
||||
|
||||
// Limits concurrent outbound connections to prevent fd exhaustion
|
||||
pub const DEFAULT_MAX_CONCURRENT_FORWARDS: usize = 1000;
|
||||
}
|
||||
|
||||
impl Default for LpDebug {
|
||||
fn default() -> Self {
|
||||
LpDebug {
|
||||
max_connections: Self::DEFAULT_MAX_CONNECTIONS,
|
||||
use_mock_ecash: false,
|
||||
handshake_ttl: Self::DEFAULT_HANDSHAKE_TTL,
|
||||
session_ttl: Self::DEFAULT_SESSION_TTL,
|
||||
state_cleanup_interval: Self::DEFAULT_STATE_CLEANUP_INTERVAL,
|
||||
max_concurrent_forwards: Self::DEFAULT_MAX_CONCURRENT_FORWARDS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper for state entries with timestamp tracking for cleanup
|
||||
///
|
||||
/// This wrapper adds `created_at` and `last_activity` timestamps to state entries,
|
||||
@@ -289,6 +137,7 @@ impl<T> TimestampedState<T> {
|
||||
}
|
||||
|
||||
/// Get age since creation
|
||||
#[allow(dead_code)]
|
||||
pub fn age(&self) -> Duration {
|
||||
self.created_at.elapsed()
|
||||
}
|
||||
@@ -309,21 +158,12 @@ impl<T> TimestampedState<T> {
|
||||
/// Shared state for LP connection handlers
|
||||
#[derive(Clone)]
|
||||
pub struct LpHandlerState {
|
||||
/// Ecash verifier for bandwidth credentials
|
||||
pub ecash_verifier: Arc<dyn EcashManager + Send + Sync>,
|
||||
|
||||
/// Storage backend for persistence
|
||||
pub storage: GatewayStorage,
|
||||
|
||||
/// Encapsulates all required key information of a local Lewes Protocol Peer.
|
||||
pub local_lp_peer: LpLocalPeer,
|
||||
|
||||
/// Metrics collection
|
||||
pub metrics: NymNodeMetrics,
|
||||
|
||||
/// Active clients tracking
|
||||
pub active_clients_store: ActiveClientsStore,
|
||||
|
||||
/// Handle registering new wireguard peers
|
||||
pub peer_registrator: Option<PeerRegistrator>,
|
||||
|
||||
@@ -334,6 +174,7 @@ pub struct LpHandlerState {
|
||||
///
|
||||
/// Used by the LP data handler (UDP:51264) to forward decrypted Sphinx packets
|
||||
/// from LP clients into the mixnet for routing.
|
||||
#[allow(dead_code)]
|
||||
pub outbound_mix_sender: MixForwardingSender,
|
||||
|
||||
/// Established sessions keyed by session_id
|
||||
@@ -397,16 +238,18 @@ impl LpListener {
|
||||
self.handler_state.lp_config
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) -> Result<(), GatewayError> {
|
||||
pub async fn run(&mut self) -> Result<(), NymNodeError> {
|
||||
let control_bind_address = self.lp_config().control_bind_address;
|
||||
let data_bind_address = self.lp_config().data_bind_address;
|
||||
let listener = TcpListener::bind(control_bind_address).await.map_err(|e| {
|
||||
error!("Failed to bind LP listener to {control_bind_address}: {e}",);
|
||||
GatewayError::ListenerBindFailure {
|
||||
address: control_bind_address.to_string(),
|
||||
source: Box::new(e),
|
||||
}
|
||||
})?;
|
||||
let listener = TcpListener::bind(control_bind_address)
|
||||
.await
|
||||
.map_err(|source| {
|
||||
error!("Failed to bind LP listener to {control_bind_address}: {source}",);
|
||||
NymNodeError::LpBindFailure {
|
||||
address: control_bind_address,
|
||||
source,
|
||||
}
|
||||
})?;
|
||||
|
||||
let shutdown_token = self.shutdown.clone_shutdown_token();
|
||||
|
||||
@@ -489,7 +332,7 @@ impl LpListener {
|
||||
/// The data handler listens on UDP port 51264 and processes LP-wrapped Sphinx packets
|
||||
/// from registered clients. It decrypts the LP layer and forwards the Sphinx packets
|
||||
/// into the mixnet.
|
||||
async fn spawn_data_handler(&self) -> Result<tokio::task::JoinHandle<()>, GatewayError> {
|
||||
async fn spawn_data_handler(&self) -> Result<tokio::task::JoinHandle<()>, NymNodeError> {
|
||||
// Create data handler
|
||||
let data_handler = data_handler::LpDataHandler::new(
|
||||
self.lp_config().data_bind_address,
|
||||
@@ -550,7 +393,8 @@ impl LpListener {
|
||||
}
|
||||
|
||||
pub(crate) mod cleanup_task {
|
||||
use crate::node::lp_listener::{LpDebug, ReceiverIndex, TimestampedState};
|
||||
use crate::config::lp::LpDebug;
|
||||
use crate::node::lp::{ReceiverIndex, TimestampedState};
|
||||
use dashmap::DashMap;
|
||||
use nym_lp::LpStateMachine;
|
||||
use nym_metrics::inc_by;
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::node::lp_listener::{LpHandlerState, ReceiverIndex};
|
||||
use crate::node::lp::{LpHandlerState, ReceiverIndex};
|
||||
use nym_metrics::{add_histogram_obs, inc};
|
||||
use nym_registration_common::dvpn::{
|
||||
LpDvpnRegistrationFinalisation, LpDvpnRegistrationInitialRequest,
|
||||
+50
-17
@@ -22,6 +22,7 @@ use crate::node::http::{HttpServerConfig, NymNodeHttpServer, NymNodeRouter};
|
||||
use crate::node::key_rotation::active_keys::ActiveSphinxKeys;
|
||||
use crate::node::key_rotation::controller::KeyRotationController;
|
||||
use crate::node::key_rotation::manager::SphinxKeyManager;
|
||||
use crate::node::lp::{LpHandlerState, LpListener};
|
||||
use crate::node::metrics::aggregator::MetricsAggregator;
|
||||
use crate::node::metrics::console_logger::ConsoleLogger;
|
||||
use crate::node::metrics::handler::client_sessions::GatewaySessionStatsHandler;
|
||||
@@ -43,12 +44,14 @@ use crate::node::shared_network::{
|
||||
use nym_bin_common::bin_info;
|
||||
use nym_credential_verification::UpgradeModeState;
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_gateway::node::lp_listener::DHKeyPair;
|
||||
use nym_gateway::node::{ActiveClientsStore, GatewayTasksBuilder, UpgradeModeCheckRequestSender};
|
||||
use nym_gateway::node::wireguard::PeerRegistrator;
|
||||
use nym_gateway::node::{GatewayTasksBuilder, UpgradeModeCheckRequestSender};
|
||||
use nym_kkt::key_utils::{
|
||||
generate_keypair_mceliece, generate_keypair_mlkem, generate_lp_keypair_x25519,
|
||||
};
|
||||
use nym_kkt::keys::KEMKeys;
|
||||
use nym_kkt::keys::{DHKeyPair, KEMKeys};
|
||||
use nym_lp::LpSession;
|
||||
use nym_lp::peer::LpLocalPeer;
|
||||
use nym_mixnet_client::client::ActiveConnections;
|
||||
use nym_mixnet_client::forwarder::MixForwardingSender;
|
||||
use nym_network_requester::{
|
||||
@@ -77,15 +80,19 @@ use std::net::SocketAddr;
|
||||
use std::ops::Deref;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::{Semaphore, mpsc};
|
||||
use tracing::{debug, info, trace};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
pub use nym_gateway::node::ActiveClientsStore;
|
||||
pub use nym_gateway::node::GatewayStorage;
|
||||
|
||||
pub mod bonding_information;
|
||||
pub mod description;
|
||||
pub mod helpers;
|
||||
pub(crate) mod http;
|
||||
pub(crate) mod key_rotation;
|
||||
pub mod lp;
|
||||
pub(crate) mod metrics;
|
||||
pub(crate) mod mixnet;
|
||||
mod nym_apis_client;
|
||||
@@ -95,7 +102,7 @@ mod shared_network;
|
||||
|
||||
pub struct GatewayTasksData {
|
||||
mnemonic: Arc<Zeroizing<bip39::Mnemonic>>,
|
||||
client_storage: nym_gateway::node::GatewayStorage,
|
||||
client_storage: GatewayStorage,
|
||||
stats_storage: nym_gateway::node::PersistentStatsStorage,
|
||||
}
|
||||
|
||||
@@ -117,7 +124,7 @@ impl GatewayTasksData {
|
||||
}
|
||||
|
||||
async fn new(config: &GatewayTasksConfig) -> Result<GatewayTasksData, EntryGatewayError> {
|
||||
let client_storage = nym_gateway::node::GatewayStorage::init(
|
||||
let client_storage = GatewayStorage::init(
|
||||
&config.storage_paths.clients_storage,
|
||||
config.debug.message_retrieval_limit,
|
||||
)
|
||||
@@ -378,7 +385,7 @@ impl From<WireguardData> for nym_wireguard::WireguardData {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct NymNode {
|
||||
pub struct NymNode {
|
||||
config: Config,
|
||||
accepted_operator_terms_and_conditions: bool,
|
||||
shutdown_manager: ShutdownManager,
|
||||
@@ -402,6 +409,7 @@ pub(crate) struct NymNode {
|
||||
sphinx_key_manager: Option<SphinxKeyManager>,
|
||||
|
||||
x25519_noise_keys: Arc<x25519::KeyPair>,
|
||||
|
||||
psq_kem_keys: KEMKeys,
|
||||
x25519_lp_keys: Arc<DHKeyPair>,
|
||||
}
|
||||
@@ -478,6 +486,33 @@ impl NymNode {
|
||||
config.save()
|
||||
}
|
||||
|
||||
pub async fn build_lp_listener(
|
||||
&mut self,
|
||||
peer_registrator: Option<PeerRegistrator>,
|
||||
mix_packet_sender: MixForwardingSender,
|
||||
) -> Result<LpListener, NymNodeError> {
|
||||
let handler_state = LpHandlerState {
|
||||
local_lp_peer: LpLocalPeer::new(
|
||||
LpSession::default_ciphersuite(),
|
||||
self.x25519_lp_keys.clone(),
|
||||
)
|
||||
.with_kem_keys(self.psq_kem_keys.clone()),
|
||||
metrics: self.metrics.clone(),
|
||||
peer_registrator,
|
||||
lp_config: self.config.lp,
|
||||
outbound_mix_sender: mix_packet_sender,
|
||||
session_states: Arc::new(dashmap::DashMap::new()),
|
||||
forward_semaphore: Arc::new(Semaphore::new(
|
||||
self.config.lp.debug.max_concurrent_forwards,
|
||||
)),
|
||||
};
|
||||
|
||||
Ok(LpListener::new(
|
||||
handler_state,
|
||||
self.shutdown_manager.shutdown_tracker().clone(),
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) async fn new(config: Config) -> Result<Self, NymNodeError> {
|
||||
let wireguard_data = WireguardData::new(&config.wireguard)?;
|
||||
let current_rotation_id =
|
||||
@@ -670,15 +705,14 @@ impl NymNode {
|
||||
let mut gateway_tasks_builder = GatewayTasksBuilder::new(
|
||||
config.gateway,
|
||||
self.ed25519_identity_keys.clone(),
|
||||
self.x25519_lp_keys.clone(),
|
||||
self.psq_kem_keys.clone(),
|
||||
self.entry_gateway.client_storage.clone(),
|
||||
mix_packet_sender,
|
||||
mix_packet_sender.clone(),
|
||||
metrics_sender,
|
||||
self.metrics.clone(),
|
||||
self.entry_gateway.mnemonic.clone(),
|
||||
Self::user_agent(),
|
||||
self.upgrade_mode_state.clone(),
|
||||
self.config.lp.debug.use_mock_ecash,
|
||||
self.shutdown_tracker().clone(),
|
||||
);
|
||||
|
||||
@@ -736,11 +770,10 @@ impl NymNode {
|
||||
// Start LP listener if enabled
|
||||
info!(
|
||||
"starting the LP listener on {} (data handler on: {})",
|
||||
self.config.gateway_tasks.lp.control_bind_address,
|
||||
self.config.gateway_tasks.lp.data_bind_address,
|
||||
self.config.lp.control_bind_address, self.config.lp.data_bind_address,
|
||||
);
|
||||
let mut lp_listener = gateway_tasks_builder
|
||||
.build_lp_listener(wg_peer_registrator.clone(), active_clients_store.clone())
|
||||
let mut lp_listener = self
|
||||
.build_lp_listener(wg_peer_registrator.clone(), mix_packet_sender)
|
||||
.await?;
|
||||
self.shutdown_tracker()
|
||||
.try_spawn_named(async move { lp_listener.run().await }, "LpListener");
|
||||
@@ -913,8 +946,8 @@ impl NymNode {
|
||||
|
||||
let lewes_protocol = LewesProtocol {
|
||||
enabled: self.modes().entry,
|
||||
control_port: self.config.gateway_tasks.lp.announced_control_port(),
|
||||
data_port: self.config.gateway_tasks.lp.announced_data_port(),
|
||||
control_port: self.config.lp.announced_control_port(),
|
||||
data_port: self.config.lp.announced_data_port(),
|
||||
x25519: self.x25519_lp_keys.pk,
|
||||
kem_keys: self.compute_kem_key_hashes(),
|
||||
};
|
||||
@@ -1371,7 +1404,7 @@ impl NymNode {
|
||||
Ok(self.shutdown_manager)
|
||||
}
|
||||
|
||||
pub(crate) async fn run(mut self) -> Result<(), NymNodeError> {
|
||||
pub async fn run(mut self) -> Result<(), NymNodeError> {
|
||||
let mut shutdown_signals = self.shutdown_manager.detach_shutdown_signals();
|
||||
|
||||
// listen for shutdown signal in case we received it when attempting to spawn all the tasks
|
||||
|
||||
@@ -5,3 +5,6 @@
|
||||
// but let's start putting everything in here
|
||||
|
||||
pub mod error;
|
||||
|
||||
pub use nym_gateway::node::wireguard::{PeerManager, PeerRegistrator};
|
||||
pub use nym_wireguard::{PeerControlRequest, WireguardGatewayData};
|
||||
|
||||
Reference in New Issue
Block a user