Compare commits

...

5 Commits

Author SHA1 Message Date
mx 61610d5838 removed broken file link + updated link to correct line for default SURB amount 2023-06-30 15:43:13 +02:00
mx e31d0b27d4 pulled in renamed example file 2023-06-30 15:38:05 +02:00
Pierre Dommerc 7a1a7c003e feat(nc-desktop): add matrix and monero to providers list (ui) (#3623) 2023-06-30 12:13:52 +02:00
Jon Häggblad 2953837f25 Add medium toggle to socks5 client (#3615)
* Add medium toggle to socks5 client

* rustfmt
2023-06-28 23:47:00 +02:00
Jon Häggblad ee98820bb4 Use different service provider directory when medium toggle enabled (#3617) 2023-06-28 23:45:45 +02:00
6 changed files with 97 additions and 47 deletions
+1
View File
@@ -94,6 +94,7 @@ impl From<Init> for OverrideConfig {
use_anonymous_replies: init_config.use_reply_surbs,
fastmode: init_config.fastmode,
no_cover: init_config.no_cover,
medium_toggle: false,
nyxd_urls: init_config.nyxd_urls,
enabled_credentials_mode: init_config.enabled_credentials_mode,
outfox: false,
+17 -1
View File
@@ -19,7 +19,7 @@ use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::error::ClientCoreError;
use nym_config::OptionalSet;
use nym_sphinx::params::PacketType;
use nym_sphinx::params::{PacketSize, PacketType};
use std::error::Error;
pub mod init;
@@ -72,6 +72,7 @@ pub(crate) struct OverrideConfig {
use_anonymous_replies: Option<bool>,
fastmode: bool,
no_cover: bool,
medium_toggle: bool,
nyxd_urls: Option<Vec<url::Url>>,
enabled_credentials_mode: Option<bool>,
outfox: bool,
@@ -91,6 +92,10 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
}
pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
let disable_cover_traffic_with_keepalive = args.medium_toggle;
let secondary_packet_size = args.medium_toggle.then_some(PacketSize::ExtendedPacket16);
let no_per_hop_delays = args.medium_toggle;
let packet_type = if args.outfox {
PacketType::Outfox
} else {
@@ -101,6 +106,17 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
BaseClientConfig::with_high_default_traffic_volume,
args.fastmode,
)
.with_base(
// NOTE: This interacts with disabling cover traffic fully, so we want to this to be set before
BaseClientConfig::with_disabled_cover_traffic_with_keepalive,
disable_cover_traffic_with_keepalive,
)
.with_base(
BaseClientConfig::with_secondary_packet_size,
secondary_packet_size,
)
.with_base(BaseClientConfig::with_no_per_hop_delays, no_per_hop_delays)
// NOTE: see comment above about the order of the other disble cover traffic config
.with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover)
.with_base(BaseClientConfig::with_packet_type, packet_type)
.with_optional(Config::with_anonymous_replies, args.use_anonymous_replies)
+6
View File
@@ -60,6 +60,11 @@ pub(crate) struct Run {
#[clap(long, hide = true)]
no_cover: bool,
/// Enable medium mixnet traffic, for experiments only.
/// This includes things like disabling cover traffic, no per hop delays, etc.
#[clap(long, hide = true)]
medium_toggle: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[clap(long, hide = true)]
@@ -77,6 +82,7 @@ impl From<Run> for OverrideConfig {
use_anonymous_replies: run_config.use_anonymous_replies,
fastmode: run_config.fastmode,
no_cover: run_config.no_cover,
medium_toggle: run_config.medium_toggle,
nyxd_urls: run_config.nyxd_urls,
enabled_credentials_mode: run_config.enabled_credentials_mode,
outfox: run_config.outfox,
+3 -7
View File
@@ -47,20 +47,16 @@ The example above involves ephemeral keys - if we want to create and then mainta
As seen in the example above, the `mixnet::MixnetClientBuilder::new()` function handles checking for keys in a storage location, loading them if present, or creating them and storing them if not, making client key management very simple.
### Manually handling storage
If you're integrating mixnet functionality into an existing app and want to integrate saving client configs and keys into your existing storage logic, you can manually perform the actions taken automatically above (`examples/manually_handle_keys_and_config.rs`)
If you're integrating mixnet functionality into an existing app and want to integrate saving client configs and keys into your existing storage logic, you can manually perform the actions taken automatically above (`examples/manually_handle_storage.rs`)
```rust,noplayground
{{#include ../../../../sdk/rust/nym-sdk/examples/manually_handle_keys_and_config.rs}}
{{#include ../../../../sdk/rust/nym-sdk/examples/manually_handle_storage.rs}}
```
### Anonymous replies with SURBs
Both functions used to send messages through the mixnet (`send_str` and `send_bytes`) send a pre-determined number of SURBs along with their messages by default.
The number of SURBs is set [here](https://github.com/nymtech/nym/blob/release/{{platform_release_version}}/sdk/rust/nym-sdk/src/mixnet/client.rs#L35):
```rust,noplayground
{{#include ../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:30}}
```
The number of SURBs is set [here](https://github.com/nymtech/nym/blob/release/{{platform_release_version}}/sdk/rust/nym-sdk/src/mixnet/client.rs#L36).
You can read more about how SURBs function under the hood [here](../architecture/traffic-flow.md#private-replies-using-surbs).
@@ -10,39 +10,58 @@ use nym_contracts_common::types::Percent;
static SERVICE_PROVIDER_WELLKNOWN_URL: &str =
"https://nymtech.net/.wellknown/connect/service-providers.json";
// List of network-requesters running with medium toggle enabled, for testing
static SERVICE_PROVIDER_WELLKNOWN_URL_MEDIUM: &str =
"https://nymtech.net/.wellknown/connect/service-providers-medium.json";
static HARBOUR_MASTER_URL: &str = "https://harbourmaster.nymtech.net/v1/services/?size=100";
static GATEWAYS_DETAILED_URL: &str =
"https://validator.nymtech.net/api/v1/status/gateways/detailed";
fn get_services_url() -> &'static str {
std::env::var("NYM_CONNECT_ENABLE_MEDIUM")
.is_ok()
.then(|| SERVICE_PROVIDER_WELLKNOWN_URL_MEDIUM)
.unwrap_or(SERVICE_PROVIDER_WELLKNOWN_URL)
}
#[tauri::command]
pub async fn get_services() -> Result<Vec<DirectoryServiceProvider>> {
log::trace!("Fetching services");
let services_res = reqwest::get(SERVICE_PROVIDER_WELLKNOWN_URL)
.await?
.json::<Vec<DirectoryService>>()
.await?;
log::trace!("Received: {:#?}", services_res);
let all_services = fetch_services().await?;
log::trace!("Received: {:#?}", all_services);
log::trace!("Fetching gateways");
let gateway_res = reqwest::get(GATEWAYS_DETAILED_URL)
.await?
.json::<Vec<GatewayBondAnnotated>>()
.await?;
log::trace!("Received: {:#?}", gateway_res);
// Early return if we're running with medium toggle enabled
if std::env::var("NYM_CONNECT_ENABLE_MEDIUM").is_ok() {
return Ok(all_services.into_iter().flat_map(|sp| sp.items).collect());
}
// TODO: get paged
log::trace!("Fetching active services");
let active_services = reqwest::get(HARBOUR_MASTER_URL)
.await?
.json::<PagedResult<HarbourMasterService>>()
.await?;
let active_services = fetch_active_services().await?;
log::trace!("Active: {:#?}", active_services);
let mut filtered: Vec<DirectoryService> = vec![];
let filtered_services = filter_out_inactive(all_services, active_services);
for service in &services_res {
let items = service
log::trace!("Fetching gateways");
let gateway_res = get_gateways_detailed().await?;
log::trace!("Received: {:#?}", gateway_res);
// Use only services that are active AND have a performance of >= 90%
let filtered_services_with_good_gateway =
filter_out_poor_gateways(filtered_services, gateway_res);
Ok(filtered_services_with_good_gateway)
}
fn filter_out_inactive(
services_res: Vec<DirectoryService>,
active_services: PagedResult<HarbourMasterService>,
) -> Vec<DirectoryService> {
let mut filtered: Vec<DirectoryService> = vec![];
for service_type in &services_res {
let items = service_type
.items
.clone()
.into_iter()
@@ -53,33 +72,48 @@ pub async fn get_services() -> Result<Vec<DirectoryServiceProvider>> {
.any(|active| active.service_provider_client_id == sp.address)
})
.collect_vec();
log::trace!("service = {} has {} items", service.id, items.len());
log::trace!("service = {} has {} items", service_type.id, items.len());
filtered.push(DirectoryService {
id: service.id.clone(),
description: service.description.clone(),
id: service_type.id.clone(),
description: service_type.description.clone(),
items,
})
}
filtered
}
fn filter_out_poor_gateways(
services: Vec<DirectoryService>,
gateway_res: Vec<GatewayBondAnnotated>,
) -> Vec<DirectoryServiceProvider> {
let perf_threshold = Percent::from_percentage_value(90).unwrap();
// Use only services that are active AND have a performance of >= 90%
let services_with_good_performance: Vec<DirectoryServiceProvider> = filtered
.iter_mut()
.fold(vec![], |mut acc, sp| {
acc.append(&mut sp.items);
acc
})
services
.into_iter()
.flat_map(|sp| sp.items)
.filter(|sp| {
gateway_res.iter().any(|gateway| {
gateway.gateway_bond.gateway.identity_key == sp.gateway
&& gateway.performance >= perf_threshold
})
})
.collect();
.collect()
}
Ok(services_with_good_performance)
async fn fetch_services() -> Result<Vec<DirectoryService>> {
let services_url = get_services_url();
let services_res = reqwest::get(services_url)
.await?
.json::<Vec<DirectoryService>>()
.await?;
Ok(services_res)
}
async fn fetch_active_services() -> Result<PagedResult<HarbourMasterService>> {
let active_services = reqwest::get(HARBOUR_MASTER_URL)
.await?
.json::<PagedResult<HarbourMasterService>>()
.await?;
Ok(active_services)
}
#[tauri::command]
+5 -8
View File
@@ -3,34 +3,31 @@ import { Divider, Typography } from '@mui/material';
import { Box } from '@mui/system';
const appsSchema = {
messagingApps: ['Telegram', 'Keybase'],
wallets: ['Blockstream', 'Electrum'],
messagingApps: ['Matrix', 'Telegram', 'Keybase'],
wallets: ['Monero', 'Blockstream', 'Electrum'],
};
export const CompatibleApps = () => (
<Box>
<Typography fontSize="small" color="grey.600" sx={{ mb: 2 }}>
<Typography fontWeight="bold" variant="body2" sx={{ mb: 2 }}>
Supported apps
</Typography>
<Typography color="nym.highlight" sx={{ mb: 2 }}>
Messaging apps
</Typography>
<Divider sx={{ mb: 2 }} />
<Box sx={{ mb: 4 }}>
<Box sx={{ mb: 2 }}>
{appsSchema.messagingApps.map((app) => (
<Typography variant="body2" color="grey.400" sx={{ mb: 2 }} key={app}>
{app}
</Typography>
))}
</Box>
<Divider sx={{ mb: 2 }} />
<Typography color="nym.highlight" sx={{ mb: 2 }}>
Wallets
</Typography>
<Divider sx={{ mb: 2 }} />
<Box sx={{ mb: 4 }}>
{appsSchema.wallets.map((wallet) => (
<Typography variant="body2" color="grey.400" sx={{ mb: 2 }} key={wallet}>