diff --git a/common/bandwidth-controller/src/lib.rs b/common/bandwidth-controller/src/lib.rs index 31d499dac9..d508f48be1 100644 --- a/common/bandwidth-controller/src/lib.rs +++ b/common/bandwidth-controller/src/lib.rs @@ -18,6 +18,7 @@ pub mod acquire; pub mod error; mod utils; +#[derive(Debug)] pub struct BandwidthController { storage: St, client: C, diff --git a/common/client-core/src/init/types.rs b/common/client-core/src/init/types.rs index 141bf8dd2d..8008656354 100644 --- a/common/client-core/src/init/types.rs +++ b/common/client-core/src/init/types.rs @@ -178,6 +178,13 @@ impl From> for GatewayDetails { } } +#[derive(Clone, Debug)] +pub enum GatewaySelectionSpecificationInput { + GatewayIdentity(String), + LatencyBased, + Uniform, +} + #[derive(Clone, Debug)] pub enum GatewaySelectionSpecification { /// Uniformly choose a random remote gateway. @@ -226,8 +233,26 @@ impl GatewaySelectionSpecification { GatewaySelectionSpecification::UniformRemote { must_use_tls } } } + + pub fn new_from_input(input: GatewaySelectionSpecificationInput, must_use_tls: bool) -> Self { + match input { + GatewaySelectionSpecificationInput::GatewayIdentity(identity) => { + GatewaySelectionSpecification::Specified { + identity, + must_use_tls, + } + } + GatewaySelectionSpecificationInput::LatencyBased => { + GatewaySelectionSpecification::RemoteByLatency { must_use_tls } + } + GatewaySelectionSpecificationInput::Uniform => { + GatewaySelectionSpecification::UniformRemote { must_use_tls } + } + } + } } +#[derive(Debug)] pub enum GatewaySetup { /// The gateway specification (details + keys) MUST BE loaded from the underlying storage. MustLoad, diff --git a/common/client-libs/gateway-client/src/client.rs b/common/client-libs/gateway-client/src/client.rs index 46b4816e2d..68deefb8b2 100644 --- a/common/client-libs/gateway-client/src/client.rs +++ b/common/client-libs/gateway-client/src/client.rs @@ -64,6 +64,7 @@ pub struct GatewayConfig { } // TODO: this should be refactored into a state machine that keeps track of its authentication state +#[derive(Debug)] pub struct GatewayClient { authenticated: bool, disabled_credentials_mode: bool, @@ -826,6 +827,7 @@ impl GatewayClient { // type alias for an ease of use pub type InitGatewayClient = GatewayClient; +#[derive(Debug)] pub struct InitOnly; impl GatewayClient { diff --git a/common/client-libs/gateway-client/src/socket_state.rs b/common/client-libs/gateway-client/src/socket_state.rs index afc50c7233..6498df2402 100644 --- a/common/client-libs/gateway-client/src/socket_state.rs +++ b/common/client-libs/gateway-client/src/socket_state.rs @@ -52,6 +52,7 @@ pub(crate) fn ws_fd(_conn: &WsConn) -> Option { None } +#[derive(Debug)] pub(crate) struct PartiallyDelegated { sink_half: SplitSink, delegated_stream: (SplitStreamReceiver, oneshot::Sender<()>), @@ -224,6 +225,7 @@ impl PartiallyDelegated { // we can either have the stream itself or an option to re-obtain it // by notifying the future owning it to finish the execution and awaiting the result // which should be almost immediate (or an invalid state which should never, ever happen) +#[derive(Debug)] pub(crate) enum SocketState { Available(Box), PartiallyDelegated(PartiallyDelegated), diff --git a/common/credential-storage/src/ephemeral_storage.rs b/common/credential-storage/src/ephemeral_storage.rs index 5b1b5b23e9..6b9f6427e5 100644 --- a/common/credential-storage/src/ephemeral_storage.rs +++ b/common/credential-storage/src/ephemeral_storage.rs @@ -23,6 +23,12 @@ impl Default for EphemeralStorage { } } +impl std::fmt::Debug for EphemeralStorage { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "EphemeralStorage {{ .. }}") + } +} + #[async_trait] impl Storage for EphemeralStorage { type StorageError = StorageError; diff --git a/sdk/rust/nym-sdk/src/mixnet.rs b/sdk/rust/nym-sdk/src/mixnet.rs index b54ef462ee..4419720ea6 100644 --- a/sdk/rust/nym-sdk/src/mixnet.rs +++ b/sdk/rust/nym-sdk/src/mixnet.rs @@ -39,7 +39,7 @@ mod socks5_client; mod traits; pub use client::{DisconnectedMixnetClient, IncludedSurbs, MixnetClientBuilder}; -pub use config::{Config, KeyMode}; +pub use config::{Config, KeyMode, RequestGateway}; pub use native_client::MixnetClient; pub use native_client::MixnetClientSender; pub use nym_client_core::{ diff --git a/sdk/rust/nym-sdk/src/mixnet/client.rs b/sdk/rust/nym-sdk/src/mixnet/client.rs index 69995214b8..d1453e0705 100644 --- a/sdk/rust/nym-sdk/src/mixnet/client.rs +++ b/sdk/rust/nym-sdk/src/mixnet/client.rs @@ -1,7 +1,7 @@ // Copyright 2022-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use super::{connection_state::BuilderState, Config, StoragePaths}; +use super::{connection_state::BuilderState, Config, RequestGateway, StoragePaths}; use crate::bandwidth::BandwidthAcquireClient; use crate::mixnet::socks5_client::Socks5MixnetClient; use crate::mixnet::{CredentialStorage, MixnetClient, Recipient}; @@ -21,7 +21,9 @@ use nym_client_core::client::base_client::BaseClient; use nym_client_core::client::key_manager::persistence::KeyStore; use nym_client_core::config::DebugConfig; use nym_client_core::init::helpers::current_gateways; -use nym_client_core::init::types::{GatewaySelectionSpecification, GatewaySetup}; +use nym_client_core::init::types::{ + GatewaySelectionSpecification, GatewaySelectionSpecificationInput, GatewaySetup, +}; use nym_client_core::{ client::{base_client::BaseClientBuilder, replies::reply_storage::ReplyStorageBackend}, config::GatewayEndpointConfig, @@ -155,11 +157,23 @@ where /// Request a specific gateway instead of a random one. #[must_use] - pub fn request_gateway(mut self, user_chosen_gateway: String) -> Self { + // pub fn request_gateway(mut self, user_chosen_gateway: String) -> Self { + pub fn request_gateway(mut self, user_chosen_gateway: RequestGateway) -> Self { self.config.user_chosen_gateway = Some(user_chosen_gateway); self } + /* + /// When a random entry gateway is selected, we skew the probability of selection towards + /// gateways with lower latency. + /// If a specific requested gateway is selected, this will en up doing nothing. + #[must_use] + pub fn latency_based_selection(mut self, latency_based_selection: bool) -> Self { + self.config.latency_based_entry_gateway_selection = Some(latency_based_selection); + self + } + */ + /// Use a specific network instead of the default (mainnet) one. #[must_use] pub fn network_details(mut self, network_details: NymNetworkDetails) -> Self { @@ -466,9 +480,9 @@ where let gateway_setup = if self.has_valid_gateway_info().await { GatewaySetup::MustLoad } else { - let selection_spec = GatewaySelectionSpecification::new( - self.config.user_chosen_gateway.clone(), - None, + let gateway_selection = map_maybe_user_chosen_gateway_to_gateway_selection_specification_input(&self.config.user_chosen_gateway); + let selection_spec = GatewaySelectionSpecification::new_from_input( + gateway_selection, self.force_tls, ); @@ -529,11 +543,13 @@ where let known_gateway = self.has_valid_gateway_info().await; let mut base_builder: BaseClientBuilder<_, _> = if !known_gateway { - let selection_spec = GatewaySelectionSpecification::new( - self.config.user_chosen_gateway, - None, - self.force_tls, - ); + let gateway_selection = + map_maybe_user_chosen_gateway_to_gateway_selection_specification_input( + &self.config.user_chosen_gateway, + ); + let selection_spec = + GatewaySelectionSpecification::new_from_input(gateway_selection, self.force_tls); + log::error!("Gateway selection specification: {:?}", selection_spec); let mut rng = OsRng; let mut available_gateways = current_gateways(&mut rng, &nym_api_endpoints).await?; @@ -747,3 +763,17 @@ impl IncludedSurbs { Self::ExposeSelfAddress } } + +fn map_maybe_user_chosen_gateway_to_gateway_selection_specification_input( + user_chosen_gateway: &Option, +) -> GatewaySelectionSpecificationInput { + match user_chosen_gateway { + Some(selection) => match selection { + RequestGateway::UserChosen(selection) => { + GatewaySelectionSpecificationInput::GatewayIdentity(selection.clone()) + } + RequestGateway::LatencyBased => GatewaySelectionSpecificationInput::LatencyBased, + }, + None => GatewaySelectionSpecificationInput::Uniform, + } +} diff --git a/sdk/rust/nym-sdk/src/mixnet/config.rs b/sdk/rust/nym-sdk/src/mixnet/config.rs index 264f857413..ace2661b60 100644 --- a/sdk/rust/nym-sdk/src/mixnet/config.rs +++ b/sdk/rust/nym-sdk/src/mixnet/config.rs @@ -1,4 +1,6 @@ -use nym_client_core::config::{Client as ClientConfig, DebugConfig}; +use nym_client_core::{ + config::{Client as ClientConfig, DebugConfig}, +}; use nym_network_defaults::NymNetworkDetails; use nym_socks5_client_core::config::BaseClientConfig; use url::Url; @@ -20,12 +22,20 @@ impl KeyMode { } } +#[derive(Clone, Debug)] +pub enum RequestGateway { + UserChosen(String), + LatencyBased, +} + /// Config struct for [`crate::mixnet::MixnetClient`] #[derive(Default)] pub struct Config { /// If the user has explicitly specified a gateway. - pub user_chosen_gateway: Option, + // pub user_chosen_gateway: Option, + pub user_chosen_gateway: Option, + // pub latency_based_entry_gateway_selection: Option, /// Determines how to handle existing key files found. pub key_mode: KeyMode,