diff --git a/service-providers/network-requester/src/config/helpers.rs b/service-providers/network-requester/src/config/helpers.rs index f3d540334c..2b29776dea 100644 --- a/service-providers/network-requester/src/config/helpers.rs +++ b/service-providers/network-requester/src/config/helpers.rs @@ -2,17 +2,19 @@ // SPDX-License-Identifier: Apache-2.0 use crate::config::default_config_filepath; +use crate::config::old::v5::ConfigV5; use crate::config::old_config_v1_1_13::OldConfigV1; use crate::config::old_config_v1_1_20::ConfigV2; use crate::config::old_config_v1_1_20_2::ConfigV3; -use crate::config::old_config_v1_1_33::ConfigV14; +use crate::config::old_config_v1_1_33::ConfigV4; +use crate::config::Config; use crate::error::NetworkRequesterError; use log::{info, trace}; use nym_client_core::cli_helpers::CliClientConfig; use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33; use std::path::Path; -async fn try_upgrade_v1_1_13_config>( +async fn try_upgrade_v1_config>( config_path: P, ) -> Result { trace!("Trying to load as v1.1.13 config"); @@ -31,20 +33,22 @@ async fn try_upgrade_v1_1_13_config>( let updated_step2: ConfigV3 = updated_step1.into(); let (updated_step3, gateway_config) = updated_step2.upgrade()?; let old_paths = updated_step3.storage_paths.clone(); - let updated = updated_step3.try_upgrade()?; + let updated_step4 = updated_step3.try_upgrade()?; v1_1_33::migrate_gateway_details( &old_paths.common_paths, - &updated.storage_paths.common_paths, + &updated_step4.storage_paths.common_paths, Some(gateway_config), ) .await?; + let updated: Config = updated_step4.into(); + updated.save_to(config_path)?; Ok(true) } -async fn try_upgrade_v1_1_20_config>( +async fn try_upgrade_v2_config>( config_path: P, ) -> Result { trace!("Trying to load as v1.1.20 config"); @@ -63,20 +67,22 @@ async fn try_upgrade_v1_1_20_config>( let updated_step1: ConfigV3 = old_config.into(); let (updated_step2, gateway_config) = updated_step1.upgrade()?; let old_paths = updated_step2.storage_paths.clone(); - let updated = updated_step2.try_upgrade()?; + let updated_step3 = updated_step2.try_upgrade()?; v1_1_33::migrate_gateway_details( &old_paths.common_paths, - &updated.storage_paths.common_paths, + &updated_step3.storage_paths.common_paths, Some(gateway_config), ) .await?; + let updated: Config = updated_step3.into(); + updated.save_to(config_path)?; Ok(true) } -async fn try_upgrade_v1_1_20_2_config>( +async fn try_upgrade_v3_config>( config_path: P, ) -> Result { trace!("Trying to load as v1.1.20_2 config"); @@ -92,26 +98,28 @@ async fn try_upgrade_v1_1_20_2_config>( let (updated_step1, gateway_config) = old_config.upgrade()?; let old_paths = updated_step1.storage_paths.clone(); - let updated = updated_step1.try_upgrade()?; + let updated_step2 = updated_step1.try_upgrade()?; v1_1_33::migrate_gateway_details( &old_paths.common_paths, - &updated.storage_paths.common_paths, + &updated_step2.storage_paths.common_paths, Some(gateway_config), ) .await?; + let updated: Config = updated_step2.into(); + updated.save_to(config_path)?; Ok(true) } -async fn try_upgrade_v1_1_33_config>( +async fn try_upgrade_v4_config>( config_path: P, ) -> Result { trace!("Trying to load as v1.1.33 config"); // explicitly load it as v1.1.33 (which is incompatible with the current one, i.e. +1.1.34) - let Ok(old_config) = ConfigV14::read_from_toml_file(config_path.as_ref()) else { + let Ok(old_config) = ConfigV4::read_from_toml_file(config_path.as_ref()) 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); @@ -120,33 +128,56 @@ async fn try_upgrade_v1_1_33_config>( 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()?; + let updated_step1 = old_config.try_upgrade()?; v1_1_33::migrate_gateway_details( &old_paths.common_paths, - &updated.storage_paths.common_paths, + &updated_step1.storage_paths.common_paths, None, ) .await?; + let updated: Config = updated_step1.into(); + updated.save_to(config_path)?; Ok(true) } +async fn try_upgrade_v5_config>( + config_path: P, +) -> Result { + // explicitly load it as v5 (which is incompatible with the current one) + let Ok(old_config) = ConfigV5::read_from_toml_file(config_path.as_ref()) 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 <= v5 config template."); + info!("It is going to get updated to the current specification."); + + let updated: Config = old_config.into(); + updated.save_to(config_path)?; + + Ok(true) +} + pub async fn try_upgrade_config>( config_path: P, ) -> Result<(), NetworkRequesterError> { trace!("Attempting to upgrade config"); - if try_upgrade_v1_1_13_config(config_path.as_ref()).await? { + if try_upgrade_v1_config(config_path.as_ref()).await? { return Ok(()); } - if try_upgrade_v1_1_20_config(config_path.as_ref()).await? { + if try_upgrade_v2_config(config_path.as_ref()).await? { return Ok(()); } - if try_upgrade_v1_1_20_2_config(config_path.as_ref()).await? { + if try_upgrade_v3_config(config_path.as_ref()).await? { return Ok(()); } - if try_upgrade_v1_1_33_config(config_path).await? { + if try_upgrade_v4_config(config_path.as_ref()).await? { + return Ok(()); + } + if try_upgrade_v5_config(config_path).await? { return Ok(()); } diff --git a/service-providers/network-requester/src/config/mod.rs b/service-providers/network-requester/src/config/mod.rs index e4d701c537..27b0d70739 100644 --- a/service-providers/network-requester/src/config/mod.rs +++ b/service-providers/network-requester/src/config/mod.rs @@ -245,12 +245,6 @@ pub struct NetworkRequester { /// This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true, pub disable_poisson_rate: bool, - /// Specifies whether this network requester should be using the deprecated allow-list, - /// as opposed to the new ExitPolicy. - /// Note: this field will be removed in a near future. - #[deprecated] - pub use_deprecated_allow_list: 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, @@ -263,7 +257,6 @@ impl Default for NetworkRequester { enabled_statistics: false, statistics_recipient: None, disable_poisson_rate: true, - use_deprecated_allow_list: true, upstream_exit_policy_url: Some( mainnet::EXIT_POLICY_URL .parse() diff --git a/service-providers/network-requester/src/config/old/mod.rs b/service-providers/network-requester/src/config/old/mod.rs index e19685b02c..3a529cd6c0 100644 --- a/service-providers/network-requester/src/config/old/mod.rs +++ b/service-providers/network-requester/src/config/old/mod.rs @@ -5,18 +5,4 @@ pub mod v1; pub mod v2; pub mod v3; pub mod v4; - -// // aliases for backwards compatibility -// pub use v1 as old_config_v1_1_13; -// pub use v2 as old_config_v1_1_20; -// pub use v3 as old_config_v1_1_20_2; -// pub use v4 as old_config_v1_1_30; -// pub use v5 as old_config_v1_1_33; - -/* - deleted: src/config/old_config_v1_1_13.rs - deleted: src/config/old_config_v1_1_19.rs - deleted: src/config/old_config_v1_1_20.rs - deleted: src/config/old_config_v1_1_20_2.rs - deleted: src/config/old_config_v1_1_33.rs -*/ +pub mod v5; diff --git a/service-providers/network-requester/src/config/old/v3.rs b/service-providers/network-requester/src/config/old/v3.rs index 37d7925fcf..aa86eb7819 100644 --- a/service-providers/network-requester/src/config/old/v3.rs +++ b/service-providers/network-requester/src/config/old/v3.rs @@ -1,10 +1,9 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use super::v4::{ConfigV14, DebugV4, NetworkRequesterV4}; +use super::v4::{ConfigV4, DebugV4, NetworkRequesterV4}; use crate::config::persistence::old::v1::NetworkRequesterPathsV1; -use crate::config::persistence::old::v2::NetworkRequesterPathsV2; -use crate::config::persistence::DEFAULT_DESCRIPTION_FILENAME; +use crate::config::persistence::old::v2::{NetworkRequesterPathsV2, DEFAULT_DESCRIPTION_FILENAME}; use crate::{config::default_config_filepath, error::NetworkRequesterError}; use log::trace; use nym_bin_common::logging::LoggingSettings; @@ -50,7 +49,7 @@ impl ConfigV3 { // so its returned to be stored elsewhere. pub fn upgrade( self, - ) -> Result<(ConfigV14, OldGatewayEndpointConfigV1_1_33), NetworkRequesterError> { + ) -> Result<(ConfigV4, OldGatewayEndpointConfigV1_1_33), NetworkRequesterError> { trace!("Upgrading from v1.1.20_2"); let gateway_details = self.base.client.gateway_endpoint.clone().into(); let nr_description = self @@ -61,7 +60,7 @@ impl ConfigV3 { .parent() .expect("config paths upgrade failure") .join(DEFAULT_DESCRIPTION_FILENAME); - let config = ConfigV14 { + let config = ConfigV4 { base: BaseConfigV1_1_30::from(self.base).into(), storage_paths: NetworkRequesterPathsV2 { common_paths: self.storage_paths.common_paths.upgrade_default()?, diff --git a/service-providers/network-requester/src/config/old/v4.rs b/service-providers/network-requester/src/config/old/v4.rs index 8e13c7d5a9..cf811825e6 100644 --- a/service-providers/network-requester/src/config/old/v4.rs +++ b/service-providers/network-requester/src/config/old/v4.rs @@ -1,10 +1,10 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::config::default_config_filepath; +use crate::config::old::v5::{ConfigV5, DebugV5, NetworkRequesterV5}; use crate::config::persistence::old::v2::NetworkRequesterPathsV2; -use crate::config::persistence::NetworkRequesterPaths; -use crate::config::Config; -use crate::config::{default_config_filepath, Debug, NetworkRequester}; +use crate::config::persistence::old::v3::NetworkRequesterPathsV3; use crate::error::NetworkRequesterError; use nym_bin_common::logging::LoggingSettings; use nym_client_core::config::old_config_v1_1_33::ConfigV1_1_33 as BaseConfigV1_1_33; @@ -20,7 +20,7 @@ pub const DEFAULT_STANDARD_LIST_UPDATE_INTERVAL: Duration = Duration::from_secs( #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] -pub struct ConfigV14 { +pub struct ConfigV4 { #[serde(flatten)] pub base: BaseConfigV1_1_33, @@ -35,7 +35,7 @@ pub struct ConfigV14 { pub logging: LoggingSettings, } -impl ConfigV14 { +impl ConfigV4 { pub fn read_from_toml_file>(path: P) -> io::Result { read_config_from_toml_file(path) } @@ -45,11 +45,11 @@ impl ConfigV14 { Self::read_from_toml_file(default_config_filepath(id)) } - pub fn try_upgrade(self) -> Result { - Ok(Config { + pub fn try_upgrade(self) -> Result { + Ok(ConfigV5 { base: self.base.into(), network_requester: self.network_requester.into(), - storage_paths: NetworkRequesterPaths { + storage_paths: NetworkRequesterPathsV3 { common_paths: self.storage_paths.common_paths.upgrade_default()?, allowed_list_location: self.storage_paths.allowed_list_location, unknown_list_location: self.storage_paths.unknown_list_location, @@ -88,9 +88,9 @@ pub struct NetworkRequesterV4 { pub upstream_exit_policy_url: Option, } -impl From for NetworkRequester { +impl From for NetworkRequesterV5 { fn from(value: NetworkRequesterV4) -> Self { - NetworkRequester { + NetworkRequesterV5 { open_proxy: value.open_proxy, enabled_statistics: value.enabled_statistics, statistics_recipient: value.statistics_recipient, @@ -109,9 +109,9 @@ pub struct DebugV4 { pub standard_list_update_interval: Duration, } -impl From for Debug { +impl From for DebugV5 { fn from(value: DebugV4) -> Self { - Debug { + DebugV5 { standard_list_update_interval: value.standard_list_update_interval, } } diff --git a/service-providers/network-requester/src/config/old/v5.rs b/service-providers/network-requester/src/config/old/v5.rs new file mode 100644 index 0000000000..46151eabad --- /dev/null +++ b/service-providers/network-requester/src/config/old/v5.rs @@ -0,0 +1,146 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::persistence::old::v3::NetworkRequesterPathsV3; +use crate::config::persistence::NetworkRequesterPaths; +use crate::config::Config; +use crate::config::{default_config_filepath, Debug, NetworkRequester}; +use nym_bin_common::logging::LoggingSettings; +use nym_client_core::config::Config as BaseClientConfig; +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; +use std::time::Duration; +use url::Url; + +pub const DEFAULT_STANDARD_LIST_UPDATE_INTERVAL: Duration = Duration::from_secs(30 * 60); + +#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct ConfigV5 { + // *sigh* currently we point to the most recent config because that's the one that's 'correct' + // but the moment we make breaking changes there, we'll have to update this config too. + // I think we should always keep versioned base config, i.e. `ConfigV1`, `ConfigV2`, etc, + // and then just make type alias for the current one, i.e. `type Config = ConfigV2`. + // then in 'old' configs we could simply use the underlying type as opposed to the alias for easier upgrades. + #[serde(flatten)] + pub base: BaseClientConfig, + + #[serde(default)] + pub network_requester: NetworkRequesterV5, + + pub storage_paths: NetworkRequesterPathsV3, + + #[serde(default)] + pub network_requester_debug: DebugV5, + + pub logging: LoggingSettings, +} + +impl ConfigV5 { + pub fn read_from_toml_file>(path: P) -> io::Result { + read_config_from_toml_file(path) + } + + #[allow(dead_code)] + pub fn read_from_default_path>(id: P) -> io::Result { + Self::read_from_toml_file(default_config_filepath(id)) + } +} + +impl From for Config { + fn from(value: ConfigV5) -> Self { + Config { + base: value.base, + network_requester: value.network_requester.into(), + storage_paths: NetworkRequesterPaths { + common_paths: value.storage_paths.common_paths, + }, + network_requester_debug: value.network_requester_debug.into(), + logging: value.logging, + } + } +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct NetworkRequesterV5 { + /// specifies whether this network requester should run in 'open-proxy' mode + /// and thus would attempt to resolve **ANY** request it receives. + pub open_proxy: bool, + + /// specifies whether this network requester would send anonymized statistics to a statistics aggregator server + pub enabled_statistics: bool, + + /// in case of enabled statistics, specifies mixnet client address where a statistics aggregator is running + pub statistics_recipient: Option, + + /// Disable Poisson sending rate. + /// This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true, + pub disable_poisson_rate: bool, + + /// Specifies whether this network requester should be using the deprecated allow-list, + /// as opposed to the new ExitPolicy. + pub use_deprecated_allow_list: 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 NetworkRequesterV5 { + fn default() -> Self { + NetworkRequesterV5 { + open_proxy: false, + enabled_statistics: false, + statistics_recipient: None, + disable_poisson_rate: true, + use_deprecated_allow_list: true, + upstream_exit_policy_url: Some( + mainnet::EXIT_POLICY_URL + .parse() + .expect("invalid default exit policy URL"), + ), + } + } +} + +impl From for NetworkRequester { + fn from(value: NetworkRequesterV5) -> Self { + NetworkRequester { + open_proxy: value.open_proxy, + enabled_statistics: value.enabled_statistics, + statistics_recipient: value.statistics_recipient, + disable_poisson_rate: value.disable_poisson_rate, + upstream_exit_policy_url: value.upstream_exit_policy_url, + } + } +} + +#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct DebugV5 { + /// Defines how often the standard allow list should get updated + /// Deprecated + #[serde(with = "humantime_serde")] + pub standard_list_update_interval: Duration, +} + +impl From for Debug { + fn from(value: DebugV5) -> Self { + Debug { + standard_list_update_interval: value.standard_list_update_interval, + } + } +} + +impl Default for DebugV5 { + fn default() -> Self { + DebugV5 { + standard_list_update_interval: DEFAULT_STANDARD_LIST_UPDATE_INTERVAL, + } + } +} diff --git a/service-providers/network-requester/src/config/persistence/mod.rs b/service-providers/network-requester/src/config/persistence/mod.rs index e4f6384117..42a23f8de7 100644 --- a/service-providers/network-requester/src/config/persistence/mod.rs +++ b/service-providers/network-requester/src/config/persistence/mod.rs @@ -3,31 +3,14 @@ use nym_client_core::config::disk_persistence::CommonClientPaths; use serde::{Deserialize, Serialize}; -use std::path::{Path, PathBuf}; +use std::path::Path; pub mod old; -pub const DEFAULT_ALLOWED_LIST_FILENAME: &str = "allowed.list"; -pub const DEFAULT_UNKNOWN_LIST_FILENAME: &str = "unknown.list"; -pub const DEFAULT_DESCRIPTION_FILENAME: &str = "description.toml"; - #[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)] pub struct NetworkRequesterPaths { #[serde(flatten)] pub common_paths: CommonClientPaths, - - /// Deprecated - /// Location of the file containing our allow.list - #[deprecated] - pub allowed_list_location: PathBuf, - - /// Deprecated - /// Location of the file containing our unknown.list - #[deprecated] - pub unknown_list_location: PathBuf, - - /// Location of the file containing our description - pub nr_description: PathBuf, } impl NetworkRequesterPaths { @@ -36,9 +19,6 @@ impl NetworkRequesterPaths { NetworkRequesterPaths { common_paths: CommonClientPaths::new_base(base_dir), - allowed_list_location: base_dir.join(DEFAULT_ALLOWED_LIST_FILENAME), - unknown_list_location: base_dir.join(DEFAULT_UNKNOWN_LIST_FILENAME), - nr_description: base_dir.join(DEFAULT_DESCRIPTION_FILENAME), } } } diff --git a/service-providers/network-requester/src/config/persistence/old/mod.rs b/service-providers/network-requester/src/config/persistence/old/mod.rs index 03a73cb2a8..e9f7e5fdba 100644 --- a/service-providers/network-requester/src/config/persistence/old/mod.rs +++ b/service-providers/network-requester/src/config/persistence/old/mod.rs @@ -3,3 +3,4 @@ pub mod v1; pub mod v2; +pub mod v3; diff --git a/service-providers/network-requester/src/config/persistence/old/v2.rs b/service-providers/network-requester/src/config/persistence/old/v2.rs index 927368e99c..a22158c8f9 100644 --- a/service-providers/network-requester/src/config/persistence/old/v2.rs +++ b/service-providers/network-requester/src/config/persistence/old/v2.rs @@ -4,6 +4,7 @@ use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33; use serde::{Deserialize, Serialize}; use std::path::PathBuf; +pub const DEFAULT_DESCRIPTION_FILENAME: &str = "description.toml"; #[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)] pub struct NetworkRequesterPathsV2 { diff --git a/service-providers/network-requester/src/config/persistence/old/v3.rs b/service-providers/network-requester/src/config/persistence/old/v3.rs new file mode 100644 index 0000000000..a5a8f3855f --- /dev/null +++ b/service-providers/network-requester/src/config/persistence/old/v3.rs @@ -0,0 +1,21 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use nym_client_core::config::disk_persistence::CommonClientPaths; +use serde::{Deserialize, Serialize}; +use std::path::PathBuf; + +#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)] +pub struct NetworkRequesterPathsV3 { + #[serde(flatten)] + pub common_paths: CommonClientPaths, + + /// Location of the file containing our allow.list + pub allowed_list_location: PathBuf, + + /// Location of the file containing our unknown.list + pub unknown_list_location: PathBuf, + + /// Location of the file containing our description + pub nr_description: PathBuf, +}