Feature/default nym api (#2898)

* Setting default 'id' if not provided

* Modified 'NymConfig' to always require 'id'

* moved creation of nym-api directories away from 'override_config'

* missing optional id usage in nym-connect

* changelog

* Removed default value for '--id' argument
This commit is contained in:
Jędrzej Stuczyński
2023-01-25 14:49:28 +00:00
committed by GitHub
parent c958975fff
commit c218cba96c
27 changed files with 98 additions and 112 deletions
+5
View File
@@ -4,6 +4,10 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
# [Unreleased]
### Changed
- nym-api: an `--id` flag is now always explicitly required ([#2898])
### Added
- dkg rerun from scratch and dkg-specific epochs ([#2839])
@@ -13,6 +17,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
[#2839]: https://github.com/nymtech/nym/pull/2839
[#2870]: https://github.com/nymtech/nym/pull/2870
[#2874]: https://github.com/nymtech/nym/pull/2874
[#2898]: https://github.com/nymtech/nym/pull/2898
# [v1.1.7] (2023-01-24)
+8 -8
View File
@@ -541,35 +541,35 @@ impl<T: NymConfig> Default for Client<T> {
impl<T: NymConfig> Client<T> {
fn default_private_identity_key_file(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("private_identity.pem")
T::default_data_directory(id).join("private_identity.pem")
}
fn default_public_identity_key_file(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("public_identity.pem")
T::default_data_directory(id).join("public_identity.pem")
}
fn default_private_encryption_key_file(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("private_encryption.pem")
T::default_data_directory(id).join("private_encryption.pem")
}
fn default_public_encryption_key_file(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("public_encryption.pem")
T::default_data_directory(id).join("public_encryption.pem")
}
fn default_gateway_shared_key_file(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("gateway_shared.pem")
T::default_data_directory(id).join("gateway_shared.pem")
}
fn default_ack_key_file(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("ack_key.pem")
T::default_data_directory(id).join("ack_key.pem")
}
fn default_reply_surb_database_path(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join("persistent_reply_store.sqlite")
T::default_data_directory(id).join("persistent_reply_store.sqlite")
}
fn default_database_path(id: &str) -> PathBuf {
T::default_data_directory(Some(id)).join(DB_FILE_NAME)
T::default_data_directory(id).join(DB_FILE_NAME)
}
}
+1 -1
View File
@@ -149,7 +149,7 @@ pub fn load_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig
where
T: NymConfig + ClientCoreConfigTrait,
{
T::load_from_file(Some(id))
T::load_from_file(id)
.map(|existing_config| existing_config.get_gateway_endpoint().clone())
.map_err(|err| {
log::error!(
+1 -1
View File
@@ -112,7 +112,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
let id = &args.id;
let already_init = Config::default_config_file_path(Some(id)).exists();
let already_init = Config::default_config_file_path(id).exists();
if already_init {
println!("Client \"{id}\" was already initialised before");
}
+1 -1
View File
@@ -99,7 +99,7 @@ fn version_check(cfg: &Config) -> bool {
pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn Error + Send + Sync>> {
let id = &args.id;
let mut config = match Config::load_from_file(Some(id)) {
let mut config = match Config::load_from_file(id) {
Ok(cfg) => cfg,
Err(err) => {
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id);
+1 -1
View File
@@ -131,7 +131,7 @@ pub(crate) fn execute(args: &Upgrade) {
let id = &args.id;
let existing_config = Config::load_from_file(Some(id)).unwrap_or_else(|err| {
let existing_config = Config::load_from_file(id).unwrap_or_else(|err| {
eprintln!("failed to load existing config file! - {err}");
process::exit(1)
});
+1 -1
View File
@@ -122,7 +122,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
let id = &args.id;
let provider_address = &args.provider;
let already_init = Config::default_config_file_path(Some(id)).exists();
let already_init = Config::default_config_file_path(id).exists();
if already_init {
println!("SOCKS5 client \"{id}\" was already initialised before");
}
+1 -1
View File
@@ -113,7 +113,7 @@ fn version_check(cfg: &Config) -> bool {
pub(crate) async fn execute(args: &Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let id = &args.id;
let mut config = match Config::load_from_file(Some(id)) {
let mut config = match Config::load_from_file(id) {
Ok(cfg) => cfg,
Err(err) => {
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id);
+1 -1
View File
@@ -144,7 +144,7 @@ pub(crate) fn execute(args: &Upgrade) {
let id = &args.id;
let existing_config = Config::load_from_file(Some(id)).unwrap_or_else(|err| {
let existing_config = Config::load_from_file(id).unwrap_or_else(|err| {
eprintln!("failed to load existing config file! - {err}");
process::exit(1)
});
+11 -27
View File
@@ -30,23 +30,15 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
fn default_root_directory() -> PathBuf;
// default, most probable, implementations; can be easily overridden where required
fn default_config_directory(id: Option<&str>) -> PathBuf {
if let Some(id) = id {
Self::default_root_directory().join(id).join(CONFIG_DIR)
} else {
Self::default_root_directory().join(CONFIG_DIR)
}
fn default_config_directory(id: &str) -> PathBuf {
Self::default_root_directory().join(id).join(CONFIG_DIR)
}
fn default_data_directory(id: Option<&str>) -> PathBuf {
if let Some(id) = id {
Self::default_root_directory().join(id).join(DATA_DIR)
} else {
Self::default_root_directory().join(DATA_DIR)
}
fn default_data_directory(id: &str) -> PathBuf {
Self::default_root_directory().join(id).join(DATA_DIR)
}
fn default_config_file_path(id: Option<&str>) -> PathBuf {
fn default_config_file_path(id: &str) -> PathBuf {
Self::default_config_directory(id).join(Self::config_file_name())
}
@@ -54,23 +46,15 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
fn try_default_root_directory() -> Option<PathBuf>;
fn try_default_config_directory(id: Option<&str>) -> Option<PathBuf> {
if let Some(id) = id {
Self::try_default_root_directory().map(|d| d.join(id).join(CONFIG_DIR))
} else {
Self::try_default_root_directory().map(|d| d.join(CONFIG_DIR))
}
fn try_default_config_directory(id: &str) -> Option<PathBuf> {
Self::try_default_root_directory().map(|d| d.join(id).join(CONFIG_DIR))
}
fn try_default_data_directory(id: Option<&str>) -> Option<PathBuf> {
if let Some(id) = id {
Self::try_default_root_directory().map(|d| d.join(id).join(DATA_DIR))
} else {
Self::try_default_root_directory().map(|d| d.join(DATA_DIR))
}
fn try_default_data_directory(id: &str) -> Option<PathBuf> {
Self::try_default_root_directory().map(|d| d.join(id).join(DATA_DIR))
}
fn try_default_config_file_path(id: Option<&str>) -> Option<PathBuf> {
fn try_default_config_file_path(id: &str) -> Option<PathBuf> {
Self::try_default_config_directory(id).map(|d| d.join(Self::config_file_name()))
}
@@ -113,7 +97,7 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned {
Ok(())
}
fn load_from_file(id: Option<&str>) -> io::Result<Self> {
fn load_from_file(id: &str) -> io::Result<Self> {
let file = Self::default_config_file_path(id);
log::trace!("Loading from file: {:#?}", file);
let config_contents = fs::read_to_string(file)?;
+1 -1
View File
@@ -106,7 +106,7 @@ impl From<Init> for OverrideConfig {
pub async fn execute(args: Init, output: OutputFormat) -> Result<(), Box<dyn Error + Send + Sync>> {
println!("Initialising gateway {}...", args.id);
let already_init = if Config::default_config_file_path(Some(&args.id)).exists() {
let already_init = if Config::default_config_file_path(&args.id).exists() {
eprintln!(
"Gateway \"{}\" was already initialised before! Config information will be \
overwritten (but keys will be kept)!",
+1 -1
View File
@@ -139,7 +139,7 @@ fn do_upgrade(mut config: Config, args: &Upgrade, package_version: Version) {
pub async fn execute(args: &Upgrade) {
let package_version = parse_package_version();
let existing_config = Config::load_from_file(Some(&args.id)).unwrap_or_else(|err| {
let existing_config = Config::load_from_file(&args.id).unwrap_or_else(|err| {
eprintln!("failed to load existing config file! - {err}");
process::exit(1)
});
+5 -5
View File
@@ -378,23 +378,23 @@ pub struct Gateway {
impl Gateway {
fn default_private_sphinx_key_file(id: &str) -> PathBuf {
Config::default_data_directory(Some(id)).join("private_sphinx.pem")
Config::default_data_directory(id).join("private_sphinx.pem")
}
fn default_public_sphinx_key_file(id: &str) -> PathBuf {
Config::default_data_directory(Some(id)).join("public_sphinx.pem")
Config::default_data_directory(id).join("public_sphinx.pem")
}
fn default_private_identity_key_file(id: &str) -> PathBuf {
Config::default_data_directory(Some(id)).join("private_identity.pem")
Config::default_data_directory(id).join("private_identity.pem")
}
fn default_public_identity_key_file(id: &str) -> PathBuf {
Config::default_data_directory(Some(id)).join("public_identity.pem")
Config::default_data_directory(id).join("public_identity.pem")
}
fn default_database_path(id: &str) -> PathBuf {
Config::default_data_directory(Some(id)).join("db.sqlite")
Config::default_data_directory(id).join("db.sqlite")
}
}
+2 -2
View File
@@ -11,14 +11,14 @@ pub(crate) fn build_config<O: Into<OverrideConfig>>(
id: String,
override_args: O,
) -> Result<Config, GatewayError> {
let config = match Config::load_from_file(Some(&id)) {
let config = match Config::load_from_file(&id) {
Ok(cfg) => cfg,
Err(err) => {
error!(
"Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})",
);
return Err(GatewayError::ConfigLoadFailure {
path: Config::default_config_file_path(Some(&id)),
path: Config::default_config_file_path(&id),
id,
source: err,
});
+2 -2
View File
@@ -41,7 +41,7 @@ fn read_user_input() -> String {
pub(crate) fn execute(args: Describe) {
// ensure that the mixnode has in fact been initialized
match Config::load_from_file(Some(&args.id)) {
match Config::load_from_file(&args.id) {
Ok(cfg) => cfg,
Err(err) => {
error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", &args.id);
@@ -83,7 +83,7 @@ pub(crate) fn execute(args: Describe) {
// save the struct
NodeDescription::save_to_file(
&node_description,
Config::default_config_directory(Some(&args.id)),
Config::default_config_directory(&args.id),
)
.unwrap()
}
+1 -1
View File
@@ -68,7 +68,7 @@ pub(crate) fn execute(args: &Init, output: OutputFormat) {
let id = &override_config_fields.id;
eprintln!("Initialising mixnode {id}...");
let already_init = if Config::default_config_file_path(Some(id)).exists() {
let already_init = if Config::default_config_file_path(id).exists() {
eprintln!("Mixnode \"{id}\" was already initialised before! Config information will be overwritten (but keys will be kept)!");
true
} else {
+1 -1
View File
@@ -15,7 +15,7 @@ pub(crate) struct NodeDetails {
}
pub(crate) fn execute(args: &NodeDetails, output: OutputFormat) {
let config = match Config::load_from_file(Some(&args.id)) {
let config = match Config::load_from_file(&args.id) {
Ok(cfg) => cfg,
Err(err) => {
error!(
+1 -1
View File
@@ -79,7 +79,7 @@ fn special_addresses() -> Vec<&'static str> {
pub(crate) async fn execute(args: &Run, output: OutputFormat) {
eprintln!("Starting mixnode {}...", args.id);
let mut config = match Config::load_from_file(Some(&args.id)) {
let mut config = match Config::load_from_file(&args.id) {
Ok(cfg) => cfg,
Err(err) => {
error!(
+1 -1
View File
@@ -71,7 +71,7 @@ fn print_signed_text(private_key: &identity::PrivateKey, text: &str) {
}
pub(crate) fn execute(args: &Sign) {
let config = match Config::load_from_file(Some(&args.id)) {
let config = match Config::load_from_file(&args.id) {
Ok(cfg) => cfg,
Err(err) => {
error!(
+1 -1
View File
@@ -125,7 +125,7 @@ fn do_upgrade(mut config: Config, args: &Upgrade, package_version: Version) {
pub(crate) fn execute(args: &Upgrade) {
let package_version = parse_package_version();
let existing_config = Config::load_from_file(Some(&args.id)).unwrap_or_else(|err| {
let existing_config = Config::load_from_file(&args.id).unwrap_or_else(|err| {
eprintln!("failed to load existing config file! - {err}");
process::exit(1)
});
+4 -4
View File
@@ -376,19 +376,19 @@ struct MixNode {
impl MixNode {
fn default_private_identity_key_file(id: &str) -> PathBuf {
Config::default_data_directory(Some(id)).join("private_identity.pem")
Config::default_data_directory(id).join("private_identity.pem")
}
fn default_public_identity_key_file(id: &str) -> PathBuf {
Config::default_data_directory(Some(id)).join("public_identity.pem")
Config::default_data_directory(id).join("public_identity.pem")
}
fn default_private_sphinx_key_file(id: &str) -> PathBuf {
Config::default_data_directory(Some(id)).join("private_sphinx.pem")
Config::default_data_directory(id).join("private_sphinx.pem")
}
fn default_public_sphinx_key_file(id: &str) -> PathBuf {
Config::default_data_directory(Some(id)).join("public_sphinx.pem")
Config::default_data_directory(id).join("public_sphinx.pem")
}
}
+1 -1
View File
@@ -58,7 +58,7 @@ impl MixNode {
}
fn load_node_description(config: &Config) -> NodeDescription {
NodeDescription::load_from_file(Config::default_config_directory(Some(&config.get_id())))
NodeDescription::load_from_file(Config::default_config_directory(&config.get_id()))
.unwrap_or_default()
}
+13 -14
View File
@@ -44,7 +44,7 @@ pub(crate) struct CliArgs {
/// Id of the nym-api we want to run
#[clap(long)]
pub(crate) id: Option<String>,
pub(crate) id: String,
/// Specifies whether network monitoring is enabled on this API
#[clap(short = 'm', long)]
@@ -104,12 +104,13 @@ pub(crate) struct CliArgs {
}
pub(crate) fn build_config(args: CliArgs) -> Result<Config> {
let id = args.id.clone();
// try to load config from the file, if it doesn't exist, use default values
let id = args.id.as_deref();
let (config_from_file, _already_initialized) = match Config::load_from_file(id) {
let (config_from_file, already_initialized) = match Config::load_from_file(&id) {
Ok(cfg) => (cfg, true),
Err(_) => {
let config_path = Config::default_config_file_path(id)
let config_path = Config::default_config_file_path(&id)
.into_os_string()
.into_string()
.unwrap();
@@ -123,8 +124,13 @@ pub(crate) fn build_config(args: CliArgs) -> Result<Config> {
let config = override_config(config_from_file, args);
#[cfg(feature = "coconut")]
if !_already_initialized {
if already_initialized {
fs::create_dir_all(Config::default_config_directory(&id))
.expect("Could not create config directory");
fs::create_dir_all(Config::default_data_directory(&id))
.expect("Could not create data directory");
#[cfg(feature = "coconut")]
crate::coconut::dkg::controller::init_keypair(&config)?;
}
@@ -132,15 +138,8 @@ pub(crate) fn build_config(args: CliArgs) -> Result<Config> {
}
pub(crate) fn override_config(mut config: Config, args: CliArgs) -> Config {
if let Some(id) = args.id {
fs::create_dir_all(Config::default_config_directory(Some(&id)))
.expect("Could not create config directory");
fs::create_dir_all(Config::default_data_directory(Some(&id)))
.expect("Could not create data directory");
config = config.with_id(&id);
}
config = config
.with_id(&args.id)
.with_optional(Config::with_custom_nyxd_validator, args.nyxd_validator)
.with_optional_env(
Config::with_custom_mixnet_contract,
+30 -32
View File
@@ -201,8 +201,8 @@ pub struct NetworkMonitor {
impl NetworkMonitor {
pub const DB_FILE: &'static str = "credentials_database.db";
fn default_credentials_database_path() -> PathBuf {
Config::default_data_directory(None).join(Self::DB_FILE)
fn default_credentials_database_path(id: &str) -> PathBuf {
Config::default_data_directory(id).join(Self::DB_FILE)
}
}
@@ -220,7 +220,7 @@ impl Default for NetworkMonitor {
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
gateway_connection_timeout: DEFAULT_GATEWAY_CONNECTION_TIMEOUT,
packet_delivery_timeout: DEFAULT_PACKET_DELIVERY_TIMEOUT,
credentials_database_path: Self::default_credentials_database_path(),
credentials_database_path: Default::default(),
test_routes: DEFAULT_TEST_ROUTES,
minimum_test_routes: DEFAULT_MINIMUM_TEST_ROUTES,
route_test_packets: DEFAULT_ROUTE_TEST_PACKETS,
@@ -242,15 +242,15 @@ pub struct NodeStatusAPI {
impl NodeStatusAPI {
pub const DB_FILE: &'static str = "db.sqlite";
fn default_database_path() -> PathBuf {
Config::default_data_directory(None).join(Self::DB_FILE)
fn default_database_path(id: &str) -> PathBuf {
Config::default_data_directory(id).join(Self::DB_FILE)
}
}
impl Default for NodeStatusAPI {
fn default() -> Self {
NodeStatusAPI {
database_path: Self::default_database_path(),
database_path: Default::default(),
caching_interval: DEFAULT_NODE_STATUS_CACHE_INTERVAL,
}
}
@@ -342,24 +342,24 @@ impl CoconutSigner {
pub const COCONUT_VERIFICATION_KEY_FILE: &'static str = "coconut_verification_key.pem";
pub const COCONUT_SECRET_KEY_FILE: &'static str = "coconut_secret_key.pem";
fn default_coconut_verification_key_path() -> PathBuf {
Config::default_data_directory(None).join(Self::COCONUT_VERIFICATION_KEY_FILE)
fn default_coconut_verification_key_path(id: &str) -> PathBuf {
Config::default_data_directory(id).join(Self::COCONUT_VERIFICATION_KEY_FILE)
}
fn default_coconut_secret_key_path() -> PathBuf {
Config::default_data_directory(None).join(Self::COCONUT_SECRET_KEY_FILE)
fn default_coconut_secret_key_path(id: &str) -> PathBuf {
Config::default_data_directory(id).join(Self::COCONUT_SECRET_KEY_FILE)
}
fn default_dkg_persistent_state_path() -> PathBuf {
Config::default_data_directory(None).join(Self::DKG_PERSISTENT_STATE_FILE)
fn default_dkg_persistent_state_path(id: &str) -> PathBuf {
Config::default_data_directory(id).join(Self::DKG_PERSISTENT_STATE_FILE)
}
fn default_dkg_decryption_key_path() -> PathBuf {
Config::default_data_directory(None).join(Self::DKG_DECRYPTION_KEY_FILE)
fn default_dkg_decryption_key_path(id: &str) -> PathBuf {
Config::default_data_directory(id).join(Self::DKG_DECRYPTION_KEY_FILE)
}
fn default_dkg_public_key_with_proof_path() -> PathBuf {
Config::default_data_directory(None).join(Self::DKG_PUBLIC_KEY_WITH_PROOF_FILE)
fn default_dkg_public_key_with_proof_path(id: &str) -> PathBuf {
Config::default_data_directory(id).join(Self::DKG_PUBLIC_KEY_WITH_PROOF_FILE)
}
}
@@ -367,11 +367,11 @@ impl Default for CoconutSigner {
fn default() -> Self {
Self {
enabled: Default::default(),
dkg_persistent_state_path: CoconutSigner::default_dkg_persistent_state_path(),
verification_key_path: CoconutSigner::default_coconut_verification_key_path(),
secret_key_path: CoconutSigner::default_coconut_secret_key_path(),
decryption_key_path: CoconutSigner::default_dkg_decryption_key_path(),
public_key_with_proof_path: CoconutSigner::default_dkg_public_key_with_proof_path(),
dkg_persistent_state_path: Default::default(),
verification_key_path: Default::default(),
secret_key_path: Default::default(),
decryption_key_path: Default::default(),
public_key_with_proof_path: Default::default(),
dkg_contract_polling_rate: DEFAULT_DKG_CONTRACT_POLLING_RATE,
}
}
@@ -384,20 +384,18 @@ impl Config {
pub fn with_id(mut self, id: &str) -> Self {
self.base.id = id.to_string();
self.node_status_api.database_path =
Config::default_data_directory(Some(id)).join(NodeStatusAPI::DB_FILE);
self.node_status_api.database_path = NodeStatusAPI::default_database_path(id);
self.network_monitor.credentials_database_path =
Config::default_data_directory(Some(id)).join(NetworkMonitor::DB_FILE);
NetworkMonitor::default_credentials_database_path(id);
self.coconut_signer.dkg_persistent_state_path =
Config::default_data_directory(Some(id)).join(CoconutSigner::DKG_PERSISTENT_STATE_FILE);
self.coconut_signer.verification_key_path = Config::default_data_directory(Some(id))
.join(CoconutSigner::COCONUT_VERIFICATION_KEY_FILE);
self.coconut_signer.secret_key_path =
Config::default_data_directory(Some(id)).join(CoconutSigner::COCONUT_SECRET_KEY_FILE);
CoconutSigner::default_dkg_persistent_state_path(id);
self.coconut_signer.verification_key_path =
CoconutSigner::default_coconut_verification_key_path(id);
self.coconut_signer.secret_key_path = CoconutSigner::default_coconut_secret_key_path(id);
self.coconut_signer.decryption_key_path =
Config::default_data_directory(Some(id)).join(CoconutSigner::DKG_DECRYPTION_KEY_FILE);
self.coconut_signer.public_key_with_proof_path = Config::default_data_directory(Some(id))
.join(CoconutSigner::DKG_PUBLIC_KEY_WITH_PROOF_FILE);
CoconutSigner::default_dkg_decryption_key_path(id);
self.coconut_signer.public_key_with_proof_path =
CoconutSigner::default_dkg_public_key_with_proof_path(id);
self
}
+1 -1
View File
@@ -93,7 +93,7 @@ impl Config {
}
pub fn config_file_location(id: &str) -> Result<PathBuf> {
Socks5Config::try_default_config_file_path(Some(id))
Socks5Config::try_default_config_file_path(id)
.ok_or(BackendError::CouldNotGetConfigFilename)
}
}
+1 -1
View File
@@ -85,7 +85,7 @@ impl State {
pub fn load_socks5_config(&self) -> Result<Socks5Config> {
let id = self.get_config_id()?;
let config = Socks5Config::load_from_file(Some(&id))
let config = Socks5Config::load_from_file(&id)
.tap_err(|_| log::warn!("Failed to load configuration file"))?;
Ok(config)
}
+1 -1
View File
@@ -36,7 +36,7 @@ pub fn start_nym_socks5_client(
GatewayEndpointConfig,
)> {
log::info!("Loading config from file: {id}");
let config = Socks5Config::load_from_file(Some(id))
let config = Socks5Config::load_from_file(id)
.tap_err(|_| log::warn!("Failed to load configuration file"))?;
let used_gateway = config.get_base().get_gateway_endpoint().clone();