further adjusting storage and setup to allow for wg use
This commit is contained in:
+2
-1
@@ -24,7 +24,8 @@ CREATE TABLE remote_gateway_details
|
||||
gateway_id_bs58 TEXT NOT NULL UNIQUE PRIMARY KEY REFERENCES registered_gateway (gateway_id_bs58),
|
||||
derived_aes128_ctr_blake3_hmac_keys_bs58 TEXT NOT NULL,
|
||||
gateway_owner_address TEXT NOT NULL,
|
||||
gateway_listener TEXT NOT NULL
|
||||
gateway_listener TEXT NOT NULL,
|
||||
wg_tun_address TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE custom_gateway_details
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::types::GatewayRegistration;
|
||||
use crate::{GatewaysDetailsStore, StorageError};
|
||||
use crate::{ActiveGateway, GatewaysDetailsStore, StorageError};
|
||||
use async_trait::async_trait;
|
||||
use manager::StorageManager;
|
||||
use std::path::Path;
|
||||
@@ -26,11 +26,12 @@ impl OnDiskGatewaysDetails {
|
||||
#[async_trait]
|
||||
impl GatewaysDetailsStore for OnDiskGatewaysDetails {
|
||||
type StorageError = error::StorageError;
|
||||
|
||||
|
||||
async fn has_gateway_details(&self, gateway_id: &str) -> Result<bool, Self::StorageError> {
|
||||
todo!()
|
||||
}
|
||||
async fn active_gateway(&self) -> Result<Option<GatewayRegistration>, Self::StorageError> {
|
||||
|
||||
async fn active_gateway(&self) -> Result<ActiveGateway, Self::StorageError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::types::GatewayRegistration;
|
||||
use crate::types::{ActiveGateway, GatewayRegistration};
|
||||
use crate::{BadGateway, GatewaysDetailsStore};
|
||||
use async_trait::async_trait;
|
||||
use std::collections::HashMap;
|
||||
@@ -38,14 +38,16 @@ impl GatewaysDetailsStore for InMemGatewaysDetails {
|
||||
Ok(self.inner.read().await.gateways.contains_key(gateway_id))
|
||||
}
|
||||
|
||||
async fn active_gateway(&self) -> Result<Option<GatewayRegistration>, Self::StorageError> {
|
||||
async fn active_gateway(&self) -> Result<ActiveGateway, Self::StorageError> {
|
||||
let guard = self.inner.read().await;
|
||||
|
||||
Ok(guard.active_gateway.as_ref().map(|id| {
|
||||
let registration = guard.active_gateway.as_ref().map(|id| {
|
||||
// SAFETY: if particular gateway is set as active, its details MUST exist
|
||||
#[allow(clippy::unwrap_used)]
|
||||
guard.gateways.get(id).unwrap().clone()
|
||||
}))
|
||||
});
|
||||
|
||||
Ok(ActiveGateway { registration })
|
||||
}
|
||||
|
||||
async fn set_active_gateway(&self, gateway_id: &str) -> Result<(), Self::StorageError> {
|
||||
|
||||
@@ -13,8 +13,8 @@ pub mod types;
|
||||
|
||||
// todo: export port types
|
||||
pub use crate::types::{
|
||||
CustomGatewayDetails, GatewayDetails, GatewayRegistration, GatewayType, RegisteredGateway,
|
||||
RemoteGatewayDetails,
|
||||
ActiveGateway, CustomGatewayDetails, GatewayDetails, GatewayRegistration, GatewayType,
|
||||
RegisteredGateway, RemoteGatewayDetails,
|
||||
};
|
||||
pub use backend::mem_backend::{InMemGatewaysDetails, InMemStorageError};
|
||||
pub use error::BadGateway;
|
||||
@@ -29,7 +29,7 @@ pub trait GatewaysDetailsStore {
|
||||
type StorageError: Error + From<error::BadGateway>;
|
||||
|
||||
/// Returns details of the currently active gateway, if available.
|
||||
async fn active_gateway(&self) -> Result<Option<GatewayRegistration>, Self::StorageError>;
|
||||
async fn active_gateway(&self) -> Result<ActiveGateway, Self::StorageError>;
|
||||
|
||||
/// Set the provided gateway as the currently active gateway.
|
||||
async fn set_active_gateway(&self, gateway_id: &str) -> Result<(), Self::StorageError>;
|
||||
|
||||
@@ -16,6 +16,11 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
pub const REMOTE_GATEWAY_TYPE: &str = "remote";
|
||||
pub const CUSTOM_GATEWAY_TYPE: &str = "custom";
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ActiveGateway {
|
||||
pub registration: Option<GatewayRegistration>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct GatewayRegistration {
|
||||
pub details: GatewayDetails,
|
||||
@@ -46,12 +51,14 @@ impl GatewayDetails {
|
||||
derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
|
||||
gateway_owner_address: AccountId,
|
||||
gateway_listener: Url,
|
||||
wg_tun_address: Option<Url>,
|
||||
) -> Self {
|
||||
GatewayDetails::Remote(RemoteGatewayDetails {
|
||||
gateway_id,
|
||||
derived_aes128_ctr_blake3_hmac_keys,
|
||||
gateway_owner_address,
|
||||
gateway_listener,
|
||||
wg_tun_address,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -136,6 +143,7 @@ pub struct RawRemoteGatewayDetails {
|
||||
pub derived_aes128_ctr_blake3_hmac_keys_bs58: String,
|
||||
pub gateway_owner_address: String,
|
||||
pub gateway_listener: String,
|
||||
pub wg_tun_address: Option<String>,
|
||||
}
|
||||
|
||||
impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
|
||||
@@ -175,11 +183,24 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
|
||||
}
|
||||
})?;
|
||||
|
||||
let wg_tun_address = value
|
||||
.wg_tun_address
|
||||
.as_ref()
|
||||
.map(|addr| {
|
||||
Url::parse(addr).map_err(|source| BadGateway::MalformedListener {
|
||||
gateway_id: value.gateway_id_bs58.clone(),
|
||||
raw_listener: addr.clone(),
|
||||
source,
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
Ok(RemoteGatewayDetails {
|
||||
gateway_id,
|
||||
derived_aes128_ctr_blake3_hmac_keys,
|
||||
gateway_owner_address,
|
||||
gateway_listener,
|
||||
wg_tun_address,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -193,6 +214,7 @@ impl From<RemoteGatewayDetails> for RawRemoteGatewayDetails {
|
||||
.to_base58_string(),
|
||||
gateway_owner_address: value.gateway_owner_address.to_string(),
|
||||
gateway_listener: value.gateway_listener.to_string(),
|
||||
wg_tun_address: value.wg_tun_address.map(|addr| addr.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -208,6 +230,8 @@ pub struct RemoteGatewayDetails {
|
||||
pub gateway_owner_address: AccountId,
|
||||
|
||||
pub gateway_listener: Url,
|
||||
|
||||
pub wg_tun_address: Option<Url>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
||||
@@ -236,6 +236,7 @@ where
|
||||
specification: selection_spec,
|
||||
available_gateways,
|
||||
overwrite_data: common_args.force_register_gateway,
|
||||
wg_tun_address: None,
|
||||
};
|
||||
|
||||
let init_details =
|
||||
|
||||
@@ -35,7 +35,7 @@ use crate::init::{
|
||||
};
|
||||
use crate::{config, spawn_future};
|
||||
use futures::channel::mpsc;
|
||||
use log::{debug, error, info};
|
||||
use log::{debug, error, info, warn};
|
||||
use nym_bandwidth_controller::BandwidthController;
|
||||
use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore};
|
||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||
@@ -43,6 +43,7 @@ use nym_crypto::asymmetric::encryption;
|
||||
use nym_gateway_client::{
|
||||
AcknowledgementReceiver, GatewayClient, GatewayConfig, MixnetMessageReceiver, PacketRouter,
|
||||
};
|
||||
use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, WG_TUN_DEVICE_ADDRESS};
|
||||
use nym_sphinx::acknowledgements::AckKey;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::addressing::nodes::NodeIdentity;
|
||||
@@ -179,6 +180,7 @@ pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
|
||||
dkg_query_client: Option<C>,
|
||||
|
||||
wait_for_gateway: bool,
|
||||
wireguard_connection: bool,
|
||||
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
||||
shutdown: Option<TaskClient>,
|
||||
@@ -201,6 +203,7 @@ where
|
||||
client_store,
|
||||
dkg_query_client,
|
||||
wait_for_gateway: false,
|
||||
wireguard_connection: false,
|
||||
custom_topology_provider: None,
|
||||
custom_gateway_transceiver: None,
|
||||
shutdown: None,
|
||||
@@ -220,6 +223,12 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_wireguard_connection(mut self, wireguard_connection: bool) -> Self {
|
||||
self.wireguard_connection = wireguard_connection;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_topology_provider(
|
||||
mut self,
|
||||
@@ -343,6 +352,7 @@ where
|
||||
|
||||
async fn start_gateway_client(
|
||||
config: &Config,
|
||||
wireguard_connection: bool,
|
||||
initialisation_result: InitialisationResult,
|
||||
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
|
||||
packet_router: PacketRouter,
|
||||
@@ -358,27 +368,41 @@ where
|
||||
return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails);
|
||||
};
|
||||
|
||||
let mut gateway_client =
|
||||
if let Some(existing_client) = initialisation_result.authenticated_ephemeral_client {
|
||||
existing_client.upgrade(packet_router, bandwidth_controller, shutdown)
|
||||
let mut gateway_client = if let Some(existing_client) =
|
||||
initialisation_result.authenticated_ephemeral_client
|
||||
{
|
||||
existing_client.upgrade(packet_router, bandwidth_controller, shutdown)
|
||||
} else {
|
||||
let gateway_listener = if wireguard_connection {
|
||||
if let Some(tun_address) = details.wg_tun_address {
|
||||
tun_address.to_string()
|
||||
} else {
|
||||
let default =
|
||||
format!("ws://{WG_TUN_DEVICE_ADDRESS}:{DEFAULT_CLIENT_LISTENING_PORT}");
|
||||
warn!("gateway {} does not have tun device address set. defaulting to '{default}'", details.gateway_id);
|
||||
default
|
||||
}
|
||||
} else {
|
||||
let cfg = GatewayConfig::new(
|
||||
details.gateway_id,
|
||||
Some(details.gateway_owner_address.to_string()),
|
||||
details.gateway_listener.to_string(),
|
||||
);
|
||||
GatewayClient::new(
|
||||
cfg,
|
||||
managed_keys.identity_keypair(),
|
||||
Some(details.derived_aes128_ctr_blake3_hmac_keys),
|
||||
packet_router,
|
||||
bandwidth_controller,
|
||||
shutdown,
|
||||
)
|
||||
.with_disabled_credentials_mode(config.client.disabled_credentials_mode)
|
||||
.with_response_timeout(config.debug.gateway_connection.gateway_response_timeout)
|
||||
details.gateway_listener.to_string()
|
||||
};
|
||||
|
||||
let cfg = GatewayConfig::new(
|
||||
details.gateway_id,
|
||||
Some(details.gateway_owner_address.to_string()),
|
||||
gateway_listener,
|
||||
);
|
||||
GatewayClient::new(
|
||||
cfg,
|
||||
managed_keys.identity_keypair(),
|
||||
Some(details.derived_aes128_ctr_blake3_hmac_keys),
|
||||
packet_router,
|
||||
bandwidth_controller,
|
||||
shutdown,
|
||||
)
|
||||
.with_disabled_credentials_mode(config.client.disabled_credentials_mode)
|
||||
.with_response_timeout(config.debug.gateway_connection.gateway_response_timeout)
|
||||
};
|
||||
|
||||
gateway_client
|
||||
.authenticate_and_start()
|
||||
.await
|
||||
@@ -396,6 +420,7 @@ where
|
||||
async fn setup_gateway_transceiver(
|
||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
||||
config: &Config,
|
||||
wireguard_connection: bool,
|
||||
initialisation_result: InitialisationResult,
|
||||
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
|
||||
packet_router: PacketRouter,
|
||||
@@ -424,6 +449,7 @@ where
|
||||
// otherwise, setup normal gateway client, etc
|
||||
let gateway_client = Self::start_gateway_client(
|
||||
config,
|
||||
wireguard_connection,
|
||||
initialisation_result,
|
||||
bandwidth_controller,
|
||||
packet_router,
|
||||
@@ -680,6 +706,7 @@ where
|
||||
let gateway_transceiver = Self::setup_gateway_transceiver(
|
||||
self.custom_gateway_transceiver,
|
||||
self.config,
|
||||
self.wireguard_connection,
|
||||
init_res,
|
||||
bandwidth_controller,
|
||||
gateway_packet_router,
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::client::key_manager::persistence::KeyStore;
|
||||
use crate::client::key_manager::ClientKeys;
|
||||
use crate::error::ClientCoreError;
|
||||
use nym_client_core_gateways_storage::{
|
||||
GatewayRegistration, GatewaysDetailsStore, GatewaysDetailsStoreExt,
|
||||
ActiveGateway, GatewayRegistration, GatewaysDetailsStore, GatewaysDetailsStoreExt,
|
||||
};
|
||||
use nym_crypto::asymmetric::identity;
|
||||
|
||||
@@ -59,18 +59,16 @@ where
|
||||
|
||||
pub async fn load_active_gateway_details<D>(
|
||||
details_store: &D,
|
||||
) -> Result<GatewayRegistration, ClientCoreError>
|
||||
) -> Result<ActiveGateway, ClientCoreError>
|
||||
where
|
||||
D: GatewaysDetailsStore,
|
||||
D::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
details_store
|
||||
.active_gateway()
|
||||
.await
|
||||
.map_err(|source| ClientCoreError::GatewaysDetailsStoreError {
|
||||
details_store.active_gateway().await.map_err(|source| {
|
||||
ClientCoreError::GatewaysDetailsStoreError {
|
||||
source: Box::new(source),
|
||||
})?
|
||||
.ok_or(ClientCoreError::NoActiveGatewaySet)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn load_gateway_details<D>(
|
||||
|
||||
@@ -102,6 +102,7 @@ pub mod v1_1_33 {
|
||||
message: format!("the stored gateway listener address was malformed: {err}"),
|
||||
}
|
||||
})?,
|
||||
wg_tun_address: None,
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ use nym_topology::gateway;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use serde::Serialize;
|
||||
use std::net::IpAddr;
|
||||
|
||||
pub mod helpers;
|
||||
pub mod types;
|
||||
@@ -46,19 +47,13 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
// fn ensure_valid_details(
|
||||
// details: &PersistedGatewayDetails,
|
||||
// loaded_keys: &ManagedKeys,
|
||||
// ) -> Result<(), ClientCoreError> {
|
||||
// details.validate(loaded_keys.gateway_shared_key().as_deref())
|
||||
// }
|
||||
|
||||
async fn setup_new_gateway<K, D>(
|
||||
key_store: &K,
|
||||
details_store: &D,
|
||||
overwrite_data: bool,
|
||||
selection_specification: GatewaySelectionSpecification,
|
||||
available_gateways: Vec<gateway::Node>,
|
||||
wg_tun_ip_address: Option<IpAddr>,
|
||||
) -> Result<InitialisationResult, ClientCoreError>
|
||||
where
|
||||
K: KeyStore,
|
||||
@@ -76,19 +71,19 @@ where
|
||||
let selected_gateway = match selection_specification {
|
||||
GatewaySelectionSpecification::UniformRemote { must_use_tls } => {
|
||||
let gateway = uniformly_random_gateway(&mut rng, &available_gateways, must_use_tls)?;
|
||||
SelectedGateway::from_topology_node(gateway, must_use_tls)?
|
||||
SelectedGateway::from_topology_node(gateway, wg_tun_ip_address, must_use_tls)?
|
||||
}
|
||||
GatewaySelectionSpecification::RemoteByLatency { must_use_tls } => {
|
||||
let gateway =
|
||||
choose_gateway_by_latency(&mut rng, &available_gateways, must_use_tls).await?;
|
||||
SelectedGateway::from_topology_node(gateway, must_use_tls)?
|
||||
SelectedGateway::from_topology_node(gateway, wg_tun_ip_address, must_use_tls)?
|
||||
}
|
||||
GatewaySelectionSpecification::Specified {
|
||||
must_use_tls,
|
||||
identity,
|
||||
} => {
|
||||
let gateway = get_specified_gateway(&identity, &available_gateways, must_use_tls)?;
|
||||
SelectedGateway::from_topology_node(gateway, must_use_tls)?
|
||||
SelectedGateway::from_topology_node(gateway, wg_tun_ip_address, must_use_tls)?
|
||||
}
|
||||
GatewaySelectionSpecification::Custom {
|
||||
gateway_identity,
|
||||
@@ -110,18 +105,23 @@ where
|
||||
gateway_id,
|
||||
gateway_owner_address,
|
||||
gateway_listener,
|
||||
wg_tun_address,
|
||||
} => {
|
||||
// if we're using a 'normal' gateway setup, do register
|
||||
let our_identity = client_keys.identity_keypair();
|
||||
|
||||
// if wg address is set, use that one
|
||||
let url = wg_tun_address.clone().unwrap_or(gateway_listener.clone());
|
||||
|
||||
let registration =
|
||||
helpers::register_with_gateway(gateway_id, gateway_listener.clone(), our_identity)
|
||||
.await?;
|
||||
helpers::register_with_gateway(gateway_id, url, our_identity).await?;
|
||||
(
|
||||
GatewayDetails::new_remote(
|
||||
gateway_id,
|
||||
registration.shared_keys,
|
||||
gateway_owner_address,
|
||||
gateway_listener,
|
||||
wg_tun_address,
|
||||
),
|
||||
Some(registration.authenticated_ephemeral_client),
|
||||
)
|
||||
@@ -161,7 +161,10 @@ where
|
||||
let loaded_details = if let Some(gateway_id) = gateway_id {
|
||||
load_gateway_details(details_store, &gateway_id).await?
|
||||
} else {
|
||||
load_active_gateway_details(details_store).await?
|
||||
load_active_gateway_details(details_store)
|
||||
.await?
|
||||
.registration
|
||||
.ok_or(ClientCoreError::NoActiveGatewaySet)?
|
||||
};
|
||||
|
||||
let loaded_keys = load_client_keys(key_store).await?;
|
||||
@@ -205,6 +208,7 @@ where
|
||||
specification,
|
||||
available_gateways,
|
||||
overwrite_data,
|
||||
wg_tun_address,
|
||||
} => {
|
||||
setup_new_gateway(
|
||||
key_store,
|
||||
@@ -212,6 +216,7 @@ where
|
||||
overwrite_data,
|
||||
specification,
|
||||
available_gateways,
|
||||
wg_tun_address,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::client::key_manager::ClientKeys;
|
||||
use crate::config::Config;
|
||||
use crate::error::ClientCoreError;
|
||||
use crate::init::{setup_gateway, use_loaded_gateway_details};
|
||||
use log::info;
|
||||
use nym_client_core_gateways_storage::{
|
||||
GatewayRegistration, GatewaysDetailsStore, RemoteGatewayDetails,
|
||||
};
|
||||
@@ -18,6 +19,7 @@ use nym_validator_client::client::IdentityKey;
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use serde::Serialize;
|
||||
use std::fmt::Display;
|
||||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use time::OffsetDateTime;
|
||||
@@ -30,6 +32,8 @@ pub enum SelectedGateway {
|
||||
gateway_owner_address: AccountId,
|
||||
|
||||
gateway_listener: Url,
|
||||
|
||||
wg_tun_address: Option<Url>,
|
||||
},
|
||||
Custom {
|
||||
gateway_id: identity::PublicKey,
|
||||
@@ -37,9 +41,36 @@ pub enum SelectedGateway {
|
||||
},
|
||||
}
|
||||
|
||||
fn wg_tun_address(
|
||||
tun_ip: Option<IpAddr>,
|
||||
gateway: &gateway::Node,
|
||||
) -> Result<Option<Url>, ClientCoreError> {
|
||||
let Some(tun_ip) = tun_ip else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
// log this so we'd remember about it if we ever decided to actually use that port
|
||||
if gateway.clients_wss_port.is_some() {
|
||||
info!(
|
||||
"gateway {} exposes wss but for wireguard we're going to use ws",
|
||||
gateway.identity_key
|
||||
);
|
||||
}
|
||||
|
||||
let raw_url = format!("ws://{tun_ip}:{}", gateway.clients_ws_port);
|
||||
Ok(Some(raw_url.as_str().parse().map_err(|source| {
|
||||
ClientCoreError::MalformedListener {
|
||||
gateway_id: gateway.identity_key.to_base58_string(),
|
||||
raw_listener: raw_url,
|
||||
source,
|
||||
}
|
||||
})?))
|
||||
}
|
||||
|
||||
impl SelectedGateway {
|
||||
pub fn from_topology_node(
|
||||
node: gateway::Node,
|
||||
wg_tun_ip_address: Option<IpAddr>,
|
||||
must_use_tls: bool,
|
||||
) -> Result<Self, ClientCoreError> {
|
||||
let gateway_listener = if must_use_tls {
|
||||
@@ -51,6 +82,8 @@ impl SelectedGateway {
|
||||
node.clients_address()
|
||||
};
|
||||
|
||||
let wg_tun_address = wg_tun_address(wg_tun_ip_address, &node)?;
|
||||
|
||||
let gateway_owner_address = AccountId::from_str(&node.owner).map_err(|source| {
|
||||
ClientCoreError::MalformedGatewayOwnerAccountAddress {
|
||||
gateway_id: node.identity_key.to_base58_string(),
|
||||
@@ -70,6 +103,7 @@ impl SelectedGateway {
|
||||
gateway_id: node.identity_key,
|
||||
gateway_owner_address,
|
||||
gateway_listener,
|
||||
wg_tun_address,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -209,6 +243,12 @@ pub enum GatewaySetup {
|
||||
|
||||
/// Specifies whether old data should be overwritten whilst setting up new gateway client.
|
||||
overwrite_data: bool,
|
||||
|
||||
/// Implicitly specify whether the chosen gateway must use wireguard mode by setting the tun address.
|
||||
///
|
||||
/// Currently this is imperfect solution as I'd imagine this address could vary from gateway to gateway
|
||||
/// so perhaps it should be part of gateway::Node struct
|
||||
wg_tun_address: Option<IpAddr>,
|
||||
},
|
||||
|
||||
ReuseConnection {
|
||||
@@ -235,6 +275,19 @@ impl GatewaySetup {
|
||||
}
|
||||
}
|
||||
|
||||
/// new gateway setup performed by each client that's inbuilt in a gateway (like NR or IPR)
|
||||
pub fn new_inbuilt(identity: identity::PublicKey) -> Self {
|
||||
GatewaySetup::New {
|
||||
specification: GatewaySelectionSpecification::Custom {
|
||||
gateway_identity: identity.to_base58_string(),
|
||||
additional_data: None,
|
||||
},
|
||||
available_gateways: vec![],
|
||||
overwrite_data: false,
|
||||
wg_tun_address: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn try_setup<K, D>(
|
||||
self,
|
||||
key_store: &K,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
use crate::var_names::{DEPRECATED_API_VALIDATOR, DEPRECATED_NYMD_VALIDATOR, NYM_API, NYXD};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::path::Path;
|
||||
use std::{
|
||||
env::{var, VarError},
|
||||
@@ -521,4 +522,5 @@ pub const WG_PORT: u16 = 51822;
|
||||
// The interface used to route traffic
|
||||
pub const WG_TUN_BASE_NAME: &str = "nymwg";
|
||||
pub const WG_TUN_DEVICE_ADDRESS: &str = "10.1.0.1";
|
||||
pub const WG_TUN_DEVICE_IP_ADDRESS: IpAddr = IpAddr::V4(Ipv4Addr::new(10, 1, 0, 1));
|
||||
pub const WG_TUN_DEVICE_NETMASK: &str = "255.255.255.0";
|
||||
|
||||
@@ -16,10 +16,7 @@ use nym_network_defaults::mainnet;
|
||||
use nym_network_defaults::var_names::NYXD;
|
||||
use nym_network_defaults::var_names::{BECH32_PREFIX, NYM_API, STATISTICS_SERVICE_DOMAIN_ADDRESS};
|
||||
use nym_network_requester::config::BaseClientConfig;
|
||||
use nym_network_requester::{
|
||||
setup_fs_gateways_storage, setup_gateway, GatewaySelectionSpecification, GatewaySetup,
|
||||
OnDiskKeys,
|
||||
};
|
||||
use nym_network_requester::{setup_fs_gateways_storage, setup_gateway, GatewaySetup, OnDiskKeys};
|
||||
use nym_types::gateway::{GatewayIpPacketRouterDetails, GatewayNetworkRequesterDetails};
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use std::net::IpAddr;
|
||||
@@ -251,7 +248,7 @@ pub(crate) fn override_ip_packet_router_config(
|
||||
|
||||
// disable poisson rate in the BASE client if the IPR option is enabled
|
||||
if cfg.ip_packet_router.disable_poisson_rate {
|
||||
log::info!("Disabling poisson rate for ip packet router");
|
||||
info!("Disabling poisson rate for ip packet router");
|
||||
cfg.set_no_poisson_process();
|
||||
}
|
||||
|
||||
@@ -280,14 +277,7 @@ pub(crate) async fn initialise_local_network_requester(
|
||||
|
||||
// gateway setup here is way simpler as we're 'connecting' to ourselves
|
||||
let init_res = setup_gateway(
|
||||
GatewaySetup::New {
|
||||
specification: GatewaySelectionSpecification::Custom {
|
||||
gateway_identity: identity.to_base58_string(),
|
||||
additional_data: Default::default(),
|
||||
},
|
||||
available_gateways: vec![],
|
||||
overwrite_data: false,
|
||||
},
|
||||
GatewaySetup::new_inbuilt(identity),
|
||||
&key_store,
|
||||
&details_store,
|
||||
)
|
||||
@@ -353,14 +343,7 @@ pub(crate) async fn initialise_local_ip_packet_router(
|
||||
|
||||
// gateway setup here is way simpler as we're 'connecting' to ourselves
|
||||
let init_res = setup_gateway(
|
||||
GatewaySetup::New {
|
||||
specification: GatewaySelectionSpecification::Custom {
|
||||
gateway_identity: identity.to_base58_string(),
|
||||
additional_data: Default::default(),
|
||||
},
|
||||
available_gateways: vec![],
|
||||
overwrite_data: false,
|
||||
},
|
||||
GatewaySetup::new_inbuilt(identity),
|
||||
&key_store,
|
||||
&details_store,
|
||||
)
|
||||
|
||||
@@ -56,7 +56,7 @@ pub use nym_client_core::{
|
||||
},
|
||||
topology_control::geo_aware_provider::{CountryGroup, GeoAwareTopologyProvider},
|
||||
},
|
||||
config::{GatewayEndpointConfig, GroupBy},
|
||||
config::GroupBy,
|
||||
};
|
||||
pub use nym_credential_storage::{
|
||||
ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage,
|
||||
|
||||
@@ -11,25 +11,27 @@ use crate::{Error, Result};
|
||||
use futures::channel::mpsc;
|
||||
use futures::StreamExt;
|
||||
use log::warn;
|
||||
use nym_client_core::client::base_client::storage::helpers::get_all_registered_identities;
|
||||
use nym_client_core::client::base_client::storage::{
|
||||
Ephemeral, GatewaysDetailsStore, MixnetClientStorage, OnDiskPersistent,
|
||||
};
|
||||
use nym_client_core::client::base_client::BaseClient;
|
||||
use nym_client_core::client::key_manager::persistence::KeyStore;
|
||||
use nym_client_core::client::{
|
||||
base_client::BaseClientBuilder, replies::reply_storage::ReplyStorageBackend,
|
||||
};
|
||||
use nym_client_core::config::DebugConfig;
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_client_core::init::helpers::current_gateways;
|
||||
use nym_client_core::init::types::{GatewaySelectionSpecification, GatewaySetup};
|
||||
use nym_client_core::{
|
||||
client::{base_client::BaseClientBuilder, replies::reply_storage::ReplyStorageBackend},
|
||||
config::GatewayEndpointConfig,
|
||||
};
|
||||
use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, WG_TUN_DEVICE_ADDRESS};
|
||||
use nym_network_defaults::WG_TUN_DEVICE_IP_ADDRESS;
|
||||
use nym_socks5_client_core::config::Socks5;
|
||||
use nym_task::manager::TaskStatus;
|
||||
use nym_task::{TaskClient, TaskHandle};
|
||||
use nym_topology::provider_trait::TopologyProvider;
|
||||
use nym_validator_client::{nyxd, QueryHttpRpcNyxdClient};
|
||||
use rand::rngs::OsRng;
|
||||
use std::net::IpAddr;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use url::Url;
|
||||
@@ -41,7 +43,6 @@ const DEFAULT_NUMBER_OF_SURBS: u32 = 10;
|
||||
pub struct MixnetClientBuilder<S: MixnetClientStorage = Ephemeral> {
|
||||
config: Config,
|
||||
storage_paths: Option<StoragePaths>,
|
||||
gateway_config: Option<GatewayEndpointConfig>,
|
||||
socks5_config: Option<Socks5>,
|
||||
|
||||
wireguard_mode: bool,
|
||||
@@ -78,7 +79,6 @@ impl MixnetClientBuilder<OnDiskPersistent> {
|
||||
Ok(MixnetClientBuilder {
|
||||
config: Default::default(),
|
||||
storage_paths: None,
|
||||
gateway_config: None,
|
||||
socks5_config: None,
|
||||
wireguard_mode: false,
|
||||
wait_for_gateway: false,
|
||||
@@ -98,6 +98,7 @@ impl<S> MixnetClientBuilder<S>
|
||||
where
|
||||
S: MixnetClientStorage + 'static,
|
||||
S::ReplyStore: Send + Sync,
|
||||
S::GatewaysDetailsStore: Sync,
|
||||
<S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send,
|
||||
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync,
|
||||
<S::KeyStore as KeyStore>::StorageError: Send + Sync,
|
||||
@@ -109,7 +110,6 @@ where
|
||||
MixnetClientBuilder {
|
||||
config: Default::default(),
|
||||
storage_paths: None,
|
||||
gateway_config: None,
|
||||
socks5_config: None,
|
||||
wireguard_mode: false,
|
||||
wait_for_gateway: false,
|
||||
@@ -128,7 +128,6 @@ where
|
||||
MixnetClientBuilder {
|
||||
config: self.config,
|
||||
storage_paths: self.storage_paths,
|
||||
gateway_config: self.gateway_config,
|
||||
socks5_config: self.socks5_config,
|
||||
wireguard_mode: self.wireguard_mode,
|
||||
wait_for_gateway: self.wait_for_gateway,
|
||||
@@ -303,6 +302,7 @@ impl<S> DisconnectedMixnetClient<S>
|
||||
where
|
||||
S: MixnetClientStorage + 'static,
|
||||
S::ReplyStore: Send + Sync,
|
||||
S::GatewaysDetailsStore: Sync,
|
||||
<S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send,
|
||||
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync,
|
||||
<S::KeyStore as KeyStore>::StorageError: Send + Sync,
|
||||
@@ -410,40 +410,58 @@ where
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Client keys are generated at client creation if none were found. The gateway shared
|
||||
/// key, however, is created during the gateway registration handshake, so it might not
|
||||
/// necessarily be available.
|
||||
/// Furthermore, it has to be coupled with particular gateway's config.
|
||||
async fn has_valid_gateway_info(&self) -> bool {
|
||||
let keys = match self.storage.key_store().load_keys().await {
|
||||
Ok(keys) => keys,
|
||||
fn wireguard_tun_address(&self) -> Option<IpAddr> {
|
||||
// currently use a hardcoded value here, but perhaps we should change that later
|
||||
if self.wireguard_mode {
|
||||
Some(WG_TUN_DEVICE_IP_ADDRESS)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
async fn new_gateway_setup(&self) -> Result<GatewaySetup, ClientCoreError> {
|
||||
let nym_api_endpoints = self.get_api_endpoints();
|
||||
|
||||
let selection_spec = GatewaySelectionSpecification::new(
|
||||
self.config.user_chosen_gateway.clone(),
|
||||
None,
|
||||
self.force_tls,
|
||||
);
|
||||
|
||||
let mut rng = OsRng;
|
||||
let available_gateways = current_gateways(&mut rng, &nym_api_endpoints).await?;
|
||||
|
||||
Ok(GatewaySetup::New {
|
||||
specification: selection_spec,
|
||||
available_gateways,
|
||||
overwrite_data: !self.config.key_mode.is_keep(),
|
||||
wg_tun_address: self.wireguard_tun_address(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Check if the client already has an active gateway enabled.
|
||||
async fn has_active_gateway(&self) -> bool {
|
||||
let storage = self.storage.gateway_details_store();
|
||||
|
||||
if storage.active_gateway().await.is_ok() {
|
||||
return true;
|
||||
}
|
||||
|
||||
match get_all_registered_identities(storage).await {
|
||||
Err(err) => {
|
||||
warn!("failed to load stored keys: {err}");
|
||||
return false;
|
||||
warn!("failed to query for all registered gateways: {err}")
|
||||
}
|
||||
};
|
||||
Ok(all_ids) => {
|
||||
if !all_ids.is_empty() {
|
||||
warn!("this client doesn't have an active gateway set, however, it's already registered with the following gateways (consider making one of them active):");
|
||||
for id in all_ids {
|
||||
warn!("{id}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
todo!()
|
||||
|
||||
// let gateway_details = match self
|
||||
// .storage
|
||||
// .gateway_details_store()
|
||||
// .load_gateway_details()
|
||||
// .await
|
||||
// {
|
||||
// Ok(details) => details,
|
||||
// Err(err) => {
|
||||
// warn!("failed to load stored gateway details: {err}");
|
||||
// return false;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// if let Err(err) = gateway_details.validate(keys.gateway_shared_key().as_deref()) {
|
||||
// warn!("stored key verification failure: {err}");
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// true
|
||||
false
|
||||
}
|
||||
|
||||
/// Register with a gateway. If a gateway is provided in the config then that will try to be
|
||||
@@ -460,24 +478,10 @@ where
|
||||
|
||||
log::debug!("Registering with gateway");
|
||||
|
||||
let api_endpoints = self.get_api_endpoints();
|
||||
|
||||
let gateway_setup = if self.has_valid_gateway_info().await {
|
||||
let gateway_setup = if self.has_active_gateway().await {
|
||||
GatewaySetup::MustLoad { gateway_id: None }
|
||||
} else {
|
||||
let selection_spec = GatewaySelectionSpecification::new(
|
||||
self.config.user_chosen_gateway.clone(),
|
||||
None,
|
||||
self.force_tls,
|
||||
);
|
||||
|
||||
let mut rng = OsRng;
|
||||
|
||||
GatewaySetup::New {
|
||||
specification: selection_spec,
|
||||
available_gateways: current_gateways(&mut rng, &api_endpoints).await?,
|
||||
overwrite_data: !self.config.key_mode.is_keep(),
|
||||
}
|
||||
self.new_gateway_setup().await?
|
||||
};
|
||||
|
||||
// this will perform necessary key and details load and optional store
|
||||
@@ -525,60 +529,70 @@ where
|
||||
.config
|
||||
.as_base_client_config(nyxd_endpoints, nym_api_endpoints.clone());
|
||||
|
||||
let known_gateway = self.has_valid_gateway_info().await;
|
||||
let known_gateway = self.has_active_gateway().await;
|
||||
|
||||
let mut base_builder: BaseClientBuilder<_, _> = if !known_gateway {
|
||||
let selection_spec = GatewaySelectionSpecification::new(
|
||||
self.config.user_chosen_gateway,
|
||||
None,
|
||||
self.force_tls,
|
||||
);
|
||||
|
||||
let mut rng = OsRng;
|
||||
let mut available_gateways = current_gateways(&mut rng, &nym_api_endpoints).await?;
|
||||
if self.wireguard_mode {
|
||||
available_gateways
|
||||
.iter_mut()
|
||||
.for_each(|node| node.host = WG_TUN_DEVICE_ADDRESS.parse().unwrap());
|
||||
}
|
||||
let setup = GatewaySetup::New {
|
||||
specification: selection_spec,
|
||||
available_gateways,
|
||||
overwrite_data: !self.config.key_mode.is_keep(),
|
||||
};
|
||||
|
||||
BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client)
|
||||
.with_wait_for_gateway(self.wait_for_gateway)
|
||||
.with_gateway_setup(setup)
|
||||
} else if self.wireguard_mode {
|
||||
todo!()
|
||||
// if let Ok(PersistedGatewayDetails::Default(mut config)) = self
|
||||
// .storage
|
||||
// .gateway_details_store()
|
||||
// .load_gateway_details()
|
||||
// .await
|
||||
// {
|
||||
// config.details.gateway_listener = format!(
|
||||
// "ws://{}:{}",
|
||||
// WG_TUN_DEVICE_ADDRESS, DEFAULT_CLIENT_LISTENING_PORT
|
||||
// );
|
||||
// if let Err(e) = self
|
||||
// .storage
|
||||
// .gateway_details_store()
|
||||
// .store_gateway_details(&PersistedGatewayDetails::Default(config))
|
||||
// .await
|
||||
// {
|
||||
// warn!("Could not switch to using wireguard mode - {:?}", e);
|
||||
// }
|
||||
// } else {
|
||||
// warn!("Storage type not supported with wireguard mode");
|
||||
// }
|
||||
// BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client)
|
||||
// .with_wait_for_gateway(self.wait_for_gateway)
|
||||
// if we have a known gateway, don't bother doing all of those queries
|
||||
let gateway_setup = if known_gateway {
|
||||
None
|
||||
} else {
|
||||
Some(self.new_gateway_setup().await?)
|
||||
};
|
||||
|
||||
let mut base_builder: BaseClientBuilder<_, _> =
|
||||
BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client)
|
||||
.with_wait_for_gateway(self.wait_for_gateway)
|
||||
};
|
||||
.with_wireguard_connection(self.wireguard_mode);
|
||||
|
||||
if !known_gateway {
|
||||
// safety: `gateway_setup` is always set whenever `known_gateway` is false
|
||||
base_builder = base_builder.with_gateway_setup(gateway_setup.unwrap());
|
||||
}
|
||||
|
||||
// let mut base_builder: BaseClientBuilder<_, _> = if !known_gateway {
|
||||
// // we need to setup a new gateway
|
||||
// let setup = self.new_gateway_setup().await;
|
||||
//
|
||||
// BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client)
|
||||
// .with_wait_for_gateway(self.wait_for_gateway)
|
||||
// .with_gateway_setup(setup)
|
||||
// // } else if self.wireguard_mode {
|
||||
// // // load current active gateway in wireguard mode
|
||||
// // details_store.set_wireguard_mode(true).await?;
|
||||
// //
|
||||
// // if let Ok(PersistedGatewayDetails::Default(mut config)) = self
|
||||
// // .storage
|
||||
// // .gateway_details_store()
|
||||
// // .load_gateway_details()
|
||||
// // .await
|
||||
// // {
|
||||
// // config.details.gateway_listener = format!(
|
||||
// // "ws://{}:{}",
|
||||
// // WG_TUN_DEVICE_ADDRESS, DEFAULT_CLIENT_LISTENING_PORT
|
||||
// // );
|
||||
// // if let Err(e) = self
|
||||
// // .storage
|
||||
// // .gateway_details_store()
|
||||
// // .store_gateway_details(&PersistedGatewayDetails::Default(config))
|
||||
// // .await
|
||||
// // {
|
||||
// // warn!("Could not switch to using wireguard mode - {:?}", e);
|
||||
// // }
|
||||
// // } else {
|
||||
// // warn!("Storage type not supported with wireguard mode");
|
||||
// // }
|
||||
// // BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client)
|
||||
// // .with_wait_for_gateway(self.wait_for_gateway)
|
||||
// } else {
|
||||
// // load current active gateway in non-wireguard mode
|
||||
//
|
||||
// // make sure our current storage mode matches the desired wg mode
|
||||
// details_store
|
||||
// .set_wireguard_mode(self.wireguard_mode)
|
||||
// .await?;
|
||||
//
|
||||
// BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client)
|
||||
// .with_wait_for_gateway(self.wait_for_gateway)
|
||||
// };
|
||||
|
||||
if let Some(topology_provider) = self.custom_topology_provider {
|
||||
base_builder = base_builder.with_topology_provider(topology_provider);
|
||||
|
||||
Reference in New Issue
Block a user