Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client: dedup setup gateway during init #1871

Merged
merged 2 commits into from
Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clients/client-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ pub enum ClientCoreError {
NoGatewayWithId(String),
#[error("No gateways on network")]
NoGatewaysOnNetwork,
#[error("Failed to setup gateway")]
FailedToSetupGateway,
#[error("List of validator apis is empty")]
ListOfValidatorApisIsEmpty,
#[error("Could not load existing gateway configuration: {0}")]
Expand Down
37 changes: 36 additions & 1 deletion clients/client-core/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use url::Url;

use crate::{
client::key_manager::KeyManager,
config::{persistence::key_pathfinder::ClientKeyPathfinder, Config},
config::{persistence::key_pathfinder::ClientKeyPathfinder, Config, GatewayEndpointConfig},
error::ClientCoreError,
};

Expand Down Expand Up @@ -140,6 +140,41 @@ async fn register_with_gateway(
Ok(shared_keys)
}

pub async fn setup_gateway<T: NymConfig>(
register: bool,
user_chosen_gateway_id: Option<&str>,
config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError> {
if register {
// Get the gateway details by querying the validator-api. Either pick one at random or use
// the chosen one if it's among the available ones.
println!("Configuring gateway");
let gateway =
query_gateway_details(config.get_validator_api_endpoints(), user_chosen_gateway_id)
.await?;
log::debug!("Querying gateway gives: {}", gateway);

// Registering with gateway by setting up and writing shared keys to disk
log::trace!("Registering gateway");
register_with_gateway_and_store_keys(gateway.clone(), config).await?;
println!("Saved all generated keys");

Ok(gateway.into())
} else if user_chosen_gateway_id.is_some() {
// Just set the config, don't register or create any keys
// This assumes that the user knows what they are doing, and that the existing keys are
// valid for the gateway being used
println!("Using gateway provided by user, keeping existing keys");
let gateway =
query_gateway_details(config.get_validator_api_endpoints(), user_chosen_gateway_id)
.await?;
log::debug!("Querying gateway gives: {}", gateway);
Ok(gateway.into())
} else {
Err(ClientCoreError::FailedToSetupGateway)
}
}

pub fn get_client_address<T>(config: &Config<T>) -> Result<Recipient, ClientCoreError>
where
T: config::NymConfig,
Expand Down
67 changes: 19 additions & 48 deletions clients/native/src/commands/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,20 @@ pub(crate) async fn execute(args: &Init) {
let override_config_fields = OverrideConfig::from(args.clone());
config = override_config(config, override_config_fields);

let gateway = setup_gateway(id, register_gateway, user_chosen_gateway_id, &config)
let gateway = if !register_gateway && user_chosen_gateway_id.is_none() {
reuse_gateway_config(id)
} else {
client_core::init::setup_gateway(
register_gateway,
user_chosen_gateway_id,
config.get_base(),
)
.await
.unwrap_or_else(|err| {
eprintln!("Failed to setup gateway\nError: {err}");
std::process::exit(1)
});
}
.unwrap_or_else(|err| {
eprintln!("Failed to setup gateway\nError: {err}");
std::process::exit(1)
});
config.get_base_mut().with_gateway_endpoint(gateway);

let config_save_location = config.get_config_file_save_location();
Expand Down Expand Up @@ -180,45 +188,11 @@ pub(crate) async fn execute(args: &Init) {
}
}

async fn setup_gateway(
id: &str,
register: bool,
user_chosen_gateway_id: Option<&str>,
config: &Config,
) -> Result<GatewayEndpointConfig, ClientCoreError> {
if register {
// Get the gateway details by querying the validator-api. Either pick one at random or use
// the chosen one if it's among the available ones.
println!("Configuring gateway");
let gateway = client_core::init::query_gateway_details(
config.get_base().get_validator_api_endpoints(),
user_chosen_gateway_id,
)
.await?;
log::debug!("Querying gateway gives: {}", gateway);

// Registering with gateway by setting up and writing shared keys to disk
log::trace!("Registering gateway");
client_core::init::register_with_gateway_and_store_keys(gateway.clone(), config.get_base())
.await?;
println!("Saved all generated keys");

Ok(gateway.into())
} else if user_chosen_gateway_id.is_some() {
// Just set the config, don't register or create any keys
// This assumes that the user knows what they are doing, and that the existing keys are
// valid for the gateway being used
println!("Using gateway provided by user, keeping existing keys");
let gateway = client_core::init::query_gateway_details(
config.get_base().get_validator_api_endpoints(),
user_chosen_gateway_id,
)
.await?;
log::debug!("Querying gateway gives: {}", gateway);
Ok(gateway.into())
} else {
println!("Not registering gateway, will reuse existing config and keys");
let existing_config = Config::load_from_file(Some(id)).map_err(|err| {
fn reuse_gateway_config(id: &str) -> Result<GatewayEndpointConfig, ClientCoreError> {
println!("Not registering gateway, will reuse existing config and keys");
Config::load_from_file(Some(id))
.map(|existing_config| existing_config.get_base().get_gateway_endpoint().clone())
.map_err(|err| {
log::error!(
"Unable to configure gateway: {err}. \n
Seems like the client was already initialized but it was not possible to read \
Expand All @@ -227,8 +201,5 @@ async fn setup_gateway(
removing the existing configuration and starting over."
);
ClientCoreError::CouldNotLoadExistingGatewayConfiguration(err)
})?;

Ok(existing_config.get_base().get_gateway_endpoint().clone())
}
})
}
66 changes: 19 additions & 47 deletions clients/socks5/src/commands/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,20 @@ pub(crate) async fn execute(args: &Init) {
let override_config_fields = OverrideConfig::from(args.clone());
config = override_config(config, override_config_fields);

let gateway = setup_gateway(id, register_gateway, user_chosen_gateway_id, &config)
let gateway = if !register_gateway && user_chosen_gateway_id.is_none() {
reuse_gateway_config(id)
} else {
client_core::init::setup_gateway(
register_gateway,
user_chosen_gateway_id,
config.get_base(),
)
.await
.unwrap_or_else(|err| {
eprintln!("Failed to setup gateway\nError: {err}");
std::process::exit(1)
});
}
.unwrap_or_else(|err| {
eprintln!("Failed to setup gateway\nError: {err}");
std::process::exit(1)
});
config.get_base_mut().with_gateway_endpoint(gateway);

let config_save_location = config.get_config_file_save_location();
Expand Down Expand Up @@ -179,45 +187,11 @@ pub(crate) async fn execute(args: &Init) {
println!("\nThe address of this client is: {}\n", address);
}

async fn setup_gateway(
id: &str,
register: bool,
user_chosen_gateway_id: Option<&str>,
config: &Config,
) -> Result<GatewayEndpointConfig, ClientCoreError> {
if register {
// Get the gateway details by querying the validator-api. Either pick one at random or use
// the chosen one if it's among the available ones.
println!("Configuring gateway");
let gateway = client_core::init::query_gateway_details(
config.get_base().get_validator_api_endpoints(),
user_chosen_gateway_id,
)
.await?;
log::debug!("Querying gateway gives: {}", gateway);

// Registering with gateway by setting up and writing shared keys to disk
log::trace!("Registering gateway");
client_core::init::register_with_gateway_and_store_keys(gateway.clone(), config.get_base())
.await?;
println!("Saved all generated keys");

Ok(gateway.into())
} else if user_chosen_gateway_id.is_some() {
// Just set the config, don't register or create any keys
// This assumes that the user knows what they are doing, and that the existing keys are
// valid for the gateway being used
println!("Using gateway provided by user, keeping existing keys");
let gateway = client_core::init::query_gateway_details(
config.get_base().get_validator_api_endpoints(),
user_chosen_gateway_id,
)
.await?;
log::debug!("Querying gateway gives: {}", gateway);
Ok(gateway.into())
} else {
println!("Not registering gateway, will reuse existing config and keys");
let existing_config = Config::load_from_file(Some(id)).map_err(|err| {
fn reuse_gateway_config(id: &str) -> Result<GatewayEndpointConfig, ClientCoreError> {
println!("Not registering gateway, will reuse existing config and keys");
Config::load_from_file(Some(id))
.map(|existing_config| existing_config.get_base().get_gateway_endpoint().clone())
.map_err(|err| {
log::error!(
"Unable to configure gateway: {err}. \n
Seems like the client was already initialized but it was not possible to read \
Expand All @@ -226,7 +200,5 @@ async fn setup_gateway(
removing the existing configuration and starting over."
);
ClientCoreError::CouldNotLoadExistingGatewayConfiguration(err)
})?;
Ok(existing_config.get_base().get_gateway_endpoint().clone())
}
})
}
78 changes: 15 additions & 63 deletions nym-connect/src-tauri/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::path::PathBuf;

use client_core::config::GatewayEndpointConfig;
use std::sync::Arc;
use tap::TapFallible;
use tokio::sync::RwLock;
Expand Down Expand Up @@ -127,21 +126,31 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str
.set_custom_validator_apis(config_common::parse_validators(&raw_validators));
}

let gateway = setup_gateway(
&id,
let gateway = client_core::init::setup_gateway(
register_gateway,
Some(&chosen_gateway_id),
config.get_socks5(),
config.get_base(),
)
.await?;

config.get_base_mut().with_gateway_endpoint(gateway);

let config_save_location = config.get_socks5().get_config_file_save_location();
config.get_socks5().save_to_file(None).tap_err(|_| {
log::error!("Failed to save the config file");
})?;

log::info!("Saved configuration file to {:?}", config_save_location);
print_save_config(&config);

let address = client_core::init::get_client_address(config.get_base())?;
log::info!("The address of this client is: {}", address);
Ok(())
}

fn print_save_config(config: &Config) {
log::info!(
"Saved configuration file to {:?}",
config.get_socks5().get_config_file_save_location()
);
log::info!("Gateway id: {}", config.get_base().get_gateway_id());
log::info!("Gateway owner: {}", config.get_base().get_gateway_owner());
log::info!(
Expand All @@ -158,61 +167,4 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str
config.get_socks5().get_listening_port()
);
log::info!("Client configuration completed.");

let address = client_core::init::get_client_address(config.get_base())?;
println!("\nThe address of this client is: {}\n", address);
Ok(())
}

// TODO: deduplicate with same functions in other client
async fn setup_gateway(
id: &str,
register: bool,
user_chosen_gateway_id: Option<&str>,
config: &Socks5Config,
) -> Result<GatewayEndpointConfig> {
if register {
// Get the gateway details by querying the validator-api. Either pick one at random or use
// the chosen one if it's among the available ones.
println!("Configuring gateway");
let gateway = client_core::init::query_gateway_details(
config.get_base().get_validator_api_endpoints(),
user_chosen_gateway_id,
)
.await?;
log::debug!("Querying gateway gives: {}", gateway);

// Registering with gateway by setting up and writing shared keys to disk
log::trace!("Registering gateway");
client_core::init::register_with_gateway_and_store_keys(gateway.clone(), config.get_base())
.await?;
println!("Saved all generated keys");

Ok(gateway.into())
} else if user_chosen_gateway_id.is_some() {
// Just set the config, don't register or create any keys
// This assumes that the user knows what they are doing, and that the existing keys are
// valid for the gateway being used
println!("Using gateway provided by user, keeping existing keys");
let gateway = client_core::init::query_gateway_details(
config.get_base().get_validator_api_endpoints(),
user_chosen_gateway_id,
)
.await?;
log::debug!("Querying gateway gives: {}", gateway);
Ok(gateway.into())
} else {
println!("Not registering gateway, will reuse existing config and keys");
let existing_config = Socks5Config::load_from_file(Some(id)).map_err(|err| {
log::error!(
"Unable to configure gateway: {err}. \n
Seems like the client was already initialized but it was not possible to read \
the existing configuration file. \n
CAUTION: Consider backing up your gateway keys and try force gateway registration, or \
removing the existing configuration and starting over."
);
BackendError::CouldNotLoadExistingGatewayConfiguration(err)
})?;
Ok(existing_config.get_base().get_gateway_endpoint().clone())
}
}