Tmp hack/wasm client persist gateway cfg (#3443)
* wip * semi-hacky way of persisting wasm-client gateway config a better way shall be introduced after config refactoring * cargo fmt * wasm client clippy * removed artifacts from other branches
This commit is contained in:
committed by
GitHub
parent
e473a05250
commit
525372d7ac
@@ -9,8 +9,8 @@ use crate::{
|
||||
};
|
||||
use clap::Args;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
|
||||
use nym_config::NymConfig;
|
||||
use nym_credential_storage::persistent_storage::PersistentStorage;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use serde::Serialize;
|
||||
@@ -152,7 +152,9 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
|
||||
|
||||
// Setup gateway by either registering a new one, or creating a new config from the selected
|
||||
// one but with keys kept, or reusing the gateway configuration.
|
||||
let gateway = nym_client_core::init::setup_gateway_from_config::<Config, _, PersistentStorage>(
|
||||
let key_store = OnDiskKeys::from_config(config.get_base());
|
||||
let gateway = nym_client_core::init::setup_gateway_from_config::<Config, _, _>(
|
||||
&key_store,
|
||||
register_gateway,
|
||||
user_chosen_gateway_id,
|
||||
config.get_base(),
|
||||
@@ -169,7 +171,8 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
|
||||
|
||||
print_saved_config(&config);
|
||||
|
||||
let address = nym_client_core::init::get_client_address_from_stored_keys(config.get_base())?;
|
||||
let address =
|
||||
nym_client_core::init::get_client_address_from_stored_ondisk_keys(config.get_base())?;
|
||||
let init_results = InitResults::new(&config, &address);
|
||||
println!("{}", args.output.format(&init_results));
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ use crate::{
|
||||
};
|
||||
use clap::Args;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
|
||||
use nym_config::NymConfig;
|
||||
use nym_credential_storage::persistent_storage::PersistentStorage;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_socks5_client_core::config::Config;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
@@ -158,7 +158,9 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
|
||||
|
||||
// Setup gateway by either registering a new one, or creating a new config from the selected
|
||||
// one but with keys kept, or reusing the gateway configuration.
|
||||
let gateway = nym_client_core::init::setup_gateway_from_config::<Config, _, PersistentStorage>(
|
||||
let key_store = OnDiskKeys::from_config(config.get_base());
|
||||
let gateway = nym_client_core::init::setup_gateway_from_config::<Config, _, _>(
|
||||
&key_store,
|
||||
register_gateway,
|
||||
user_chosen_gateway_id,
|
||||
config.get_base(),
|
||||
@@ -177,7 +179,8 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
|
||||
|
||||
print_saved_config(&config);
|
||||
|
||||
let address = nym_client_core::init::get_client_address_from_stored_keys(config.get_base())?;
|
||||
let address =
|
||||
nym_client_core::init::get_client_address_from_stored_ondisk_keys(config.get_base())?;
|
||||
let init_results = InitResults::new(&config, &address);
|
||||
println!("{}", args.output.format(&init_results));
|
||||
|
||||
|
||||
@@ -106,29 +106,25 @@ function printAndDisplayTestResult(result) {
|
||||
});
|
||||
}
|
||||
|
||||
function dummyGatewayConfig() {
|
||||
return new GatewayEndpointConfig(
|
||||
'336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9',
|
||||
'n1rqqw8km7a0rvf8lr6k8dsdqvvkyn2mglj7xxfm',
|
||||
'ws://85.159.212.96:9000',
|
||||
)
|
||||
}
|
||||
|
||||
async function testWithTester() {
|
||||
const gatewayConfig = dummyGatewayConfig();
|
||||
const dummyGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
|
||||
|
||||
// A) construct with hardcoded topology
|
||||
const topology = dummyTopology()
|
||||
const nodeTester = await new NymNodeTester(gatewayConfig, topology);
|
||||
const nodeTester = await new NymNodeTester(topology, dummyGateway);
|
||||
|
||||
// B) first get topology directly from nym-api
|
||||
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
|
||||
// const topology = await current_network_topology(validator)
|
||||
// const nodeTester = await new NymNodeTester(gatewayConfig, topology);
|
||||
// const nodeTester = await new NymNodeTester(topology, dummyGateway);
|
||||
//
|
||||
// C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers)
|
||||
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
|
||||
// const nodeTester = await NymNodeTester.new_with_api(gatewayConfig, validator)
|
||||
// const nodeTester = await NymNodeTester.new_with_api(validator, dummyGateway)
|
||||
|
||||
// D, E, F) you also don't have to specify the gateway. if you don't, a random one (from your topology) will be used
|
||||
// const topology = dummyTopology()
|
||||
// const nodeTester = await new NymNodeTester(topology);
|
||||
|
||||
self.onmessage = async event => {
|
||||
if (event.data && event.data.kind) {
|
||||
@@ -146,7 +142,7 @@ async function testWithTester() {
|
||||
}
|
||||
|
||||
async function testWithNymClient() {
|
||||
const gatewayConfig = dummyGatewayConfig();
|
||||
const dummyGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
|
||||
const topology = dummyTopology()
|
||||
|
||||
let received = 0
|
||||
@@ -168,7 +164,7 @@ async function testWithNymClient() {
|
||||
|
||||
console.log('Instantiating WASM client...');
|
||||
|
||||
let clientBuilder = NymClientBuilder.new_tester(gatewayConfig, topology, onMessageHandler)
|
||||
let clientBuilder = NymClientBuilder.new_tester(topology, onMessageHandler, dummyGateway)
|
||||
console.log('Web worker creating WASM client...');
|
||||
let local_client = await clientBuilder.start_client();
|
||||
console.log('WASM client running!');
|
||||
@@ -226,10 +222,10 @@ async function normalNymClientUsage() {
|
||||
|
||||
debug.topology_refresh_rate_ms = BigInt(60000)
|
||||
|
||||
const gatewayConfig = dummyGatewayConfig();
|
||||
const dummyGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9";
|
||||
const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
|
||||
|
||||
const config = new Config('my-awesome-wasm-client', validator, gatewayConfig, debug);
|
||||
const config = new Config('my-awesome-wasm-client', validator, dummyGateway, debug);
|
||||
|
||||
const onMessageHandler = (message) => {
|
||||
console.log(message);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// due to expansion of #[wasm_bindgen] macro on `Debug` Config struct
|
||||
@@ -9,10 +9,10 @@
|
||||
use nym_client_core::config::{
|
||||
Acknowledgements as ConfigAcknowledgements, CoverTraffic as ConfigCoverTraffic,
|
||||
DebugConfig as ConfigDebug, GatewayConnection as ConfigGatewayConnection,
|
||||
GatewayEndpointConfig, ReplySurbs as ConfigReplySurbs, Topology as ConfigTopology,
|
||||
Traffic as ConfigTraffic,
|
||||
ReplySurbs as ConfigReplySurbs, Topology as ConfigTopology, Traffic as ConfigTraffic,
|
||||
};
|
||||
use nym_sphinx::params::PacketSize;
|
||||
use nym_validator_client::client::IdentityKey;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
@@ -29,8 +29,9 @@ pub struct Config {
|
||||
|
||||
pub(crate) disabled_credentials_mode: bool,
|
||||
|
||||
/// Information regarding how the client should send data to gateway.
|
||||
pub(crate) gateway_endpoint: GatewayEndpointConfig,
|
||||
/// Information regarding how the client should choose gateway.
|
||||
/// If unspecified, the client will attempt to load the config from the storage.
|
||||
pub(crate) gateway: Option<IdentityKey>,
|
||||
|
||||
pub(crate) debug: ConfigDebug,
|
||||
}
|
||||
@@ -41,7 +42,7 @@ impl Config {
|
||||
pub fn new(
|
||||
id: String,
|
||||
validator_server: String,
|
||||
gateway_endpoint: GatewayEndpointConfig,
|
||||
gateway: Option<IdentityKey>,
|
||||
debug: Option<Debug>,
|
||||
) -> Self {
|
||||
Config {
|
||||
@@ -52,7 +53,7 @@ impl Config {
|
||||
.expect("provided url was malformed"),
|
||||
),
|
||||
disabled_credentials_mode: true,
|
||||
gateway_endpoint,
|
||||
gateway,
|
||||
debug: debug.map(Into::into).unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,10 @@ use crate::client::helpers::{InputSender, NymClientTestRequest, WasmTopologyExt}
|
||||
use crate::client::response_pusher::ResponsePusher;
|
||||
use crate::constants::NODE_TESTER_CLIENT_ID;
|
||||
use crate::error::WasmClientError;
|
||||
use crate::helpers::{parse_recipient, parse_sender_tag, setup_reply_surb_storage_backend};
|
||||
use crate::helpers::{
|
||||
choose_gateway, gateway_from_topology, parse_recipient, parse_sender_tag,
|
||||
setup_reply_surb_storage_backend,
|
||||
};
|
||||
use crate::storage::traits::FullWasmClientStorage;
|
||||
use crate::storage::ClientStorage;
|
||||
use crate::topology::WasmNymTopology;
|
||||
@@ -18,16 +21,15 @@ use nym_client_core::client::base_client::{
|
||||
};
|
||||
use nym_client_core::client::inbound_messages::InputMessage;
|
||||
use nym_client_core::client::replies::reply_storage::browser_backend;
|
||||
use nym_client_core::config::{
|
||||
CoverTraffic, DebugConfig, GatewayEndpointConfig, Topology, Traffic,
|
||||
};
|
||||
use nym_client_core::config::{CoverTraffic, DebugConfig, Topology, Traffic};
|
||||
use nym_credential_storage::ephemeral_storage::EphemeralStorage;
|
||||
use nym_task::connections::TransmissionLane;
|
||||
use nym_task::TaskManager;
|
||||
use nym_topology::provider_trait::{HardcodedTopologyProvider, TopologyProvider};
|
||||
use nym_topology::NymTopology;
|
||||
use nym_validator_client::client::IdentityKey;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::RngCore;
|
||||
use rand::{thread_rng, RngCore};
|
||||
use std::sync::Arc;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_futures::future_to_promise;
|
||||
@@ -92,19 +94,21 @@ impl NymClientBuilder {
|
||||
// hardcoded topology
|
||||
// NOTE: you most likely want to use `[NymNodeTester]` instead.
|
||||
pub fn new_tester(
|
||||
gateway_config: GatewayEndpointConfig,
|
||||
topology: WasmNymTopology,
|
||||
on_message: js_sys::Function,
|
||||
gateway: Option<IdentityKey>,
|
||||
) -> Self {
|
||||
if !topology.ensure_contains(&gateway_config) {
|
||||
panic!("the specified topology does not contain the gateway used by the client")
|
||||
if let Some(gateway_id) = &gateway {
|
||||
if !topology.ensure_contains_gateway_id(gateway_id) {
|
||||
panic!("the specified topology does not contain the gateway used by the client")
|
||||
}
|
||||
}
|
||||
|
||||
let full_config = Config {
|
||||
id: NODE_TESTER_CLIENT_ID.to_string(),
|
||||
nym_api_url: None,
|
||||
disabled_credentials_mode: true,
|
||||
gateway_endpoint: gateway_config,
|
||||
gateway,
|
||||
debug: DebugConfig {
|
||||
traffic: Traffic {
|
||||
disable_main_poisson_packet_distribution: true,
|
||||
@@ -150,27 +154,45 @@ impl NymClientBuilder {
|
||||
async fn start_client_async(mut self) -> Result<NymClient, WasmClientError> {
|
||||
console_log!("Starting the wasm client");
|
||||
|
||||
let maybe_topology_provider = self.topology_provider();
|
||||
|
||||
let disabled_credentials = if self.disabled_credentials {
|
||||
CredentialsToggle::Disabled
|
||||
} else {
|
||||
CredentialsToggle::Enabled
|
||||
};
|
||||
|
||||
let nym_api_endpoints = match self.config.nym_api_url {
|
||||
Some(endpoint) => vec![endpoint],
|
||||
let nym_api_endpoints = match &self.config.nym_api_url {
|
||||
Some(endpoint) => vec![endpoint.clone()],
|
||||
None => Vec::new(),
|
||||
};
|
||||
|
||||
// TODO: this will have to be re-used for surbs. but this is a problem for another PR.
|
||||
let key_store =
|
||||
let client_store =
|
||||
ClientStorage::new_async(&self.config.id, self.storage_passphrase.take()).await?;
|
||||
|
||||
// if we provided hardcoded topology, get gateway from it, otherwise get it the 'standard' way
|
||||
let gateway_endpoint = if let Some(topology) = &self.custom_topology {
|
||||
gateway_from_topology(
|
||||
&mut thread_rng(),
|
||||
self.config.gateway.as_deref(),
|
||||
topology,
|
||||
&client_store,
|
||||
)
|
||||
.await?
|
||||
} else {
|
||||
choose_gateway(
|
||||
&client_store,
|
||||
self.config.gateway.clone(),
|
||||
&nym_api_endpoints,
|
||||
)
|
||||
.await?
|
||||
};
|
||||
|
||||
let maybe_topology_provider = self.topology_provider();
|
||||
|
||||
let mut base_builder: BaseClientBuilder<_, FullWasmClientStorage> = BaseClientBuilder::new(
|
||||
&self.config.gateway_endpoint,
|
||||
&gateway_endpoint,
|
||||
&self.config.debug,
|
||||
key_store,
|
||||
client_store,
|
||||
self.bandwidth_controller,
|
||||
self.reply_surb_storage_backend,
|
||||
disabled_credentials,
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
use crate::storage::errors::ClientStorageError;
|
||||
use crate::topology::WasmTopologyError;
|
||||
use js_sys::Promise;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
|
||||
use nym_gateway_client::error::GatewayClientError;
|
||||
use nym_node_tester_utils::error::NetworkTestingError;
|
||||
use nym_sphinx::addressing::clients::RecipientFormattingError;
|
||||
use nym_sphinx::anonymous_replies::requests::InvalidAnonymousSenderTagRepresentation;
|
||||
use nym_topology::NymTopologyError;
|
||||
use nym_validator_client::ValidatorClientError;
|
||||
use thiserror::Error;
|
||||
use wasm_bindgen::JsValue;
|
||||
@@ -44,12 +46,18 @@ pub enum WasmClientError {
|
||||
source: ValidatorClientError,
|
||||
},
|
||||
|
||||
#[error("The provided topology was invalid: {source}")]
|
||||
#[error("The provided wasm topology was invalid: {source}")]
|
||||
WasmTopologyError {
|
||||
#[from]
|
||||
source: WasmTopologyError,
|
||||
},
|
||||
|
||||
#[error("The provided nym topology was invalid: {source}")]
|
||||
TopologyError {
|
||||
#[from]
|
||||
source: NymTopologyError,
|
||||
},
|
||||
|
||||
#[error("failed to test the node: {source}")]
|
||||
NodeTestingFailure {
|
||||
#[from]
|
||||
@@ -68,6 +76,9 @@ pub enum WasmClientError {
|
||||
#[error("Mixnode {mixnode_identity} is not present in the current network topology")]
|
||||
NonExistentMixnode { mixnode_identity: String },
|
||||
|
||||
#[error("Gateway {gateway_identity} is not present in the current network topology")]
|
||||
NonExistentGateway { gateway_identity: String },
|
||||
|
||||
#[error("{raw} is not a valid Nym network recipient: {source}")]
|
||||
MalformedRecipient {
|
||||
raw: String,
|
||||
@@ -85,6 +96,11 @@ pub enum WasmClientError {
|
||||
#[from]
|
||||
source: ClientStorageError,
|
||||
},
|
||||
|
||||
#[error("this client has already registered with a gateway: {gateway_config:?}")]
|
||||
AlreadyRegistered {
|
||||
gateway_config: GatewayEndpointConfig,
|
||||
},
|
||||
}
|
||||
|
||||
impl WasmClientError {
|
||||
|
||||
@@ -2,18 +2,24 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::WasmClientError;
|
||||
use crate::storage::ClientStorage;
|
||||
use crate::topology::WasmNymTopology;
|
||||
use js_sys::Promise;
|
||||
use nym_client_core::client::replies::reply_storage::browser_backend;
|
||||
use nym_client_core::config;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
use nym_client_core::init::GatewaySetup;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
||||
use nym_topology::NymTopology;
|
||||
use nym_validator_client::client::{IdentityKey, IdentityKeyRef};
|
||||
use nym_validator_client::NymApiClient;
|
||||
use rand::{CryptoRng, Rng};
|
||||
use url::Url;
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
use wasm_bindgen_futures::future_to_promise;
|
||||
use wasm_utils::PromisableResult;
|
||||
use wasm_utils::{console_log, PromisableResult};
|
||||
|
||||
// don't get too excited about the name, under the hood it's just a big fat placeholder
|
||||
// with no persistence
|
||||
@@ -72,3 +78,88 @@ pub fn current_network_topology(nym_api_url: String) -> Promise {
|
||||
.into_promise_result()
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) async fn choose_gateway(
|
||||
client_store: &ClientStorage,
|
||||
chosen_gateway: Option<IdentityKey>,
|
||||
nym_apis: &[Url],
|
||||
) -> Result<GatewayEndpointConfig, WasmClientError> {
|
||||
let existing_gateway_config = client_store.read_gateway_config().await?;
|
||||
|
||||
console_log!("loaded: {:?}", existing_gateway_config);
|
||||
|
||||
if let Some(existing) = existing_gateway_config {
|
||||
if let Some(provided) = &chosen_gateway {
|
||||
if provided != &existing.gateway_id {
|
||||
return Err(WasmClientError::AlreadyRegistered {
|
||||
gateway_config: existing,
|
||||
});
|
||||
}
|
||||
}
|
||||
return Ok(existing);
|
||||
};
|
||||
|
||||
// if NOTHING is specified nor available, choose gateway randomly.
|
||||
let setup = GatewaySetup::new(None, chosen_gateway, None);
|
||||
let config = setup.try_get_gateway_details(nym_apis).await?;
|
||||
|
||||
// perform registration + persist the new gateway info
|
||||
// TODO: this is actually quite bad. we shouldn't be persisting gateway info here since we did not have persisted
|
||||
// the shared key yet. this will only happen when we start the base client itself.
|
||||
// but unfortunately, we can't do much more until we do a bit more refactoring.
|
||||
client_store.store_gateway_config(&config).await?;
|
||||
|
||||
console_log!("stored: {:?}", config);
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub(crate) async fn gateway_from_topology<R: Rng + CryptoRng>(
|
||||
rng: &mut R,
|
||||
explicit_gateway: Option<IdentityKeyRef<'_>>,
|
||||
topology: &NymTopology,
|
||||
client_store: &ClientStorage,
|
||||
) -> Result<GatewayEndpointConfig, WasmClientError> {
|
||||
let existing_gateway_config = client_store.read_gateway_config().await?;
|
||||
console_log!("loaded: {:?}", existing_gateway_config);
|
||||
|
||||
let new_gateway: GatewayEndpointConfig = if let Some(provided) = explicit_gateway {
|
||||
if let Some(existing) = existing_gateway_config {
|
||||
// we have stored gateway info and explicitly provided identity key
|
||||
//
|
||||
// check if they match, otherwise return an error
|
||||
return if provided != existing.gateway_id {
|
||||
Err(WasmClientError::AlreadyRegistered {
|
||||
gateway_config: existing,
|
||||
})
|
||||
} else {
|
||||
Ok(existing)
|
||||
};
|
||||
} else {
|
||||
// we have explicitly provided identity key and didn't have any prior stored data
|
||||
//
|
||||
// try to grab details from the topology
|
||||
let gateway_identity = identity::PublicKey::from_base58_string(provided)
|
||||
.map_err(|source| WasmClientError::InvalidGatewayIdentity { source })?;
|
||||
if let Some(gateway) = topology.get_gateway(&gateway_identity) {
|
||||
gateway.clone().into()
|
||||
} else {
|
||||
return Err(WasmClientError::NonExistentGateway {
|
||||
gateway_identity: gateway_identity.to_base58_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if let Some(existing) = existing_gateway_config {
|
||||
// we have stored data and didn't provide anything separately - use what's stored!
|
||||
return Ok(existing);
|
||||
} else {
|
||||
// we don't have anything stored nor we have provided anything
|
||||
//
|
||||
// just grab random gateway from our topology
|
||||
topology.random_gateway(rng)?.clone().into()
|
||||
};
|
||||
|
||||
console_log!("storing: {:?}", new_gateway);
|
||||
client_store.store_gateway_config(&new_gateway).await?;
|
||||
Ok(new_gateway)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::storage::errors::ClientStorageError;
|
||||
use js_sys::Promise;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
use nym_crypto::asymmetric::{encryption, identity};
|
||||
use nym_gateway_client::SharedKeys;
|
||||
use nym_sphinx::acknowledgements::AckKey;
|
||||
@@ -23,8 +24,12 @@ const STORAGE_VERSION: u32 = 1;
|
||||
mod v1 {
|
||||
// stores
|
||||
pub const KEYS_STORE: &str = "keys";
|
||||
pub const CORE_STORE: &str = "core";
|
||||
|
||||
// keys
|
||||
// TODO: to replace with FULL config
|
||||
pub const GATEWAY_CONFIG: &str = "gateway_config";
|
||||
|
||||
pub const ED25519_IDENTITY_KEYPAIR: &str = "ed25519_identity_keypair";
|
||||
pub const X25519_ENCRYPTION_KEYPAIR: &str = "x25519_encryption_key";
|
||||
|
||||
@@ -67,6 +72,7 @@ impl ClientStorage {
|
||||
let db = evt.db();
|
||||
|
||||
db.create_object_store(v1::KEYS_STORE)?;
|
||||
db.create_object_store(v1::CORE_STORE)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -104,6 +110,15 @@ impl ClientStorage {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) async fn read_gateway_config(
|
||||
&self,
|
||||
) -> Result<Option<GatewayEndpointConfig>, ClientStorageError> {
|
||||
self.inner
|
||||
.read_value(v1::CORE_STORE, JsValue::from_str(v1::GATEWAY_CONFIG))
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn may_read_identity_keypair(
|
||||
&self,
|
||||
) -> Result<Option<identity::KeyPair>, ClientStorageError> {
|
||||
@@ -228,4 +243,18 @@ impl ClientStorage {
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub(crate) async fn store_gateway_config(
|
||||
&self,
|
||||
gateway_endpoint: &GatewayEndpointConfig,
|
||||
) -> Result<(), ClientStorageError> {
|
||||
self.inner
|
||||
.store_value(
|
||||
v1::CORE_STORE,
|
||||
JsValue::from_str(v1::GATEWAY_CONFIG),
|
||||
gateway_endpoint,
|
||||
)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::constants::NODE_TESTER_ID;
|
||||
use crate::error::WasmClientError;
|
||||
use crate::helpers::current_network_topology_async;
|
||||
use crate::helpers::{current_network_topology_async, gateway_from_topology};
|
||||
use crate::storage::ClientStorage;
|
||||
use crate::tester::ephemeral_receiver::EphemeralTestReceiver;
|
||||
use crate::tester::helpers::{
|
||||
@@ -17,7 +17,6 @@ use nym_bandwidth_controller::BandwidthController;
|
||||
use nym_client_core::client::key_manager::ManagedKeys;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
use nym_credential_storage::ephemeral_storage::EphemeralStorage;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_gateway_client::GatewayClient;
|
||||
use nym_node_tester_utils::receiver::SimpleMessageReceiver;
|
||||
use nym_node_tester_utils::{NodeTester, TestMessage};
|
||||
@@ -27,7 +26,9 @@ use nym_sphinx::params::PacketSize;
|
||||
use nym_sphinx::preparer::PreparedFragment;
|
||||
use nym_task::TaskManager;
|
||||
use nym_topology::NymTopology;
|
||||
use nym_validator_client::client::IdentityKey;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::{CryptoRng, Rng};
|
||||
use std::collections::HashSet;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
||||
use std::sync::{Arc, Mutex as SyncMutex};
|
||||
@@ -72,7 +73,7 @@ pub struct NymNodeTester {
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct NymNodeTesterBuilder {
|
||||
gateway_config: GatewayEndpointConfig,
|
||||
gateway: Option<IdentityKey>,
|
||||
|
||||
base_topology: NymTopology,
|
||||
|
||||
@@ -93,48 +94,61 @@ fn address(keys: &ManagedKeys, gateway_identity: NodeIdentity) -> Recipient {
|
||||
impl NymNodeTesterBuilder {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(
|
||||
gateway_config: GatewayEndpointConfig,
|
||||
base_topology: WasmNymTopology,
|
||||
gateway: Option<IdentityKey>,
|
||||
) -> NymNodeTesterBuilder {
|
||||
NymNodeTesterBuilder {
|
||||
gateway_config,
|
||||
gateway,
|
||||
base_topology: base_topology.into(),
|
||||
bandwidth_controller: None,
|
||||
}
|
||||
}
|
||||
|
||||
async fn _new_with_api(
|
||||
gateway_config: GatewayEndpointConfig,
|
||||
api_url: String,
|
||||
gateway: Option<IdentityKey>,
|
||||
) -> Result<Self, WasmClientError> {
|
||||
let topology = current_network_topology_async(api_url).await?;
|
||||
Ok(NymNodeTesterBuilder::new(gateway_config, topology))
|
||||
Ok(NymNodeTesterBuilder::new(topology, gateway))
|
||||
}
|
||||
|
||||
pub fn new_with_api(gateway_config: GatewayEndpointConfig, api_url: String) -> Promise {
|
||||
pub fn new_with_api(gateway: Option<IdentityKey>, api_url: String) -> Promise {
|
||||
future_to_promise(async move {
|
||||
Self::_new_with_api(gateway_config, api_url)
|
||||
Self::_new_with_api(api_url, gateway)
|
||||
.await
|
||||
.into_promise_result()
|
||||
})
|
||||
}
|
||||
|
||||
async fn gateway_info<R: Rng + CryptoRng>(
|
||||
&self,
|
||||
rng: &mut R,
|
||||
client_store: &ClientStorage,
|
||||
) -> Result<GatewayEndpointConfig, WasmClientError> {
|
||||
gateway_from_topology(
|
||||
rng,
|
||||
self.gateway.as_deref(),
|
||||
&self.base_topology,
|
||||
client_store,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn _setup_client(mut self) -> Result<NymNodeTester, WasmClientError> {
|
||||
let mut rng = OsRng;
|
||||
let task_manager = TaskManager::default();
|
||||
|
||||
let gateway_identity =
|
||||
identity::PublicKey::from_base58_string(self.gateway_config.gateway_id)
|
||||
.map_err(|source| WasmClientError::InvalidGatewayIdentity { source })?;
|
||||
let client_store = ClientStorage::new_async(NODE_TESTER_ID, None).await?;
|
||||
|
||||
let key_store = ClientStorage::new_async(NODE_TESTER_ID, None).await?;
|
||||
let mut managed_keys = ManagedKeys::load_or_generate(&mut rng, &key_store).await;
|
||||
let gateway_endpoint = self.gateway_info(&mut rng, &client_store).await?;
|
||||
let gateway_identity = gateway_endpoint.try_get_gateway_identity_key()?;
|
||||
let mut managed_keys = ManagedKeys::load_or_generate(&mut rng, &client_store).await;
|
||||
|
||||
let (mixnet_message_sender, mixnet_message_receiver) = mpsc::unbounded();
|
||||
let (ack_sender, ack_receiver) = mpsc::unbounded();
|
||||
|
||||
let mut gateway_client = GatewayClient::new(
|
||||
self.gateway_config.gateway_listener,
|
||||
gateway_endpoint.gateway_listener,
|
||||
managed_keys.identity_keypair(),
|
||||
gateway_identity,
|
||||
managed_keys.gateway_shared_key(),
|
||||
@@ -148,7 +162,7 @@ impl NymNodeTesterBuilder {
|
||||
gateway_client.set_disabled_credentials_mode(true);
|
||||
let shared_keys = gateway_client.authenticate_and_start().await?;
|
||||
managed_keys
|
||||
.deal_with_gateway_key(shared_keys, &key_store)
|
||||
.deal_with_gateway_key(shared_keys, &client_store)
|
||||
.await?;
|
||||
|
||||
// TODO: make those values configurable later
|
||||
@@ -227,24 +241,24 @@ async fn test_mixnode(
|
||||
impl NymNodeTester {
|
||||
#[wasm_bindgen(constructor)]
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
pub fn new(gateway_config: GatewayEndpointConfig, topology: WasmNymTopology) -> Promise {
|
||||
pub fn new(topology: WasmNymTopology, gateway: Option<IdentityKey>) -> Promise {
|
||||
console_log!("constructing node tester!");
|
||||
NymNodeTesterBuilder::new(gateway_config, topology).setup_client()
|
||||
NymNodeTesterBuilder::new(topology, gateway).setup_client()
|
||||
}
|
||||
|
||||
async fn _new_with_api(
|
||||
gateway_config: GatewayEndpointConfig,
|
||||
api_url: String,
|
||||
gateway: Option<IdentityKey>,
|
||||
) -> Result<Self, WasmClientError> {
|
||||
NymNodeTesterBuilder::_new_with_api(gateway_config, api_url)
|
||||
NymNodeTesterBuilder::_new_with_api(api_url, gateway)
|
||||
.await?
|
||||
._setup_client()
|
||||
.await
|
||||
}
|
||||
|
||||
pub fn new_with_api(gateway_config: GatewayEndpointConfig, api_url: String) -> Promise {
|
||||
pub fn new_with_api(api_url: String, gateway: Option<IdentityKey>) -> Promise {
|
||||
future_to_promise(async move {
|
||||
Self::_new_with_api(gateway_config, api_url)
|
||||
Self::_new_with_api(api_url, gateway)
|
||||
.await
|
||||
.into_promise_result()
|
||||
})
|
||||
|
||||
@@ -6,7 +6,7 @@ use nym_crypto::asymmetric::{encryption, identity};
|
||||
use nym_topology::gateway::GatewayConversionError;
|
||||
use nym_topology::mix::{Layer, MixnodeConversionError};
|
||||
use nym_topology::{gateway, mix, MixLayer, NymTopology};
|
||||
use nym_validator_client::client::MixId;
|
||||
use nym_validator_client::client::{IdentityKeyRef, MixId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
use thiserror::Error;
|
||||
@@ -82,11 +82,16 @@ impl WasmNymTopology {
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn ensure_contains(&self, gateway_config: &GatewayEndpointConfig) -> bool {
|
||||
self.ensure_contains_gateway_id(&gateway_config.gateway_id)
|
||||
}
|
||||
|
||||
pub(crate) fn ensure_contains_gateway_id(&self, gateway_id: IdentityKeyRef) -> bool {
|
||||
self.inner
|
||||
.gateways()
|
||||
.iter()
|
||||
.any(|g| g.identity_key.to_base58_string() == gateway_config.gateway_id)
|
||||
.any(|g| g.identity_key.to_base58_string() == gateway_id)
|
||||
}
|
||||
|
||||
pub fn print(&self) {
|
||||
|
||||
@@ -26,7 +26,7 @@ pub mod error;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub mod wasm_mockups;
|
||||
|
||||
pub struct BandwidthController<C, St: Storage> {
|
||||
pub struct BandwidthController<C, St> {
|
||||
storage: St,
|
||||
client: C,
|
||||
}
|
||||
|
||||
@@ -37,22 +37,27 @@ impl ManagedKeys {
|
||||
!matches!(self, ManagedKeys::Invalidated)
|
||||
}
|
||||
|
||||
pub async fn must_load<S: KeyStore>(key_store: &S) -> Result<Self, S::StorageError> {
|
||||
pub async fn try_load<S: KeyStore>(key_store: &S) -> Result<Self, S::StorageError> {
|
||||
Ok(ManagedKeys::FullyDerived(
|
||||
KeyManager::load_keys(key_store).await?,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn generate_new<R>(rng: &mut R) -> Self
|
||||
where
|
||||
R: RngCore + CryptoRng,
|
||||
{
|
||||
ManagedKeys::Initial(KeyManagerBuilder::new(rng))
|
||||
}
|
||||
|
||||
pub async fn load_or_generate<R, S>(rng: &mut R, key_store: &S) -> Self
|
||||
where
|
||||
R: RngCore + CryptoRng,
|
||||
S: KeyStore,
|
||||
{
|
||||
if let Ok(loaded) = KeyManager::load_keys(key_store).await {
|
||||
ManagedKeys::FullyDerived(loaded)
|
||||
} else {
|
||||
ManagedKeys::Initial(KeyManagerBuilder::new(rng))
|
||||
}
|
||||
Self::try_load(key_store)
|
||||
.await
|
||||
.unwrap_or_else(|_| Self::generate_new(rng))
|
||||
}
|
||||
|
||||
pub fn identity_keypair(&self) -> Arc<identity::KeyPair> {
|
||||
|
||||
@@ -8,6 +8,8 @@ use std::error::Error;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use crate::config::persistence::key_pathfinder::ClientKeyPathfinder;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use crate::config::Config;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use nym_crypto::asymmetric::{encryption, identity};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use nym_gateway_requests::registration::handshake::SharedKeys;
|
||||
@@ -79,6 +81,10 @@ impl OnDiskKeys {
|
||||
OnDiskKeys { pathfinder }
|
||||
}
|
||||
|
||||
pub fn from_config<T>(config: &Config<T>) -> Self {
|
||||
OnDiskKeys::new(ClientKeyPathfinder::new_from_config(config))
|
||||
}
|
||||
|
||||
fn load_key<T: PemStorableKey>(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use nym_config::defaults::NymNetworkDetails;
|
||||
use nym_config::{NymConfig, OptionalSet, CRED_DB_FILE_NAME};
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_sphinx::params::PacketSize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::marker::PhantomData;
|
||||
@@ -10,6 +11,7 @@ use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
use crate::error::ClientCoreError;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
@@ -446,6 +448,14 @@ impl GatewayEndpointConfig {
|
||||
}
|
||||
}
|
||||
|
||||
// separate block so it wouldn't be exported via wasm bindgen
|
||||
impl GatewayEndpointConfig {
|
||||
pub fn try_get_gateway_identity_key(&self) -> Result<identity::PublicKey, ClientCoreError> {
|
||||
identity::PublicKey::from_base58_string(&self.gateway_id)
|
||||
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nym_topology::gateway::Node> for GatewayEndpointConfig {
|
||||
fn from(node: nym_topology::gateway::Node) -> GatewayEndpointConfig {
|
||||
let gateway_listener = node.clients_address();
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::Config;
|
||||
use nym_config::NymConfig;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -29,7 +28,7 @@ impl ClientKeyPathfinder {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_config<T: NymConfig>(config: &Config<T>) -> Self {
|
||||
pub fn new_from_config<T>(config: &Config<T>) -> Self {
|
||||
ClientKeyPathfinder {
|
||||
identity_private_key: config.get_private_identity_key_file(),
|
||||
identity_public_key: config.get_public_identity_key_file(),
|
||||
|
||||
@@ -92,6 +92,11 @@ pub enum ClientCoreError {
|
||||
|
||||
#[error("Unexpected exit")]
|
||||
UnexpectedExit,
|
||||
|
||||
#[error(
|
||||
"This operation would have resulted in clients keys being overwritten without permission"
|
||||
)]
|
||||
ForbiddenKeyOverwrite,
|
||||
}
|
||||
|
||||
/// Set of messages that the client can send to listeners via the task manager
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::GatewayEndpointConfig;
|
||||
use crate::error::ClientCoreError;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use log::{debug, info, trace, warn};
|
||||
use nym_credential_storage::storage::Storage;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_gateway_client::GatewayClient;
|
||||
use nym_gateway_requests::registration::handshake::SharedKeys;
|
||||
use nym_topology::{filter::VersionFilterable, gateway};
|
||||
use rand::{seq::SliceRandom, thread_rng, Rng};
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tap::TapFallible;
|
||||
use tungstenite::Message;
|
||||
@@ -27,12 +27,6 @@ use tokio_tungstenite::connect_async;
|
||||
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
type WsConn = WebSocketStream<MaybeTlsStream<TcpStream>>;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use crate::client::key_manager::persistence::OnDiskKeys;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use crate::config::{persistence::key_pathfinder::ClientKeyPathfinder, Config};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use nym_config::NymConfig;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use nym_bandwidth_controller::wasm_mockups::DirectSigningNyxdClient;
|
||||
@@ -61,9 +55,9 @@ impl GatewayWithLatency {
|
||||
}
|
||||
}
|
||||
|
||||
async fn current_gateways<R: Rng>(
|
||||
pub(super) async fn current_gateways<R: Rng>(
|
||||
rng: &mut R,
|
||||
nym_apis: Vec<Url>,
|
||||
nym_apis: &[Url],
|
||||
) -> Result<Vec<gateway::Node>, ClientCoreError> {
|
||||
let nym_api = nym_apis
|
||||
.choose(rng)
|
||||
@@ -160,7 +154,7 @@ async fn measure_latency(gateway: gateway::Node) -> Result<GatewayWithLatency, C
|
||||
Ok(GatewayWithLatency::new(gateway, avg))
|
||||
}
|
||||
|
||||
async fn choose_gateway_by_latency<R: Rng>(
|
||||
pub(super) async fn choose_gateway_by_latency<R: Rng>(
|
||||
rng: &mut R,
|
||||
gateways: Vec<gateway::Node>,
|
||||
) -> Result<gateway::Node, ClientCoreError> {
|
||||
@@ -193,7 +187,7 @@ async fn choose_gateway_by_latency<R: Rng>(
|
||||
Ok(chosen.gateway.clone())
|
||||
}
|
||||
|
||||
fn uniformly_random_gateway<R: Rng>(
|
||||
pub(super) fn uniformly_random_gateway<R: Rng>(
|
||||
rng: &mut R,
|
||||
gateways: Vec<gateway::Node>,
|
||||
) -> Result<gateway::Node, ClientCoreError> {
|
||||
@@ -203,39 +197,14 @@ fn uniformly_random_gateway<R: Rng>(
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub(super) async fn query_gateway_details(
|
||||
validator_servers: Vec<Url>,
|
||||
chosen_gateway_id: Option<identity::PublicKey>,
|
||||
by_latency: bool,
|
||||
) -> Result<gateway::Node, ClientCoreError> {
|
||||
let mut rng = thread_rng();
|
||||
let gateways = current_gateways(&mut rng, validator_servers).await?;
|
||||
|
||||
// if we set an explicit gateway, use that one and nothing else
|
||||
if let Some(explicitly_chosen) = chosen_gateway_id {
|
||||
gateways
|
||||
.into_iter()
|
||||
.find(|gateway| gateway.identity_key == explicitly_chosen)
|
||||
.ok_or_else(|| ClientCoreError::NoGatewayWithId(explicitly_chosen.to_string()))
|
||||
} else if by_latency {
|
||||
choose_gateway_by_latency(&mut rng, gateways).await
|
||||
} else {
|
||||
uniformly_random_gateway(&mut rng, gateways)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) async fn register_with_gateway<St>(
|
||||
gateway: &gateway::Node,
|
||||
pub(super) async fn register_with_gateway(
|
||||
gateway: &GatewayEndpointConfig,
|
||||
our_identity: Arc<identity::KeyPair>,
|
||||
) -> Result<Arc<SharedKeys>, ClientCoreError>
|
||||
where
|
||||
St: Storage,
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
) -> Result<Arc<SharedKeys>, ClientCoreError> {
|
||||
let timeout = Duration::from_millis(1500);
|
||||
let mut gateway_client: GatewayClient<DirectSigningNyxdClient, St> = GatewayClient::new_init(
|
||||
gateway.clients_address(),
|
||||
gateway.identity_key,
|
||||
let mut gateway_client: GatewayClient<DirectSigningNyxdClient, _> = GatewayClient::new_init(
|
||||
gateway.gateway_listener.clone(),
|
||||
gateway.try_get_gateway_identity_key()?,
|
||||
our_identity.clone(),
|
||||
timeout,
|
||||
);
|
||||
@@ -249,13 +218,3 @@ where
|
||||
.tap_err(|_| log::warn!("Failed to register with the gateway!"))?;
|
||||
Ok(shared_keys)
|
||||
}
|
||||
|
||||
// TODO: make it generic
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(super) fn on_disk_key_store<T>(config: &Config<T>) -> OnDiskKeys
|
||||
where
|
||||
T: NymConfig,
|
||||
{
|
||||
let pathfinder = ClientKeyPathfinder::new_from_config(config);
|
||||
OnDiskKeys::new(pathfinder)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
|
||||
//! Collection of initialization steps used by client implementations
|
||||
|
||||
use crate::client::key_manager::KeyManager;
|
||||
use crate::client::base_client::storage::MixnetClientStorage;
|
||||
use crate::client::key_manager::persistence::KeyStore;
|
||||
use crate::client::key_manager::{KeyManager, ManagedKeys};
|
||||
use crate::init::helpers::{choose_gateway_by_latency, current_gateways, uniformly_random_gateway};
|
||||
use crate::{
|
||||
config::{
|
||||
persistence::key_pathfinder::ClientKeyPathfinder, ClientCoreConfigTrait, Config,
|
||||
@@ -12,18 +15,102 @@ use crate::{
|
||||
error::ClientCoreError,
|
||||
};
|
||||
use nym_config::NymConfig;
|
||||
use nym_credential_storage::storage::Storage;
|
||||
use nym_crypto::asymmetric::{encryption, identity};
|
||||
use nym_gateway_requests::registration::handshake::SharedKeys;
|
||||
use nym_sphinx::addressing::{clients::Recipient, nodes::NodeIdentity};
|
||||
use nym_validator_client::client::IdentityKey;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::thread_rng;
|
||||
use serde::Serialize;
|
||||
use std::fmt::Display;
|
||||
use std::sync::Arc;
|
||||
use tap::TapFallible;
|
||||
use url::Url;
|
||||
|
||||
mod helpers;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum GatewaySetup {
|
||||
/// Specifies usage of a new, random, gateway.
|
||||
New {
|
||||
/// Should the new gateway be selected based on latency.
|
||||
by_latency: bool,
|
||||
},
|
||||
Specified {
|
||||
/// Identity key of the gateway we want to try to use.
|
||||
gateway_identity: IdentityKey,
|
||||
},
|
||||
Predefined {
|
||||
/// Full gateway configuration
|
||||
config: GatewayEndpointConfig,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<GatewayEndpointConfig> for GatewaySetup {
|
||||
fn from(config: GatewayEndpointConfig) -> Self {
|
||||
GatewaySetup::Predefined { config }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IdentityKey> for GatewaySetup {
|
||||
fn from(gateway_identity: IdentityKey) -> Self {
|
||||
GatewaySetup::Specified { gateway_identity }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GatewaySetup {
|
||||
fn default() -> Self {
|
||||
GatewaySetup::New { by_latency: false }
|
||||
}
|
||||
}
|
||||
|
||||
impl GatewaySetup {
|
||||
pub fn new(
|
||||
full_config: Option<GatewayEndpointConfig>,
|
||||
gateway_identity: Option<IdentityKey>,
|
||||
latency_based_selection: Option<bool>,
|
||||
) -> Self {
|
||||
if let Some(config) = full_config {
|
||||
GatewaySetup::Predefined { config }
|
||||
} else if let Some(gateway_identity) = gateway_identity {
|
||||
GatewaySetup::Specified { gateway_identity }
|
||||
} else {
|
||||
GatewaySetup::New {
|
||||
by_latency: latency_based_selection.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn try_get_gateway_details(
|
||||
self,
|
||||
validator_servers: &[Url],
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError> {
|
||||
match self {
|
||||
GatewaySetup::New { by_latency } => {
|
||||
let mut rng = thread_rng();
|
||||
let gateways = current_gateways(&mut rng, validator_servers).await?;
|
||||
if by_latency {
|
||||
choose_gateway_by_latency(&mut rng, gateways).await
|
||||
} else {
|
||||
uniformly_random_gateway(&mut rng, gateways)
|
||||
}
|
||||
}
|
||||
.map(Into::into),
|
||||
GatewaySetup::Specified { gateway_identity } => {
|
||||
let user_gateway = identity::PublicKey::from_base58_string(&gateway_identity)
|
||||
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
|
||||
|
||||
let mut rng = thread_rng();
|
||||
let gateways = current_gateways(&mut rng, validator_servers).await?;
|
||||
gateways
|
||||
.into_iter()
|
||||
.find(|gateway| gateway.identity_key == user_gateway)
|
||||
.ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string()))
|
||||
}
|
||||
.map(Into::into),
|
||||
GatewaySetup::Predefined { config } => Ok(config),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Struct describing the results of the client initialization procedure.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct InitResults {
|
||||
@@ -62,29 +149,55 @@ impl Display for InitResults {
|
||||
}
|
||||
}
|
||||
|
||||
/// Authenticate and register with a gateway.
|
||||
/// Either pick one at random by querying the available gateways from the nym-api, or use the
|
||||
/// chosen one if it's among the available ones.
|
||||
/// The shared key is added to the supplied `KeyManager` and the endpoint details are returned.
|
||||
pub async fn register_with_gateway<St>(
|
||||
identity_keys: Arc<identity::KeyPair>,
|
||||
nym_api_endpoints: Vec<Url>,
|
||||
chosen_gateway_id: Option<identity::PublicKey>,
|
||||
by_latency: bool,
|
||||
) -> Result<(GatewayEndpointConfig, Arc<SharedKeys>), ClientCoreError>
|
||||
/// Recovers the already present gateway information or attempts to register with new gateway
|
||||
/// and stores the newly obtained key
|
||||
pub async fn get_registered_gateway<S>(
|
||||
validator_servers: Vec<Url>,
|
||||
key_store: &S::KeyStore,
|
||||
setup: GatewaySetup,
|
||||
overwrite_keys: bool,
|
||||
) -> Result<GatewayEndpointConfig, ClientCoreError>
|
||||
where
|
||||
St: Storage,
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
S: MixnetClientStorage,
|
||||
<S::KeyStore as KeyStore>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
// Get the gateway details of the gateway we will use
|
||||
let gateway =
|
||||
helpers::query_gateway_details(nym_api_endpoints, chosen_gateway_id, by_latency).await?;
|
||||
log::debug!("Querying gateway gives: {gateway}");
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
// try load keys
|
||||
let mut managed_keys = match ManagedKeys::try_load(key_store).await {
|
||||
Ok(_) => {
|
||||
// if we loaded something and we don't have full gateway details, check if we can overwrite the data
|
||||
if let GatewaySetup::Predefined { config } = setup {
|
||||
// we already have defined gateway details AND a shared key, so nothing more for us to do
|
||||
return Ok(config);
|
||||
} else if overwrite_keys {
|
||||
ManagedKeys::generate_new(&mut rng)
|
||||
} else {
|
||||
return Err(ClientCoreError::ForbiddenKeyOverwrite);
|
||||
}
|
||||
}
|
||||
Err(_) => ManagedKeys::generate_new(&mut rng),
|
||||
};
|
||||
|
||||
// choose gateway
|
||||
let gateway_details = setup.try_get_gateway_details(&validator_servers).await?;
|
||||
|
||||
// get our identity key
|
||||
let our_identity = managed_keys.identity_keypair();
|
||||
|
||||
// Establish connection, authenticate and generate keys for talking with the gateway
|
||||
let shared_keys = helpers::register_with_gateway::<St>(&gateway, identity_keys).await?;
|
||||
let shared_keys = helpers::register_with_gateway(&gateway_details, our_identity).await?;
|
||||
|
||||
Ok((gateway.into(), shared_keys))
|
||||
managed_keys
|
||||
.deal_with_gateway_key(shared_keys, key_store)
|
||||
.await
|
||||
.map_err(|source| ClientCoreError::KeyStoreError {
|
||||
source: Box::new(source),
|
||||
})?;
|
||||
|
||||
// TODO: here we should be probably persisting gateway details as opposed to returning them
|
||||
|
||||
Ok(gateway_details)
|
||||
}
|
||||
|
||||
/// Convenience function for setting up the gateway for a client given a `Config`. Depending on the
|
||||
@@ -94,8 +207,8 @@ where
|
||||
/// b. Create a new gateway configuration but keep existing keys. This assumes that the caller
|
||||
/// knows what they are doing and that the keys match the requested gateway.
|
||||
/// c. Create a new gateway configuration with a newly registered gateway and keys.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub async fn setup_gateway_from_config<C, T, St>(
|
||||
pub async fn setup_gateway_from_config<C, T, KSt>(
|
||||
key_store: &KSt,
|
||||
register_gateway: bool,
|
||||
user_chosen_gateway_id: Option<identity::PublicKey>,
|
||||
config: &Config<T>,
|
||||
@@ -104,8 +217,8 @@ pub async fn setup_gateway_from_config<C, T, St>(
|
||||
where
|
||||
C: NymConfig + ClientCoreConfigTrait,
|
||||
T: NymConfig,
|
||||
St: Storage,
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
KSt: KeyStore,
|
||||
<KSt as KeyStore>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
let id = config.get_id();
|
||||
|
||||
@@ -116,41 +229,42 @@ where
|
||||
return load_existing_gateway_config::<C>(&id);
|
||||
}
|
||||
|
||||
let gateway_setup = GatewaySetup::new(
|
||||
None,
|
||||
user_chosen_gateway_id.map(|id| id.to_base58_string()),
|
||||
Some(by_latency),
|
||||
);
|
||||
// Else, we proceed by querying the nym-api
|
||||
let gateway = helpers::query_gateway_details(
|
||||
config.get_nym_api_endpoints(),
|
||||
user_chosen_gateway_id,
|
||||
by_latency,
|
||||
)
|
||||
.await?;
|
||||
log::debug!("Querying gateway gives: {}", gateway);
|
||||
let gateway = gateway_setup
|
||||
.try_get_gateway_details(&config.get_nym_api_endpoints())
|
||||
.await?;
|
||||
log::debug!("Querying gateway gives: {:?}", gateway);
|
||||
|
||||
// If we are not registering, just return this and assume the caller has the keys already and
|
||||
// wants to keep the,
|
||||
if !register_gateway && user_chosen_gateway_id.is_some() {
|
||||
eprintln!("Using gateway provided by user, keeping existing keys");
|
||||
return Ok(gateway.into());
|
||||
return Ok(gateway);
|
||||
}
|
||||
|
||||
let key_store = helpers::on_disk_key_store(config);
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut rng = OsRng;
|
||||
let mut managed_keys =
|
||||
crate::client::key_manager::ManagedKeys::load_or_generate(&mut rng, &key_store).await;
|
||||
crate::client::key_manager::ManagedKeys::load_or_generate(&mut rng, key_store).await;
|
||||
|
||||
// Create new keys and derive our identity
|
||||
let our_identity = managed_keys.identity_keypair();
|
||||
|
||||
// Establish connection, authenticate and generate keys for talking with the gateway
|
||||
eprintln!("Registering with new gateway");
|
||||
let shared_keys = helpers::register_with_gateway::<St>(&gateway, our_identity).await?;
|
||||
let shared_keys = helpers::register_with_gateway(&gateway, our_identity).await?;
|
||||
managed_keys
|
||||
.deal_with_gateway_key(shared_keys, &key_store)
|
||||
.deal_with_gateway_key(shared_keys, key_store)
|
||||
.await
|
||||
.map_err(|source| ClientCoreError::KeyStoreError {
|
||||
source: Box::new(source),
|
||||
})?;
|
||||
|
||||
Ok(gateway.into())
|
||||
Ok(gateway)
|
||||
}
|
||||
|
||||
/// Read and reuse the existing gateway configuration from a file that was generate earlier.
|
||||
@@ -187,7 +301,8 @@ pub fn get_client_address(
|
||||
}
|
||||
|
||||
/// Get the client address by loading the keys from stored files.
|
||||
pub fn get_client_address_from_stored_keys<T>(
|
||||
// TODO: rethink that sucker
|
||||
pub fn get_client_address_from_stored_ondisk_keys<T>(
|
||||
config: &Config<T>,
|
||||
) -> Result<Recipient, ClientCoreError>
|
||||
where
|
||||
@@ -197,11 +312,8 @@ where
|
||||
pathfinder: &ClientKeyPathfinder,
|
||||
) -> Result<identity::KeyPair, ClientCoreError> {
|
||||
let identity_keypair: identity::KeyPair =
|
||||
nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new(
|
||||
pathfinder.private_identity_key().to_owned(),
|
||||
pathfinder.public_identity_key().to_owned(),
|
||||
))
|
||||
.tap_err(|_| log::error!("Failed to read stored identity key files"))?;
|
||||
nym_pemstore::load_keypair(&pathfinder.identity_key_pair_path())
|
||||
.tap_err(|_| log::error!("Failed to read stored identity key files"))?;
|
||||
Ok(identity_keypair)
|
||||
}
|
||||
|
||||
@@ -209,11 +321,8 @@ where
|
||||
pathfinder: &ClientKeyPathfinder,
|
||||
) -> Result<encryption::KeyPair, ClientCoreError> {
|
||||
let sphinx_keypair: encryption::KeyPair =
|
||||
nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new(
|
||||
pathfinder.private_encryption_key().to_owned(),
|
||||
pathfinder.public_encryption_key().to_owned(),
|
||||
))
|
||||
.tap_err(|_| log::error!("Failed to read stored sphinx key files"))?;
|
||||
nym_pemstore::load_keypair(&pathfinder.encryption_key_pair_path())
|
||||
.tap_err(|_| log::error!("Failed to read stored sphinx key files"))?;
|
||||
Ok(sphinx_keypair)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ use futures::{SinkExt, StreamExt};
|
||||
use log::*;
|
||||
use nym_bandwidth_controller::BandwidthController;
|
||||
use nym_coconut_interface::Credential;
|
||||
use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
|
||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_gateway_requests::authentication::encrypted_address::EncryptedAddressBytes;
|
||||
use nym_gateway_requests::iv::IV;
|
||||
@@ -26,7 +28,6 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tungstenite::protocol::Message;
|
||||
|
||||
use nym_credential_storage::storage::Storage;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use nym_validator_client::nyxd::traits::DkgQueryClient;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
@@ -42,7 +43,7 @@ use wasm_utils::websocket::JSWebsocket;
|
||||
const DEFAULT_RECONNECTION_ATTEMPTS: usize = 10;
|
||||
const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5);
|
||||
|
||||
pub struct GatewayClient<C, St: Storage> {
|
||||
pub struct GatewayClient<C, St> {
|
||||
authenticated: bool,
|
||||
disabled_credentials_mode: bool,
|
||||
bandwidth_remaining: i64,
|
||||
@@ -68,12 +69,7 @@ pub struct GatewayClient<C, St: Storage> {
|
||||
shutdown: TaskClient,
|
||||
}
|
||||
|
||||
impl<C, St> GatewayClient<C, St>
|
||||
where
|
||||
C: Sync + Send,
|
||||
St: Storage,
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
impl<C, St> GatewayClient<C, St> {
|
||||
// TODO: put it all in a Config struct
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
@@ -124,40 +120,6 @@ where
|
||||
self.reconnection_backoff = backoff
|
||||
}
|
||||
|
||||
pub fn new_init(
|
||||
gateway_address: String,
|
||||
gateway_identity: identity::PublicKey,
|
||||
local_identity: Arc<identity::KeyPair>,
|
||||
response_timeout_duration: Duration,
|
||||
) -> Self {
|
||||
use futures::channel::mpsc;
|
||||
|
||||
// note: this packet_router is completely invalid in normal circumstances, but "works"
|
||||
// perfectly fine here, because it's not meant to be used
|
||||
let (ack_tx, _) = mpsc::unbounded();
|
||||
let (mix_tx, _) = mpsc::unbounded();
|
||||
let shutdown = TaskClient::dummy();
|
||||
let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone());
|
||||
|
||||
GatewayClient::<C, St> {
|
||||
authenticated: false,
|
||||
disabled_credentials_mode: true,
|
||||
bandwidth_remaining: 0,
|
||||
gateway_address,
|
||||
gateway_identity,
|
||||
local_identity,
|
||||
shared_key: None,
|
||||
connection: SocketState::NotConnected,
|
||||
packet_router,
|
||||
response_timeout_duration,
|
||||
bandwidth_controller: None,
|
||||
should_reconnect_on_failure: false,
|
||||
reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS,
|
||||
reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF,
|
||||
shutdown,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gateway_identity(&self) -> identity::PublicKey {
|
||||
self.gateway_identity
|
||||
}
|
||||
@@ -569,7 +531,9 @@ where
|
||||
|
||||
pub async fn claim_bandwidth(&mut self) -> Result<(), GatewayClientError>
|
||||
where
|
||||
C: DkgQueryClient,
|
||||
C: DkgQueryClient + Send + Sync,
|
||||
St: CredentialStorage,
|
||||
<St as CredentialStorage>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
if !self.authenticated {
|
||||
return Err(GatewayClientError::NotAuthenticated);
|
||||
@@ -773,7 +737,9 @@ where
|
||||
|
||||
pub async fn authenticate_and_start(&mut self) -> Result<Arc<SharedKeys>, GatewayClientError>
|
||||
where
|
||||
C: DkgQueryClient,
|
||||
C: DkgQueryClient + Send + Sync,
|
||||
St: CredentialStorage,
|
||||
<St as CredentialStorage>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
if !self.connection.is_established() {
|
||||
self.establish_connection().await?;
|
||||
@@ -792,3 +758,40 @@ where
|
||||
Ok(shared_key)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> GatewayClient<C, EphemeralCredentialStorage> {
|
||||
// for initialisation we do not need credential storage. Though it's still a bit weird we have to set the generic...
|
||||
pub fn new_init(
|
||||
gateway_address: String,
|
||||
gateway_identity: identity::PublicKey,
|
||||
local_identity: Arc<identity::KeyPair>,
|
||||
response_timeout_duration: Duration,
|
||||
) -> Self {
|
||||
use futures::channel::mpsc;
|
||||
|
||||
// note: this packet_router is completely invalid in normal circumstances, but "works"
|
||||
// perfectly fine here, because it's not meant to be used
|
||||
let (ack_tx, _) = mpsc::unbounded();
|
||||
let (mix_tx, _) = mpsc::unbounded();
|
||||
let shutdown = TaskClient::dummy();
|
||||
let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone());
|
||||
|
||||
GatewayClient::<C, EphemeralCredentialStorage> {
|
||||
authenticated: false,
|
||||
disabled_credentials_mode: true,
|
||||
bandwidth_remaining: 0,
|
||||
gateway_address,
|
||||
gateway_identity,
|
||||
local_identity,
|
||||
shared_key: None,
|
||||
connection: SocketState::NotConnected,
|
||||
packet_router,
|
||||
response_timeout_duration,
|
||||
bandwidth_controller: None,
|
||||
should_reconnect_on_failure: false,
|
||||
reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS,
|
||||
reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF,
|
||||
shutdown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@ use nym_api_requests::models::{
|
||||
};
|
||||
use nym_coconut_dkg_common::types::NodeIndex;
|
||||
use nym_coconut_interface::VerificationKey;
|
||||
pub use nym_mixnet_contract_common::{mixnode::MixNodeDetails, GatewayBond, IdentityKeyRef, MixId};
|
||||
pub use nym_mixnet_contract_common::{
|
||||
mixnode::MixNodeDetails, GatewayBond, IdentityKey, IdentityKeyRef, MixId,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
#[cfg(feature = "nyxd-client")]
|
||||
@@ -31,7 +33,7 @@ use nym_mixnet_contract_common::{
|
||||
families::{Family, FamilyHead},
|
||||
mixnode::MixNodeBond,
|
||||
pending_events::{PendingEpochEvent, PendingIntervalEvent},
|
||||
Delegation, IdentityKey, RewardedSetNodeStatus, UnbondedMixnode,
|
||||
Delegation, RewardedSetNodeStatus, UnbondedMixnode,
|
||||
};
|
||||
#[cfg(feature = "nyxd-client")]
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
|
||||
@@ -7,6 +7,7 @@ use nym_mixnet_contract_common::mixnode::MixNodeDetails;
|
||||
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId};
|
||||
use nym_sphinx_addressing::nodes::NodeIdentity;
|
||||
use nym_sphinx_types::Node as SphinxNode;
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::{CryptoRng, Rng};
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::TryInto;
|
||||
@@ -138,7 +139,7 @@ impl NymTopology {
|
||||
&self.gateways
|
||||
}
|
||||
|
||||
fn get_gateway(&self, gateway_identity: &NodeIdentity) -> Option<&gateway::Node> {
|
||||
pub fn get_gateway(&self, gateway_identity: &NodeIdentity) -> Option<&gateway::Node> {
|
||||
self.gateways
|
||||
.iter()
|
||||
.find(|gateway| gateway.identity() == gateway_identity)
|
||||
@@ -152,6 +153,15 @@ impl NymTopology {
|
||||
self.gateways = gateways
|
||||
}
|
||||
|
||||
pub fn random_gateway<R>(&self, rng: &mut R) -> Result<&gateway::Node, NymTopologyError>
|
||||
where
|
||||
R: Rng + CryptoRng,
|
||||
{
|
||||
self.gateways
|
||||
.choose(rng)
|
||||
.ok_or(NymTopologyError::NoGatewaysAvailable)
|
||||
}
|
||||
|
||||
/// Returns a vec of size of `num_mix_hops` of mixnodes, such that each subsequent node is on
|
||||
/// next layer, starting from layer 1
|
||||
pub fn random_mix_route<R>(
|
||||
@@ -162,8 +172,6 @@ impl NymTopology {
|
||||
where
|
||||
R: Rng + CryptoRng + ?Sized,
|
||||
{
|
||||
use rand::seq::SliceRandom;
|
||||
|
||||
if self.mixes.len() < num_mix_hops as usize {
|
||||
return Err(NymTopologyError::InvalidNumberOfHopsError {
|
||||
available: self.mixes.len(),
|
||||
|
||||
@@ -2,9 +2,9 @@ use crate::{
|
||||
error::{BackendError, Result},
|
||||
state::State,
|
||||
};
|
||||
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
|
||||
use nym_client_core::config::Config as BaseConfig;
|
||||
use nym_config_common::NymConfig;
|
||||
use nym_credential_storage::persistent_storage::PersistentStorage;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_socks5_client_core::config::{Config as Socks5Config, Socks5};
|
||||
use std::path::PathBuf;
|
||||
@@ -139,15 +139,16 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str
|
||||
.map_err(|_| BackendError::UnableToParseGateway)?;
|
||||
|
||||
// Setup gateway by either registering a new one, or reusing exiting keys
|
||||
let gateway =
|
||||
nym_client_core::init::setup_gateway_from_config::<Socks5Config, _, PersistentStorage>(
|
||||
register_gateway,
|
||||
Some(chosen_gateway_id),
|
||||
config.get_base(),
|
||||
// TODO: another instance where this setting should probably get used
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
let key_store = OnDiskKeys::from_config(config.get_base());
|
||||
let gateway = nym_client_core::init::setup_gateway_from_config::<Socks5Config, _, _>(
|
||||
&key_store,
|
||||
register_gateway,
|
||||
Some(chosen_gateway_id),
|
||||
config.get_base(),
|
||||
// TODO: another instance where this setting should probably get used
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
|
||||
config.get_base_mut().set_gateway_endpoint(gateway);
|
||||
|
||||
@@ -157,7 +158,8 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str
|
||||
|
||||
print_saved_config(&config);
|
||||
|
||||
let address = nym_client_core::init::get_client_address_from_stored_keys(config.get_base())?;
|
||||
let address =
|
||||
nym_client_core::init::get_client_address_from_stored_ondisk_keys(config.get_base())?;
|
||||
log::info!("The address of this client is: {}", address);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -16,14 +16,11 @@ use nym_client_core::client::base_client::BaseClient;
|
||||
use nym_client_core::client::key_manager::persistence::KeyStore;
|
||||
use nym_client_core::client::key_manager::ManagedKeys;
|
||||
use nym_client_core::config::DebugConfig;
|
||||
use nym_client_core::init::GatewaySetup;
|
||||
use nym_client_core::{
|
||||
client::{
|
||||
base_client::{BaseClientBuilder, CredentialsToggle},
|
||||
replies::reply_storage::ReplyStorageBackend,
|
||||
},
|
||||
client::{base_client::BaseClientBuilder, replies::reply_storage::ReplyStorageBackend},
|
||||
config::GatewayEndpointConfig,
|
||||
};
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use nym_socks5_client_core::config::Socks5;
|
||||
use nym_task::manager::TaskStatus;
|
||||
@@ -356,31 +353,17 @@ where
|
||||
}
|
||||
log::debug!("Registering with gateway");
|
||||
|
||||
let user_chosen_gateway = self
|
||||
.config
|
||||
.user_chosen_gateway
|
||||
.as_ref()
|
||||
.map(identity::PublicKey::from_base58_string)
|
||||
.transpose()?;
|
||||
|
||||
let api_endpoints = self.get_api_endpoints();
|
||||
let (gateway_config, shared_key) =
|
||||
nym_client_core::init::register_with_gateway::<S::CredentialStore>(
|
||||
self.managed_keys.identity_keypair(),
|
||||
api_endpoints,
|
||||
user_chosen_gateway,
|
||||
// TODO: this should probably be configurable with the config
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
let gateway_setup = GatewaySetup::new(None, self.config.user_chosen_gateway.clone(), None);
|
||||
|
||||
let gateway_config = nym_client_core::init::get_registered_gateway::<S>(
|
||||
api_endpoints,
|
||||
&self.key_store,
|
||||
gateway_setup,
|
||||
!self.config.key_mode.is_keep(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// TODO: this will deal with storage if it's a fresh key
|
||||
self.managed_keys
|
||||
.deal_with_gateway_key(shared_key, &self.key_store)
|
||||
.await
|
||||
.map_err(|source| Error::KeyStorageError {
|
||||
source: Box::new(source),
|
||||
})?;
|
||||
self.state = BuilderState::Registered {
|
||||
gateway_endpoint_config: gateway_config,
|
||||
};
|
||||
@@ -481,7 +464,7 @@ where
|
||||
self.key_store,
|
||||
self.bandwidth_controller,
|
||||
self.reply_storage_backend,
|
||||
CredentialsToggle::from(self.config.enabled_credentials_mode),
|
||||
self.config.enabled_credentials_mode.into(),
|
||||
nym_api_endpoints,
|
||||
);
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ use crate::{
|
||||
};
|
||||
use clap::Args;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
|
||||
use nym_config::NymConfig;
|
||||
use nym_credential_storage::persistent_storage::PersistentStorage;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use serde::Serialize;
|
||||
@@ -128,7 +128,9 @@ pub(crate) async fn execute(args: &Init) -> Result<(), NetworkRequesterError> {
|
||||
|
||||
// Setup gateway by either registering a new one, or creating a new config from the selected
|
||||
// one but with keys kept, or reusing the gateway configuration.
|
||||
let gateway = nym_client_core::init::setup_gateway_from_config::<Config, _, PersistentStorage>(
|
||||
let key_store = OnDiskKeys::from_config(config.get_base());
|
||||
let gateway = nym_client_core::init::setup_gateway_from_config::<Config, _, _>(
|
||||
&key_store,
|
||||
register_gateway,
|
||||
user_chosen_gateway_id,
|
||||
config.get_base(),
|
||||
@@ -148,7 +150,8 @@ pub(crate) async fn execute(args: &Init) -> Result<(), NetworkRequesterError> {
|
||||
|
||||
print_saved_config(&config);
|
||||
|
||||
let address = nym_client_core::init::get_client_address_from_stored_keys(config.get_base())?;
|
||||
let address =
|
||||
nym_client_core::init::get_client_address_from_stored_ondisk_keys(config.get_base())?;
|
||||
let init_results = InitResults::new(&config, &address);
|
||||
println!("{}", args.output.format(&init_results));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user