Merge remote-tracking branch 'origin' into georgio/lp-psqv2-integration
This commit is contained in:
Generated
+2
-2
@@ -5443,6 +5443,7 @@ dependencies = [
|
||||
"nym-crypto",
|
||||
"nym-ecash-signer-check-types",
|
||||
"nym-ecash-time",
|
||||
"nym-kkt-ciphersuite",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-network-defaults",
|
||||
"nym-node-requests",
|
||||
@@ -6500,6 +6501,7 @@ dependencies = [
|
||||
"nym-http-api-client-macro",
|
||||
"nym-ip-packet-client",
|
||||
"nym-ip-packet-requests",
|
||||
"nym-kkt-ciphersuite",
|
||||
"nym-lp",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-network-defaults",
|
||||
@@ -7551,8 +7553,6 @@ dependencies = [
|
||||
"nym-test-utils",
|
||||
"nym-wireguard-types",
|
||||
"serde",
|
||||
"time",
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
+4
-3
@@ -432,6 +432,7 @@ nym-http-api-client = { version = "1.20.1", path = "common/http-api-client" }
|
||||
nym-http-api-client-macro = { version = "1.20.1", path = "common/http-api-client-macro" }
|
||||
nym-http-api-common = { version = "1.20.1", path = "common/http-api-common", default-features = false }
|
||||
nym-id = { version = "1.20.1", path = "common/nym-id" }
|
||||
nym-kkt-ciphersuite = { path = "common/nym-kkt-ciphersuite" }
|
||||
nym-ip-packet-client = { version = "1.20.1", path = "nym-ip-packet-client" }
|
||||
nym-ip-packet-requests = { version = "1.20.1", path = "common/ip-packet-requests" }
|
||||
nym-metrics = { version = "1.20.1", path = "common/nym-metrics" }
|
||||
@@ -482,9 +483,9 @@ nym-vesting-contract-common = { version = "1.20.1", path = "common/cosmwasm-smar
|
||||
nym-verloc = { version = "1.20.1", path = "common/verloc" }
|
||||
nym-wireguard = { version = "1.20.1", path = "common/wireguard" }
|
||||
nym-wireguard-types = { version = "1.20.1", path = "common/wireguard-types" }
|
||||
nym-wireguard-private-metadata-shared = { version = "1.20.1", path = "common/wireguard-private-metadata/shared" }
|
||||
nym-wireguard-private-metadata-client = { version = "1.20.1", path = "common/wireguard-private-metadata/client" }
|
||||
nym-wireguard-private-metadata-server = { version = "1.20.1", path = "common/wireguard-private-metadata/server" }
|
||||
nym-wireguard-private-metadata-shared = { version = "1.20.1", path = "common/wireguard-private-metadata/shared" }
|
||||
nym-wireguard-private-metadata-client = { version = "1.20.1", path = "common/wireguard-private-metadata/client" }
|
||||
nym-wireguard-private-metadata-server = { version = "1.20.1", path = "common/wireguard-private-metadata/server" }
|
||||
nym-sqlx-pool-guard = { version = "1.2.0", path = "nym-sqlx-pool-guard" }
|
||||
nym-wasm-client-core = { version = "1.20.1", path = "common/wasm/client-core" }
|
||||
nym-wasm-storage = { version = "1.20.1", path = "common/wasm/storage" }
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::error::KKTCiphersuiteError;
|
||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
use strum_macros::EnumIter;
|
||||
use strum_macros::{EnumIter, EnumString};
|
||||
|
||||
pub mod error;
|
||||
|
||||
@@ -47,12 +47,15 @@ pub mod xwing {
|
||||
|
||||
pub type KEMKeyDigests = HashMap<HashFunction, Vec<u8>>;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, IntoPrimitive, TryFromPrimitive, EnumIter)]
|
||||
#[derive(
|
||||
Clone, Copy, PartialEq, Eq, Hash, Debug, IntoPrimitive, TryFromPrimitive, EnumIter, EnumString,
|
||||
)]
|
||||
#[strum(ascii_case_insensitive)]
|
||||
#[repr(u8)]
|
||||
pub enum HashFunction {
|
||||
Blake3 = 0,
|
||||
SHAKE256 = 1,
|
||||
SHAKE128 = 2,
|
||||
Shake256 = 1,
|
||||
Shake128 = 2,
|
||||
SHA256 = 3,
|
||||
}
|
||||
|
||||
@@ -67,8 +70,8 @@ impl HashFunction {
|
||||
hasher.finalize_xof().fill(&mut out);
|
||||
hasher.reset();
|
||||
}
|
||||
HashFunction::SHAKE256 => libcrux_sha3::shake256_ema(&mut out, data.as_ref()),
|
||||
HashFunction::SHAKE128 => libcrux_sha3::shake128_ema(&mut out, data.as_ref()),
|
||||
HashFunction::Shake256 => libcrux_sha3::shake256_ema(&mut out, data.as_ref()),
|
||||
HashFunction::Shake128 => libcrux_sha3::shake128_ema(&mut out, data.as_ref()),
|
||||
HashFunction::SHA256 => libcrux_sha3::sha256_ema(&mut out, data.as_ref()),
|
||||
}
|
||||
|
||||
@@ -80,8 +83,8 @@ impl Display for HashFunction {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(match self {
|
||||
HashFunction::Blake3 => "blake3",
|
||||
HashFunction::SHAKE128 => "shake128",
|
||||
HashFunction::SHAKE256 => "shake256",
|
||||
HashFunction::Shake128 => "shake128",
|
||||
HashFunction::Shake256 => "shake256",
|
||||
HashFunction::SHA256 => "sha256",
|
||||
})
|
||||
}
|
||||
@@ -180,7 +183,10 @@ impl Display for SignatureScheme {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, IntoPrimitive, TryFromPrimitive)]
|
||||
#[derive(
|
||||
Clone, Copy, PartialEq, Eq, Hash, Debug, IntoPrimitive, TryFromPrimitive, EnumIter, EnumString,
|
||||
)]
|
||||
#[strum(ascii_case_insensitive)]
|
||||
#[repr(u8)]
|
||||
pub enum KEM {
|
||||
XWing = 0,
|
||||
@@ -335,3 +341,26 @@ impl Display for Ciphersuite {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::str::FromStr;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
#[test]
|
||||
fn kem_display_consistency() {
|
||||
for kem in KEM::iter() {
|
||||
let display = format!("{kem}");
|
||||
assert_eq!(kem, KEM::from_str(&display).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hash_function_display_consistency() {
|
||||
for hash_fn in HashFunction::iter() {
|
||||
let display = format!("{hash_fn}");
|
||||
assert_eq!(hash_fn, HashFunction::from_str(&display).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ strum = { workspace = true }
|
||||
|
||||
# internal
|
||||
nym-crypto = { path = "../crypto", features = ["asymmetric", "serde"] }
|
||||
nym-kkt-ciphersuite = { path = "../nym-kkt-ciphersuite", features = ["digests"] }
|
||||
nym-kkt-ciphersuite = { workspace = true, features = ["digests"] }
|
||||
|
||||
libcrux-kem = { git = "https://github.com/cryspen/libcrux" }
|
||||
libcrux-ecdh = { git = "https://github.com/cryspen/libcrux", features = ["codec"] }
|
||||
|
||||
@@ -57,8 +57,8 @@ pub fn kkt_benchmark(c: &mut Criterion) {
|
||||
for hash_function in [
|
||||
HashFunction::Blake3,
|
||||
HashFunction::SHA256,
|
||||
HashFunction::SHAKE128,
|
||||
HashFunction::SHAKE256,
|
||||
HashFunction::Shake128,
|
||||
HashFunction::Shake256,
|
||||
] {
|
||||
let ciphersuite = Ciphersuite::resolve_ciphersuite(
|
||||
kem,
|
||||
|
||||
@@ -48,8 +48,8 @@ mod test {
|
||||
for hash_function in [
|
||||
HashFunction::Blake3,
|
||||
HashFunction::SHA256,
|
||||
HashFunction::SHAKE128,
|
||||
HashFunction::SHAKE256,
|
||||
HashFunction::Shake128,
|
||||
HashFunction::Shake256,
|
||||
] {
|
||||
let ciphersuite = Ciphersuite::resolve_ciphersuite(
|
||||
kem,
|
||||
@@ -250,8 +250,8 @@ mod test {
|
||||
for hash_function in [
|
||||
HashFunction::Blake3,
|
||||
HashFunction::SHA256,
|
||||
HashFunction::SHAKE128,
|
||||
HashFunction::SHAKE256,
|
||||
HashFunction::Shake128,
|
||||
HashFunction::Shake256,
|
||||
] {
|
||||
let ciphersuite = Ciphersuite::resolve_ciphersuite(
|
||||
kem,
|
||||
|
||||
@@ -15,7 +15,6 @@ workspace = true
|
||||
[dependencies]
|
||||
bincode = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
tokio-util.workspace = true
|
||||
|
||||
nym-authenticator-requests = { workspace = true }
|
||||
nym-credentials-interface = { workspace = true }
|
||||
@@ -23,9 +22,8 @@ nym-crypto = { workspace = true }
|
||||
nym-ip-packet-requests = { workspace = true }
|
||||
nym-sphinx = { workspace = true }
|
||||
nym-wireguard-types = { workspace = true }
|
||||
nym-kkt-ciphersuite = { path = "../nym-kkt-ciphersuite" }
|
||||
nym-kkt-ciphersuite = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
bincode.workspace = true
|
||||
time.workspace = true
|
||||
nym-test-utils = { workspace = true }
|
||||
|
||||
@@ -1,47 +1,49 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_authenticator_requests::AuthenticatorVersion;
|
||||
use nym_crypto::asymmetric::x25519::serde_helpers::bs58_x25519_pubkey;
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_ip_packet_requests::IpPair;
|
||||
use nym_kkt_ciphersuite::{KEM, KEMKeyDigests};
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
|
||||
use nym_authenticator_requests::AuthenticatorVersion;
|
||||
use nym_crypto::asymmetric::x25519::{PublicKey, serde_helpers::bs58_x25519_pubkey};
|
||||
use nym_ip_packet_requests::IpPair;
|
||||
use nym_sphinx::addressing::{NodeIdentity, Recipient};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
mod lp_messages;
|
||||
mod serialisation;
|
||||
|
||||
pub use lp_messages::{
|
||||
LpDvpnRegistrationRequest, LpMixnetGatewayData, LpMixnetRegistrationRequest,
|
||||
LpRegistrationData, LpRegistrationRequest, LpRegistrationResponse, RegistrationMode,
|
||||
};
|
||||
use nym_kkt_ciphersuite::{KEM, KEMKeyDigests};
|
||||
pub use serialisation::BincodeError;
|
||||
|
||||
mod lp_messages;
|
||||
mod serialisation;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NymNode {
|
||||
pub identity: NodeIdentity,
|
||||
pub struct NymNodeInformation {
|
||||
pub identity: ed25519::PublicKey,
|
||||
pub ip_address: IpAddr,
|
||||
pub ipr_address: Option<Recipient>,
|
||||
pub authenticator_address: Option<Recipient>,
|
||||
pub lp_data: Option<LpData>,
|
||||
pub lp_data: Option<NymNodeLPInformation>,
|
||||
pub version: AuthenticatorVersion,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct GatewayData {
|
||||
pub struct WireguardConfiguration {
|
||||
#[serde(with = "bs58_x25519_pubkey")]
|
||||
pub public_key: PublicKey,
|
||||
pub public_key: x25519::PublicKey,
|
||||
pub endpoint: SocketAddr,
|
||||
pub private_ipv4: Ipv4Addr,
|
||||
pub private_ipv6: Ipv6Addr,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct LpData {
|
||||
pub struct NymNodeLPInformation {
|
||||
pub address: SocketAddr,
|
||||
pub expected_kem_key_hashes: HashMap<KEM, KEMKeyDigests>,
|
||||
pub x25519: x25519::PublicKey,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
//! LP (Lewes Protocol) registration message types shared between client and gateway.
|
||||
|
||||
use crate::GatewayData;
|
||||
use crate::WireguardConfiguration;
|
||||
use crate::serialisation::{BincodeError, BincodeOptions, lp_bincode_serializer};
|
||||
use nym_credentials_interface::{CredentialSpendingData, TicketType};
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
@@ -94,7 +94,7 @@ pub struct LpRegistrationResponse {
|
||||
|
||||
/// Gateway configuration data for dVPN mode (WireGuard)
|
||||
/// This matches what WireguardRegistrationResult expects
|
||||
pub gateway_data: Option<GatewayData>,
|
||||
pub gateway_data: Option<WireguardConfiguration>,
|
||||
|
||||
/// Gateway data for mixnet mode
|
||||
///
|
||||
@@ -152,7 +152,7 @@ impl LpRegistrationRequest {
|
||||
|
||||
impl LpRegistrationResponse {
|
||||
/// Create a success response with GatewayData (for dVPN mode)
|
||||
pub fn success(allocated_bandwidth: i64, gateway_data: GatewayData) -> Self {
|
||||
pub fn success(allocated_bandwidth: i64, gateway_data: WireguardConfiguration) -> Self {
|
||||
Self {
|
||||
success: true,
|
||||
error: None,
|
||||
@@ -202,10 +202,10 @@ mod tests {
|
||||
use std::net::Ipv4Addr;
|
||||
// ==================== Helper Functions ====================
|
||||
|
||||
fn create_test_gateway_data() -> GatewayData {
|
||||
fn create_test_gateway_data() -> WireguardConfiguration {
|
||||
use std::net::Ipv6Addr;
|
||||
|
||||
GatewayData {
|
||||
WireguardConfiguration {
|
||||
public_key: nym_crypto::asymmetric::x25519::PublicKey::from(
|
||||
nym_sphinx::PublicKey::from([1u8; 32]),
|
||||
),
|
||||
|
||||
@@ -18,8 +18,8 @@ use nym_gateway_storage::models::PersistedBandwidth;
|
||||
use nym_gateway_storage::traits::BandwidthGatewayStorage;
|
||||
use nym_metrics::{add_histogram_obs, inc, inc_by};
|
||||
use nym_registration_common::{
|
||||
GatewayData, LpDvpnRegistrationRequest, LpMixnetGatewayData, LpMixnetRegistrationRequest,
|
||||
LpRegistrationData, LpRegistrationRequest, LpRegistrationResponse,
|
||||
LpDvpnRegistrationRequest, LpMixnetGatewayData, LpMixnetRegistrationRequest,
|
||||
LpRegistrationData, LpRegistrationRequest, LpRegistrationResponse, WireguardConfiguration,
|
||||
};
|
||||
use nym_wireguard::PeerControlRequest;
|
||||
use std::sync::Arc;
|
||||
@@ -185,7 +185,7 @@ async fn check_existing_registration(
|
||||
|
||||
Some(LpRegistrationResponse::success(
|
||||
bandwidth,
|
||||
GatewayData {
|
||||
WireguardConfiguration {
|
||||
public_key: *wg_data.keypair().public_key(),
|
||||
endpoint: wg_data.config().bind_address,
|
||||
private_ipv4,
|
||||
@@ -350,7 +350,7 @@ async fn register_wg_peer(
|
||||
public_key_bytes: &[u8],
|
||||
ticket_type: nym_credentials_interface::TicketType,
|
||||
state: &LpHandlerState,
|
||||
) -> Result<(GatewayData, i64), GatewayError> {
|
||||
) -> Result<(WireguardConfiguration, i64), GatewayError> {
|
||||
let Some(wg_controller) = &state.wg_peer_controller else {
|
||||
return Err(GatewayError::ServiceProviderNotRunning {
|
||||
service: "WireGuard".to_string(),
|
||||
@@ -467,7 +467,7 @@ async fn register_wg_peer(
|
||||
|
||||
// Create GatewayData response (matching authenticator response format)
|
||||
Ok((
|
||||
GatewayData {
|
||||
WireguardConfiguration {
|
||||
public_key: gateway_pubkey,
|
||||
endpoint: gateway_endpoint,
|
||||
private_ipv4: client_ipv4,
|
||||
|
||||
+10
-12
@@ -93,6 +93,9 @@ 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<x25519::KeyPair>,
|
||||
|
||||
/// x25519 (for now, to be changed into MlKem) keypair used for the PSQ derivation
|
||||
kem_psq_keys: Arc<x25519::KeyPair>,
|
||||
|
||||
@@ -124,6 +127,7 @@ impl GatewayTasksBuilder {
|
||||
pub fn new(
|
||||
config: Config,
|
||||
identity: Arc<ed25519::KeyPair>,
|
||||
x25519: Arc<x25519::KeyPair>,
|
||||
kem_psq_keys: Arc<x25519::KeyPair>,
|
||||
storage: GatewayStorage,
|
||||
mix_packet_sender: MixForwardingSender,
|
||||
@@ -142,6 +146,7 @@ impl GatewayTasksBuilder {
|
||||
wireguard_data: None,
|
||||
user_agent,
|
||||
identity_keypair: identity,
|
||||
x25519_keypair: x25519,
|
||||
kem_psq_keys,
|
||||
storage,
|
||||
mix_packet_sender,
|
||||
@@ -331,21 +336,14 @@ impl GatewayTasksBuilder {
|
||||
.as_ref()
|
||||
.map(|wg_data| wg_data.inner.peer_tx().clone());
|
||||
|
||||
// We use standard RFC 7748 conversion to derive X25519 keys from Ed25519 identity keys.
|
||||
// This allows callers to provide only Ed25519 keys (which they already have for signing/identity)
|
||||
// without needing to manage separate X25519 keypairs.
|
||||
//
|
||||
// Security: Ed25519→X25519 conversion is cryptographically sound (RFC 7748).
|
||||
// The derived X25519 keys are used for:
|
||||
// - Noise protocol ephemeral DH
|
||||
// - PSQ ECDH baseline security (pre-quantum)
|
||||
let x25519_keys = Arc::new(self.identity_keypair.to_x25519());
|
||||
|
||||
let handler_state = lp_listener::LpHandlerState {
|
||||
ecash_verifier: self.ecash_manager().await?,
|
||||
storage: self.storage.clone(),
|
||||
local_lp_peer: LpLocalPeer::new(self.identity_keypair.clone(), x25519_keys)
|
||||
.with_kem_psq_key(self.kem_psq_keys.clone()),
|
||||
local_lp_peer: LpLocalPeer::new(
|
||||
self.identity_keypair.clone(),
|
||||
self.x25519_keypair.clone(),
|
||||
)
|
||||
.with_kem_psq_key(self.kem_psq_keys.clone()),
|
||||
metrics: self.metrics.clone(),
|
||||
active_clients_store,
|
||||
wg_peer_controller,
|
||||
|
||||
@@ -392,7 +392,6 @@ mod tests {
|
||||
client_data.base.peer.ed25519().clone(),
|
||||
entry.base.peer.as_remote(),
|
||||
entry.base.socket_addr,
|
||||
client_data.base.socket_addr.ip(),
|
||||
);
|
||||
|
||||
// 1. establish mock connection between client and gateway and retrieve gateway's handle
|
||||
@@ -483,7 +482,6 @@ mod tests {
|
||||
client_data.base.peer.ed25519().clone(),
|
||||
entry.base.peer.as_remote(),
|
||||
entry.base.socket_addr,
|
||||
client_data.base.socket_addr.ip(),
|
||||
);
|
||||
|
||||
// 1. establish mock connection between client and gateway and retrieve gateway's handle
|
||||
@@ -544,7 +542,6 @@ mod tests {
|
||||
client_data.base.peer.ed25519().clone(),
|
||||
entry.base.peer.as_remote(),
|
||||
entry.base.socket_addr,
|
||||
client_data.base.socket_addr.ip(),
|
||||
);
|
||||
|
||||
// START: ENTRY SETUP
|
||||
|
||||
@@ -49,7 +49,7 @@ nym-noise-keys = { workspace = true }
|
||||
nym-network-defaults = { workspace = true }
|
||||
nym-ticketbooks-merkle = { workspace = true }
|
||||
nym-ecash-signer-check-types = { workspace = true }
|
||||
|
||||
nym-kkt-ciphersuite = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rand_chacha = { workspace = true }
|
||||
|
||||
@@ -8,6 +8,7 @@ use celes::Country;
|
||||
use nym_crypto::asymmetric::ed25519::serde_helpers::bs58_ed25519_pubkey;
|
||||
use nym_crypto::asymmetric::x25519::serde_helpers::bs58_x25519_pubkey;
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_kkt_ciphersuite::{HashFunction, KEM};
|
||||
use nym_network_defaults::{WG_METADATA_PORT, WG_TUNNEL_PORT};
|
||||
use nym_noise_keys::VersionedNoiseKeyV1;
|
||||
use schemars::JsonSchema;
|
||||
@@ -424,3 +425,25 @@ impl From<nym_node_requests::api::v1::lewes_protocol::models::LPHashFunction> fo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LPKEM> for KEM {
|
||||
fn from(value: LPKEM) -> Self {
|
||||
match value {
|
||||
LPKEM::MlKem768 => KEM::MlKem768,
|
||||
LPKEM::XWing => KEM::XWing,
|
||||
LPKEM::X25519 => KEM::X25519,
|
||||
LPKEM::McEliece => KEM::McEliece,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LPHashFunction> for HashFunction {
|
||||
fn from(value: LPHashFunction) -> Self {
|
||||
match value {
|
||||
LPHashFunction::Blake3 => HashFunction::Blake3,
|
||||
LPHashFunction::Shake128 => HashFunction::Shake128,
|
||||
LPHashFunction::Shake256 => HashFunction::Shake256,
|
||||
LPHashFunction::Sha256 => HashFunction::SHA256,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use nym_authenticator_requests::client_message::QueryMessageImpl;
|
||||
use nym_bandwidth_controller::{BandwidthTicketProvider, DEFAULT_TICKETS_TO_SPEND};
|
||||
use nym_crypto::asymmetric::x25519::KeyPair;
|
||||
use nym_registration_common::GatewayData;
|
||||
use nym_registration_common::WireguardConfiguration;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
@@ -261,7 +261,7 @@ impl AuthenticatorClient {
|
||||
&mut self,
|
||||
controller: &dyn BandwidthTicketProvider,
|
||||
ticketbook_type: TicketType,
|
||||
) -> std::result::Result<GatewayData, RegistrationError> {
|
||||
) -> std::result::Result<WireguardConfiguration, RegistrationError> {
|
||||
debug!("Registering with the wg gateway...");
|
||||
let pub_key = self.peer_public_key();
|
||||
|
||||
@@ -348,7 +348,7 @@ impl AuthenticatorClient {
|
||||
&self.ip_addr, ®istered_data
|
||||
);
|
||||
|
||||
let gateway_data = GatewayData {
|
||||
let gateway_data = WireguardConfiguration {
|
||||
public_key: registered_data.pub_key().inner().into(),
|
||||
endpoint: SocketAddr::new(self.ip_addr, registered_data.wg_port()),
|
||||
private_ipv4: registered_data.private_ips().ipv4,
|
||||
|
||||
@@ -65,6 +65,8 @@ nym-node-status-client = { path = "../nym-node-status-api/nym-node-status-client
|
||||
nym-node-requests = { path = "../nym-node/nym-node-requests" }
|
||||
nym-registration-client = { path = "../nym-registration-client" }
|
||||
nym-lp = { path = "../common/nym-lp" }
|
||||
nym-kkt-ciphersuite = { workspace = true }
|
||||
|
||||
nym-mixnet-contract-common = { path = "../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
nym-network-defaults = { path = "../common/network-defaults" }
|
||||
nym-registration-common = { path = "../common/registration" }
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use std::{
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use crate::types::Entry;
|
||||
use anyhow::{Context, bail};
|
||||
use anyhow::bail;
|
||||
use base64::{Engine as _, engine::general_purpose};
|
||||
use bytes::BytesMut;
|
||||
use clap::Args;
|
||||
@@ -39,7 +33,14 @@ use nym_sdk::mixnet::{
|
||||
NodeIdentity, Recipient, ReconstructedMessage, StoragePaths,
|
||||
};
|
||||
use rand::rngs::OsRng;
|
||||
use std::collections::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::PathBuf;
|
||||
use std::{
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_util::{codec::Decoder, sync::CancellationToken};
|
||||
use tracing::*;
|
||||
@@ -62,8 +63,11 @@ mod types;
|
||||
use crate::bandwidth_helpers::{acquire_bandwidth, import_bandwidth};
|
||||
use crate::nodes::{DirectoryNode, NymApiDirectory};
|
||||
pub use mode::TestMode;
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_kkt_ciphersuite::{KEM, KEMKeyDigests};
|
||||
use nym_lp::peer::LpRemotePeer;
|
||||
use nym_node_status_client::models::AttachedTicketMaterials;
|
||||
use nym_registration_client::{LpRegistrationClient, NestedLpSession};
|
||||
pub use types::{IpPingReplies, ProbeOutcome, ProbeResult};
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
@@ -156,17 +160,23 @@ pub struct TestedNodeDetails {
|
||||
authenticator_address: Option<Recipient>,
|
||||
authenticator_version: AuthenticatorVersion,
|
||||
ip_address: Option<IpAddr>,
|
||||
lp_address: Option<std::net::SocketAddr>,
|
||||
lp_data: Option<TestedNodeLpDetails>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TestedNodeLpDetails {
|
||||
pub address: SocketAddr,
|
||||
pub expected_kem_key_hashes: HashMap<KEM, KEMKeyDigests>,
|
||||
pub x25519: x25519::PublicKey,
|
||||
}
|
||||
|
||||
impl TestedNodeDetails {
|
||||
/// Create from CLI args (localnet mode - no HTTP query needed)
|
||||
/// Only identity and LP address are required; other fields are None/default.
|
||||
pub fn from_cli(identity: NodeIdentity, lp_address: std::net::SocketAddr) -> Self {
|
||||
pub fn from_cli(identity: NodeIdentity, lp_data: TestedNodeLpDetails) -> Self {
|
||||
Self {
|
||||
identity,
|
||||
ip_address: Some(lp_address.ip()),
|
||||
lp_address: Some(lp_address),
|
||||
ip_address: Some(lp_data.address.ip()),
|
||||
lp_data: Some(lp_data),
|
||||
// These are None in localnet mode - only needed for mixnet/authenticator
|
||||
exit_router_address: None,
|
||||
authenticator_address: None,
|
||||
@@ -176,7 +186,7 @@ impl TestedNodeDetails {
|
||||
|
||||
/// Check if this node has sufficient info for LP testing
|
||||
pub fn can_test_lp(&self) -> bool {
|
||||
self.lp_address.is_some()
|
||||
self.lp_data.is_some()
|
||||
}
|
||||
|
||||
/// Check if this node has sufficient info for mixnet testing
|
||||
@@ -577,11 +587,8 @@ impl Probe {
|
||||
}
|
||||
|
||||
// Check if node has LP address
|
||||
let (lp_address, ip_address) = match (node_info.lp_address, node_info.ip_address) {
|
||||
(Some(lp_addr), Some(ip_addr)) => (lp_addr, ip_addr),
|
||||
_ => {
|
||||
bail!("Gateway does not have LP address configured");
|
||||
}
|
||||
let Some(lp_data) = node_info.lp_data else {
|
||||
bail!("Gateway does not have LP data configured");
|
||||
};
|
||||
|
||||
info!("Testing LP registration for gateway {}", node_info.identity);
|
||||
@@ -597,15 +604,10 @@ impl Probe {
|
||||
);
|
||||
|
||||
// Run LP registration probe
|
||||
let lp_outcome = lp_registration_probe(
|
||||
node_info.identity,
|
||||
lp_address,
|
||||
ip_address,
|
||||
&bw_controller,
|
||||
use_mock_ecash,
|
||||
)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
let lp_outcome =
|
||||
lp_registration_probe(node_info.identity, lp_data, &bw_controller, use_mock_ecash)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
// Return result with only LP outcome
|
||||
Ok(ProbeResult {
|
||||
@@ -925,10 +927,8 @@ impl Probe {
|
||||
};
|
||||
|
||||
// Test LP registration if node has LP address
|
||||
let lp_outcome = if let (Some(lp_address), Some(ip_address)) =
|
||||
(node_info.lp_address, node_info.ip_address)
|
||||
{
|
||||
info!("Node has LP address, testing LP registration...");
|
||||
let lp_outcome = if let Some(lp_data) = node_info.lp_data {
|
||||
info!("Node has LP data, testing LP registration...");
|
||||
|
||||
// Prepare bandwidth credential for LP registration
|
||||
let config = nym_validator_client::nyxd::Config::try_from_nym_network_details(
|
||||
@@ -941,15 +941,10 @@ impl Probe {
|
||||
client,
|
||||
);
|
||||
|
||||
let outcome = lp_registration_probe(
|
||||
node_info.identity,
|
||||
lp_address,
|
||||
ip_address,
|
||||
&bw_controller,
|
||||
use_mock_ecash,
|
||||
)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
let outcome =
|
||||
lp_registration_probe(node_info.identity, lp_data, &bw_controller, use_mock_ecash)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
Some(outcome)
|
||||
} else {
|
||||
@@ -1081,10 +1076,13 @@ async fn wg_probe(
|
||||
Ok(wg_outcome)
|
||||
}
|
||||
|
||||
fn to_lp_remote_peer(identity: ed25519::PublicKey, data: TestedNodeLpDetails) -> LpRemotePeer {
|
||||
LpRemotePeer::new(identity, data.x25519).with_kem_key_digests(data.expected_kem_key_hashes)
|
||||
}
|
||||
|
||||
async fn lp_registration_probe<St>(
|
||||
gateway_identity: NodeIdentity,
|
||||
gateway_lp_address: std::net::SocketAddr,
|
||||
gateway_ip: IpAddr,
|
||||
gateway_lp_data: TestedNodeLpDetails,
|
||||
bandwidth_controller: &nym_bandwidth_controller::BandwidthController<
|
||||
nym_validator_client::nyxd::NyxdClient<nym_validator_client::HttpRpcClient>,
|
||||
St,
|
||||
@@ -1098,10 +1096,10 @@ where
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_registration_client::LpRegistrationClient;
|
||||
|
||||
info!(
|
||||
"Starting LP registration probe for gateway at {}",
|
||||
gateway_lp_address
|
||||
);
|
||||
let lp_address = gateway_lp_data.address;
|
||||
let peer = to_lp_remote_peer(gateway_identity, gateway_lp_data);
|
||||
|
||||
info!("Starting LP registration probe for gateway at {lp_address}",);
|
||||
|
||||
let mut lp_outcome = types::LpProbeResults::default();
|
||||
|
||||
@@ -1110,23 +1108,18 @@ where
|
||||
let client_ed25519_keypair = std::sync::Arc::new(ed25519::KeyPair::new(&mut rng));
|
||||
|
||||
// Step 0: Derive X25519 keys from Ed25519 for the gateways
|
||||
let gateway_x25519_key = gateway_identity
|
||||
.to_x25519()
|
||||
.context("failed to convert entry ed25519 key to x25519")?;
|
||||
let peer = LpRemotePeer::new(gateway_identity, gateway_x25519_key);
|
||||
|
||||
// Create LP registration client (uses Ed25519 keys directly, derives X25519 internally)
|
||||
let mut client = LpRegistrationClient::<TcpStream>::new_with_default_config(
|
||||
client_ed25519_keypair,
|
||||
peer,
|
||||
gateway_lp_address,
|
||||
gateway_ip,
|
||||
lp_address,
|
||||
);
|
||||
|
||||
// Step 1: Perform handshake (connection is implicit in packet-per-connection model)
|
||||
// LpRegistrationClient uses packet-per-connection model - connect() is gone,
|
||||
// connection is established during handshake and registration automatically.
|
||||
info!("Performing LP handshake at {}...", gateway_lp_address);
|
||||
info!("Performing LP handshake at {lp_address}...");
|
||||
match client.perform_handshake().await {
|
||||
Ok(_) => {
|
||||
info!("LP handshake completed successfully");
|
||||
@@ -1245,49 +1238,38 @@ where
|
||||
St: nym_sdk::mixnet::CredentialStorage + Clone + Send + Sync + 'static,
|
||||
<St as nym_sdk::mixnet::CredentialStorage>::StorageError: Send + Sync,
|
||||
{
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_registration_client::{LpRegistrationClient, NestedLpSession};
|
||||
// Validate that both gateways have required information
|
||||
let entry_lp_data = entry_gateway
|
||||
.lp_data
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow::anyhow!("Entry gateway missing LP data"))?;
|
||||
|
||||
let exit_lp_data = exit_gateway
|
||||
.lp_data
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow::anyhow!("Exit gateway missing LP data"))?;
|
||||
|
||||
let entry_address = entry_lp_data.address;
|
||||
let exit_address = exit_lp_data.address;
|
||||
|
||||
let entry_ip = entry_address.ip();
|
||||
let exit_ip = exit_address.ip();
|
||||
|
||||
info!("Starting LP-based WireGuard probe (entry→exit via forwarding)");
|
||||
|
||||
let mut wg_outcome = WgProbeResults::default();
|
||||
|
||||
// Validate that both gateways have required information
|
||||
let entry_lp_address = entry_gateway
|
||||
.lp_address
|
||||
.ok_or_else(|| anyhow::anyhow!("Entry gateway missing LP address"))?;
|
||||
let exit_lp_address = exit_gateway
|
||||
.lp_address
|
||||
.ok_or_else(|| anyhow::anyhow!("Exit gateway missing LP address"))?;
|
||||
let entry_ip = entry_gateway
|
||||
.ip_address
|
||||
.ok_or_else(|| anyhow::anyhow!("Entry gateway missing IP address"))?;
|
||||
let exit_ip = exit_gateway
|
||||
.ip_address
|
||||
.ok_or_else(|| anyhow::anyhow!("Exit gateway missing IP address"))?;
|
||||
|
||||
// Generate Ed25519 keypairs for LP protocol
|
||||
let mut rng = rand::thread_rng();
|
||||
let entry_lp_keypair = Arc::new(ed25519::KeyPair::new(&mut rng));
|
||||
let exit_lp_keypair = Arc::new(ed25519::KeyPair::new(&mut rng));
|
||||
|
||||
// Step 0: Derive X25519 keys from Ed25519 for the gateways
|
||||
let entry_x25519_public = entry_gateway
|
||||
.identity
|
||||
.to_x25519()
|
||||
.context("failed to convert entry ed25519 key to x25519")?;
|
||||
|
||||
let exit_x25519_public = exit_gateway
|
||||
.identity
|
||||
.to_x25519()
|
||||
.context("failed to convert exit ed25519 key to x25519")?;
|
||||
|
||||
// Generate WireGuard keypairs for VPN registration
|
||||
let entry_wg_keypair = x25519::KeyPair::new(&mut rng);
|
||||
let exit_wg_keypair = x25519::KeyPair::new(&mut rng);
|
||||
|
||||
let entry_peer = LpRemotePeer::new(entry_gateway.identity, entry_x25519_public);
|
||||
let exit_peer = LpRemotePeer::new(exit_gateway.identity, exit_x25519_public);
|
||||
let entry_peer = to_lp_remote_peer(entry_gateway.identity, entry_lp_data);
|
||||
let exit_peer = to_lp_remote_peer(exit_gateway.identity, exit_lp_data);
|
||||
|
||||
// STEP 1: Establish outer LP session with entry gateway
|
||||
// LpRegistrationClient uses packet-per-connection model - connect() is gone,
|
||||
@@ -1296,8 +1278,7 @@ where
|
||||
let mut entry_client = LpRegistrationClient::<TcpStream>::new_with_default_config(
|
||||
entry_lp_keypair,
|
||||
entry_peer,
|
||||
entry_lp_address,
|
||||
entry_ip,
|
||||
entry_address,
|
||||
);
|
||||
|
||||
// Perform handshake with entry gateway (connection is implicit)
|
||||
@@ -1310,7 +1291,7 @@ where
|
||||
// STEP 2: Use nested session to register with exit gateway via forwarding
|
||||
info!("Registering with exit gateway via entry forwarding...");
|
||||
let mut nested_session =
|
||||
NestedLpSession::new(exit_lp_address.to_string(), exit_lp_keypair, exit_peer);
|
||||
NestedLpSession::new(exit_address.to_string(), exit_lp_keypair, exit_peer);
|
||||
|
||||
// Convert exit gateway identity to ed25519 public key for registration
|
||||
let exit_gateway_pubkey = ed25519::PublicKey::from_bytes(&exit_gateway.identity.to_bytes())
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::TestedNodeDetails;
|
||||
use crate::{TestedNodeDetails, TestedNodeLpDetails};
|
||||
use anyhow::{Context, anyhow, bail};
|
||||
use nym_api_requests::models::{
|
||||
AuthenticatorDetailsV2, DeclaredRolesV2, DescribedNodeTypeV2, HostInformationV2,
|
||||
@@ -19,6 +19,7 @@ use nym_validator_client::client::NymApiClientExt;
|
||||
use nym_validator_client::models::NymNodeDescriptionV2;
|
||||
use rand::prelude::IteratorRandom;
|
||||
use std::collections::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
use tracing::{debug, info, warn};
|
||||
@@ -96,16 +97,14 @@ impl DirectoryNode {
|
||||
}
|
||||
|
||||
pub fn to_testable_node(&self) -> anyhow::Result<TestedNodeDetails> {
|
||||
let exit_router_address = self
|
||||
.described
|
||||
.description
|
||||
let description = &self.described.description;
|
||||
|
||||
let exit_router_address = description
|
||||
.ip_packet_router
|
||||
.as_ref()
|
||||
.map(|ipr| ipr.address.parse().context("malformed ipr address"))
|
||||
.transpose()?;
|
||||
let authenticator_address = self
|
||||
.described
|
||||
.description
|
||||
let authenticator_address = description
|
||||
.authenticator
|
||||
.as_ref()
|
||||
.map(|ipr| {
|
||||
@@ -114,32 +113,46 @@ impl DirectoryNode {
|
||||
.context("malformed authenticator address")
|
||||
})
|
||||
.transpose()?;
|
||||
let authenticator_version = AuthenticatorVersion::from(
|
||||
self.described
|
||||
.description
|
||||
.build_information
|
||||
.build_version
|
||||
.as_str(),
|
||||
);
|
||||
let ip_address = self
|
||||
.described
|
||||
.description
|
||||
let authenticator_version =
|
||||
AuthenticatorVersion::from(description.build_information.build_version.as_str());
|
||||
let ip_address = description
|
||||
.host_information
|
||||
.ip_address
|
||||
.first()
|
||||
.copied();
|
||||
.copied()
|
||||
.ok_or_else(|| anyhow!("no ip address known"))?;
|
||||
|
||||
// Derive LP address from gateway IP + default LP control port (41264)
|
||||
// TODO: Update this when LP address is exposed in node description API
|
||||
let lp_address = ip_address.map(|ip| std::net::SocketAddr::new(ip, 41264));
|
||||
let lp_data = match (
|
||||
description.lewes_protocol.clone(),
|
||||
description.host_information.keys.x25519_versioned_noise,
|
||||
) {
|
||||
(Some(lp_data), Some(noise_key)) => Some(TestedNodeLpDetails {
|
||||
address: SocketAddr::new(ip_address, lp_data.control_port),
|
||||
expected_kem_key_hashes: lp_data
|
||||
.kem_keys
|
||||
.into_iter()
|
||||
.map(|(kem, digests)| {
|
||||
(
|
||||
kem.into(),
|
||||
digests
|
||||
.into_iter()
|
||||
.map(|(hash_fn, digest)| (hash_fn.into(), digest))
|
||||
.collect(),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
x25519: noise_key.x25519_pubkey,
|
||||
}),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
Ok(TestedNodeDetails {
|
||||
identity: self.identity(),
|
||||
exit_router_address,
|
||||
authenticator_address,
|
||||
authenticator_version,
|
||||
ip_address,
|
||||
lp_address,
|
||||
ip_address: Some(ip_address),
|
||||
lp_data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+109
-27
@@ -5,11 +5,15 @@ use anyhow::bail;
|
||||
use clap::{Parser, Subcommand};
|
||||
use nym_bin_common::bin_info;
|
||||
use nym_config::defaults::setup_env;
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_gateway_probe::nodes::{NymApiDirectory, query_gateway_by_ip};
|
||||
use nym_gateway_probe::{
|
||||
CredentialArgs, NetstackArgs, ProbeResult, TestMode, TestedNode, TestedNodeDetails,
|
||||
TestedNodeLpDetails,
|
||||
};
|
||||
use nym_kkt_ciphersuite::{HashFunction, KEM};
|
||||
use nym_sdk::mixnet::NodeIdentity;
|
||||
use std::collections::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::Path;
|
||||
use std::{path::PathBuf, sync::OnceLock};
|
||||
@@ -46,32 +50,70 @@ struct CliArgs {
|
||||
#[arg(long, global = true)]
|
||||
gateway_ip: Option<String>,
|
||||
|
||||
// ##########
|
||||
// ENTRY
|
||||
// ##########
|
||||
/// Ed25519 identity of the entry gateway (base58 encoded)
|
||||
/// When provided, skips HTTP API query - use for localnet testing
|
||||
#[arg(long, global = true)]
|
||||
entry_gateway_identity: Option<String>,
|
||||
|
||||
/// x25519 key of the entry gateway used for KKT exchange (base58 encoded)
|
||||
#[arg(long, global = true, requires = "entry_gateway_identity")]
|
||||
entry_gateway_x25519_key: Option<String>,
|
||||
|
||||
/// expected kem type of the entry gateway used during KKT exchange
|
||||
#[arg(long, global = true, requires = "entry_gateway_x25519_key")]
|
||||
entry_gateway_kem_key_type: Option<String>,
|
||||
|
||||
/// expected hash function used for the entry gateway kem key digest
|
||||
#[arg(long, global = true, requires = "entry_gateway_kem_key_type")]
|
||||
entry_gateway_kem_key_hash_function: Option<String>,
|
||||
|
||||
/// expected entry gateway kem key digest (base58 encoded)
|
||||
#[arg(long, global = true, requires = "entry_gateway_kem_key_hash_function")]
|
||||
entry_gateway_kem_hey_hash_bs58: Option<String>,
|
||||
|
||||
/// LP listener address for entry gateway (e.g., "192.168.66.6:41264")
|
||||
/// Used with --entry-gateway-identity for localnet mode
|
||||
#[arg(long, global = true)]
|
||||
entry_lp_address: Option<SocketAddr>,
|
||||
|
||||
// ##########
|
||||
// EXIT
|
||||
// ##########
|
||||
/// The address of the exit gateway for LP forwarding tests (used with --test-lp-wg)
|
||||
/// When specified, --gateway-ip becomes the entry gateway and this becomes the exit gateway
|
||||
/// Supports formats: IP (192.168.66.5), IP:PORT (192.168.66.5:8080), HOST:PORT (localhost:30004)
|
||||
#[arg(long, global = true)]
|
||||
exit_gateway_ip: Option<String>,
|
||||
|
||||
/// Ed25519 identity of the entry gateway (base58 encoded)
|
||||
/// When provided, skips HTTP API query - use for localnet testing
|
||||
#[arg(long, global = true)]
|
||||
entry_gateway_identity: Option<String>,
|
||||
|
||||
/// Ed25519 identity of the exit gateway (base58 encoded)
|
||||
/// When provided, skips HTTP API query - use for localnet testing
|
||||
#[arg(long, global = true)]
|
||||
exit_gateway_identity: Option<String>,
|
||||
|
||||
/// LP listener address for entry gateway (e.g., "192.168.66.6:41264")
|
||||
/// Used with --entry-gateway-identity for localnet mode
|
||||
#[arg(long, global = true)]
|
||||
entry_lp_address: Option<String>,
|
||||
/// x25519 key of the exit gateway used for KKT exchange (base58 encoded)
|
||||
#[arg(long, global = true, requires = "exit_gateway_identity")]
|
||||
exit_gateway_x25519_key: Option<String>,
|
||||
|
||||
/// expected kem type of the exit gateway used during KKT exchange
|
||||
#[arg(long, global = true, requires = "exit_gateway_x25519_key")]
|
||||
exit_gateway_kem_key_type: Option<String>,
|
||||
|
||||
/// expected hash function used for the exit gateway kem key digest
|
||||
#[arg(long, global = true, requires = "exit_gateway_kem_key_type")]
|
||||
exit_gateway_kem_key_hash_function: Option<String>,
|
||||
|
||||
/// expected exit gateway kem key digest (base58 encoded)
|
||||
#[arg(long, global = true, requires = "exit_gateway_kem_key_hash_function")]
|
||||
exit_gateway_kem_hey_hash_bs58: Option<String>,
|
||||
|
||||
/// LP listener address for exit gateway (e.g., "172.18.0.5:41264")
|
||||
/// This is the address the entry gateway uses to reach exit (for forwarding)
|
||||
/// Used with --exit-gateway-identity for localnet mode
|
||||
#[arg(long, global = true)]
|
||||
exit_lp_address: Option<String>,
|
||||
exit_lp_address: Option<SocketAddr>,
|
||||
|
||||
/// Default LP control port when deriving LP address from gateway IP
|
||||
#[arg(long, global = true, default_value = "41264")]
|
||||
@@ -202,6 +244,7 @@ fn mode_to_flags(mode: TestMode) -> (bool, bool, bool) {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::unwrap_used)]
|
||||
pub(crate) async fn run() -> anyhow::Result<ProbeResult> {
|
||||
let args = CliArgs::parse();
|
||||
if !args.no_log {
|
||||
@@ -224,21 +267,35 @@ pub(crate) async fn run() -> anyhow::Result<ProbeResult> {
|
||||
// 3. Directory mode: uses nym-api directory service
|
||||
|
||||
// Localnet mode: identity provided via CLI, skip HTTP queries entirely
|
||||
if let Some(entry_identity_str) = &args.entry_gateway_identity {
|
||||
if let Some(kem_key_digest) = &args.entry_gateway_kem_hey_hash_bs58 {
|
||||
info!("Using localnet mode with CLI-provided gateway identity");
|
||||
|
||||
let entry_identity = NodeIdentity::from_base58_string(entry_identity_str)?;
|
||||
// SAFETY: if kem key digest is provided, all other LP data must also be present
|
||||
// (enforced by clap)
|
||||
let hash_fn: HashFunction = args
|
||||
.entry_gateway_kem_key_hash_function
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.parse()?;
|
||||
let kem_type: KEM = args.entry_gateway_kem_key_type.as_ref().unwrap().parse()?;
|
||||
let x25519_key: x25519::PublicKey =
|
||||
args.entry_gateway_x25519_key.as_ref().unwrap().parse()?;
|
||||
let identity: ed25519::PublicKey = args.entry_gateway_identity.as_ref().unwrap().parse()?;
|
||||
let digest = bs58::decode(&kem_key_digest).into_vec()?;
|
||||
|
||||
let mut expected_kem_key_hashes = HashMap::new();
|
||||
let mut digests = HashMap::new();
|
||||
digests.insert(hash_fn, digest);
|
||||
expected_kem_key_hashes.insert(kem_type, digests);
|
||||
|
||||
// Entry LP address: explicit or derived from gateway_ip + lp_port
|
||||
let entry_lp_addr: SocketAddr = if let Some(lp_addr) = &args.entry_lp_address {
|
||||
let entry_lp_addr: SocketAddr = if let Some(lp_addr) = args.entry_lp_address {
|
||||
lp_addr
|
||||
.parse()
|
||||
.map_err(|e| anyhow::anyhow!("Invalid entry-lp-address '{}': {}", lp_addr, e))?
|
||||
} else if let Some(gw_ip) = &args.gateway_ip {
|
||||
// Derive LP address from gateway IP
|
||||
let ip: std::net::IpAddr = gw_ip
|
||||
.parse()
|
||||
.map_err(|e| anyhow::anyhow!("Invalid gateway-ip '{}': {}", gw_ip, e))?;
|
||||
.map_err(|e| anyhow::anyhow!("Invalid gateway-ip '{gw_ip}': {e}"))?;
|
||||
SocketAddr::new(ip, args.lp_port)
|
||||
} else {
|
||||
anyhow::bail!(
|
||||
@@ -246,20 +303,45 @@ pub(crate) async fn run() -> anyhow::Result<ProbeResult> {
|
||||
);
|
||||
};
|
||||
|
||||
let entry_details = TestedNodeDetails::from_cli(entry_identity, entry_lp_addr);
|
||||
let entry_lp_node = TestedNodeLpDetails {
|
||||
address: entry_lp_addr,
|
||||
expected_kem_key_hashes,
|
||||
x25519: x25519_key,
|
||||
};
|
||||
let entry_details = TestedNodeDetails::from_cli(identity, entry_lp_node);
|
||||
|
||||
// Parse exit gateway if provided
|
||||
let exit_details = if let Some(exit_identity_str) = &args.exit_gateway_identity {
|
||||
let exit_identity = NodeIdentity::from_base58_string(exit_identity_str)?;
|
||||
let exit_lp_addr: SocketAddr = args
|
||||
.exit_lp_address
|
||||
let exit_details = if let Some(kem_key_digest) = &args.exit_gateway_kem_hey_hash_bs58 {
|
||||
let exit_lp_addr = *args.exit_lp_address.as_ref().ok_or_else(|| {
|
||||
anyhow::anyhow!("--exit-lp-address required with --exit-gateway-identity")
|
||||
})?;
|
||||
|
||||
// SAFETY: if kem key digest is provided, all other LP data must also be present
|
||||
// (enforced by clap)
|
||||
let hash_fn: HashFunction = args
|
||||
.exit_gateway_kem_key_hash_function
|
||||
.as_ref()
|
||||
.ok_or_else(|| {
|
||||
anyhow::anyhow!("--exit-lp-address required with --exit-gateway-identity")
|
||||
})?
|
||||
.parse()
|
||||
.map_err(|e| anyhow::anyhow!("Invalid exit-lp-address: {}", e))?;
|
||||
Some(TestedNodeDetails::from_cli(exit_identity, exit_lp_addr))
|
||||
.unwrap()
|
||||
.parse()?;
|
||||
let kem_type: KEM = args.exit_gateway_kem_key_type.as_ref().unwrap().parse()?;
|
||||
let x25519_key: x25519::PublicKey =
|
||||
args.exit_gateway_x25519_key.as_ref().unwrap().parse()?;
|
||||
let identity: ed25519::PublicKey =
|
||||
args.exit_gateway_identity.as_ref().unwrap().parse()?;
|
||||
let digest = bs58::decode(&kem_key_digest).into_vec()?;
|
||||
|
||||
let mut expected_kem_key_hashes = HashMap::new();
|
||||
let mut digests = HashMap::new();
|
||||
digests.insert(hash_fn, digest);
|
||||
expected_kem_key_hashes.insert(kem_type, digests);
|
||||
|
||||
let exit_lp_node = TestedNodeLpDetails {
|
||||
address: exit_lp_addr,
|
||||
expected_kem_key_hashes,
|
||||
x25519: x25519_key,
|
||||
};
|
||||
|
||||
Some(TestedNodeDetails::from_cli(identity, exit_lp_node))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@ nym-exit-policy = { workspace = true }
|
||||
nym-noise-keys = { workspace = true }
|
||||
nym-wireguard-types = { workspace = true }
|
||||
nym-upgrade-mode-check = { workspace = true, features = ["openapi"] }
|
||||
nym-kkt-ciphersuite = { path = "../../common/nym-kkt-ciphersuite" }
|
||||
nym-kkt-ciphersuite = { workspace = true }
|
||||
|
||||
# feature-specific dependencies:
|
||||
|
||||
|
||||
@@ -122,8 +122,8 @@ impl From<LPHashFunction> for nym_kkt_ciphersuite::HashFunction {
|
||||
fn from(lp_hash_fnction: LPHashFunction) -> Self {
|
||||
match lp_hash_fnction {
|
||||
LPHashFunction::Blake3 => nym_kkt_ciphersuite::HashFunction::Blake3,
|
||||
LPHashFunction::Shake128 => nym_kkt_ciphersuite::HashFunction::SHAKE128,
|
||||
LPHashFunction::Shake256 => nym_kkt_ciphersuite::HashFunction::SHAKE256,
|
||||
LPHashFunction::Shake128 => nym_kkt_ciphersuite::HashFunction::Shake128,
|
||||
LPHashFunction::Shake256 => nym_kkt_ciphersuite::HashFunction::Shake256,
|
||||
LPHashFunction::Sha256 => nym_kkt_ciphersuite::HashFunction::SHA256,
|
||||
}
|
||||
}
|
||||
@@ -133,8 +133,8 @@ impl From<nym_kkt_ciphersuite::HashFunction> for LPHashFunction {
|
||||
fn from(kem: nym_kkt_ciphersuite::HashFunction) -> Self {
|
||||
match kem {
|
||||
nym_kkt_ciphersuite::HashFunction::Blake3 => LPHashFunction::Blake3,
|
||||
nym_kkt_ciphersuite::HashFunction::SHAKE128 => LPHashFunction::Shake128,
|
||||
nym_kkt_ciphersuite::HashFunction::SHAKE256 => LPHashFunction::Shake256,
|
||||
nym_kkt_ciphersuite::HashFunction::Shake128 => LPHashFunction::Shake128,
|
||||
nym_kkt_ciphersuite::HashFunction::Shake256 => LPHashFunction::Shake256,
|
||||
nym_kkt_ciphersuite::HashFunction::SHA256 => LPHashFunction::Sha256,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,7 +400,6 @@ pub(crate) struct NymNode {
|
||||
sphinx_key_manager: Option<SphinxKeyManager>,
|
||||
|
||||
// to be used when noise is integrated
|
||||
#[allow(dead_code)]
|
||||
x25519_noise_keys: Arc<x25519::KeyPair>,
|
||||
}
|
||||
|
||||
@@ -644,6 +643,7 @@ impl NymNode {
|
||||
let mut gateway_tasks_builder = GatewayTasksBuilder::new(
|
||||
config.gateway,
|
||||
self.ed25519_identity_keys.clone(),
|
||||
self.x25519_noise_keys.clone(),
|
||||
self.entry_gateway.psq_kem_key.clone(),
|
||||
self.entry_gateway.client_storage.clone(),
|
||||
mix_packet_sender,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use nym_credential_storage::persistent_storage::PersistentStorage;
|
||||
use nym_registration_common::NymNode;
|
||||
use nym_registration_common::NymNodeInformation;
|
||||
use nym_sdk::{
|
||||
DebugConfig, NymNetworkDetails, RememberMe, TopologyProvider, UserAgent,
|
||||
mixnet::{
|
||||
@@ -25,7 +25,7 @@ const MIXNET_CLIENT_STARTUP_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NymNodeWithKeys {
|
||||
pub node: NymNode,
|
||||
pub node: NymNodeInformation,
|
||||
pub keys: Arc<x25519::KeyPair>,
|
||||
}
|
||||
|
||||
|
||||
@@ -93,9 +93,6 @@ pub enum RegistrationClientError {
|
||||
#[source]
|
||||
source: Box<crate::lp_client::LpClientError>,
|
||||
},
|
||||
|
||||
#[error("failed to convert ed25519 pubkey into x25519 pubkey")]
|
||||
X25519PubkeyConversionFailure,
|
||||
}
|
||||
|
||||
impl RegistrationClientError {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::config::RegistrationClientConfig;
|
||||
use crate::lp_client::helpers::to_lp_remote_peer;
|
||||
use nym_authenticator_client::{AuthClientMixnetListener, AuthenticatorClient};
|
||||
use nym_bandwidth_controller::BandwidthTicketProvider;
|
||||
use nym_credentials_interface::TicketType;
|
||||
@@ -14,12 +13,7 @@ use nym_sdk::mixnet::{EventReceiver, MixnetClient, Recipient};
|
||||
use rand::rngs::OsRng;
|
||||
use std::sync::Arc;
|
||||
use tokio::net::TcpStream;
|
||||
|
||||
mod builder;
|
||||
mod config;
|
||||
mod error;
|
||||
mod lp_client;
|
||||
mod types;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
pub use builder::RegistrationClientBuilder;
|
||||
pub use builder::config::{
|
||||
@@ -29,11 +23,16 @@ pub use builder::config::{
|
||||
pub use config::RegistrationMode;
|
||||
pub use error::RegistrationClientError;
|
||||
pub use lp_client::{LpConfig, LpRegistrationClient, NestedLpSession, error::LpClientError};
|
||||
use nym_lp::peer::LpRemotePeer;
|
||||
pub use types::{
|
||||
LpRegistrationResult, MixnetRegistrationResult, RegistrationResult, WireguardRegistrationResult,
|
||||
};
|
||||
|
||||
mod builder;
|
||||
mod config;
|
||||
mod error;
|
||||
mod lp_client;
|
||||
mod types;
|
||||
|
||||
pub struct RegistrationClient {
|
||||
mixnet_client: MixnetClient,
|
||||
config: RegistrationClientConfig,
|
||||
@@ -168,64 +167,46 @@ impl RegistrationClient {
|
||||
},
|
||||
)?;
|
||||
|
||||
tracing::debug!("Entry gateway LP address: {}", entry_lp_data.address);
|
||||
tracing::debug!("Exit gateway LP address: {}", exit_lp_data.address);
|
||||
let entry_address = entry_lp_data.address;
|
||||
let exit_address = exit_lp_data.address;
|
||||
|
||||
tracing::debug!("Entry gateway LP address: {entry_address}");
|
||||
tracing::debug!("Exit gateway LP address: {exit_address}");
|
||||
|
||||
// Generate fresh Ed25519 keypairs for LP registration
|
||||
// These are ephemeral and used only for the LP handshake protocol
|
||||
let entry_lp_keypair = Arc::new(ed25519::KeyPair::new(&mut OsRng));
|
||||
let exit_lp_keypair = Arc::new(ed25519::KeyPair::new(&mut OsRng));
|
||||
|
||||
// Step 1: Derive X25519 keys from Ed25519 for the gateways
|
||||
let entry_x25519_public = self
|
||||
.config
|
||||
.entry
|
||||
.node
|
||||
.identity
|
||||
.to_x25519()
|
||||
.map_err(|_| RegistrationClientError::X25519PubkeyConversionFailure)?;
|
||||
let entry_peer = to_lp_remote_peer(self.config.entry.node.identity, entry_lp_data);
|
||||
let exit_peer = to_lp_remote_peer(self.config.exit.node.identity, exit_lp_data);
|
||||
|
||||
let exit_x25519_public = self
|
||||
.config
|
||||
.exit
|
||||
.node
|
||||
.identity
|
||||
.to_x25519()
|
||||
.map_err(|_| RegistrationClientError::X25519PubkeyConversionFailure)?;
|
||||
|
||||
let entry_peer = LpRemotePeer::new(self.config.entry.node.identity, entry_x25519_public)
|
||||
.with_kem_key_digests(entry_lp_data.expected_kem_key_hashes);
|
||||
|
||||
let exit_peer = LpRemotePeer::new(self.config.exit.node.identity, exit_x25519_public)
|
||||
.with_kem_key_digests(exit_lp_data.expected_kem_key_hashes);
|
||||
|
||||
// STEP 2: Establish outer session with entry gateway
|
||||
// STEP 1: Establish outer session with entry gateway
|
||||
// This creates the LP session that will be used to forward packets to exit.
|
||||
// Uses packet-per-connection model: each handshake packet on new TCP connection.
|
||||
tracing::info!("Establishing outer session with entry gateway");
|
||||
let mut entry_client = LpRegistrationClient::new_with_default_config(
|
||||
entry_lp_keypair.clone(),
|
||||
entry_peer,
|
||||
entry_lp_data.address,
|
||||
self.config.entry.node.ip_address,
|
||||
entry_address,
|
||||
);
|
||||
|
||||
// Perform handshake with entry gateway (outer session now established)
|
||||
entry_client.perform_handshake().await.map_err(|source| {
|
||||
RegistrationClientError::EntryGatewayRegisterLp {
|
||||
gateway_id: self.config.entry.node.identity.to_base58_string(),
|
||||
lp_address: entry_lp_data.address,
|
||||
lp_address: entry_address,
|
||||
source: Box::new(source),
|
||||
}
|
||||
})?;
|
||||
|
||||
tracing::info!("Outer session with entry gateway established");
|
||||
|
||||
// STEP 3: Use nested session to register with exit gateway via forwarding
|
||||
// STEP 2: Use nested session to register with exit gateway via forwarding
|
||||
// This hides the client's IP address from the exit gateway
|
||||
tracing::info!("Registering with exit gateway via entry forwarding");
|
||||
let mut nested_session =
|
||||
NestedLpSession::new(exit_lp_data.address.to_string(), exit_lp_keypair, exit_peer);
|
||||
NestedLpSession::new(exit_address.to_string(), exit_lp_keypair, exit_peer);
|
||||
|
||||
// Perform handshake and registration with exit gateway (all via entry forwarding)
|
||||
let exit_gateway_data = nested_session
|
||||
@@ -239,13 +220,13 @@ impl RegistrationClient {
|
||||
.await
|
||||
.map_err(|source| RegistrationClientError::ExitGatewayRegisterLp {
|
||||
gateway_id: self.config.exit.node.identity.to_base58_string(),
|
||||
lp_address: exit_lp_data.address,
|
||||
lp_address: exit_address,
|
||||
source: Box::new(source),
|
||||
})?;
|
||||
|
||||
tracing::info!("Exit gateway registration completed via forwarding");
|
||||
|
||||
// STEP 4: Register with entry gateway (packet-per-connection)
|
||||
// STEP 3: Register with entry gateway (packet-per-connection)
|
||||
tracing::info!("Registering with entry gateway");
|
||||
let entry_gateway_data = entry_client
|
||||
.register(
|
||||
@@ -257,7 +238,7 @@ impl RegistrationClient {
|
||||
.await
|
||||
.map_err(|source| RegistrationClientError::EntryGatewayRegisterLp {
|
||||
gateway_id: self.config.entry.node.identity.to_base58_string(),
|
||||
lp_address: entry_lp_data.address,
|
||||
lp_address: entry_address,
|
||||
source: Box::new(source),
|
||||
})?;
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ use nym_lp::message::ForwardPacketData;
|
||||
use nym_lp::peer::{LpLocalPeer, LpRemotePeer};
|
||||
use nym_lp::state_machine::{LpAction, LpData, LpInput, LpStateMachine};
|
||||
use nym_lp_transport::traits::LpTransport;
|
||||
use nym_registration_common::{GatewayData, LpRegistrationRequest};
|
||||
use nym_registration_common::{LpRegistrationRequest, WireguardConfiguration};
|
||||
use nym_wireguard_types::PeerPublicKey;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
@@ -54,9 +54,6 @@ pub struct LpRegistrationClient<S = TcpStream> {
|
||||
/// Created during handshake initiation. Persists across packet-per-connection calls.
|
||||
state_machine: Option<LpStateMachine>,
|
||||
|
||||
/// Client's IP address for registration metadata.
|
||||
client_ip: IpAddr,
|
||||
|
||||
/// Configuration for timeouts and TCP parameters.
|
||||
config: LpConfig,
|
||||
|
||||
@@ -75,7 +72,6 @@ where
|
||||
/// * `local_ed25519_keypair` - Client's Ed25519 identity keypair
|
||||
/// * `gateway_lp_peer` - Encapsulates all the gateway keys needed for the Lewes Protocol
|
||||
/// * `gateway_lp_address` - Gateway's LP listener socket address
|
||||
/// * `client_ip` - Client IP address for registration
|
||||
/// * `config` - Configuration for timeouts and TCP parameters (use `LpConfig::default()`)
|
||||
///
|
||||
/// # Note
|
||||
@@ -84,7 +80,6 @@ where
|
||||
local_ed25519_keypair: Arc<ed25519::KeyPair>,
|
||||
gateway_lp_peer: LpRemotePeer,
|
||||
gateway_lp_address: SocketAddr,
|
||||
client_ip: IpAddr,
|
||||
config: LpConfig,
|
||||
) -> Self {
|
||||
let local_x25519_keypair = local_ed25519_keypair.to_x25519();
|
||||
@@ -94,7 +89,6 @@ where
|
||||
gateway_lp_peer,
|
||||
gateway_lp_address,
|
||||
state_machine: None,
|
||||
client_ip,
|
||||
config,
|
||||
stream: None,
|
||||
}
|
||||
@@ -115,13 +109,11 @@ where
|
||||
local_ed25519_keypair: Arc<ed25519::KeyPair>,
|
||||
gateway_lp_peer: LpRemotePeer,
|
||||
gateway_lp_address: SocketAddr,
|
||||
client_ip: IpAddr,
|
||||
) -> Self {
|
||||
Self::new(
|
||||
local_ed25519_keypair,
|
||||
gateway_lp_peer,
|
||||
gateway_lp_address,
|
||||
client_ip,
|
||||
LpConfig::default(),
|
||||
)
|
||||
}
|
||||
@@ -140,11 +132,6 @@ where
|
||||
self.gateway_lp_address
|
||||
}
|
||||
|
||||
/// Returns the client's IP address.
|
||||
pub fn client_ip(&self) -> IpAddr {
|
||||
self.client_ip
|
||||
}
|
||||
|
||||
/// Returns reference to the established connection between the client and the gateway.
|
||||
pub fn connection(&self) -> &Option<S> {
|
||||
&self.stream
|
||||
@@ -697,7 +684,7 @@ where
|
||||
gateway_identity: &ed25519::PublicKey,
|
||||
bandwidth_controller: &dyn BandwidthTicketProvider,
|
||||
ticket_type: TicketType,
|
||||
) -> Result<GatewayData> {
|
||||
) -> Result<WireguardConfiguration> {
|
||||
tracing::debug!("Acquiring bandwidth credential for registration");
|
||||
|
||||
// Get bandwidth credential from controller
|
||||
@@ -739,7 +726,7 @@ where
|
||||
wg_keypair: &x25519::KeyPair,
|
||||
credential: CredentialSpendingData,
|
||||
ticket_type: TicketType,
|
||||
) -> Result<GatewayData> {
|
||||
) -> Result<WireguardConfiguration> {
|
||||
tracing::debug!("Sending registration request (persistent connection)");
|
||||
|
||||
// 1. Build registration request
|
||||
@@ -885,7 +872,7 @@ where
|
||||
bandwidth_controller: &dyn BandwidthTicketProvider,
|
||||
ticket_type: TicketType,
|
||||
max_retries: u32,
|
||||
) -> Result<GatewayData> {
|
||||
) -> Result<WireguardConfiguration> {
|
||||
tracing::debug!("Starting resilient registration (max_retries={max_retries})",);
|
||||
|
||||
// Acquire credential ONCE before any attempts
|
||||
@@ -1179,17 +1166,14 @@ mod tests {
|
||||
let gateway_peer =
|
||||
LpRemotePeer::new(*gateway_ed_keys.public_key(), *gateway_x_keys.public_key());
|
||||
let address = "127.0.0.1:41264".parse().unwrap();
|
||||
let client_ip = "192.168.1.100".parse().unwrap();
|
||||
|
||||
let client = LpRegistrationClient::<TcpStream>::new_with_default_config(
|
||||
keypair,
|
||||
gateway_peer,
|
||||
address,
|
||||
client_ip,
|
||||
);
|
||||
|
||||
assert!(!client.is_handshake_complete());
|
||||
assert_eq!(client.gateway_address(), address);
|
||||
assert_eq!(client.client_ip(), client_ip);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::LpClientError;
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_lp::message::ForwardPacketData;
|
||||
use nym_lp::peer::LpRemotePeer;
|
||||
use nym_lp::state_machine::{LpAction, LpData, LpDataKind, LpInput};
|
||||
use nym_registration_common::{LpRegistrationRequest, LpRegistrationResponse};
|
||||
use nym_registration_common::{
|
||||
LpRegistrationRequest, LpRegistrationResponse, NymNodeLPInformation,
|
||||
};
|
||||
|
||||
pub(crate) fn convert_registration_request(
|
||||
request: LpRegistrationRequest,
|
||||
@@ -81,3 +85,10 @@ pub(crate) fn try_convert_forward_response(action: LpAction) -> Result<Vec<u8>,
|
||||
|
||||
Ok(response_data.content.into())
|
||||
}
|
||||
|
||||
pub(crate) fn to_lp_remote_peer(
|
||||
identity: ed25519::PublicKey,
|
||||
data: NymNodeLPInformation,
|
||||
) -> LpRemotePeer {
|
||||
LpRemotePeer::new(identity, data.x25519).with_kem_key_digests(data.expected_kem_key_hashes)
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ use nym_lp::peer::{LpLocalPeer, LpRemotePeer};
|
||||
use nym_lp::state_machine::{LpAction, LpInput, LpStateMachine};
|
||||
use nym_lp::{LpMessage, LpPacket};
|
||||
use nym_lp_transport::traits::LpTransport;
|
||||
use nym_registration_common::{GatewayData, LpRegistrationRequest};
|
||||
use nym_registration_common::{LpRegistrationRequest, WireguardConfiguration};
|
||||
use nym_wireguard_types::PeerPublicKey;
|
||||
use std::sync::Arc;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
@@ -293,7 +293,7 @@ impl NestedLpSession {
|
||||
wg_keypair: &x25519::KeyPair,
|
||||
credential: nym_credentials_interface::CredentialSpendingData,
|
||||
ticket_type: TicketType,
|
||||
) -> Result<GatewayData>
|
||||
) -> Result<WireguardConfiguration>
|
||||
where
|
||||
S: LpTransport + Unpin,
|
||||
{
|
||||
@@ -432,7 +432,7 @@ impl NestedLpSession {
|
||||
gateway_identity: &ed25519::PublicKey,
|
||||
bandwidth_controller: &dyn BandwidthTicketProvider,
|
||||
ticket_type: TicketType,
|
||||
) -> Result<GatewayData>
|
||||
) -> Result<WireguardConfiguration>
|
||||
where
|
||||
S: LpTransport + Unpin,
|
||||
{
|
||||
@@ -585,7 +585,7 @@ impl NestedLpSession {
|
||||
bandwidth_controller: &dyn BandwidthTicketProvider,
|
||||
ticket_type: TicketType,
|
||||
max_retries: u32,
|
||||
) -> Result<GatewayData>
|
||||
) -> Result<WireguardConfiguration>
|
||||
where
|
||||
S: LpTransport + Unpin,
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use nym_authenticator_client::{AuthClientMixnetListenerHandle, AuthenticatorClient};
|
||||
use nym_bandwidth_controller::BandwidthTicketProvider;
|
||||
use nym_registration_common::{AssignedAddresses, GatewayData};
|
||||
use nym_registration_common::{AssignedAddresses, WireguardConfiguration};
|
||||
use nym_sdk::mixnet::{EventReceiver, MixnetClient};
|
||||
|
||||
pub enum RegistrationResult {
|
||||
@@ -21,8 +21,8 @@ pub struct MixnetRegistrationResult {
|
||||
pub struct WireguardRegistrationResult {
|
||||
pub entry_gateway_client: AuthenticatorClient,
|
||||
pub exit_gateway_client: AuthenticatorClient,
|
||||
pub entry_gateway_data: GatewayData,
|
||||
pub exit_gateway_data: GatewayData,
|
||||
pub entry_gateway_data: WireguardConfiguration,
|
||||
pub exit_gateway_data: WireguardConfiguration,
|
||||
pub authenticator_listener_handle: AuthClientMixnetListenerHandle,
|
||||
pub bw_controller: Box<dyn BandwidthTicketProvider>,
|
||||
}
|
||||
@@ -39,10 +39,10 @@ pub struct WireguardRegistrationResult {
|
||||
/// * `bw_controller` - Bandwidth ticket provider for credential management
|
||||
pub struct LpRegistrationResult {
|
||||
/// Gateway configuration data from entry gateway
|
||||
pub entry_gateway_data: GatewayData,
|
||||
pub entry_gateway_data: WireguardConfiguration,
|
||||
|
||||
/// Gateway configuration data from exit gateway
|
||||
pub exit_gateway_data: GatewayData,
|
||||
pub exit_gateway_data: WireguardConfiguration,
|
||||
|
||||
/// Bandwidth controller for credential management
|
||||
pub bw_controller: Box<dyn BandwidthTicketProvider>,
|
||||
|
||||
Generated
+1
@@ -4229,6 +4229,7 @@ dependencies = [
|
||||
"nym-crypto",
|
||||
"nym-ecash-signer-check-types",
|
||||
"nym-ecash-time",
|
||||
"nym-kkt-ciphersuite",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-network-defaults",
|
||||
"nym-node-requests",
|
||||
|
||||
@@ -28,7 +28,7 @@ url = { workspace = true }
|
||||
# Nym crates
|
||||
nym-api-requests = { path = "../../nym-api/nym-api-requests" }
|
||||
nym-crypto = { path = "../../common/crypto" }
|
||||
nym-kkt-ciphersuite = { path = "../../common/nym-kkt-ciphersuite" }
|
||||
nym-kkt-ciphersuite = { workspace = true }
|
||||
nym-http-api-client = { path = "../../common/http-api-client" }
|
||||
nym-kcp = { path = "../../common/nym-kcp" }
|
||||
nym-lp = { path = "../../common/nym-lp" }
|
||||
|
||||
@@ -117,8 +117,6 @@ impl SpeedtestClient {
|
||||
self.gateway.lp_address
|
||||
);
|
||||
|
||||
let client_ip = "0.0.0.0".parse()?;
|
||||
|
||||
let gw_peer = LpRemotePeer::new(self.gateway.identity, self.gateway.identity.to_x25519()?)
|
||||
.with_kem_key_digests(self.gateway.kem_key_hashes.clone());
|
||||
|
||||
@@ -126,7 +124,6 @@ impl SpeedtestClient {
|
||||
self.identity_keypair.clone(),
|
||||
gw_peer,
|
||||
self.gateway.lp_address,
|
||||
client_ip,
|
||||
);
|
||||
|
||||
let start = Instant::now();
|
||||
@@ -163,8 +160,6 @@ impl SpeedtestClient {
|
||||
self.gateway.lp_address
|
||||
);
|
||||
|
||||
let client_ip = "0.0.0.0".parse()?;
|
||||
|
||||
let gw_peer = LpRemotePeer::new(self.gateway.identity, self.gateway.identity.to_x25519()?)
|
||||
.with_kem_key_digests(self.gateway.kem_key_hashes.clone());
|
||||
|
||||
@@ -172,7 +167,6 @@ impl SpeedtestClient {
|
||||
self.identity_keypair.clone(),
|
||||
gw_peer,
|
||||
self.gateway.lp_address,
|
||||
client_ip,
|
||||
);
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
Reference in New Issue
Block a user