From 9b10871efb4877e036b5d7ed33ffdfb52ddb9a22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 11 Mar 2024 12:09:37 +0000 Subject: [PATCH] ipr config migration --- .../ip-packet-router/src/cli/init.rs | 4 +- .../ip-packet-router/src/cli/mod.rs | 71 +++++++------- .../ip-packet-router/src/cli/run.rs | 2 +- .../ip-packet-router/src/cli/sign.rs | 2 +- .../ip-packet-router/src/config/mod.rs | 1 + .../src/config/old_config_v1.rs | 95 +++++++++++++++++++ 6 files changed, 137 insertions(+), 38 deletions(-) create mode 100644 service-providers/ip-packet-router/src/config/old_config_v1.rs diff --git a/service-providers/ip-packet-router/src/cli/init.rs b/service-providers/ip-packet-router/src/cli/init.rs index 207a6a748c..9a5808b755 100644 --- a/service-providers/ip-packet-router/src/cli/init.rs +++ b/service-providers/ip-packet-router/src/cli/init.rs @@ -21,8 +21,8 @@ impl InitialisableClient for IpPacketRouterInit { type InitArgs = Init; type Config = Config; - fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> { - try_upgrade_config(id) + async fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> { + try_upgrade_config(id).await } fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> { diff --git a/service-providers/ip-packet-router/src/cli/mod.rs b/service-providers/ip-packet-router/src/cli/mod.rs index c2ef5b800e..1ed7ca2920 100644 --- a/service-providers/ip-packet-router/src/cli/mod.rs +++ b/service-providers/ip-packet-router/src/cli/mod.rs @@ -1,14 +1,12 @@ -use clap::{CommandFactory, Parser, Subcommand}; -use log::{error, trace}; -use nym_bin_common::completions::{fig_generate, ArgShell}; -use nym_bin_common::{bin_info, version_checker}; -use nym_client_core::client::key_manager::persistence::OnDiskKeys; -use nym_client_core::config::GatewayEndpointConfig; -use nym_client_core::error::ClientCoreError; -use std::sync::OnceLock; - use crate::config::{BaseClientConfig, Config}; use crate::error::IpPacketRouterError; +use clap::{CommandFactory, Parser, Subcommand}; +use log::{error, info, trace}; +use nym_bin_common::completions::{fig_generate, ArgShell}; +use nym_bin_common::{bin_info, version_checker}; +use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33; +use nym_ip_packet_router::config::old_config_v1::ConfigV1; +use std::sync::OnceLock; mod build_info; mod init; @@ -105,36 +103,41 @@ pub(crate) async fn execute(args: Cli) -> Result<(), IpPacketRouterError> { Ok(()) } -// Unused until we need to start implementing config upgrades -#[allow(unused)] -fn persist_gateway_details( - config: &Config, - details: GatewayEndpointConfig, -) -> Result<(), IpPacketRouterError> { - let details_store = - OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details); - let keys_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone()); - let shared_keys = keys_store.ephemeral_load_gateway_keys().map_err(|source| { - IpPacketRouterError::ClientCoreError(ClientCoreError::KeyStoreError { - source: Box::new(source), - }) - })?; - let persisted_details = PersistedGatewayDetails::new(details.into(), Some(&shared_keys))?; - details_store - .store_to_disk(&persisted_details) - .map_err(|source| { - IpPacketRouterError::ClientCoreError(ClientCoreError::GatewaysDetailsStoreError { - source: Box::new(source), - }) - }) +async fn try_upgrade_v1_config(id: &str) -> Result { + // explicitly load it as v1 (which is incompatible with the current one) + let Ok(old_config) = ConfigV1::read_from_default_path(id) else { + // if we failed to load it, there might have been nothing to upgrade + // or maybe it was an even older file. in either way. just ignore it and carry on with our day + return Ok(false); + }; + info!("It seems the client is using v1 config template."); + info!("It is going to get updated to the current specification."); + + let old_paths = old_config.storage_paths.clone(); + let updated = old_config.try_upgrade()?; + + v1_1_33::migrate_gateway_details( + &old_paths.common_paths, + &updated.storage_paths.common_paths, + None, + ) + .await?; + + updated.save_to_default_location()?; + Ok(true) } -fn try_upgrade_config(_id: &str) -> Result<(), IpPacketRouterError> { +async fn try_upgrade_config(id: &str) -> Result<(), IpPacketRouterError> { trace!("Attempting to upgrade config"); + + if try_upgrade_v1_config(id).await? { + return Ok(()); + } + Ok(()) } -fn try_load_current_config(id: &str) -> Result { +async fn try_load_current_config(id: &str) -> Result { // try to load the config as is if let Ok(cfg) = Config::read_from_default_path(id) { return if !cfg.validate() { @@ -145,7 +148,7 @@ fn try_load_current_config(id: &str) -> Result { } // we couldn't load it - try upgrading it from older revisions - try_upgrade_config(id)?; + try_upgrade_config(id).await?; let config = match Config::read_from_default_path(id) { Ok(cfg) => cfg, diff --git a/service-providers/ip-packet-router/src/cli/run.rs b/service-providers/ip-packet-router/src/cli/run.rs index cbfb3f8453..6167de7666 100644 --- a/service-providers/ip-packet-router/src/cli/run.rs +++ b/service-providers/ip-packet-router/src/cli/run.rs @@ -25,7 +25,7 @@ impl From for OverrideConfig { } pub(crate) async fn execute(args: &Run) -> Result<(), IpPacketRouterError> { - let mut config = try_load_current_config(&args.common_args.id)?; + let mut config = try_load_current_config(&args.common_args.id).await?; config = override_config(config, OverrideConfig::from(args.clone())); log::debug!("Using config: {:#?}", config); diff --git a/service-providers/ip-packet-router/src/cli/sign.rs b/service-providers/ip-packet-router/src/cli/sign.rs index c282483de3..2b56007b47 100644 --- a/service-providers/ip-packet-router/src/cli/sign.rs +++ b/service-providers/ip-packet-router/src/cli/sign.rs @@ -52,7 +52,7 @@ fn print_signed_contract_msg( } pub(crate) async fn execute(args: &Sign) -> Result<(), IpPacketRouterError> { - let config = try_load_current_config(&args.id)?; + let config = try_load_current_config(&args.id).await?; if !version_check(&config) { log::error!("Failed the local version check"); diff --git a/service-providers/ip-packet-router/src/config/mod.rs b/service-providers/ip-packet-router/src/config/mod.rs index 1ea0ee755b..1d36c97d16 100644 --- a/service-providers/ip-packet-router/src/config/mod.rs +++ b/service-providers/ip-packet-router/src/config/mod.rs @@ -22,6 +22,7 @@ use crate::config::persistence::IpPacketRouterPaths; use self::template::CONFIG_TEMPLATE; +pub mod old_config_v1; mod persistence; mod template; diff --git a/service-providers/ip-packet-router/src/config/old_config_v1.rs b/service-providers/ip-packet-router/src/config/old_config_v1.rs new file mode 100644 index 0000000000..34399af4cf --- /dev/null +++ b/service-providers/ip-packet-router/src/config/old_config_v1.rs @@ -0,0 +1,95 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::persistence::IpPacketRouterPaths; +use crate::config::Config; +use crate::config::{default_config_filepath, IpPacketRouter}; +use crate::error::IpPacketRouterError; +use nym_bin_common::logging::LoggingSettings; +use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33; +use nym_client_core::config::old_config_v1_1_33::ConfigV1_1_33 as BaseConfigV1_1_33; +use nym_config::read_config_from_toml_file; +use nym_config::serde_helpers::de_maybe_stringified; +use nym_network_defaults::mainnet; +use serde::{Deserialize, Serialize}; +use std::io; +use std::path::{Path, PathBuf}; +use url::Url; + +#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)] +pub struct IpPacketRouterPathsV1 { + #[serde(flatten)] + pub common_paths: CommonClientPathsV1_1_33, + + /// Location of the file containing our description + pub ip_packet_router_description: PathBuf, +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct ConfigV1 { + #[serde(flatten)] + pub base: BaseConfigV1_1_33, + + #[serde(default)] + pub ip_packet_router: IpPacketRouterV1, + + pub storage_paths: IpPacketRouterPathsV1, + + pub logging: LoggingSettings, +} + +impl ConfigV1 { + pub fn read_from_toml_file>(path: P) -> io::Result { + read_config_from_toml_file(path) + } + + pub fn read_from_default_path>(id: P) -> io::Result { + Self::read_from_toml_file(default_config_filepath(id)) + } + + pub fn try_upgrade(self) -> Result { + Ok(Config { + base: self.base.into(), + ip_packet_router: self.ip_packet_router.into(), + storage_paths: IpPacketRouterPaths { + common_paths: self.storage_paths.common_paths.upgrade_default()?, + ip_packet_router_description: self.storage_paths.ip_packet_router_description, + }, + logging: self.logging, + }) + } +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct IpPacketRouterV1 { + /// Disable Poisson sending rate. + pub disable_poisson_rate: bool, + + /// Specifies the url for an upstream source of the exit policy used by this node. + #[serde(deserialize_with = "de_maybe_stringified")] + pub upstream_exit_policy_url: Option, +} + +impl Default for IpPacketRouterV1 { + fn default() -> Self { + IpPacketRouterV1 { + disable_poisson_rate: true, + upstream_exit_policy_url: Some( + mainnet::EXIT_POLICY_URL + .parse() + .expect("invalid default exit policy URL"), + ), + } + } +} + +impl From for IpPacketRouter { + fn from(value: IpPacketRouterV1) -> Self { + IpPacketRouter { + disable_poisson_rate: value.disable_poisson_rate, + upstream_exit_policy_url: value.upstream_exit_policy_url, + } + } +}