From d180f7063c030735883426af2550ef0c736d75bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Oct 2023 22:51:15 +0000 Subject: [PATCH 001/236] build(deps): bump golang.org/x/net in /wasm/mix-fetch/go-mix-conn Bumps [golang.org/x/net](https://github.com/golang/net) from 0.11.0 to 0.17.0. - [Commits](https://github.com/golang/net/compare/v0.11.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- wasm/mix-fetch/go-mix-conn/go.mod | 4 ++-- wasm/mix-fetch/go-mix-conn/go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/wasm/mix-fetch/go-mix-conn/go.mod b/wasm/mix-fetch/go-mix-conn/go.mod index ff161559bb..7a9bbe7814 100644 --- a/wasm/mix-fetch/go-mix-conn/go.mod +++ b/wasm/mix-fetch/go-mix-conn/go.mod @@ -2,6 +2,6 @@ module go-mix-conn go 1.20 -require golang.org/x/net v0.11.0 +require golang.org/x/net v0.17.0 -require golang.org/x/text v0.10.0 // indirect +require golang.org/x/text v0.13.0 // indirect diff --git a/wasm/mix-fetch/go-mix-conn/go.sum b/wasm/mix-fetch/go-mix-conn/go.sum index 6ea647559f..66be8d971e 100644 --- a/wasm/mix-fetch/go-mix-conn/go.sum +++ b/wasm/mix-fetch/go-mix-conn/go.sum @@ -1,4 +1,4 @@ -golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= -golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= -golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= From 0a7826d286db0500f6fb14bdea01567c002d6494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 13 Oct 2023 10:57:58 +0100 Subject: [PATCH 002/236] allow setting custom bind address for socks5 client --- clients/socks5/src/commands/init.rs | 16 ++- clients/socks5/src/commands/mod.rs | 46 ++++++-- clients/socks5/src/commands/run.rs | 6 + clients/socks5/src/config/mod.rs | 13 ++- .../socks5/src/config/old_config_v1_1_20_2.rs | 8 +- .../socks5/src/config/old_config_v1_1_30.rs | 44 ++++++++ common/socks5-client-core/src/config/mod.rs | 21 +++- .../src/config/old_config_v1_1_20_2.rs | 21 ++-- .../src/config/old_config_v1_1_30.rs | 106 ++++++++++++++++++ common/socks5-client-core/src/lib.rs | 2 +- common/socks5-client-core/src/socks/server.rs | 9 +- sdk/rust/nym-sdk/src/mixnet/socks5_client.rs | 2 +- 12 files changed, 251 insertions(+), 43 deletions(-) create mode 100644 clients/socks5/src/config/old_config_v1_1_30.rs create mode 100644 common/socks5-client-core/src/config/old_config_v1_1_30.rs diff --git a/clients/socks5/src/commands/init.rs b/clients/socks5/src/commands/init.rs index 8adc4e891b..3c6a2a943f 100644 --- a/clients/socks5/src/commands/init.rs +++ b/clients/socks5/src/commands/init.rs @@ -22,6 +22,7 @@ use nym_sphinx::addressing::clients::Recipient; use nym_topology::NymTopology; use serde::Serialize; use std::fmt::Display; +use std::net::{IpAddr, SocketAddr}; use std::path::PathBuf; use std::{fs, io}; use tap::TapFallible; @@ -77,6 +78,10 @@ pub(crate) struct Init { #[clap(short, long)] port: Option, + /// The custom host on which the socks5 client will be listening for requests + #[clap(long)] + host: Option, + /// Path to .json file containing custom network specification. #[clap(long, group = "network", hide = true)] custom_mixnet: Option, @@ -103,6 +108,7 @@ impl From for OverrideConfig { fn from(init_config: Init) -> Self { OverrideConfig { nym_apis: init_config.nym_apis, + ip: init_config.host, port: init_config.port, use_anonymous_replies: init_config.use_reply_surbs, fastmode: init_config.fastmode, @@ -120,7 +126,7 @@ impl From for OverrideConfig { pub struct InitResults { #[serde(flatten)] client_core: nym_client_core::init::types::InitResults, - socks5_listening_port: u16, + socks5_listening_address: SocketAddr, client_address: String, } @@ -132,7 +138,7 @@ impl InitResults { address, gateway, ), - socks5_listening_port: config.core.socks5.listening_port, + socks5_listening_address: config.core.socks5.bind_adddress, client_address: address.to_string(), } } @@ -141,7 +147,11 @@ impl InitResults { impl Display for InitResults { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "{}", self.client_core)?; - writeln!(f, "SOCKS5 listening port: {}", self.socks5_listening_port)?; + writeln!( + f, + "SOCKS5 listening address: {}", + self.socks5_listening_address + )?; write!(f, "Address of this client: {}", self.client_address) } } diff --git a/clients/socks5/src/commands/mod.rs b/clients/socks5/src/commands/mod.rs index 1f42cdc905..eeef6559b4 100644 --- a/clients/socks5/src/commands/mod.rs +++ b/clients/socks5/src/commands/mod.rs @@ -4,7 +4,8 @@ use crate::config::old_config_v1_1_13::OldConfigV1_1_13; use crate::config::old_config_v1_1_20::ConfigV1_1_20; use crate::config::old_config_v1_1_20_2::ConfigV1_1_20_2; -use crate::config::{BaseClientConfig, Config}; +use crate::config::old_config_v1_1_30::ConfigV1_1_30; +use crate::config::{BaseClientConfig, Config, SocksClientPaths}; use crate::error::Socks5ClientError; use clap::CommandFactory; use clap::{Parser, Subcommand}; @@ -22,6 +23,7 @@ use nym_client_core::error::ClientCoreError; use nym_config::OptionalSet; use nym_sphinx::params::{PacketSize, PacketType}; use std::error::Error; +use std::net::IpAddr; pub(crate) mod build_info; pub mod init; @@ -72,6 +74,7 @@ pub(crate) enum Commands { // Configuration that can be overridden. pub(crate) struct OverrideConfig { nym_apis: Option>, + ip: Option, port: Option, use_anonymous_replies: Option, fastmode: bool, @@ -145,6 +148,7 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config { ) .with_optional(Config::with_anonymous_replies, args.use_anonymous_replies) .with_optional(Config::with_port, args.port) + .with_optional(Config::with_ip, args.ip) .with_optional_base_custom_env( BaseClientConfig::with_custom_nym_apis, args.nym_apis, @@ -164,12 +168,11 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config { } fn persist_gateway_details( - config: &Config, + storage_paths: &SocksClientPaths, details: GatewayEndpointConfig, ) -> Result<(), Socks5ClientError> { - 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 details_store = OnDiskGatewayDetails::new(&storage_paths.common_paths.gateway_details); + let keys_store = OnDiskKeys::new(storage_paths.common_paths.keys.clone()); let shared_keys = keys_store.ephemeral_load_gateway_keys().map_err(|source| { Socks5ClientError::ClientCoreError(ClientCoreError::KeyStoreError { source: Box::new(source), @@ -199,9 +202,10 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result { let updated_step1: ConfigV1_1_20 = old_config.into(); let updated_step2: ConfigV1_1_20_2 = updated_step1.into(); - let (updated, gateway_config) = updated_step2.upgrade()?; - persist_gateway_details(&updated, gateway_config)?; + let (updated_step3, gateway_config) = updated_step2.upgrade()?; + persist_gateway_details(&updated_step3.storage_paths, gateway_config)?; + let updated: Config = updated_step3.into(); updated.save_to_default_location()?; Ok(true) } @@ -219,9 +223,10 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result { info!("It is going to get updated to the current specification."); let updated_step1: ConfigV1_1_20_2 = old_config.into(); - let (updated, gateway_config) = updated_step1.upgrade()?; - persist_gateway_details(&updated, gateway_config)?; + let (updated_step2, gateway_config) = updated_step1.upgrade()?; + persist_gateway_details(&updated_step2.storage_paths, gateway_config)?; + let updated: Config = updated_step2.into(); updated.save_to_default_location()?; Ok(true) } @@ -236,9 +241,25 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result { info!("It seems the client is using <= v1.1.20_2 config template."); info!("It is going to get updated to the current specification."); - let (updated, gateway_config) = old_config.upgrade()?; - persist_gateway_details(&updated, gateway_config)?; + let (updated_step1, gateway_config) = old_config.upgrade()?; + persist_gateway_details(&updated_step1.storage_paths, gateway_config)?; + let updated: Config = updated_step1.into(); + updated.save_to_default_location()?; + Ok(true) +} + +fn try_upgrade_v1_1_30_config(id: &str) -> Result { + // explicitly load it as v1.1.20_2 (which is incompatible with the current one, i.e. +1.1.21) + let Ok(old_config) = ConfigV1_1_30::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.1.30 config template."); + info!("It is going to get updated to the current specification."); + + let updated: Config = old_config.into(); updated.save_to_default_location()?; Ok(true) } @@ -253,6 +274,9 @@ fn try_upgrade_config(id: &str) -> Result<(), Socks5ClientError> { if try_upgrade_v1_1_20_2_config(id)? { return Ok(()); } + if try_upgrade_v1_1_30_config(id)? { + return Ok(()); + } Ok(()) } diff --git a/clients/socks5/src/commands/run.rs b/clients/socks5/src/commands/run.rs index 46bd9cd361..51efa4fdb6 100644 --- a/clients/socks5/src/commands/run.rs +++ b/clients/socks5/src/commands/run.rs @@ -1,6 +1,7 @@ // Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use std::net::IpAddr; use crate::commands::try_load_current_config; use crate::config::Config; use crate::{ @@ -53,6 +54,10 @@ pub(crate) struct Run { #[clap(short, long)] port: Option, + /// The custom host on which the socks5 client will be listening for requests + #[clap(long)] + host: Option, + /// Path to .json file containing custom network specification. #[clap(long, group = "network", group = "routing", hide = true)] custom_mixnet: Option, @@ -88,6 +93,7 @@ impl From for OverrideConfig { fn from(run_config: Run) -> Self { OverrideConfig { nym_apis: run_config.nym_apis, + ip: run_config.host, port: run_config.port, use_anonymous_replies: run_config.use_anonymous_replies, fastmode: run_config.fastmode, diff --git a/clients/socks5/src/config/mod.rs b/clients/socks5/src/config/mod.rs index 6f9c0c7fa4..8a8681c50f 100644 --- a/clients/socks5/src/config/mod.rs +++ b/clients/socks5/src/config/mod.rs @@ -1,7 +1,6 @@ // Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::persistence::SocksClientPaths; use crate::config::template::CONFIG_TEMPLATE; use nym_bin_common::logging::LoggingSettings; use nym_config::{ @@ -11,15 +10,18 @@ use nym_config::{ use serde::{Deserialize, Serialize}; use std::fmt::Debug; use std::io; +use std::net::IpAddr; use std::path::{Path, PathBuf}; use std::str::FromStr; +pub use crate::config::persistence::SocksClientPaths; pub use nym_client_core::config::Config as BaseClientConfig; pub use nym_socks5_client_core::config::Config as CoreConfig; pub mod old_config_v1_1_13; pub mod old_config_v1_1_20; pub mod old_config_v1_1_20_2; +pub mod old_config_v1_1_30; mod persistence; mod template; @@ -102,8 +104,15 @@ impl Config { self.core.validate() } + #[must_use] pub fn with_port(mut self, port: u16) -> Self { - self.core.socks5.listening_port = port; + self.core = self.core.with_port(port); + self + } + + #[must_use] + pub fn with_ip(mut self, ip: IpAddr) -> Self { + self.core = self.core.with_ip(ip); self } diff --git a/clients/socks5/src/config/old_config_v1_1_20_2.rs b/clients/socks5/src/config/old_config_v1_1_20_2.rs index 998bd90b32..4668e3ea9d 100644 --- a/clients/socks5/src/config/old_config_v1_1_20_2.rs +++ b/clients/socks5/src/config/old_config_v1_1_20_2.rs @@ -1,11 +1,11 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::config::old_config_v1_1_30::ConfigV1_1_30; use crate::{ - config::{default_config_filepath, persistence::SocksClientPaths, Config}, + config::{default_config_filepath, persistence::SocksClientPaths}, error::Socks5ClientError, }; - use nym_bin_common::logging::LoggingSettings; use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2; use nym_client_core::config::GatewayEndpointConfig; @@ -43,9 +43,9 @@ impl ConfigV1_1_20_2 { // in this upgrade, gateway endpoint configuration was moved out of the config file, // so its returned to be stored elsewhere. - pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig), Socks5ClientError> { + pub fn upgrade(self) -> Result<(ConfigV1_1_30, GatewayEndpointConfig), Socks5ClientError> { let gateway_details = self.core.base.client.gateway_endpoint.clone().into(); - let config = Config { + let config = ConfigV1_1_30 { core: self.core.into(), storage_paths: SocksClientPaths { common_paths: self.storage_paths.common_paths.upgrade_default()?, diff --git a/clients/socks5/src/config/old_config_v1_1_30.rs b/clients/socks5/src/config/old_config_v1_1_30.rs new file mode 100644 index 0000000000..cd7a5ab9e4 --- /dev/null +++ b/clients/socks5/src/config/old_config_v1_1_30.rs @@ -0,0 +1,44 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::persistence::SocksClientPaths; +use crate::config::{default_config_filepath, Config}; +use nym_bin_common::logging::LoggingSettings; +use nym_config::read_config_from_toml_file; +use nym_socks5_client_core::config::old_config_v1_1_30::ConfigV1_1_30 as CoreConfigV1_1_30; +use serde::{Deserialize, Serialize}; +use std::io; +use std::path::Path; + +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct ConfigV1_1_30 { + pub core: CoreConfigV1_1_30, + + // I'm leaving a landmine here for when the paths actually do change the next time, + // but propagating the change right now (in ALL clients) would be such a hassle..., + // so sorry for the next person looking at it : ) + pub storage_paths: SocksClientPaths, + + pub logging: LoggingSettings, +} + +impl From for Config { + fn from(value: ConfigV1_1_30) -> Self { + Config { + core: value.core.into(), + storage_paths: value.storage_paths, + logging: LoggingSettings::default(), + } + } +} + +impl ConfigV1_1_30 { + 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)) + } +} diff --git a/common/socks5-client-core/src/config/mod.rs b/common/socks5-client-core/src/config/mod.rs index a560645140..8c5c722093 100644 --- a/common/socks5-client-core/src/config/mod.rs +++ b/common/socks5-client-core/src/config/mod.rs @@ -7,9 +7,11 @@ use nym_config::OptionalSet; use nym_sphinx::addressing::clients::Recipient; use serde::{Deserialize, Serialize}; use std::fmt::Debug; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::str::FromStr; pub mod old_config_v1_1_20_2; +pub mod old_config_v1_1_30; pub use nym_service_providers_common::interface::ProviderInterfaceVersion; pub use nym_socks5_requests::Socks5ProtocolVersion; @@ -43,8 +45,15 @@ impl Config { self.base.validate() } + #[must_use] pub fn with_port(mut self, port: u16) -> Self { - self.socks5.listening_port = port; + self.socks5.bind_adddress = SocketAddr::new(self.socks5.bind_adddress.ip(), port); + self + } + + #[must_use] + pub fn with_ip(mut self, ip: IpAddr) -> Self { + self.socks5.bind_adddress = SocketAddr::new(ip, self.socks5.bind_adddress.port()); self } @@ -101,8 +110,9 @@ impl Config { #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] pub struct Socks5 { - /// The port on which the client will be listening for incoming requests - pub listening_port: u16, + /// The address on which the client will be listening for incoming requests + /// (default: 127.0.0.1:1080) + pub bind_adddress: SocketAddr, /// The mix address of the provider to which all requests are going to be sent. pub provider_mix_address: String, @@ -131,7 +141,10 @@ pub struct Socks5 { impl Socks5 { pub fn new>(provider_mix_address: S) -> Self { Socks5 { - listening_port: DEFAULT_SOCKS5_LISTENING_PORT, + bind_adddress: SocketAddr::new( + IpAddr::V4(Ipv4Addr::LOCALHOST), + DEFAULT_SOCKS5_LISTENING_PORT, + ), provider_mix_address: provider_mix_address.into(), provider_interface_version: ProviderInterfaceVersion::Legacy, socks5_protocol_version: Socks5ProtocolVersion::Legacy, diff --git a/common/socks5-client-core/src/config/old_config_v1_1_20_2.rs b/common/socks5-client-core/src/config/old_config_v1_1_20_2.rs index 2269a0fa01..dc24de4131 100644 --- a/common/socks5-client-core/src/config/old_config_v1_1_20_2.rs +++ b/common/socks5-client-core/src/config/old_config_v1_1_20_2.rs @@ -1,13 +1,12 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use super::old_config_v1_1_30::{ConfigV1_1_30, Socks5DebugV1_1_30, Socks5V1_1_30}; pub use nym_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as BaseClientConfigV1_1_20_2; -use serde::{Deserialize, Serialize}; -use std::fmt::Debug; - -use crate::config::{Config, Socks5, Socks5Debug}; pub use nym_service_providers_common::interface::ProviderInterfaceVersion; pub use nym_socks5_requests::Socks5ProtocolVersion; +use serde::{Deserialize, Serialize}; +use std::fmt::Debug; const DEFAULT_CONNECTION_START_SURBS: u32 = 20; const DEFAULT_PER_REQUEST_SURBS: u32 = 3; @@ -21,10 +20,10 @@ pub struct ConfigV1_1_20_2 { pub socks5: Socks5V1_1_20_2, } -impl From for Config { +impl From for ConfigV1_1_30 { fn from(value: ConfigV1_1_20_2) -> Self { - Config { - base: value.base.into(), + ConfigV1_1_30 { + base: value.base, socks5: value.socks5.into(), } } @@ -45,9 +44,9 @@ pub struct Socks5V1_1_20_2 { pub socks5_debug: Socks5DebugV1_1_20_2, } -impl From for Socks5 { +impl From for Socks5V1_1_30 { fn from(value: Socks5V1_1_20_2) -> Self { - Socks5 { + Socks5V1_1_30 { listening_port: value.listening_port, provider_mix_address: value.provider_mix_address, provider_interface_version: value.provider_interface_version, @@ -68,9 +67,9 @@ pub struct Socks5DebugV1_1_20_2 { pub per_request_surbs: u32, } -impl From for Socks5Debug { +impl From for Socks5DebugV1_1_30 { fn from(value: Socks5DebugV1_1_20_2) -> Self { - Socks5Debug { + Socks5DebugV1_1_30 { connection_start_surbs: value.connection_start_surbs, per_request_surbs: value.per_request_surbs, } diff --git a/common/socks5-client-core/src/config/old_config_v1_1_30.rs b/common/socks5-client-core/src/config/old_config_v1_1_30.rs new file mode 100644 index 0000000000..e84eb7011b --- /dev/null +++ b/common/socks5-client-core/src/config/old_config_v1_1_30.rs @@ -0,0 +1,106 @@ +// Copyright 2021-2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use super::old_config_v1_1_20_2::BaseClientConfigV1_1_20_2; +use super::{Config, Socks5, Socks5Debug}; +use serde::{Deserialize, Serialize}; +use std::fmt::Debug; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + +// TODO: those should really be redefined here in case we change them... +use nym_service_providers_common::interface::ProviderInterfaceVersion; +use nym_socks5_requests::Socks5ProtocolVersion; + +const DEFAULT_CONNECTION_START_SURBS: u32 = 20; +const DEFAULT_PER_REQUEST_SURBS: u32 = 3; + +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct ConfigV1_1_30 { + #[serde(flatten)] + // base client config hasn't changed between v1.1.20 and v1.1.30 + pub base: BaseClientConfigV1_1_20_2, + + pub socks5: Socks5V1_1_30, +} + +impl From for Config { + fn from(value: ConfigV1_1_30) -> Self { + Config { + base: value.base.into(), + socks5: value.socks5.into(), + } + } +} + +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct Socks5V1_1_30 { + /// The port on which the client will be listening for incoming requests + pub listening_port: u16, + + /// The mix address of the provider to which all requests are going to be sent. + pub provider_mix_address: String, + + /// The version of the 'service provider' this client is going to use in its communication with the + /// specified socks5 provider. + // if in doubt, use the legacy version as initially nobody will be using the updated binaries + #[serde(default)] + pub provider_interface_version: ProviderInterfaceVersion, + + #[serde(default)] + pub socks5_protocol_version: Socks5ProtocolVersion, + + /// Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. + /// While this is going to hide its actual address information, it will make the actual communication + /// slower and consume nearly double the bandwidth as it will require sending reply SURBs. + /// + /// Note that some service providers might not support this. + #[serde(default)] + pub send_anonymously: bool, + + #[serde(default)] + pub socks5_debug: Socks5DebugV1_1_30, +} + +impl From for Socks5 { + fn from(value: Socks5V1_1_30) -> Self { + Socks5 { + // in <= 1.1.30 the address was hardcoded to 127.0.0.1 + bind_adddress: SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), value.listening_port), + provider_mix_address: value.provider_mix_address, + provider_interface_version: value.provider_interface_version, + socks5_protocol_version: value.socks5_protocol_version, + send_anonymously: value.send_anonymously, + socks5_debug: value.socks5_debug.into(), + } + } +} + +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct Socks5DebugV1_1_30 { + /// Number of reply SURBs attached to each `Request::Connect` message. + pub connection_start_surbs: u32, + + /// Number of reply SURBs attached to each `Request::Send` message. + pub per_request_surbs: u32, +} + +impl From for Socks5Debug { + fn from(value: Socks5DebugV1_1_30) -> Self { + Socks5Debug { + connection_start_surbs: value.connection_start_surbs, + per_request_surbs: value.per_request_surbs, + } + } +} + +impl Default for Socks5DebugV1_1_30 { + fn default() -> Self { + Socks5DebugV1_1_30 { + connection_start_surbs: DEFAULT_CONNECTION_START_SURBS, + per_request_surbs: DEFAULT_PER_REQUEST_SURBS, + } + } +} diff --git a/common/socks5-client-core/src/lib.rs b/common/socks5-client-core/src/lib.rs index bbf9b7ed72..44747c8753 100644 --- a/common/socks5-client-core/src/lib.rs +++ b/common/socks5-client-core/src/lib.rs @@ -123,7 +123,7 @@ where let authenticator = Authenticator::new(auth_methods, allowed_users); let mut sphinx_socks = NymSocksServer::new( - socks5_config.listening_port, + socks5_config.bind_adddress, authenticator, socks5_config.get_provider_mix_address(), self_address, diff --git a/common/socks5-client-core/src/socks/server.rs b/common/socks5-client-core/src/socks/server.rs index 1fd5703113..a67ed64e19 100644 --- a/common/socks5-client-core/src/socks/server.rs +++ b/common/socks5-client-core/src/socks/server.rs @@ -33,7 +33,7 @@ impl NymSocksServer { /// Create a new SphinxSocks instance #[allow(clippy::too_many_arguments)] pub(crate) fn new( - port: u16, + bind_adddress: SocketAddr, authenticator: Authenticator, service_provider: Recipient, self_address: Recipient, @@ -42,13 +42,10 @@ impl NymSocksServer { shutdown: TaskClient, packet_type: PacketType, ) -> Self { - // hardcode ip as we (presumably) ONLY want to listen locally. If we change it, we can - // just modify the config - let ip = "127.0.0.1"; - info!("Listening on {}:{}", ip, port); + info!("Listening on {bind_adddress}"); NymSocksServer { authenticator, - listening_address: format!("{ip}:{port}").parse().unwrap(), + listening_address: bind_adddress, service_provider, self_address, client_config, diff --git a/sdk/rust/nym-sdk/src/mixnet/socks5_client.rs b/sdk/rust/nym-sdk/src/mixnet/socks5_client.rs index 776fd8b9b3..ab340447f9 100644 --- a/sdk/rust/nym-sdk/src/mixnet/socks5_client.rs +++ b/sdk/rust/nym-sdk/src/mixnet/socks5_client.rs @@ -56,7 +56,7 @@ impl Socks5MixnetClient { /// Get the SOCKS5 proxy URL that a HTTP(S) client can connect to. pub fn socks5_url(&self) -> String { - format!("socks5h://127.0.0.1:{}", self.socks5_config.listening_port) + format!("socks5h://{}", self.socks5_config.bind_adddress) } /// Get a shallow clone of [`LaneQueueLengths`]. This is useful to manually implement some form From 0f38f35aba67fa334f2550bebce242e6f9ba81a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 13 Oct 2023 10:58:50 +0100 Subject: [PATCH 003/236] updated client config template --- clients/socks5/src/config/template.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clients/socks5/src/config/template.rs b/clients/socks5/src/config/template.rs index 22d047bb16..764a7c6884 100644 --- a/clients/socks5/src/config/template.rs +++ b/clients/socks5/src/config/template.rs @@ -75,8 +75,9 @@ gateway_details = '{{ storage_paths.gateway_details }}' # The mix address of the provider to which all requests are going to be sent. provider_mix_address = '{{ core.socks5.provider_mix_address }}' -# The port on which the client will be listening for incoming requests -listening_port = {{ core.socks5.listening_port }} +# The address on which the client will be listening for incoming requests +# (default: 127.0.0.1:1080) +bind_adddress = '{{ core.socks5.bind_adddress }}' # Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. # While this is going to hide its actual address information, it will make the actual communication From 85938113b7d070cf6518155097c7b922fee16487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 13 Oct 2023 11:02:15 +0100 Subject: [PATCH 004/236] cargo fmt --- clients/socks5/src/commands/run.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/socks5/src/commands/run.rs b/clients/socks5/src/commands/run.rs index 51efa4fdb6..8be21ef808 100644 --- a/clients/socks5/src/commands/run.rs +++ b/clients/socks5/src/commands/run.rs @@ -1,7 +1,6 @@ // Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use std::net::IpAddr; use crate::commands::try_load_current_config; use crate::config::Config; use crate::{ @@ -16,6 +15,7 @@ use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup; use nym_crypto::asymmetric::identity; use nym_socks5_client_core::NymClient; use nym_sphinx::addressing::clients::Recipient; +use std::net::IpAddr; use std::path::PathBuf; #[derive(Args, Clone)] From 078365c467d3bbea4b51a6451d84c6cc4715e90d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 13 Oct 2023 11:07:30 +0100 Subject: [PATCH 005/236] nym connect fix --- nym-connect/desktop/src-tauri/src/config/mod.rs | 2 +- .../desktop/src-tauri/src/config/old_config_v1_1_20_2.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/nym-connect/desktop/src-tauri/src/config/mod.rs b/nym-connect/desktop/src-tauri/src/config/mod.rs index 0b8d9b0789..c62e48ce26 100644 --- a/nym-connect/desktop/src-tauri/src/config/mod.rs +++ b/nym-connect/desktop/src-tauri/src/config/mod.rs @@ -254,7 +254,7 @@ fn print_saved_config(config: &Config, gateway_details: &GatewayEndpointConfig) ); log::info!( "Service provider port: {}", - config.core.socks5.listening_port + config.core.socks5.bind_adddress.port() ); log::info!("Client configuration completed."); } diff --git a/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_20_2.rs b/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_20_2.rs index 0a2f017a75..f4effd9e23 100644 --- a/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_20_2.rs +++ b/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_20_2.rs @@ -9,6 +9,7 @@ use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV use nym_client_core::config::GatewayEndpointConfig; use nym_config::read_config_from_toml_file; pub use nym_socks5_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as CoreConfigV1_1_20_2; +pub use nym_socks5_client_core::config::old_config_v1_1_30::ConfigV1_1_30 as CoreConfigV1_1_30; use serde::{Deserialize, Serialize}; use std::io; use std::path::Path; @@ -43,7 +44,7 @@ impl ConfigV1_1_20_2 { pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig)> { let gateway_details = self.core.base.client.gateway_endpoint.clone().into(); let config = Config { - core: self.core.into(), + core: CoreConfigV1_1_30::from(self.core).into(), storage_paths: NymConnectPaths { common_paths: self.storage_paths.common_paths.upgrade_default()?, }, From 855ae2fe783901e1fb68e34c9b3426b90121a5c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 17 Oct 2023 11:50:08 +0100 Subject: [PATCH 006/236] nym-connect config upgrades --- .../desktop/src-tauri/src/config/mod.rs | 1 + .../src/config/old_config_v1_1_20_2.rs | 13 +++--- .../src/config/old_config_v1_1_30.rs | 40 +++++++++++++++++ .../desktop/src-tauri/src/config/upgrade.rs | 45 ++++++++++++++----- 4 files changed, 83 insertions(+), 16 deletions(-) create mode 100644 nym-connect/desktop/src-tauri/src/config/old_config_v1_1_30.rs diff --git a/nym-connect/desktop/src-tauri/src/config/mod.rs b/nym-connect/desktop/src-tauri/src/config/mod.rs index c62e48ce26..3426cf36b2 100644 --- a/nym-connect/desktop/src-tauri/src/config/mod.rs +++ b/nym-connect/desktop/src-tauri/src/config/mod.rs @@ -25,6 +25,7 @@ use tap::TapFallible; mod old_config_v1_1_13; mod old_config_v1_1_20; mod old_config_v1_1_20_2; +mod old_config_v1_1_30; mod persistence; mod template; mod upgrade; diff --git a/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_20_2.rs b/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_20_2.rs index f4effd9e23..d87f41ae0f 100644 --- a/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_20_2.rs +++ b/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_20_2.rs @@ -1,19 +1,20 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::config::default_config_filepath; +use crate::config::old_config_v1_1_30::ConfigV1_1_30; use crate::config::persistence::NymConnectPaths; -use crate::config::{default_config_filepath, Config}; use crate::error::Result; use nym_bin_common::logging::LoggingSettings; use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2; use nym_client_core::config::GatewayEndpointConfig; use nym_config::read_config_from_toml_file; -pub use nym_socks5_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as CoreConfigV1_1_20_2; -pub use nym_socks5_client_core::config::old_config_v1_1_30::ConfigV1_1_30 as CoreConfigV1_1_30; use serde::{Deserialize, Serialize}; use std::io; use std::path::Path; +pub use nym_socks5_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as CoreConfigV1_1_20_2; + #[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)] pub struct SocksClientPathsV1_1_20_2 { #[serde(flatten)] @@ -41,10 +42,10 @@ impl ConfigV1_1_20_2 { // in this upgrade, gateway endpoint configuration was moved out of the config file, // so its returned to be stored elsewhere. - pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig)> { + pub fn upgrade(self) -> Result<(ConfigV1_1_30, GatewayEndpointConfig)> { let gateway_details = self.core.base.client.gateway_endpoint.clone().into(); - let config = Config { - core: CoreConfigV1_1_30::from(self.core).into(), + let config = ConfigV1_1_30 { + core: self.core.into(), storage_paths: NymConnectPaths { common_paths: self.storage_paths.common_paths.upgrade_default()?, }, diff --git a/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_30.rs b/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_30.rs new file mode 100644 index 0000000000..a18ae5831c --- /dev/null +++ b/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_30.rs @@ -0,0 +1,40 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::persistence::NymConnectPaths; +use crate::config::{default_config_filepath, Config}; +use nym_config::read_config_from_toml_file; +use nym_socks5_client_core::config::old_config_v1_1_30::ConfigV1_1_30 as CoreConfigV1_1_30; +use serde::{Deserialize, Serialize}; +use std::io; +use std::path::Path; + +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct ConfigV1_1_30 { + pub core: CoreConfigV1_1_30, + + // I'm leaving a landmine here for when the paths actually do change the next time, + // but propagating the change right now (in ALL clients) would be such a hassle..., + // so sorry for the next person looking at it : ) + pub storage_paths: NymConnectPaths, +} + +impl From for Config { + fn from(value: ConfigV1_1_30) -> Self { + Config { + core: value.core.into(), + storage_paths: value.storage_paths, + } + } +} + +impl ConfigV1_1_30 { + 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)) + } +} diff --git a/nym-connect/desktop/src-tauri/src/config/upgrade.rs b/nym-connect/desktop/src-tauri/src/config/upgrade.rs index bdaf138a00..5ec509e733 100644 --- a/nym-connect/desktop/src-tauri/src/config/upgrade.rs +++ b/nym-connect/desktop/src-tauri/src/config/upgrade.rs @@ -1,6 +1,8 @@ // Copyright 2022-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::config::old_config_v1_1_30::ConfigV1_1_30; +use crate::config::persistence::NymConnectPaths; use crate::{ config::{ old_config_v1_1_13::OldConfigV1_1_13, old_config_v1_1_20::ConfigV1_1_20, @@ -18,10 +20,12 @@ use nym_client_core::{ error::ClientCoreError, }; -fn persist_gateway_details(config: &Config, details: GatewayEndpointConfig) -> Result<()> { - let details_store = - OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details); - let keys_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone()); +fn persist_gateway_details( + storage_paths: &NymConnectPaths, + details: GatewayEndpointConfig, +) -> Result<()> { + let details_store = OnDiskGatewayDetails::new(&storage_paths.common_paths.gateway_details); + let keys_store = OnDiskKeys::new(storage_paths.common_paths.keys.clone()); let shared_keys = keys_store.ephemeral_load_gateway_keys().map_err(|source| { BackendError::ClientCoreError { source: ClientCoreError::KeyStoreError { @@ -52,9 +56,10 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result { let updated_step1: ConfigV1_1_20 = old_config.into(); let updated_step2: ConfigV1_1_20_2 = updated_step1.into(); - let (updated, gateway_config) = updated_step2.upgrade()?; - persist_gateway_details(&updated, gateway_config)?; + let (updated_step3, gateway_config) = updated_step2.upgrade()?; + persist_gateway_details(&updated_step3.storage_paths, gateway_config)?; + let updated: Config = updated_step3.into(); updated.save_to_default_location()?; Ok(true) } @@ -72,9 +77,10 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result { info!("It is going to get updated to the current specification."); let updated_step1: ConfigV1_1_20_2 = old_config.into(); - let (updated, gateway_config) = updated_step1.upgrade()?; - persist_gateway_details(&updated, gateway_config)?; + let (updated_step2, gateway_config) = updated_step1.upgrade()?; + persist_gateway_details(&updated_step2.storage_paths, gateway_config)?; + let updated: Config = updated_step2.into(); updated.save_to_default_location()?; Ok(true) } @@ -89,9 +95,25 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result { info!("It seems the client is using <= v1.1.20_2 config template."); info!("It is going to get updated to the current specification."); - let (updated, gateway_config) = old_config.upgrade()?; - persist_gateway_details(&updated, gateway_config)?; + let (updated_step1, gateway_config) = old_config.upgrade()?; + persist_gateway_details(&updated_step1.storage_paths, gateway_config)?; + let updated: Config = updated_step1.into(); + updated.save_to_default_location()?; + Ok(true) +} + +fn try_upgrade_v1_1_30_config(id: &str) -> Result { + // explicitly load it as v1.1.20_2 (which is incompatible with the current one, i.e. +1.1.21) + let Ok(old_config) = ConfigV1_1_30::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.1.30 config template."); + info!("It is going to get updated to the current specification."); + + let updated: Config = old_config.into(); updated.save_to_default_location()?; Ok(true) } @@ -107,6 +129,9 @@ pub fn try_upgrade_config(id: &str) -> Result<()> { if try_upgrade_v1_1_20_2_config(id)? { return Ok(()); } + if try_upgrade_v1_1_30_config(id)? { + return Ok(()); + } Ok(()) } From d14337b9db124685d5d66a43361de78ec8a65af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 17 Oct 2023 12:52:52 +0100 Subject: [PATCH 007/236] updated config templates --- nym-connect/desktop/src-tauri/src/config/template.rs | 5 +++-- sdk/lib/socks5-listener/src/config/template.rs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/nym-connect/desktop/src-tauri/src/config/template.rs b/nym-connect/desktop/src-tauri/src/config/template.rs index 3394f6c80e..27e2ed435a 100644 --- a/nym-connect/desktop/src-tauri/src/config/template.rs +++ b/nym-connect/desktop/src-tauri/src/config/template.rs @@ -76,8 +76,9 @@ gateway_details = '{{ storage_paths.gateway_details }}' # The mix address of the provider to which all requests are going to be sent. provider_mix_address = '{{ core.socks5.provider_mix_address }}' -# The port on which the client will be listening for incoming requests -listening_port = {{ core.socks5.listening_port }} +# The address on which the client will be listening for incoming requests +# (default: 127.0.0.1:1080) +bind_adddress = '{{ core.socks5.bind_adddress }}' # Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. # While this is going to hide its actual address information, it will make the actual communication diff --git a/sdk/lib/socks5-listener/src/config/template.rs b/sdk/lib/socks5-listener/src/config/template.rs index 0c9262e5c7..e310ef2e32 100644 --- a/sdk/lib/socks5-listener/src/config/template.rs +++ b/sdk/lib/socks5-listener/src/config/template.rs @@ -83,8 +83,9 @@ gateway_listener = '{{ core.client.gateway_endpoint.gateway_listener }}' # The mix address of the provider to which all requests are going to be sent. provider_mix_address = '{{ core.socks5.provider_mix_address }}' -# The port on which the client will be listening for incoming requests -listening_port = {{ core.socks5.listening_port }} +# The address on which the client will be listening for incoming requests +# (default: 127.0.0.1:1080) +bind_adddress = '{{ core.socks5.bind_adddress }}' # Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. # While this is going to hide its actual address information, it will make the actual communication From c3571e53d9c3aba9594662de44cf41043de30ee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 17 Oct 2023 14:44:23 +0100 Subject: [PATCH 008/236] base config actually did change --- clients/socks5/src/commands/mod.rs | 2 +- common/client-core/src/config/mod.rs | 3 +- .../src/config/old_config_v1_1_20_2.rs | 43 +- .../src/config/old_config_v1_1_30.rs | 472 ++++++++++++++++++ .../src/config/old_config_v1_1_20_2.rs | 2 +- .../src/config/old_config_v1_1_30.rs | 5 +- 6 files changed, 500 insertions(+), 27 deletions(-) create mode 100644 common/client-core/src/config/old_config_v1_1_30.rs diff --git a/clients/socks5/src/commands/mod.rs b/clients/socks5/src/commands/mod.rs index eeef6559b4..7bd5205791 100644 --- a/clients/socks5/src/commands/mod.rs +++ b/clients/socks5/src/commands/mod.rs @@ -250,7 +250,7 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result { } fn try_upgrade_v1_1_30_config(id: &str) -> Result { - // explicitly load it as v1.1.20_2 (which is incompatible with the current one, i.e. +1.1.21) + // explicitly load it as v1.1.30 (which is incompatible with the current one, i.e. +1.1.31) let Ok(old_config) = ConfigV1_1_30::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 diff --git a/common/client-core/src/config/mod.rs b/common/client-core/src/config/mod.rs index b3e8afabff..cdce63c4c6 100644 --- a/common/client-core/src/config/mod.rs +++ b/common/client-core/src/config/mod.rs @@ -1,6 +1,7 @@ // Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::{client::topology_control::geo_aware_provider::CountryGroup, error::ClientCoreError}; use nym_config::defaults::NymNetworkDetails; use nym_crypto::asymmetric::identity; use nym_gateway_client::client::GatewayConfig; @@ -12,7 +13,6 @@ use serde::{Deserialize, Serialize}; use std::time::Duration; use url::Url; -use crate::{client::topology_control::geo_aware_provider::CountryGroup, error::ClientCoreError}; #[cfg(target_arch = "wasm32")] use wasm_bindgen::prelude::*; @@ -20,6 +20,7 @@ pub mod disk_persistence; pub mod old_config_v1_1_13; pub mod old_config_v1_1_20; pub mod old_config_v1_1_20_2; +pub mod old_config_v1_1_30; // 'DEBUG' const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5; diff --git a/common/client-core/src/config/old_config_v1_1_20_2.rs b/common/client-core/src/config/old_config_v1_1_20_2.rs index afb6536192..a7abd41ddc 100644 --- a/common/client-core/src/config/old_config_v1_1_20_2.rs +++ b/common/client-core/src/config/old_config_v1_1_20_2.rs @@ -1,10 +1,11 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::{ - Acknowledgements, Client, Config, CoverTraffic, DebugConfig, GatewayConnection, - GatewayEndpointConfig, ReplySurbs, Topology, Traffic, +use crate::config::old_config_v1_1_30::{ + AcknowledgementsV1_1_30, ClientV1_1_30, ConfigV1_1_30, CoverTrafficV1_1_30, DebugConfigV1_1_30, + GatewayConnectionV1_1_30, ReplySurbsV1_1_30, TopologyV1_1_30, TrafficV1_1_30, }; +use crate::config::GatewayEndpointConfig; use nym_sphinx::params::{PacketSize, PacketType}; use serde::{Deserialize, Serialize}; use std::time::Duration; @@ -58,9 +59,9 @@ pub struct ConfigV1_1_20_2 { pub debug: DebugConfigV1_1_20_2, } -impl From for Config { +impl From for ConfigV1_1_30 { fn from(value: ConfigV1_1_20_2) -> Self { - Config { + ConfigV1_1_30 { client: value.client.into(), debug: value.debug.into(), } @@ -107,9 +108,9 @@ pub struct ClientV1_1_20_2 { pub gateway_endpoint: GatewayEndpointConfigV1_1_20_2, } -impl From for Client { +impl From for ClientV1_1_30 { fn from(value: ClientV1_1_20_2) -> Self { - Client { + ClientV1_1_30 { version: value.version, id: value.id, disabled_credentials_mode: value.disabled_credentials_mode, @@ -132,9 +133,9 @@ pub struct TrafficV1_1_20_2 { pub packet_type: PacketType, } -impl From for Traffic { +impl From for TrafficV1_1_30 { fn from(value: TrafficV1_1_20_2) -> Self { - Traffic { + TrafficV1_1_30 { average_packet_delay: value.average_packet_delay, message_sending_average_delay: value.message_sending_average_delay, disable_main_poisson_packet_distribution: value @@ -168,9 +169,9 @@ pub struct CoverTrafficV1_1_20_2 { pub disable_loop_cover_traffic_stream: bool, } -impl From for CoverTraffic { +impl From for CoverTrafficV1_1_30 { fn from(value: CoverTrafficV1_1_20_2) -> Self { - CoverTraffic { + CoverTrafficV1_1_30 { loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay, cover_traffic_primary_size_ratio: value.cover_traffic_primary_size_ratio, disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream, @@ -195,9 +196,9 @@ pub struct GatewayConnectionV1_1_20_2 { pub gateway_response_timeout: Duration, } -impl From for GatewayConnection { +impl From for GatewayConnectionV1_1_30 { fn from(value: GatewayConnectionV1_1_20_2) -> Self { - GatewayConnection { + GatewayConnectionV1_1_30 { gateway_response_timeout: value.gateway_response_timeout, } } @@ -221,9 +222,9 @@ pub struct AcknowledgementsV1_1_20_2 { pub ack_wait_addition: Duration, } -impl From for Acknowledgements { +impl From for AcknowledgementsV1_1_30 { fn from(value: AcknowledgementsV1_1_20_2) -> Self { - Acknowledgements { + AcknowledgementsV1_1_30 { average_ack_delay: value.average_ack_delay, ack_wait_multiplier: value.ack_wait_multiplier, ack_wait_addition: value.ack_wait_addition, @@ -261,9 +262,9 @@ impl Default for TopologyV1_1_20_2 { } } -impl From for Topology { +impl From for TopologyV1_1_30 { fn from(value: TopologyV1_1_20_2) -> Self { - Topology { + TopologyV1_1_30 { topology_refresh_rate: value.topology_refresh_rate, topology_resolution_timeout: value.topology_resolution_timeout, disable_refreshing: value.disable_refreshing, @@ -307,9 +308,9 @@ impl Default for ReplySurbsV1_1_20_2 { } } -impl From for ReplySurbs { +impl From for ReplySurbsV1_1_30 { fn from(value: ReplySurbsV1_1_20_2) -> Self { - ReplySurbs { + ReplySurbsV1_1_30 { minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold, maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold, minimum_reply_surb_request_size: value.minimum_reply_surb_request_size, @@ -335,9 +336,9 @@ pub struct DebugConfigV1_1_20_2 { pub reply_surbs: ReplySurbsV1_1_20_2, } -impl From for DebugConfig { +impl From for DebugConfigV1_1_30 { fn from(value: DebugConfigV1_1_20_2) -> Self { - DebugConfig { + DebugConfigV1_1_30 { traffic: value.traffic.into(), cover_traffic: value.cover_traffic.into(), gateway_connection: value.gateway_connection.into(), diff --git a/common/client-core/src/config/old_config_v1_1_30.rs b/common/client-core/src/config/old_config_v1_1_30.rs new file mode 100644 index 0000000000..20501f5880 --- /dev/null +++ b/common/client-core/src/config/old_config_v1_1_30.rs @@ -0,0 +1,472 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::client::topology_control::geo_aware_provider::CountryGroup; +use crate::config::{ + Acknowledgements, Client, Config, CoverTraffic, DebugConfig, GatewayConnection, GroupBy, + ReplySurbs, Topology, TopologyStructure, Traffic, +}; +use nym_sphinx::{ + addressing::clients::Recipient, + params::{PacketSize, PacketType}, +}; +use serde::{Deserialize, Serialize}; +use std::time::Duration; +use url::Url; + +// 'DEBUG' +const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5; + +const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500); +const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200); +const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20); +const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50); +const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min +const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000); +const DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD: Duration = Duration::from_secs(70 * 60); // 70min -> full epoch (1h) + a bit of overhead + +// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause +// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the +// bandwidth bridging protocol, we can come back to a smaller timeout value +const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60); + +const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70; + +// reply-surbs related: + +// define when to request +// clients/client-core/src/client/replies/reply_storage/surb_storage.rs +const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10; +const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200; + +// define how much to request at once +// clients/client-core/src/client/replies/reply_controller.rs +const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10; +const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100; + +const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500; + +const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10); +const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60); + +// 12 hours +const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60); + +// 24 hours +const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60); + +#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct ConfigV1_1_30 { + pub client: ClientV1_1_30, + + #[serde(default)] + pub debug: DebugConfigV1_1_30, +} + +impl From for Config { + fn from(value: ConfigV1_1_30) -> Self { + Config { + client: Client { + version: value.client.version, + id: value.client.id, + disabled_credentials_mode: value.client.disabled_credentials_mode, + nyxd_urls: value.client.nyxd_urls, + nym_api_urls: value.client.nym_api_urls, + }, + debug: DebugConfig { + traffic: Traffic { + average_packet_delay: value.debug.traffic.average_packet_delay, + message_sending_average_delay: value + .debug + .traffic + .message_sending_average_delay, + disable_main_poisson_packet_distribution: value + .debug + .traffic + .disable_main_poisson_packet_distribution, + primary_packet_size: value.debug.traffic.primary_packet_size, + secondary_packet_size: value.debug.traffic.secondary_packet_size, + packet_type: value.debug.traffic.packet_type, + }, + cover_traffic: CoverTraffic { + loop_cover_traffic_average_delay: value + .debug + .cover_traffic + .loop_cover_traffic_average_delay, + cover_traffic_primary_size_ratio: value + .debug + .cover_traffic + .cover_traffic_primary_size_ratio, + disable_loop_cover_traffic_stream: value + .debug + .cover_traffic + .disable_loop_cover_traffic_stream, + }, + gateway_connection: GatewayConnection { + gateway_response_timeout: value + .debug + .gateway_connection + .gateway_response_timeout, + }, + acknowledgements: Acknowledgements { + average_ack_delay: value.debug.acknowledgements.average_ack_delay, + ack_wait_multiplier: value.debug.acknowledgements.ack_wait_multiplier, + ack_wait_addition: value.debug.acknowledgements.ack_wait_addition, + }, + topology: Topology { + topology_refresh_rate: value.debug.topology.topology_refresh_rate, + topology_resolution_timeout: value.debug.topology.topology_resolution_timeout, + disable_refreshing: value.debug.topology.disable_refreshing, + max_startup_gateway_waiting_period: value + .debug + .topology + .max_startup_gateway_waiting_period, + topology_structure: value.debug.topology.topology_structure.into(), + }, + reply_surbs: ReplySurbs { + minimum_reply_surb_storage_threshold: value + .debug + .reply_surbs + .minimum_reply_surb_storage_threshold, + maximum_reply_surb_storage_threshold: value + .debug + .reply_surbs + .maximum_reply_surb_storage_threshold, + minimum_reply_surb_request_size: value + .debug + .reply_surbs + .minimum_reply_surb_request_size, + maximum_reply_surb_request_size: value + .debug + .reply_surbs + .maximum_reply_surb_request_size, + maximum_allowed_reply_surb_request_size: value + .debug + .reply_surbs + .maximum_allowed_reply_surb_request_size, + maximum_reply_surb_rerequest_waiting_period: value + .debug + .reply_surbs + .maximum_reply_surb_rerequest_waiting_period, + maximum_reply_surb_drop_waiting_period: value + .debug + .reply_surbs + .maximum_reply_surb_drop_waiting_period, + maximum_reply_surb_age: value.debug.reply_surbs.maximum_reply_surb_age, + maximum_reply_key_age: value.debug.reply_surbs.maximum_reply_key_age, + }, + }, + } + } +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] +// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2 +#[serde(deny_unknown_fields)] +pub struct ClientV1_1_30 { + /// Version of the client for which this configuration was created. + pub version: String, + + /// ID specifies the human readable ID of this particular client. + pub id: String, + + /// Indicates whether this client is running in a disabled credentials mode, thus attempting + /// to claim bandwidth without presenting bandwidth credentials. + // TODO: this should be moved to `debug.gateway_connection` + #[serde(default)] + pub disabled_credentials_mode: bool, + + /// Addresses to nyxd validators via which the client can communicate with the chain. + #[serde(alias = "validator_urls")] + pub nyxd_urls: Vec, + + /// Addresses to APIs running on validator from which the client gets the view of the network. + #[serde(alias = "validator_api_urls")] + pub nym_api_urls: Vec, +} + +#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct TrafficV1_1_30 { + /// The parameter of Poisson distribution determining how long, on average, + /// sent packet is going to be delayed at any given mix node. + /// So for a packet going through three mix nodes, on average, it will take three times this value + /// until the packet reaches its destination. + #[serde(with = "humantime_serde")] + pub average_packet_delay: Duration, + + /// The parameter of Poisson distribution determining how long, on average, + /// it is going to take another 'real traffic stream' message to be sent. + /// If no real packets are available and cover traffic is enabled, + /// a loop cover message is sent instead in order to preserve the rate. + #[serde(with = "humantime_serde")] + pub message_sending_average_delay: Duration, + + /// Controls whether the main packet stream constantly produces packets according to the predefined + /// poisson distribution. + pub disable_main_poisson_packet_distribution: bool, + + /// Specifies the packet size used for sent messages. + /// Do not override it unless you understand the consequences of that change. + pub primary_packet_size: PacketSize, + + /// Specifies the optional auxiliary packet size for optimizing message streams. + /// Note that its use decreases overall anonymity. + /// Do not set it it unless you understand the consequences of that change. + pub secondary_packet_size: Option, + + pub packet_type: PacketType, +} + +impl Default for TrafficV1_1_30 { + fn default() -> Self { + TrafficV1_1_30 { + average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY, + message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY, + disable_main_poisson_packet_distribution: false, + primary_packet_size: PacketSize::RegularPacket, + secondary_packet_size: None, + packet_type: PacketType::Mix, + } + } +} + +#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct CoverTrafficV1_1_30 { + /// The parameter of Poisson distribution determining how long, on average, + /// it is going to take for another loop cover traffic message to be sent. + #[serde(with = "humantime_serde")] + pub loop_cover_traffic_average_delay: Duration, + + /// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic. + /// Only applicable if `secondary_packet_size` is enabled. + pub cover_traffic_primary_size_ratio: f64, + + /// Controls whether the dedicated loop cover traffic stream should be enabled. + /// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay]) + pub disable_loop_cover_traffic_stream: bool, +} + +impl Default for CoverTrafficV1_1_30 { + fn default() -> Self { + CoverTrafficV1_1_30 { + loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY, + cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO, + disable_loop_cover_traffic_stream: false, + } + } +} + +#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct GatewayConnectionV1_1_30 { + /// How long we're willing to wait for a response to a message sent to the gateway, + /// before giving up on it. + #[serde(with = "humantime_serde")] + pub gateway_response_timeout: Duration, +} + +impl Default for GatewayConnectionV1_1_30 { + fn default() -> Self { + GatewayConnectionV1_1_30 { + gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT, + } + } +} + +#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct AcknowledgementsV1_1_30 { + /// The parameter of Poisson distribution determining how long, on average, + /// sent acknowledgement is going to be delayed at any given mix node. + /// So for an ack going through three mix nodes, on average, it will take three times this value + /// until the packet reaches its destination. + #[serde(with = "humantime_serde")] + pub average_ack_delay: Duration, + + /// Value multiplied with the expected round trip time of an acknowledgement packet before + /// it is assumed it was lost and retransmission of the data packet happens. + /// In an ideal network with 0 latency, this value would have been 1. + pub ack_wait_multiplier: f64, + + /// Value added to the expected round trip time of an acknowledgement packet before + /// it is assumed it was lost and retransmission of the data packet happens. + /// In an ideal network with 0 latency, this value would have been 0. + #[serde(with = "humantime_serde")] + pub ack_wait_addition: Duration, +} + +impl Default for AcknowledgementsV1_1_30 { + fn default() -> Self { + AcknowledgementsV1_1_30 { + average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY, + ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER, + ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION, + } + } +} + +#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct TopologyV1_1_30 { + /// The uniform delay every which clients are querying the directory server + /// to try to obtain a compatible network topology to send sphinx packets through. + #[serde(with = "humantime_serde")] + pub topology_refresh_rate: Duration, + + /// During topology refresh, test packets are sent through every single possible network + /// path. This timeout determines waiting period until it is decided that the packet + /// did not reach its destination. + #[serde(with = "humantime_serde")] + pub topology_resolution_timeout: Duration, + + /// Specifies whether the client should not refresh the network topology after obtaining + /// the first valid instance. + /// Supersedes `topology_refresh_rate_ms`. + pub disable_refreshing: bool, + + /// Defines how long the client is going to wait on startup for its gateway to come online, + /// before abandoning the procedure. + #[serde(with = "humantime_serde")] + pub max_startup_gateway_waiting_period: Duration, + + /// Specifies the mixnode topology to be used for sending packets. + pub topology_structure: TopologyStructureV1_1_30, +} + +#[allow(clippy::large_enum_variant)] +#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum TopologyStructureV1_1_30 { + #[default] + NymApi, + GeoAware(GroupByV1_1_30), +} + +impl From for TopologyStructure { + fn from(value: TopologyStructureV1_1_30) -> Self { + match value { + TopologyStructureV1_1_30::NymApi => TopologyStructure::NymApi, + TopologyStructureV1_1_30::GeoAware(group_by) => { + TopologyStructure::GeoAware(group_by.into()) + } + } + } +} + +#[allow(clippy::large_enum_variant)] +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum GroupByV1_1_30 { + CountryGroup(CountryGroup), + NymAddress(Recipient), +} + +impl From for GroupBy { + fn from(value: GroupByV1_1_30) -> Self { + match value { + GroupByV1_1_30::CountryGroup(country) => GroupBy::CountryGroup(country), + GroupByV1_1_30::NymAddress(addr) => GroupBy::NymAddress(addr), + } + } +} + +impl std::fmt::Display for GroupByV1_1_30 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + GroupByV1_1_30::CountryGroup(group) => write!(f, "group: {}", group), + GroupByV1_1_30::NymAddress(address) => write!(f, "address: {}", address), + } + } +} + +impl Default for TopologyV1_1_30 { + fn default() -> Self { + TopologyV1_1_30 { + topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE, + topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT, + disable_refreshing: false, + max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD, + topology_structure: TopologyStructureV1_1_30::default(), + } + } +} + +#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct ReplySurbsV1_1_30 { + /// Defines the minimum number of reply surbs the client wants to keep in its storage at all times. + /// It can only allow to go below that value if its to request additional reply surbs. + pub minimum_reply_surb_storage_threshold: usize, + + /// Defines the maximum number of reply surbs the client wants to keep in its storage at any times. + pub maximum_reply_surb_storage_threshold: usize, + + /// Defines the minimum number of reply surbs the client would request. + pub minimum_reply_surb_request_size: u32, + + /// Defines the maximum number of reply surbs the client would request. + pub maximum_reply_surb_request_size: u32, + + /// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once. + pub maximum_allowed_reply_surb_request_size: u32, + + /// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking + /// for more even though in theory they wouldn't need to. + #[serde(with = "humantime_serde")] + pub maximum_reply_surb_rerequest_waiting_period: Duration, + + /// Defines maximum amount of time the client is going to wait for reply surbs before + /// deciding it's never going to get them and would drop all pending messages + #[serde(with = "humantime_serde")] + pub maximum_reply_surb_drop_waiting_period: Duration, + + /// Defines maximum amount of time given reply surb is going to be valid for. + /// This is going to be superseded by key rotation once implemented. + #[serde(with = "humantime_serde")] + pub maximum_reply_surb_age: Duration, + + /// Defines maximum amount of time given reply key is going to be valid for. + /// This is going to be superseded by key rotation once implemented. + #[serde(with = "humantime_serde")] + pub maximum_reply_key_age: Duration, +} + +impl Default for ReplySurbsV1_1_30 { + fn default() -> Self { + ReplySurbsV1_1_30 { + minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD, + maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD, + minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE, + maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE, + maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE, + maximum_reply_surb_rerequest_waiting_period: + DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD, + maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD, + maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE, + maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE, + } + } +} + +#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct DebugConfigV1_1_30 { + /// Defines all configuration options related to traffic streams. + pub traffic: TrafficV1_1_30, + + /// Defines all configuration options related to cover traffic stream(s). + pub cover_traffic: CoverTrafficV1_1_30, + + /// Defines all configuration options related to the gateway connection. + pub gateway_connection: GatewayConnectionV1_1_30, + + /// Defines all configuration options related to acknowledgements, such as delays or wait timeouts. + pub acknowledgements: AcknowledgementsV1_1_30, + + /// Defines all configuration options related topology, such as refresh rates or timeouts. + pub topology: TopologyV1_1_30, + + /// Defines all configuration options related to reply SURBs. + pub reply_surbs: ReplySurbsV1_1_30, +} diff --git a/common/socks5-client-core/src/config/old_config_v1_1_20_2.rs b/common/socks5-client-core/src/config/old_config_v1_1_20_2.rs index dc24de4131..b33a211485 100644 --- a/common/socks5-client-core/src/config/old_config_v1_1_20_2.rs +++ b/common/socks5-client-core/src/config/old_config_v1_1_20_2.rs @@ -23,7 +23,7 @@ pub struct ConfigV1_1_20_2 { impl From for ConfigV1_1_30 { fn from(value: ConfigV1_1_20_2) -> Self { ConfigV1_1_30 { - base: value.base, + base: value.base.into(), socks5: value.socks5.into(), } } diff --git a/common/socks5-client-core/src/config/old_config_v1_1_30.rs b/common/socks5-client-core/src/config/old_config_v1_1_30.rs index e84eb7011b..3f3f877797 100644 --- a/common/socks5-client-core/src/config/old_config_v1_1_30.rs +++ b/common/socks5-client-core/src/config/old_config_v1_1_30.rs @@ -1,8 +1,8 @@ // Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use super::old_config_v1_1_20_2::BaseClientConfigV1_1_20_2; use super::{Config, Socks5, Socks5Debug}; +pub use nym_client_core::config::old_config_v1_1_30::ConfigV1_1_30 as BaseClientConfigV1_1_30; use serde::{Deserialize, Serialize}; use std::fmt::Debug; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; @@ -18,8 +18,7 @@ const DEFAULT_PER_REQUEST_SURBS: u32 = 3; #[serde(deny_unknown_fields)] pub struct ConfigV1_1_30 { #[serde(flatten)] - // base client config hasn't changed between v1.1.20 and v1.1.30 - pub base: BaseClientConfigV1_1_20_2, + pub base: BaseClientConfigV1_1_30, pub socks5: Socks5V1_1_30, } From 82070b4ccbc7e3b692d509483973764b0cf04f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 17 Oct 2023 15:17:58 +0100 Subject: [PATCH 009/236] i hate config backwards compatibility --- clients/native/src/client/config/old_config_v1_1_20_2.rs | 3 ++- .../network-requester/src/config/old_config_v1_1_20_2.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/clients/native/src/client/config/old_config_v1_1_20_2.rs b/clients/native/src/client/config/old_config_v1_1_20_2.rs index 30969b0f12..8e50fe0047 100644 --- a/clients/native/src/client/config/old_config_v1_1_20_2.rs +++ b/clients/native/src/client/config/old_config_v1_1_20_2.rs @@ -11,6 +11,7 @@ use crate::{ use nym_bin_common::logging::LoggingSettings; use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2; use nym_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as BaseConfigV1_1_20_2; +use nym_client_core::config::old_config_v1_1_30::ConfigV1_1_30 as BaseConfigV1_1_30; use nym_client_core::config::GatewayEndpointConfig; use nym_config::read_config_from_toml_file; use nym_network_defaults::DEFAULT_WEBSOCKET_LISTENING_PORT; @@ -51,7 +52,7 @@ impl ConfigV1_1_20_2 { pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig), ClientError> { let gateway_details = self.base.client.gateway_endpoint.clone().into(); let config = Config { - base: self.base.into(), + base: BaseConfigV1_1_30::from(self.base).into(), socket: self.socket.into(), storage_paths: ClientPaths { common_paths: self.storage_paths.common_paths.upgrade_default()?, diff --git a/service-providers/network-requester/src/config/old_config_v1_1_20_2.rs b/service-providers/network-requester/src/config/old_config_v1_1_20_2.rs index 68cd8031ec..25aa2e1975 100644 --- a/service-providers/network-requester/src/config/old_config_v1_1_20_2.rs +++ b/service-providers/network-requester/src/config/old_config_v1_1_20_2.rs @@ -13,6 +13,7 @@ use log::trace; use nym_bin_common::logging::LoggingSettings; use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2; use nym_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as BaseClientConfigV1_1_20_2; +use nym_client_core::config::old_config_v1_1_30::ConfigV1_1_30 as BaseConfigV1_1_30; use nym_client_core::config::GatewayEndpointConfig; use nym_config::read_config_from_toml_file; use serde::{Deserialize, Serialize}; @@ -76,7 +77,7 @@ impl ConfigV1_1_20_2 { .expect("config paths upgrade failure") .join(DEFAULT_DESCRIPTION_FILENAME); let config = Config { - base: self.base.into(), + base: BaseConfigV1_1_30::from(self.base).into(), storage_paths: NetworkRequesterPaths { common_paths: self.storage_paths.common_paths.upgrade_default()?, allowed_list_location: self.storage_paths.allowed_list_location, From bc6634fb6f3ae9b415bcc25899def512da85d48e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Oct 2023 22:42:31 +0200 Subject: [PATCH 010/236] ci: use custom-linux instead of custom-runner-linux (#4014) --- .github/workflows/cd-docs.yml | 2 +- .github/workflows/ci-binary-checker.yml | 2 +- .github/workflows/ci-contracts-schema.yml | 2 +- .github/workflows/ci-docs.yml | 2 +- .github/workflows/ci-nym-connect-desktop.yml | 2 +- .github/workflows/ci-nym-network-explorer.yml | 2 +- .github/workflows/ci-nym-wallet-storybook.yml | 2 +- .github/workflows/ci-sdk-docs-typescript.yml | 2 +- .github/workflows/ci-sdk-wasm.yml | 2 +- .github/workflows/nightly-build.yml | 2 +- .github/workflows/nightly-nym-wallet-build.yml | 2 +- .github/workflows/nightly-security-audit.yml | 2 +- .github/workflows/publish-nyms5-android-apk.yml | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/cd-docs.yml b/.github/workflows/cd-docs.yml index e775e0c601..2e7d024f60 100644 --- a/.github/workflows/cd-docs.yml +++ b/.github/workflows/cd-docs.yml @@ -9,7 +9,7 @@ on: jobs: build: - runs-on: custom-runner-linux + runs-on: custom-linux steps: - uses: actions/checkout@v3 - name: Install rsync diff --git a/.github/workflows/ci-binary-checker.yml b/.github/workflows/ci-binary-checker.yml index 167f6dcad9..86e4903be2 100644 --- a/.github/workflows/ci-binary-checker.yml +++ b/.github/workflows/ci-binary-checker.yml @@ -31,7 +31,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [custom-runner-linux] + platform: [custom-linux] runs-on: ${{ matrix.platform }} steps: diff --git a/.github/workflows/ci-contracts-schema.yml b/.github/workflows/ci-contracts-schema.yml index e09f71432c..790d06d9f6 100644 --- a/.github/workflows/ci-contracts-schema.yml +++ b/.github/workflows/ci-contracts-schema.yml @@ -14,7 +14,7 @@ on: jobs: check-schema: name: Generate and check schema - runs-on: custom-runner-linux + runs-on: custom-linux env: CARGO_TERM_COLOR: always steps: diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index 4fdf5163de..b503516e70 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -9,7 +9,7 @@ on: jobs: build: - runs-on: custom-runner-linux + runs-on: custom-linux steps: - uses: actions/checkout@v3 - name: Install rsync diff --git a/.github/workflows/ci-nym-connect-desktop.yml b/.github/workflows/ci-nym-connect-desktop.yml index 6a599c408f..5955de1ffa 100644 --- a/.github/workflows/ci-nym-connect-desktop.yml +++ b/.github/workflows/ci-nym-connect-desktop.yml @@ -11,7 +11,7 @@ defaults: jobs: build: - runs-on: custom-runner-linux + runs-on: custom-linux steps: - uses: actions/checkout@v2 - name: Install rsync diff --git a/.github/workflows/ci-nym-network-explorer.yml b/.github/workflows/ci-nym-network-explorer.yml index 3c7cacdba8..04bf1f7688 100644 --- a/.github/workflows/ci-nym-network-explorer.yml +++ b/.github/workflows/ci-nym-network-explorer.yml @@ -12,7 +12,7 @@ defaults: jobs: build: - runs-on: custom-runner-linux + runs-on: custom-linux steps: - uses: actions/checkout@v2 - name: Install rsync diff --git a/.github/workflows/ci-nym-wallet-storybook.yml b/.github/workflows/ci-nym-wallet-storybook.yml index 54f5804cbf..7b17b2a741 100644 --- a/.github/workflows/ci-nym-wallet-storybook.yml +++ b/.github/workflows/ci-nym-wallet-storybook.yml @@ -7,7 +7,7 @@ on: jobs: build: - runs-on: custom-runner-linux + runs-on: custom-linux steps: - uses: actions/checkout@v2 - name: Install rsync diff --git a/.github/workflows/ci-sdk-docs-typescript.yml b/.github/workflows/ci-sdk-docs-typescript.yml index c07aa703e4..b98d160b47 100644 --- a/.github/workflows/ci-sdk-docs-typescript.yml +++ b/.github/workflows/ci-sdk-docs-typescript.yml @@ -12,7 +12,7 @@ on: jobs: build: - runs-on: custom-runner-linux + runs-on: custom-linux steps: - uses: actions/checkout@v2 - name: Install rsync diff --git a/.github/workflows/ci-sdk-wasm.yml b/.github/workflows/ci-sdk-wasm.yml index e3f38bcd71..4cd34ece69 100644 --- a/.github/workflows/ci-sdk-wasm.yml +++ b/.github/workflows/ci-sdk-wasm.yml @@ -9,7 +9,7 @@ on: jobs: wasm: - runs-on: [custom-runner-linux] + runs-on: [custom-linux] env: CARGO_TERM_COLOR: always steps: diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 16c98ce16d..9185c9f304 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -70,7 +70,7 @@ jobs: notification: needs: build - runs-on: custom-runner-linux + runs-on: custom-linux steps: - name: Collect jobs status uses: technote-space/workflow-conclusion-action@v2 diff --git a/.github/workflows/nightly-nym-wallet-build.yml b/.github/workflows/nightly-nym-wallet-build.yml index aa684e62d9..de75c26d3d 100644 --- a/.github/workflows/nightly-nym-wallet-build.yml +++ b/.github/workflows/nightly-nym-wallet-build.yml @@ -68,7 +68,7 @@ jobs: notification: needs: build - runs-on: custom-runner-linux + runs-on: custom-linux steps: - name: Collect jobs status uses: technote-space/workflow-conclusion-action@v2 diff --git a/.github/workflows/nightly-security-audit.yml b/.github/workflows/nightly-security-audit.yml index 1a55fd34fa..a286050abb 100644 --- a/.github/workflows/nightly-security-audit.yml +++ b/.github/workflows/nightly-security-audit.yml @@ -26,7 +26,7 @@ jobs: path: .github/workflows/support-files/notifications/deny.message notification: needs: cargo-deny - runs-on: custom-runner-linux + runs-on: custom-linux steps: - name: Check out repository code uses: actions/checkout@v2 diff --git a/.github/workflows/publish-nyms5-android-apk.yml b/.github/workflows/publish-nyms5-android-apk.yml index 1dcbcdb171..e143fef431 100644 --- a/.github/workflows/publish-nyms5-android-apk.yml +++ b/.github/workflows/publish-nyms5-android-apk.yml @@ -94,7 +94,7 @@ jobs: gh-release: name: Publish APK (GH release) needs: build - runs-on: custom-runner-linux + runs-on: custom-linux steps: - name: Checkout uses: actions/checkout@v3 From c39fd49b1f64279994be36000ceecee1fb2d9534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Oct 2023 22:47:17 +0200 Subject: [PATCH 011/236] Remove commented out leftovers --- .github/workflows/ci-binary-checker.yml | 10 +++++----- .github/workflows/ci-build-upload-binaries.yml | 3 --- .github/workflows/ci-build.yml | 3 --- .github/workflows/ci-nym-connect-desktop-rust.yml | 2 -- .github/workflows/ci-nym-wallet-rust.yml | 2 -- .github/workflows/ci-nym-wallet-storybook.yml | 13 ++++++++++++- .github/workflows/ci-sdk-wasm.yml | 3 +-- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci-binary-checker.yml b/.github/workflows/ci-binary-checker.yml index 86e4903be2..ec08504816 100644 --- a/.github/workflows/ci-binary-checker.yml +++ b/.github/workflows/ci-binary-checker.yml @@ -32,7 +32,7 @@ jobs: fail-fast: false matrix: platform: [custom-linux] - + runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v3 @@ -45,12 +45,12 @@ jobs: uses: actions-rs/toolchain@v1 with: toolchain: stable - + - name: Branch name run: echo running on branch ${GITHUB_REF##*/} - + - name: Run tests against binaries run: ./build_and_run.sh ${{ github.head_ref || github.ref_name }} working-directory: tests/ - - + + diff --git a/.github/workflows/ci-build-upload-binaries.yml b/.github/workflows/ci-build-upload-binaries.yml index d3a84b7600..559bac5295 100644 --- a/.github/workflows/ci-build-upload-binaries.yml +++ b/.github/workflows/ci-build-upload-binaries.yml @@ -31,9 +31,6 @@ on: - 'tools/nym-cli/**' - 'tools/ts-rs-cli/**' -env: - NETWORK: mainnet - jobs: publish-nym: strategy: diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 4ad027637f..aa95bd7763 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -48,9 +48,6 @@ jobs: runs-on: ${{ matrix.os }} env: CARGO_TERM_COLOR: always - # Enable sccache via environment variable - # env: - # RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache steps: - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler diff --git a/.github/workflows/ci-nym-connect-desktop-rust.yml b/.github/workflows/ci-nym-connect-desktop-rust.yml index 0eea154550..9edb08d4a9 100644 --- a/.github/workflows/ci-nym-connect-desktop-rust.yml +++ b/.github/workflows/ci-nym-connect-desktop-rust.yml @@ -27,8 +27,6 @@ jobs: runs-on: [self-hosted, custom-linux] env: CARGO_TERM_COLOR: always - # env: - # RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache steps: - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libayatana-appindicator3-dev diff --git a/.github/workflows/ci-nym-wallet-rust.yml b/.github/workflows/ci-nym-wallet-rust.yml index 8d95a534c4..8f865195e7 100644 --- a/.github/workflows/ci-nym-wallet-rust.yml +++ b/.github/workflows/ci-nym-wallet-rust.yml @@ -19,8 +19,6 @@ jobs: runs-on: [ self-hosted, custom-linux ] env: CARGO_TERM_COLOR: always - # env: - # RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache steps: - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools diff --git a/.github/workflows/ci-nym-wallet-storybook.yml b/.github/workflows/ci-nym-wallet-storybook.yml index 7b17b2a741..a252cd1359 100644 --- a/.github/workflows/ci-nym-wallet-storybook.yml +++ b/.github/workflows/ci-nym-wallet-storybook.yml @@ -10,26 +10,35 @@ jobs: runs-on: custom-linux steps: - uses: actions/checkout@v2 + - name: Install rsync run: sudo apt-get install rsync continue-on-error: true + - uses: rlespinasse/github-slug-action@v3.x + - uses: actions/setup-node@v3 with: node-version: 18 + - name: Setup yarn run: npm install -g yarn + - name: Install Rust stable uses: actions-rs/toolchain@v1 with: toolchain: stable + - name: Install wasm-pack - run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + - name: Build dependencies run: yarn && yarn build + - name: Build storybook run: yarn storybook:build working-directory: ./nym-wallet + - name: Deploy branch to CI www (storybook) continue-on-error: true uses: easingthemes/ssh-deploy@main @@ -41,9 +50,11 @@ jobs: REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }} TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/wallet-${{ env.GITHUB_REF_SLUG }} EXCLUDE: "/dist/, /node_modules/" + - name: Matrix - Node Install run: npm install working-directory: .github/workflows/support-files + - name: Matrix - Send Notification env: NYM_NOTIFICATION_KIND: nym-wallet diff --git a/.github/workflows/ci-sdk-wasm.yml b/.github/workflows/ci-sdk-wasm.yml index 4cd34ece69..bbcc31246e 100644 --- a/.github/workflows/ci-sdk-wasm.yml +++ b/.github/workflows/ci-sdk-wasm.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/setup-node@v3 with: node-version: 18 - + - uses: actions-rs/toolchain@v1 with: profile: minimal @@ -32,7 +32,6 @@ jobs: with: go-version: '1.20' - - name: Install wasm-pack run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh From 1935df960bb1d2413dbff57bd705f54591bdc7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Oct 2023 22:50:30 +0200 Subject: [PATCH 012/236] Remove push triggers on a bunch of CI workflows --- .github/workflows/ci-build-upload-binaries.yml | 14 -------------- .github/workflows/ci-contracts-schema.yml | 4 ---- .github/workflows/ci-contracts-upload-binaries.yml | 4 ---- .github/workflows/ci-lint-typescript.yml | 9 --------- .github/workflows/ci-nym-connect-desktop-rust.yml | 10 ---------- .github/workflows/ci-sdk-docs-typescript.yml | 4 ---- 6 files changed, 45 deletions(-) diff --git a/.github/workflows/ci-build-upload-binaries.yml b/.github/workflows/ci-build-upload-binaries.yml index 559bac5295..9fb6a631da 100644 --- a/.github/workflows/ci-build-upload-binaries.yml +++ b/.github/workflows/ci-build-upload-binaries.yml @@ -2,20 +2,6 @@ name: ci-build-upload-binaries on: workflow_dispatch: - push: - paths: - - 'clients/**' - - 'common/**' - - 'explorer-api/**' - - 'gateway/**' - - 'integrations/**' - - 'mixnode/**' - - 'sdk/rust/nym-sdk/**' - - 'service-providers/**' - - 'nym-api/**' - - 'nym-outfox/**' - - 'tools/nym-cli/**' - - 'tools/ts-rs-cli/**' pull_request: paths: - 'clients/**' diff --git a/.github/workflows/ci-contracts-schema.yml b/.github/workflows/ci-contracts-schema.yml index 790d06d9f6..cb37e5d799 100644 --- a/.github/workflows/ci-contracts-schema.yml +++ b/.github/workflows/ci-contracts-schema.yml @@ -2,10 +2,6 @@ name: ci-contracts-schema on: workflow_dispatch: - push: - paths: - - 'contracts/**' - - 'common/**' pull_request: paths: - 'contracts/**' diff --git a/.github/workflows/ci-contracts-upload-binaries.yml b/.github/workflows/ci-contracts-upload-binaries.yml index 147ddf3ff3..1c26745016 100644 --- a/.github/workflows/ci-contracts-upload-binaries.yml +++ b/.github/workflows/ci-contracts-upload-binaries.yml @@ -2,10 +2,6 @@ name: ci-contracts-upload-binaries on: workflow_dispatch: - push: - paths: - - 'common/**' - - 'contracts/**' pull_request: paths: - 'common/**' diff --git a/.github/workflows/ci-lint-typescript.yml b/.github/workflows/ci-lint-typescript.yml index bf9e4bf924..bad492ff8e 100644 --- a/.github/workflows/ci-lint-typescript.yml +++ b/.github/workflows/ci-lint-typescript.yml @@ -1,15 +1,6 @@ name: ci-lint-typescript on: - push: - paths: - - "ts-packages/**" - - "sdk/typescript/**" - - "nym-connect/desktop/src/**" - - "nym-connect/desktop/package.json" - - "nym-wallet/src/**" - - "nym-wallet/package.json" - - "explorer/**" pull_request: paths: - "ts-packages/**" diff --git a/.github/workflows/ci-nym-connect-desktop-rust.yml b/.github/workflows/ci-nym-connect-desktop-rust.yml index 9edb08d4a9..e5e56b8f43 100644 --- a/.github/workflows/ci-nym-connect-desktop-rust.yml +++ b/.github/workflows/ci-nym-connect-desktop-rust.yml @@ -1,16 +1,6 @@ name: ci-nym-connect-desktop-rust on: - push: - paths: - - "nym-connect/desktop/src-tauri/**" - - "nym-connect/desktop/src-tauri/Cargo.toml" - - "clients/client-core/**" - - "clients/socks5/**" - - "common/**" - - "gateway/gateway-requests/**" - - "contracts/vesting/**" - - "nym-api/nym-api-requests/**" pull_request: paths: - "nym-connect/desktop/src-tauri/**" diff --git a/.github/workflows/ci-sdk-docs-typescript.yml b/.github/workflows/ci-sdk-docs-typescript.yml index b98d160b47..f1a13d5471 100644 --- a/.github/workflows/ci-sdk-docs-typescript.yml +++ b/.github/workflows/ci-sdk-docs-typescript.yml @@ -1,10 +1,6 @@ name: ci-sdk-docs-typescript on: - push: - paths: - - "sdk/typescript/**" - - "wasm/**" pull_request: paths: - "sdk/typescript/**" From 5729123dd1428cb48cb4441a81c9642c7378500c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Oct 2023 22:51:24 +0200 Subject: [PATCH 013/236] Rename to build-upload-binaries --- ...d-upload-binaries.yml => build-upload-binaries.yml} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename .github/workflows/{build-and-upload-binaries.yml => build-upload-binaries.yml} (93%) diff --git a/.github/workflows/build-and-upload-binaries.yml b/.github/workflows/build-upload-binaries.yml similarity index 93% rename from .github/workflows/build-and-upload-binaries.yml rename to .github/workflows/build-upload-binaries.yml index ec4366ab61..ee1271b4cd 100644 --- a/.github/workflows/build-and-upload-binaries.yml +++ b/.github/workflows/build-upload-binaries.yml @@ -1,16 +1,16 @@ -name: Build and upload binaries to artifact storage +name: build-upload-binaries on: workflow_dispatch: - inputs: + inputs: add_tokio_unstable: description: 'True to add RUSTFLAGS="--cfg tokio_unstable"' required: true default: false - type: boolean - + type: boolean + env: - NETWORK: mainnet + NETWORK: mainnet jobs: publish-nym: From 188e766106d16fa9bcfe53e6cb2978a0a4e639cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Oct 2023 22:52:15 +0200 Subject: [PATCH 014/236] Rename to ci-nym-api-tests --- .github/workflows/{run-api-tests.yml => ci-nym-api-tests.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{run-api-tests.yml => ci-nym-api-tests.yml} (100%) diff --git a/.github/workflows/run-api-tests.yml b/.github/workflows/ci-nym-api-tests.yml similarity index 100% rename from .github/workflows/run-api-tests.yml rename to .github/workflows/ci-nym-api-tests.yml From 5102fe9797fad7166c43841daac28763ecd1da8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Oct 2023 22:53:45 +0200 Subject: [PATCH 015/236] Remove some old build conditionals --- .github/workflows/ci-build-upload-binaries.yml | 2 -- .github/workflows/ci-contracts-upload-binaries.yml | 2 -- 2 files changed, 4 deletions(-) diff --git a/.github/workflows/ci-build-upload-binaries.yml b/.github/workflows/ci-build-upload-binaries.yml index 9fb6a631da..ebaf16355e 100644 --- a/.github/workflows/ci-build-upload-binaries.yml +++ b/.github/workflows/ci-build-upload-binaries.yml @@ -27,8 +27,6 @@ jobs: runs-on: ${{ matrix.platform }} env: CARGO_TERM_COLOR: always - # a push event from the origin repo, or a PR from external repo - if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name != 'nymtech/nym' }} steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/ci-contracts-upload-binaries.yml b/.github/workflows/ci-contracts-upload-binaries.yml index 1c26745016..1469a96bf0 100644 --- a/.github/workflows/ci-contracts-upload-binaries.yml +++ b/.github/workflows/ci-contracts-upload-binaries.yml @@ -20,8 +20,6 @@ jobs: runs-on: ${{ matrix.platform }} env: CARGO_TERM_COLOR: always - # a push event from the origin repo, or a PR from external repo - if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name != 'nymtech/nym' }} steps: - uses: actions/checkout@v3 From af018180d27b2503bb8d86d1a577928a589e84b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Oct 2023 22:55:00 +0200 Subject: [PATCH 016/236] Switch to pull_request triggers on a few workflows --- .github/workflows/ci-build-ts.yml | 2 +- .github/workflows/ci-nym-connect-desktop.yml | 2 +- .github/workflows/ci-nym-wallet-storybook.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-build-ts.yml b/.github/workflows/ci-build-ts.yml index 29d986f5ce..9dd6f238a2 100644 --- a/.github/workflows/ci-build-ts.yml +++ b/.github/workflows/ci-build-ts.yml @@ -1,7 +1,7 @@ name: ci-build-ts on: - push: + pull_request: paths: - "ts-packages/**" - "sdk/typescript/**" diff --git a/.github/workflows/ci-nym-connect-desktop.yml b/.github/workflows/ci-nym-connect-desktop.yml index 5955de1ffa..5938e3a606 100644 --- a/.github/workflows/ci-nym-connect-desktop.yml +++ b/.github/workflows/ci-nym-connect-desktop.yml @@ -1,7 +1,7 @@ name: ci-nym-connect-desktop on: - push: + pull_request: paths: - 'nym-connect/desktop/**' diff --git a/.github/workflows/ci-nym-wallet-storybook.yml b/.github/workflows/ci-nym-wallet-storybook.yml index a252cd1359..d44ee1651b 100644 --- a/.github/workflows/ci-nym-wallet-storybook.yml +++ b/.github/workflows/ci-nym-wallet-storybook.yml @@ -1,7 +1,7 @@ name: Nym Wallet Storybook on: - push: + pull_request: paths: - 'nym-wallet/**' From 8377c178381b4ea47fcbd8e848e98f7e2eb734ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Oct 2023 22:55:46 +0200 Subject: [PATCH 017/236] Remove unnecessary apt install --- .github/workflows/ci-build-upload-binaries.yml | 3 +-- .github/workflows/ci-contracts-upload-binaries.yml | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/ci-build-upload-binaries.yml b/.github/workflows/ci-build-upload-binaries.yml index ebaf16355e..168abf2837 100644 --- a/.github/workflows/ci-build-upload-binaries.yml +++ b/.github/workflows/ci-build-upload-binaries.yml @@ -40,8 +40,7 @@ jobs: echo $OUTPUT_DIR - name: Install Dependencies (Linux) - run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler - continue-on-error: true + run: sudo apt update && sudo apt install libudev-dev - name: Install Rust stable uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/ci-contracts-upload-binaries.yml b/.github/workflows/ci-contracts-upload-binaries.yml index 1469a96bf0..5173e95af6 100644 --- a/.github/workflows/ci-contracts-upload-binaries.yml +++ b/.github/workflows/ci-contracts-upload-binaries.yml @@ -32,10 +32,6 @@ jobs: mkdir -p $OUTPUT_DIR echo $OUTPUT_DIR - - name: Install Dependencies (Linux) - run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler - continue-on-error: true - - name: Install Rust stable uses: actions-rs/toolchain@v1 with: From b5eb8e94f4b9c7d7eb1c89f054df61d14990812b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Oct 2023 22:56:33 +0200 Subject: [PATCH 018/236] Rename a few workflows --- .github/workflows/ci-nym-wallet-storybook.yml | 2 +- .github/workflows/greetings.yml | 2 +- .github/workflows/nightly-security-audit.yml | 2 +- .github/workflows/publish-nyms5-android-apk.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-nym-wallet-storybook.yml b/.github/workflows/ci-nym-wallet-storybook.yml index d44ee1651b..9ba9cd3d9f 100644 --- a/.github/workflows/ci-nym-wallet-storybook.yml +++ b/.github/workflows/ci-nym-wallet-storybook.yml @@ -1,4 +1,4 @@ -name: Nym Wallet Storybook +name: ci-nym-wallet-storybook on: pull_request: diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml index 6afe9f37aa..6b31063c73 100644 --- a/.github/workflows/greetings.yml +++ b/.github/workflows/greetings.yml @@ -1,4 +1,4 @@ -name: Greetings +name: greetings on: [pull_request_target, issues] diff --git a/.github/workflows/nightly-security-audit.yml b/.github/workflows/nightly-security-audit.yml index a286050abb..808cc20144 100644 --- a/.github/workflows/nightly-security-audit.yml +++ b/.github/workflows/nightly-security-audit.yml @@ -1,4 +1,4 @@ -name: Daily security audit +name: nightly-security-audit on: schedule: diff --git a/.github/workflows/publish-nyms5-android-apk.yml b/.github/workflows/publish-nyms5-android-apk.yml index e143fef431..06f4c6c126 100644 --- a/.github/workflows/publish-nyms5-android-apk.yml +++ b/.github/workflows/publish-nyms5-android-apk.yml @@ -1,4 +1,4 @@ -name: Nyms5 Android +name: publish-nyms5-android-apk # unsigned APKs only, supported archs: # - arm64-v8a (arm64) # - x86_64 From 9095da1e108e727d8e899681c77497534776f111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Oct 2023 22:57:24 +0200 Subject: [PATCH 019/236] Install wasm-pacl in ci-sdk-docs-typescript --- .github/workflows/ci-sdk-docs-typescript.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci-sdk-docs-typescript.yml b/.github/workflows/ci-sdk-docs-typescript.yml index f1a13d5471..5916ea1560 100644 --- a/.github/workflows/ci-sdk-docs-typescript.yml +++ b/.github/workflows/ci-sdk-docs-typescript.yml @@ -30,6 +30,9 @@ jobs: with: go-version: '1.20' + - name: Install wasm-pack + run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + - name: Build branch WASM packages run: make sdk-wasm-build From 833502ee3594cb7c796c93a8e33eaff26b1ee4f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Oct 2023 22:58:25 +0200 Subject: [PATCH 020/236] Download wasm-opt release binaries instead of compiling --- .github/workflows/ci-contracts-upload-binaries.yml | 4 +++- .github/workflows/ci-lint-typescript.yml | 6 +++++- .github/workflows/ci-sdk-docs-typescript.yml | 5 +++++ .github/workflows/ci-sdk-wasm.yml | 4 +++- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-contracts-upload-binaries.yml b/.github/workflows/ci-contracts-upload-binaries.yml index 5173e95af6..c5466d7506 100644 --- a/.github/workflows/ci-contracts-upload-binaries.yml +++ b/.github/workflows/ci-contracts-upload-binaries.yml @@ -40,7 +40,9 @@ jobs: override: true - name: Install wasm-opt - run: cargo install --version 0.112.0 wasm-opt + uses: ./.github/actions/install-wasm-opt + with: + version: '112' - name: Build release contracts run: make contracts diff --git a/.github/workflows/ci-lint-typescript.yml b/.github/workflows/ci-lint-typescript.yml index bad492ff8e..fec923c03d 100644 --- a/.github/workflows/ci-lint-typescript.yml +++ b/.github/workflows/ci-lint-typescript.yml @@ -28,10 +28,14 @@ jobs: uses: actions-rs/toolchain@v1 with: toolchain: stable + - name: Install wasm-pack run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + - name: Install wasm-opt - run: cargo install wasm-opt + uses: ./.github/actions/install-wasm-opt + with: + version: '116' - name: Set up Go uses: actions/setup-go@v4 diff --git a/.github/workflows/ci-sdk-docs-typescript.yml b/.github/workflows/ci-sdk-docs-typescript.yml index 5916ea1560..926adf0804 100644 --- a/.github/workflows/ci-sdk-docs-typescript.yml +++ b/.github/workflows/ci-sdk-docs-typescript.yml @@ -33,6 +33,11 @@ jobs: - name: Install wasm-pack run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + - name: Install wasm-opt + uses: ./.github/actions/install-wasm-opt + with: + version: '116' + - name: Build branch WASM packages run: make sdk-wasm-build diff --git a/.github/workflows/ci-sdk-wasm.yml b/.github/workflows/ci-sdk-wasm.yml index bbcc31246e..074083042d 100644 --- a/.github/workflows/ci-sdk-wasm.yml +++ b/.github/workflows/ci-sdk-wasm.yml @@ -36,7 +36,9 @@ jobs: run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - name: Install wasm-opt - run: cargo install wasm-opt + uses: ./.github/actions/install-wasm-opt + with: + version: '116' - name: Install wasm-bindgen-cli run: cargo install wasm-bindgen-cli From 4141a7844f6c2723a15dd3c36066f168f4dc646d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Oct 2023 23:39:28 +0200 Subject: [PATCH 021/236] ci: install protoc in nightly-nym-wallet-build --- .github/workflows/nightly-nym-wallet-build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/nightly-nym-wallet-build.yml b/.github/workflows/nightly-nym-wallet-build.yml index de75c26d3d..c4943e0c6c 100644 --- a/.github/workflows/nightly-nym-wallet-build.yml +++ b/.github/workflows/nightly-nym-wallet-build.yml @@ -35,6 +35,9 @@ jobs: override: true components: rustfmt, clippy + - name: Install Protoc + uses: arduino/setup-protoc@v2 + - name: Check formatting uses: actions-rs/cargo@v1 with: From ee02583cd27703833db6007a0804ba5b2e26314f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Wed, 18 Oct 2023 11:19:59 +0200 Subject: [PATCH 022/236] ci: onlyh install protoc on macos-latest --- .github/workflows/nightly-nym-wallet-build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nightly-nym-wallet-build.yml b/.github/workflows/nightly-nym-wallet-build.yml index c4943e0c6c..f4d32bd396 100644 --- a/.github/workflows/nightly-nym-wallet-build.yml +++ b/.github/workflows/nightly-nym-wallet-build.yml @@ -25,7 +25,7 @@ jobs: - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler - if: matrix.os == 'custom-linux' + if: matrix.os == 'custom-ubuntu-20.04' - name: Install rust toolchain uses: actions-rs/toolchain@v1 @@ -37,6 +37,7 @@ jobs: - name: Install Protoc uses: arduino/setup-protoc@v2 + if: matrix.os == 'macos-latest' - name: Check formatting uses: actions-rs/cargo@v1 From bbfb1f434601996d410c2052d908a850a24d8715 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Wed, 18 Oct 2023 16:10:36 +0200 Subject: [PATCH 023/236] Integrate gateway registry with nym-wireguard (#4010) * NC-54 Integrate gateway registry with nym-wireguard * Feature flag wireguard types * Restore etherparse * Fix start command * clippy * fmt * Fix clippy lint --- Cargo.lock | 35 +++- Cargo.toml | 1 + .../src/validator/cosmwasm/init_contract.rs | 2 +- common/types/Cargo.toml | 15 +- .../types/src/gateway_client_registration.rs | 106 +++--------- common/types/src/lib.rs | 4 + common/types/src/wireguard.rs | 71 ++++++++ common/wasm/client-core/src/config/mod.rs | 2 - common/wireguard/Cargo.toml | 4 +- common/wireguard/src/lib.rs | 14 +- common/wireguard/src/registered_peers.rs | 25 +-- common/wireguard/src/udp_listener.rs | 56 ++++-- gateway/Cargo.toml | 2 +- gateway/src/node/client_handling/mod.rs | 1 - .../src/node/http/api/v1/client_registry.rs | 21 +-- gateway/src/node/http/mod.rs | 30 ++-- gateway/src/node/mod.rs | 6 +- .../src/operations/directory/gateways.rs | 2 +- nym-wallet/Cargo.lock | 159 ++++++++++++++---- .../src/operations/simulate/cosmos.rs | 2 +- .../src-tauri/src/wallet_storage/mod.rs | 22 +-- tools/nym-cli/src/validator/account.rs | 4 +- 22 files changed, 385 insertions(+), 199 deletions(-) rename gateway/src/node/client_handling/client_registration.rs => common/types/src/gateway_client_registration.rs (51%) create mode 100644 common/types/src/wireguard.rs diff --git a/Cargo.lock b/Cargo.lock index 1563a0e199..987e01c682 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7364,13 +7364,18 @@ dependencies = [ name = "nym-types" version = "1.0.0" dependencies = [ + "base64 0.21.4", + "boringtun", "cosmrs", "cosmwasm-std", + "dashmap", "eyre", - "itertools 0.10.5", + "hmac 0.12.1", + "itertools 0.11.0", "log", "nym-coconut-interface", "nym-config", + "nym-crypto", "nym-mixnet-contract-common", "nym-validator-client", "nym-vesting-contract-common", @@ -7378,11 +7383,13 @@ dependencies = [ "schemars", "serde", "serde_json", - "strum 0.23.0", + "sha2 0.10.8", + "strum 0.25.0", "tempfile", "thiserror", "ts-rs", "url", + "x25519-dalek 2.0.0", ] [[package]] @@ -7491,6 +7498,8 @@ dependencies = [ "ip_network_table", "log", "nym-task", + "nym-types", + "serde", "tap", "thiserror", "tokio", @@ -10226,6 +10235,15 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros 0.25.3", +] + [[package]] name = "strum_macros" version = "0.23.1" @@ -10252,6 +10270,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.38", +] + [[package]] name = "stun" version = "0.4.4" diff --git a/Cargo.toml b/Cargo.toml index 96014d8f6d..1c3108ba15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -130,6 +130,7 @@ license = "Apache-2.0" anyhow = "1.0.71" async-trait = "0.1.68" bip39 = { version = "2.0.0", features = ["zeroize"] } +boringtun = { git = "https://github.com/cloudflare/boringtun", rev = "e1d6360d6ab4529fc942a078e4c54df107abe2ba" } cfg-if = "1.0.0" cosmwasm-derive = "=1.3.0" cosmwasm-schema = "=1.3.0" diff --git a/common/commands/src/validator/cosmwasm/init_contract.rs b/common/commands/src/validator/cosmwasm/init_contract.rs index 4392704328..430440be44 100644 --- a/common/commands/src/validator/cosmwasm/init_contract.rs +++ b/common/commands/src/validator/cosmwasm/init_contract.rs @@ -60,7 +60,7 @@ pub async fn init(args: Args, client: SigningClient, network_details: &NymNetwor // by default we make ourselves an admin, let me know if you don't like that behaviour let opts = Some(InstantiateOptions { funds, - admin: Some(args.admin.unwrap_or_else(|| client.address().clone())), + admin: Some(args.admin.unwrap_or_else(|| client.address())), }); let msg: serde_json::Value = diff --git a/common/types/Cargo.toml b/common/types/Cargo.toml index 4df4087661..f7c79daf7b 100644 --- a/common/types/Cargo.toml +++ b/common/types/Cargo.toml @@ -7,17 +7,23 @@ edition = "2021" rust-version = "1.58" [dependencies] +base64 = "0.21.4" +boringtun = { workspace = true, optional = true } +dashmap = "5.5.3" eyre = "0.6.5" +hmac = "0.12.1" +itertools = "0.11" log = { workspace = true } -itertools = "0.10" reqwest = { workspace = true } schemars = "0.8" serde = { version = "1.0", features = ["derive"] } serde_json = { workspace = true } -strum = { version = "0.23", features = ["derive"] } +sha2 = "0.10.8" +strum = { version = "0.25", features = ["derive"] } thiserror = { workspace = true } -url = { workspace = true } ts-rs = { workspace = true } +url = { workspace = true } +x25519-dalek = { version = "2.0.0", features = ["static_secrets"] } cosmwasm-std = { workspace = true } cosmrs = { workspace = true } @@ -27,7 +33,7 @@ nym-mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mix nym-vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" } nym-config = { path = "../../common/config" } nym-coconut-interface = { path = "../../common/coconut-interface" } - +nym-crypto = { path = "../../common/crypto", features = ["asymmetric"] } [dev-dependencies] tempfile = "3.3.0" @@ -35,3 +41,4 @@ tempfile = "3.3.0" [features] default = [] generate-ts = ["nym-mixnet-contract-common/generate-ts"] +wireguard = ["boringtun"] diff --git a/gateway/src/node/client_handling/client_registration.rs b/common/types/src/gateway_client_registration.rs similarity index 51% rename from gateway/src/node/client_handling/client_registration.rs rename to common/types/src/gateway_client_registration.rs index 3dd97b7b45..e558cd043f 100644 --- a/gateway/src/node/client_handling/client_registration.rs +++ b/common/types/src/gateway_client_registration.rs @@ -1,11 +1,6 @@ -use std::{ - fmt, - hash::{Hash, Hasher}, - net::SocketAddr, - ops::Deref, - str::FromStr, -}; +use std::{net::SocketAddr, ops::Deref, str::FromStr}; +use crate::wireguard::PeerPublicKey; use base64::{engine::general_purpose, Engine}; use dashmap::DashMap; use hmac::{Hmac, Mac}; @@ -14,25 +9,23 @@ use serde::{Deserialize, Serialize}; use sha2::Sha256; use x25519_dalek::StaticSecret; -use crate::error::GatewayError; - #[derive(Debug, Clone, Deserialize, Serialize)] -pub(crate) enum ClientMessage { +pub enum ClientMessage { Init(InitMessage), - Final(Client), + Final(GatewayClient), } #[derive(Debug, Clone, Deserialize, Serialize)] -pub(crate) struct InitMessage { - pub_key: ClientPublicKey, +pub struct InitMessage { + pub_key: PeerPublicKey, } impl InitMessage { - pub fn pub_key(&self) -> &ClientPublicKey { + pub fn pub_key(&self) -> &PeerPublicKey { &self.pub_key } #[allow(dead_code)] - pub fn new(pub_key: ClientPublicKey) -> Self { + pub fn new(pub_key: PeerPublicKey) -> Self { InitMessage { pub_key } } } @@ -40,19 +33,23 @@ impl InitMessage { // Client that wants to register sends its PublicKey and SocketAddr bytes mac digest encrypted with a DH shared secret. // Gateway can then verify pub_key payload using the sme process #[derive(Debug, Clone, Deserialize, Serialize)] -pub(crate) struct Client { +pub struct GatewayClient { // base64 encoded public key, using x25519-dalek for impl - pub(crate) pub_key: ClientPublicKey, - pub(crate) socket: SocketAddr, - pub(crate) mac: ClientMac, + pub pub_key: PeerPublicKey, + pub socket: SocketAddr, + pub mac: ClientMac, } pub type HmacSha256 = Hmac; -impl Client { +impl GatewayClient { // Reusable secret should be gateways Wireguard PK // Client should perform this step when generating its payload, using its own WG PK - pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), GatewayError> { + pub fn verify( + &self, + gateway_key: &PrivateKey, + nonce: u64, + ) -> Result<(), Box> { #[allow(clippy::expect_used)] let static_secret = StaticSecret::try_from(gateway_key.to_bytes()).expect("This is infalliable"); @@ -65,7 +62,7 @@ impl Client { Ok(mac.verify_slice(&self.mac)?) } - pub fn pub_key(&self) -> &ClientPublicKey { + pub fn pub_key(&self) -> &PeerPublicKey { &self.pub_key } @@ -74,11 +71,8 @@ impl Client { } } -// This should go into nym-wireguard crate -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct ClientPublicKey(x25519_dalek::PublicKey); #[derive(Debug, Clone)] -pub(crate) struct ClientMac(Vec); +pub struct ClientMac(Vec); impl ClientMac { #[allow(dead_code)] @@ -95,18 +89,6 @@ impl Deref for ClientMac { } } -impl fmt::Display for ClientPublicKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", general_purpose::STANDARD.encode(self.0.as_bytes())) - } -} - -impl Hash for ClientPublicKey { - fn hash(&self, state: &mut H) { - self.0.as_bytes().hash(state) - } -} - impl FromStr for ClientMac { type Err = String; @@ -132,50 +114,4 @@ impl<'de> Deserialize<'de> for ClientMac { } } -impl ClientPublicKey { - #[allow(dead_code)] - pub fn new(key: x25519_dalek::PublicKey) -> Self { - ClientPublicKey(key) - } - - pub fn as_bytes(&self) -> &[u8] { - self.0.as_bytes() - } -} - -impl Deref for ClientPublicKey { - type Target = x25519_dalek::PublicKey; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl FromStr for ClientPublicKey { - type Err = String; - - fn from_str(s: &str) -> Result { - let key_bytes: [u8; 32] = general_purpose::STANDARD - .decode(s) - .map_err(|_| "Could not base64 decode public key representation".to_string())? - .try_into() - .map_err(|_| "Invalid key length".to_string())?; - Ok(ClientPublicKey(x25519_dalek::PublicKey::from(key_bytes))) - } -} - -impl Serialize for ClientPublicKey { - fn serialize(&self, serializer: S) -> Result { - let encoded_key = general_purpose::STANDARD.encode(self.0.as_bytes()); - serializer.serialize_str(&encoded_key) - } -} - -impl<'de> Deserialize<'de> for ClientPublicKey { - fn deserialize>(deserializer: D) -> Result { - let encoded_key = String::deserialize(deserializer)?; - Ok(ClientPublicKey::from_str(&encoded_key).map_err(serde::de::Error::custom))? - } -} - -pub(crate) type ClientRegistry = DashMap; +pub type GatewayClientRegistry = DashMap; diff --git a/common/types/src/lib.rs b/common/types/src/lib.rs index e44fa517df..956036000a 100644 --- a/common/types/src/lib.rs +++ b/common/types/src/lib.rs @@ -9,8 +9,12 @@ pub mod error; pub mod fees; pub mod gas; pub mod gateway; +#[cfg(feature = "wireguard")] +pub mod gateway_client_registration; pub mod helpers; pub mod mixnode; pub mod pending_events; pub mod transaction; pub mod vesting; +#[cfg(feature = "wireguard")] +pub mod wireguard; diff --git a/common/types/src/wireguard.rs b/common/types/src/wireguard.rs new file mode 100644 index 0000000000..279b8392ad --- /dev/null +++ b/common/types/src/wireguard.rs @@ -0,0 +1,71 @@ +use std::{ + fmt, + hash::{Hash, Hasher}, + ops::Deref, + str::FromStr, +}; + +use base64::{engine::general_purpose, Engine}; +use boringtun::x25519::PublicKey; +use serde::Serialize; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct PeerPublicKey(PublicKey); + +impl fmt::Display for PeerPublicKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", general_purpose::STANDARD.encode(self.0.as_bytes())) + } +} + +impl Hash for PeerPublicKey { + fn hash(&self, state: &mut H) { + self.0.as_bytes().hash(state) + } +} + +impl PeerPublicKey { + #[allow(dead_code)] + pub fn new(key: PublicKey) -> Self { + PeerPublicKey(key) + } + + pub fn as_bytes(&self) -> &[u8] { + self.0.as_bytes() + } +} + +impl Deref for PeerPublicKey { + type Target = PublicKey; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl FromStr for PeerPublicKey { + type Err = String; + + fn from_str(s: &str) -> Result { + let key_bytes: [u8; 32] = general_purpose::STANDARD + .decode(s) + .map_err(|_| "Could not base64 decode public key representation".to_string())? + .try_into() + .map_err(|_| "Invalid key length".to_string())?; + Ok(PeerPublicKey(PublicKey::from(key_bytes))) + } +} + +impl Serialize for PeerPublicKey { + fn serialize(&self, serializer: S) -> Result { + let encoded_key = general_purpose::STANDARD.encode(self.0.as_bytes()); + serializer.serialize_str(&encoded_key) + } +} + +impl<'de> serde::Deserialize<'de> for PeerPublicKey { + fn deserialize>(deserializer: D) -> Result { + let encoded_key = String::deserialize(deserializer)?; + Ok(PeerPublicKey::from_str(&encoded_key).map_err(serde::de::Error::custom))? + } +} diff --git a/common/wasm/client-core/src/config/mod.rs b/common/wasm/client-core/src/config/mod.rs index 77dad1da5c..6aca58b3ba 100644 --- a/common/wasm/client-core/src/config/mod.rs +++ b/common/wasm/client-core/src/config/mod.rs @@ -3,8 +3,6 @@ // due to expansion of #[wasm_bindgen] macro on `Debug` Config struct #![allow(clippy::drop_non_drop)] -// another issue due to #[wasm_bindgen] and `Copy` trait -#![allow(dropping_copy_types)] use crate::error::WasmCoreError; use nym_config::helpers::OptionalSet; diff --git a/common/wireguard/Cargo.toml b/common/wireguard/Cargo.toml index a78920f7f5..c82f52141a 100644 --- a/common/wireguard/Cargo.toml +++ b/common/wireguard/Cargo.toml @@ -17,7 +17,7 @@ base64 = "0.21.3" # version mismatch with x25519-dalek/curve25519-dalek that is resolved in the # latest commit. So pick that for now. #boringtun = "0.6.0" -boringtun = { git = "https://github.com/cloudflare/boringtun", rev = "e1d6360d6ab4529fc942a078e4c54df107abe2ba" } +boringtun = { workspace = true } bytes = "1.5.0" dashmap = "5.5.3" etherparse = "0.13.0" @@ -29,6 +29,8 @@ nym-task = { path = "../task" } tap.workspace = true thiserror.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "net", "io-util"] } +serde = { workspace = true, features = ["derive"] } +nym-types = { path = "../types", features = ["wireguard"] } [target.'cfg(target_os = "linux")'.dependencies] tokio-tun = "0.9.0" diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index 49b9a5d93e..a20dc23fa4 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -13,6 +13,9 @@ mod setup; mod udp_listener; mod wg_tunnel; +use nym_types::gateway_client_registration::GatewayClientRegistry; +use std::sync::Arc; + // Currently the module related to setting up the virtual network device is platform specific. #[cfg(target_os = "linux")] use platform::linux::tun_device; @@ -34,9 +37,8 @@ impl TunTaskTx { #[cfg(target_os = "linux")] pub async fn start_wireguard( task_client: nym_task::TaskClient, + gateway_client_registry: Arc, ) -> Result<(), Box> { - use std::sync::Arc; - let peers_by_ip = Arc::new(std::sync::Mutex::new(network_table::NetworkTable::new())); // Start the tun device that is used to relay traffic outbound @@ -44,7 +46,12 @@ pub async fn start_wireguard( tun.start(); // Start the UDP listener that clients connect to - let udp_listener = udp_listener::WgUdpListener::new(tun_task_tx, peers_by_ip).await?; + let udp_listener = udp_listener::WgUdpListener::new( + tun_task_tx, + peers_by_ip, + Arc::clone(&gateway_client_registry), + ) + .await?; udp_listener.start(task_client); Ok(()) @@ -53,6 +60,7 @@ pub async fn start_wireguard( #[cfg(not(target_os = "linux"))] pub async fn start_wireguard( _task_client: nym_task::TaskClient, + _gateway_client_registry: Arc, ) -> Result<(), Box> { todo!("WireGuard is currently only supported on Linux") } diff --git a/common/wireguard/src/registered_peers.rs b/common/wireguard/src/registered_peers.rs index db9819dc25..248f8f85a5 100644 --- a/common/wireguard/src/registered_peers.rs +++ b/common/wireguard/src/registered_peers.rs @@ -1,13 +1,13 @@ use std::{collections::HashMap, sync::Arc}; -use boringtun::x25519; use ip_network::IpNetwork; +use nym_types::wireguard::PeerPublicKey; pub(crate) type PeerIdx = u32; #[derive(Debug)] pub(crate) struct RegisteredPeer { - pub(crate) public_key: x25519::PublicKey, + pub(crate) public_key: PeerPublicKey, pub(crate) index: PeerIdx, pub(crate) allowed_ips: IpNetwork, // endpoint: SocketAddr, @@ -15,23 +15,28 @@ pub(crate) struct RegisteredPeer { #[derive(Debug, Default)] pub(crate) struct RegisteredPeers { - peers: HashMap>>, + peers: HashMap>>, peers_by_idx: HashMap>>, } impl RegisteredPeers { - pub(crate) async fn insert( - &mut self, - public_key: x25519::PublicKey, - peer: Arc>, - ) { + pub(crate) fn contains_key(&self, public_key: &PeerPublicKey) -> bool { + self.peers.contains_key(public_key) + } + + pub(crate) fn next_idx(&self) -> PeerIdx { + self.peers_by_idx.keys().max().unwrap_or(&0) + 1 + } + + pub(crate) async fn insert(&mut self, peer: Arc>) { let peer_idx = { peer.lock().await.index }; + let public_key = { peer.lock().await.public_key.clone() }; self.peers.insert(public_key, Arc::clone(&peer)); self.peers_by_idx.insert(peer_idx, peer); } #[allow(unused)] - pub(crate) async fn remove(&mut self, public_key: &x25519::PublicKey) { + pub(crate) async fn remove(&mut self, public_key: &PeerPublicKey) { if let Some(peer) = self.peers.remove(public_key) { let peer_idx = peer.lock().await.index; if self.peers_by_idx.remove(&peer_idx).is_none() { @@ -42,7 +47,7 @@ impl RegisteredPeers { pub(crate) fn get_by_key( &self, - public_key: &x25519::PublicKey, + public_key: &PeerPublicKey, ) -> Option<&Arc>> { self.peers.get(public_key) } diff --git a/common/wireguard/src/udp_listener.rs b/common/wireguard/src/udp_listener.rs index 7e601da834..a62c279f9d 100644 --- a/common/wireguard/src/udp_listener.rs +++ b/common/wireguard/src/udp_listener.rs @@ -7,10 +7,14 @@ use boringtun::{ use futures::StreamExt; use log::error; use nym_task::TaskClient; +use nym_types::{gateway_client_registration::GatewayClientRegistry, wireguard::PeerPublicKey}; use tap::TapFallible; use tokio::{ net::UdpSocket, - sync::mpsc::{self}, + sync::{ + mpsc::{self}, + Mutex, + }, }; use crate::{ @@ -29,15 +33,15 @@ const MAX_PACKET: usize = 65535; pub(crate) type PeersByIp = NetworkTable>; async fn add_test_peer(registered_peers: &mut RegisteredPeers) { - let peer_static_public = setup::peer_static_public_key(); + let peer_static_public = PeerPublicKey::new(setup::peer_static_public_key()); let peer_index = 0; let peer_allowed_ips = setup::peer_allowed_ips(); let test_peer = Arc::new(tokio::sync::Mutex::new(RegisteredPeer { - public_key: peer_static_public, + public_key: peer_static_public.clone(), index: peer_index, allowed_ips: peer_allowed_ips, })); - registered_peers.insert(peer_static_public, test_peer).await; + registered_peers.insert(test_peer).await; } pub struct WgUdpListener { @@ -61,12 +65,15 @@ pub struct WgUdpListener { // Wireguard rate limiter rate_limiter: RateLimiter, + + gateway_client_registry: Arc, } impl WgUdpListener { pub async fn new( tun_task_tx: TunTaskTx, peers_by_ip: Arc>, + gateway_client_registry: Arc, ) -> Result> { let wg_address = SocketAddr::new(WG_ADDRESS.parse().unwrap(), WG_PORT); log::info!("Starting wireguard UDP listener on {wg_address}"); @@ -90,10 +97,11 @@ impl WgUdpListener { udp, tun_task_tx, rate_limiter, + gateway_client_registry, }) } - pub async fn run(self, mut task_client: TaskClient) { + pub async fn run(mut self, mut task_client: TaskClient) { // The set of active tunnels let active_peers = ActivePeers::default(); // Each tunnel is run in its own task, and the task handle is stored here so we can remove @@ -157,10 +165,11 @@ impl WgUdpListener { // Check if this is a registered peer, if not, just skip let registered_peer = match parse_peer( verified_packet, - &self.registered_peers, + &mut self.registered_peers, &self.static_private, - &self.static_public - ) { + &self.static_public, + Arc::clone(&self.gateway_client_registry), + ).await { Ok(Some(peer)) => peer.lock().await, Ok(None) => { log::warn!("Peer not registered: {addr}"); @@ -189,7 +198,7 @@ impl WgUdpListener { addr, self.udp.clone(), self.static_private.clone(), - registered_peer.public_key, + *registered_peer.public_key, registered_peer.index, registered_peer.allowed_ips, self.tun_task_tx.clone(), @@ -202,7 +211,7 @@ impl WgUdpListener { .ok(); log::info!("Adding peer: {:?}: {addr}", registered_peer.public_key); - active_peers.insert(registered_peer.public_key, addr, peer_tx); + active_peers.insert(*registered_peer.public_key, addr, peer_tx); active_peers_task_handles.push(join_handle); } }, @@ -216,18 +225,37 @@ impl WgUdpListener { } } -fn parse_peer<'a>( - verified_packet: noise::Packet, - registered_peers: &'a RegisteredPeers, +async fn parse_peer<'a>( + verified_packet: noise::Packet<'a>, + registered_peers: &'a mut RegisteredPeers, static_private: &x25519::StaticSecret, static_public: &x25519::PublicKey, + gateway_client_registry: Arc, ) -> Result>>, WgError> { let registered_peer = match verified_packet { noise::Packet::HandshakeInit(ref packet) => { let Ok(handshake) = parse_handshake_anon(static_private, static_public, packet) else { return Err(WgError::HandshakeFailed); }; - registered_peers.get_by_key(&x25519::PublicKey::from(handshake.peer_static_public)) + let peer_public_key = + PeerPublicKey::new(x25519::PublicKey::from(handshake.peer_static_public)); + + let already_registered = registered_peers.contains_key(&peer_public_key); + + if already_registered { + registered_peers.get_by_key(&peer_public_key) + } else if gateway_client_registry.contains_key(&peer_public_key) { + let peer_idx = registered_peers.next_idx(); + let peer = Arc::new(Mutex::new(RegisteredPeer { + public_key: peer_public_key.clone(), + index: peer_idx, + allowed_ips: setup::peer_allowed_ips(), + })); + registered_peers.insert(peer).await; + registered_peers.get_by_key(&peer_public_key) + } else { + None + } } noise::Packet::HandshakeResponse(packet) => { let peer_idx = packet.receiver_idx >> 8; diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index e6046f93ca..43549cb78b 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -97,4 +97,4 @@ sqlx = { version = "0.5", features = [ ] } [features] -wireguard = ["nym-wireguard"] +wireguard = ["nym-wireguard", "nym-types/wireguard"] diff --git a/gateway/src/node/client_handling/mod.rs b/gateway/src/node/client_handling/mod.rs index a5712842f9..bc63605d58 100644 --- a/gateway/src/node/client_handling/mod.rs +++ b/gateway/src/node/client_handling/mod.rs @@ -3,7 +3,6 @@ pub(crate) mod active_clients; mod bandwidth; -pub(crate) mod client_registration; pub(crate) mod embedded_network_requester; pub(crate) mod websocket; diff --git a/gateway/src/node/http/api/v1/client_registry.rs b/gateway/src/node/http/api/v1/client_registry.rs index 07750d57f1..fc8d3a8a94 100644 --- a/gateway/src/node/http/api/v1/client_registry.rs +++ b/gateway/src/node/http/api/v1/client_registry.rs @@ -1,4 +1,6 @@ use axum::extract::Path; +use nym_types::gateway_client_registration::{ClientMessage, GatewayClient, InitMessage}; +use nym_types::wireguard::PeerPublicKey; use std::sync::Arc; use axum::http::StatusCode; @@ -7,12 +9,9 @@ use std::str::FromStr; // use axum_macros::debug_handler; -use crate::node::client_handling::client_registration::{ - Client, ClientMessage, ClientPublicKey, InitMessage, -}; use crate::node::http::ApiState; -async fn process_final_message(client: Client, state: Arc) -> StatusCode { +async fn process_final_message(client: GatewayClient, state: Arc) -> StatusCode { let preshared_nonce = { if let Some(nonce) = state.registration_in_progress.get(client.pub_key()) { *nonce @@ -29,7 +28,9 @@ async fn process_final_message(client: Client, state: Arc) -> StatusCo state.registration_in_progress.remove(client.pub_key()); } { - state.client_registry.insert(client.socket(), client); + state + .client_registry + .insert(client.pub_key().clone(), client); } return StatusCode::OK; } @@ -64,7 +65,7 @@ pub(crate) async fn register_client( pub(crate) async fn get_all_clients( State(state): State>, -) -> (StatusCode, Json>) { +) -> (StatusCode, Json>) { ( StatusCode::OK, Json( @@ -72,7 +73,7 @@ pub(crate) async fn get_all_clients( .client_registry .iter() .map(|c| c.pub_key().clone()) - .collect::>(), + .collect::>(), ), ) } @@ -80,8 +81,8 @@ pub(crate) async fn get_all_clients( pub(crate) async fn get_client( Path(pub_key): Path, State(state): State>, -) -> (StatusCode, Json>) { - let pub_key = match ClientPublicKey::from_str(&pub_key) { +) -> (StatusCode, Json>) { + let pub_key = match PeerPublicKey::from_str(&pub_key) { Ok(pub_key) => pub_key, Err(_) => return (StatusCode::BAD_REQUEST, Json(vec![])), }; @@ -96,7 +97,7 @@ pub(crate) async fn get_client( None } }) - .collect::>(); + .collect::>(); if clients.is_empty() { return (StatusCode::NOT_FOUND, Json(clients)); } diff --git a/gateway/src/node/http/mod.rs b/gateway/src/node/http/mod.rs index d9fcd8a331..91f73561d2 100644 --- a/gateway/src/node/http/mod.rs +++ b/gateway/src/node/http/mod.rs @@ -10,15 +10,15 @@ use nym_crypto::asymmetric::encryption; mod api; use api::v1::client_registry::*; - -use super::client_handling::client_registration::{ClientPublicKey, ClientRegistry}; +use nym_types::gateway_client_registration::GatewayClientRegistry; +use nym_types::wireguard::PeerPublicKey; const ROUTE_PREFIX: &str = "/api/v1/gateway/client-interfaces/wireguard"; pub struct ApiState { - client_registry: Arc, + client_registry: Arc, sphinx_key_pair: Arc, - registration_in_progress: Arc>, + registration_in_progress: Arc>, } fn router_with_state(state: Arc) -> Router { @@ -33,7 +33,7 @@ fn router_with_state(state: Arc) -> Router { } pub(crate) async fn start_http_api( - client_registry: Arc, + client_registry: Arc, sphinx_key_pair: Arc, ) { // Port should be 80 post smoosh @@ -69,16 +69,18 @@ mod test { use axum::http::StatusCode; use dashmap::DashMap; use hmac::Mac; + use nym_types::gateway_client_registration::ClientMac; + use nym_types::gateway_client_registration::ClientMessage; + use nym_types::gateway_client_registration::GatewayClient; + use nym_types::gateway_client_registration::HmacSha256; + use nym_types::gateway_client_registration::InitMessage; + use nym_types::wireguard::PeerPublicKey; use tower::Service; use tower::ServiceExt; use nym_crypto::asymmetric::encryption; use x25519_dalek::{PublicKey, StaticSecret}; - use crate::node::client_handling::client_registration::{ - Client, ClientMac, ClientMessage, InitMessage, - }; - use crate::node::client_handling::client_registration::{ClientPublicKey, HmacSha256}; use crate::node::http::{router_with_state, ApiState, ROUTE_PREFIX}; #[tokio::test] @@ -119,7 +121,7 @@ mod test { let mut app = router_with_state(state); let init_message = - ClientMessage::Init(InitMessage::new(ClientPublicKey::new(client_static_public))); + ClientMessage::Init(InitMessage::new(PeerPublicKey::new(client_static_public))); let init_request = Request::builder() .method("POST") @@ -150,8 +152,8 @@ mod test { mac.update(&nonce.unwrap().to_le_bytes()); let mac = mac.finalize().into_bytes(); - let finalized_message = ClientMessage::Final(Client { - pub_key: ClientPublicKey::new(client_static_public), + let finalized_message = ClientMessage::Final(GatewayClient { + pub_key: PeerPublicKey::new(client_static_public), socket: SocketAddr::from_str("127.0.0.1:8080").unwrap(), mac: ClientMac::new(mac.as_slice().to_vec()), }); @@ -188,7 +190,7 @@ mod test { assert_eq!(response.status(), StatusCode::OK); - let clients: Vec = + let clients: Vec = serde_json::from_slice(&hyper::body::to_bytes(response.into_body()).await.unwrap()) .unwrap(); @@ -198,7 +200,7 @@ mod test { client_registry .iter() .map(|c| c.value().pub_key().clone()) - .collect::>(), + .collect::>(), clients ) } diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index eb56456b81..6d7ddf44cd 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -1,7 +1,6 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use self::client_handling::client_registration::ClientRegistry; use self::storage::PersistentStorage; use crate::commands::helpers::{override_network_requester_config, OverrideNetworkRequesterConfig}; use crate::config::Config; @@ -27,6 +26,7 @@ use nym_network_defaults::NymNetworkDetails; use nym_network_requester::{LocalGateway, NRServiceProviderBuilder}; use nym_statistics_common::collector::StatisticsSender; use nym_task::{TaskClient, TaskManager}; +use nym_types::gateway_client_registration::GatewayClientRegistry; use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient}; use rand::seq::SliceRandom; use rand::thread_rng; @@ -90,7 +90,7 @@ pub(crate) struct Gateway { sphinx_keypair: Arc, storage: St, - client_registry: Arc, + client_registry: Arc, } impl Gateway { @@ -162,7 +162,7 @@ impl Gateway { shutdown: TaskClient, ) -> Result<(), Box> { // TODO: possibly we should start the UDP listener and TUN device explicitly here - nym_wireguard::start_wireguard(shutdown).await + nym_wireguard::start_wireguard(shutdown, Arc::clone(&self.client_registry)).await } fn start_client_websocket_listener( diff --git a/nym-connect/desktop/src-tauri/src/operations/directory/gateways.rs b/nym-connect/desktop/src-tauri/src/operations/directory/gateways.rs index 8c00fa21b5..56bc16ab67 100644 --- a/nym-connect/desktop/src-tauri/src/operations/directory/gateways.rs +++ b/nym-connect/desktop/src-tauri/src/operations/directory/gateways.rs @@ -101,7 +101,7 @@ pub async fn get_gateways() -> Result> { log::debug!("Received {} gateways", all_gateways.len()); log::trace!("Received: {:#?}", all_gateways); - let gateways_filtered = filter_out_low_performance_gateways(all_gateways.clone())? + let gateways_filtered = filter_out_low_performance_gateways(all_gateways)? .into_iter() .map(|g| Gateway { identity: g.identity().clone(), diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index d53f3a54a5..75fff483b3 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -282,9 +282,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "base64ct" @@ -305,7 +305,7 @@ dependencies = [ "pbkdf2", "rand_core 0.6.4", "ripemd", - "sha2 0.10.7", + "sha2 0.10.8", "subtle 2.4.1", "zeroize", ] @@ -452,7 +452,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" dependencies = [ - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -893,7 +893,7 @@ dependencies = [ "schemars", "serde", "serde-json-wasm", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", ] @@ -1066,6 +1066,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle 2.4.1", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "curve25519-dalek-ng" version = "4.1.1" @@ -1210,6 +1237,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.0", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "der" version = "0.6.1" @@ -1455,7 +1495,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 3.2.0", "ed25519 1.5.3", "rand 0.7.3", "serde", @@ -1469,7 +1509,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 3.2.0", "hashbrown 0.12.3", "hex", "rand_core 0.6.4", @@ -1663,6 +1703,12 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "fiat-crypto" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" + [[package]] name = "field-offset" version = "0.3.6" @@ -2654,6 +2700,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" @@ -2747,7 +2802,7 @@ dependencies = [ "cfg-if", "ecdsa 0.14.8", "elliptic-curve 0.12.3", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -2760,7 +2815,7 @@ dependencies = [ "ecdsa 0.16.8", "elliptic-curve 0.13.5", "once_cell", - "sha2 0.10.7", + "sha2 0.10.8", "signature 2.1.0", ] @@ -3166,7 +3221,7 @@ dependencies = [ "ff 0.11.1", "getrandom 0.2.10", "group 0.11.0", - "itertools", + "itertools 0.10.5", "nym-dkg", "nym-pemstore", "rand 0.8.5", @@ -3243,7 +3298,7 @@ dependencies = [ "rand 0.7.3", "subtle-encoding", "thiserror", - "x25519-dalek", + "x25519-dalek 1.1.1", "zeroize", ] @@ -3396,13 +3451,17 @@ dependencies = [ name = "nym-types" version = "1.0.0" dependencies = [ + "base64 0.21.4", "cosmrs", "cosmwasm-std", + "dashmap", "eyre", - "itertools", + "hmac 0.12.1", + "itertools 0.11.0", "log", "nym-coconut-interface", "nym-config", + "nym-crypto", "nym-mixnet-contract-common", "nym-validator-client", "nym-vesting-contract-common", @@ -3410,10 +3469,12 @@ dependencies = [ "schemars", "serde", "serde_json", - "strum", + "sha2 0.10.8", + "strum 0.25.0", "thiserror", "ts-rs", "url", + "x25519-dalek 2.0.0", ] [[package]] @@ -3434,7 +3495,7 @@ dependencies = [ "eyre", "flate2", "futures", - "itertools", + "itertools 0.10.5", "log", "nym-api-requests", "nym-coconut-bandwidth-contract-common", @@ -3506,7 +3567,7 @@ dependencies = [ "nym-vesting-contract-common", "serde", "serde_json", - "strum", + "strum 0.23.0", "ts-rs", ] @@ -3526,7 +3587,7 @@ dependencies = [ "eyre", "fern", "futures", - "itertools", + "itertools 0.10.5", "k256 0.13.1", "log", "nym-coconut-interface", @@ -3546,7 +3607,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "strum", + "strum 0.23.0", "tauri", "tauri-build", "tauri-codegen", @@ -3878,7 +3939,7 @@ checksum = "56af0a30af74d0445c0bf6d9d051c979b516a1a5af790d251daee76005420a48" dependencies = [ "once_cell", "pest", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -4037,13 +4098,19 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "platforms" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" + [[package]] name = "plist" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdc0001cfea3db57a2e24bc0d818e9e20e554b5f97fabb9bc231dc240269ae06" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "indexmap 1.9.3", "line-wrap", "quick-xml", @@ -4164,7 +4231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", - "itertools", + "itertools 0.10.5", "proc-macro2", "quote", "syn 1.0.109", @@ -4391,7 +4458,7 @@ version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "bytes", "encoding_rs", "futures-core", @@ -4897,9 +4964,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -5031,7 +5098,7 @@ dependencies = [ "bs58 0.4.0", "byteorder", "chacha", - "curve25519-dalek", + "curve25519-dalek 3.2.0", "digest 0.9.0", "hkdf", "hmac 0.11.0", @@ -5122,7 +5189,16 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" dependencies = [ - "strum_macros", + "strum_macros 0.23.1", +] + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros 0.25.3", ] [[package]] @@ -5138,6 +5214,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.28", +] + [[package]] name = "subtle" version = "1.0.0" @@ -5369,7 +5458,7 @@ dependencies = [ "semver 1.0.18", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "tauri-utils", "thiserror", "time", @@ -5494,7 +5583,7 @@ dependencies = [ "serde_bytes", "serde_json", "serde_repr", - "sha2 0.10.7", + "sha2 0.10.8", "signature 2.1.0", "subtle 2.4.1", "subtle-encoding", @@ -6586,7 +6675,7 @@ dependencies = [ "once_cell", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "soup2", "tao", "thiserror", @@ -6634,11 +6723,23 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 3.2.0", "rand_core 0.5.1", "zeroize", ] +[[package]] +name = "x25519-dalek" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" +dependencies = [ + "curve25519-dalek 4.1.1", + "rand_core 0.6.4", + "serde", + "zeroize", +] + [[package]] name = "xattr" version = "1.0.1" diff --git a/nym-wallet/src-tauri/src/operations/simulate/cosmos.rs b/nym-wallet/src-tauri/src/operations/simulate/cosmos.rs index 0f01c60be9..6d538175c4 100644 --- a/nym-wallet/src-tauri/src/operations/simulate/cosmos.rs +++ b/nym-wallet/src-tauri/src/operations/simulate/cosmos.rs @@ -21,7 +21,7 @@ pub async fn simulate_send( let amount = vec![amount_base.into()]; let client = guard.current_client()?; - let from_address = client.nyxd.address().clone(); + let from_address = client.nyxd.address(); // TODO: I'm still not 100% convinced whether this should be exposed here or handled somewhere else in the client code let msg = MsgSend { diff --git a/nym-wallet/src-tauri/src/wallet_storage/mod.rs b/nym-wallet/src-tauri/src/wallet_storage/mod.rs index 1ebfc82b90..ba6e5e7172 100644 --- a/nym-wallet/src-tauri/src/wallet_storage/mod.rs +++ b/nym-wallet/src-tauri/src/wallet_storage/mod.rs @@ -1577,7 +1577,7 @@ mod tests { // name. store_login_with_multiple_accounts_at_file( &wallet_file, - mnemonic1.clone(), + mnemonic1, hd_path.clone(), login_id.clone(), &password, @@ -1589,7 +1589,7 @@ mod tests { append_account_to_login_at_file( &wallet_file, - mnemonic2.clone(), + mnemonic2, hd_path.clone(), login_id.clone(), account2.clone(), @@ -1601,7 +1601,7 @@ mod tests { assert!(matches!( append_account_to_login_at_file( &wallet_file, - mnemonic3.clone(), + mnemonic3, hd_path, login_id, account2, @@ -1967,7 +1967,7 @@ mod tests { &wallet, &login_id, &DEFAULT_FIRST_ACCOUNT_NAME.into(), - &renamed_account.clone(), + &renamed_account, &password, ) .unwrap(); @@ -1975,8 +1975,8 @@ mod tests { let loaded_login = load_existing_login_at_file(&wallet, &login_id, &password).unwrap(); let loaded_accounts = loaded_login.as_multiple_accounts().unwrap(); let expected = vec![WalletAccount::new( - renamed_account.clone(), - MnemonicAccount::new(account1.clone(), hd_path.clone()), + renamed_account, + MnemonicAccount::new(account1, hd_path), )] .into(); assert_eq!(loaded_accounts, &expected); @@ -2047,10 +2047,7 @@ mod tests { DEFAULT_FIRST_ACCOUNT_NAME.into(), MnemonicAccount::new(account1, hd_path.clone()), ), - WalletAccount::new( - renamed_account_id2.clone(), - MnemonicAccount::new(account2, hd_path.clone()), - ), + WalletAccount::new(renamed_account_id2, MnemonicAccount::new(account2, hd_path)), ] .into(); assert_eq!(loaded_accounts, &expected); @@ -2123,10 +2120,7 @@ mod tests { DEFAULT_FIRST_ACCOUNT_NAME.into(), MnemonicAccount::new(account1, hd_path.clone()), ), - WalletAccount::new( - account_id2.clone(), - MnemonicAccount::new(account2, hd_path.clone()), - ), + WalletAccount::new(account_id2, MnemonicAccount::new(account2, hd_path)), ] .into(); assert_eq!(loaded_accounts, &expected); diff --git a/tools/nym-cli/src/validator/account.rs b/tools/nym-cli/src/validator/account.rs index 18aacaa503..b6c422170d 100644 --- a/tools/nym-cli/src/validator/account.rs +++ b/tools/nym-cli/src/validator/account.rs @@ -64,9 +64,7 @@ fn get_account_from_mnemonic( address: Option, ) -> anyhow::Result> { Ok(address.or(Some( - create_signing_client(global_args, network_details)? - .address() - .clone(), + create_signing_client(global_args, network_details)?.address(), ))) } From f328f3fa9e2a394784c8238f9a29ea655cba1842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Thu, 19 Oct 2023 11:36:53 +0100 Subject: [PATCH 024/236] Feature/gateway api (#3970) * Squashing all the changes initial router started expanding the API initial empty openapi/swagger populated build-info endpoint wip: populating rest of swagger missing swagger data + using closure capture for immutable state running the api as a proper task in gateway 'run' fixing some version/feature clashes refactored routes structures initial host information endpoint expanded on gateway-related endpoints signing host information moved all models to separate crate unified http api client routes unification + node api client new generic cache and refresher nym-api caching node self described information removed old cache type temporarily wired up NymContractCache to NodeDescriptionProvider caching self reported host info clients using self-described gateway information fixed request timeouts for wasm fixed wasm builds post rebase fixes cargo fmt brought in wg routes into nym-node router added ErrorResponse for wireguard routes basic swagger support for wg endpoints turns out swagger can be happy with strongly typed requests output type support for wg routes using concrete error type for nym node request error fixed the registration test landing page configurability increased configurability fixed build and lints of other crates added default user-agent to http-api-client reduced severity of gateway details lookup failure changed default http port from 80 to 8080 nym-api using new default port for queries added health endpoint nym-api trying multiple ports for the client using camelcase for node status corrected health endpoint description restored and revamped 'force_tls' flag to filter all gateways that support the wss protocol fixed 'pub_key' path param in open api schema derived Debug on 'NymNodeDescription' ensuring valid public ips added init and run flags to set hostname and public ips fixed listening address being pushed to public ip fixed the positional local flag logging remote ip address of the request updated helper function to query for described gateways enabled tls in gateway client removed hack-opts from mix fetch additional changes after rebasing against origin/develop * clippy * wasm-related target locking * more clippy, but this time in tests --- Cargo.lock | 416 ++++++++------ Cargo.toml | 16 +- common/bandwidth-controller/Cargo.toml | 2 +- common/bin-common/Cargo.toml | 4 + .../bin-common/src/build_information/mod.rs | 2 + .../topology_control/nym_api_provider.rs | 2 +- common/client-core/src/config/mod.rs | 33 +- common/client-core/src/error.rs | 6 + common/client-core/src/init/helpers.rs | 44 +- common/client-core/src/init/mod.rs | 13 +- common/client-libs/gateway-client/Cargo.toml | 3 + .../client-libs/validator-client/Cargo.toml | 1 + .../validator-client/src/client.rs | 19 +- .../validator-client/src/nym_api/error.rs | 23 +- .../validator-client/src/nym_api/mod.rs | 341 +++--------- .../validator-client/src/nym_api/routes.rs | 1 + common/coconut-interface/Cargo.toml | 2 +- .../mixnet/query/query_all_gateways.rs | 6 +- .../mixnet/query/query_all_mixnodes.rs | 6 +- .../validator/mixnet/query/query_all_names.rs | 8 +- .../query/query_all_service_providers.rs | 8 +- .../mixnet-contract/Cargo.toml | 2 +- .../multisig-contract/Cargo.toml | 2 +- .../vesting-contract/Cargo.toml | 2 +- common/credential-storage/Cargo.toml | 2 +- common/crypto/Cargo.toml | 2 +- common/crypto/src/asymmetric/identity/mod.rs | 14 +- common/dkg/Cargo.toml | 6 +- common/http-api-client/Cargo.toml | 25 + common/http-api-client/src/lib.rs | 512 ++++++++++++++++++ common/http-requests/Cargo.toml | 19 - common/http-requests/src/error.rs | 23 - common/http-requests/src/lib.rs | 63 --- common/http-requests/src/socks.rs | 214 -------- common/ledger/Cargo.toml | 2 +- common/mixnode-common/src/verloc/packet.rs | 4 +- common/mobile-storage/Cargo.toml | 2 +- common/network-defaults/Cargo.toml | 2 +- common/network-defaults/src/lib.rs | 3 + common/nymcoconut/Cargo.toml | 4 +- common/nymsphinx/addressing/Cargo.toml | 2 +- common/nymsphinx/anonymous-replies/Cargo.toml | 4 +- common/nymsphinx/chunking/Cargo.toml | 2 +- common/nymsphinx/cover/Cargo.toml | 2 +- common/nymsphinx/forwarding/Cargo.toml | 2 +- common/nymsphinx/framing/Cargo.toml | 2 +- common/nymsphinx/params/Cargo.toml | 2 +- common/nymsphinx/src/receiver.rs | 3 +- common/nymsphinx/types/Cargo.toml | 2 +- common/pemstore/src/lib.rs | 6 +- common/socks5-client-core/Cargo.toml | 4 +- common/socks5/ordered-buffer/Cargo.toml | 2 +- common/statistics/Cargo.toml | 2 +- common/topology/Cargo.toml | 6 +- common/topology/src/gateway.rs | 92 +++- common/topology/src/lib.rs | 32 +- common/topology/src/serde.rs | 17 +- common/types/Cargo.toml | 3 - .../types/src/gateway_client_registration.rs | 117 ---- common/types/src/lib.rs | 4 - common/types/src/wireguard.rs | 71 --- common/wasm/client-core/Cargo.toml | 2 +- common/wireguard-types/Cargo.toml | 48 ++ common/wireguard-types/src/error.rs | 35 ++ common/wireguard-types/src/lib.rs | 15 + common/wireguard-types/src/public_key.rs | 90 +++ common/wireguard-types/src/registration.rs | 231 ++++++++ common/wireguard/Cargo.toml | 2 +- common/wireguard/src/lib.rs | 2 +- common/wireguard/src/registered_peers.rs | 4 +- common/wireguard/src/udp_listener.rs | 6 +- contracts/Cargo.lock | 26 +- contracts/Cargo.toml | 2 + contracts/coconut-bandwidth/Cargo.toml | 2 +- contracts/coconut-dkg/Cargo.toml | 2 +- contracts/coconut-test/Cargo.toml | 2 +- contracts/ephemera/Cargo.toml | 2 +- .../src/support/setup.rs | 2 +- contracts/mixnet/Cargo.toml | 2 +- contracts/mixnet/src/support/tests/mod.rs | 4 +- contracts/multisig/cw4-group/Cargo.toml | 2 +- contracts/name-service/Cargo.toml | 2 +- .../name-service/src/test_helpers/signing.rs | 2 +- .../service-provider-directory/Cargo.toml | 2 +- .../src/test_helpers/signing.rs | 2 +- contracts/vesting/Cargo.toml | 2 +- ephemera/Cargo.toml | 8 +- explorer-api/Cargo.toml | 8 +- explorer-api/explorer-api-requests/Cargo.toml | 2 +- explorer-api/src/mix_node/econ_stats.rs | 1 + gateway/Cargo.toml | 13 +- gateway/gateway-requests/Cargo.toml | 2 +- .../src/registration/handshake/state.rs | 4 +- gateway/src/commands/helpers.rs | 9 +- gateway/src/commands/init.rs | 59 +- gateway/src/commands/run.rs | 64 ++- gateway/src/commands/upgrade_helpers.rs | 30 +- gateway/src/config/mod.rs | 61 ++- gateway/src/config/old_config_v1_1_28.rs | 29 +- gateway/src/config/old_config_v1_1_29.rs | 279 ++++++++++ gateway/src/config/template.rs | 25 +- gateway/src/error.rs | 14 +- gateway/src/http/mod.rs | 141 +++++ gateway/src/main.rs | 4 +- gateway/src/node/http/api/mod.rs | 1 - .../src/node/http/api/v1/client_registry.rs | 105 ---- gateway/src/node/http/api/v1/mod.rs | 1 - gateway/src/node/mod.rs | 20 +- integrations/bity/Cargo.toml | 2 +- nym-api/Cargo.toml | 10 +- nym-api/nym-api-requests/Cargo.toml | 7 +- nym-api/nym-api-requests/src/models.rs | 44 ++ .../src/circulating_supply_api/cache/data.rs | 6 +- .../src/circulating_supply_api/cache/mod.rs | 8 +- nym-api/src/main.rs | 18 + nym-api/src/network/routes.rs | 18 +- nym-api/src/node_describe_cache/mod.rs | 241 +++++++++ nym-api/src/node_status_api/cache/mod.rs | 24 +- .../src/node_status_api/cache/node_sets.rs | 1 + nym-api/src/node_status_api/mod.rs | 13 +- nym-api/src/nym_contract_cache/cache/mod.rs | 72 +-- nym-api/src/nym_contract_cache/routes.rs | 16 +- nym-api/src/nym_nodes/mod.rs | 16 + nym-api/src/nym_nodes/routes.rs | 44 ++ nym-api/src/support/caching/cache.rs | 156 ++++++ nym-api/src/support/caching/mod.rs | 60 +- nym-api/src/support/caching/refresher.rs | 136 +++++ nym-api/src/support/config/mod.rs | 11 + .../src/support/config/old_config_v1_1_21.rs | 1 + nym-api/src/support/http/mod.rs | 6 +- nym-connect/desktop/Cargo.lock | 314 +++++++++-- nym-connect/desktop/src-tauri/Cargo.toml | 2 +- .../src/operations/directory/gateways.rs | 12 +- nym-node/Cargo.toml | 58 ++ nym-node/nym-node-requests/Cargo.toml | 39 ++ nym-node/nym-node-requests/src/api/client.rs | 47 ++ nym-node/nym-node-requests/src/api/mod.rs | 85 +++ .../api/v1/gateway/client_interfaces/mod.rs | 4 + .../client_interfaces/wireguard/mod.rs | 4 + .../client_interfaces/wireguard/models.rs | 7 + .../src/api/v1/gateway/mod.rs | 5 + .../src/api/v1/gateway/models.rs | 38 ++ .../src/api/v1/health/mod.rs | 4 + .../src/api/v1/health/models.rs | 35 ++ .../src/api/v1/mixnode/mod.rs | 4 + .../src/api/v1/mixnode/models.rs | 15 + nym-node/nym-node-requests/src/api/v1/mod.rs | 8 + .../src/api/v1/network_requester/mod.rs | 4 + .../src/api/v1/network_requester/models.rs | 31 ++ .../nym-node-requests/src/api/v1/node/mod.rs | 4 + .../src/api/v1/node/models.rs | 43 ++ nym-node/nym-node-requests/src/error.rs | 19 + nym-node/nym-node-requests/src/lib.rs | 142 +++++ nym-node/src/config/mod.rs | 92 ++++ nym-node/src/config/persistence.rs | 10 + nym-node/src/config/serde_helpers.rs | 29 + nym-node/src/error.rs | 36 ++ nym-node/src/http/middleware/logging.rs | 49 ++ nym-node/src/http/middleware/mod.rs | 4 + nym-node/src/http/mod.rs | 64 +++ nym-node/src/http/router/api/mod.rs | 108 ++++ .../api/v1/gateway/client_interfaces/mod.rs | 123 +++++ .../wireguard/client_registry.rs | 194 +++++++ .../client_interfaces/wireguard}/mod.rs | 195 ++++--- .../src/http/router/api/v1/gateway/mod.rs | 37 ++ .../src/http/router/api/v1/gateway/root.rs | 33 ++ nym-node/src/http/router/api/v1/health.rs | 34 ++ .../src/http/router/api/v1/mixnode/mod.rs | 23 + .../src/http/router/api/v1/mixnode/root.rs | 33 ++ nym-node/src/http/router/api/v1/mod.rs | 39 ++ .../router/api/v1/network_requester/mod.rs | 23 + .../router/api/v1/network_requester/root.rs | 33 ++ .../router/api/v1/node/build_information.rs | 30 + .../router/api/v1/node/host_information.rs | 30 + nym-node/src/http/router/api/v1/node/mod.rs | 46 ++ nym-node/src/http/router/api/v1/node/roles.rs | 30 + nym-node/src/http/router/api/v1/openapi.rs | 65 +++ nym-node/src/http/router/landing_page.rs | 32 ++ nym-node/src/http/router/mod.rs | 136 +++++ nym-node/src/http/router/types.rs | 46 ++ nym-node/src/http/state.rs | 38 ++ nym-node/src/lib.rs | 12 + nym-node/src/wireguard/error.rs | 13 + nym-node/src/wireguard/mod.rs | 8 + nym-node/src/wireguard/types.rs | 5 + nym-outfox/Cargo.toml | 2 +- nym-wallet/Cargo.lock | 72 ++- nym-wallet/src-tauri/Cargo.toml | 2 +- .../src-tauri/src/operations/helpers.rs | 4 +- .../src-tauri/src/operations/mixnet/bond.rs | 1 + .../src/operations/mixnet/delegate.rs | 1 + .../src/operations/nym_api/status.rs | 1 + sdk/rust/nym-sdk/src/mixnet/client.rs | 33 +- .../network-requester/Cargo.toml | 2 +- .../network-statistics/Cargo.toml | 2 +- wasm/mix-fetch/Cargo.toml | 3 +- wasm/mix-fetch/go-mix-conn/build/go_conn.wasm | Bin 8527995 -> 0 bytes wasm/mix-fetch/src/client.rs | 54 +- wasm/mix-fetch/src/fetch.rs | 28 +- wasm/mix-fetch/src/harbourmaster.rs | 112 +--- wasm/mix-fetch/src/helpers.rs | 62 +-- 201 files changed, 5643 insertions(+), 1827 deletions(-) create mode 100644 common/http-api-client/Cargo.toml create mode 100644 common/http-api-client/src/lib.rs delete mode 100644 common/http-requests/Cargo.toml delete mode 100644 common/http-requests/src/error.rs delete mode 100644 common/http-requests/src/lib.rs delete mode 100644 common/http-requests/src/socks.rs delete mode 100644 common/types/src/gateway_client_registration.rs delete mode 100644 common/types/src/wireguard.rs create mode 100644 common/wireguard-types/Cargo.toml create mode 100644 common/wireguard-types/src/error.rs create mode 100644 common/wireguard-types/src/lib.rs create mode 100644 common/wireguard-types/src/public_key.rs create mode 100644 common/wireguard-types/src/registration.rs create mode 100644 gateway/src/config/old_config_v1_1_29.rs create mode 100644 gateway/src/http/mod.rs delete mode 100644 gateway/src/node/http/api/mod.rs delete mode 100644 gateway/src/node/http/api/v1/client_registry.rs delete mode 100644 gateway/src/node/http/api/v1/mod.rs create mode 100644 nym-api/src/node_describe_cache/mod.rs create mode 100644 nym-api/src/nym_nodes/mod.rs create mode 100644 nym-api/src/nym_nodes/routes.rs create mode 100644 nym-api/src/support/caching/cache.rs create mode 100644 nym-api/src/support/caching/refresher.rs create mode 100644 nym-node/Cargo.toml create mode 100644 nym-node/nym-node-requests/Cargo.toml create mode 100644 nym-node/nym-node-requests/src/api/client.rs create mode 100644 nym-node/nym-node-requests/src/api/mod.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/gateway/client_interfaces/mod.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/gateway/client_interfaces/wireguard/mod.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/gateway/client_interfaces/wireguard/models.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/gateway/mod.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/gateway/models.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/health/mod.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/health/models.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/mixnode/mod.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/mixnode/models.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/mod.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/network_requester/mod.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/network_requester/models.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/node/mod.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/node/models.rs create mode 100644 nym-node/nym-node-requests/src/error.rs create mode 100644 nym-node/nym-node-requests/src/lib.rs create mode 100644 nym-node/src/config/mod.rs create mode 100644 nym-node/src/config/persistence.rs create mode 100644 nym-node/src/config/serde_helpers.rs create mode 100644 nym-node/src/error.rs create mode 100644 nym-node/src/http/middleware/logging.rs create mode 100644 nym-node/src/http/middleware/mod.rs create mode 100644 nym-node/src/http/mod.rs create mode 100644 nym-node/src/http/router/api/mod.rs create mode 100644 nym-node/src/http/router/api/v1/gateway/client_interfaces/mod.rs create mode 100644 nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/client_registry.rs rename {gateway/src/node/http => nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard}/mod.rs (51%) create mode 100644 nym-node/src/http/router/api/v1/gateway/mod.rs create mode 100644 nym-node/src/http/router/api/v1/gateway/root.rs create mode 100644 nym-node/src/http/router/api/v1/health.rs create mode 100644 nym-node/src/http/router/api/v1/mixnode/mod.rs create mode 100644 nym-node/src/http/router/api/v1/mixnode/root.rs create mode 100644 nym-node/src/http/router/api/v1/mod.rs create mode 100644 nym-node/src/http/router/api/v1/network_requester/mod.rs create mode 100644 nym-node/src/http/router/api/v1/network_requester/root.rs create mode 100644 nym-node/src/http/router/api/v1/node/build_information.rs create mode 100644 nym-node/src/http/router/api/v1/node/host_information.rs create mode 100644 nym-node/src/http/router/api/v1/node/mod.rs create mode 100644 nym-node/src/http/router/api/v1/node/roles.rs create mode 100644 nym-node/src/http/router/api/v1/openapi.rs create mode 100644 nym-node/src/http/router/landing_page.rs create mode 100644 nym-node/src/http/router/mod.rs create mode 100644 nym-node/src/http/router/types.rs create mode 100644 nym-node/src/http/state.rs create mode 100644 nym-node/src/lib.rs create mode 100644 nym-node/src/wireguard/error.rs create mode 100644 nym-node/src/wireguard/mod.rs create mode 100644 nym-node/src/wireguard/types.rs delete mode 100755 wasm/mix-fetch/go-mix-conn/build/go_conn.wasm diff --git a/Cargo.lock b/Cargo.lock index 987e01c682..24f0e34659 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,7 +37,7 @@ dependencies = [ "actix-utils", "ahash 0.8.3", "base64 0.21.4", - "bitflags 2.4.0", + "bitflags 2.4.1", "brotli", "bytes", "bytestring", @@ -613,7 +613,7 @@ dependencies = [ "log", "parking", "polling", - "rustix 0.37.24", + "rustix 0.37.25", "slab", "socket2 0.4.9", "waker-fn", @@ -663,9 +663,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", @@ -799,18 +799,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "axum-macros" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdca6a10ecad987bda04e95606ef85a5417dcaac1a78455242d72e031e2b6b62" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "syn 2.0.38", -] - [[package]] name = "backtrace" version = "0.3.69" @@ -923,9 +911,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "bitvec" @@ -2085,9 +2073,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.67+curl-8.3.0" +version = "0.4.68+curl-8.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cc35d066510b197a0f72de863736641539957628c8a42e70e27c66849e77c34" +checksum = "b4a0d18d88360e374b16b2273c832b5e57258ffc1d4aa4f96b108e0738d5752f" dependencies = [ "cc", "libc", @@ -2329,7 +2317,7 @@ dependencies = [ "hashbrown 0.14.1", "lock_api", "once_cell", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.9", ] [[package]] @@ -2409,10 +2397,11 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" dependencies = [ + "powerfmt", "serde", ] @@ -2497,7 +2486,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "proc-macro2", "proc-macro2-diagnostics", "quote", @@ -2681,9 +2670,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60f6d271ca33075c88028be6f04d502853d63a5ece419d269c15315d4fc1cf1d" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8 0.10.2", "signature 2.1.0", @@ -2724,7 +2713,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" dependencies = [ "curve25519-dalek 4.1.1", - "ed25519 2.2.2", + "ed25519 2.2.3", "rand_core 0.6.4", "serde", "sha2 0.10.8", @@ -2913,7 +2902,7 @@ dependencies = [ "unsigned-varint", "utoipa", "utoipa-swagger-ui", - "uuid 1.4.1", + "uuid 1.5.0", ] [[package]] @@ -3151,9 +3140,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "libz-sys", @@ -3866,6 +3855,20 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-api-client" +version = "0.1.0" +dependencies = [ + "async-trait", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tracing", + "url", + "wasmtimer", +] + [[package]] name = "http-body" version = "0.4.5" @@ -3877,6 +3880,12 @@ dependencies = [ "pin-project-lite 0.2.13", ] +[[package]] +name = "http-range-header" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" + [[package]] name = "httparse" version = "1.8.0" @@ -4012,16 +4021,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows 0.48.0", + "windows-core", ] [[package]] @@ -4072,9 +4081,9 @@ dependencies = [ [[package]] name = "if-watch" -version = "3.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9465340214b296cd17a0009acdb890d6160010b8adf8f78a00d0d7ab270f79f" +checksum = "bbb892e5777fe09e16f3d44de7802f4daa7267ecbe8c466f19d94e25bb0c303e" dependencies = [ "async-io", "core-foundation", @@ -4086,7 +4095,7 @@ dependencies = [ "rtnetlink", "system-configuration", "tokio", - "windows 0.34.0", + "windows 0.51.1", ] [[package]] @@ -4103,7 +4112,7 @@ checksum = "bfbcff6ae46750b15cc594bfd277b188cbddcfdc1817848f97f03f26f8625b9e" dependencies = [ "cfg-if", "js-sys", - "uuid 1.4.1", + "uuid 1.5.0", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -4298,7 +4307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.3", - "rustix 0.38.18", + "rustix 0.38.19", "windows-sys 0.48.0", ] @@ -5360,9 +5369,9 @@ checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg 1.1.0", "scopeguard", @@ -5552,13 +5561,14 @@ dependencies = [ name = "mix-fetch-wasm" version = "1.2.0" dependencies = [ + "async-trait", "futures", + "http-api-client", "js-sys", "nym-ordered-buffer", "nym-service-providers-common", "nym-socks5-requests", "rand 0.7.3", - "reqwest", "serde", "serde-wasm-bindgen", "thiserror", @@ -5814,7 +5824,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "cfg-if", "libc", ] @@ -5985,6 +5995,7 @@ dependencies = [ "nym-mixnet-contract-common", "nym-multisig-contract-common", "nym-name-service-common", + "nym-node-requests", "nym-node-tester-utils", "nym-pemstore", "nym-service-provider-directory-common", @@ -5995,7 +6006,6 @@ dependencies = [ "nym-vesting-contract-common", "okapi", "pin-project", - "pretty_env_logger", "rand 0.7.3", "rand 0.8.5", "reqwest", @@ -6015,7 +6025,7 @@ dependencies = [ "tokio-stream", "ts-rs", "url", - "uuid 1.4.1", + "uuid 1.5.0", "zeroize", ] @@ -6029,6 +6039,7 @@ dependencies = [ "getset", "nym-coconut-interface", "nym-mixnet-contract-common", + "nym-node-requests", "schemars", "serde", "ts-rs", @@ -6062,12 +6073,14 @@ dependencies = [ "opentelemetry", "opentelemetry-jaeger", "pretty_env_logger", + "schemars", "semver 0.11.0", "serde", "serde_json", "tracing-opentelemetry", "tracing-subscriber", "tracing-tree", + "utoipa", "vergen", ] @@ -6496,9 +6509,6 @@ dependencies = [ "anyhow", "async-trait", "atty", - "axum", - "axum-macros", - "base64 0.21.4", "bip39", "bs58 0.4.0", "clap 4.4.6", @@ -6506,9 +6516,7 @@ dependencies = [ "dashmap", "dirs 4.0.0", "dotenvy", - "fastrand 2.0.1", "futures", - "hmac 0.12.1", "humantime-serde", "hyper", "lazy_static", @@ -6524,6 +6532,7 @@ dependencies = [ "nym-mixnode-common", "nym-network-defaults", "nym-network-requester", + "nym-node", "nym-pemstore", "nym-sphinx", "nym-statistics-common", @@ -6537,7 +6546,6 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "sha2 0.10.8", "sqlx 0.5.13", "subtle-encoding", "thiserror", @@ -6547,7 +6555,6 @@ dependencies = [ "tokio-util", "tower", "url", - "x25519-dalek 2.0.0", "zeroize", ] @@ -6615,21 +6622,6 @@ dependencies = [ "serde", ] -[[package]] -name = "nym-http-requests" -version = "0.1.0" -dependencies = [ - "bytecodec", - "bytes", - "http", - "httpcodec", - "nym-ordered-buffer", - "nym-service-providers-common", - "nym-socks5-requests", - "thiserror", - "url", -] - [[package]] name = "nym-inclusion-probability" version = "0.1.0" @@ -6854,6 +6846,56 @@ dependencies = [ "tokio", ] +[[package]] +name = "nym-node" +version = "0.1.0" +dependencies = [ + "anyhow", + "axum", + "bytes", + "colored", + "dashmap", + "fastrand 2.0.1", + "hmac 0.12.1", + "hyper", + "mime", + "nym-config", + "nym-crypto", + "nym-node-requests", + "nym-task", + "nym-wireguard-types", + "rand 0.7.3", + "serde", + "serde_json", + "serde_yaml", + "thiserror", + "tokio", + "tower", + "tower-http", + "tracing", + "utoipa", + "utoipa-swagger-ui", + "x25519-dalek 2.0.0", +] + +[[package]] +name = "nym-node-requests" +version = "0.1.0" +dependencies = [ + "async-trait", + "base64 0.21.4", + "http-api-client", + "nym-bin-common", + "nym-crypto", + "nym-wireguard-types", + "schemars", + "serde", + "serde_json", + "thiserror", + "tokio", + "utoipa", +] + [[package]] name = "nym-node-tester-utils" version = "0.1.0" @@ -7343,6 +7385,7 @@ dependencies = [ "async-trait", "bs58 0.4.0", "log", + "nym-api-requests", "nym-bin-common", "nym-config", "nym-crypto", @@ -7365,10 +7408,8 @@ name = "nym-types" version = "1.0.0" dependencies = [ "base64 0.21.4", - "boringtun", "cosmrs", "cosmwasm-std", - "dashmap", "eyre", "hmac 0.12.1", "itertools 0.11.0", @@ -7410,6 +7451,7 @@ dependencies = [ "eyre", "flate2", "futures", + "http-api-client", "itertools 0.10.5", "log", "nym-api-requests", @@ -7498,7 +7540,7 @@ dependencies = [ "ip_network_table", "log", "nym-task", - "nym-types", + "nym-wireguard-types", "serde", "tap", "thiserror", @@ -7506,6 +7548,24 @@ dependencies = [ "tokio-tun", ] +[[package]] +name = "nym-wireguard-types" +version = "0.1.0" +dependencies = [ + "base64 0.21.4", + "boringtun", + "dashmap", + "hmac 0.12.1", + "nym-crypto", + "rand 0.7.3", + "serde", + "serde_json", + "sha2 0.10.8", + "thiserror", + "utoipa", + "x25519-dalek 2.0.0", +] + [[package]] name = "object" version = "0.32.1" @@ -7575,7 +7635,7 @@ version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -7730,9 +7790,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.1" +version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "overload" @@ -7782,9 +7842,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" @@ -7804,7 +7864,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.9", ] [[package]] @@ -7823,13 +7883,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "smallvec", "windows-targets 0.48.5", ] @@ -8167,6 +8227,12 @@ dependencies = [ "universal-hash 0.5.1", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -8704,6 +8770,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_users" version = "0.4.3" @@ -8781,14 +8856,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.0" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d119d7c7ca818f8a53c300863d4f87566aac09943aef5b355bb83969dae75d87" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.1", - "regex-syntax 0.8.0", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] @@ -8802,13 +8877,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465c6fc0621e4abc4187a2bda0937bfd4f722c2730b29562e19689ea796c9a4b" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.0", + "regex-syntax 0.8.2", ] [[package]] @@ -8819,9 +8894,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3cbb081b9784b07cceb8824c8583f86db4814d172ab043f3c23f7dc600bf83d" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" @@ -8910,9 +8985,9 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.3" +version = "0.17.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babe80d5c16becf6594aa32ad2be8fe08498e7ae60b77de8df700e67f191d7e" +checksum = "fce3045ffa7c981a6ee93f640b538952e155f1ae3a1a02b84547fc7a56b7059a" dependencies = [ "cc", "getrandom 0.2.10", @@ -9188,9 +9263,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.24" +version = "0.37.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4279d76516df406a8bd37e7dff53fd37d1a093f997a3c34a5c21658c126db06d" +checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035" dependencies = [ "bitflags 1.3.2", "errno", @@ -9202,11 +9277,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.18" +version = "0.38.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a74ee2d7c2581cd139b42447d7d9389b889bdaad3a73f1ebb16f2a3237bb19c" +checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys 0.4.10", @@ -9538,9 +9613,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.188" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" dependencies = [ "serde_derive", ] @@ -9585,9 +9660,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" dependencies = [ "proc-macro2", "quote", @@ -9669,6 +9744,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" +dependencies = [ + "indexmap 2.0.2", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -10439,7 +10527,7 @@ dependencies = [ "cfg-if", "fastrand 2.0.1", "redox_syscall 0.3.5", - "rustix 0.38.18", + "rustix 0.38.19", "windows-sys 0.48.0", ] @@ -10451,7 +10539,7 @@ checksum = "3f0a7d05cf78524782337f8edd55cbc578d159a16ad4affe2135c92f7dbac7f0" dependencies = [ "bytes", "digest 0.10.7", - "ed25519 2.2.2", + "ed25519 2.2.3", "ed25519-consensus", "flex-error", "futures", @@ -10556,7 +10644,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ - "rustix 0.38.18", + "rustix 0.38.19", "windows-sys 0.48.0", ] @@ -10620,13 +10708,14 @@ dependencies = [ [[package]] name = "time" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ "deranged", "itoa", "js-sys", + "powerfmt", "serde", "time-core", "time-macros", @@ -10802,7 +10891,9 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", + "native-tls", "tokio", + "tokio-native-tls", "tungstenite", ] @@ -10963,6 +11054,31 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +dependencies = [ + "bitflags 2.4.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "httpdate", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite 0.2.13", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower-layer" version = "0.3.2" @@ -10977,11 +11093,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9" dependencies = [ - "cfg-if", "log", "pin-project-lite 0.2.13", "tracing-attributes", @@ -10990,9 +11105,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", @@ -11001,9 +11116,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -11231,6 +11346,7 @@ dependencies = [ "http", "httparse", "log", + "native-tls", "rand 0.8.5", "sha1", "thiserror", @@ -11393,6 +11509,12 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" + [[package]] name = "unsigned-varint" version = "0.7.2" @@ -11502,6 +11624,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84614caa239fb25b2bb373a52859ffd94605ceb256eeb1d63436325cf81e3653" dependencies = [ "actix-web", + "axum", "mime_guess", "regex", "rust-embed", @@ -11519,9 +11642,9 @@ checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" [[package]] name = "uuid" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" dependencies = [ "getrandom 0.2.10", "serde", @@ -11822,7 +11945,7 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.3", + "ring 0.17.4", "untrusted 0.9.0", ] @@ -11964,7 +12087,7 @@ dependencies = [ "tokio", "turn", "url", - "uuid 1.4.1", + "uuid 1.5.0", "waitgroup", "webrtc-mdns", "webrtc-util", @@ -12067,7 +12190,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.18", + "rustix 0.38.19", ] [[package]] @@ -12109,22 +12232,28 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.34.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45296b64204227616fdbf2614cefa4c236b98ee64dfaaaa435207ed99fe7829f" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows_aarch64_msvc 0.34.0", - "windows_i686_gnu 0.34.0", - "windows_i686_msvc 0.34.0", - "windows_x86_64_gnu 0.34.0", - "windows_x86_64_msvc 0.34.0", + "windows-targets 0.48.5", ] [[package]] name = "windows" -version = "0.48.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ "windows-targets 0.48.5", ] @@ -12189,12 +12318,6 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" -[[package]] -name = "windows_aarch64_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -12207,12 +12330,6 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" -[[package]] -name = "windows_i686_gnu" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -12225,12 +12342,6 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" -[[package]] -name = "windows_i686_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -12243,12 +12354,6 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" -[[package]] -name = "windows_x86_64_gnu" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -12273,12 +12378,6 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" -[[package]] -name = "windows_x86_64_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -12293,9 +12392,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.16" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907" +checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" dependencies = [ "memchr", ] @@ -12488,11 +12587,10 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" +version = "2.0.9+zstd.1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" dependencies = [ "cc", - "libc", "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index 1c3108ba15..4b18c15e2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ members = [ "common/crypto", "common/dkg", "common/execute", - "common/http-requests", + "common/http-api-client", "common/inclusion-probability", "common/ledger", "common/mixnode-common", @@ -78,6 +78,7 @@ members = [ "common/wasm/storage", "common/wasm/utils", "common/wireguard", + "common/wireguard-types", "explorer-api", "explorer-api/explorer-api-requests", "explorer-api/explorer-client", @@ -93,6 +94,8 @@ members = [ "nym-api", "nym-browser-extension/storage", "nym-api/nym-api-requests", + "nym-node", + "nym-node/nym-node-requests", "nym-outfox", "tools/internal/ssl-inject", "tools/internal/sdk-version-bump", @@ -129,6 +132,8 @@ license = "Apache-2.0" [workspace.dependencies] anyhow = "1.0.71" async-trait = "0.1.68" +axum = "0.6.20" +base64 = "0.21.4" bip39 = { version = "2.0.0", features = ["zeroize"] } boringtun = { git = "https://github.com/cloudflare/boringtun", rev = "e1d6360d6ab4529fc942a078e4c54df107abe2ba" } cfg-if = "1.0.0" @@ -152,22 +157,27 @@ dotenvy = "0.15.6" futures = "0.3.28" generic-array = "0.14.7" getrandom = "0.2.10" +hyper = "0.14.27" k256 = "0.13" lazy_static = "1.4.0" log = "0.4" once_cell = "1.7.2" parking_lot = "0.12.1" rand = "0.8.5" -reqwest = "0.11.18" +reqwest = "0.11.22" +schemars = "0.8.1" serde = "1.0.152" serde_json = "1.0.91" tap = "1.0.1" tendermint-rpc = "0.32" # same version as used by cosmrs -thiserror = "1.0.38" +thiserror = "1.0.48" tokio = "1.24.1" tokio-tungstenite = "0.20.1" +tracing = "0.1.37" tungstenite = { version = "0.20.1", default-features = false } ts-rs = "7.0.0" +utoipa = "3.5.0" +utoipa-swagger-ui = "3.1.5" url = "2.4" zeroize = "1.6.0" diff --git a/common/bandwidth-controller/Cargo.toml b/common/bandwidth-controller/Cargo.toml index 3ce1f01454..7b8e4a51cb 100644 --- a/common/bandwidth-controller/Cargo.toml +++ b/common/bandwidth-controller/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] bip39 = { workspace = true } rand = "0.7.3" -thiserror = "1.0" +thiserror = { workspace = true } url = { workspace = true } nym-coconut-interface = { path = "../coconut-interface" } diff --git a/common/bin-common/Cargo.toml b/common/bin-common/Cargo.toml index 5e817b6afd..7f9ae7fe89 100644 --- a/common/bin-common/Cargo.toml +++ b/common/bin-common/Cargo.toml @@ -15,6 +15,7 @@ clap_complete_fig = "4.0" log = { workspace = true } pretty_env_logger = "0.4.0" semver = "0.11" +schemars = { workspace = true, features = ["preserve_order"], optional = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true, optional = true } @@ -29,6 +30,7 @@ opentelemetry-jaeger = { version = "0.18.0", optional = true, features = [ "isahc_collector_client", ] } tracing-opentelemetry = { version = "0.19.0", optional = true } +utoipa = { workspace = true, optional = true } opentelemetry = { version = "0.19.0", optional = true, features = ["rt-tokio"] } @@ -42,7 +44,9 @@ vergen = { version = "=7.4.3", default-features = false, features = [ [features] default = [] +openapi = ["utoipa"] output_format = ["serde_json"] +bin_info_schema = ["schemars"] tracing = [ "tracing-subscriber", "tracing-tree", diff --git a/common/bin-common/src/build_information/mod.rs b/common/bin-common/src/build_information/mod.rs index 064f8a60fa..06dc1da51c 100644 --- a/common/bin-common/src/build_information/mod.rs +++ b/common/bin-common/src/build_information/mod.rs @@ -81,6 +81,8 @@ impl BinaryBuildInformation { } #[derive(Clone, Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +#[cfg_attr(feature = "bin_info_schema", derive(schemars::JsonSchema))] pub struct BinaryBuildInformationOwned { /// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable. pub binary_name: String, diff --git a/common/client-core/src/client/topology_control/nym_api_provider.rs b/common/client-core/src/client/topology_control/nym_api_provider.rs index 5de16663de..824294793b 100644 --- a/common/client-core/src/client/topology_control/nym_api_provider.rs +++ b/common/client-core/src/client/topology_control/nym_api_provider.rs @@ -69,7 +69,7 @@ impl NymApiTopologyProvider { Ok(mixes) => mixes, }; - let gateways = match self.validator_client.get_cached_gateways().await { + let gateways = match self.validator_client.get_cached_described_gateways().await { Err(err) => { error!("failed to get network gateways - {err}"); return None; diff --git a/common/client-core/src/config/mod.rs b/common/client-core/src/config/mod.rs index cdce63c4c6..ce6d8d4f91 100644 --- a/common/client-core/src/config/mod.rs +++ b/common/client-core/src/config/mod.rs @@ -281,29 +281,24 @@ impl GatewayEndpointConfig { .map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId) } - pub fn from_node(node: nym_topology::gateway::Node, use_tls: bool) -> Self { - // TODO: in the future this shall return a Result and explicit `use_tls` will be removed in favour of the tls info being available on the struct - if use_tls { - Self::from_topology_node_tls(node) + pub fn from_node( + node: nym_topology::gateway::Node, + must_use_tls: bool, + ) -> Result { + let gateway_listener = if must_use_tls { + node.clients_address_tls() + .ok_or(ClientCoreError::UnsupportedWssProtocol { + gateway: node.identity_key.to_base58_string(), + })? } else { - Self::from_topology_node_no_tls(node) - } - } + node.clients_address() + }; - pub fn from_topology_node_no_tls(node: nym_topology::gateway::Node) -> Self { - GatewayEndpointConfig { + Ok(GatewayEndpointConfig { gateway_id: node.identity_key.to_base58_string(), - gateway_listener: node.clients_address(), + gateway_listener, gateway_owner: node.owner, - } - } - - pub fn from_topology_node_tls(node: nym_topology::gateway::Node) -> Self { - GatewayEndpointConfig { - gateway_id: node.identity_key.to_base58_string(), - gateway_listener: node.clients_address_tls(), - gateway_owner: node.owner, - } + }) } } diff --git a/common/client-core/src/error.rs b/common/client-core/src/error.rs index 15b6c1a1bf..8118936730 100644 --- a/common/client-core/src/error.rs +++ b/common/client-core/src/error.rs @@ -126,6 +126,12 @@ pub enum ClientCoreError { #[error("this client has performed gateway initialisation in another session")] NoInitClientPresent, + + #[error("there are no gateways supporting the wss protocol available")] + NoWssGateways, + + #[error("the specified gateway '{gateway}' does not support the wss protocol")] + UnsupportedWssProtocol { gateway: String }, } /// Set of messages that the client can send to listeners via the task manager diff --git a/common/client-core/src/init/helpers.rs b/common/client-core/src/init/helpers.rs index 27516e7750..4b50f0864b 100644 --- a/common/client-core/src/init/helpers.rs +++ b/common/client-core/src/init/helpers.rs @@ -67,7 +67,7 @@ pub async fn current_gateways( log::trace!("Fetching list of gateways from: {nym_api}"); - let gateways = client.get_cached_gateways().await?; + let gateways = client.get_cached_described_gateways().await?; let valid_gateways = gateways .into_iter() .filter_map(|gateway| gateway.try_into().ok()) @@ -174,7 +174,10 @@ async fn measure_latency(gateway: &gateway::Node) -> Result( rng: &mut R, gateways: &[gateway::Node], + must_use_tls: bool, ) -> Result { + let gateways = filter_by_tls(gateways, must_use_tls)?; + info!( "choosing gateway by latency, pinging {} gateways ...", gateways.len() @@ -210,28 +213,57 @@ pub async fn choose_gateway_by_latency( Ok(chosen.gateway.clone()) } +fn filter_by_tls( + gateways: &[gateway::Node], + must_use_tls: bool, +) -> Result, ClientCoreError> { + if must_use_tls { + let filtered = gateways + .iter() + .filter(|g| g.clients_wss_port.is_some()) + .collect::>(); + + if filtered.is_empty() { + return Err(ClientCoreError::NoWssGateways); + } + + Ok(filtered) + } else { + Ok(gateways.iter().collect()) + } +} + pub(super) fn uniformly_random_gateway( rng: &mut R, gateways: &[gateway::Node], + must_use_tls: bool, ) -> Result { - gateways + filter_by_tls(gateways, must_use_tls)? .choose(rng) .ok_or(ClientCoreError::NoGatewaysOnNetwork) - .cloned() + .map(|&r| r.clone()) } pub(super) fn get_specified_gateway( gateway_identity: IdentityKeyRef, gateways: &[gateway::Node], + must_use_tls: bool, ) -> Result { let user_gateway = identity::PublicKey::from_base58_string(gateway_identity) .map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?; - gateways + let gateway = gateways .iter() .find(|gateway| gateway.identity_key == user_gateway) - .ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string())) - .cloned() + .ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string()))?; + + if must_use_tls && gateway.clients_wss_port.is_none() { + return Err(ClientCoreError::UnsupportedWssProtocol { + gateway: gateway_identity.to_string(), + }); + } + + Ok(gateway.clone()) } pub(super) async fn register_with_gateway( diff --git a/common/client-core/src/init/mod.rs b/common/client-core/src/init/mod.rs index 27279cfadb..395fdd45c2 100644 --- a/common/client-core/src/init/mod.rs +++ b/common/client-core/src/init/mod.rs @@ -108,19 +108,20 @@ where let gateway_details = match selection_specification { GatewaySelectionSpecification::UniformRemote { must_use_tls } => { - let gateway = uniformly_random_gateway(&mut rng, &available_gateways)?; - GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls)) + let gateway = uniformly_random_gateway(&mut rng, &available_gateways, must_use_tls)?; + GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls)?) } GatewaySelectionSpecification::RemoteByLatency { must_use_tls } => { - let gateway = choose_gateway_by_latency(&mut rng, &available_gateways).await?; - GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls)) + let gateway = + choose_gateway_by_latency(&mut rng, &available_gateways, must_use_tls).await?; + GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls)?) } GatewaySelectionSpecification::Specified { must_use_tls, identity, } => { - let gateway = get_specified_gateway(&identity, &available_gateways)?; - GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls)) + let gateway = get_specified_gateway(&identity, &available_gateways, must_use_tls)?; + GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls)?) } GatewaySelectionSpecification::Custom { gateway_identity, diff --git a/common/client-libs/gateway-client/Cargo.toml b/common/client-libs/gateway-client/Cargo.toml index 0840d5882f..92b1134512 100644 --- a/common/client-libs/gateway-client/Cargo.toml +++ b/common/client-libs/gateway-client/Cargo.toml @@ -45,6 +45,9 @@ features = ["net", "sync", "time"] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite] workspace = true +# the choice of this particular tls feature was arbitrary; +# if you reckon a different one would be more appropriate, feel free to change it +features = ["native-tls"] # wasm-only dependencies [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen] diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index 4b3533ef7e..e16345f446 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -24,6 +24,7 @@ nym-service-provider-directory-common = { path = "../../cosmwasm-smart-contracts serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } reqwest = { workspace = true, features = ["json"] } +http-api-client = { path = "../../../common/http-api-client"} thiserror = { workspace = true } log = { workspace = true } url = { workspace = true, features = ["serde"] } diff --git a/common/client-libs/validator-client/src/client.rs b/common/client-libs/validator-client/src/client.rs index c5ae83a6bf..a04b8f05d5 100644 --- a/common/client-libs/validator-client/src/client.rs +++ b/common/client-libs/validator-client/src/client.rs @@ -11,7 +11,7 @@ use crate::{ use nym_api_requests::coconut::{ BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse, }; -use nym_api_requests::models::MixNodeBondAnnotated; +use nym_api_requests::models::{DescribedGateway, MixNodeBondAnnotated}; use nym_api_requests::models::{ GatewayCoreStatusResponse, MixnodeCoreStatusResponse, MixnodeStatusResponse, RewardEstimationResponse, StakeSaturationResponse, @@ -19,6 +19,7 @@ use nym_api_requests::models::{ use nym_network_defaults::NymNetworkDetails; use url::Url; +pub use crate::nym_api::NymApiClientExt; pub use nym_mixnet_contract_common::{ mixnode::MixNodeDetails, GatewayBond, IdentityKey, IdentityKeyRef, MixId, }; @@ -147,7 +148,7 @@ impl Client { impl Client { pub fn new_with_rpc_client(config: Config, rpc_client: C) -> Self { - let nym_api_client = nym_api::Client::new(config.api_url.clone()); + let nym_api_client = nym_api::Client::new(config.api_url.clone(), None); Client { nym_api: nym_api_client, @@ -161,7 +162,7 @@ impl Client { where S: OfflineSigner, { - let nym_api_client = nym_api::Client::new(config.api_url.clone()); + let nym_api_client = nym_api::Client::new(config.api_url.clone(), None); Client { nym_api: nym_api_client, @@ -177,7 +178,7 @@ impl Client { } pub fn change_nym_api(&mut self, new_endpoint: Url) { - self.nym_api.change_url(new_endpoint) + self.nym_api.change_base_url(new_endpoint) } pub async fn get_cached_mixnodes(&self) -> Result, ValidatorClientError> { @@ -241,7 +242,7 @@ pub struct NymApiClient { impl NymApiClient { pub fn new(api_url: Url) -> Self { - let nym_api = nym_api::Client::new(api_url); + let nym_api = nym_api::Client::new(api_url, None); NymApiClient { nym_api } } @@ -251,7 +252,7 @@ impl NymApiClient { } pub fn change_nym_api(&mut self, new_endpoint: Url) { - self.nym_api.change_url(new_endpoint); + self.nym_api.change_base_url(new_endpoint); } pub async fn get_cached_active_mixnodes( @@ -274,6 +275,12 @@ impl NymApiClient { Ok(self.nym_api.get_gateways().await?) } + pub async fn get_cached_described_gateways( + &self, + ) -> Result, ValidatorClientError> { + Ok(self.nym_api.get_gateways_described().await?) + } + pub async fn get_gateway_core_status_count( &self, identity: IdentityKeyRef<'_>, diff --git a/common/client-libs/validator-client/src/nym_api/error.rs b/common/client-libs/validator-client/src/nym_api/error.rs index 34053daeaf..554a0826d4 100644 --- a/common/client-libs/validator-client/src/nym_api/error.rs +++ b/common/client-libs/validator-client/src/nym_api/error.rs @@ -1,20 +1,7 @@ +// Copyright 2022-2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use http_api_client::HttpClientError; use nym_api_requests::models::RequestError; -use thiserror::Error; -#[derive(Error, Debug)] -pub enum NymAPIError { - #[error("There was an issue with the REST request - {source}")] - ReqwestClientError { - #[from] - source: reqwest::Error, - }, - - #[error("Not found")] - NotFound, - - #[error("Request failed with error message - {0}")] - GenericRequestFailure(String), - - #[error("The nym API has failed to resolve our request. It returned status code {status} and additional error message: {}", error.message())] - ApiRequestFailure { status: u16, error: RequestError }, -} +pub type NymAPIError = HttpClientError; diff --git a/common/client-libs/validator-client/src/nym_api/mod.rs b/common/client-libs/validator-client/src/nym_api/mod.rs index a7d2f1c1c1..21ac049840 100644 --- a/common/client-libs/validator-client/src/nym_api/mod.rs +++ b/common/client-libs/validator-client/src/nym_api/mod.rs @@ -3,140 +3,38 @@ use crate::nym_api::error::NymAPIError; use crate::nym_api::routes::{CORE_STATUS_COUNT, SINCE_ARG}; +use async_trait::async_trait; +use http_api_client::{ApiClient, NO_PARAMS}; use nym_api_requests::coconut::{ BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse, }; use nym_api_requests::models::{ - ComputeRewardEstParam, GatewayBondAnnotated, GatewayCoreStatusResponse, + ComputeRewardEstParam, DescribedGateway, GatewayBondAnnotated, GatewayCoreStatusResponse, GatewayStatusReportResponse, GatewayUptimeHistoryResponse, InclusionProbabilityResponse, MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse, - MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RequestError, RewardEstimationResponse, + MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RewardEstimationResponse, StakeSaturationResponse, UptimeResponse, }; use nym_mixnet_contract_common::mixnode::MixNodeDetails; use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId}; use nym_name_service_common::response::NamesListResponse; use nym_service_provider_directory_common::response::ServicesListResponse; -use reqwest::{Response, StatusCode}; -use serde::{Deserialize, Serialize}; -use url::Url; pub mod error; pub mod routes; -type PathSegments<'a> = &'a [&'a str]; -type Params<'a, K, V> = &'a [(K, V)]; +pub use http_api_client::Client; -const NO_PARAMS: Params<'_, &'_ str, &'_ str> = &[]; - -#[derive(Clone)] -pub struct Client { - url: Url, - reqwest_client: reqwest::Client, -} - -impl Client { - pub fn new(url: Url) -> Self { - let reqwest_client = reqwest::Client::new(); - Self { - url, - reqwest_client, - } - } - - pub fn change_url(&mut self, new_url: Url) { - self.url = new_url - } - - pub fn current_url(&self) -> &Url { - &self.url - } - - async fn send_get_request( - &self, - path: PathSegments<'_>, - params: Params<'_, K, V>, - ) -> Result - where - K: AsRef, - V: AsRef, - { - let url = create_api_url(&self.url, path, params); - Ok(self.reqwest_client.get(url).send().await?) - } - - async fn query_nym_api( - &self, - path: PathSegments<'_>, - params: Params<'_, K, V>, - ) -> Result - where - for<'a> T: Deserialize<'a>, - K: AsRef, - V: AsRef, - { - let res = self.send_get_request(path, params).await?; - if res.status().is_success() { - Ok(res.json().await?) - } else if res.status() == StatusCode::NOT_FOUND { - Err(NymAPIError::NotFound) - } else { - Err(NymAPIError::GenericRequestFailure(res.text().await?)) - } - } - - // This works for endpoints returning Result, ErrorResponse> - async fn query_nym_api_fallible( - &self, - path: PathSegments<'_>, - params: Params<'_, K, V>, - ) -> Result - where - for<'a> T: Deserialize<'a>, - K: AsRef, - V: AsRef, - { - let res = self.send_get_request(path, params).await?; - let status = res.status(); - if res.status().is_success() { - Ok(res.json().await?) - } else { - let request_error: RequestError = res.json().await?; - Err(NymAPIError::ApiRequestFailure { - status: status.as_u16(), - error: request_error, - }) - } - } - - async fn post_nym_api( - &self, - path: PathSegments<'_>, - params: Params<'_, K, V>, - json_body: &B, - ) -> Result - where - B: Serialize + ?Sized, - for<'a> T: Deserialize<'a>, - K: AsRef, - V: AsRef, - { - let url = create_api_url(&self.url, path, params); - let response = self.reqwest_client.post(url).json(json_body).send().await?; - if response.status().is_success() { - Ok(response.json().await?) - } else { - Err(NymAPIError::GenericRequestFailure(response.text().await?)) - } - } - - pub async fn get_mixnodes(&self) -> Result, NymAPIError> { - self.query_nym_api(&[routes::API_VERSION, routes::MIXNODES], NO_PARAMS) +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +pub trait NymApiClientExt: ApiClient { + async fn get_mixnodes(&self) -> Result, NymAPIError> { + self.get_json(&[routes::API_VERSION, routes::MIXNODES], NO_PARAMS) .await } - pub async fn get_mixnodes_detailed(&self) -> Result, NymAPIError> { - self.query_nym_api( + async fn get_mixnodes_detailed(&self) -> Result, NymAPIError> { + self.get_json( &[ routes::API_VERSION, routes::STATUS, @@ -148,8 +46,8 @@ impl Client { .await } - pub async fn get_gateways_detailed(&self) -> Result, NymAPIError> { - self.query_nym_api( + async fn get_gateways_detailed(&self) -> Result, NymAPIError> { + self.get_json( &[ routes::API_VERSION, routes::STATUS, @@ -161,10 +59,10 @@ impl Client { .await } - pub async fn get_mixnodes_detailed_unfiltered( + async fn get_mixnodes_detailed_unfiltered( &self, ) -> Result, NymAPIError> { - self.query_nym_api( + self.get_json( &[ routes::API_VERSION, routes::STATUS, @@ -176,23 +74,29 @@ impl Client { .await } - pub async fn get_gateways(&self) -> Result, NymAPIError> { - self.query_nym_api(&[routes::API_VERSION, routes::GATEWAYS], NO_PARAMS) + async fn get_gateways(&self) -> Result, NymAPIError> { + self.get_json(&[routes::API_VERSION, routes::GATEWAYS], NO_PARAMS) .await } - pub async fn get_active_mixnodes(&self) -> Result, NymAPIError> { - self.query_nym_api( + async fn get_gateways_described(&self) -> Result, NymAPIError> { + self.get_json( + &[routes::API_VERSION, routes::GATEWAYS, routes::DESCRIBED], + NO_PARAMS, + ) + .await + } + + async fn get_active_mixnodes(&self) -> Result, NymAPIError> { + self.get_json( &[routes::API_VERSION, routes::MIXNODES, routes::ACTIVE], NO_PARAMS, ) .await } - pub async fn get_active_mixnodes_detailed( - &self, - ) -> Result, NymAPIError> { - self.query_nym_api( + async fn get_active_mixnodes_detailed(&self) -> Result, NymAPIError> { + self.get_json( &[ routes::API_VERSION, routes::STATUS, @@ -205,19 +109,19 @@ impl Client { .await } - pub async fn get_rewarded_mixnodes(&self) -> Result, NymAPIError> { - self.query_nym_api( + async fn get_rewarded_mixnodes(&self) -> Result, NymAPIError> { + self.get_json( &[routes::API_VERSION, routes::MIXNODES, routes::REWARDED], NO_PARAMS, ) .await } - pub async fn get_mixnode_report( + async fn get_mixnode_report( &self, mix_id: MixId, ) -> Result { - self.query_nym_api( + self.get_json( &[ routes::API_VERSION, routes::STATUS, @@ -230,11 +134,11 @@ impl Client { .await } - pub async fn get_gateway_report( + async fn get_gateway_report( &self, identity: IdentityKeyRef<'_>, ) -> Result { - self.query_nym_api( + self.get_json( &[ routes::API_VERSION, routes::STATUS, @@ -247,11 +151,11 @@ impl Client { .await } - pub async fn get_mixnode_history( + async fn get_mixnode_history( &self, mix_id: MixId, ) -> Result { - self.query_nym_api( + self.get_json( &[ routes::API_VERSION, routes::STATUS, @@ -264,11 +168,11 @@ impl Client { .await } - pub async fn get_gateway_history( + async fn get_gateway_history( &self, identity: IdentityKeyRef<'_>, ) -> Result { - self.query_nym_api( + self.get_json( &[ routes::API_VERSION, routes::STATUS, @@ -281,10 +185,10 @@ impl Client { .await } - pub async fn get_rewarded_mixnodes_detailed( + async fn get_rewarded_mixnodes_detailed( &self, ) -> Result, NymAPIError> { - self.query_nym_api( + self.get_json( &[ routes::API_VERSION, routes::STATUS, @@ -297,13 +201,13 @@ impl Client { .await } - pub async fn get_gateway_core_status_count( + async fn get_gateway_core_status_count( &self, identity: IdentityKeyRef<'_>, since: Option, ) -> Result { if let Some(since) = since { - self.query_nym_api( + self.get_json( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -315,7 +219,7 @@ impl Client { ) .await } else { - self.query_nym_api( + self.get_json( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -328,13 +232,13 @@ impl Client { } } - pub async fn get_mixnode_core_status_count( + async fn get_mixnode_core_status_count( &self, mix_id: MixId, since: Option, ) -> Result { if let Some(since) = since { - self.query_nym_api( + self.get_json( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -346,7 +250,7 @@ impl Client { ) .await } else { - self.query_nym_api( + self.get_json( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -360,11 +264,11 @@ impl Client { } } - pub async fn get_mixnode_status( + async fn get_mixnode_status( &self, mix_id: MixId, ) -> Result { - self.query_nym_api( + self.get_json( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -377,11 +281,11 @@ impl Client { .await } - pub async fn get_mixnode_reward_estimation( + async fn get_mixnode_reward_estimation( &self, mix_id: MixId, ) -> Result { - self.query_nym_api_fallible( + self.get_json( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -394,12 +298,12 @@ impl Client { .await } - pub async fn compute_mixnode_reward_estimation( + async fn compute_mixnode_reward_estimation( &self, mix_id: MixId, request_body: &ComputeRewardEstParam, ) -> Result { - self.post_nym_api( + self.post_json( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -413,11 +317,11 @@ impl Client { .await } - pub async fn get_mixnode_stake_saturation( + async fn get_mixnode_stake_saturation( &self, mix_id: MixId, ) -> Result { - self.query_nym_api_fallible( + self.get_json( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -430,11 +334,11 @@ impl Client { .await } - pub async fn get_mixnode_inclusion_probability( + async fn get_mixnode_inclusion_probability( &self, mix_id: MixId, ) -> Result { - self.query_nym_api_fallible( + self.get_json( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -447,11 +351,8 @@ impl Client { .await } - pub async fn get_mixnode_avg_uptime( - &self, - mix_id: MixId, - ) -> Result { - self.query_nym_api_fallible( + async fn get_mixnode_avg_uptime(&self, mix_id: MixId) -> Result { + self.get_json( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -464,11 +365,11 @@ impl Client { .await } - pub async fn blind_sign( + async fn blind_sign( &self, request_body: &BlindSignRequestBody, ) -> Result { - self.post_nym_api( + self.post_json( &[ routes::API_VERSION, routes::COCONUT_ROUTES, @@ -481,11 +382,11 @@ impl Client { .await } - pub async fn verify_bandwidth_credential( + async fn verify_bandwidth_credential( &self, request_body: &VerifyCredentialBody, ) -> Result { - self.post_nym_api( + self.post_json( &[ routes::API_VERSION, routes::COCONUT_ROUTES, @@ -498,118 +399,20 @@ impl Client { .await } - pub async fn get_service_providers(&self) -> Result { + async fn get_service_providers(&self) -> Result { log::trace!("Getting service providers"); - self.query_nym_api(&[routes::API_VERSION, routes::SERVICE_PROVIDERS], NO_PARAMS) + self.get_json(&[routes::API_VERSION, routes::SERVICE_PROVIDERS], NO_PARAMS) .await } - //pub async fn get_registered_names(&self) -> Result, NymAPIError> { - pub async fn get_registered_names(&self) -> Result { + //async fn get_registered_names(&self) -> Result, NymAPIError> { + async fn get_registered_names(&self) -> Result { log::trace!("Getting registered names"); - self.query_nym_api(&[routes::API_VERSION, routes::REGISTERED_NAMES], NO_PARAMS) + self.get_json(&[routes::API_VERSION, routes::REGISTERED_NAMES], NO_PARAMS) .await } } -// utility function that should solve the double slash problem in validator API forever. -fn create_api_url, V: AsRef>( - base: &Url, - segments: PathSegments<'_>, - params: Params<'_, K, V>, -) -> Url { - let mut url = base.clone(); - let mut path_segments = url - .path_segments_mut() - .expect("provided validator url does not have a base!"); - for segment in segments { - let segment = segment.strip_prefix('/').unwrap_or(segment); - let segment = segment.strip_suffix('/').unwrap_or(segment); - - path_segments.push(segment); - } - // I don't understand why compiler couldn't figure out that it's no longer used - // and can be dropped - drop(path_segments); - - if !params.is_empty() { - url.query_pairs_mut().extend_pairs(params); - } - - url -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn creating_api_path() { - let base_url: Url = "http://foomp.com".parse().unwrap(); - - // works with 1 segment - assert_eq!( - "http://foomp.com/foo", - create_api_url(&base_url, &["foo"], NO_PARAMS).as_str() - ); - - // works with 2 segments - assert_eq!( - "http://foomp.com/foo/bar", - create_api_url(&base_url, &["foo", "bar"], NO_PARAMS).as_str() - ); - - // works with leading slash - assert_eq!( - "http://foomp.com/foo", - create_api_url(&base_url, &["/foo"], NO_PARAMS).as_str() - ); - assert_eq!( - "http://foomp.com/foo/bar", - create_api_url(&base_url, &["/foo", "bar"], NO_PARAMS).as_str() - ); - assert_eq!( - "http://foomp.com/foo/bar", - create_api_url(&base_url, &["foo", "/bar"], NO_PARAMS).as_str() - ); - - // works with trailing slash - assert_eq!( - "http://foomp.com/foo", - create_api_url(&base_url, &["foo/"], NO_PARAMS).as_str() - ); - assert_eq!( - "http://foomp.com/foo/bar", - create_api_url(&base_url, &["foo/", "bar"], NO_PARAMS).as_str() - ); - assert_eq!( - "http://foomp.com/foo/bar", - create_api_url(&base_url, &["foo", "bar/"], NO_PARAMS).as_str() - ); - - // works with both leading and trailing slash - assert_eq!( - "http://foomp.com/foo", - create_api_url(&base_url, &["/foo/"], NO_PARAMS).as_str() - ); - assert_eq!( - "http://foomp.com/foo/bar", - create_api_url(&base_url, &["/foo/", "/bar/"], NO_PARAMS).as_str() - ); - - // adds params - assert_eq!( - "http://foomp.com/foo/bar?foomp=baz", - create_api_url(&base_url, &["foo", "bar"], &[("foomp", "baz")]).as_str() - ); - assert_eq!( - "http://foomp.com/foo/bar?arg1=val1&arg2=val2", - create_api_url( - &base_url, - &["/foo/", "/bar/"], - &[("arg1", "val1"), ("arg2", "val2")] - ) - .as_str() - ); - } -} +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +impl NymApiClientExt for Client {} diff --git a/common/client-libs/validator-client/src/nym_api/routes.rs b/common/client-libs/validator-client/src/nym_api/routes.rs index fd97047b6a..df063a114d 100644 --- a/common/client-libs/validator-client/src/nym_api/routes.rs +++ b/common/client-libs/validator-client/src/nym_api/routes.rs @@ -6,6 +6,7 @@ use nym_network_defaults::NYM_API_VERSION; pub const API_VERSION: &str = NYM_API_VERSION; pub const MIXNODES: &str = "mixnodes"; pub const GATEWAYS: &str = "gateways"; +pub const DESCRIBED: &str = "described"; pub const DETAILED: &str = "detailed"; pub const DETAILED_UNFILTERED: &str = "detailed-unfiltered"; diff --git a/common/coconut-interface/Cargo.toml b/common/coconut-interface/Cargo.toml index 8f62dcc9b5..e749824e51 100644 --- a/common/coconut-interface/Cargo.toml +++ b/common/coconut-interface/Cargo.toml @@ -8,6 +8,6 @@ description = "Crutch library until there is proper SerDe support for coconut st bs58 = "0.4.0" getset = "0.1.1" serde = { workspace = true, features = ["derive"] } -thiserror = "1" +thiserror = { workspace = true } nym-coconut = {path = "../nymcoconut" } diff --git a/common/commands/src/validator/mixnet/query/query_all_gateways.rs b/common/commands/src/validator/mixnet/query/query_all_gateways.rs index 17f1d4d48d..16f0e44285 100644 --- a/common/commands/src/validator/mixnet/query/query_all_gateways.rs +++ b/common/commands/src/validator/mixnet/query/query_all_gateways.rs @@ -1,11 +1,11 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use clap::Parser; -use comfy_table::Table; - use crate::context::QueryClientWithNyxd; use crate::utils::{pretty_cosmwasm_coin, show_error}; +use clap::Parser; +use comfy_table::Table; +use nym_validator_client::client::NymApiClientExt; #[derive(Debug, Parser)] pub struct Args { diff --git a/common/commands/src/validator/mixnet/query/query_all_mixnodes.rs b/common/commands/src/validator/mixnet/query/query_all_mixnodes.rs index 3b23f2092e..9bb20cc8d4 100644 --- a/common/commands/src/validator/mixnet/query/query_all_mixnodes.rs +++ b/common/commands/src/validator/mixnet/query/query_all_mixnodes.rs @@ -1,11 +1,11 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use clap::Parser; -use comfy_table::Table; - use crate::context::QueryClientWithNyxd; use crate::utils::{pretty_decimal_with_denom, show_error}; +use clap::Parser; +use comfy_table::Table; +use nym_validator_client::client::NymApiClientExt; #[derive(Debug, Parser)] pub struct Args { diff --git a/common/commands/src/validator/mixnet/query/query_all_names.rs b/common/commands/src/validator/mixnet/query/query_all_names.rs index 5a17cad30d..fa75752c6c 100644 --- a/common/commands/src/validator/mixnet/query/query_all_names.rs +++ b/common/commands/src/validator/mixnet/query/query_all_names.rs @@ -1,12 +1,12 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use clap::Parser; -use comfy_table::Table; -use nym_validator_client::nym_api::error::NymAPIError; - use crate::context::QueryClientWithNyxd; use crate::utils::show_error; +use clap::Parser; +use comfy_table::Table; +use nym_validator_client::client::NymApiClientExt; +use nym_validator_client::nym_api::error::NymAPIError; #[derive(Debug, Parser)] pub struct Args { diff --git a/common/commands/src/validator/mixnet/query/query_all_service_providers.rs b/common/commands/src/validator/mixnet/query/query_all_service_providers.rs index e13f483f93..74ef07a637 100644 --- a/common/commands/src/validator/mixnet/query/query_all_service_providers.rs +++ b/common/commands/src/validator/mixnet/query/query_all_service_providers.rs @@ -1,12 +1,12 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use clap::Parser; -use comfy_table::Table; -use nym_validator_client::nym_api::error::NymAPIError; - use crate::context::QueryClientWithNyxd; use crate::utils::show_error; +use clap::Parser; +use comfy_table::Table; +use nym_validator_client::client::NymApiClientExt; +use nym_validator_client::nym_api::error::NymAPIError; #[derive(Debug, Parser)] pub struct Args { diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml index e82be77e29..205b3d7d01 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml @@ -18,7 +18,7 @@ serde_repr = "0.1" # we still have to preserve that import for `JsonSchema` for `Layer` type (since we can't use cw_serde macro due to custom serde impl) schemars = "0.8" -thiserror = "1.0" +thiserror = { workspace = true } contracts-common = { path = "../contracts-common", package = "nym-contracts-common", version = "0.5.0" } serde-json-wasm = { workspace = true } humantime-serde = "1.1.1" diff --git a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml index d419e25086..6ffc7deb14 100644 --- a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml @@ -14,4 +14,4 @@ cosmwasm-schema = { workspace = true } cosmwasm-std = { workspace = true } schemars = "0.8" serde = { version = "1.0.103", default-features = false, features = ["derive"] } -thiserror = { version = "1.0.23" } +thiserror = { workspace = true } diff --git a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml index 3fd7e8a377..a975df45ae 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml @@ -14,7 +14,7 @@ cw2 = { workspace = true, optional = true } mixnet-contract-common = { path = "../mixnet-contract", package = "nym-mixnet-contract-common", version = "0.6.0" } contracts-common = { path = "../contracts-common", package = "nym-contracts-common", version = "0.5.0" } serde = { version = "1.0", features = ["derive"] } -thiserror = "1.0" +thiserror = { workspace = true } ts-rs = { workspace = true, optional = true} [features] diff --git a/common/credential-storage/Cargo.toml b/common/credential-storage/Cargo.toml index f86d919197..a5c6f9e71d 100644 --- a/common/credential-storage/Cargo.toml +++ b/common/credential-storage/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" async-trait = { workspace = true } log = { workspace = true } -thiserror = "1.0" +thiserror = { workspace = true } tokio = { version = "1.24.1", features = ["sync"]} [target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx] diff --git a/common/crypto/Cargo.toml b/common/crypto/Cargo.toml index 992005f2d4..481ecbf1f7 100644 --- a/common/crypto/Cargo.toml +++ b/common/crypto/Cargo.toml @@ -23,7 +23,7 @@ rand = { version = "0.7.3", features = ["wasm-bindgen"], optional = true } serde_bytes = { version = "0.11.6", optional = true } serde_crate = { version = "1.0", optional = true, default_features = false, features = ["derive"], package = "serde" } subtle-encoding = { version = "0.5", features = ["bech32-preview"]} -thiserror = "1.0.37" +thiserror = { workspace = true } zeroize = { workspace = true, optional = true, features = ["zeroize_derive"] } # internal diff --git a/common/crypto/src/asymmetric/identity/mod.rs b/common/crypto/src/asymmetric/identity/mod.rs index ae001c2df6..a56abdee32 100644 --- a/common/crypto/src/asymmetric/identity/mod.rs +++ b/common/crypto/src/asymmetric/identity/mod.rs @@ -145,8 +145,12 @@ impl PublicKey { Self::from_bytes(&bytes) } - pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> { - self.0.verify(message, &signature.0) + pub fn verify>( + &self, + message: M, + signature: &Signature, + ) -> Result<(), SignatureError> { + self.0.verify(message.as_ref(), &signature.0) } } @@ -239,16 +243,16 @@ impl PrivateKey { Self::from_bytes(&bytes) } - pub fn sign(&self, message: &[u8]) -> Signature { + pub fn sign>(&self, message: M) -> Signature { let expanded_secret_key = ed25519_dalek::ExpandedSecretKey::from(&self.0); let public_key: PublicKey = self.into(); - let sig = expanded_secret_key.sign(message, &public_key.0); + let sig = expanded_secret_key.sign(message.as_ref(), &public_key.0); Signature(sig) } /// Signs text with the provided Ed25519 private key, returning a base58 signature pub fn sign_text(&self, text: &str) -> String { - let signature_bytes = self.sign(text.as_ref()).to_bytes(); + let signature_bytes = self.sign(text).to_bytes(); bs58::encode(signature_bytes).into_string() } } diff --git a/common/dkg/Cargo.toml b/common/dkg/Cargo.toml index dc1f4c29e9..26808724bf 100644 --- a/common/dkg/Cargo.toml +++ b/common/dkg/Cargo.toml @@ -21,10 +21,10 @@ rand = { version = "0.8.5", default-features = false} rand_chacha = "0.3" rand_core = "0.6.3" sha2 = "0.9" -serde = "1.0" +serde = { workspace = true } serde_derive = "1.0" -thiserror = "1.0" -zeroize = { version = "1.4", features = ["zeroize_derive"] } +thiserror = { workspace = true } +zeroize = { workspace = true, features = ["zeroize_derive"] } nym-pemstore = { path = "../pemstore" } diff --git a/common/http-api-client/Cargo.toml b/common/http-api-client/Cargo.toml new file mode 100644 index 0000000000..ac43b59576 --- /dev/null +++ b/common/http-api-client/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "http-api-client" +version = "0.1.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-trait = { workspace = true } +reqwest = { workspace = true, features = ["json"] } +url = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +tracing = { workspace = true } + +# for request timeout until https://github.com/seanmonstar/reqwest/issues/1135 is fixed +[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer] +workspace = true +features = ["tokio"] \ No newline at end of file diff --git a/common/http-api-client/src/lib.rs b/common/http-api-client/src/lib.rs new file mode 100644 index 0000000000..2d816cc142 --- /dev/null +++ b/common/http-api-client/src/lib.rs @@ -0,0 +1,512 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use async_trait::async_trait; +use reqwest::{IntoUrl, Response, StatusCode}; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; +use std::fmt::Display; +use std::time::Duration; +use thiserror::Error; +use tracing::warn; +use url::Url; + +pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(3); + +pub type PathSegments<'a> = &'a [&'a str]; +pub type Params<'a, K, V> = &'a [(K, V)]; + +pub const NO_PARAMS: Params<'_, &'_ str, &'_ str> = &[]; + +#[derive(Debug, Error)] +pub enum HttpClientError { + #[error("there was an issue with the REST request: {source}")] + ReqwestClientError { + #[from] + source: reqwest::Error, + }, + + #[error("provided url is malformed: {source}")] + MalformedUrl { + #[from] + source: url::ParseError, + }, + + #[error("the requested resource could not be found")] + NotFound, + + #[error("request failed with error message: {0}")] + GenericRequestFailure(String), + + #[error("the request failed with status '{status}'. no additional error message provided")] + RequestFailure { status: StatusCode }, + + #[error("the returned response was empty. status: '{status}'")] + EmptyResponse { status: StatusCode }, + + #[error("failed to resolve request. status: '{status}', additional error message: {error}")] + EndpointFailure { status: StatusCode, error: E }, + + #[cfg(target_arch = "wasm32")] + #[error("the request has timed out")] + RequestTimeout, +} + +/// A simple extendable client wrapper for http request with extra url sanitization. +#[derive(Debug, Clone)] +pub struct Client { + base_url: Url, + reqwest_client: reqwest::Client, + + #[cfg(target_arch = "wasm32")] + request_timeout: Duration, +} + +impl Client { + // no timeout until https://github.com/seanmonstar/reqwest/issues/1135 is fixed + pub fn new(base_url: Url, timeout: Option) -> Self { + #[cfg(target_arch = "wasm32")] + let reqwest_client = reqwest::Client::new(); + + // TODO: we should probably be propagating the error rather than panicking, + // but that'd break bunch of things due to type changes + #[cfg(not(target_arch = "wasm32"))] + let reqwest_client = reqwest::ClientBuilder::new() + .timeout(timeout.unwrap_or(DEFAULT_TIMEOUT)) + .user_agent(format!("nym-http-api-client/{}", env!("CARGO_PKG_VERSION"))) + .build() + .expect("Client::new()"); + + Client { + base_url, + reqwest_client, + + #[cfg(target_arch = "wasm32")] + request_timeout: timeout.unwrap_or(DEFAULT_TIMEOUT), + } + } + + pub fn new_url(url: U, timeout: Option) -> Result> + where + U: IntoUrl, + E: Display, + { + // a naive check: if the provided URL does not start with http(s), add that scheme + let str_url = url.as_str(); + + if !str_url.starts_with("http") { + let alt = format!("http://{str_url}"); + warn!("the provided url ('{str_url}') does not contain scheme information. Changing it to '{alt}' ..."); + // TODO: or should we maybe default to https? + Self::new_url(alt, timeout) + } else { + Ok(Self::new(url.into_url()?, timeout)) + } + } + + pub fn change_base_url(&mut self, new_url: Url) { + self.base_url = new_url + } + + pub fn current_url(&self) -> &Url { + &self.base_url + } + + async fn send_get_request( + &self, + path: PathSegments<'_>, + params: Params<'_, K, V>, + ) -> Result> + where + K: AsRef, + V: AsRef, + E: Display, + { + let url = sanitize_url(&self.base_url, path, params); + + #[cfg(target_arch = "wasm32")] + { + Ok( + wasmtimer::tokio::timeout( + self.request_timeout, + self.reqwest_client.get(url).send(), + ) + .await + .map_err(|_timeout| HttpClientError::RequestTimeout)??, + ) + } + + #[cfg(not(target_arch = "wasm32"))] + { + Ok(self.reqwest_client.get(url).send().await?) + } + } + + async fn send_post_request( + &self, + path: PathSegments<'_>, + params: Params<'_, K, V>, + json_body: &B, + ) -> Result> + where + B: Serialize + ?Sized, + K: AsRef, + V: AsRef, + E: Display, + { + let url = sanitize_url(&self.base_url, path, params); + + #[cfg(target_arch = "wasm32")] + { + Ok(wasmtimer::tokio::timeout( + self.request_timeout, + self.reqwest_client.post(url).json(json_body).send(), + ) + .await + .map_err(|_timeout| HttpClientError::RequestTimeout)??) + } + + #[cfg(not(target_arch = "wasm32"))] + { + Ok(self.reqwest_client.post(url).json(json_body).send().await?) + } + } + + pub async fn get_json( + &self, + path: PathSegments<'_>, + params: Params<'_, K, V>, + ) -> Result> + where + for<'a> T: Deserialize<'a>, + K: AsRef, + V: AsRef, + E: Display + DeserializeOwned, + { + let res = self.send_get_request(path, params).await?; + parse_response(res, false).await + } + + pub async fn post_json( + &self, + path: PathSegments<'_>, + params: Params<'_, K, V>, + json_body: &B, + ) -> Result> + where + B: Serialize + ?Sized, + for<'a> T: Deserialize<'a>, + K: AsRef, + V: AsRef, + E: Display + DeserializeOwned, + { + let res = self.send_post_request(path, params, json_body).await?; + parse_response(res, true).await + } + + pub async fn get_json_endpoint(&self, endpoint: S) -> Result> + where + for<'a> T: Deserialize<'a>, + E: Display + DeserializeOwned, + S: AsRef, + { + #[cfg(target_arch = "wasm32")] + let res = { + wasmtimer::tokio::timeout( + self.request_timeout, + self.reqwest_client + .get(self.base_url.join(endpoint.as_ref())?) + .send(), + ) + .await + .map_err(|_timeout| HttpClientError::RequestTimeout)?? + }; + + #[cfg(not(target_arch = "wasm32"))] + let res = { + self.reqwest_client + .get(self.base_url.join(endpoint.as_ref())?) + .send() + .await? + }; + + parse_response(res, false).await + } + + pub async fn post_json_endpoint( + &self, + endpoint: S, + json_body: &B, + ) -> Result> + where + B: Serialize + ?Sized, + for<'a> T: Deserialize<'a>, + E: Display + DeserializeOwned, + S: AsRef, + { + #[cfg(target_arch = "wasm32")] + let res = { + wasmtimer::tokio::timeout( + self.request_timeout, + self.reqwest_client + .post(self.base_url.join(endpoint.as_ref())?) + .json(json_body) + .send(), + ) + .await + .map_err(|_timeout| HttpClientError::RequestTimeout)?? + }; + + #[cfg(not(target_arch = "wasm32"))] + let res = { + self.reqwest_client + .post(self.base_url.join(endpoint.as_ref())?) + .json(json_body) + .send() + .await? + }; + + parse_response(res, true).await + } +} + +// define those methods on the trait for nicer extensions (and not having to type the thing twice) +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +pub trait ApiClient { + /// 'get' json data from the segment-defined path, i.e. for example `["api", "v1", "mixnodes"]`, + /// with tuple defined key-value parameters, i.e. for example `[("since", "12345")]` + async fn get_json( + &self, + path: PathSegments<'_>, + params: Params<'_, K, V>, + ) -> Result> + where + for<'a> T: Deserialize<'a>, + K: AsRef + Sync, + V: AsRef + Sync, + E: Display + DeserializeOwned; + + async fn post_json( + &self, + path: PathSegments<'_>, + params: Params<'_, K, V>, + json_body: &B, + ) -> Result> + where + B: Serialize + ?Sized + Sync, + for<'a> T: Deserialize<'a>, + K: AsRef + Sync, + V: AsRef + Sync, + E: Display + DeserializeOwned; + + /// `get` json data from the provided absolute endpoint, i.e. for example `"/api/v1/mixnodes?since=12345"` + async fn get_json_from(&self, endpoint: S) -> Result> + where + for<'a> T: Deserialize<'a>, + E: Display + DeserializeOwned, + S: AsRef + Sync + Send; + + async fn post_json_data_to( + &self, + endpoint: S, + json_body: &B, + ) -> Result> + where + B: Serialize + ?Sized + Sync, + for<'a> T: Deserialize<'a>, + E: Display + DeserializeOwned, + S: AsRef + Sync + Send; +} + +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +impl ApiClient for Client { + async fn get_json( + &self, + path: PathSegments<'_>, + params: Params<'_, K, V>, + ) -> Result> + where + for<'a> T: Deserialize<'a>, + K: AsRef + Sync, + V: AsRef + Sync, + E: Display + DeserializeOwned, + { + self.get_json(path, params).await + } + + async fn post_json( + &self, + path: PathSegments<'_>, + params: Params<'_, K, V>, + json_body: &B, + ) -> Result> + where + B: Serialize + ?Sized + Sync, + for<'a> T: Deserialize<'a>, + K: AsRef + Sync, + V: AsRef + Sync, + E: Display + DeserializeOwned, + { + self.post_json(path, params, json_body).await + } + + async fn get_json_from(&self, endpoint: S) -> Result> + where + for<'a> T: Deserialize<'a>, + E: Display + DeserializeOwned, + S: AsRef + Sync + Send, + { + self.get_json_endpoint(endpoint).await + } + + async fn post_json_data_to( + &self, + endpoint: S, + json_body: &B, + ) -> Result> + where + B: Serialize + ?Sized + Sync, + for<'a> T: Deserialize<'a>, + E: Display + DeserializeOwned, + S: AsRef + Sync + Send, + { + self.post_json_endpoint(endpoint, json_body).await + } +} + +// utility function that should solve the double slash problem in API urls forever. +pub fn sanitize_url, V: AsRef>( + base: &Url, + segments: PathSegments<'_>, + params: Params<'_, K, V>, +) -> Url { + let mut url = base.clone(); + let mut path_segments = url + .path_segments_mut() + .expect("provided validator url does not have a base!"); + for segment in segments { + let segment = segment.strip_prefix('/').unwrap_or(segment); + let segment = segment.strip_suffix('/').unwrap_or(segment); + + path_segments.push(segment); + } + // I don't understand why compiler couldn't figure out that it's no longer used + // and can be dropped + drop(path_segments); + + if !params.is_empty() { + url.query_pairs_mut().extend_pairs(params); + } + + url +} + +async fn parse_response(res: Response, allow_empty: bool) -> Result> +where + T: DeserializeOwned, + E: DeserializeOwned + Display, +{ + let status = res.status(); + + if !allow_empty { + if let Some(0) = res.content_length() { + return Err(HttpClientError::EmptyResponse { status }); + } + } + + if res.status().is_success() { + Ok(res.json().await?) + } else if res.status() == StatusCode::NOT_FOUND { + Err(HttpClientError::NotFound) + } else { + let Ok(plaintext) = res.text().await else { + return Err(HttpClientError::RequestFailure { status }); + }; + + if let Ok(request_error) = serde_json::from_str(&plaintext) { + Err(HttpClientError::EndpointFailure { + status, + error: request_error, + }) + } else { + Err(HttpClientError::GenericRequestFailure(plaintext)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sanitizing_urls() { + let base_url: Url = "http://foomp.com".parse().unwrap(); + + // works with 1 segment + assert_eq!( + "http://foomp.com/foo", + sanitize_url(&base_url, &["foo"], NO_PARAMS).as_str() + ); + + // works with 2 segments + assert_eq!( + "http://foomp.com/foo/bar", + sanitize_url(&base_url, &["foo", "bar"], NO_PARAMS).as_str() + ); + + // works with leading slash + assert_eq!( + "http://foomp.com/foo", + sanitize_url(&base_url, &["/foo"], NO_PARAMS).as_str() + ); + assert_eq!( + "http://foomp.com/foo/bar", + sanitize_url(&base_url, &["/foo", "bar"], NO_PARAMS).as_str() + ); + assert_eq!( + "http://foomp.com/foo/bar", + sanitize_url(&base_url, &["foo", "/bar"], NO_PARAMS).as_str() + ); + + // works with trailing slash + assert_eq!( + "http://foomp.com/foo", + sanitize_url(&base_url, &["foo/"], NO_PARAMS).as_str() + ); + assert_eq!( + "http://foomp.com/foo/bar", + sanitize_url(&base_url, &["foo/", "bar"], NO_PARAMS).as_str() + ); + assert_eq!( + "http://foomp.com/foo/bar", + sanitize_url(&base_url, &["foo", "bar/"], NO_PARAMS).as_str() + ); + + // works with both leading and trailing slash + assert_eq!( + "http://foomp.com/foo", + sanitize_url(&base_url, &["/foo/"], NO_PARAMS).as_str() + ); + assert_eq!( + "http://foomp.com/foo/bar", + sanitize_url(&base_url, &["/foo/", "/bar/"], NO_PARAMS).as_str() + ); + + // adds params + assert_eq!( + "http://foomp.com/foo/bar?foomp=baz", + sanitize_url(&base_url, &["foo", "bar"], &[("foomp", "baz")]).as_str() + ); + assert_eq!( + "http://foomp.com/foo/bar?arg1=val1&arg2=val2", + sanitize_url( + &base_url, + &["/foo/", "/bar/"], + &[("arg1", "val1"), ("arg2", "val2")] + ) + .as_str() + ); + } +} diff --git a/common/http-requests/Cargo.toml b/common/http-requests/Cargo.toml deleted file mode 100644 index 6245eeedf4..0000000000 --- a/common/http-requests/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "nym-http-requests" -version = "0.1.0" -description = "Helper library for sending HTTP requesters over the Nym mixnet" -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } -repository = { workspace = true } - -[dependencies] -nym-socks5-requests = { path = "../socks5/requests" } -nym-ordered-buffer = { path = "../socks5/ordered-buffer" } -nym-service-providers-common = { path = "../../service-providers/common" } -bytecodec = "0.4.15" -httpcodec = "0.2.3" -bytes = "1" -http = "0.2.9" -thiserror = "1" -url = "2" diff --git a/common/http-requests/src/error.rs b/common/http-requests/src/error.rs deleted file mode 100644 index 180a4fd44a..0000000000 --- a/common/http-requests/src/error.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::io; -use thiserror::Error; - -#[derive(Debug, Error)] -pub enum MixHttpRequestError { - #[error("invalid Socks5 response")] - InvalidSocks5Response, - - #[error("the received Socks5 response was empty")] - EmptySocks5Response, - - #[error("bytecodec Error: {0}")] - ByteCodecError(#[from] bytecodec::Error), - - #[error("Url parse error: {0}")] - UrlParseError(#[from] url::ParseError), - - #[error("could not resolve socket address from the provided URL")] - SocketAddrResolveError { - #[source] - source: io::Error, - }, -} diff --git a/common/http-requests/src/lib.rs b/common/http-requests/src/lib.rs deleted file mode 100644 index 1905396279..0000000000 --- a/common/http-requests/src/lib.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2021 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use bytecodec::bytes::BytesEncoder; -use bytecodec::io::IoEncodeExt; -use bytecodec::Encode; -use httpcodec::{BodyEncoder, Request, RequestEncoder}; - -pub mod error; -pub mod socks; - -pub fn encode_http_request_as_string( - request: Request>, -) -> Result { - // Encode HTTP request as bytes - let mut encoder = RequestEncoder::new(BodyEncoder::new(BytesEncoder::new())); - encoder.start_encoding(request)?; - let mut buf = Vec::new(); - encoder.encode_all(&mut buf)?; - - Ok(String::from_utf8_lossy(&buf).to_string()) -} - -#[cfg(test)] -mod http_requests_tests { - use super::*; - use httpcodec::{HeaderField, HttpVersion, Method, RequestTarget}; - - fn create_http_get_request() -> Request> { - let mut request = Request::new( - Method::new("GET").unwrap(), - RequestTarget::new("/.wellknown/wallet/validators.json").unwrap(), - HttpVersion::V1_1, - b"".to_vec(), - ); - let mut headers = request.header_mut(); - headers.add_field(HeaderField::new("Host", "nymtech.net").unwrap()); - - request - } - - #[test] - fn http_request_ok() { - // Encode HTTP request as bytes - let request = create_http_get_request(); - let mut encoder = RequestEncoder::new(BodyEncoder::new(BytesEncoder::new())); - encoder.start_encoding(request).unwrap(); - let mut buf = Vec::new(); - encoder.encode_all(&mut buf).unwrap(); - - let body_as_string = String::from_utf8(buf).unwrap(); - - // replace newlines with \r\n - let expected = r"GET /.wellknown/wallet/validators.json HTTP/1.1 -Host: nymtech.net -Content-Length: 0 - -" - .replace('\n', "\r\n"); - - assert_eq!(expected, body_as_string); - } -} diff --git a/common/http-requests/src/socks.rs b/common/http-requests/src/socks.rs deleted file mode 100644 index 952ff1fc52..0000000000 --- a/common/http-requests/src/socks.rs +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2023 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use crate::error; -use bytecodec::bytes::BytesEncoder; -use bytecodec::bytes::RemainingBytesDecoder; -use bytecodec::io::IoEncodeExt; -use bytecodec::{DecodeExt, Encode}; -use httpcodec::{BodyDecoder, ResponseDecoder}; -use httpcodec::{BodyEncoder, Request, RequestEncoder}; -use nym_service_providers_common::interface::ProviderInterfaceVersion; -use nym_socks5_requests::{SocketData, Socks5ProtocolVersion, Socks5ProviderRequest}; - -pub fn encode_http_request_as_socks_send_request( - provider_interface: ProviderInterfaceVersion, - socks5_protocol: Socks5ProtocolVersion, - conn_id: u64, - request: Request>, - seq: Option, - local_closed: bool, -) -> Result { - // Encode HTTP request as bytes - let mut encoder = RequestEncoder::new(BodyEncoder::new(BytesEncoder::new())); - encoder.start_encoding(request)?; - let mut buf = Vec::new(); - encoder.encode_all(&mut buf)?; - - // Wrap it as SOCKS send request - let request_content = nym_socks5_requests::request::Socks5Request::new_send( - socks5_protocol, - SocketData::new(seq.unwrap_or_default(), conn_id, local_closed, buf), - ); - - // and wrap it in provider request - Ok(Socks5ProviderRequest::new_provider_data( - provider_interface, - request_content, - )) -} - -#[derive(Debug)] -pub struct MixHttpResponse { - // pub connection_id: u64, - // #[deprecated] - // pub is_closed: bool, - pub http_response: httpcodec::Response>, - // #[deprecated] - // pub seq: u64, -} - -impl MixHttpResponse { - pub fn try_from_bytes(b: &[u8]) -> Result { - if b.is_empty() { - Err(error::MixHttpRequestError::EmptySocks5Response) - } else { - let mut decoder = ResponseDecoder::>::default(); - let http_response = decoder.decode_from_bytes(b)?; - - Ok(MixHttpResponse { http_response }) - } - } -} - -// impl TryFrom for MixHttpResponse { -// type Error = error::MixHttpRequestError; -// -// fn try_from(value: Socks5Response) -> Result { -// if let Socks5ResponseContent::NetworkData { content } = value.content { -// content.try_into() -// } else { -// Err(error::MixHttpRequestError::InvalidSocks5Response) -// } -// } -// } -// -// impl TryFrom for MixHttpResponse { -// type Error = error::MixHttpRequestError; -// -// fn try_from(value: SocketData) -> Result { -// if value.data.is_empty() { -// Err(error::MixHttpRequestError::EmptySocks5Response) -// } else { -// let mut decoder = ResponseDecoder::>::default(); -// let http_response = decoder.decode_from_bytes(value.data.as_ref())?; -// -// Ok(MixHttpResponse { -// connection_id: value.header.connection_id, -// is_closed: value.header.local_socket_closed, -// http_response, -// seq: value.header.seq, -// }) -// } -// } -// } - -// pub fn decode_socks_response_as_http_response( -// socks5_response: Socks5Response, -// ) -> Result { -// socks5_response.try_into() -// } -// -// #[cfg(test)] -// mod http_requests_tests { -// use super::*; -// use httpcodec::{HeaderField, HttpVersion, Method, RequestTarget}; -// use nym_service_providers_common::interface::Serializable; -// use nym_socks5_requests::Socks5Response; -// -// fn create_http_get_request() -> Request> { -// let mut request = Request::new( -// Method::new("GET").unwrap(), -// RequestTarget::new("/.wellknown/wallet/validators.json").unwrap(), -// HttpVersion::V1_1, -// b"".to_vec(), -// ); -// let mut headers = request.header_mut(); -// headers.add_field(HeaderField::new("Host", "nymtech.net").unwrap()); -// -// request -// } -// -// fn create_socks5_request_buffer() -> Vec { -// let request = create_http_get_request(); -// let socks5_request = encode_http_request_as_socks_send_request( -// ProviderInterfaceVersion::new_current(), -// Socks5ProtocolVersion::new_current(), -// 99u64, -// request, -// Some(42u64), -// true, -// ) -// .unwrap(); -// socks5_request.into_bytes() -// } -// -// #[test] -// fn request_http_request_content_ok() { -// let buffer = create_socks5_request_buffer(); -// -// // HTTP request string content is as expected -// assert_eq!( -// [71u8, 69u8, 84u8, 32u8, 47u8, 46u8, 119u8, 101u8], -// buffer[19..27] -// ); -// } -// -// /// This test will fail if the framing of the request buffer changes, e.g. when OrderedMessage -// /// changes to have the `index` value as a field, instead of packed with the `data` -// #[test] -// fn request_size_as_expected_ok() { -// let buffer = create_socks5_request_buffer(); -// // println!("{:?}", buffer) // uncomment and run `cargo test -- --nocapture` to view -// -// assert_eq!(108, buffer.len()); // version set to SOCKS5 -// } -// -// #[test] -// fn request_socks5_headers_ok() { -// let buffer = create_socks5_request_buffer(); -// -// assert_eq!(5u8, buffer[0]); // version set to SOCKS5 -// assert_eq!(1u8, buffer[1]); // type is SEND -// assert_eq!(99u8, buffer[9]); // ConnectionId is correct -// assert_eq!(1u8, buffer[10]); // local_closed is true -// } -// -// #[test] -// fn request_ordered_message_ok() { -// let buffer = create_socks5_request_buffer(); -// -// // OrderedMessage index is correct -// assert_eq!(42u8, buffer[18]); -// } -// -// fn create_socks_response() -> Socks5Response { -// // HTTP response is just a string -// let http_response_string = "HTTP/1.1 200 OK\r\nServer: foo/0.0.1\r\n\r\n"; -// -// let data = http_response_string.as_bytes().to_vec(); -// -// // wrap in `NetworkData`, then Socks5Response -// Socks5Response::new( -// Socks5ProtocolVersion::new_current(), -// Socks5ResponseContent::NetworkData { -// content: SocketData::new(42, 99u64, false, data), -// }, -// ) -// } -// -// /// This test will fail is anything in the framing of the socks5_response byte -// /// representation changes -// #[test] -// fn response_byte_size_is_as_expected() { -// let socks5_response = create_socks_response(); -// let buf = socks5_response.into_bytes(); -// -// assert_eq!(57, buf.len()); -// } -// -// #[test] -// fn response_parses() { -// unimplemented!() -// // let socks5_response = create_socks_response(); -// // let response = decode_socks_response_as_http_response(socks5_response).unwrap(); -// // -// // assert_eq!(42u64, response.seq); // OrderedMessage index as expected -// // assert_eq!(HttpVersion::V1_1, response.http_response.http_version()); -// // assert_eq!(200u16, response.http_response.status_code().as_u16()); -// // assert_eq!( -// // "foo/0.0.1", -// // response.http_response.header().get_field("Server").unwrap() -// // ); -// } -// } diff --git a/common/ledger/Cargo.toml b/common/ledger/Cargo.toml index 5ea9badd52..dbbce3e920 100644 --- a/common/ledger/Cargo.toml +++ b/common/ledger/Cargo.toml @@ -10,4 +10,4 @@ bip32 = "0.5.1" k256 = { workspace = true } ledger-transport = "0.10.0" ledger-transport-hid = "0.10.0" -thiserror = "1" \ No newline at end of file +thiserror = { workspace = true } \ No newline at end of file diff --git a/common/mixnode-common/src/verloc/packet.rs b/common/mixnode-common/src/verloc/packet.rs index 80d7f59ac9..3951a7f6b0 100644 --- a/common/mixnode-common/src/verloc/packet.rs +++ b/common/mixnode-common/src/verloc/packet.rs @@ -23,7 +23,7 @@ impl EchoPacket { .chain(keys.public_key().to_bytes().iter().cloned()) .collect::>(); - let signature = keys.private_key().sign(&bytes_to_sign); + let signature = keys.private_key().sign(bytes_to_sign); EchoPacket { sequence_number, @@ -67,7 +67,7 @@ impl EchoPacket { pub(crate) fn construct_reply(self, private_key: &identity::PrivateKey) -> ReplyPacket { let bytes = self.to_bytes(); - let signature = private_key.sign(&bytes); + let signature = private_key.sign(bytes); ReplyPacket { base_packet: self, signature, diff --git a/common/mobile-storage/Cargo.toml b/common/mobile-storage/Cargo.toml index bd58629110..4b02821498 100644 --- a/common/mobile-storage/Cargo.toml +++ b/common/mobile-storage/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] async-trait = { workspace = true } -thiserror = "1.0" +thiserror = { workspace = true } diff --git a/common/network-defaults/Cargo.toml b/common/network-defaults/Cargo.toml index bc5bddb497..5d5e071343 100644 --- a/common/network-defaults/Cargo.toml +++ b/common/network-defaults/Cargo.toml @@ -12,7 +12,7 @@ cfg-if = { workspace = true } dotenvy = { workspace = true } hex-literal = "0.3.3" once_cell = { workspace = true } -schemars = { version = "0.8", features = ["preserve_order"] } +schemars = { workspace = true, features = ["preserve_order"] } serde = { workspace = true, features = ["derive"]} thiserror = { workspace = true } url = { workspace = true } diff --git a/common/network-defaults/src/lib.rs b/common/network-defaults/src/lib.rs index fe353b16ae..b45b5483e9 100644 --- a/common/network-defaults/src/lib.rs +++ b/common/network-defaults/src/lib.rs @@ -462,6 +462,9 @@ pub const DEFAULT_NYM_API_PORT: u16 = 8080; pub const NYM_API_VERSION: &str = "v1"; +// NYM-NODE +pub const DEFAULT_NYM_NODE_HTTP_PORT: u16 = 8080; + // REWARDING /// We'll be assuming a few more things, profit margin and cost function. Since we don't have reliable package measurement, we'll be using uptime. We'll also set the value of 1 Nym to 1 $, to be able to translate interval costs to Nyms. We'll also assume a cost of 40$ per interval(month), converting that to Nym at our 1$ rate translates to 40_000_000 uNyms diff --git a/common/nymcoconut/Cargo.toml b/common/nymcoconut/Cargo.toml index 73e427f547..7aed2bb595 100644 --- a/common/nymcoconut/Cargo.toml +++ b/common/nymcoconut/Cargo.toml @@ -11,8 +11,8 @@ bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", branch ="gt-seriali itertools = "0.10" digest = "0.9" rand = "0.8" -thiserror = "1.0" -serde = "1.0" +thiserror = { workspace = true } +serde = { workspace = true } serde_derive = "1.0" bs58 = "0.4.0" sha2 = "0.9" diff --git a/common/nymsphinx/addressing/Cargo.toml b/common/nymsphinx/addressing/Cargo.toml index 4420d7f258..c73e692e62 100644 --- a/common/nymsphinx/addressing/Cargo.toml +++ b/common/nymsphinx/addressing/Cargo.toml @@ -11,7 +11,7 @@ repository = { workspace = true } nym-crypto = { path = "../../crypto", features = ["asymmetric"] } # all addresses are expressed in terms on their crypto keys nym-sphinx-types = { path = "../types", features = ["sphinx"] } # we need to be able to refer to some types defined inside sphinx crate serde = "1.0" # implementing serialization/deserialization for some types, like `Recipient` -thiserror = "1.0.37" +thiserror = { workspace = true } [dev-dependencies] rand = "0.7" diff --git a/common/nymsphinx/anonymous-replies/Cargo.toml b/common/nymsphinx/anonymous-replies/Cargo.toml index 49367da152..58c7c44890 100644 --- a/common/nymsphinx/anonymous-replies/Cargo.toml +++ b/common/nymsphinx/anonymous-replies/Cargo.toml @@ -10,8 +10,8 @@ repository = { workspace = true } [dependencies] rand = { version = "0.7.3", features = ["wasm-bindgen"] } bs58 = "0.4" -serde = "1.0" -thiserror = "1" +serde = { workspace = true } +thiserror = { workspace = true } nym-crypto = { path = "../../crypto", features = ["symmetric", "rand"] } nym-sphinx-addressing = { path = "../addressing" } diff --git a/common/nymsphinx/chunking/Cargo.toml b/common/nymsphinx/chunking/Cargo.toml index 94bec5886b..542c8d28e2 100644 --- a/common/nymsphinx/chunking/Cargo.toml +++ b/common/nymsphinx/chunking/Cargo.toml @@ -12,7 +12,7 @@ repository = { workspace = true } [dependencies] log = { workspace = true } rand = { version = "0.7.3", features = ["wasm-bindgen"] } -thiserror = "1.0.37" +thiserror = { workspace = true } nym-sphinx-addressing = { path = "../addressing" } nym-sphinx-params = { path = "../params" } diff --git a/common/nymsphinx/cover/Cargo.toml b/common/nymsphinx/cover/Cargo.toml index e700327c93..d3da16d2db 100644 --- a/common/nymsphinx/cover/Cargo.toml +++ b/common/nymsphinx/cover/Cargo.toml @@ -9,7 +9,7 @@ repository = { workspace = true } [dependencies] rand = { version = "0.7.3", features = ["wasm-bindgen"] } -thiserror = "1.0.37" +thiserror = { workspace = true } nym-crypto = { path = "../../crypto" } nym-sphinx-acknowledgements = { path = "../acknowledgements" } diff --git a/common/nymsphinx/forwarding/Cargo.toml b/common/nymsphinx/forwarding/Cargo.toml index 4060cbf076..c3f3e0dc9f 100644 --- a/common/nymsphinx/forwarding/Cargo.toml +++ b/common/nymsphinx/forwarding/Cargo.toml @@ -12,4 +12,4 @@ nym-sphinx-addressing = { path = "../addressing" } nym-sphinx-params = { path = "../params" } nym-sphinx-types = { path = "../types", features = ["sphinx", "outfox"] } nym-outfox = { path = "../../../nym-outfox" } -thiserror = "1" +thiserror = { workspace = true } diff --git a/common/nymsphinx/framing/Cargo.toml b/common/nymsphinx/framing/Cargo.toml index 3915f204a2..bf2c030e2e 100644 --- a/common/nymsphinx/framing/Cargo.toml +++ b/common/nymsphinx/framing/Cargo.toml @@ -10,7 +10,7 @@ repository = { workspace = true } [dependencies] bytes = "1.0" tokio-util = { version = "0.7.4", features = ["codec"] } -thiserror = "1.0.37" +thiserror = { workspace = true } nym-sphinx-types = { path = "../types", features = ["sphinx", "outfox"] } nym-sphinx-params = { path = "../params", features = ["sphinx", "outfox"] } diff --git a/common/nymsphinx/params/Cargo.toml b/common/nymsphinx/params/Cargo.toml index 9d9a5a24e2..7933943630 100644 --- a/common/nymsphinx/params/Cargo.toml +++ b/common/nymsphinx/params/Cargo.toml @@ -8,7 +8,7 @@ license = { workspace = true } repository = { workspace = true } [dependencies] -thiserror = "1.0.37" +thiserror = { workspace = true } serde = { workspace = true, features = ["derive"] } nym-crypto = { path = "../../crypto", features = ["hashing", "symmetric"] } diff --git a/common/nymsphinx/src/receiver.rs b/common/nymsphinx/src/receiver.rs index a756d6b1ba..cbf3db277c 100644 --- a/common/nymsphinx/src/receiver.rs +++ b/common/nymsphinx/src/receiver.rs @@ -294,7 +294,8 @@ mod message_receiver { owner: "foomp4".to_string(), host: "1.2.3.4".parse().unwrap(), mix_host: "1.2.3.4:1789".parse().unwrap(), - clients_port: 9000, + clients_ws_port: 9000, + clients_wss_port: None, identity_key: identity::PublicKey::from_base58_string( "FioFa8nMmPpQnYi7JyojoTuwGLeyNS8BF4ChPr29zUML", ) diff --git a/common/nymsphinx/types/Cargo.toml b/common/nymsphinx/types/Cargo.toml index ae348113a0..47ad47c2d2 100644 --- a/common/nymsphinx/types/Cargo.toml +++ b/common/nymsphinx/types/Cargo.toml @@ -10,7 +10,7 @@ repository = { workspace = true } [dependencies] sphinx-packet = { version = "0.1.0", optional = true } nym-outfox = { path = "../../../nym-outfox", optional = true } -thiserror = "1" +thiserror = { workspace = true } [features] default = ["sphinx"] diff --git a/common/pemstore/src/lib.rs b/common/pemstore/src/lib.rs index 51b779be29..e883ed60c0 100644 --- a/common/pemstore/src/lib.rs +++ b/common/pemstore/src/lib.rs @@ -51,7 +51,11 @@ where if T::pem_type() != key_pem.tag { return Err(io::Error::new( io::ErrorKind::Other, - "unexpected key pem tag", + format!( + "unexpected key pem tag. Got '{}', expected: '{}'", + key_pem.tag, + T::pem_type() + ), )); } diff --git a/common/socks5-client-core/Cargo.toml b/common/socks5-client-core/Cargo.toml index ca4c53023d..a02684958f 100644 --- a/common/socks5-client-core/Cargo.toml +++ b/common/socks5-client-core/Cargo.toml @@ -13,10 +13,10 @@ log = { workspace = true } pin-project = "1.0" rand = { version = "0.7.3", features = ["wasm-bindgen"] } reqwest = { workspace = true } -schemars = { version = "0.8", features = ["preserve_order"] } +schemars = { workspace = true, features = ["preserve_order"] } serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization tap = "1.0.1" -thiserror = "1.0.34" +thiserror = { workspace = true } tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] } url = { workspace = true } diff --git a/common/socks5/ordered-buffer/Cargo.toml b/common/socks5/ordered-buffer/Cargo.toml index faa16769db..b92662f633 100644 --- a/common/socks5/ordered-buffer/Cargo.toml +++ b/common/socks5/ordered-buffer/Cargo.toml @@ -8,4 +8,4 @@ edition = "2021" [dependencies] log = { workspace = true } -thiserror = "1.0.37" +thiserror = { workspace = true } diff --git a/common/statistics/Cargo.toml b/common/statistics/Cargo.toml index 1e762b88f1..8a6974096d 100644 --- a/common/statistics/Cargo.toml +++ b/common/statistics/Cargo.toml @@ -15,5 +15,5 @@ reqwest = { workspace = true, features = ["json"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1" sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "chrono"]} -thiserror = "1" +thiserror = { workspace = true } tokio = { version = "1.24.1", features = [ "time" ] } diff --git a/common/topology/Cargo.toml b/common/topology/Cargo.toml index 079429cc69..3d43cfe229 100644 --- a/common/topology/Cargo.toml +++ b/common/topology/Cargo.toml @@ -15,7 +15,7 @@ documentation = { workspace = true } bs58 = "0.4" log = { workspace = true } rand = { version = "0.7.3", features = ["wasm-bindgen"] } -thiserror = "1.0.37" +thiserror = { workspace = true } async-trait = { workspace = true, optional = true } semver = "0.11" @@ -35,6 +35,10 @@ nym-sphinx-types = { path = "../nymsphinx/types", features = ["sphinx", "outfox" nym-sphinx-routing = { path = "../nymsphinx/routing" } nym-bin-common = { path = "../bin-common" } +# I'm not sure how to feel about pulling in this dependency here... +nym-api-requests = { path = "../../nym-api/nym-api-requests" } + + # 'serializable' feature nym-config = { path = "../config", optional = true } diff --git a/common/topology/src/gateway.rs b/common/topology/src/gateway.rs index ce5acc7638..9d10b8d2a0 100644 --- a/common/topology/src/gateway.rs +++ b/common/topology/src/gateway.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{filter, NetworkAddress, NodeVersion}; +use nym_api_requests::models::DescribedGateway; use nym_crypto::asymmetric::{encryption, identity}; use nym_mixnet_contract_common::GatewayBond; use nym_sphinx_addressing::nodes::{NodeIdentity, NymNodeRoutingAddress}; @@ -10,6 +11,7 @@ use std::convert::{TryFrom, TryInto}; use std::fmt; use std::fmt::Formatter; use std::io; +use std::net::AddrParseError; use std::net::SocketAddr; use thiserror::Error; @@ -27,6 +29,17 @@ pub enum GatewayConversionError { #[source] source: io::Error, }, + + #[error("'{gateway}' has not provided any valid ip addresses")] + NoIpAddressesProvided { gateway: String }, + + #[error("'{gateway}' has provided a malformed ip address: {err}")] + MalformedIpAddress { + gateway: String, + + #[source] + err: AddrParseError, + }, } #[derive(Clone)] @@ -36,7 +49,13 @@ pub struct Node { // we're keeping this as separate resolved field since we do not want to be resolving the potential // hostname every time we want to construct a path via this node pub mix_host: SocketAddr, - pub clients_port: u16, + + // #[serde(alias = "clients_port")] + pub clients_ws_port: u16, + + // #[serde(default)] + pub clients_wss_port: Option, + pub identity_key: identity::PublicKey, pub sphinx_key: encryption::PublicKey, // TODO: or nymsphinx::PublicKey? both are x25519 pub version: NodeVersion, @@ -48,7 +67,8 @@ impl std::fmt::Debug for Node { .field("host", &self.host) .field("owner", &self.owner) .field("mix_host", &self.mix_host) - .field("clients_port", &self.clients_port) + .field("clients_ws_port", &self.clients_ws_port) + .field("clients_wss_port", &self.clients_wss_port) .field("identity_key", &self.identity_key.to_base58_string()) .field("sphinx_key", &self.sphinx_key.to_base58_string()) .field("version", &self.version) @@ -82,11 +102,17 @@ impl Node { } pub fn clients_address(&self) -> String { - format!("ws://{}:{}", self.host, self.clients_port) + self.clients_address_tls() + .unwrap_or_else(|| self.clients_address_no_tls()) } - pub fn clients_address_tls(&self) -> String { - format!("wss://{}:443", self.host) + pub fn clients_address_no_tls(&self) -> String { + format!("ws://{}:{}", self.host, self.clients_ws_port) + } + + pub fn clients_address_tls(&self) -> Option { + self.clients_wss_port + .map(|p| format!("wss://{}:{p}", self.host)) } } @@ -131,7 +157,8 @@ impl<'a> TryFrom<&'a GatewayBond> for Node { owner: bond.owner.as_str().to_owned(), host, mix_host, - clients_port: bond.gateway.clients_port, + clients_ws_port: bond.gateway.clients_port, + clients_wss_port: None, identity_key: identity::PublicKey::from_base58_string(&bond.gateway.identity_key)?, sphinx_key: encryption::PublicKey::from_base58_string(&bond.gateway.sphinx_key)?, version: bond.gateway.version.as_str().into(), @@ -146,3 +173,56 @@ impl TryFrom for Node { Node::try_from(&bond) } } + +impl<'a> TryFrom<&'a DescribedGateway> for Node { + type Error = GatewayConversionError; + + fn try_from(value: &'a DescribedGateway) -> Result { + let Some(ref self_described) = value.self_described else { + return (&value.bond).try_into(); + }; + + let ips = &self_described.host_information.ip_address; + if ips.is_empty() { + return Err(GatewayConversionError::NoIpAddressesProvided { + gateway: value.bond.gateway.identity_key.clone(), + }); + } + + let host = match &self_described.host_information.hostname { + None => NetworkAddress::IpAddr(ips[0]), + Some(hostname) => NetworkAddress::Hostname(hostname.clone()), + }; + + // get ip from the self-reported values so we wouldn't need to do any hostname resolution + // (which doesn't really work in wasm) + let mix_host = SocketAddr::new(ips[0], value.bond.gateway.mix_port); + + Ok(Node { + owner: value.bond.owner.as_str().to_owned(), + host, + mix_host, + clients_ws_port: self_described.mixnet_websockets.ws_port, + clients_wss_port: self_described.mixnet_websockets.wss_port, + identity_key: identity::PublicKey::from_base58_string( + &self_described.host_information.keys.ed25519, + )?, + sphinx_key: encryption::PublicKey::from_base58_string( + &self_described.host_information.keys.x25519, + )?, + version: self_described + .build_information + .build_version + .as_str() + .into(), + }) + } +} + +impl TryFrom for Node { + type Error = GatewayConversionError; + + fn try_from(value: DescribedGateway) -> Result { + Node::try_from(&value) + } +} diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index 0273cf4a3a..039e30eb94 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -19,6 +19,7 @@ use std::str::FromStr; #[cfg(feature = "serializable")] use ::serde::{Deserialize, Deserializer, Serialize, Serializer}; +use nym_api_requests::models::DescribedGateway; pub mod error; pub mod filter; @@ -403,10 +404,33 @@ impl<'de> Deserialize<'de> for NymTopology { } } -pub fn nym_topology_from_detailed( +pub trait IntoGatewayNode: TryInto +where + >::Error: Display, +{ + fn identity(&self) -> IdentityKeyRef; +} + +impl IntoGatewayNode for GatewayBond { + fn identity(&self) -> IdentityKeyRef { + &self.gateway.identity_key + } +} + +impl IntoGatewayNode for DescribedGateway { + fn identity(&self) -> IdentityKeyRef { + &self.bond.gateway.identity_key + } +} + +pub fn nym_topology_from_detailed( mix_details: Vec, - gateway_bonds: Vec, -) -> NymTopology { + gateway_bonds: Vec, +) -> NymTopology +where + G: IntoGatewayNode, + >::Error: Display, +{ let mut mixes = BTreeMap::new(); for bond in mix_details .into_iter() @@ -435,7 +459,7 @@ pub fn nym_topology_from_detailed( let mut gateways = Vec::with_capacity(gateway_bonds.len()); for bond in gateway_bonds.into_iter() { - let gate_id = bond.gateway.identity_key.clone(); + let gate_id = bond.identity().to_owned(); match bond.try_into() { Ok(gate) => gateways.push(gate), Err(err) => { diff --git a/common/topology/src/serde.rs b/common/topology/src/serde.rs index 89e943e03e..84770a4868 100644 --- a/common/topology/src/serde.rs +++ b/common/topology/src/serde.rs @@ -190,7 +190,12 @@ pub struct SerializableGateway { #[cfg_attr(feature = "wasm-serde-types", tsify(optional))] #[serde(alias = "clients_port")] - pub clients_port: Option, + #[serde(alias = "clients_ws_port")] + pub clients_ws_port: Option, + + #[cfg_attr(feature = "wasm-serde-types", tsify(optional))] + #[serde(alias = "clients_wss_port")] + pub clients_wss_port: Option, #[serde(alias = "identity_key")] pub identity_key: String, @@ -209,7 +214,9 @@ impl TryFrom for gateway::Node { let host = gateway::Node::parse_host(&value.host)?; let mix_port = value.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT); - let clients_port = value.clients_port.unwrap_or(DEFAULT_CLIENT_LISTENING_PORT); + let clients_ws_port = value + .clients_ws_port + .unwrap_or(DEFAULT_CLIENT_LISTENING_PORT); let version = value.version.map(|v| v.as_str().into()).unwrap_or_default(); // try to completely resolve the host in the mix situation to avoid doing it every @@ -224,7 +231,8 @@ impl TryFrom for gateway::Node { owner: value.owner, host, mix_host, - clients_port, + clients_ws_port, + clients_wss_port: value.clients_wss_port, identity_key: identity::PublicKey::from_base58_string(&value.identity_key) .map_err(GatewayConversionError::from)?, sphinx_key: encryption::PublicKey::from_base58_string(&value.sphinx_key) @@ -241,7 +249,8 @@ impl<'a> From<&'a gateway::Node> for SerializableGateway { host: value.host.to_string(), explicit_ip: Some(value.mix_host.ip()), mix_port: Some(value.mix_host.port()), - clients_port: Some(value.clients_port), + clients_ws_port: Some(value.clients_ws_port), + clients_wss_port: value.clients_wss_port, identity_key: value.identity_key.to_base58_string(), sphinx_key: value.sphinx_key.to_base58_string(), version: Some(value.version.to_string()), diff --git a/common/types/Cargo.toml b/common/types/Cargo.toml index f7c79daf7b..4ac66b8a9b 100644 --- a/common/types/Cargo.toml +++ b/common/types/Cargo.toml @@ -8,8 +8,6 @@ rust-version = "1.58" [dependencies] base64 = "0.21.4" -boringtun = { workspace = true, optional = true } -dashmap = "5.5.3" eyre = "0.6.5" hmac = "0.12.1" itertools = "0.11" @@ -41,4 +39,3 @@ tempfile = "3.3.0" [features] default = [] generate-ts = ["nym-mixnet-contract-common/generate-ts"] -wireguard = ["boringtun"] diff --git a/common/types/src/gateway_client_registration.rs b/common/types/src/gateway_client_registration.rs deleted file mode 100644 index e558cd043f..0000000000 --- a/common/types/src/gateway_client_registration.rs +++ /dev/null @@ -1,117 +0,0 @@ -use std::{net::SocketAddr, ops::Deref, str::FromStr}; - -use crate::wireguard::PeerPublicKey; -use base64::{engine::general_purpose, Engine}; -use dashmap::DashMap; -use hmac::{Hmac, Mac}; -use nym_crypto::asymmetric::encryption::PrivateKey; -use serde::{Deserialize, Serialize}; -use sha2::Sha256; -use x25519_dalek::StaticSecret; - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub enum ClientMessage { - Init(InitMessage), - Final(GatewayClient), -} - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct InitMessage { - pub_key: PeerPublicKey, -} - -impl InitMessage { - pub fn pub_key(&self) -> &PeerPublicKey { - &self.pub_key - } - #[allow(dead_code)] - pub fn new(pub_key: PeerPublicKey) -> Self { - InitMessage { pub_key } - } -} - -// Client that wants to register sends its PublicKey and SocketAddr bytes mac digest encrypted with a DH shared secret. -// Gateway can then verify pub_key payload using the sme process -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct GatewayClient { - // base64 encoded public key, using x25519-dalek for impl - pub pub_key: PeerPublicKey, - pub socket: SocketAddr, - pub mac: ClientMac, -} - -pub type HmacSha256 = Hmac; - -impl GatewayClient { - // Reusable secret should be gateways Wireguard PK - // Client should perform this step when generating its payload, using its own WG PK - pub fn verify( - &self, - gateway_key: &PrivateKey, - nonce: u64, - ) -> Result<(), Box> { - #[allow(clippy::expect_used)] - let static_secret = - StaticSecret::try_from(gateway_key.to_bytes()).expect("This is infalliable"); - let dh = static_secret.diffie_hellman(&self.pub_key); - let mut mac = HmacSha256::new_from_slice(dh.as_bytes())?; - mac.update(self.pub_key.as_bytes()); - mac.update(self.socket.ip().to_string().as_bytes()); - mac.update(self.socket.port().to_string().as_bytes()); - mac.update(&nonce.to_le_bytes()); - Ok(mac.verify_slice(&self.mac)?) - } - - pub fn pub_key(&self) -> &PeerPublicKey { - &self.pub_key - } - - pub fn socket(&self) -> SocketAddr { - self.socket - } -} - -#[derive(Debug, Clone)] -pub struct ClientMac(Vec); - -impl ClientMac { - #[allow(dead_code)] - pub fn new(mac: Vec) -> Self { - ClientMac(mac) - } -} - -impl Deref for ClientMac { - type Target = Vec; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl FromStr for ClientMac { - type Err = String; - - fn from_str(s: &str) -> Result { - let mac_bytes: Vec = general_purpose::STANDARD - .decode(s) - .map_err(|_| "Could not base64 decode public key mac representation".to_string())?; - Ok(ClientMac(mac_bytes)) - } -} - -impl Serialize for ClientMac { - fn serialize(&self, serializer: S) -> Result { - let encoded_key = general_purpose::STANDARD.encode(self.0.clone()); - serializer.serialize_str(&encoded_key) - } -} - -impl<'de> Deserialize<'de> for ClientMac { - fn deserialize>(deserializer: D) -> Result { - let encoded_key = String::deserialize(deserializer)?; - ClientMac::from_str(&encoded_key).map_err(serde::de::Error::custom) - } -} - -pub type GatewayClientRegistry = DashMap; diff --git a/common/types/src/lib.rs b/common/types/src/lib.rs index 956036000a..e44fa517df 100644 --- a/common/types/src/lib.rs +++ b/common/types/src/lib.rs @@ -9,12 +9,8 @@ pub mod error; pub mod fees; pub mod gas; pub mod gateway; -#[cfg(feature = "wireguard")] -pub mod gateway_client_registration; pub mod helpers; pub mod mixnode; pub mod pending_events; pub mod transaction; pub mod vesting; -#[cfg(feature = "wireguard")] -pub mod wireguard; diff --git a/common/types/src/wireguard.rs b/common/types/src/wireguard.rs deleted file mode 100644 index 279b8392ad..0000000000 --- a/common/types/src/wireguard.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::{ - fmt, - hash::{Hash, Hasher}, - ops::Deref, - str::FromStr, -}; - -use base64::{engine::general_purpose, Engine}; -use boringtun::x25519::PublicKey; -use serde::Serialize; - -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct PeerPublicKey(PublicKey); - -impl fmt::Display for PeerPublicKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", general_purpose::STANDARD.encode(self.0.as_bytes())) - } -} - -impl Hash for PeerPublicKey { - fn hash(&self, state: &mut H) { - self.0.as_bytes().hash(state) - } -} - -impl PeerPublicKey { - #[allow(dead_code)] - pub fn new(key: PublicKey) -> Self { - PeerPublicKey(key) - } - - pub fn as_bytes(&self) -> &[u8] { - self.0.as_bytes() - } -} - -impl Deref for PeerPublicKey { - type Target = PublicKey; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl FromStr for PeerPublicKey { - type Err = String; - - fn from_str(s: &str) -> Result { - let key_bytes: [u8; 32] = general_purpose::STANDARD - .decode(s) - .map_err(|_| "Could not base64 decode public key representation".to_string())? - .try_into() - .map_err(|_| "Invalid key length".to_string())?; - Ok(PeerPublicKey(PublicKey::from(key_bytes))) - } -} - -impl Serialize for PeerPublicKey { - fn serialize(&self, serializer: S) -> Result { - let encoded_key = general_purpose::STANDARD.encode(self.0.as_bytes()); - serializer.serialize_str(&encoded_key) - } -} - -impl<'de> serde::Deserialize<'de> for PeerPublicKey { - fn deserialize>(deserializer: D) -> Result { - let encoded_key = String::deserialize(deserializer)?; - Ok(PeerPublicKey::from_str(&encoded_key).map_err(serde::de::Error::custom))? - } -} diff --git a/common/wasm/client-core/Cargo.toml b/common/wasm/client-core/Cargo.toml index 38a9e3f5f9..3e8ec57163 100644 --- a/common/wasm/client-core/Cargo.toml +++ b/common/wasm/client-core/Cargo.toml @@ -14,7 +14,7 @@ js-sys = { workspace = true } rand = { version = "0.7.3", features = ["wasm-bindgen"] } serde = { workspace = true, features = ["derive"] } serde-wasm-bindgen = { workspace = true } -thiserror = { workspace = true } +thiserror = { workspace = true } tsify = { workspace = true, features = ["js"] } url = { workspace = true } wasm-bindgen = { workspace = true } diff --git a/common/wireguard-types/Cargo.toml b/common/wireguard-types/Cargo.toml new file mode 100644 index 0000000000..41c5a19b16 --- /dev/null +++ b/common/wireguard-types/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "nym-wireguard-types" +version = "0.1.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +base64 = { workspace = true } +dashmap = { workspace = true } +serde = { workspace = true, features = ["derive"] } +thiserror = { workspace = true } + +nym-crypto = { path = "../crypto", features = ["asymmetric"] } + +# feature-specific dependencies: + +## verify: +hmac = { version = "0.12.1", optional = true } +sha2 = { version = "0.10.8", optional = true } + +## openapi: +utoipa = { workspace = true, optional = true } +serde_json = { workspace = true, optional = true } + +# target-specific dependencies +[target."cfg(not(target_arch = \"wasm32\"))".dependencies.boringtun] +workspace = true + +[target."cfg(target_arch = \"wasm32\")".dependencies.x25519-dalek] +version = "2.0.0" + + +[dev-dependencies] +rand = "0.7.3" +nym-crypto = { path = "../crypto", features = ["rand"]} + + +[features] +default = ["verify"] +openapi = ["utoipa", "serde_json"] +# this is moved to a separate feature as we really need clients to import it (especially, *cough*, wasm) +verify = ["hmac", "sha2"] \ No newline at end of file diff --git a/common/wireguard-types/src/error.rs b/common/wireguard-types/src/error.rs new file mode 100644 index 0000000000..0bd4a8d3f6 --- /dev/null +++ b/common/wireguard-types/src/error.rs @@ -0,0 +1,35 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum Error { + #[error("the provided base64-encoded client MAC ('{mac}') was malformed: {source}")] + MalformedClientMac { + mac: String, + #[source] + source: base64::DecodeError, + }, + + #[error("the provided base64-encoded client x25519 public key ('{pub_key}') was malformed: {source}")] + MalformedPeerPublicKeyEncoding { + pub_key: String, + #[source] + source: base64::DecodeError, + }, + + #[error("the provided base64-encoded client x25519 public key ('{pub_key}') has invalid length: {decoded_length}. expected 32 bytes")] + InvalidPeerPublicKeyLength { + pub_key: String, + decoded_length: usize, + }, + + #[cfg(feature = "verify")] + #[error("failed to verify mac provided by '{client}': {source}")] + FailedClientMacVerification { + client: String, + #[source] + source: hmac::digest::MacError, + }, +} diff --git a/common/wireguard-types/src/lib.rs b/common/wireguard-types/src/lib.rs new file mode 100644 index 0000000000..acb3366f86 --- /dev/null +++ b/common/wireguard-types/src/lib.rs @@ -0,0 +1,15 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod error; +pub mod public_key; +pub mod registration; + +pub use error::Error; +pub use public_key::PeerPublicKey; +pub use registration::{ + ClientMac, ClientMessage, ClientRegistrationResponse, GatewayClient, InitMessage, Nonce, +}; + +#[cfg(feature = "verify")] +pub use registration::HmacSha256; diff --git a/common/wireguard-types/src/public_key.rs b/common/wireguard-types/src/public_key.rs new file mode 100644 index 0000000000..7843f35c4c --- /dev/null +++ b/common/wireguard-types/src/public_key.rs @@ -0,0 +1,90 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::Error; +use base64::engine::general_purpose; +use base64::Engine; +use serde::Serialize; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::ops::Deref; +use std::str::FromStr; + +// underneath the same library is being used, i.e. x25519-dalek 2.0, +// which is being reexported by boringtun but wasm hates internals of boringtun +#[cfg(target_arch = "wasm32")] +use x25519_dalek::PublicKey as BoringtunPublicKey; + +#[cfg(not(target_arch = "wasm32"))] +use boringtun::x25519::PublicKey as BoringtunPublicKey; + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub struct PeerPublicKey(BoringtunPublicKey); + +impl PeerPublicKey { + #[allow(dead_code)] + pub fn new(key: BoringtunPublicKey) -> Self { + PeerPublicKey(key) + } + + pub fn as_bytes(&self) -> &[u8] { + self.0.as_bytes() + } +} + +impl fmt::Display for PeerPublicKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", general_purpose::STANDARD.encode(self.0.as_bytes())) + } +} + +impl Hash for PeerPublicKey { + fn hash(&self, state: &mut H) { + self.0.as_bytes().hash(state) + } +} + +impl Deref for PeerPublicKey { + type Target = BoringtunPublicKey; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl FromStr for PeerPublicKey { + type Err = Error; + + fn from_str(s: &str) -> Result { + let key_bytes: Vec = general_purpose::STANDARD.decode(s).map_err(|source| { + Error::MalformedPeerPublicKeyEncoding { + pub_key: s.to_string(), + source, + } + })?; + + let decoded_length = key_bytes.len(); + let Ok(key_arr): Result<[u8; 32], _> = key_bytes.try_into() else { + return Err(Error::InvalidPeerPublicKeyLength { + pub_key: s.to_string(), + decoded_length, + })?; + }; + + Ok(PeerPublicKey(BoringtunPublicKey::from(key_arr))) + } +} + +impl Serialize for PeerPublicKey { + fn serialize(&self, serializer: S) -> Result { + let encoded_key = general_purpose::STANDARD.encode(self.0.as_bytes()); + serializer.serialize_str(&encoded_key) + } +} + +impl<'de> serde::Deserialize<'de> for PeerPublicKey { + fn deserialize>(deserializer: D) -> Result { + let encoded_key = String::deserialize(deserializer)?; + Ok(PeerPublicKey::from_str(&encoded_key).map_err(serde::de::Error::custom))? + } +} diff --git a/common/wireguard-types/src/registration.rs b/common/wireguard-types/src/registration.rs new file mode 100644 index 0000000000..c899be5d02 --- /dev/null +++ b/common/wireguard-types/src/registration.rs @@ -0,0 +1,231 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::error::Error; +use crate::PeerPublicKey; +use base64::{engine::general_purpose, Engine}; +use dashmap::DashMap; +use serde::{Deserialize, Serialize}; +use std::net::SocketAddr; +use std::{fmt, ops::Deref, str::FromStr}; + +#[cfg(feature = "verify")] +use hmac::{Hmac, Mac}; +#[cfg(feature = "verify")] +use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey}; +#[cfg(feature = "verify")] +use sha2::Sha256; + +pub type GatewayClientRegistry = DashMap; +pub type PendingRegistrations = DashMap; + +#[cfg(feature = "verify")] +pub type HmacSha256 = Hmac; + +pub type Nonce = u64; + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(tag = "type", rename_all = "camelCase")] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub enum ClientMessage { + Initial(InitMessage), + Final(GatewayClient), +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct InitMessage { + /// Base64 encoded x25519 public key + #[cfg_attr(feature = "openapi", schema(value_type = String, format = Byte))] + pub pub_key: PeerPublicKey, +} + +impl InitMessage { + pub fn pub_key(&self) -> PeerPublicKey { + self.pub_key + } + + pub fn new(pub_key: PeerPublicKey) -> Self { + InitMessage { pub_key } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(tag = "type", rename_all = "camelCase")] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub enum ClientRegistrationResponse { + PendingRegistration { nonce: u64 }, + Registered { success: bool }, +} + +/// Client that wants to register sends its PublicKey and SocketAddr bytes mac digest encrypted with a DH shared secret. +/// Gateway/Nym node can then verify pub_key payload using the same process +#[derive(Serialize, Deserialize, Debug, Clone)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct GatewayClient { + /// Base64 encoded x25519 public key + #[cfg_attr(feature = "openapi", schema(value_type = String, format = Byte))] + pub pub_key: PeerPublicKey, + + /// Client's socket address + #[cfg_attr(feature = "openapi", schema(example = "1.2.3.4:51820", value_type = String))] + pub socket: SocketAddr, + + /// Sha256 hmac on the data (alongside the prior nonce) + #[cfg_attr(feature = "openapi", schema(value_type = String, format = Byte))] + pub mac: ClientMac, +} + +impl GatewayClient { + #[cfg(feature = "verify")] + pub fn new( + local_secret: &PrivateKey, + remote_public: PublicKey, + socket_address: SocketAddr, + nonce: u64, + ) -> Self { + // convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek + #[allow(clippy::expect_used)] + let static_secret = boringtun::x25519::StaticSecret::try_from(local_secret.to_bytes()) + .expect("conversion between x25519 private keys is infallible"); + let local_public: boringtun::x25519::PublicKey = (&static_secret).into(); + + let remote_public = boringtun::x25519::PublicKey::from(remote_public.to_bytes()); + + let dh = static_secret.diffie_hellman(&remote_public); + + // TODO: change that to use our nym_crypto::hmac module instead + #[allow(clippy::expect_used)] + let mut mac = HmacSha256::new_from_slice(dh.as_bytes()) + .expect("x25519 shared secret is always 32 bytes long"); + + mac.update(local_public.as_bytes()); + mac.update(socket_address.ip().to_string().as_bytes()); + mac.update(socket_address.port().to_string().as_bytes()); + mac.update(&nonce.to_le_bytes()); + + GatewayClient { + pub_key: PeerPublicKey::new(local_public), + socket: socket_address, + mac: ClientMac(mac.finalize().into_bytes().to_vec()), + } + } + + // Reusable secret should be gateways Wireguard PK + // Client should perform this step when generating its payload, using its own WG PK + #[cfg(feature = "verify")] + pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> { + // convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek + #[allow(clippy::expect_used)] + let static_secret = boringtun::x25519::StaticSecret::try_from(gateway_key.to_bytes()) + .expect("conversion between x25519 private keys is infallible"); + + let dh = static_secret.diffie_hellman(&self.pub_key); + + // TODO: change that to use our nym_crypto::hmac module instead + #[allow(clippy::expect_used)] + let mut mac = HmacSha256::new_from_slice(dh.as_bytes()) + .expect("x25519 shared secret is always 32 bytes long"); + + mac.update(self.pub_key.as_bytes()); + mac.update(self.socket.ip().to_string().as_bytes()); + mac.update(self.socket.port().to_string().as_bytes()); + mac.update(&nonce.to_le_bytes()); + + mac.verify_slice(&self.mac) + .map_err(|source| Error::FailedClientMacVerification { + client: self.pub_key.to_string(), + source, + }) + } + + pub fn pub_key(&self) -> PeerPublicKey { + self.pub_key + } + + pub fn socket(&self) -> SocketAddr { + self.socket + } +} + +// TODO: change the inner type into generic array of size HmacSha256::OutputSize +// TODO2: rely on our internal crypto/hmac +#[derive(Debug, Clone)] +pub struct ClientMac(Vec); + +impl fmt::Display for ClientMac { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", general_purpose::STANDARD.encode(&self.0)) + } +} + +impl ClientMac { + #[allow(dead_code)] + pub fn new(mac: Vec) -> Self { + ClientMac(mac) + } +} + +impl Deref for ClientMac { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl FromStr for ClientMac { + type Err = Error; + + fn from_str(s: &str) -> Result { + let mac_bytes: Vec = + general_purpose::STANDARD + .decode(s) + .map_err(|source| Error::MalformedClientMac { + mac: s.to_string(), + source, + })?; + + Ok(ClientMac(mac_bytes)) + } +} + +impl Serialize for ClientMac { + fn serialize(&self, serializer: S) -> Result { + let encoded_key = general_purpose::STANDARD.encode(self.0.clone()); + serializer.serialize_str(&encoded_key) + } +} + +impl<'de> Deserialize<'de> for ClientMac { + fn deserialize>(deserializer: D) -> Result { + let encoded_key = String::deserialize(deserializer)?; + ClientMac::from_str(&encoded_key).map_err(serde::de::Error::custom) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use nym_crypto::asymmetric::encryption; + + #[test] + #[cfg(feature = "verify")] + fn client_request_roundtrip() { + let mut rng = rand::thread_rng(); + + let gateway_key_pair = encryption::KeyPair::new(&mut rng); + let client_key_pair = encryption::KeyPair::new(&mut rng); + + let socket: SocketAddr = "1.2.3.4:5678".parse().unwrap(); + let nonce = 1234567890; + + let client = GatewayClient::new( + client_key_pair.private_key(), + *gateway_key_pair.public_key(), + socket, + nonce, + ); + assert!(client.verify(gateway_key_pair.private_key(), nonce).is_ok()) + } +} diff --git a/common/wireguard/Cargo.toml b/common/wireguard/Cargo.toml index c82f52141a..25cb796cc4 100644 --- a/common/wireguard/Cargo.toml +++ b/common/wireguard/Cargo.toml @@ -30,7 +30,7 @@ tap.workspace = true thiserror.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "net", "io-util"] } serde = { workspace = true, features = ["derive"] } -nym-types = { path = "../types", features = ["wireguard"] } +nym-wireguard-types = { path = "../wireguard-types" } [target.'cfg(target_os = "linux")'.dependencies] tokio-tun = "0.9.0" diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index a20dc23fa4..5a4520d6c2 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -13,7 +13,7 @@ mod setup; mod udp_listener; mod wg_tunnel; -use nym_types::gateway_client_registration::GatewayClientRegistry; +use nym_wireguard_types::registration::GatewayClientRegistry; use std::sync::Arc; // Currently the module related to setting up the virtual network device is platform specific. diff --git a/common/wireguard/src/registered_peers.rs b/common/wireguard/src/registered_peers.rs index 248f8f85a5..a0a5b7f6dc 100644 --- a/common/wireguard/src/registered_peers.rs +++ b/common/wireguard/src/registered_peers.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, sync::Arc}; use ip_network::IpNetwork; -use nym_types::wireguard::PeerPublicKey; +use nym_wireguard_types::PeerPublicKey; pub(crate) type PeerIdx = u32; @@ -30,7 +30,7 @@ impl RegisteredPeers { pub(crate) async fn insert(&mut self, peer: Arc>) { let peer_idx = { peer.lock().await.index }; - let public_key = { peer.lock().await.public_key.clone() }; + let public_key = { peer.lock().await.public_key }; self.peers.insert(public_key, Arc::clone(&peer)); self.peers_by_idx.insert(peer_idx, peer); } diff --git a/common/wireguard/src/udp_listener.rs b/common/wireguard/src/udp_listener.rs index a62c279f9d..045dd7e892 100644 --- a/common/wireguard/src/udp_listener.rs +++ b/common/wireguard/src/udp_listener.rs @@ -7,7 +7,7 @@ use boringtun::{ use futures::StreamExt; use log::error; use nym_task::TaskClient; -use nym_types::{gateway_client_registration::GatewayClientRegistry, wireguard::PeerPublicKey}; +use nym_wireguard_types::{registration::GatewayClientRegistry, PeerPublicKey}; use tap::TapFallible; use tokio::{ net::UdpSocket, @@ -37,7 +37,7 @@ async fn add_test_peer(registered_peers: &mut RegisteredPeers) { let peer_index = 0; let peer_allowed_ips = setup::peer_allowed_ips(); let test_peer = Arc::new(tokio::sync::Mutex::new(RegisteredPeer { - public_key: peer_static_public.clone(), + public_key: peer_static_public, index: peer_index, allowed_ips: peer_allowed_ips, })); @@ -247,7 +247,7 @@ async fn parse_peer<'a>( } else if gateway_client_registry.contains_key(&peer_public_key) { let peer_idx = registered_peers.next_idx(); let peer = Arc::new(Mutex::new(RegisteredPeer { - public_key: peer_public_key.clone(), + public_key: peer_public_key, index: peer_idx, allowed_ips: setup::peer_allowed_ips(), })); diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index cfe8bc7e30..5855dd5322 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -810,7 +810,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn 2.0.32", ] [[package]] @@ -1628,9 +1628,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.26" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5907a1b7c277254a8b15170f6e7c97cfa60ee7872a3217663bb81151e48184bb" dependencies = [ "proc-macro2", ] @@ -1894,7 +1894,7 @@ checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn 2.0.32", ] [[package]] @@ -1927,7 +1927,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn 2.0.32", ] [[package]] @@ -2041,9 +2041,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.12" +version = "2.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927" +checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" dependencies = [ "proc-macro2", "quote", @@ -2065,22 +2065,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn 2.0.32", ] [[package]] @@ -2427,5 +2427,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn 2.0.32", ] diff --git a/contracts/Cargo.toml b/contracts/Cargo.toml index 9ec0049b20..effb7d9df7 100644 --- a/contracts/Cargo.toml +++ b/contracts/Cargo.toml @@ -48,3 +48,5 @@ cw3 = "=1.1.0" cw3-fixed-multisig = "=1.1.0" cw4 = "=1.1.0" cw20 = "=1.1.0" + +thiserror = "1.0.48" diff --git a/contracts/coconut-bandwidth/Cargo.toml b/contracts/coconut-bandwidth/Cargo.toml index 5ed8e5f98b..86a6a1bbfb 100644 --- a/contracts/coconut-bandwidth/Cargo.toml +++ b/contracts/coconut-bandwidth/Cargo.toml @@ -23,7 +23,7 @@ cw-storage-plus = { workspace = true } cw-controllers = { workspace = true } serde = { version = "1.0.103", default-features = false, features = ["derive"] } -thiserror = "1.0.23" +thiserror = { workspace = true } [features] schema-gen = ["nym-coconut-bandwidth-contract-common/schema", "cosmwasm-schema"] \ No newline at end of file diff --git a/contracts/coconut-dkg/Cargo.toml b/contracts/coconut-dkg/Cargo.toml index 794c1f3a0f..dbdd097553 100644 --- a/contracts/coconut-dkg/Cargo.toml +++ b/contracts/coconut-dkg/Cargo.toml @@ -22,7 +22,7 @@ cw-storage-plus = { workspace = true } cw-controllers = { workspace = true } cw4 = { workspace = true } serde = { version = "1.0.103", default-features = false, features = ["derive"] } -thiserror = "1.0.23" +thiserror = { workspace = true } [dev-dependencies] cw-multi-test = { workspace = true } diff --git a/contracts/coconut-test/Cargo.toml b/contracts/coconut-test/Cargo.toml index 7cafdc200f..b7497b060b 100644 --- a/contracts/coconut-test/Cargo.toml +++ b/contracts/coconut-test/Cargo.toml @@ -22,7 +22,7 @@ cw-utils = { workspace = true } schemars = "0.8" serde = { version = "1.0.103", default-features = false, features = ["derive"] } -thiserror = "1.0.23" +thiserror = { workspace = true } nym-coconut-bandwidth = { path = "../coconut-bandwidth" } nym-coconut-dkg = { path = "../coconut-dkg" } diff --git a/contracts/ephemera/Cargo.toml b/contracts/ephemera/Cargo.toml index 376eec374e..edcde5d054 100644 --- a/contracts/ephemera/Cargo.toml +++ b/contracts/ephemera/Cargo.toml @@ -23,7 +23,7 @@ cw-controllers = { workspace = true } cw4 = { workspace = true } serde = { version = "1.0.103", default-features = false, features = ["derive"] } -thiserror = "1.0.23" +thiserror = { workspace = true } [dev-dependencies] cw-multi-test = { workspace = true } diff --git a/contracts/mixnet-vesting-integration-tests/src/support/setup.rs b/contracts/mixnet-vesting-integration-tests/src/support/setup.rs index ecc25f459e..4f1a4d3bec 100644 --- a/contracts/mixnet-vesting-integration-tests/src/support/setup.rs +++ b/contracts/mixnet-vesting-integration-tests/src/support/setup.rs @@ -243,7 +243,7 @@ impl TestSetup { ContractMessageContent::new(Addr::unchecked(owner), proxy, vec![stake], payload); let sign_payload = SignableMixNodeBondingMsg::new(signing_nonce, content); let plaintext = sign_payload.to_plaintext().unwrap(); - let signature = keypair.private_key().sign(&plaintext); + let signature = keypair.private_key().sign(plaintext); let msg_signature = MessageSignature::from(signature.to_bytes().as_ref()); (mixnode, msg_signature) diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index 6824f2e309..a6f1ba5d0e 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -39,7 +39,7 @@ cw-storage-plus = { workspace = true } bs58 = "0.4.0" serde = { version = "1.0.103", default-features = false, features = ["derive"] } -thiserror = { version = "1.0.23" } +thiserror = { workspace = true } time = { version = "0.3", features = ["macros"] } semver = { version = "1.0.16", default-features = false } diff --git a/contracts/mixnet/src/support/tests/mod.rs b/contracts/mixnet/src/support/tests/mod.rs index 851d394bfe..2bd98eb175 100644 --- a/contracts/mixnet/src/support/tests/mod.rs +++ b/contracts/mixnet/src/support/tests/mod.rs @@ -206,7 +206,7 @@ pub mod test_helpers { let sig_bytes = family_owner_keys .private_key() - .sign(&msg.to_plaintext().unwrap()) + .sign(msg.to_plaintext().unwrap()) .to_bytes(); MessageSignature::from(sig_bytes.as_ref()) } @@ -956,7 +956,7 @@ pub mod test_helpers { match message.algorithm { SigningAlgorithm::Ed25519 => { let plaintext = message.to_plaintext().unwrap(); - let signature = private_key.sign(&plaintext); + let signature = private_key.sign(plaintext); MessageSignature::from(signature.to_bytes().as_ref()) } SigningAlgorithm::Secp256k1 => { diff --git a/contracts/multisig/cw4-group/Cargo.toml b/contracts/multisig/cw4-group/Cargo.toml index a2897779b9..6c63d707ef 100644 --- a/contracts/multisig/cw4-group/Cargo.toml +++ b/contracts/multisig/cw4-group/Cargo.toml @@ -41,5 +41,5 @@ cosmwasm-schema = { workspace = true } cosmwasm-std = { workspace = true } schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } -thiserror = { version = "1.0.23" } +thiserror = { workspace = true } diff --git a/contracts/name-service/Cargo.toml b/contracts/name-service/Cargo.toml index f680b41c35..e2b5ddb753 100644 --- a/contracts/name-service/Cargo.toml +++ b/contracts/name-service/Cargo.toml @@ -22,7 +22,7 @@ nym-contracts-common = { path = "../../common/cosmwasm-smart-contracts/contracts nym-name-service-common = { path = "../../common/cosmwasm-smart-contracts/name-service" } semver = { version = "1.0.16", default-features = false } serde = { version = "1.0.155", default-features = false, features = ["derive"] } -thiserror = "1.0.39" +thiserror = { workspace = true } [build-dependencies] vergen = { version = "=7.4.3", default-features = false, features = ["build", "git", "rustc"] } diff --git a/contracts/name-service/src/test_helpers/signing.rs b/contracts/name-service/src/test_helpers/signing.rs index d7431fc7ed..2a2a280290 100644 --- a/contracts/name-service/src/test_helpers/signing.rs +++ b/contracts/name-service/src/test_helpers/signing.rs @@ -29,7 +29,7 @@ pub fn ed25519_sign_message( match message.algorithm { SigningAlgorithm::Ed25519 => { let plaintext = message.to_plaintext().unwrap(); - let signature = private_key.sign(&plaintext); + let signature = private_key.sign(plaintext); MessageSignature::from(signature.to_bytes().as_ref()) } SigningAlgorithm::Secp256k1 => { diff --git a/contracts/service-provider-directory/Cargo.toml b/contracts/service-provider-directory/Cargo.toml index 39ffcaf6f7..e6b36d3346 100644 --- a/contracts/service-provider-directory/Cargo.toml +++ b/contracts/service-provider-directory/Cargo.toml @@ -22,7 +22,7 @@ nym-contracts-common = { path = "../../common/cosmwasm-smart-contracts/contracts nym-service-provider-directory-common = { path = "../../common/cosmwasm-smart-contracts/service-provider-directory" } semver = { version = "1.0.16", default-features = false } serde = { version = "1.0.155", default-features = false, features = ["derive"] } -thiserror = "1.0.39" +thiserror = { workspace = true } [build-dependencies] vergen = { version = "=7.4.3", default-features = false, features = ["build", "git", "rustc"] } diff --git a/contracts/service-provider-directory/src/test_helpers/signing.rs b/contracts/service-provider-directory/src/test_helpers/signing.rs index 4bd1708bff..1d9aed1266 100644 --- a/contracts/service-provider-directory/src/test_helpers/signing.rs +++ b/contracts/service-provider-directory/src/test_helpers/signing.rs @@ -31,7 +31,7 @@ pub fn ed25519_sign_message( match message.algorithm { SigningAlgorithm::Ed25519 => { let plaintext = message.to_plaintext().unwrap(); - let signature = private_key.sign(&plaintext); + let signature = private_key.sign(plaintext); MessageSignature::from(signature.to_bytes().as_ref()) } SigningAlgorithm::Secp256k1 => { diff --git a/contracts/vesting/Cargo.toml b/contracts/vesting/Cargo.toml index f9a4f53d2a..efd3f73006 100644 --- a/contracts/vesting/Cargo.toml +++ b/contracts/vesting/Cargo.toml @@ -35,7 +35,7 @@ cw2 = { workspace = true } cw-storage-plus = { workspace = true, features = ["iterator"] } serde = { version = "1.0", default-features = false, features = ["derive"] } -thiserror = { version = "1.0" } +thiserror ={ workspace = true } semver = { version = "1.0.16", default-features = false } [dev-dependencies] diff --git a/ephemera/Cargo.toml b/ephemera/Cargo.toml index ee991b3876..63ccaa9ab7 100644 --- a/ephemera/Cargo.toml +++ b/ephemera/Cargo.toml @@ -36,7 +36,7 @@ nym-config = { path = "../common/config" } nym-ephemera-common = { path = "../common/cosmwasm-smart-contracts/ephemera" } pretty_env_logger = "0.4" refinery = { version = "0.8.7", features = ["rusqlite"], optional = true } -reqwest = { version = "0.11.6", features = ["json"] } +reqwest = { version = "0.11.22", features = ["json"] } # Rocksdb kills compilation times and we're not currently using it. The reason # we comment it out is that rust-analyzer runs with --all-features #rocksdb = { version = "0.21.0", optional = true } @@ -44,14 +44,14 @@ rusqlite = { version = "0.27.0", features = ["bundled"], optional = true } serde = { version = "1.0", features = ["derive"] } serde_derive = "1.0.149" serde_json = "1.0.91" -thiserror = "1.0.37" +thiserror = { workspace = true } tokio = { version = "1", features = ["macros", "net","rt-multi-thread"] } tokio-tungstenite = { workspace = true } tokio-util = { version = "0.7.4", features = ["full"] } toml = "0.7.0" unsigned-varint = "0.7.1" -utoipa = { version = "3.0.1", features = ["actix_extras"] } -utoipa-swagger-ui = { version = "3.0.2", features = ["actix-web"] } +utoipa = { workspace = true, features = ["actix_extras"] } +utoipa-swagger-ui = { workspace = true, features = ["actix-web"] } uuid = { version = "1.2.2", features = ["v4"] } # Temporary fix to https://github.com/bluejekyll/trust-dns/issues/1946 diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index 160ac37bd4..935a76cb52 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -24,10 +24,10 @@ reqwest = { workspace = true } rocket = { version = "0.5.0-rc.2", features = ["json"] } rocket_cors = { git="https://github.com/lawliet89/rocket_cors", rev="dfd3662c49e2f6fc37df35091cb94d82f7fb5915" } rocket_okapi = { version = "0.8.0-rc.2", features = ["swagger"] } -schemars = { version = "0.8", features = ["preserve_order"] } -serde = "1.0.126" -serde_json = "1.0.66" -thiserror = "1.0.29" +schemars = { workspace = true, features = ["preserve_order"] } +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } tokio = {version = "1.21.2", features = ["full"] } nym-bin-common = { path = "../common/bin-common"} diff --git a/explorer-api/explorer-api-requests/Cargo.toml b/explorer-api/explorer-api-requests/Cargo.toml index d7139b9f78..825af93a91 100644 --- a/explorer-api/explorer-api-requests/Cargo.toml +++ b/explorer-api/explorer-api-requests/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" nym-contracts-common = { path = "../../common/cosmwasm-smart-contracts/contracts-common" } nym-mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" } nym-api-requests = { path = "../../nym-api/nym-api-requests" } -schemars = { version = "0.8", features = ["preserve_order"] } +schemars = { workspace = true, features = ["preserve_order"] } serde = { version = "1.0", features = ["derive"] } ts-rs = { workspace = true, optional = true } diff --git a/explorer-api/src/mix_node/econ_stats.rs b/explorer-api/src/mix_node/econ_stats.rs index 66a4676376..0b1c901a40 100644 --- a/explorer-api/src/mix_node/econ_stats.rs +++ b/explorer-api/src/mix_node/econ_stats.rs @@ -6,6 +6,7 @@ use crate::helpers::best_effort_small_dec_to_f64; use crate::mix_node::models::EconomicDynamicsStats; use nym_contracts_common::truncate_decimal; use nym_mixnet_contract_common::MixId; +use nym_validator_client::client::NymApiClientExt; pub(crate) async fn retrieve_mixnode_econ_stats( client: &ThreadsafeValidatorClient, diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index 43549cb78b..b968ee7b7e 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -15,13 +15,6 @@ rust-version = "1.56" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -axum = "0.6.20" -sha2 = "0.10.8" -hmac = "0.12.1" -axum-macros = "0.3.8" # Useful for debugging axum Handler trait errors -fastrand = "2" -x25519-dalek = { version = "2.0.0", features = ["static_secrets"] } -base64 = "0.21.4" anyhow = { workspace = true } async-trait = { workspace = true } atty = "0.2" @@ -48,7 +41,7 @@ sqlx = { version = "0.5", features = [ "migrate", ] } subtle-encoding = { version = "0.5", features = ["bech32-preview"] } -thiserror = "1" +thiserror = { workspace = true } tokio = { workspace = true, features = [ "rt-multi-thread", "net", @@ -63,6 +56,8 @@ url = { version = "2.2", features = ["serde"] } zeroize = { workspace = true } # internal +nym-node = { path = "../nym-node" } + nym-api-requests = { path = "../nym-api/nym-api-requests" } nym-bin-common = { path = "../common/bin-common", features = ["output_format"] } nym-coconut-interface = { path = "../common/coconut-interface" } @@ -97,4 +92,4 @@ sqlx = { version = "0.5", features = [ ] } [features] -wireguard = ["nym-wireguard", "nym-types/wireguard"] +wireguard = ["nym-wireguard"] diff --git a/gateway/gateway-requests/Cargo.toml b/gateway/gateway-requests/Cargo.toml index df6c59414a..fc46005eba 100644 --- a/gateway/gateway-requests/Cargo.toml +++ b/gateway/gateway-requests/Cargo.toml @@ -17,7 +17,7 @@ log = { workspace = true } rand = { version = "0.7.3", features = ["wasm-bindgen"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -thiserror = "1.0" +thiserror = { workspace = true } zeroize = { workspace = true } nym-crypto = { path = "../../common/crypto" } diff --git a/gateway/gateway-requests/src/registration/handshake/state.rs b/gateway/gateway-requests/src/registration/handshake/state.rs index 97f88c570a..a224e24720 100644 --- a/gateway/gateway-requests/src/registration/handshake/state.rs +++ b/gateway/gateway-requests/src/registration/handshake/state.rs @@ -137,7 +137,7 @@ impl<'a, S> State<'a, S> { .chain(remote_ephemeral_key.to_bytes().iter().cloned()) .collect(); - let signature = self.identity.private_key().sign(&message); + let signature = self.identity.private_key().sign(message); let zero_iv = stream_cipher::zero_iv::(); stream_cipher::encrypt::( self.derived_shared_keys.as_ref().unwrap().encryption_key(), @@ -191,7 +191,7 @@ impl<'a, S> State<'a, S> { self.remote_pubkey .as_ref() .unwrap() - .verify(&signed_payload, &signature) + .verify(signed_payload, &signature) .map_err(|_| HandshakeError::InvalidSignature) } diff --git a/gateway/src/commands/helpers.rs b/gateway/src/commands/helpers.rs index f8b9e326bd..c58020ca3c 100644 --- a/gateway/src/commands/helpers.rs +++ b/gateway/src/commands/helpers.rs @@ -25,7 +25,10 @@ use std::path::PathBuf; // Configuration that can be overridden. #[derive(Default)] pub(crate) struct OverrideConfig { - pub(crate) host: Option, + pub(crate) listening_address: Option, + pub(crate) public_ips: Option>, + pub(crate) hostname: Option, + pub(crate) mix_port: Option, pub(crate) clients_port: Option, pub(crate) datastore: Option, @@ -41,7 +44,9 @@ pub(crate) struct OverrideConfig { impl OverrideConfig { pub(crate) fn do_override(self, mut config: Config) -> Result { config = config - .with_optional(Config::with_listening_address, self.host) + .with_optional(Config::with_hostname, self.hostname) + .with_optional(Config::with_public_ips, self.public_ips) + .with_optional(Config::with_listening_address, self.listening_address) .with_optional(Config::with_mix_port, self.mix_port) .with_optional(Config::with_clients_port, self.clients_port) .with_optional_custom_env( diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index c5123703ab..645fbd7ab3 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -17,32 +17,41 @@ use std::{fs, io}; #[derive(Args, Clone)] pub struct Init { /// Id of the gateway we want to create config for - #[arg(long)] + #[clap(long)] id: String, - /// The custom host on which the gateway will be running for receiving sphinx packets - #[arg(long)] - host: IpAddr, + /// The listening address on which the gateway will be receiving sphinx packets and listening for client data + #[clap(long, alias = "host")] + listening_address: IpAddr, + + /// Comma separated list of public ip addresses that will announced to the nym-api and subsequently to the clients. + /// In nearly all circumstances, it's going to be identical to the address you're going to use for bonding. + #[clap(long, value_delimiter = ',')] + public_ips: Option>, + + /// Optional hostname associated with this gateway that will announced to the nym-api and subsequently to the clients + #[clap(long)] + hostname: Option, /// The port on which the gateway will be listening for sphinx packets - #[arg(long)] + #[clap(long)] mix_port: Option, /// The port on which the gateway will be listening for clients gateway-requests - #[arg(long)] + #[clap(long)] clients_port: Option, /// Path to sqlite database containing all gateway persistent data - #[arg(long)] + #[clap(long)] datastore: Option, /// Comma separated list of endpoints of nym APIs - #[arg(long, alias = "validator_apis", value_delimiter = ',')] + #[clap(long, alias = "validator_apis", value_delimiter = ',')] // the alias here is included for backwards compatibility (1.1.4 and before) nym_apis: Option>, /// Comma separated list of endpoints of the validator - #[arg( + #[clap( long, alias = "validators", alias = "nyxd_validators", @@ -53,43 +62,43 @@ pub struct Init { nyxd_urls: Option>, /// Cosmos wallet mnemonic needed for double spending protection - #[arg(long)] + #[clap(long)] mnemonic: Option, /// Set this gateway to work only with coconut credentials; that would disallow clients to /// bypass bandwidth credential requirement - #[arg(long, hide = true)] + #[clap(long, hide = true)] only_coconut_credentials: Option, /// Enable/disable gateway anonymized statistics that get sent to a statistics aggregator server - #[arg(long)] + #[clap(long)] enabled_statistics: Option, /// URL where a statistics aggregator is running. The default value is a Nym aggregator server - #[arg(long)] + #[clap(long)] statistics_service_url: Option, /// Allows this gateway to run an embedded network requester for minimal network overhead - #[arg(long)] + #[clap(long)] with_network_requester: bool, // ##### NETWORK REQUESTER FLAGS ##### /// Specifies whether this network requester should run in 'open-proxy' mode - #[arg(long, requires = "with_network_requester")] + #[clap(long, requires = "with_network_requester")] open_proxy: Option, /// Enable service anonymized statistics that get sent to a statistics aggregator server - #[arg(long, requires = "with_network_requester")] + #[clap(long, requires = "with_network_requester")] enable_statistics: Option, /// Mixnet client address where a statistics aggregator is running. The default value is a Nym /// aggregator client - #[arg(long, requires = "with_network_requester")] + #[clap(long, requires = "with_network_requester")] statistics_recipient: Option, /// Mostly debug-related option to increase default traffic rate so that you would not need to /// modify config post init - #[arg( + #[clap( long, hide = true, conflicts_with = "medium_toggle", @@ -98,7 +107,7 @@ pub struct Init { fastmode: bool, /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) - #[arg( + #[clap( long, hide = true, conflicts_with = "medium_toggle", @@ -108,7 +117,7 @@ pub struct Init { /// Enable medium mixnet traffic, for experiments only. /// This includes things like disabling cover traffic, no per hop delays, etc. - #[arg( + #[clap( long, hide = true, conflicts_with = "no_cover", @@ -117,14 +126,16 @@ pub struct Init { )] medium_toggle: bool, - #[arg(short, long, default_value_t = OutputFormat::default())] + #[clap(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, } impl From for OverrideConfig { fn from(init_config: Init) -> Self { OverrideConfig { - host: Some(init_config.host), + listening_address: Some(init_config.listening_address), + public_ips: init_config.public_ips, + hostname: init_config.hostname, mix_port: init_config.mix_port, clients_port: init_config.clients_port, datastore: init_config.datastore, @@ -244,7 +255,9 @@ mod tests { async fn create_gateway_with_in_mem_storage() { let args = Init { id: "foo-id".to_string(), - host: "1.1.1.1".parse().unwrap(), + listening_address: "1.1.1.1".parse().unwrap(), + public_ips: None, + hostname: None, mix_port: Some(42), clients_port: Some(43), datastore: Some("/foo-datastore".parse().unwrap()), diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index 6dd01e90bc..95dd0c5707 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -6,9 +6,12 @@ use crate::commands::helpers::{ }; use crate::node::helpers::node_details; use crate::support::config::build_config; +use anyhow::bail; use clap::Args; +use log::warn; use nym_bin_common::output_format::OutputFormat; use nym_config::helpers::SPECIAL_ADDRESSES; +use nym_node::error::NymNodeError; use std::net::IpAddr; use std::path::PathBuf; @@ -18,9 +21,18 @@ pub struct Run { #[clap(long)] id: String, - /// The custom host on which the gateway will be running for receiving sphinx packets + /// The custom listening address on which the gateway will be running for receiving sphinx packets + #[clap(long, alias = "host")] + listening_address: Option, + + /// Comma separated list of public ip addresses that will announced to the nym-api and subsequently to the clients. + /// In nearly all circumstances, it's going to be identical to the address you're going to use for bonding. + #[clap(long, value_delimiter = ',')] + public_ips: Option>, + + /// Optional hostname associated with this gateway that will announced to the nym-api and subsequently to the clients #[clap(long)] - host: Option, + hostname: Option, /// The port on which the gateway will be listening for sphinx packets #[clap(long)] @@ -116,12 +128,18 @@ pub struct Run { #[clap(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, + + /// Flag specifying this node will be running in a local setting. + #[clap(long)] + local: bool, } impl From for OverrideConfig { fn from(run_config: Run) -> Self { OverrideConfig { - host: run_config.host, + listening_address: run_config.listening_address, + public_ips: run_config.public_ips, + hostname: run_config.hostname, mix_port: run_config.mix_port, clients_port: run_config.clients_port, datastore: run_config.datastore, @@ -150,7 +168,7 @@ impl<'a> From<&'a Run> for OverrideNetworkRequesterConfig { } } -fn show_binding_warning(address: &str) { +fn show_binding_warning(address: IpAddr) { eprintln!("\n##### NOTE #####"); eprintln!( "\nYou are trying to bind to {address} - you might not be accessible to other nodes\n\ @@ -160,8 +178,33 @@ fn show_binding_warning(address: &str) { eprintln!("\n\n"); } +fn check_public_ips(ips: &[IpAddr], local: bool) -> anyhow::Result<()> { + let mut suspicious_ip = Vec::new(); + for ip in ips { + if SPECIAL_ADDRESSES.contains(ip) { + if !local { + return Err(NymNodeError::InvalidPublicIp { address: *ip }.into()); + } + suspicious_ip.push(ip); + } + } + + if !suspicious_ip.is_empty() { + warn!("\n##### WARNING #####"); + for ip in suspicious_ip { + warn!("The 'public' IP address you're trying to announce: {ip} may not be accessible to other clients.\ + Please make sure this is what you intended to announce.\ + You can ignore this warning if you're running setup on a local network ") + } + warn!("\n##### WARNING #####\n"); + } + Ok(()) +} + pub async fn execute(args: Run) -> anyhow::Result<()> { let id = args.id.clone(); + let local = args.local; + eprintln!("Starting gateway {id}..."); let output = args.output; @@ -171,15 +214,24 @@ pub async fn execute(args: Run) -> anyhow::Result<()> { let config = build_config(id, args)?; ensure_config_version_compatibility(&config)?; + let public_ips = &config.host.public_ips; + if public_ips.is_empty() { + return Err(NymNodeError::NoPublicIps.into()); + } + check_public_ips(public_ips, local)?; + if config.gateway.clients_wss_port.is_some() && config.host.hostname.is_none() { + bail!("attempted to announce 'wss' port without a valid hostname") + } + if SPECIAL_ADDRESSES.contains(&config.gateway.listening_address) { - show_binding_warning(&config.gateway.listening_address.to_string()); + show_binding_warning(config.gateway.listening_address); } let node_details = node_details(&config)?; let gateway = crate::node::create_gateway(config, Some(nr_opts), custom_mixnet).await?; eprintln!( "\nTo bond your gateway you will need to install the Nym wallet, go to https://nymtech.net/get-involved and select the Download button.\n\ - Select the correct version and install it to your machine. You will need to provide the following: \n "); + Select the correct version and install it to your machine. You will need to provide some of the following: \n "); output.to_stdout(&node_details); gateway.run().await diff --git a/gateway/src/commands/upgrade_helpers.rs b/gateway/src/commands/upgrade_helpers.rs index d8555ca215..7b13cc3f53 100644 --- a/gateway/src/commands/upgrade_helpers.rs +++ b/gateway/src/commands/upgrade_helpers.rs @@ -3,6 +3,7 @@ use crate::config::old_config_v1_1_20::ConfigV1_1_20; use crate::config::old_config_v1_1_28::ConfigV1_1_28; +use crate::config::old_config_v1_1_29::ConfigV1_1_29; use crate::config::{default_config_filepath, Config}; use crate::error::GatewayError; use log::info; @@ -20,7 +21,8 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result { info!("It is going to get updated to the current specification."); let updated_step1: ConfigV1_1_28 = old_config.into(); - let updated: Config = updated_step1.into(); + let updated_step2: ConfigV1_1_29 = updated_step1.into(); + let updated: Config = updated_step2.into(); updated .save_to_default_location() .map_err(|err| GatewayError::ConfigSaveFailure { @@ -42,6 +44,29 @@ fn try_upgrade_v1_1_28_config(id: &str) -> Result { info!("It seems the gateway is using <= v1.1.28 config template."); info!("It is going to get updated to the current specification."); + let updated_step1: ConfigV1_1_29 = old_config.into(); + let updated: Config = updated_step1.into(); + updated + .save_to_default_location() + .map_err(|err| GatewayError::ConfigSaveFailure { + path: default_config_filepath(id), + id: id.to_string(), + source: err, + })?; + + Ok(true) +} + +fn try_upgrade_v1_1_29_config(id: &str) -> Result { + // explicitly load it as v1.1.29 (which is incompatible with the current, i.e. 1.1.30+) + let Ok(old_config) = ConfigV1_1_29::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 gateway is using <= v1.1.29 config template."); + info!("It is going to get updated to the current specification."); + let updated: Config = old_config.into(); updated .save_to_default_location() @@ -61,6 +86,9 @@ pub(crate) fn try_upgrade_config(id: &str) -> Result<(), GatewayError> { if try_upgrade_v1_1_28_config(id)? { return Ok(()); } + if try_upgrade_v1_1_29_config(id)? { + return Ok(()); + } Ok(()) } diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index 23620953d6..134964fe94 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -12,9 +12,10 @@ use nym_config::{ DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, }; use nym_network_defaults::mainnet; -use serde::{Deserialize, Serialize}; +use nym_node::config; +use serde::{Deserialize, Deserializer, Serialize}; use std::io; -use std::net::IpAddr; +use std::net::{IpAddr, SocketAddr}; use std::path::{Path, PathBuf}; use std::time::Duration; use url::Url; @@ -22,6 +23,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop}; pub(crate) mod old_config_v1_1_20; pub(crate) mod old_config_v1_1_28; +pub(crate) mod old_config_v1_1_29; pub mod persistence; mod template; @@ -38,6 +40,18 @@ const DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE: usize = 2000; const DEFAULT_STORED_MESSAGE_FILENAME_LENGTH: u16 = 16; const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100; +fn de_maybe_port<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let port = u16::deserialize(deserializer)?; + if port == 0 { + Ok(None) + } else { + Ok(Some(port)) + } +} + /// Derive default path to gateway's config directory. /// It should get resolved to `$HOME/.nym/gateways//config` pub fn default_config_directory>(id: P) -> PathBuf { @@ -71,8 +85,17 @@ pub struct Config { #[serde(skip)] pub(crate) save_path: Option, + pub host: config::Host, + + #[serde(default)] + pub http: config::Http, + pub gateway: Gateway, + #[serde(default)] + // currently not really used for anything useful + pub wireguard: config::Wireguard, + pub storage_paths: GatewayPaths, pub network_requester: NetworkRequester, @@ -92,9 +115,17 @@ impl NymConfigTemplate for Config { impl Config { pub fn new>(id: S) -> Self { + let default_gateway = Gateway::new_default(id.as_ref()); Config { save_path: None, - gateway: Gateway::new_default(id.as_ref()), + host: config::Host { + // this is a very bad default! + public_ips: vec![default_gateway.listening_address], + hostname: None, + }, + http: Default::default(), + gateway: default_gateway, + wireguard: Default::default(), storage_paths: GatewayPaths::new_default(id.as_ref()), network_requester: Default::default(), logging: Default::default(), @@ -140,6 +171,18 @@ impl Config { } } + #[must_use] + pub fn with_hostname(mut self, hostname: String) -> Self { + self.host.hostname = Some(hostname); + self + } + + #[must_use] + pub fn with_public_ips(mut self, public_ips: Vec) -> Self { + self.host.public_ips = public_ips; + self + } + pub fn with_enabled_network_requester(mut self, enabled_network_requester: bool) -> Self { self.network_requester.enabled = enabled_network_requester; self @@ -184,6 +227,12 @@ impl Config { pub fn with_listening_address(mut self, listening_address: IpAddr) -> Self { self.gateway.listening_address = listening_address; + + let http_port = self.http.bind_address.port(); + self.http.bind_address = SocketAddr::new(listening_address, http_port); + let wg_port = self.wireguard.bind_address.port(); + self.wireguard.bind_address = SocketAddr::new(listening_address, wg_port); + self } @@ -245,6 +294,11 @@ pub struct Gateway { /// (default: 9000) pub clients_port: u16, + /// If applicable, announced port for listening for secure websocket client traffic. + /// (default: None) + #[serde(deserialize_with = "de_maybe_port")] + pub clients_wss_port: Option, + /// Whether gateway collects and sends anonymized statistics pub enabled_statistics: bool, @@ -279,6 +333,7 @@ impl Gateway { listening_address: inaddr_any(), mix_port: DEFAULT_MIX_LISTENING_PORT, clients_port: DEFAULT_CLIENT_LISTENING_PORT, + clients_wss_port: None, enabled_statistics: false, statistics_service_url: mainnet::STATISTICS_SERVICE_DOMAIN_ADDRESS .parse() diff --git a/gateway/src/config/old_config_v1_1_28.rs b/gateway/src/config/old_config_v1_1_28.rs index 7639d860f9..dff9cc896c 100644 --- a/gateway/src/config/old_config_v1_1_28.rs +++ b/gateway/src/config/old_config_v1_1_28.rs @@ -1,9 +1,10 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::persistence::paths::{GatewayPaths, KeysPaths}; -use crate::config::{Config, Debug, Gateway}; -use nym_bin_common::logging::LoggingSettings; +use crate::config::old_config_v1_1_29::{ + ConfigV1_1_29, DebugV1_1_29, GatewayPathsV1_1_29, GatewayV1_1_29, KeysPathsV1_1_29, + LoggingSettingsV1_1_29, +}; use nym_config::{ must_get_home, read_config_from_toml_file, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, NYM_DIR, }; @@ -84,11 +85,13 @@ impl ConfigV1_1_28 { } } -impl From for Config { +impl From for ConfigV1_1_29 { fn from(value: ConfigV1_1_28) -> Self { - Config { + ConfigV1_1_29 { + // \/ ADDED save_path: None, - gateway: Gateway { + // /\ ADDED + gateway: GatewayV1_1_29 { version: value.gateway.version, id: value.gateway.id, only_coconut_credentials: value.gateway.only_coconut_credentials, @@ -101,19 +104,25 @@ impl From for Config { statistics_service_url: value.gateway.statistics_service_url, cosmos_mnemonic: value.gateway.cosmos_mnemonic, }, - storage_paths: GatewayPaths { - keys: KeysPaths { + storage_paths: GatewayPathsV1_1_29 { + keys: KeysPathsV1_1_29 { private_identity_key_file: value.storage_paths.keys.private_identity_key_file, public_identity_key_file: value.storage_paths.keys.public_identity_key_file, private_sphinx_key_file: value.storage_paths.keys.private_sphinx_key_file, public_sphinx_key_file: value.storage_paths.keys.public_sphinx_key_file, }, clients_storage: value.storage_paths.clients_storage, + + // \/ ADDED network_requester_config: None, + // /\ ADDED }, + + // \/ ADDED network_requester: Default::default(), - logging: LoggingSettings {}, - debug: Debug { + // /\ ADDED + logging: LoggingSettingsV1_1_29 {}, + debug: DebugV1_1_29 { packet_forwarding_initial_backoff: value.debug.packet_forwarding_initial_backoff, packet_forwarding_maximum_backoff: value.debug.packet_forwarding_maximum_backoff, initial_connection_timeout: value.debug.initial_connection_timeout, diff --git a/gateway/src/config/old_config_v1_1_29.rs b/gateway/src/config/old_config_v1_1_29.rs new file mode 100644 index 0000000000..e38ff2a57c --- /dev/null +++ b/gateway/src/config/old_config_v1_1_29.rs @@ -0,0 +1,279 @@ +// Copyright 2020-2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::persistence::paths::{GatewayPaths, KeysPaths}; +use crate::config::{Config, Debug, Gateway, NetworkRequester}; +use nym_bin_common::logging::LoggingSettings; +use nym_config::{ + must_get_home, read_config_from_toml_file, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, NYM_DIR, +}; +use serde::{Deserialize, Deserializer, Serialize}; +use std::io; +use std::net::IpAddr; +use std::path::{Path, PathBuf}; +use std::time::Duration; +use url::Url; + +const DEFAULT_GATEWAYS_DIR: &str = "gateways"; + +// 'DEBUG' +// where applicable, the below are defined in milliseconds +const DEFAULT_PRESENCE_SENDING_DELAY: Duration = Duration::from_millis(10_000); +const DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF: Duration = Duration::from_millis(10_000); +const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: Duration = Duration::from_millis(300_000); +const DEFAULT_INITIAL_CONNECTION_TIMEOUT: Duration = Duration::from_millis(1_500); +const DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE: usize = 2000; + +const DEFAULT_STORED_MESSAGE_FILENAME_LENGTH: u16 = 16; +const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100; + +/// Derive default path to gateway's config directory. +/// It should get resolved to `$HOME/.nym/gateways//config` +pub fn default_config_directory>(id: P) -> PathBuf { + must_get_home() + .join(NYM_DIR) + .join(DEFAULT_GATEWAYS_DIR) + .join(id) + .join(DEFAULT_CONFIG_DIR) +} + +/// Derive default path to gateways's config file. +/// It should get resolved to `$HOME/.nym/gateways//config/config.toml` +pub fn default_config_filepath>(id: P) -> PathBuf { + default_config_directory(id).join(DEFAULT_CONFIG_FILENAME) +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct KeysPathsV1_1_29 { + pub private_identity_key_file: PathBuf, + pub public_identity_key_file: PathBuf, + pub private_sphinx_key_file: PathBuf, + pub public_sphinx_key_file: PathBuf, +} + +fn de_maybe_path<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let path = PathBuf::deserialize(deserializer)?; + if path.as_os_str().is_empty() { + Ok(None) + } else { + Ok(Some(path)) + } +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct GatewayPathsV1_1_29 { + pub keys: KeysPathsV1_1_29, + + #[serde(alias = "persistent_storage")] + pub clients_storage: PathBuf, + + #[serde(deserialize_with = "de_maybe_path")] + pub network_requester_config: Option, +} + +#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct LoggingSettingsV1_1_29 {} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct ConfigV1_1_29 { + #[serde(skip)] + pub save_path: Option, + + pub gateway: GatewayV1_1_29, + + pub storage_paths: GatewayPathsV1_1_29, + + pub network_requester: NetworkRequesterV1_1_29, + + #[serde(default)] + pub logging: LoggingSettingsV1_1_29, + + #[serde(default)] + pub debug: DebugV1_1_29, +} + +impl ConfigV1_1_29 { + pub fn read_from_default_path>(id: P) -> io::Result { + read_config_from_toml_file(default_config_filepath(id)) + } +} + +impl From for Config { + fn from(value: ConfigV1_1_29) -> Self { + Config { + save_path: value.save_path, + + // \/ ADDED + host: nym_node::config::Host { + // this is a very bad default! + public_ips: vec![value.gateway.listening_address], + hostname: None, + }, + // /\ ADDED + + // \/ ADDED + http: Default::default(), + // /\ ADDED + gateway: Gateway { + version: value.gateway.version, + id: value.gateway.id, + only_coconut_credentials: value.gateway.only_coconut_credentials, + listening_address: value.gateway.listening_address, + mix_port: value.gateway.mix_port, + clients_port: value.gateway.clients_port, + + // \/ ADDED + clients_wss_port: None, + // /\ ADDED + enabled_statistics: value.gateway.enabled_statistics, + nym_api_urls: value.gateway.nym_api_urls, + nyxd_urls: value.gateway.nyxd_urls, + statistics_service_url: value.gateway.statistics_service_url, + cosmos_mnemonic: value.gateway.cosmos_mnemonic, + }, + // \/ ADDED + wireguard: Default::default(), + // /\ ADDED + storage_paths: GatewayPaths { + keys: KeysPaths { + private_identity_key_file: value.storage_paths.keys.private_identity_key_file, + public_identity_key_file: value.storage_paths.keys.public_identity_key_file, + private_sphinx_key_file: value.storage_paths.keys.private_sphinx_key_file, + public_sphinx_key_file: value.storage_paths.keys.public_sphinx_key_file, + }, + clients_storage: value.storage_paths.clients_storage, + network_requester_config: value.storage_paths.network_requester_config, + }, + network_requester: NetworkRequester { + enabled: value.network_requester.enabled, + }, + logging: LoggingSettings {}, + debug: Debug { + packet_forwarding_initial_backoff: value.debug.packet_forwarding_initial_backoff, + packet_forwarding_maximum_backoff: value.debug.packet_forwarding_maximum_backoff, + initial_connection_timeout: value.debug.initial_connection_timeout, + maximum_connection_buffer_size: value.debug.maximum_connection_buffer_size, + presence_sending_delay: value.debug.presence_sending_delay, + stored_messages_filename_length: value.debug.stored_messages_filename_length, + message_retrieval_limit: value.debug.message_retrieval_limit, + use_legacy_framed_packet_version: value.debug.use_legacy_framed_packet_version, + }, + } + } +} + +#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)] +pub struct GatewayV1_1_29 { + /// Version of the gateway for which this configuration was created. + pub version: String, + + /// ID specifies the human readable ID of this particular gateway. + pub id: String, + + /// Indicates whether this gateway is accepting only coconut credentials for accessing the + /// the mixnet, or if it also accepts non-paying clients + #[serde(default)] + pub only_coconut_credentials: bool, + + /// Address to which this mixnode will bind to and will be listening for packets. + pub listening_address: IpAddr, + + /// Port used for listening for all mixnet traffic. + /// (default: 1789) + pub mix_port: u16, + + /// Port used for listening for all client-related traffic. + /// (default: 9000) + pub clients_port: u16, + + /// Whether gateway collects and sends anonymized statistics + pub enabled_statistics: bool, + + /// Domain address of the statistics service + pub statistics_service_url: Url, + + /// Addresses to APIs from which the node gets the view of the network. + #[serde(alias = "validator_api_urls")] + pub nym_api_urls: Vec, + + /// Addresses to validators which the node uses to check for double spending of ERC20 tokens. + #[serde(alias = "validator_nymd_urls")] + pub nyxd_urls: Vec, + + /// Mnemonic of a cosmos wallet used in checking for double spending. + // #[deprecated(note = "move to storage")] + // TODO: I don't think this should be stored directly in the config... + pub cosmos_mnemonic: bip39::Mnemonic, +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(default)] +pub struct NetworkRequesterV1_1_29 { + pub enabled: bool, +} + +#[allow(clippy::derivable_impls)] +impl Default for NetworkRequesterV1_1_29 { + fn default() -> Self { + NetworkRequesterV1_1_29 { enabled: false } + } +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(default)] +pub struct DebugV1_1_29 { + /// Initial value of an exponential backoff to reconnect to dropped TCP connection when + /// forwarding sphinx packets. + #[serde(with = "humantime_serde")] + pub packet_forwarding_initial_backoff: Duration, + + /// Maximum value of an exponential backoff to reconnect to dropped TCP connection when + /// forwarding sphinx packets. + #[serde(with = "humantime_serde")] + pub packet_forwarding_maximum_backoff: Duration, + + /// Timeout for establishing initial connection when trying to forward a sphinx packet. + #[serde(with = "humantime_serde")] + pub initial_connection_timeout: Duration, + + /// Maximum number of packets that can be stored waiting to get sent to a particular connection. + pub maximum_connection_buffer_size: usize, + + /// Delay between each subsequent presence data being sent. + #[serde(with = "humantime_serde")] + pub presence_sending_delay: Duration, + + /// Length of filenames for new client messages. + pub stored_messages_filename_length: u16, + + /// Number of messages from offline client that can be pulled at once from the storage. + pub message_retrieval_limit: i64, + + /// Specifies whether the mixnode should be using the legacy framing for the sphinx packets. + // it's set to true by default. The reason for that decision is to preserve compatibility with the + // existing nodes whilst everyone else is upgrading and getting the code for handling the new field. + // It shall be disabled in the subsequent releases. + pub use_legacy_framed_packet_version: bool, +} + +impl Default for DebugV1_1_29 { + fn default() -> Self { + DebugV1_1_29 { + packet_forwarding_initial_backoff: DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF, + packet_forwarding_maximum_backoff: DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF, + initial_connection_timeout: DEFAULT_INITIAL_CONNECTION_TIMEOUT, + presence_sending_delay: DEFAULT_PRESENCE_SENDING_DELAY, + maximum_connection_buffer_size: DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE, + stored_messages_filename_length: DEFAULT_STORED_MESSAGE_FILENAME_LENGTH, + message_retrieval_limit: DEFAULT_MESSAGE_RETRIEVAL_LIMIT, + use_legacy_framed_packet_version: false, + } + } +} diff --git a/gateway/src/config/template.rs b/gateway/src/config/template.rs index 7e7563edf9..0f77d499fc 100644 --- a/gateway/src/config/template.rs +++ b/gateway/src/config/template.rs @@ -9,7 +9,18 @@ pub(crate) const CONFIG_TEMPLATE: &str = r#" # This is a TOML config file. # For more information, see https://github.com/toml-lang/toml -##### main base mixnode config options ##### +##### main base gateway config options ##### + +[host] +# Ip address(es) of this host, such as 1.1.1.1 that external clients will use for connections. +public_ips = [ + {{#each host.public_ips }} + '{{this}}', + {{/each}} +] + +# (temporary) Optional hostname of this node, for example nymtech.net. +hostname = '{{ host.hostname }}' [gateway] # Version of the gateway for which this configuration was created. @@ -33,6 +44,10 @@ mix_port = {{ gateway.mix_port }} # (default: 9000) clients_port = {{ gateway.clients_port }} +# If applicable, announced port for listening for secure websocket client traffic. +# (default: 0 - disabled) +clients_wss_port ={{#if gateway.clients_wss_port }} {{ gateway.clients_wss_port }} {{else}} 0 {{/if}} + # Wheather gateway collects and sends anonymized statistics enabled_statistics = {{ gateway.enabled_statistics }} @@ -55,6 +70,14 @@ nyxd_urls = [ cosmos_mnemonic = '{{ gateway.cosmos_mnemonic }}' +[http] +# Socket address this node will use for binding its http API. +# default: `0.0.0.0:8080` +bind_address = '{{ http.bind_address }}' + +# Path to assets directory of custom landing page of this node +landing_page_assets_path = '{{ http.landing_page_assets_path }}' + [network_requester] # Specifies whether network requester service is enabled in this process. enabled = {{ network_requester.enabled }} diff --git a/gateway/src/error.rs b/gateway/src/error.rs index 80fee0a7fa..438b684981 100644 --- a/gateway/src/error.rs +++ b/gateway/src/error.rs @@ -106,16 +106,10 @@ pub(crate) enum GatewayError { #[from] source: NyxdError, }, - #[error("Error verifying hmac digest")] - HmacDigestError { - #[from] - source: hmac::digest::MacError, - }, - #[error("Invalid hmac length")] - HmacInvalidLength { - #[from] - source: hmac::digest::InvalidLength, - }, + + // TODO: in the future this should work the other way, i.e. NymNode depending on Gateway errors + #[error(transparent)] + NymNodeError(#[from] nym_node::error::NymNodeError), } impl From for GatewayError { diff --git a/gateway/src/http/mod.rs b/gateway/src/http/mod.rs new file mode 100644 index 0000000000..eabb377456 --- /dev/null +++ b/gateway/src/http/mod.rs @@ -0,0 +1,141 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::Config; +use crate::error::GatewayError; +use crate::node::helpers::load_public_key; +use nym_bin_common::bin_info_owned; +use nym_crypto::asymmetric::{encryption, identity}; +use nym_node::error::NymNodeError; +use nym_node::http::api::api_requests; +use nym_node::http::api::api_requests::SignedHostInformation; +use nym_node::http::router::WireguardAppState; +use nym_node::wireguard::types::GatewayClientRegistry; +use nym_sphinx::addressing::clients::Recipient; +use nym_task::TaskClient; +use std::sync::Arc; + +fn load_gateway_details( + config: &Config, +) -> Result { + let wireguard = if config.wireguard.enabled { + Some(api_requests::v1::gateway::models::Wireguard { + port: config.wireguard.announced_port, + public_key: "placeholder key value".to_string(), + }) + } else { + None + }; + + Ok(api_requests::v1::gateway::models::Gateway { + client_interfaces: api_requests::v1::gateway::models::ClientInterfaces { + wireguard, + mixnet_websockets: Some(api_requests::v1::gateway::models::WebSockets { + ws_port: config.gateway.clients_port, + wss_port: config.gateway.clients_wss_port, + }), + }, + }) +} + +fn load_host_details( + config: &Config, + sphinx_key: &encryption::PublicKey, + identity_keypair: &identity::KeyPair, +) -> Result { + let host_info = api_requests::v1::node::models::HostInformation { + ip_address: config.host.public_ips.clone(), + hostname: config.host.hostname.clone(), + keys: api_requests::v1::node::models::HostKeys { + ed25519: identity_keypair.public_key().to_base58_string(), + x25519: sphinx_key.to_base58_string(), + }, + }; + + let signed_info = SignedHostInformation::new(host_info, identity_keypair.private_key()) + .map_err(NymNodeError::from)?; + Ok(signed_info) +} + +fn load_network_requester_details( + config: &Config, + network_requester_config: &nym_network_requester::Config, +) -> Result { + let identity_public_key: identity::PublicKey = load_public_key( + &network_requester_config + .storage_paths + .common_paths + .keys + .public_identity_key_file, + "network requester identity", + )?; + + let dh_public_key: encryption::PublicKey = load_public_key( + &network_requester_config + .storage_paths + .common_paths + .keys + .public_encryption_key_file, + "network requester diffie hellman", + )?; + + let gateway_identity_public_key: identity::PublicKey = load_public_key( + &config.storage_paths.keys.public_identity_key_file, + "gateway identity", + )?; + + Ok( + api_requests::v1::network_requester::models::NetworkRequester { + encoded_identity_key: identity_public_key.to_base58_string(), + encoded_x25519_key: dh_public_key.to_base58_string(), + address: Recipient::new( + identity_public_key, + dh_public_key, + gateway_identity_public_key, + ) + .to_string(), + }, + ) +} + +pub(crate) fn start_http_api( + gateway_config: &Config, + network_requester_config: Option<&nym_network_requester::Config>, + client_registry: Arc, + identity_keypair: &identity::KeyPair, + // TODO: this should be a wg specific key and not re-used sphinx + sphinx_keypair: Arc, + + task_client: TaskClient, +) -> Result<(), GatewayError> { + // is it suboptimal to load all the keys, etc for the second time after they've already been + // retrieved during startup of the rest of the components? + // yes, a bit. + // but in the grand scheme of things performance penalty is negligible since it's only happening on startup + // and makes the code a bit nicer to manage. on top of it, all of it will refactored anyway at some point + // (famous last words, eh? - 22.09.23) + let mut config = nym_node::http::Config::new( + bin_info_owned!(), + load_host_details( + gateway_config, + sphinx_keypair.public_key(), + identity_keypair, + )?, + ) + .with_gateway(load_gateway_details(gateway_config)?) + .with_landing_page_assets(gateway_config.http.landing_page_assets_path.as_ref()); + + if let Some(nr_config) = network_requester_config { + config = config + .with_network_requester(load_network_requester_details(gateway_config, nr_config)?) + } + + let wg_state = WireguardAppState::new(sphinx_keypair, client_registry, Default::default()); + let router = nym_node::http::NymNodeRouter::new(config, Some(wg_state)); + + let server = router + .build_server(&gateway_config.http.bind_address)? + .with_task_client(task_client); + tokio::spawn(async move { server.run().await }); + Ok(()) +} diff --git a/gateway/src/main.rs b/gateway/src/main.rs index 1f3f54b398..16ef053776 100644 --- a/gateway/src/main.rs +++ b/gateway/src/main.rs @@ -17,6 +17,7 @@ use std::error::Error; mod commands; mod config; pub(crate) mod error; +mod http; mod node; pub(crate) mod support; @@ -46,13 +47,14 @@ struct Cli { #[tokio::main] async fn main() -> Result<(), Box> { + setup_logging(); + let args = Cli::parse(); setup_env(args.config_env_file.as_ref()); if !args.no_banner { maybe_print_banner(crate_name!(), crate_version!()); } - setup_logging(); commands::execute(args).await.map_err(|err| { if atty::is(atty::Stream::Stdout) { diff --git a/gateway/src/node/http/api/mod.rs b/gateway/src/node/http/api/mod.rs deleted file mode 100644 index c0753a12f8..0000000000 --- a/gateway/src/node/http/api/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub(crate) mod v1; diff --git a/gateway/src/node/http/api/v1/client_registry.rs b/gateway/src/node/http/api/v1/client_registry.rs deleted file mode 100644 index fc8d3a8a94..0000000000 --- a/gateway/src/node/http/api/v1/client_registry.rs +++ /dev/null @@ -1,105 +0,0 @@ -use axum::extract::Path; -use nym_types::gateway_client_registration::{ClientMessage, GatewayClient, InitMessage}; -use nym_types::wireguard::PeerPublicKey; -use std::sync::Arc; - -use axum::http::StatusCode; -use axum::{extract::State, Json}; -use std::str::FromStr; - -// use axum_macros::debug_handler; - -use crate::node::http::ApiState; - -async fn process_final_message(client: GatewayClient, state: Arc) -> StatusCode { - let preshared_nonce = { - if let Some(nonce) = state.registration_in_progress.get(client.pub_key()) { - *nonce - } else { - return StatusCode::BAD_REQUEST; - } - }; - - if client - .verify(state.sphinx_key_pair.private_key(), preshared_nonce) - .is_ok() - { - { - state.registration_in_progress.remove(client.pub_key()); - } - { - state - .client_registry - .insert(client.pub_key().clone(), client); - } - return StatusCode::OK; - } - - StatusCode::BAD_REQUEST -} - -async fn process_init_message(init_message: InitMessage, state: Arc) -> u64 { - let nonce: u64 = fastrand::u64(..); - state - .registration_in_progress - .insert(init_message.pub_key().clone(), nonce); - nonce -} - -// #[debug_handler] -pub(crate) async fn register_client( - State(state): State>, - Json(payload): Json, -) -> (StatusCode, Json>) { - match payload { - ClientMessage::Init(i) => ( - StatusCode::OK, - Json(Some(process_init_message(i, Arc::clone(&state)).await)), - ), - ClientMessage::Final(client) => ( - process_final_message(client, Arc::clone(&state)).await, - Json(None), - ), - } -} - -pub(crate) async fn get_all_clients( - State(state): State>, -) -> (StatusCode, Json>) { - ( - StatusCode::OK, - Json( - state - .client_registry - .iter() - .map(|c| c.pub_key().clone()) - .collect::>(), - ), - ) -} - -pub(crate) async fn get_client( - Path(pub_key): Path, - State(state): State>, -) -> (StatusCode, Json>) { - let pub_key = match PeerPublicKey::from_str(&pub_key) { - Ok(pub_key) => pub_key, - Err(_) => return (StatusCode::BAD_REQUEST, Json(vec![])), - }; - let clients = state - .client_registry - .iter() - .filter_map(|r| { - let client = r.value(); - if client.pub_key() == &pub_key { - Some(client.clone()) - } else { - None - } - }) - .collect::>(); - if clients.is_empty() { - return (StatusCode::NOT_FOUND, Json(clients)); - } - (StatusCode::OK, Json(clients)) -} diff --git a/gateway/src/node/http/api/v1/mod.rs b/gateway/src/node/http/api/v1/mod.rs deleted file mode 100644 index 082c8dd954..0000000000 --- a/gateway/src/node/http/api/v1/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub(crate) mod client_registry; diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 6d7ddf44cd..f902bb66d7 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -5,6 +5,7 @@ use self::storage::PersistentStorage; use crate::commands::helpers::{override_network_requester_config, OverrideNetworkRequesterConfig}; use crate::config::Config; use crate::error::GatewayError; +use crate::http::start_http_api; use crate::node::client_handling::active_clients::ActiveClientsStore; use crate::node::client_handling::embedded_network_requester::{ LocalNetworkRequesterHandle, MessageRouter, @@ -12,7 +13,6 @@ use crate::node::client_handling::embedded_network_requester::{ use crate::node::client_handling::websocket; use crate::node::client_handling::websocket::connection_handler::coconut::CoconutVerifier; use crate::node::helpers::{initialise_main_storage, load_network_requester_config}; -use crate::node::http::start_http_api; use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler; use crate::node::statistics::collector::GatewayStatisticsCollector; use crate::node::storage::Storage; @@ -24,9 +24,9 @@ use nym_crypto::asymmetric::{encryption, identity}; use nym_mixnet_client::forwarder::{MixForwardingSender, PacketForwarder}; use nym_network_defaults::NymNetworkDetails; use nym_network_requester::{LocalGateway, NRServiceProviderBuilder}; +use nym_node::wireguard::types::GatewayClientRegistry; use nym_statistics_common::collector::StatisticsSender; use nym_task::{TaskClient, TaskManager}; -use nym_types::gateway_client_registration::GatewayClientRegistry; use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient}; use rand::seq::SliceRandom; use rand::thread_rng; @@ -37,7 +37,6 @@ use std::sync::Arc; pub(crate) mod client_handling; pub(crate) mod helpers; -pub(crate) mod http; pub(crate) mod mixnet_handling; pub(crate) mod statistics; pub(crate) mod storage; @@ -341,6 +340,15 @@ impl Gateway { CoconutVerifier::new(nyxd_client) }; + start_http_api( + &self.config, + self.network_requester_opts.as_ref().map(|o| &o.config), + self.client_registry.clone(), + self.identity_keypair.as_ref(), + self.sphinx_keypair.clone(), + shutdown.subscribe().named("http-api"), + )?; + let mix_forwarding_channel = self.start_packet_forwarder(shutdown.subscribe().named("PacketForwarder")); @@ -395,12 +403,6 @@ impl Gateway { bail!("{err}") } - // This should likely be wireguard feature gated, but its easier to test if it hangs in here - tokio::spawn(start_http_api( - Arc::clone(&self.client_registry), - Arc::clone(&self.sphinx_keypair), - )); - info!("Finished nym gateway startup procedure - it should now be able to receive mix and client traffic!"); if let Err(err) = Self::wait_for_interrupt(shutdown).await { diff --git a/integrations/bity/Cargo.toml b/integrations/bity/Cargo.toml index db8bdc9420..d2b8e9ee10 100644 --- a/integrations/bity/Cargo.toml +++ b/integrations/bity/Cargo.toml @@ -7,7 +7,7 @@ rust-version = "1.56" [dependencies] serde = { version = "1", features = ["derive"] } serde_json = "1" -thiserror = "1.0" +thiserror = { workspace = true } k256 = { workspace = true, features = ["ecdsa", "sha256"] } eyre = "0.6.5" diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 4389d27de8..4691bf250f 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -16,7 +16,7 @@ rust-version = "1.56" [dependencies] async-trait = { workspace = true } -bs58 = {version = "0.4.0" } +bs58 = { version = "0.4.0" } bip39 = { workspace = true } cfg-if = "1.0" clap = { version = "4.0", features = ["cargo", "derive"] } @@ -27,7 +27,6 @@ humantime-serde = "1.0" lazy_static = "1.4.0" log = { workspace = true } pin-project = "1.0" -pretty_env_logger = "0.4.0" rand = "0.8.5" rand-07 = { package = "rand", version = "0.7.3" } # required for compatibility reqwest = { workspace = true, features = ["json"] } @@ -49,7 +48,7 @@ url = { workspace = true } ts-rs = { workspace = true, optional = true} -anyhow = "1.0" +anyhow = { workspace = true } getset = "0.1.1" sqlx = { version = "0.6.2", features = [ @@ -61,7 +60,7 @@ sqlx = { version = "0.6.2", features = [ okapi = { version = "0.7.0-rc.1", features = ["impl_json_schema"] } rocket_okapi = { version = "0.8.0-rc.2", features = ["swagger"] } -schemars = { version = "0.8", features = ["preserve_order"] } +schemars = { workspace = true, features = ["preserve_order"] } zeroize = { workspace = true } ## ephemera-specific @@ -106,13 +105,14 @@ nym-api-requests = { path = "nym-api-requests" } nym-validator-client = { path = "../common/client-libs/validator-client" } nym-bin-common = { path = "../common/bin-common" } nym-node-tester-utils = { path = "../common/node-tester-utils" } +nym-node-requests = { path = "../nym-node/nym-node-requests" } [features] no-reward = [] generate-ts = ["ts-rs"] [build-dependencies] -tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] } +tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } sqlx = { version = "0.6.2", features = [ "runtime-tokio-rustls", "sqlite", diff --git a/nym-api/nym-api-requests/Cargo.toml b/nym-api/nym-api-requests/Cargo.toml index 2d39074adb..d9869bd7ae 100644 --- a/nym-api/nym-api-requests/Cargo.toml +++ b/nym-api/nym-api-requests/Cargo.toml @@ -10,13 +10,14 @@ bs58 = "0.4.0" cosmrs = { workspace = true } cosmwasm-std = { workspace = true } getset = "0.1.1" -schemars = { version = "0.8", features = ["preserve_order"] } -serde = { version = "1.0", features = ["derive"] } +schemars = { workspace = true, features = ["preserve_order"] } +serde = { workspace = true, features = ["derive"] } ts-rs = { workspace = true, optional = true } nym-coconut-interface = { path = "../../common/coconut-interface" } nym-mixnet-contract-common = { path= "../../common/cosmwasm-smart-contracts/mixnet-contract" } +nym-node-requests = { path = "../../nym-node/nym-node-requests", default-features = false } [features] default = [] -generate-ts = ["ts-rs"] +generate-ts = ["ts-rs", "nym-mixnet-contract-common/generate-ts"] diff --git a/nym-api/nym-api-requests/src/models.rs b/nym-api/nym-api-requests/src/models.rs index 319d49edd1..3ab82c320a 100644 --- a/nym-api/nym-api-requests/src/models.rs +++ b/nym-api/nym-api-requests/src/models.rs @@ -9,8 +9,11 @@ use nym_mixnet_contract_common::rewarding::RewardEstimate; use nym_mixnet_contract_common::{ GatewayBond, IdentityKey, Interval, MixId, MixNode, Percent, RewardedSetNodeStatus, }; +use nym_node_requests::api::v1::gateway::models::WebSockets; +use nym_node_requests::api::v1::node::models::{BinaryBuildInformationOwned, HostInformation}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use std::fmt::{Display, Formatter}; use std::{fmt, time::Duration}; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] @@ -30,6 +33,12 @@ impl RequestError { } } +impl Display for RequestError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + self.message.fmt(f) + } +} + #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( @@ -135,6 +144,10 @@ impl MixNodeBondAnnotated { #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct GatewayBondAnnotated { pub gateway_bond: GatewayBond, + + #[serde(default)] + pub self_described: Option, + // NOTE: the performance field is deprecated in favour of node_performance pub performance: Performance, pub node_performance: NodePerformance, @@ -151,6 +164,11 @@ impl GatewayBondAnnotated { } } +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +pub struct GatewayDescription { + // for now only expose what we need. this struct will evolve in the future (or be incorporated into nym-node properly) +} + #[derive(Debug, Serialize, Deserialize, JsonSchema)] pub struct ComputeRewardEstParam { pub performance: Option, @@ -337,3 +355,29 @@ pub struct CirculatingSupplyResponse { pub vesting_tokens: Coin, pub circulating_supply: Coin, } + +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +pub struct NymNodeDescription { + pub host_information: HostInformation, + + // TODO: do we really care about ALL build info or just the version? + pub build_information: BinaryBuildInformationOwned, + + // for now we only care about their ws/wss situation, nothing more + pub mixnet_websockets: WebSockets, +} + +#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)] +pub struct DescribedGateway { + pub bond: GatewayBond, + pub self_described: Option, +} + +impl From for DescribedGateway { + fn from(bond: GatewayBond) -> Self { + DescribedGateway { + bond, + self_described: None, + } + } +} diff --git a/nym-api/src/circulating_supply_api/cache/data.rs b/nym-api/src/circulating_supply_api/cache/data.rs index 162429bf58..0ca5b7a23a 100644 --- a/nym-api/src/circulating_supply_api/cache/data.rs +++ b/nym-api/src/circulating_supply_api/cache/data.rs @@ -30,9 +30,9 @@ impl<'a> From<&'a CirculatingSupplyCacheData> for CirculatingSupplyResponse { fn from(value: &'a CirculatingSupplyCacheData) -> Self { CirculatingSupplyResponse { total_supply: value.total_supply.clone().into(), - mixmining_reserve: value.mixmining_reserve.clone().into_inner().into(), - vesting_tokens: value.vesting_tokens.clone().into_inner().into(), - circulating_supply: value.circulating_supply.clone().into_inner().into(), + mixmining_reserve: value.mixmining_reserve.clone().into(), + vesting_tokens: value.vesting_tokens.clone().into(), + circulating_supply: value.circulating_supply.clone().into(), } } } diff --git a/nym-api/src/circulating_supply_api/cache/mod.rs b/nym-api/src/circulating_supply_api/cache/mod.rs index 70794bc72e..a9f6279e8c 100644 --- a/nym-api/src/circulating_supply_api/cache/mod.rs +++ b/nym-api/src/circulating_supply_api/cache/mod.rs @@ -85,8 +85,10 @@ impl CirculatingSupplyCache { log::info!("the number of tokens still vesting is now {vesting_tokens}"); log::info!("the circulating supply is now {circulating_supply}"); - cache.mixmining_reserve.update(mixmining_reserve); - cache.vesting_tokens.update(vesting_tokens); - cache.circulating_supply.update(circulating_supply); + cache.mixmining_reserve.unchecked_update(mixmining_reserve); + cache.vesting_tokens.unchecked_update(vesting_tokens); + cache + .circulating_supply + .unchecked_update(circulating_supply); } } diff --git a/nym-api/src/main.rs b/nym-api/src/main.rs index a259879ace..1320efa590 100644 --- a/nym-api/src/main.rs +++ b/nym-api/src/main.rs @@ -6,7 +6,9 @@ extern crate rocket; use crate::epoch_operations::RewardedSetUpdater; use crate::network::models::NetworkDetails; +use crate::node_describe_cache::DescribedNodes; use crate::node_status_api::uptime_updater::HistoricalUptimeUpdater; +use crate::support::caching::cache::SharedCache; use crate::support::cli; use crate::support::cli::CliArgs; use crate::support::config::Config; @@ -34,8 +36,10 @@ mod ephemera; mod epoch_operations; pub(crate) mod network; mod network_monitor; +pub(crate) mod node_describe_cache; pub(crate) mod node_status_api; pub(crate) mod nym_contract_cache; +pub(crate) mod nym_nodes; pub(crate) mod support; struct ShutdownHandles { @@ -90,6 +94,19 @@ async fn start_nym_api_tasks( let node_status_cache_state = rocket.state::().unwrap(); let circulating_supply_cache_state = rocket.state::().unwrap(); let maybe_storage = rocket.state::(); + let described_nodes_state = rocket.state::>().unwrap(); + + // start note describe cache refresher + // we should be doing the below, but can't due to our current startup structure + // let refresher = node_describe_cache::new_refresher(&config.topology_cacher); + // let cache = refresher.get_shared_cache(); + node_describe_cache::new_refresher_with_initial_value( + &config.topology_cacher, + nym_contract_cache_state.clone(), + described_nodes_state.to_owned(), + ) + .named("node-self-described-data-refresher") + .start(shutdown.subscribe_named("node-self-described-data-refresher")); // start all the caches first let nym_contract_cache_listener = nym_contract_cache::start_refresher( @@ -98,6 +115,7 @@ async fn start_nym_api_tasks( nyxd_client.clone(), &shutdown, ); + node_status_api::start_cache_refresh( &config.node_status_api, nym_contract_cache_state, diff --git a/nym-api/src/network/routes.rs b/nym-api/src/network/routes.rs index 77f60f0fa9..05dd0b8524 100644 --- a/nym-api/src/network/routes.rs +++ b/nym-api/src/network/routes.rs @@ -25,14 +25,13 @@ pub(crate) async fn nym_contracts( ) -> Json>> { let info = cache.contract_details().await; Json( - info.value - .into_iter() + info.iter() .map(|(contract, info)| { ( - contract, + contract.to_owned(), ContractInformation { - address: info.address.map(|a| a.to_string()), - details: info.base, + address: info.address.as_ref().map(|a| a.to_string()), + details: info.base.clone(), }, ) }) @@ -47,14 +46,13 @@ pub(crate) async fn nym_contracts_detailed( ) -> Json>> { let info = cache.contract_details().await; Json( - info.value - .into_iter() + info.iter() .map(|(contract, info)| { ( - contract, + contract.to_owned(), ContractInformation { - address: info.address.map(|a| a.to_string()), - details: info.detailed, + address: info.address.as_ref().map(|a| a.to_string()), + details: info.detailed.clone(), }, ) }) diff --git a/nym-api/src/node_describe_cache/mod.rs b/nym-api/src/node_describe_cache/mod.rs new file mode 100644 index 0000000000..fc1c697cac --- /dev/null +++ b/nym-api/src/node_describe_cache/mod.rs @@ -0,0 +1,241 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::nym_contract_cache::cache::NymContractCache; +use crate::support::caching::cache::{SharedCache, UninitialisedCache}; +use crate::support::caching::refresher::{CacheItemProvider, CacheRefresher}; +use crate::support::config; +use crate::support::config::DEFAULT_NODE_DESCRIBE_BATCH_SIZE; +use futures_util::{stream, StreamExt}; +use nym_api_requests::models::NymNodeDescription; +use nym_config::defaults::DEFAULT_NYM_NODE_HTTP_PORT; +use nym_contracts_common::IdentityKey; +use nym_mixnet_contract_common::Gateway; +use nym_node_requests::api::client::{NymNodeApiClientError, NymNodeApiClientExt}; +use std::collections::HashMap; +use thiserror::Error; + +// type alias for ease of use +pub type DescribedNodes = HashMap; + +#[derive(Debug, Error)] +pub enum NodeDescribeCacheError { + #[error("contract cache hasn't been initialised")] + UninitialisedContractCache { + #[from] + source: UninitialisedCache, + }, + + #[error("gateway {gateway} has provided malformed host information ({host}: {source}")] + MalformedHost { + host: String, + + gateway: IdentityKey, + + #[source] + source: NymNodeApiClientError, + }, + + #[error("gateway '{gateway}' with host '{host}' doesn't seem to expose any of the standard API ports, i.e.: 80, 443 or {}", DEFAULT_NYM_NODE_HTTP_PORT)] + NoHttpPortsAvailable { host: String, gateway: IdentityKey }, + + #[error("failed to query gateway '{gateway}': {source}")] + ApiFailure { + gateway: IdentityKey, + + #[source] + source: NymNodeApiClientError, + }, + + // TODO: perhaps include more details here like whether key/signature/payload was malformed + #[error("could not verify signed host information for gateway '{gateway}'")] + MissignedHostInformation { gateway: IdentityKey }, +} + +pub struct NodeDescriptionProvider { + // for now we only care about gateways, nothing more + // network_gateways: SharedCache>, + contract_cache: NymContractCache, + + batch_size: usize, +} + +impl NodeDescriptionProvider { + pub(crate) fn new(contract_cache: NymContractCache) -> NodeDescriptionProvider { + NodeDescriptionProvider { + contract_cache, + batch_size: DEFAULT_NODE_DESCRIBE_BATCH_SIZE, + } + } + + #[must_use] + pub(crate) fn with_batch_size(mut self, batch_size: usize) -> Self { + self.batch_size = batch_size; + self + } +} + +async fn try_get_client( + gateway: &Gateway, +) -> Result { + let gateway_host = &gateway.host; + + // first try the standard port in case the operator didn't put the node behind the proxy, + // then default https (443) + // finally default http (80) + let addresses_to_try = vec![ + format!("http://{gateway_host}:{DEFAULT_NYM_NODE_HTTP_PORT}"), + format!("https://{gateway_host}"), + format!("http://{gateway_host}"), + ]; + + for address in addresses_to_try { + // if provided host was malformed, no point in continuing + let client = match nym_node_requests::api::Client::new_url(address, None) { + Ok(client) => client, + Err(err) => { + return Err(NodeDescribeCacheError::MalformedHost { + host: gateway_host.clone(), + gateway: gateway.identity_key.clone(), + source: err, + }); + } + }; + if let Ok(health) = client.get_health().await { + if health.status.is_up() { + return Ok(client); + } + } + } + + Err(NodeDescribeCacheError::NoHttpPortsAvailable { + host: gateway_host.clone(), + gateway: gateway.identity_key.clone(), + }) +} + +async fn get_gateway_description( + gateway: Gateway, +) -> Result<(IdentityKey, NymNodeDescription), NodeDescribeCacheError> { + let client = try_get_client(&gateway).await?; + + let host_info = + client + .get_host_information() + .await + .map_err(|err| NodeDescribeCacheError::ApiFailure { + gateway: gateway.identity_key.clone(), + source: err, + })?; + + if !host_info.verify_host_information() { + return Err(NodeDescribeCacheError::MissignedHostInformation { + gateway: gateway.identity_key, + }); + } + + let build_info = + client + .get_build_information() + .await + .map_err(|err| NodeDescribeCacheError::ApiFailure { + gateway: gateway.identity_key.clone(), + source: err, + })?; + + let websockets = + client + .get_mixnet_websockets() + .await + .map_err(|err| NodeDescribeCacheError::ApiFailure { + gateway: gateway.identity_key.clone(), + source: err, + })?; + + let description = NymNodeDescription { + host_information: host_info.data, + build_information: build_info, + mixnet_websockets: websockets, + }; + + Ok((gateway.identity_key, description)) +} + +#[async_trait] +impl CacheItemProvider for NodeDescriptionProvider { + type Item = HashMap; + type Error = NodeDescribeCacheError; + + async fn wait_until_ready(&self) { + self.contract_cache.wait_for_initial_values().await + } + + async fn try_refresh(&self) -> Result { + let gateways = self.contract_cache.gateways_all().await; + + // let guard = self.network_gateways.get().await?; + // let gateways = &*guard; + + if gateways.is_empty() { + return Ok(HashMap::new()); + } + + // TODO: somehow bypass the 'higher-ranked lifetime error' and remove that redundant clone + let websockets = stream::iter( + gateways + // .deref() + // .clone() + .into_iter() + .map(|bond| bond.gateway) + .map(get_gateway_description), + ) + .buffer_unordered(self.batch_size) + .filter_map(|res| async move { + match res { + Ok((identity, description)) => Some((identity, description)), + Err(err) => { + debug!("{err}"); + None + } + } + }) + .collect::>() + .await; + + Ok(websockets) + } +} + +// currently dead code : ( +#[allow(dead_code)] +pub(crate) fn new_refresher( + config: &config::TopologyCacher, + contract_cache: NymContractCache, + // hehe. we can't do that yet + // network_gateways: SharedCache>, +) -> CacheRefresher { + CacheRefresher::new( + Box::new( + NodeDescriptionProvider::new(contract_cache) + .with_batch_size(config.debug.node_describe_batch_size), + ), + config.debug.node_describe_caching_interval, + ) +} + +pub(crate) fn new_refresher_with_initial_value( + config: &config::TopologyCacher, + contract_cache: NymContractCache, + // hehe. we can't do that yet + // network_gateways: SharedCache>, + initial: SharedCache, +) -> CacheRefresher { + CacheRefresher::new_with_initial_value( + Box::new( + NodeDescriptionProvider::new(contract_cache) + .with_batch_size(config.debug.node_describe_batch_size), + ), + config.debug.node_describe_caching_interval, + initial, + ) +} diff --git a/nym-api/src/node_status_api/cache/mod.rs b/nym-api/src/node_status_api/cache/mod.rs index ba74ab561c..c1f2d93c61 100644 --- a/nym-api/src/node_status_api/cache/mod.rs +++ b/nym-api/src/node_status_api/cache/mod.rs @@ -63,13 +63,13 @@ impl NodeStatusCache { ) { match time::timeout(Duration::from_millis(CACHE_TIMEOUT_MS), self.inner.write()).await { Ok(mut cache) => { - cache.mixnodes_annotated.update(mixnodes); - cache.rewarded_set_annotated.update(rewarded_set); - cache.active_set_annotated.update(active_set); - cache.gateways_annotated.update(gateways); + cache.mixnodes_annotated.unchecked_update(mixnodes); + cache.rewarded_set_annotated.unchecked_update(rewarded_set); + cache.active_set_annotated.unchecked_update(active_set); + cache.gateways_annotated.unchecked_update(gateways); cache .inclusion_probabilities - .update(inclusion_probabilities); + .unchecked_update(inclusion_probabilities); } Err(e) => error!("{e}"), } @@ -90,33 +90,33 @@ impl NodeStatusCache { } pub(crate) async fn mixnodes_annotated_full(&self) -> Option>> { - self.get(|c| c.mixnodes_annotated.clone()).await + self.get(|c| c.mixnodes_annotated.clone_cache()).await } pub(crate) async fn mixnodes_annotated_filtered(&self) -> Option> { let full = self.mixnodes_annotated_full().await?; - Some(full.value.into_iter().filter(|m| !m.blacklisted).collect()) + Some(full.iter().filter(|m| !m.blacklisted).cloned().collect()) } pub(crate) async fn rewarded_set_annotated(&self) -> Option>> { - self.get(|c| c.rewarded_set_annotated.clone()).await + self.get(|c| c.rewarded_set_annotated.clone_cache()).await } pub(crate) async fn active_set_annotated(&self) -> Option>> { - self.get(|c| c.active_set_annotated.clone()).await + self.get(|c| c.active_set_annotated.clone_cache()).await } pub(crate) async fn gateways_annotated_full(&self) -> Option>> { - self.get(|c| c.gateways_annotated.clone()).await + self.get(|c| c.gateways_annotated.clone_cache()).await } pub(crate) async fn gateways_annotated_filtered(&self) -> Option> { let full = self.gateways_annotated_full().await?; - Some(full.value.into_iter().filter(|m| !m.blacklisted).collect()) + Some(full.iter().filter(|m| !m.blacklisted).cloned().collect()) } pub(crate) async fn inclusion_probabilities(&self) -> Option> { - self.get(|c| c.inclusion_probabilities.clone()).await + self.get(|c| c.inclusion_probabilities.clone_cache()).await } pub async fn mixnode_details( diff --git a/nym-api/src/node_status_api/cache/node_sets.rs b/nym-api/src/node_status_api/cache/node_sets.rs index a80c84d2d1..f871505016 100644 --- a/nym-api/src/node_status_api/cache/node_sets.rs +++ b/nym-api/src/node_status_api/cache/node_sets.rs @@ -180,6 +180,7 @@ pub(crate) async fn annotate_gateways_with_details( annotated.push(GatewayBondAnnotated { blacklisted: blacklist.contains(&gateway_bond.gateway.identity_key), gateway_bond, + self_described: None, performance, node_performance, }); diff --git a/nym-api/src/node_status_api/mod.rs b/nym-api/src/node_status_api/mod.rs index d3488eb99a..c87b7e5b1c 100644 --- a/nym-api/src/node_status_api/mod.rs +++ b/nym-api/src/node_status_api/mod.rs @@ -1,6 +1,12 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use self::cache::refresher::NodeStatusCacheRefresher; +use crate::support::config; +use crate::{ + nym_contract_cache::cache::NymContractCache, + support::{self, storage}, +}; pub(crate) use cache::NodeStatusCache; use nym_task::TaskManager; use okapi::openapi3::OpenApi; @@ -8,13 +14,6 @@ use rocket::Route; use rocket_okapi::{openapi_get_routes_spec, settings::OpenApiSettings}; use std::time::Duration; -use crate::support::config; -use crate::{ - nym_contract_cache::cache::NymContractCache, - support::{self, storage}, -}; - -use self::cache::refresher::NodeStatusCacheRefresher; pub(crate) mod cache; pub(crate) mod helpers; pub(crate) mod local_guard; diff --git a/nym-api/src/nym_contract_cache/cache/mod.rs b/nym-api/src/nym_contract_cache/cache/mod.rs index ec0ce7f8e5..250ba423ac 100644 --- a/nym-api/src/nym_contract_cache/cache/mod.rs +++ b/nym-api/src/nym_contract_cache/cache/mod.rs @@ -59,17 +59,25 @@ impl NymContractCache { ) { match time::timeout(Duration::from_millis(100), self.inner.write()).await { Ok(mut cache) => { - cache.mixnodes.update(mixnodes); - cache.gateways.update(gateways); - cache.rewarded_set.update(rewarded_set); - cache.active_set.update(active_set); - cache.current_reward_params.update(Some(rewarding_params)); - cache.current_interval.update(Some(current_interval)); - cache.mix_to_family.update(mix_to_family); + cache.mixnodes.unchecked_update(mixnodes); + cache.gateways.unchecked_update(gateways); + cache.rewarded_set.unchecked_update(rewarded_set); + cache.active_set.unchecked_update(active_set); + cache + .current_reward_params + .unchecked_update(Some(rewarding_params)); + cache + .current_interval + .unchecked_update(Some(current_interval)); + cache.mix_to_family.unchecked_update(mix_to_family); // Just return empty lists when these are not available - cache.service_providers.update(services.unwrap_or_default()); - cache.registered_names.update(names.unwrap_or_default()); - cache.contracts_info.update(nym_contracts_info) + cache + .service_providers + .unchecked_update(services.unwrap_or_default()); + cache + .registered_names + .unchecked_update(names.unwrap_or_default()); + cache.contracts_info.unchecked_update(nym_contracts_info) } Err(err) => { error!("{err}"); @@ -79,7 +87,7 @@ impl NymContractCache { pub async fn mixnodes_blacklist(&self) -> Cache> { match time::timeout(Duration::from_millis(100), self.inner.read()).await { - Ok(cache) => cache.mixnodes_blacklist.clone(), + Ok(cache) => cache.mixnodes_blacklist.clone_cache(), Err(err) => { error!("{err}"); Cache::new(HashSet::new()) @@ -89,7 +97,7 @@ impl NymContractCache { pub async fn gateways_blacklist(&self) -> Cache> { match time::timeout(Duration::from_millis(100), self.inner.read()).await { - Ok(cache) => cache.gateways_blacklist.clone(), + Ok(cache) => cache.gateways_blacklist.clone_cache(), Err(err) => { error!("{err}"); Cache::new(HashSet::new()) @@ -99,11 +107,7 @@ impl NymContractCache { pub async fn update_mixnodes_blacklist(&self, add: HashSet, remove: HashSet) { let blacklist = self.mixnodes_blacklist().await; - let mut blacklist = blacklist - .value - .union(&add) - .cloned() - .collect::>(); + let mut blacklist = blacklist.union(&add).cloned().collect::>(); let to_remove = blacklist .intersection(&remove) .cloned() @@ -113,7 +117,7 @@ impl NymContractCache { } match time::timeout(Duration::from_millis(100), self.inner.write()).await { Ok(mut cache) => { - cache.mixnodes_blacklist.update(blacklist); + cache.mixnodes_blacklist.unchecked_update(blacklist); } Err(err) => { error!("Failed to update mixnodes blacklist: {err}"); @@ -128,7 +132,6 @@ impl NymContractCache { ) { let blacklist = self.gateways_blacklist().await; let mut blacklist = blacklist - .value .union(&add) .cloned() .collect::>(); @@ -141,7 +144,7 @@ impl NymContractCache { } match time::timeout(Duration::from_millis(100), self.inner.write()).await { Ok(mut cache) => { - cache.gateways_blacklist.update(blacklist); + cache.gateways_blacklist.unchecked_update(blacklist); } Err(err) => { error!("Failed to update gateways blacklist: {err}"); @@ -159,7 +162,7 @@ impl NymContractCache { if !blacklist.is_empty() { mixnodes .into_iter() - .filter(|mix| !blacklist.value.contains(&mix.mix_id())) + .filter(|mix| !blacklist.contains(&mix.mix_id())) .collect() } else { mixnodes @@ -168,7 +171,7 @@ impl NymContractCache { pub async fn mixnodes_all(&self) -> Vec { match time::timeout(Duration::from_millis(100), self.inner.read()).await { - Ok(cache) => cache.mixnodes.clone().value, + Ok(cache) => cache.mixnodes.clone(), Err(err) => { error!("{err}"); Vec::new() @@ -181,7 +184,6 @@ impl NymContractCache { Ok(cache) => cache .mixnodes .clone() - .into_inner() .into_iter() .map(|bond| bond.bond_information) .collect(), @@ -203,7 +205,7 @@ impl NymContractCache { if !blacklist.is_empty() { gateways .into_iter() - .filter(|mix| !blacklist.value.contains(mix.identity())) + .filter(|mix| !blacklist.contains(mix.identity())) .collect() } else { gateways @@ -212,7 +214,7 @@ impl NymContractCache { pub async fn gateways_all(&self) -> Vec { match time::timeout(Duration::from_millis(100), self.inner.read()).await { - Ok(cache) => cache.gateways.value.clone(), + Ok(cache) => cache.gateways.clone(), Err(err) => { error!("{err}"); Vec::new() @@ -222,7 +224,7 @@ impl NymContractCache { pub async fn rewarded_set(&self) -> Cache> { match time::timeout(Duration::from_millis(100), self.inner.read()).await { - Ok(cache) => cache.rewarded_set.clone(), + Ok(cache) => cache.rewarded_set.clone_cache(), Err(err) => { error!("{err}"); Cache::new(Vec::new()) @@ -232,7 +234,7 @@ impl NymContractCache { pub async fn active_set(&self) -> Cache> { match time::timeout(Duration::from_millis(100), self.inner.read()).await { - Ok(cache) => cache.active_set.clone(), + Ok(cache) => cache.active_set.clone_cache(), Err(err) => { error!("{err}"); Cache::new(Vec::new()) @@ -242,7 +244,7 @@ impl NymContractCache { pub async fn mix_to_family(&self) -> Cache> { match time::timeout(Duration::from_millis(100), self.inner.read()).await { - Ok(cache) => cache.mix_to_family.clone(), + Ok(cache) => cache.mix_to_family.clone_cache(), Err(err) => { error!("{err}"); Cache::new(Vec::new()) @@ -252,7 +254,7 @@ impl NymContractCache { pub(crate) async fn interval_reward_params(&self) -> Cache> { match time::timeout(Duration::from_millis(100), self.inner.read()).await { - Ok(cache) => cache.current_reward_params.clone(), + Ok(cache) => cache.current_reward_params.clone_cache(), Err(err) => { error!("{err}"); Cache::new(None) @@ -262,7 +264,7 @@ impl NymContractCache { pub(crate) async fn current_interval(&self) -> Cache> { match time::timeout(Duration::from_millis(100), self.inner.read()).await { - Ok(cache) => cache.current_interval.clone(), + Ok(cache) => cache.current_interval.clone_cache(), Err(err) => { error!("{err}"); Cache::new(None) @@ -272,7 +274,7 @@ impl NymContractCache { pub(crate) async fn contract_details(&self) -> Cache { match time::timeout(Duration::from_millis(100), self.inner.read()).await { - Ok(cache) => cache.contracts_info.clone(), + Ok(cache) => cache.contracts_info.clone_cache(), Err(err) => { error!("{err}"); Cache::default() @@ -284,12 +286,12 @@ impl NymContractCache { // it might not be the most optimal to possibly iterate the entire vector to find (or not) // the relevant value. However, the vectors are relatively small (< 10_000 elements, < 1000 for active set) - let active_set = &self.active_set().await.value; + let active_set = &self.active_set().await; if let Some(bond) = active_set.iter().find(|mix| mix.mix_id() == mix_id) { return (Some(bond.clone()), MixnodeStatus::Active); } - let rewarded_set = &self.rewarded_set().await.value; + let rewarded_set = &self.rewarded_set().await; if let Some(bond) = rewarded_set.iter().find(|mix| mix.mix_id() == mix_id) { return (Some(bond.clone()), MixnodeStatus::Standby); } @@ -308,7 +310,7 @@ impl NymContractCache { pub(crate) async fn services(&self) -> Cache> { match time::timeout(Duration::from_millis(100), self.inner.read()).await { - Ok(cache) => cache.service_providers.clone(), + Ok(cache) => cache.service_providers.clone_cache(), Err(err) => { error!("{err}"); Cache::new(Vec::new()) @@ -318,7 +320,7 @@ impl NymContractCache { pub(crate) async fn names(&self) -> Cache> { match time::timeout(Duration::from_millis(100), self.inner.read()).await { - Ok(cache) => cache.registered_names.clone(), + Ok(cache) => cache.registered_names.clone_cache(), Err(err) => { error!("{err}"); Cache::new(Vec::new()) diff --git a/nym-api/src/nym_contract_cache/routes.rs b/nym-api/src/nym_contract_cache/routes.rs index 56f1ec2bff..9840e51e97 100644 --- a/nym-api/src/nym_contract_cache/routes.rs +++ b/nym-api/src/nym_contract_cache/routes.rs @@ -49,7 +49,7 @@ pub async fn get_gateways(cache: &State) -> Json) -> Json> { - Json(cache.rewarded_set().await.value) + Json(cache.rewarded_set().await.clone()) } // DEPRECATED: this endpoint now lives in `node_status_api`. Once all consumers are updated, @@ -70,7 +70,7 @@ pub async fn get_rewarded_set_detailed( #[openapi(tag = "contract-cache")] #[get("/mixnodes/active")] pub async fn get_active_set(cache: &State) -> Json> { - Json(cache.active_set().await.value) + Json(cache.active_set().await.clone()) } // DEPRECATED: this endpoint now lives in `node_status_api`. Once all consumers are updated, @@ -93,7 +93,7 @@ pub async fn get_active_set_detailed( pub async fn get_blacklisted_mixnodes( cache: &State, ) -> Json>> { - let blacklist = cache.mixnodes_blacklist().await.value; + let blacklist = cache.mixnodes_blacklist().await.clone(); if blacklist.is_empty() { Json(None) } else { @@ -106,7 +106,7 @@ pub async fn get_blacklisted_mixnodes( pub async fn get_blacklisted_gateways( cache: &State, ) -> Json>> { - let blacklist = cache.gateways_blacklist().await.value; + let blacklist = cache.gateways_blacklist().await.clone(); if blacklist.is_empty() { Json(None) } else { @@ -119,25 +119,25 @@ pub async fn get_blacklisted_gateways( pub async fn get_interval_reward_params( cache: &State, ) -> Json> { - Json(cache.interval_reward_params().await.value) + Json(*cache.interval_reward_params().await) } #[openapi(tag = "contract-cache")] #[get("/epoch/current")] pub async fn get_current_epoch(cache: &State) -> Json> { - Json(cache.current_interval().await.value) + Json(*cache.current_interval().await) } #[openapi(tag = "contract-cache")] #[get("/services")] pub async fn get_services(cache: &State) -> Json { - let services = cache.services().await.value; + let services = cache.services().await.clone(); Json(services.as_slice().into()) } #[openapi(tag = "contract-cache")] #[get("/names")] pub async fn get_registered_names(cache: &State) -> Json { - let names = cache.names().await.value; + let names = cache.names().await.clone(); Json(names.as_slice().into()) } diff --git a/nym-api/src/nym_nodes/mod.rs b/nym-api/src/nym_nodes/mod.rs new file mode 100644 index 0000000000..4e2a10c5b0 --- /dev/null +++ b/nym-api/src/nym_nodes/mod.rs @@ -0,0 +1,16 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use okapi::openapi3::OpenApi; +use rocket::Route; +use rocket_okapi::openapi_get_routes_spec; +use rocket_okapi::settings::OpenApiSettings; + +pub(crate) mod routes; + +/// Merges the routes with http information and returns it to Rocket for serving +pub(crate) fn nym_node_routes(settings: &OpenApiSettings) -> (Vec, OpenApi) { + openapi_get_routes_spec![ + settings: routes::get_gateways_described + ] +} diff --git a/nym-api/src/nym_nodes/routes.rs b/nym-api/src/nym_nodes/routes.rs new file mode 100644 index 0000000000..cad4549b45 --- /dev/null +++ b/nym-api/src/nym_nodes/routes.rs @@ -0,0 +1,44 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::node_describe_cache::DescribedNodes; +use crate::nym_contract_cache::cache::NymContractCache; +use crate::support::caching::cache::SharedCache; +use nym_api_requests::models::DescribedGateway; +use rocket::serde::json::Json; +use rocket::State; +use rocket_okapi::openapi; +use std::ops::Deref; + +// obviously this should get refactored later on because gateways will go away. +// unless maybe this will be filtering based on which nodes got assigned gateway role? TBD + +#[openapi(tag = "Nym Nodes")] +#[get("/gateways/described")] +pub async fn get_gateways_described( + contract_cache: &State, + describe_cache: &State>, +) -> Json> { + let gateways = contract_cache.gateways_filtered().await; + if gateways.is_empty() { + return Json(Vec::new()); + } + + // if the self describe cache is unavailable, well, don't attach describe data + let Ok(self_descriptions) = describe_cache.get().await else { + return Json(gateways.into_iter().map(Into::into).collect()); + }; + + // TODO: this is extremely inefficient, but given we don't have many gateways, + // it shouldn't be too much of a problem until we go ahead with directory v3 / the smoosh 2: electric smoosharoo, + // but at that point (I hope) the whole caching situation should get refactored + Json( + gateways + .into_iter() + .map(|bond| DescribedGateway { + self_described: self_descriptions.deref().get(bond.identity()).cloned(), + bond, + }) + .collect(), + ) +} diff --git a/nym-api/src/support/caching/cache.rs b/nym-api/src/support/caching/cache.rs new file mode 100644 index 0000000000..d330d2f667 --- /dev/null +++ b/nym-api/src/support/caching/cache.rs @@ -0,0 +1,156 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use std::ops::Deref; +use std::sync::Arc; +use std::time::Duration; +use thiserror::Error; +use time::OffsetDateTime; +use tokio::sync::{RwLock, RwLockReadGuard}; + +#[derive(Debug, Error)] +#[error("the cache item has not been initialised")] +pub struct UninitialisedCache; + +pub struct SharedCache(Arc>>); + +impl Clone for SharedCache { + fn clone(&self) -> Self { + SharedCache(Arc::clone(&self.0)) + } +} + +impl Default for SharedCache { + fn default() -> Self { + SharedCache(Arc::new(RwLock::new(CachedItem { inner: None }))) + } +} + +impl SharedCache { + pub(crate) fn new() -> Self { + SharedCache::default() + } + + pub(crate) async fn update(&self, value: T) { + let mut guard = self.0.write().await; + if let Some(ref mut existing) = guard.inner { + existing.unchecked_update(value) + } else { + guard.inner = Some(Cache::new(value)) + } + } + + pub(crate) async fn get(&self) -> Result>, UninitialisedCache> { + let guard = self.0.read().await; + RwLockReadGuard::try_map(guard, |a| a.inner.as_ref()).map_err(|_| UninitialisedCache) + } + + // ignores expiration data + #[allow(dead_code)] + pub(crate) async fn unchecked_get_inner( + &self, + ) -> Result, UninitialisedCache> { + Ok(RwLockReadGuard::map(self.get().await?, |a| &a.value)) + } +} + +impl From> for SharedCache { + fn from(value: Cache) -> Self { + SharedCache(Arc::new(RwLock::new(value.into()))) + } +} + +#[derive(Default)] +pub(crate) struct CachedItem { + inner: Option>, +} + +impl CachedItem { + #[allow(dead_code)] + fn get(&self) -> Result<&Cache, UninitialisedCache> { + self.inner.as_ref().ok_or(UninitialisedCache) + } +} + +impl From> for CachedItem { + fn from(value: Cache) -> Self { + CachedItem { inner: Some(value) } + } +} + +// don't use this directly! +// opt for SharedCache instead +pub struct Cache { + value: T, + as_at: i64, +} + +impl Cache { + // ugh. I hate to expose it, but it'd have broken pre-existing code + pub(crate) fn new(value: T) -> Self { + Cache { + value, + as_at: current_unix_timestamp(), + } + } + + // ugh. I hate to expose it, but it'd have broken pre-existing code + pub(crate) fn clone_cache(&self) -> Self + where + T: Clone, + { + Cache { + value: self.value.clone(), + as_at: self.as_at, + } + } + + // ugh. I hate to expose it, but it'd have broken pre-existing code + pub(crate) fn unchecked_update(&mut self, value: T) { + self.value = value; + self.as_at = current_unix_timestamp() + } + + #[allow(dead_code)] + pub fn has_expired(&self, ttl: Duration, now: Option) -> bool { + let now = now.unwrap_or(OffsetDateTime::now_utc()).unix_timestamp(); + let diff = now - self.as_at; + + diff > (ttl.as_secs() as i64) + } + + #[allow(dead_code)] + pub fn timestamp(&self) -> i64 { + self.as_at + } + + #[allow(dead_code)] + pub fn into_inner(self) -> T { + self.value + } +} + +impl Deref for Cache { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.value + } +} + +impl Default for Cache +where + T: Default, +{ + fn default() -> Self { + Cache { + value: T::default(), + as_at: 0, + } + } +} + +fn current_unix_timestamp() -> i64 { + let now = OffsetDateTime::now_utc(); + now.unix_timestamp() +} diff --git a/nym-api/src/support/caching/mod.rs b/nym-api/src/support/caching/mod.rs index 0d2615d327..7d647c6666 100644 --- a/nym-api/src/support/caching/mod.rs +++ b/nym-api/src/support/caching/mod.rs @@ -1,59 +1,11 @@ -use serde::Serialize; -use std::ops::Deref; -use time::OffsetDateTime; +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 -#[derive(Serialize, Clone)] -pub struct Cache { - pub value: T, - as_at: i64, -} +pub(crate) mod cache; +pub(crate) mod refresher; -impl Cache { - pub fn new(value: T) -> Self { - Cache { - value, - as_at: current_unix_timestamp(), - } - } - - pub(crate) fn update(&mut self, value: T) { - self.value = value; - self.as_at = current_unix_timestamp() - } - - pub fn timestamp(&self) -> i64 { - self.as_at - } - - pub fn into_inner(self) -> T { - self.value - } -} - -impl Deref for Cache { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.value - } -} - -impl Default for Cache -where - T: Default, -{ - fn default() -> Self { - Cache { - value: T::default(), - as_at: 0, - } - } -} - -fn current_unix_timestamp() -> i64 { - let now = OffsetDateTime::now_utc(); - now.unix_timestamp() -} +// don't break existing imports +pub(crate) use cache::Cache; // The cache can emit notifications to listeners about the current state #[derive(Debug, PartialEq, Eq)] diff --git a/nym-api/src/support/caching/refresher.rs b/nym-api/src/support/caching/refresher.rs new file mode 100644 index 0000000000..bb0435a6cf --- /dev/null +++ b/nym-api/src/support/caching/refresher.rs @@ -0,0 +1,136 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::support::caching::cache::SharedCache; +use nym_task::TaskClient; +use std::time::Duration; +use tokio::time::interval; + +pub struct CacheRefresher { + name: String, + refreshing_interval: Duration, + + // TODO: the Send + Sync bounds are only required for the `start` method. could we maybe make it less restrictive? + provider: Box + Send + Sync>, + shared_cache: SharedCache, + // triggers: Vec>, +} + +#[async_trait] +pub trait CacheItemProvider { + type Item; + type Error: std::error::Error; + + async fn wait_until_ready(&self) {} + + async fn try_refresh(&self) -> Result; +} + +// pub struct TriggerFailure; +// +// #[async_trait] +// pub trait RefreshTriggerTrait { +// async fn triggerred(&mut self) -> Result<(), TriggerFailure>; +// } +// +// // TODO: how to get rid of `T: Send + Sync`? it really doesn't need to be Send + Sync +// // since it's wrapped in Shared internally anyway +// #[async_trait] +// impl RefreshTriggerTrait for watch::Receiver +// where +// T: Send + Sync, +// { +// async fn triggerred(&mut self) -> Result<(), TriggerFailure> { +// self.changed().await.map_err(|err| { +// error!("failed to process refresh trigger: {err}"); +// TriggerFailure +// }) +// } +// } + +impl CacheRefresher +where + E: std::error::Error, +{ + pub(crate) fn new( + item_provider: Box + Send + Sync>, + refreshing_interval: Duration, + ) -> Self { + CacheRefresher { + name: "GenericCacheRefresher".to_string(), + refreshing_interval, + provider: item_provider, + shared_cache: SharedCache::new(), + } + } + + pub(crate) fn new_with_initial_value( + item_provider: Box + Send + Sync>, + refreshing_interval: Duration, + shared_cache: SharedCache, + ) -> Self { + CacheRefresher { + name: "GenericCacheRefresher".to_string(), + refreshing_interval, + provider: item_provider, + shared_cache, + } + } + + #[must_use] + pub(crate) fn named(mut self, name: impl Into) -> Self { + self.name = name.into(); + self + } + + #[allow(dead_code)] + pub(crate) fn get_shared_cache(&self) -> SharedCache { + self.shared_cache.clone() + } + + async fn do_refresh_cache(&self) { + match self.provider.try_refresh().await { + Ok(updated_items) => { + self.shared_cache.update(updated_items).await; + } + Err(err) => { + error!("{}: failed to refresh the cache: {err}", self.name) + } + } + } + + pub async fn refresh(&self, task_client: &mut TaskClient) { + log::info!("{}: refreshing cache state", self.name); + + tokio::select! { + biased; + _ = task_client.recv() => { + log::trace!("{}: Received shutdown while refreshing cache", self.name) + } + _ = self.do_refresh_cache() => (), + } + } + + pub async fn run(&self, mut task_client: TaskClient) { + self.provider.wait_until_ready().await; + + let mut refresh_interval = interval(self.refreshing_interval); + while !task_client.is_shutdown() { + tokio::select! { + biased; + _ = task_client.recv() => { + log::trace!("{}: Received shutdown", self.name) + } + _ = refresh_interval.tick() => self.refresh(&mut task_client).await, + } + } + } + + pub fn start(self, task_client: TaskClient) + where + T: Send + Sync + 'static, + E: Send + Sync + 'static, + { + tokio::spawn(async move { self.run(task_client).await }); + } +} diff --git a/nym-api/src/support/config/mod.rs b/nym-api/src/support/config/mod.rs index 9cf1404b38..43eb0ddf8a 100644 --- a/nym-api/src/support/config/mod.rs +++ b/nym-api/src/support/config/mod.rs @@ -49,6 +49,10 @@ const DEFAULT_PER_NODE_TEST_PACKETS: usize = 3; const DEFAULT_TOPOLOGY_CACHE_INTERVAL: Duration = Duration::from_secs(30); const DEFAULT_NODE_STATUS_CACHE_INTERVAL: Duration = Duration::from_secs(120); const DEFAULT_CIRCULATING_SUPPLY_CACHE_INTERVAL: Duration = Duration::from_secs(3600); + +pub(crate) const DEFAULT_NODE_DESCRIBE_CACHE_INTERVAL: Duration = Duration::from_secs(4500); +pub(crate) const DEFAULT_NODE_DESCRIBE_BATCH_SIZE: usize = 50; + const DEFAULT_MONITOR_THRESHOLD: u8 = 60; const DEFAULT_MIN_MIXNODE_RELIABILITY: u8 = 50; const DEFAULT_MIN_GATEWAY_RELIABILITY: u8 = 20; @@ -451,12 +455,19 @@ pub struct TopologyCacher { pub struct TopologyCacherDebug { #[serde(with = "humantime_serde")] pub caching_interval: Duration, + + #[serde(with = "humantime_serde")] + pub node_describe_caching_interval: Duration, + + pub node_describe_batch_size: usize, } impl Default for TopologyCacherDebug { fn default() -> Self { TopologyCacherDebug { caching_interval: DEFAULT_TOPOLOGY_CACHE_INTERVAL, + node_describe_caching_interval: DEFAULT_NODE_DESCRIBE_CACHE_INTERVAL, + node_describe_batch_size: DEFAULT_NODE_DESCRIBE_BATCH_SIZE, } } } diff --git a/nym-api/src/support/config/old_config_v1_1_21.rs b/nym-api/src/support/config/old_config_v1_1_21.rs index 2f13baaad0..be8c06d7c8 100644 --- a/nym-api/src/support/config/old_config_v1_1_21.rs +++ b/nym-api/src/support/config/old_config_v1_1_21.rs @@ -126,6 +126,7 @@ impl From for Config { topology_cacher: TopologyCacher { debug: TopologyCacherDebug { caching_interval: value.topology_cacher.caching_interval, + ..Default::default() }, }, circulating_supply_cacher: CirculatingSupplyCacher { diff --git a/nym-api/src/support/http/mod.rs b/nym-api/src/support/http/mod.rs index b21ccdb381..5d0b646107 100644 --- a/nym-api/src/support/http/mod.rs +++ b/nym-api/src/support/http/mod.rs @@ -5,11 +5,13 @@ use crate::circulating_supply_api::cache::CirculatingSupplyCache; use crate::coconut::{self, comm::QueryCommunicationChannel, InternalSignRequest}; use crate::network::models::NetworkDetails; use crate::network::network_routes; +use crate::node_describe_cache::DescribedNodes; use crate::node_status_api::{self, NodeStatusCache}; use crate::nym_contract_cache::cache::NymContractCache; +use crate::support::caching::cache::SharedCache; use crate::support::config::Config; use crate::support::{nyxd, storage}; -use crate::{circulating_supply_api, nym_contract_cache}; +use crate::{circulating_supply_api, nym_contract_cache, nym_nodes::nym_node_routes}; use anyhow::Result; use rocket::http::Method; use rocket::{Ignite, Rocket}; @@ -39,10 +41,12 @@ pub(crate) async fn setup_rocket( "" => nym_contract_cache::nym_contract_cache_routes(&openapi_settings), "/status" => node_status_api::node_status_routes(&openapi_settings, config.network_monitor.enabled), "/network" => network_routes(&openapi_settings), + "" => nym_node_routes(&openapi_settings), } let rocket = rocket .manage(network_details) + .manage(SharedCache::::new()) .mount("/swagger", make_swagger_ui(&openapi::get_docs())) .attach(setup_cors()?) .attach(NymContractCache::stage()) diff --git a/nym-connect/desktop/Cargo.lock b/nym-connect/desktop/Cargo.lock index 00e1040483..83a2c97fe9 100644 --- a/nym-connect/desktop/Cargo.lock +++ b/nym-connect/desktop/Cargo.lock @@ -422,9 +422,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "base64ct" @@ -454,7 +454,7 @@ dependencies = [ "pbkdf2", "rand_core 0.6.4", "ripemd", - "sha2 0.10.7", + "sha2 0.10.8", "subtle 2.4.1", "zeroize", ] @@ -515,6 +515,15 @@ dependencies = [ "opaque-debug 0.2.3", ] +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "blake3" version = "1.4.1" @@ -602,6 +611,29 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "845141a4fade3f790628b7daaaa298a25b204fb28907eb54febe5142db6ce653" +[[package]] +name = "boringtun" +version = "0.6.0" +source = "git+https://github.com/cloudflare/boringtun?rev=e1d6360d6ab4529fc942a078e4c54df107abe2ba#e1d6360d6ab4529fc942a078e4c54df107abe2ba" +dependencies = [ + "aead", + "base64 0.13.1", + "blake2 0.10.6", + "chacha20poly1305", + "hex", + "hmac 0.12.1", + "ip_network", + "ip_network_table", + "libc", + "nix 0.25.1", + "parking_lot 0.12.1", + "rand_core 0.6.4", + "ring", + "tracing", + "untrusted 0.9.0", + "x25519-dalek 2.0.0", +] + [[package]] name = "brotli" version = "3.3.4" @@ -635,7 +667,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" dependencies = [ - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -1130,7 +1162,7 @@ dependencies = [ "schemars", "serde", "serde-json-wasm", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", ] @@ -1367,6 +1399,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle 2.4.1", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "curve25519-dalek-ng" version = "4.1.1" @@ -1794,7 +1853,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 3.2.0", "ed25519 1.5.3", "rand 0.7.3", "serde", @@ -1808,7 +1867,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 3.2.0", "hashbrown 0.12.3", "hex", "rand_core 0.6.4", @@ -2061,6 +2120,12 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "fiat-crypto" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" + [[package]] name = "field-offset" version = "0.3.6" @@ -2964,6 +3029,20 @@ dependencies = [ "itoa 1.0.9", ] +[[package]] +name = "http-api-client" +version = "0.1.0" +dependencies = [ + "async-trait", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tracing", + "url", + "wasmtimer", +] + [[package]] name = "http-body" version = "0.4.5" @@ -3237,6 +3316,28 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ip_network" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" + +[[package]] +name = "ip_network_table" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4099b7cfc5c5e2fe8c5edf3f6f7adf7a714c9cc697534f63a5a5da30397cb2c0" +dependencies = [ + "ip_network", + "ip_network_table-deps-treebitmap", +] + +[[package]] +name = "ip_network_table-deps-treebitmap" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e537132deb99c0eb4b752f0346b6a836200eaaa3516dd7e5514b63930a09e5d" + [[package]] name = "ipnet" version = "2.8.0" @@ -3357,7 +3458,7 @@ dependencies = [ "cfg-if", "ecdsa 0.14.8", "elliptic-curve 0.12.3", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -3370,7 +3471,7 @@ dependencies = [ "ecdsa 0.16.8", "elliptic-curve 0.13.5", "once_cell", - "sha2 0.10.7", + "sha2 0.10.8", "signature 2.1.0", ] @@ -3513,7 +3614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae926706ba42c425c9457121178330d75e273df2e82e28b758faf3de3a9acb9" dependencies = [ "arrayref", - "blake2", + "blake2 0.8.1", "chacha", "keystream", ] @@ -3730,6 +3831,18 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "libc", +] + [[package]] name = "nix" version = "0.26.2" @@ -3874,6 +3987,7 @@ dependencies = [ "getset", "nym-coconut-interface", "nym-mixnet-contract-common", + "nym-node-requests", "schemars", "serde", ] @@ -3904,6 +4018,7 @@ dependencies = [ "clap_complete_fig", "log", "pretty_env_logger", + "schemars", "semver 0.11.0", "serde", "vergen", @@ -3914,7 +4029,7 @@ name = "nym-client-core" version = "1.1.15" dependencies = [ "async-trait", - "base64 0.21.2", + "base64 0.21.4", "cfg-if", "dashmap", "dirs 4.0.0", @@ -3940,7 +4055,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "sqlx 0.6.3", "tap", "thiserror", @@ -4128,7 +4243,7 @@ dependencies = [ "rand 0.7.3", "subtle-encoding", "thiserror", - "x25519-dalek", + "x25519-dalek 1.1.1", "zeroize", ] @@ -4310,6 +4425,20 @@ dependencies = [ "url", ] +[[package]] +name = "nym-node-requests" +version = "0.1.0" +dependencies = [ + "base64 0.21.4", + "nym-bin-common", + "nym-crypto", + "nym-wireguard-types", + "schemars", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "nym-nonexhaustive-delayqueue" version = "0.1.0" @@ -4335,7 +4464,7 @@ dependencies = [ "blake3", "chacha20", "chacha20poly1305", - "curve25519-dalek", + "curve25519-dalek 3.2.0", "getrandom 0.2.10", "log", "rand 0.7.3", @@ -4602,6 +4731,7 @@ dependencies = [ "async-trait", "bs58 0.4.0", "log", + "nym-api-requests", "nym-bin-common", "nym-config", "nym-crypto", @@ -4634,6 +4764,7 @@ dependencies = [ "eyre", "flate2", "futures", + "http-api-client", "itertools", "log", "nym-api-requests", @@ -4676,6 +4807,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "nym-wireguard-types" +version = "0.1.0" +dependencies = [ + "base64 0.21.4", + "boringtun", + "dashmap", + "nym-crypto", + "serde", + "thiserror", + "x25519-dalek 2.0.0", +] + [[package]] name = "objc" version = "0.2.7" @@ -5043,7 +5187,7 @@ checksum = "56af0a30af74d0445c0bf6d9d051c979b516a1a5af790d251daee76005420a48" dependencies = [ "once_cell", "pest", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -5202,13 +5346,19 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "platforms" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" + [[package]] name = "plist" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdc0001cfea3db57a2e24bc0d818e9e20e554b5f97fabb9bc231dc240269ae06" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "indexmap 1.9.3", "line-wrap", "quick-xml 0.29.0", @@ -5598,11 +5748,11 @@ checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "reqwest" -version = "0.11.18" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "bytes", "encoding_rs", "futures-core", @@ -5623,6 +5773,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-native-tls", "tokio-socks", @@ -5633,7 +5784,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "winreg 0.10.1", + "winreg 0.50.0", ] [[package]] @@ -5691,7 +5842,7 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] @@ -5736,7 +5887,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74" dependencies = [ "globset", - "sha2 0.10.7", + "sha2 0.10.8", "walkdir", ] @@ -5825,7 +5976,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", ] [[package]] @@ -5908,7 +6059,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -5918,7 +6069,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -6247,7 +6398,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1402f54f9a3b9e2efe71c1cea24e648acce55887983553eeb858cf3115acfd49" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "chrono", "hex", "indexmap 1.9.3", @@ -6328,9 +6479,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -6468,11 +6619,11 @@ checksum = "cc43eda802856ee82a7555c7b75ceb9e07451741c7a2f5f23d036020e01189d4" dependencies = [ "aes 0.7.5", "arrayref", - "blake2", + "blake2 0.8.1", "bs58 0.4.0", "byteorder", "chacha", - "curve25519-dalek", + "curve25519-dalek 3.2.0", "digest 0.9.0", "hkdf 0.11.0", "hmac 0.11.0", @@ -6594,7 +6745,7 @@ dependencies = [ "paste", "percent-encoding", "rustls 0.19.1", - "sha2 0.10.7", + "sha2 0.10.8", "smallvec", "sqlformat 0.1.8", "sqlx-rt 0.5.13", @@ -6641,7 +6792,7 @@ dependencies = [ "percent-encoding", "rustls 0.20.8", "rustls-pemfile", - "sha2 0.10.7", + "sha2 0.10.8", "smallvec", "sqlformat 0.2.1", "sqlx-rt 0.6.3", @@ -6664,7 +6815,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "sha2 0.10.7", + "sha2 0.10.8", "sqlx-core 0.5.13", "sqlx-rt 0.5.13", "syn 1.0.109", @@ -6683,7 +6834,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "sha2 0.10.7", + "sha2 0.10.8", "sqlx-core 0.6.3", "sqlx-rt 0.6.3", "syn 1.0.109", @@ -6833,6 +6984,27 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "5.0.0" @@ -6949,7 +7121,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fbe522898e35407a8e60dc3870f7579fea2fc262a6a6072eccdd37ae1e1d91e" dependencies = [ "anyhow", - "base64 0.21.2", + "base64 0.21.4", "bytes", "cocoa", "dirs-next", @@ -7020,7 +7192,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54ad2d49fdeab4a08717f5b49a163bdc72efc3b1950b6758245fcde79b645e1a" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "brotli", "ico", "json-patch", @@ -7032,7 +7204,7 @@ dependencies = [ "semver 1.0.18", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "tauri-utils", "thiserror", "time", @@ -7179,7 +7351,7 @@ dependencies = [ "serde_bytes", "serde_json", "serde_repr", - "sha2 0.10.7", + "sha2 0.10.8", "signature 2.1.0", "subtle 2.4.1", "subtle-encoding", @@ -7283,18 +7455,18 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.44" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.44" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", @@ -7450,7 +7622,9 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", + "native-tls", "tokio", + "tokio-native-tls", "tungstenite", ] @@ -7630,6 +7804,7 @@ dependencies = [ "http", "httparse", "log", + "native-tls", "rand 0.8.5", "sha1", "thiserror", @@ -7717,13 +7892,19 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "ureq" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "log", "native-tls", "once_cell", @@ -7963,9 +8144,9 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-streams" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078" +checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" dependencies = [ "futures-util", "js-sys", @@ -8067,7 +8248,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -8077,7 +8258,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07ecc0cd7cac091bf682ec5efa18b1cff79d617b84181f38b3951dbe135f607f" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -8427,15 +8608,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] - [[package]] name = "winreg" version = "0.11.0" @@ -8446,6 +8618,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "wry" version = "0.24.3" @@ -8472,7 +8654,7 @@ dependencies = [ "once_cell", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "soup2", "tao", "thiserror", @@ -8520,11 +8702,23 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 3.2.0", "rand_core 0.5.1", "zeroize", ] +[[package]] +name = "x25519-dalek" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" +dependencies = [ + "curve25519-dalek 4.1.1", + "rand_core 0.6.4", + "serde", + "zeroize", +] + [[package]] name = "xattr" version = "1.0.1" @@ -8540,7 +8734,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" dependencies = [ - "nix", + "nix 0.26.2", "winapi", ] @@ -8577,7 +8771,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix", + "nix 0.26.2", "once_cell", "ordered-stream", "rand 0.8.5", diff --git a/nym-connect/desktop/src-tauri/Cargo.toml b/nym-connect/desktop/src-tauri/Cargo.toml index 3947434d65..193d3a53a3 100644 --- a/nym-connect/desktop/src-tauri/Cargo.toml +++ b/nym-connect/desktop/src-tauri/Cargo.toml @@ -31,7 +31,7 @@ log = { version = "0.4", features = ["serde"] } pretty_env_logger = "0.4.0" rand = "0.8" rand-07 = { package = "rand", version = "0.7.3" } -reqwest = { version = "0.11.18", features = ["json", "socks"] } +reqwest = { version = "0.11.22", features = ["json", "socks"] } rust-embed = { version = "6.4.2", features = ["include-exclude"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/nym-connect/desktop/src-tauri/src/operations/directory/gateways.rs b/nym-connect/desktop/src-tauri/src/operations/directory/gateways.rs index 56bc16ab67..fca43e8fff 100644 --- a/nym-connect/desktop/src-tauri/src/operations/directory/gateways.rs +++ b/nym-connect/desktop/src-tauri/src/operations/directory/gateways.rs @@ -8,6 +8,7 @@ use nym_bin_common::version_checker::is_minor_version_compatible; use nym_config::defaults::var_names::NYM_API; use nym_contracts_common::types::Percent; use nym_topology::gateway; +use nym_validator_client::client::NymApiClientExt; use nym_validator_client::nym_api::Client as ApiClient; use std::str::FromStr; use url::Url; @@ -16,7 +17,7 @@ use url::Url; const GATEWAY_PERFORMANCE_SCORE_THRESHOLD: u64 = 90; async fn fetch_all_gateways() -> Result> { - let api_client = ApiClient::new(Url::from_str(&std::env::var(NYM_API)?)?); + let api_client = ApiClient::new(Url::from_str(&std::env::var(NYM_API)?)?, None); let gateways = api_client.get_gateways_detailed().await?; if gateways.is_empty() { Err(BackendError::NoGatewaysFoundInDirectory) @@ -87,9 +88,12 @@ async fn select_gateway_by_latency(gateways: Vec) -> Resul .collect(); let mut rng = rand_07::rngs::OsRng; - let selected_gateway = - nym_client_core::init::helpers::choose_gateway_by_latency(&mut rng, &gateways_as_nodes) - .await?; + let selected_gateway = nym_client_core::init::helpers::choose_gateway_by_latency( + &mut rng, + &gateways_as_nodes, + false, + ) + .await?; Ok(selected_gateway) } diff --git a/nym-node/Cargo.toml b/nym-node/Cargo.toml new file mode 100644 index 0000000000..7b70ae86e0 --- /dev/null +++ b/nym-node/Cargo.toml @@ -0,0 +1,58 @@ +[package] +name = "nym-node" +version = "0.1.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = { workspace = true } +bytes = "1.5.0" +colored = "2" +serde = { workspace = true, features = ["derive"] } +serde_yaml = "0.9.25" +serde_json = { workspace = true } +thiserror = { workspace = true } +tracing = { workspace = true } +tokio = { workspace = true, features = ["macros", "sync"] } + +# Wireguard: +fastrand = "2" + +# HTTP API: +axum = { workspace = true } +# useful for `#[axum_macros::debug_handler]` +#axum-macros = "0.3.8" +mime = "0.3.17" +hyper = { workspace = true } +tower = { version = "0.4.13" } +tower-http = { version = "0.4.4", features = ["fs"] } + +# `actix_extras`? what the hell? +# hear me out first! +# we can't use `axum_extras` because of freaking ephemera that depends on `actix_extras`. +# however, it seems that pulling in `actix_extras` pulls in just enough shared features to improve `IntoParams` for our Query attributes +utoipa = { workspace = true, features = ["actix_extras"] } # can't use `"axum_extras"` feature because ephemera uses `"actix_extras"` -.-' +utoipa-swagger-ui = { workspace = true, features = ["axum"] } + +# if we ever wanted redoc/rapidoc bridges: +#utoipa-redoc = { version = "0.1.0", features = ["axum"] } +#utoipa-rapidoc = { version = "0.1.0", features = ["axum"] } + +nym-config = { path = "../common/config" } +nym-crypto = { path = "../common/crypto", features = ["asymmetric" ]} +nym-node-requests = { path = "nym-node-requests", default-features = false, features = ["openapi"]} +nym-task = { path = "../common/task" } +nym-wireguard-types = { path = "../common/wireguard-types", features = ["verify"] } + +[dev-dependencies] +dashmap = { workspace = true } +rand = "0.7.3" +nym-crypto = { path = "../common/crypto", features = ["rand"]} +hmac = "0.12.1" +x25519-dalek = { version = "2.0.0" } diff --git a/nym-node/nym-node-requests/Cargo.toml b/nym-node/nym-node-requests/Cargo.toml new file mode 100644 index 0000000000..ff7cb13336 --- /dev/null +++ b/nym-node/nym-node-requests/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "nym-node-requests" +version = "0.1.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +base64 = { workspace = true } +schemars = { workspace = true, features = ["preserve_order"] } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +thiserror = { workspace = true } + +nym-crypto = { path = "../../common/crypto", features = ["asymmetric"] } +nym-wireguard-types = { path = "../../common/wireguard-types", default-features = false } + +# feature-specific dependencies: + +## client: +async-trait = { workspace = true, optional = true } +http-api-client = { path = "../../common/http-api-client", optional = true } + +## openapi: +utoipa = { workspace = true, optional = true } +nym-bin-common = { path = "../../common/bin-common", features = ["bin_info_schema"] } + +[dev-dependencies] +tokio = { workspace = true, features = ["full"] } + +[features] +default = ["client"] +client = ["http-api-client", "async-trait"] +openapi = ["utoipa", "nym-bin-common/openapi", "nym-wireguard-types/openapi"] diff --git a/nym-node/nym-node-requests/src/api/client.rs b/nym-node/nym-node-requests/src/api/client.rs new file mode 100644 index 0000000000..1967b6963e --- /dev/null +++ b/nym-node/nym-node-requests/src/api/client.rs @@ -0,0 +1,47 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::api::v1::gateway::models::WebSockets; +use crate::api::v1::node::models::SignedHostInformation; +use crate::api::ErrorResponse; +use crate::routes; +use async_trait::async_trait; +use http_api_client::{ApiClient, HttpClientError}; +use nym_bin_common::build_information::BinaryBuildInformationOwned; + +use crate::api::v1::health::models::NodeHealth; +pub use http_api_client::Client; + +pub type NymNodeApiClientError = HttpClientError; + +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +pub trait NymNodeApiClientExt: ApiClient { + async fn get_health(&self) -> Result { + self.get_json_from(routes::api::v1::health_absolute()).await + } + + async fn get_host_information(&self) -> Result { + self.get_json_from(routes::api::v1::host_info_absolute()) + .await + } + + async fn get_build_information( + &self, + ) -> Result { + self.get_json_from(routes::api::v1::build_info_absolute()) + .await + } + + // TODO: implement calls for other endpoints; for now I only care about the wss + async fn get_mixnet_websockets(&self) -> Result { + self.get_json_from( + routes::api::v1::gateway::client_interfaces::mixnet_websockets_absolute(), + ) + .await + } +} + +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +impl NymNodeApiClientExt for Client {} diff --git a/nym-node/nym-node-requests/src/api/mod.rs b/nym-node/nym-node-requests/src/api/mod.rs new file mode 100644 index 0000000000..8da95074a9 --- /dev/null +++ b/nym-node/nym-node-requests/src/api/mod.rs @@ -0,0 +1,85 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::api::v1::node::models::HostInformation; +use crate::error::Error; +use nym_crypto::asymmetric::identity; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::fmt::{Display, Formatter}; +use std::ops::Deref; + +#[cfg(feature = "client")] +pub mod client; +pub mod v1; + +#[cfg(feature = "client")] +pub use client::Client; + +// create the type alias manually if openapi is not enabled +#[cfg(not(feature = "openapi"))] +pub type SignedHostInformation = SignedData; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +#[cfg_attr(feature = "openapi", aliases(SignedHostInformation = SignedData))] +pub struct SignedData { + // #[serde(flatten)] + pub data: T, + pub signature: String, +} + +impl SignedData { + pub fn new(data: T, key: &identity::PrivateKey) -> Result + where + T: Serialize, + { + let plaintext = serde_json::to_string(&data)?; + let signature = key.sign(plaintext).to_base58_string(); + Ok(SignedData { data, signature }) + } + + pub fn verify(&self, key: &identity::PublicKey) -> bool + where + T: Serialize, + { + let Ok(plaintext) = serde_json::to_string(&self.data) else { + return false; + }; + let Ok(signature) = identity::Signature::from_base58_string(&self.signature) else { + return false; + }; + + key.verify(plaintext, &signature).is_ok() + } +} + +impl SignedHostInformation { + pub fn verify_host_information(&self) -> bool { + let Ok(pub_key) = identity::PublicKey::from_base58_string(&self.keys.ed25519) else { + return false; + }; + + self.verify(&pub_key) + } +} + +impl Deref for SignedData { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.data + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct ErrorResponse { + pub message: String, +} + +impl Display for ErrorResponse { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + self.message.fmt(f) + } +} diff --git a/nym-node/nym-node-requests/src/api/v1/gateway/client_interfaces/mod.rs b/nym-node/nym-node-requests/src/api/v1/gateway/client_interfaces/mod.rs new file mode 100644 index 0000000000..487c41bb7d --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/gateway/client_interfaces/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod wireguard; diff --git a/nym-node/nym-node-requests/src/api/v1/gateway/client_interfaces/wireguard/mod.rs b/nym-node/nym-node-requests/src/api/v1/gateway/client_interfaces/wireguard/mod.rs new file mode 100644 index 0000000000..c57081432b --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/gateway/client_interfaces/wireguard/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod models; diff --git a/nym-node/nym-node-requests/src/api/v1/gateway/client_interfaces/wireguard/models.rs b/nym-node/nym-node-requests/src/api/v1/gateway/client_interfaces/wireguard/models.rs new file mode 100644 index 0000000000..27c086d8c8 --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/gateway/client_interfaces/wireguard/models.rs @@ -0,0 +1,7 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub use nym_wireguard_types::{ + ClientMac, ClientMessage, ClientRegistrationResponse, GatewayClient, InitMessage, Nonce, + PeerPublicKey, +}; diff --git a/nym-node/nym-node-requests/src/api/v1/gateway/mod.rs b/nym-node/nym-node-requests/src/api/v1/gateway/mod.rs new file mode 100644 index 0000000000..6c690d4f82 --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/gateway/mod.rs @@ -0,0 +1,5 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod client_interfaces; +pub mod models; diff --git a/nym-node/nym-node-requests/src/api/v1/gateway/models.rs b/nym-node/nym-node-requests/src/api/v1/gateway/models.rs new file mode 100644 index 0000000000..6287e9612a --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/gateway/models.rs @@ -0,0 +1,38 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct Gateway { + pub client_interfaces: ClientInterfaces, +} + +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct Wireguard { + #[cfg_attr(feature = "openapi", schema(example = 51820, default = 51820))] + pub port: u16, + + pub public_key: String, +} + +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct ClientInterfaces { + pub wireguard: Option, + + pub mixnet_websockets: Option, + // pub mixnet_tcp: +} + +#[derive(Serialize, Deserialize, Debug, Clone, Copy, JsonSchema)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct WebSockets { + #[cfg_attr(feature = "openapi", schema(example = 9000, default = 9000))] + pub ws_port: u16, + + pub wss_port: Option, +} diff --git a/nym-node/nym-node-requests/src/api/v1/health/mod.rs b/nym-node/nym-node-requests/src/api/v1/health/mod.rs new file mode 100644 index 0000000000..c57081432b --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/health/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod models; diff --git a/nym-node/nym-node-requests/src/api/v1/health/models.rs b/nym-node/nym-node-requests/src/api/v1/health/models.rs new file mode 100644 index 0000000000..30d9889c11 --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/health/models.rs @@ -0,0 +1,35 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::time::Duration; + +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct NodeHealth { + pub status: NodeStatus, + pub uptime: u64, +} + +impl NodeHealth { + pub fn new_healthy(uptime: Duration) -> Self { + NodeHealth { + status: NodeStatus::Up, + uptime: uptime.as_secs(), + } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +#[serde(rename_all = "camelCase")] +pub enum NodeStatus { + Up, +} + +impl NodeStatus { + pub fn is_up(&self) -> bool { + matches!(self, NodeStatus::Up) + } +} diff --git a/nym-node/nym-node-requests/src/api/v1/mixnode/mod.rs b/nym-node/nym-node-requests/src/api/v1/mixnode/mod.rs new file mode 100644 index 0000000000..c57081432b --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/mixnode/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod models; diff --git a/nym-node/nym-node-requests/src/api/v1/mixnode/models.rs b/nym-node/nym-node-requests/src/api/v1/mixnode/models.rs new file mode 100644 index 0000000000..76b8c9cc5b --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/mixnode/models.rs @@ -0,0 +1,15 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct Mixnode { + // /// Base58 encoded ed25519 EdDSA public key of the mixnode. + // pub encoded_identity_key: String, + // + // /// Base58-encoded x25519 public key used for sphinx key derivation. + // pub encoded_sphinx_key: String, +} diff --git a/nym-node/nym-node-requests/src/api/v1/mod.rs b/nym-node/nym-node-requests/src/api/v1/mod.rs new file mode 100644 index 0000000000..b07fdbb7aa --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/mod.rs @@ -0,0 +1,8 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod gateway; +pub mod health; +pub mod mixnode; +pub mod network_requester; +pub mod node; diff --git a/nym-node/nym-node-requests/src/api/v1/network_requester/mod.rs b/nym-node/nym-node-requests/src/api/v1/network_requester/mod.rs new file mode 100644 index 0000000000..c57081432b --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/network_requester/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod models; diff --git a/nym-node/nym-node-requests/src/api/v1/network_requester/models.rs b/nym-node/nym-node-requests/src/api/v1/network_requester/models.rs new file mode 100644 index 0000000000..b8aa29236b --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/network_requester/models.rs @@ -0,0 +1,31 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct NetworkRequester { + /// Base58 encoded ed25519 EdDSA public key of the network requester. + pub encoded_identity_key: String, + + /// Base58-encoded x25519 public key used for performing key exchange with remote clients. + pub encoded_x25519_key: String, + + /// Nym address of this network requester. + pub address: String, +} + +// #[derive(Serialize, Debug, Clone, ToSchema)] +// pub struct ExitPolicy { +// // pub allowed_ports: +// // pub deny_list: DenyList, +// } +// +// #[derive(Serialize, Debug, Clone, ToSchema)] +// pub struct DenyListEntry { +// // pub ports: +// // pub ips: +// pub description: String, +// } diff --git a/nym-node/nym-node-requests/src/api/v1/node/mod.rs b/nym-node/nym-node-requests/src/api/v1/node/mod.rs new file mode 100644 index 0000000000..c57081432b --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/node/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod models; diff --git a/nym-node/nym-node-requests/src/api/v1/node/models.rs b/nym-node/nym-node-requests/src/api/v1/node/models.rs new file mode 100644 index 0000000000..260752436b --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/node/models.rs @@ -0,0 +1,43 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::net::IpAddr; + +pub use crate::api::SignedHostInformation; +pub use nym_bin_common::build_information::BinaryBuildInformationOwned; + +#[derive(Clone, Default, Debug, Copy, Serialize, Deserialize, JsonSchema)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct NodeRoles { + pub mixnode_enabled: bool, + pub gateway_enabled: bool, + pub network_requester_enabled: bool, +} + +#[derive(Clone, Default, Debug, Serialize, Deserialize, JsonSchema)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct HostInformation { + /// Ip address(es) of this host, such as `1.1.1.1`. + #[cfg_attr(feature = "openapi", schema(value_type = Vec, format = Byte, example = json!(["1.1.1.1"])))] + pub ip_address: Vec, + + /// Optional hostname of this node, for example `nymtech.net`. + #[cfg_attr(feature = "openapi", schema(example = "nymtech.net"))] + pub hostname: Option, + + /// Public keys associated with this node. + pub keys: HostKeys, +} + +#[derive(Clone, Default, Debug, Serialize, Deserialize, JsonSchema)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct HostKeys { + /// Base58-encoded ed25519 public key of this node. Currently it corresponds to either mixnode's or gateway's identity. + pub ed25519: String, + + /// Base58-encoded x25519 public key of this node used for sphinx/outfox packet creation. + /// Currently it corresponds to either mixnode's or gateway's key. + pub x25519: String, +} diff --git a/nym-node/nym-node-requests/src/error.rs b/nym-node/nym-node-requests/src/error.rs new file mode 100644 index 0000000000..d14e252270 --- /dev/null +++ b/nym-node/nym-node-requests/src/error.rs @@ -0,0 +1,19 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum Error { + #[error("failed to serialize json data: {source}")] + JsonSerializationFailure { + #[from] + source: serde_json::Error, + }, + + #[error(transparent)] + WireguardError { + #[from] + source: nym_wireguard_types::Error, + }, +} diff --git a/nym-node/nym-node-requests/src/lib.rs b/nym-node/nym-node-requests/src/lib.rs new file mode 100644 index 0000000000..e1922f5d3b --- /dev/null +++ b/nym-node/nym-node-requests/src/lib.rs @@ -0,0 +1,142 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +#![warn(clippy::expect_used)] +#![warn(clippy::unwrap_used)] + +pub mod api; +pub mod error; + +// still thinking how to nicely organise it +pub mod routes { + use crate::absolute_route; + + pub const LANDING_PAGE: &str = "/"; + pub const ROOT: &str = "/"; + pub const API: &str = "/api"; + + pub mod api { + use super::*; + + pub const V1: &str = "/v1"; + + absolute_route!(v1_absolute, super::API, V1); + + pub mod v1 { + use super::*; + + pub const ROLES: &str = "/roles"; + pub const BUILD_INFO: &str = "/build-information"; + pub const HOST_INFO: &str = "/host-information"; + + pub const HEALTH: &str = "/health"; + pub const GATEWAY: &str = "/gateway"; + pub const MIXNODE: &str = "/mixnode"; + pub const NETWORK_REQUESTER: &str = "/network-requester"; + pub const SWAGGER: &str = "/swagger"; + + // define helper functions to get absolute routes + absolute_route!(health_absolute, v1_absolute(), HEALTH); + absolute_route!(roles_absolute, v1_absolute(), ROLES); + absolute_route!(build_info_absolute, v1_absolute(), BUILD_INFO); + absolute_route!(host_info_absolute, v1_absolute(), HOST_INFO); + absolute_route!(gateway_absolute, v1_absolute(), GATEWAY); + absolute_route!(mixnode_absolute, v1_absolute(), MIXNODE); + absolute_route!(network_requester_absolute, v1_absolute(), NETWORK_REQUESTER); + absolute_route!(swagger_absolute, v1_absolute(), SWAGGER); + + pub mod gateway { + use super::*; + + pub const CLIENT_INTERFACES: &str = "/client-interfaces"; + + absolute_route!( + client_interfaces_absolute, + gateway_absolute(), + CLIENT_INTERFACES + ); + + pub mod client_interfaces { + use super::*; + + pub const WIREGUARD: &str = "/wireguard"; + pub const WEBSOCKETS: &str = "/mixnet-websockets"; + + absolute_route!(wireguard_absolute, client_interfaces_absolute(), WIREGUARD); + absolute_route!( + mixnet_websockets_absolute, + client_interfaces_absolute(), + WEBSOCKETS + ); + + pub mod wireguard { + use super::*; + + pub const CLIENT: &str = "/client"; + pub const CLIENTS: &str = "/clients"; + + absolute_route!(client_absolute, wireguard_absolute(), CLIENT); + absolute_route!(clients_absolute, wireguard_absolute(), CLIENTS); + } + } + } + + pub mod mixnode { + // use super::*; + } + + pub mod network_requester { + // use super::*; + } + } + } +} + +#[macro_export] +macro_rules! absolute_route { + ( $name:ident, $parent:expr, $suffix:expr ) => { + pub fn $name() -> String { + format!("{}{}", $parent, $suffix) + } + }; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn route_expansion_works() { + assert_eq!("/api/v1", routes::api::v1_absolute()); + + assert_eq!( + "/api/v1/build-information", + routes::api::v1::build_info_absolute() + ); + assert_eq!( + "/api/v1/host-information", + routes::api::v1::host_info_absolute() + ); + assert_eq!("/api/v1/roles", routes::api::v1::roles_absolute()); + + assert_eq!("/api/v1/gateway", routes::api::v1::gateway_absolute()); + assert_eq!( + "/api/v1/gateway/client-interfaces", + routes::api::v1::gateway::client_interfaces_absolute() + ); + assert_eq!( + "/api/v1/gateway/client-interfaces/wireguard", + routes::api::v1::gateway::client_interfaces::wireguard_absolute() + ); + assert_eq!( + "/api/v1/gateway/client-interfaces/mixnet-websockets", + routes::api::v1::gateway::client_interfaces::mixnet_websockets_absolute() + ); + + assert_eq!("/api/v1/mixnode", routes::api::v1::mixnode_absolute()); + assert_eq!( + "/api/v1/network-requester", + routes::api::v1::network_requester_absolute() + ); + } +} diff --git a/nym-node/src/config/mod.rs b/nym-node/src/config/mod.rs new file mode 100644 index 0000000000..87b464c48e --- /dev/null +++ b/nym-node/src/config/mod.rs @@ -0,0 +1,92 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use nym_config::defaults::DEFAULT_NYM_NODE_HTTP_PORT; +use serde::{Deserialize, Serialize}; +use serde_helpers::*; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use std::path::PathBuf; + +pub mod persistence; +mod serde_helpers; + +pub const DEFAULT_WIREGUARD_PORT: u16 = 51820; +pub const DEFAULT_HTTP_PORT: u16 = DEFAULT_NYM_NODE_HTTP_PORT; + +// TODO: this is very much a WIP. we need proper ssl certificate support here +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct Host { + /// Ip address(es) of this host, such as 1.1.1.1 that external clients will use for connections. + pub public_ips: Vec, + + /// Optional hostname of this node, for example nymtech.net. + // TODO: this is temporary. to be replaced by pulling the data directly from the certs. + #[serde(deserialize_with = "de_maybe_string")] + pub hostname: Option, +} + +impl Host { + pub fn validate(&self) -> bool { + if self.public_ips.is_empty() { + return false; + } + + true + } +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(default)] +#[serde(deny_unknown_fields)] +pub struct Http { + /// Socket address this node will use for binding its http API. + /// default: `0.0.0.0:8080` + pub bind_address: SocketAddr, + + /// Path to assets directory of custom landing page of this node. + #[serde(deserialize_with = "de_maybe_path")] + pub landing_page_assets_path: Option, +} + +impl Default for Http { + fn default() -> Self { + Http { + bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), DEFAULT_HTTP_PORT), + landing_page_assets_path: None, + } + } +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(default)] +#[serde(deny_unknown_fields)] +pub struct Wireguard { + /// Specifies whether the wireguard service is enabled on this node. + pub enabled: bool, + + /// Socket address this node will use for binding its wireguard interface. + /// default: `0.0.0.0:51820` + pub bind_address: SocketAddr, + + /// Port announced to external clients wishing to connect to the wireguard interface. + /// Useful in the instances where the node is behind a proxy. + pub announced_port: u16, + + /// Paths for wireguard keys, client registries, etc. + pub storage_paths: persistence::WireguardPaths, +} + +impl Default for Wireguard { + fn default() -> Self { + Wireguard { + enabled: false, + bind_address: SocketAddr::new( + IpAddr::V4(Ipv4Addr::UNSPECIFIED), + DEFAULT_WIREGUARD_PORT, + ), + announced_port: DEFAULT_WIREGUARD_PORT, + storage_paths: persistence::WireguardPaths {}, + } + } +} diff --git a/nym-node/src/config/persistence.rs b/nym-node/src/config/persistence.rs new file mode 100644 index 0000000000..2ceed4b3cc --- /dev/null +++ b/nym-node/src/config/persistence.rs @@ -0,0 +1,10 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct WireguardPaths { + // pub keys: +} diff --git a/nym-node/src/config/serde_helpers.rs b/nym-node/src/config/serde_helpers.rs new file mode 100644 index 0000000000..df0f42bb44 --- /dev/null +++ b/nym-node/src/config/serde_helpers.rs @@ -0,0 +1,29 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use serde::{Deserialize, Deserializer}; +use std::path::PathBuf; + +pub(super) fn de_maybe_path<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let path = PathBuf::deserialize(deserializer)?; + if path.as_os_str().is_empty() { + Ok(None) + } else { + Ok(Some(path)) + } +} + +pub(super) fn de_maybe_string<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let path = String::deserialize(deserializer)?; + if path.is_empty() { + Ok(None) + } else { + Ok(Some(path)) + } +} diff --git a/nym-node/src/error.rs b/nym-node/src/error.rs new file mode 100644 index 0000000000..09cbbe8952 --- /dev/null +++ b/nym-node/src/error.rs @@ -0,0 +1,36 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::wireguard::error::WireguardError; +use std::net::{IpAddr, SocketAddr}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum NymNodeError { + #[error("failed to bind the HTTP API to {bind_address}: {source}")] + HttpBindFailure { + bind_address: SocketAddr, + source: hyper::Error, + }, + + #[error("this node hasn't set any valid public addresses to announce. Please modify [host.public_ips] section of your config")] + NoPublicIps, + + #[error("this node attempted to announce an invalid public address: {address}. Please modify [host.public_ips] section of your config. Alternatively, if you wanted to use it in the local setting, run the node with the '--local' flag.")] + InvalidPublicIp { address: IpAddr }, + + #[error("failed to use nym-node requests: {source}")] + RequestError { + #[from] + source: nym_node_requests::error::Error, + }, + + #[error(transparent)] + WireguardError { + #[from] + source: WireguardError, + }, + + #[error("unimplemented")] + Unimplemented, +} diff --git a/nym-node/src/http/middleware/logging.rs b/nym-node/src/http/middleware/logging.rs new file mode 100644 index 0000000000..68b12b4155 --- /dev/null +++ b/nym-node/src/http/middleware/logging.rs @@ -0,0 +1,49 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use axum::{ + extract::ConnectInfo, + http::{HeaderValue, Request}, + middleware::Next, + response::IntoResponse, +}; +use colored::*; +use hyper::header::{HOST, USER_AGENT}; +use std::net::SocketAddr; +use tracing::info; + +/// Simple logger for requests +pub async fn logger( + ConnectInfo(addr): ConnectInfo, + req: Request, + next: Next, +) -> impl IntoResponse { + let method = req.method().to_string().green(); + let uri = req.uri().to_string().blue(); + let agent = header_map( + req.headers().get(USER_AGENT), + "Unknown User Agent".to_string(), + ); + + let host = header_map(req.headers().get(HOST), "Unknown Host".to_string()); + + let res = next.run(req).await; + let status = res.status(); + let print_status = if status.is_client_error() || status.is_server_error() { + status.to_string().red() + } else if status.is_success() { + status.to_string().green() + } else { + status.to_string().yellow() + }; + + info!(target: "incoming request", "[{addr} -> {host}] {method} '{uri}': {print_status} / agent: {agent}"); + + res +} + +fn header_map(header: Option<&HeaderValue>, msg: String) -> String { + header + .map(|x| x.to_str().unwrap_or(&msg).to_string()) + .unwrap_or(msg) +} diff --git a/nym-node/src/http/middleware/mod.rs b/nym-node/src/http/middleware/mod.rs new file mode 100644 index 0000000000..872a6d3520 --- /dev/null +++ b/nym-node/src/http/middleware/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod logging; diff --git a/nym-node/src/http/mod.rs b/nym-node/src/http/mod.rs new file mode 100644 index 0000000000..a7a4fa0d4b --- /dev/null +++ b/nym-node/src/http/mod.rs @@ -0,0 +1,64 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use axum::extract::connect_info::IntoMakeServiceWithConnectInfo; +use axum::Router; +use hyper::server::conn::AddrIncoming; +use hyper::Server; +use nym_task::TaskClient; +use std::net::SocketAddr; +use tracing::{debug, error, info}; + +pub mod middleware; +pub mod router; +pub mod state; + +pub use router::{api, landing_page, Config, NymNodeRouter}; + +pub struct NymNodeHTTPServer { + task_client: Option, + inner: Server>, +} + +impl NymNodeHTTPServer { + pub(crate) fn new( + inner: Server>, + ) -> Self { + NymNodeHTTPServer { + task_client: None, + inner, + } + } + + #[must_use] + pub fn with_task_client(mut self, task_client: TaskClient) -> Self { + self.task_client = Some(task_client); + self + } + + async fn run_server_forever( + server: Server>, + ) { + if let Err(err) = server.await { + error!("the HTTP server has terminated with the error: {err}"); + } else { + error!("the HTTP server has terminated with producing any errors"); + } + } + + pub async fn run(self) { + info!("Started NymNodeHTTPServer on {}", self.inner.local_addr()); + if let Some(mut task_client) = self.task_client { + tokio::select! { + _ = task_client.recv_with_delay() => { + debug!("NymNodeHTTPServer: Received shutdown"); + } + _ = Self::run_server_forever(self.inner) => { } + } + } else { + Self::run_server_forever(self.inner).await + } + + debug!("NymNodeHTTPServer: Exiting"); + } +} diff --git a/nym-node/src/http/router/api/mod.rs b/nym-node/src/http/router/api/mod.rs new file mode 100644 index 0000000000..757ec48e97 --- /dev/null +++ b/nym-node/src/http/router/api/mod.rs @@ -0,0 +1,108 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use axum::http::{header, HeaderValue, StatusCode}; +use axum::response::{IntoResponse, Response}; +use axum::{Json, Router}; +use bytes::{BufMut, BytesMut}; +use serde::{Deserialize, Serialize}; +use utoipa::{IntoParams, ToSchema}; + +pub mod v1; + +use crate::http::api::v1::gateway::client_interfaces::wireguard::WireguardAppState; +use crate::http::state::AppState; +pub use nym_node_requests::api as api_requests; +use nym_node_requests::routes; + +#[derive(Debug, Clone)] +pub struct Config { + pub v1_config: v1::Config, +} + +pub(super) fn routes(config: Config, initial_wg_state: WireguardAppState) -> Router { + Router::new().nest( + routes::api::V1, + v1::routes(config.v1_config, initial_wg_state), + ) +} + +#[derive(Debug, Clone, ToSchema)] +pub enum FormattedResponse { + Json(Json), + Yaml(Yaml), +} + +impl IntoResponse for FormattedResponse +where + T: Serialize, +{ + fn into_response(self) -> Response { + match self { + FormattedResponse::Json(json_response) => json_response.into_response(), + FormattedResponse::Yaml(yaml_response) => yaml_response.into_response(), + } + } +} + +#[derive(Default, Debug, Serialize, Deserialize, Copy, Clone, ToSchema)] +#[serde(rename_all = "lowercase")] +pub enum Output { + #[default] + Json, + Yaml, +} + +#[derive(Default, Debug, Serialize, Deserialize, Copy, Clone, IntoParams, ToSchema)] +#[serde(default)] +pub struct OutputParams { + pub output: Option, +} + +impl Output { + pub fn to_response(self, data: T) -> FormattedResponse { + match self { + Output::Json => FormattedResponse::Json(Json(data)), + Output::Yaml => FormattedResponse::Yaml(Yaml(data)), + } + } +} + +#[derive(Debug, Clone, Copy, Default)] +#[must_use] +pub struct Yaml(pub T); + +impl From for Yaml { + fn from(inner: T) -> Self { + Self(inner) + } +} + +impl IntoResponse for Yaml +where + T: Serialize, +{ + // replicates axum's Json + fn into_response(self) -> Response { + let mut buf = BytesMut::with_capacity(128).writer(); + match serde_yaml::to_writer(&mut buf, &self.0) { + Ok(()) => ( + [( + header::CONTENT_TYPE, + HeaderValue::from_static("application/yaml"), + )], + buf.into_inner().freeze(), + ) + .into_response(), + Err(err) => ( + StatusCode::INTERNAL_SERVER_ERROR, + [( + header::CONTENT_TYPE, + HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()), + )], + err.to_string(), + ) + .into_response(), + } + } +} diff --git a/nym-node/src/http/router/api/v1/gateway/client_interfaces/mod.rs b/nym-node/src/http/router/api/v1/gateway/client_interfaces/mod.rs new file mode 100644 index 0000000000..a9b4f6beb7 --- /dev/null +++ b/nym-node/src/http/router/api/v1/gateway/client_interfaces/mod.rs @@ -0,0 +1,123 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::api::v1::gateway::client_interfaces::wireguard::WireguardAppState; +use crate::http::api::{FormattedResponse, OutputParams}; +use axum::extract::Query; +use axum::http::StatusCode; +use axum::routing::get; +use axum::Router; +use nym_node_requests::api::v1::gateway::models::{ClientInterfaces, WebSockets, Wireguard}; +use nym_node_requests::routes::api::v1::gateway::client_interfaces; + +pub(crate) mod wireguard; + +pub(crate) fn routes( + interfaces: Option, + initial_wg_state: WireguardAppState, +) -> Router { + Router::new() + .route( + "/", + get({ + let interfaces = interfaces.clone(); + move |query| client_interfaces(interfaces, query) + }), + ) + .route( + client_interfaces::WEBSOCKETS, + get({ + let websockets = interfaces.as_ref().and_then(|i| i.mixnet_websockets); + move |query| mixnet_websockets(websockets, query) + }), + ) + .nest( + client_interfaces::WIREGUARD, + wireguard::routes(initial_wg_state), + ) + .route( + client_interfaces::WIREGUARD, + get({ + let wireguard_cfg_info = interfaces.and_then(|i| i.wireguard); + move |query| wireguard_info(wireguard_cfg_info, query) + }), + ) +} + +/// Returns client interfaces supported by this gateway. +#[utoipa::path( + get, + path = "/client-interfaces", + context_path = "/api/v1/gateway", + tag = "Gateway", + responses( + (status = 501, description = "the endpoint hasn't been implemented yet"), + (status = 200, content( + ("application/json" = ClientInterfaces), + ("application/yaml" = ClientInterfaces) + )) + ), + params(OutputParams) +)] +pub(crate) async fn client_interfaces( + interfaces: Option, + Query(output): Query, +) -> Result { + let interfaces = interfaces.ok_or(StatusCode::NOT_IMPLEMENTED)?; + let output = output.output.unwrap_or_default(); + Ok(output.to_response(interfaces)) +} + +pub type ClientInterfacesResponse = FormattedResponse; + +/// Returns client interfaces supported by this gateway. +#[utoipa::path( + get, + path = "/wireguard", + context_path = "/api/v1/gateway/client-interfaces", + tag = "Gateway", + responses( + (status = 501, description = "the endpoint hasn't been implemented yet"), + (status = 200, content( + ("application/json" = Wireguard), + ("application/yaml" = Wireguard) + )) + ), + params(OutputParams) +)] +pub(crate) async fn wireguard_info( + wireguard: Option, + Query(output): Query, +) -> Result { + let wireguard = wireguard.ok_or(StatusCode::NOT_IMPLEMENTED)?; + let output = output.output.unwrap_or_default(); + Ok(output.to_response(wireguard)) +} + +pub type WireguardResponse = FormattedResponse; + +/// Returns client interfaces supported by this gateway. +#[utoipa::path( + get, + path = "/mixnet-websockets", + context_path = "/api/v1/gateway/client-interfaces", + tag = "Gateway", + responses( + (status = 501, description = "the endpoint hasn't been implemented yet"), + (status = 200, content( + ("application/json" = WebSockets), + ("application/yaml" = WebSockets) + )) + ), + params(OutputParams) +)] +pub(crate) async fn mixnet_websockets( + websockets: Option, + Query(output): Query, +) -> Result { + let websockets = websockets.ok_or(StatusCode::NOT_IMPLEMENTED)?; + let output = output.output.unwrap_or_default(); + Ok(output.to_response(websockets)) +} + +pub type MixnetWebSocketsResponse = FormattedResponse; diff --git a/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/client_registry.rs b/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/client_registry.rs new file mode 100644 index 0000000000..f21a1e719f --- /dev/null +++ b/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/client_registry.rs @@ -0,0 +1,194 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::api::v1::gateway::client_interfaces::wireguard::{ + WireguardAppState, WireguardAppStateInner, +}; +use crate::http::api::{FormattedResponse, OutputParams}; +use crate::http::router::types::RequestError; +use crate::wireguard::error::WireguardError; +use axum::extract::{Path, Query, State}; +use axum::http::StatusCode; +use axum::Json; +use nym_node_requests::api::v1::gateway::client_interfaces::wireguard::models::{ + ClientMessage, ClientRegistrationResponse, GatewayClient, InitMessage, Nonce, PeerPublicKey, +}; + +async fn process_final_message( + client: GatewayClient, + state: &WireguardAppStateInner, +) -> Result { + let preshared_nonce = { + if let Some(nonce) = state.registration_in_progress.get(&client.pub_key()) { + *nonce + } else { + return Err(RequestError::from_err( + WireguardError::RegistrationNotInProgress, + StatusCode::BAD_REQUEST, + )); + } + }; + + if client + .verify(state.dh_keypair.private_key(), preshared_nonce) + .is_ok() + { + state.registration_in_progress.remove(&client.pub_key()); + state.client_registry.insert(client.pub_key(), client); + + Ok(StatusCode::OK) + } else { + Err(RequestError::from_err( + WireguardError::MacVerificationFailure, + StatusCode::BAD_REQUEST, + )) + } +} + +async fn process_init_message(init_message: InitMessage, state: &WireguardAppStateInner) -> Nonce { + let nonce: u64 = fastrand::u64(..); + state + .registration_in_progress + .insert(init_message.pub_key(), nonce); + nonce +} + +/// Perform wireguard client registration. +#[utoipa::path( + post, + path = "/client", + context_path = "/api/v1/gateway/client-interfaces/wireguard", + tag = "Wireguard (EXPERIMENTAL AND UNSTABLE)", + request_body( + content = ClientMessage, + description = "Data used for proceeding with client wireguard registration", + content_type = "application/json" + ), + responses( + (status = 501, body = ErrorResponse, description = "the endpoint hasn't been implemented yet"), + (status = 400, body = ErrorResponse), + (status = 200, content( + ("application/json" = ClientRegistrationResponse), + ("application/yaml" = ClientRegistrationResponse) + )) + ), + params(OutputParams) +)] +pub(crate) async fn register_client( + State(state): State, + Query(output): Query, + Json(payload): Json, +) -> Result { + let output = output.output.unwrap_or_default(); + + let Some(state) = state.inner() else { + return Err(RequestError::new_status(StatusCode::NOT_IMPLEMENTED)); + }; + + match payload { + ClientMessage::Initial(init) => { + let nonce = process_init_message(init, state).await; + let response = ClientRegistrationResponse::PendingRegistration { nonce }; + Ok(output.to_response(response)) + } + ClientMessage::Final(finalize) => { + let result = process_final_message(finalize, state).await?; + if result.is_success() { + let response = ClientRegistrationResponse::Registered { success: true }; + Ok(output.to_response(response)) + } else { + Err(RequestError::new_status(result)) + } + } + } +} + +pub type RegisterClientResponse = FormattedResponse; + +/// Get public keys of all registered wireguard clients. +#[utoipa::path( + get, + path = "/clients", + context_path = "/api/v1/gateway/client-interfaces/wireguard", + tag = "Wireguard (EXPERIMENTAL AND UNSTABLE)", + responses( + (status = 501, body = ErrorResponse, description = "the endpoint hasn't been implemented yet"), + (status = 200, content( + ("application/json" = Vec), + ("application/yaml" = Vec) + )) + ), + params(OutputParams) +)] +pub(crate) async fn get_all_clients( + Query(output): Query, + State(state): State, +) -> Result { + let output = output.output.unwrap_or_default(); + + let Some(state) = state.inner() else { + return Err(RequestError::new_status(StatusCode::NOT_IMPLEMENTED)); + }; + + let clients = state + .client_registry + .iter() + .map(|c| c.pub_key()) + .collect::>(); + + Ok(output.to_response(clients)) +} + +pub type AllClientsResponse = FormattedResponse>; + +/// Get client details of the registered wireguard client by its public key. +#[utoipa::path( + get, + path = "/client/{pub_key}", + context_path = "/api/v1/gateway/client-interfaces/wireguard", + tag = "Wireguard (EXPERIMENTAL AND UNSTABLE)", + params( + ("pub_key", Path, description = "The public key of the client"), + OutputParams + ), + responses( + (status = 501, body = ErrorResponse, description = "the endpoint hasn't been implemented yet"), + (status = 404, body = ErrorResponse, description = "there are no clients with the provided public key"), + (status = 400, body = ErrorResponse), + (status = 200, content( + ("application/json" = Vec), + ("application/yaml" = Vec) + )) + ), +)] +pub(crate) async fn get_client( + Path(pub_key): Path, + Query(output): Query, + State(state): State, +) -> Result { + let output = output.output.unwrap_or_default(); + + let Some(state) = state.inner() else { + return Err(RequestError::new_status(StatusCode::NOT_IMPLEMENTED)); + }; + + let clients = state + .client_registry + .iter() + .filter_map(|c| { + if c.pub_key() == pub_key { + Some(c.clone()) + } else { + None + } + }) + .collect::>(); + + if clients.is_empty() { + return Err(RequestError::new_status(StatusCode::NOT_FOUND)); + } + + Ok(output.to_response(clients)) +} + +pub type ClientResponse = FormattedResponse>; diff --git a/gateway/src/node/http/mod.rs b/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/mod.rs similarity index 51% rename from gateway/src/node/http/mod.rs rename to nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/mod.rs index 91f73561d2..8e29d8c0fb 100644 --- a/gateway/src/node/http/mod.rs +++ b/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/mod.rs @@ -1,88 +1,112 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::api::v1::gateway::client_interfaces::wireguard::client_registry::{ + get_all_clients, get_client, register_client, +}; +use crate::wireguard::types::{GatewayClientRegistry, PendingRegistrations}; +use axum::routing::{get, post}; +use axum::Router; +use nym_crypto::asymmetric::encryption; +use nym_node_requests::routes::api::v1::gateway::client_interfaces::wireguard; use std::sync::Arc; -use axum::{ - routing::{get, post}, - Router, -}; -use dashmap::DashMap; -use log::info; -use nym_crypto::asymmetric::encryption; +pub(crate) mod client_registry; -mod api; -use api::v1::client_registry::*; -use nym_types::gateway_client_registration::GatewayClientRegistry; -use nym_types::wireguard::PeerPublicKey; - -const ROUTE_PREFIX: &str = "/api/v1/gateway/client-interfaces/wireguard"; - -pub struct ApiState { - client_registry: Arc, - sphinx_key_pair: Arc, - registration_in_progress: Arc>, +// I don't see any reason why this state should be accessible to any routes outside /wireguard +// if anyone finds compelling reason, it could be moved to the `AppState` struct instead +#[derive(Clone, Default)] +pub struct WireguardAppState { + inner: Option, } -fn router_with_state(state: Arc) -> Router { +impl WireguardAppState { + pub fn new( + dh_keypair: Arc, + client_registry: Arc, + registration_in_progress: Arc, + ) -> Self { + WireguardAppState { + inner: Some(WireguardAppStateInner { + dh_keypair, + client_registry, + registration_in_progress, + }), + } + } + + // #[allow(dead_code)] + // pub(crate) fn dh_keypair(&self) -> Option<&encryption::KeyPair> { + // self.inner.as_ref().map(|s| s.dh_keypair.as_ref()) + // } + // + // #[allow(dead_code)] + // pub(crate) fn client_registry(&self) -> Option<&RwLock> { + // self.inner.as_ref().map(|s| s.client_registry.as_ref()) + // } + // + // #[allow(dead_code)] + // pub(crate) fn registration_in_progress(&self) -> Option<&RwLock> { + // self.inner + // .as_ref() + // .map(|s| s.registration_in_progress.as_ref()) + // } + + // not sure what to feel about exposing this method + pub(crate) fn inner(&self) -> Option<&WireguardAppStateInner> { + self.inner.as_ref() + } +} + +// helper macro to deal with missing wg state (if not being exposed by the node) +#[macro_export] +macro_rules! get_state { + ( $state: ident, $field: ident ) => {{ + let Some(ref inner) = $state.inner else { + return ::axum::http::StatusCode::NOT_IMPLEMENTED; + }; + inner.$field.as_ref() + }}; +} + +#[derive(Clone)] +pub(crate) struct WireguardAppStateInner { + dh_keypair: Arc, + client_registry: Arc, + registration_in_progress: Arc, +} + +pub(crate) fn routes(initial_state: WireguardAppState) -> Router { Router::new() - .route(&format!("{}/clients", ROUTE_PREFIX), get(get_all_clients)) - .route(&format!("{}/client", ROUTE_PREFIX), post(register_client)) - .route( - &format!("{}/client/:pub_key", ROUTE_PREFIX), - get(get_client), - ) - .with_state(state) -} - -pub(crate) async fn start_http_api( - client_registry: Arc, - sphinx_key_pair: Arc, -) { - // Port should be 80 post smoosh - let port = 8000; - - info!("Started HTTP API on port {}", port); - - let client_registry = Arc::clone(&client_registry); - - let state = Arc::new(ApiState { - client_registry, - sphinx_key_pair, - registration_in_progress: Arc::new(DashMap::new()), - }); - - let routes = router_with_state(state); - - #[allow(clippy::unwrap_used)] - axum::Server::bind(&format!("0.0.0.0:{}", port).parse().unwrap()) - .serve(routes.into_make_service()) - .await - .unwrap(); + // .route("/", get()) + .route(wireguard::CLIENTS, get(get_all_clients)) + .route(wireguard::CLIENT, post(register_client)) + .route(&format!("{}/:pub_key", wireguard::CLIENT), get(get_client)) + .with_state(initial_state) } #[cfg(test)] mod test { - use std::net::SocketAddr; - use std::str::FromStr; - use std::sync::Arc; - + use crate::http::api::v1::gateway::client_interfaces::wireguard::{ + routes, WireguardAppState, WireguardAppStateInner, + }; use axum::body::Body; use axum::http::Request; use axum::http::StatusCode; use dashmap::DashMap; use hmac::Mac; - use nym_types::gateway_client_registration::ClientMac; - use nym_types::gateway_client_registration::ClientMessage; - use nym_types::gateway_client_registration::GatewayClient; - use nym_types::gateway_client_registration::HmacSha256; - use nym_types::gateway_client_registration::InitMessage; - use nym_types::wireguard::PeerPublicKey; + use nym_crypto::asymmetric::encryption; + use nym_node_requests::api::v1::gateway::client_interfaces::wireguard::models::{ + ClientMac, ClientMessage, ClientRegistrationResponse, GatewayClient, InitMessage, + PeerPublicKey, + }; + use nym_node_requests::routes::api::v1::gateway::client_interfaces::wireguard; + use nym_wireguard_types::registration::HmacSha256; + use std::sync::Arc; use tower::Service; use tower::ServiceExt; - - use nym_crypto::asymmetric::encryption; use x25519_dalek::{PublicKey, StaticSecret}; - use crate::node::http::{router_with_state, ApiState, ROUTE_PREFIX}; - #[tokio::test] async fn registration() { // 1. Provision random keys for gateway and client @@ -110,22 +134,25 @@ mod test { let registration_in_progress = Arc::new(DashMap::new()); let client_registry = Arc::new(DashMap::new()); - let state = Arc::new(ApiState { - client_registry: Arc::clone(&client_registry), - sphinx_key_pair: Arc::new(gateway_key_pair), - registration_in_progress: Arc::clone(®istration_in_progress), - }); + let state = WireguardAppState { + inner: Some(WireguardAppStateInner { + client_registry: Arc::clone(&client_registry), + dh_keypair: Arc::new(gateway_key_pair), + registration_in_progress: Arc::clone(®istration_in_progress), + }), + }; // `Router` implements `tower::Service>` so we can // call it like any tower service, no need to run an HTTP server. - let mut app = router_with_state(state); + let mut app = routes(state); - let init_message = - ClientMessage::Init(InitMessage::new(PeerPublicKey::new(client_static_public))); + let init_message = ClientMessage::Initial(InitMessage { + pub_key: PeerPublicKey::new(client_static_public), + }); let init_request = Request::builder() .method("POST") - .uri(format!("{}/client", ROUTE_PREFIX)) + .uri(wireguard::CLIENT) .header("Content-type", "application/json") .body(Body::from(serde_json::to_vec(&init_message).unwrap())) .unwrap(); @@ -140,27 +167,29 @@ mod test { assert_eq!(response.status(), StatusCode::OK); assert!(!registration_in_progress.is_empty()); - let nonce: Option = + let ClientRegistrationResponse::PendingRegistration { nonce } = serde_json::from_slice(&hyper::body::to_bytes(response.into_body()).await.unwrap()) - .unwrap(); - assert!(nonce.is_some()); + .unwrap() + else { + panic!("invalid response") + }; let mut mac = HmacSha256::new_from_slice(client_dh.as_bytes()).unwrap(); mac.update(client_static_public.as_bytes()); mac.update("127.0.0.1".as_bytes()); mac.update("8080".as_bytes()); - mac.update(&nonce.unwrap().to_le_bytes()); + mac.update(&nonce.to_le_bytes()); let mac = mac.finalize().into_bytes(); let finalized_message = ClientMessage::Final(GatewayClient { pub_key: PeerPublicKey::new(client_static_public), - socket: SocketAddr::from_str("127.0.0.1:8080").unwrap(), + socket: "127.0.0.1:8080".parse().unwrap(), mac: ClientMac::new(mac.as_slice().to_vec()), }); let final_request = Request::builder() .method("POST") - .uri(format!("{}/client", ROUTE_PREFIX)) + .uri(wireguard::CLIENT) .header("Content-type", "application/json") .body(Body::from(serde_json::to_vec(&finalized_message).unwrap())) .unwrap(); @@ -177,7 +206,7 @@ mod test { let clients_request = Request::builder() .method("GET") - .uri(format!("{}/clients", ROUTE_PREFIX)) + .uri(wireguard::CLIENTS) .body(Body::empty()) .unwrap(); @@ -199,7 +228,7 @@ mod test { assert_eq!( client_registry .iter() - .map(|c| c.value().pub_key().clone()) + .map(|c| c.value().pub_key()) .collect::>(), clients ) diff --git a/nym-node/src/http/router/api/v1/gateway/mod.rs b/nym-node/src/http/router/api/v1/gateway/mod.rs new file mode 100644 index 0000000000..d2bba50118 --- /dev/null +++ b/nym-node/src/http/router/api/v1/gateway/mod.rs @@ -0,0 +1,37 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::api::v1::gateway::client_interfaces::wireguard::WireguardAppState; +use axum::routing::get; +use axum::Router; +use nym_node_requests::api::v1::gateway::models; +use nym_node_requests::routes::api::v1::gateway; + +pub mod client_interfaces; +pub mod root; + +#[derive(Debug, Clone, Default)] +pub struct Config { + pub details: Option, +} + +pub(crate) fn routes( + config: Config, + initial_wg_state: WireguardAppState, +) -> Router { + Router::new() + .route( + "/", + get({ + let gateway_details = config.details.clone(); + move |query| root::root_gateway(gateway_details, query) + }), + ) + .nest( + gateway::CLIENT_INTERFACES, + client_interfaces::routes( + config.details.map(|g| g.client_interfaces), + initial_wg_state, + ), + ) +} diff --git a/nym-node/src/http/router/api/v1/gateway/root.rs b/nym-node/src/http/router/api/v1/gateway/root.rs new file mode 100644 index 0000000000..526d1825dd --- /dev/null +++ b/nym-node/src/http/router/api/v1/gateway/root.rs @@ -0,0 +1,33 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::router::api::{FormattedResponse, OutputParams}; +use axum::extract::Query; +use axum::http::StatusCode; +use nym_node_requests::api::v1::gateway::models::Gateway; + +/// Returns root gateway information +#[utoipa::path( + get, + path = "", + context_path = "/api/v1/gateway", + tag = "Gateway", + responses( + (status = 501, description = "the endpoint hasn't been implemented yet"), + (status = 200, content( + ("application/json" = Gateway), + ("application/yaml" = Gateway) + )) + ), + params(OutputParams) +)] +pub(crate) async fn root_gateway( + details: Option, + Query(output): Query, +) -> Result { + let details = details.ok_or(StatusCode::NOT_IMPLEMENTED)?; + let output = output.output.unwrap_or_default(); + Ok(output.to_response(details)) +} + +pub type GatewayResponse = FormattedResponse; diff --git a/nym-node/src/http/router/api/v1/health.rs b/nym-node/src/http/router/api/v1/health.rs new file mode 100644 index 0000000000..08e9ff28d5 --- /dev/null +++ b/nym-node/src/http/router/api/v1/health.rs @@ -0,0 +1,34 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::api::{FormattedResponse, OutputParams}; +use crate::http::state::AppState; +use axum::extract::{Query, State}; +use nym_node_requests::api::v1::health::models::NodeHealth; + +/// Returns health status of this node. +#[utoipa::path( + get, + path = "/health", + context_path = "/api/v1", + tag = "Health", + responses( + (status = 200, content( + ("application/json" = Vec), + ("application/yaml" = Vec) + ), description = "the api is available and healthy") + ), + params(OutputParams) +)] +pub(crate) async fn root_health( + Query(output): Query, + State(state): State, +) -> HealthResponse { + let output = output.output.unwrap_or_default(); + let uptime = state.startup_time.elapsed(); + let health = NodeHealth::new_healthy(uptime); + + output.to_response(health) +} + +pub type HealthResponse = FormattedResponse; diff --git a/nym-node/src/http/router/api/v1/mixnode/mod.rs b/nym-node/src/http/router/api/v1/mixnode/mod.rs new file mode 100644 index 0000000000..998a0edd3e --- /dev/null +++ b/nym-node/src/http/router/api/v1/mixnode/mod.rs @@ -0,0 +1,23 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use axum::routing::get; +use axum::Router; +use nym_node_requests::api::v1::mixnode::models; + +pub mod root; + +#[derive(Debug, Clone, Default)] +pub struct Config { + pub details: Option, +} + +pub(crate) fn routes(config: Config) -> Router { + Router::new().route( + "/", + get({ + let mixnode_details = config.details; + move |query| root::root_mixnode(mixnode_details, query) + }), + ) +} diff --git a/nym-node/src/http/router/api/v1/mixnode/root.rs b/nym-node/src/http/router/api/v1/mixnode/root.rs new file mode 100644 index 0000000000..2b71fea15c --- /dev/null +++ b/nym-node/src/http/router/api/v1/mixnode/root.rs @@ -0,0 +1,33 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::router::api::{FormattedResponse, OutputParams}; +use axum::extract::Query; +use axum::http::StatusCode; +use nym_node_requests::api::v1::mixnode::models::Mixnode; + +/// Returns root mixnode information +#[utoipa::path( + get, + path = "", + context_path = "/api/v1/mixnode", + tag = "Mixnode", + responses( + (status = 501, description = "the endpoint hasn't been implemented yet"), + (status = 200, content( + ("application/json" = Mixnode), + ("application/yaml" = Mixnode) + )) + ), + params(OutputParams) +)] +pub(crate) async fn root_mixnode( + details: Option, + Query(output): Query, +) -> Result { + let details = details.ok_or(StatusCode::NOT_IMPLEMENTED)?; + let output = output.output.unwrap_or_default(); + Ok(output.to_response(details)) +} + +pub type MixnodeResponse = FormattedResponse; diff --git a/nym-node/src/http/router/api/v1/mod.rs b/nym-node/src/http/router/api/v1/mod.rs new file mode 100644 index 0000000000..cc81f9948f --- /dev/null +++ b/nym-node/src/http/router/api/v1/mod.rs @@ -0,0 +1,39 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::api::v1::gateway::client_interfaces::wireguard::WireguardAppState; +use crate::http::state::AppState; +use axum::routing::get; +use axum::Router; +use nym_node_requests::routes::api::v1; + +pub mod gateway; +pub mod health; +pub mod mixnode; +pub mod network_requester; +pub mod node; +pub mod openapi; + +#[derive(Debug, Clone)] +pub struct Config { + pub node: node::Config, + pub gateway: gateway::Config, + pub mixnode: mixnode::Config, + pub network_requester: network_requester::Config, +} + +pub(super) fn routes(config: Config, initial_wg_state: WireguardAppState) -> Router { + Router::new() + .route(v1::HEALTH, get(health::root_health)) + .nest( + v1::GATEWAY, + gateway::routes(config.gateway, initial_wg_state), + ) + .nest(v1::MIXNODE, mixnode::routes(config.mixnode)) + .nest( + v1::NETWORK_REQUESTER, + network_requester::routes(config.network_requester), + ) + .merge(node::routes(config.node)) + .merge(openapi::route()) +} diff --git a/nym-node/src/http/router/api/v1/network_requester/mod.rs b/nym-node/src/http/router/api/v1/network_requester/mod.rs new file mode 100644 index 0000000000..aced86bad3 --- /dev/null +++ b/nym-node/src/http/router/api/v1/network_requester/mod.rs @@ -0,0 +1,23 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use axum::routing::get; +use axum::Router; +use nym_node_requests::api::v1::network_requester::models; + +pub mod root; + +#[derive(Debug, Clone, Default)] +pub struct Config { + pub details: Option, +} + +pub(crate) fn routes(config: Config) -> Router { + Router::new().route( + "/", + get({ + let network_requester_details = config.details; + move |query| root::root_network_requester(network_requester_details, query) + }), + ) +} diff --git a/nym-node/src/http/router/api/v1/network_requester/root.rs b/nym-node/src/http/router/api/v1/network_requester/root.rs new file mode 100644 index 0000000000..a1849e2560 --- /dev/null +++ b/nym-node/src/http/router/api/v1/network_requester/root.rs @@ -0,0 +1,33 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::router::api::{FormattedResponse, OutputParams}; +use axum::extract::Query; +use axum::http::StatusCode; +use nym_node_requests::api::v1::network_requester::models::NetworkRequester; + +/// Returns root network requester information +#[utoipa::path( + get, + path = "", + context_path = "/api/v1/network-requester", + tag = "Network Requester", + responses( + (status = 501, description = "the endpoint hasn't been implemented yet"), + (status = 200, content( + ("application/json" = NetworkRequester), + ("application/yaml" = NetworkRequester) + )) + ), + params(OutputParams) +)] +pub(crate) async fn root_network_requester( + details: Option, + Query(output): Query, +) -> Result { + let details = details.ok_or(StatusCode::NOT_IMPLEMENTED)?; + let output = output.output.unwrap_or_default(); + Ok(output.to_response(details)) +} + +pub type NetworkRequesterResponse = FormattedResponse; diff --git a/nym-node/src/http/router/api/v1/node/build_information.rs b/nym-node/src/http/router/api/v1/node/build_information.rs new file mode 100644 index 0000000000..1288d94dda --- /dev/null +++ b/nym-node/src/http/router/api/v1/node/build_information.rs @@ -0,0 +1,30 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::router::api::{FormattedResponse, OutputParams}; +use axum::extract::Query; +use nym_node_requests::api::v1::node::models::BinaryBuildInformationOwned; + +/// Returns build metadata of the binary running the API +#[utoipa::path( + get, + path = "/build-information", + context_path = "/api/v1", + tag = "Node", + responses( + (status = 200, content( + ("application/json" = BinaryBuildInformationOwned), + ("application/yaml" = BinaryBuildInformationOwned) + )) + ), + params(OutputParams) +)] +pub(crate) async fn build_information( + build_information: BinaryBuildInformationOwned, + Query(output): Query, +) -> BuildInformationResponse { + let output = output.output.unwrap_or_default(); + output.to_response(build_information) +} + +pub type BuildInformationResponse = FormattedResponse; diff --git a/nym-node/src/http/router/api/v1/node/host_information.rs b/nym-node/src/http/router/api/v1/node/host_information.rs new file mode 100644 index 0000000000..3581de10bc --- /dev/null +++ b/nym-node/src/http/router/api/v1/node/host_information.rs @@ -0,0 +1,30 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::api::{FormattedResponse, OutputParams}; +use axum::extract::Query; +use nym_node_requests::api::v1::node::models::SignedHostInformation; + +/// Returns host information of this node. +#[utoipa::path( + get, + path = "/host-information", + context_path = "/api/v1", + tag = "Node", + responses( + (status = 200, content( + ("application/json" = SignedHostInformation), + ("application/yaml" = SignedHostInformation) + )) + ), + params(OutputParams) +)] +pub(crate) async fn host_information( + host_information: SignedHostInformation, + Query(output): Query, +) -> HostInformationResponse { + let output = output.output.unwrap_or_default(); + output.to_response(host_information) +} + +pub type HostInformationResponse = FormattedResponse; diff --git a/nym-node/src/http/router/api/v1/node/mod.rs b/nym-node/src/http/router/api/v1/node/mod.rs new file mode 100644 index 0000000000..6644e75572 --- /dev/null +++ b/nym-node/src/http/router/api/v1/node/mod.rs @@ -0,0 +1,46 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::api::v1::node::build_information::build_information; +use crate::http::api::v1::node::host_information::host_information; +use crate::http::api::v1::node::roles::roles; +use axum::routing::get; +use axum::Router; +use nym_node_requests::api::v1::node::models; +use nym_node_requests::routes::api::v1; + +pub mod build_information; +pub mod host_information; +pub mod roles; + +#[derive(Debug, Clone)] +pub struct Config { + pub build_information: models::BinaryBuildInformationOwned, + pub host_information: models::SignedHostInformation, + pub roles: models::NodeRoles, +} + +pub(super) fn routes(config: Config) -> Router { + Router::new() + .route( + v1::BUILD_INFO, + get({ + let build_info = config.build_information; + move |query| build_information(build_info, query) + }), + ) + .route( + v1::ROLES, + get({ + let node_roles = config.roles; + move |query| roles(node_roles, query) + }), + ) + .route( + v1::HOST_INFO, + get({ + let host_info = config.host_information; + move |query| host_information(host_info, query) + }), + ) +} diff --git a/nym-node/src/http/router/api/v1/node/roles.rs b/nym-node/src/http/router/api/v1/node/roles.rs new file mode 100644 index 0000000000..811954ed52 --- /dev/null +++ b/nym-node/src/http/router/api/v1/node/roles.rs @@ -0,0 +1,30 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::router::api::{FormattedResponse, OutputParams}; +use axum::extract::Query; +use nym_node_requests::api::v1::node::models::NodeRoles; + +/// Returns roles supported by this node +#[utoipa::path( + get, + path = "/roles", + context_path = "/api/v1", + tag = "Node", + responses( + (status = 200, content( + ("application/json" = NodeRoles), + ("application/yaml" = NodeRoles) + )) + ), + params(OutputParams) +)] +pub(crate) async fn roles( + node_roles: NodeRoles, + Query(output): Query, +) -> RolesResponse { + let output = output.output.unwrap_or_default(); + output.to_response(node_roles) +} + +pub type RolesResponse = FormattedResponse; diff --git a/nym-node/src/http/router/api/v1/openapi.rs b/nym-node/src/http/router/api/v1/openapi.rs new file mode 100644 index 0000000000..8678c613d7 --- /dev/null +++ b/nym-node/src/http/router/api/v1/openapi.rs @@ -0,0 +1,65 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::router::api; +use crate::http::router::types::{ErrorResponse, RequestError}; +use axum::Router; +use nym_node_requests::api as api_requests; +use nym_node_requests::routes::api::v1; +use utoipa::OpenApi; +use utoipa_swagger_ui::SwaggerUi; + +#[derive(OpenApi)] +#[openapi( + info(title = "NymNode API"), + paths( + api::v1::node::build_information::build_information, + api::v1::node::host_information::host_information, + api::v1::node::roles::roles, + api::v1::health::root_health, + api::v1::gateway::root::root_gateway, + api::v1::gateway::client_interfaces::client_interfaces, + api::v1::gateway::client_interfaces::wireguard_info, + api::v1::gateway::client_interfaces::mixnet_websockets, + api::v1::gateway::client_interfaces::wireguard::client_registry::register_client, + api::v1::gateway::client_interfaces::wireguard::client_registry::get_all_clients, + api::v1::gateway::client_interfaces::wireguard::client_registry::get_client, + api::v1::mixnode::root::root_mixnode, + api::v1::network_requester::root::root_network_requester, + ), + components( + schemas( + ErrorResponse, + api::Output, + api::OutputParams, + api_requests::v1::health::models::NodeHealth, + api_requests::v1::health::models::NodeStatus, + api_requests::v1::node::models::BinaryBuildInformationOwned, + api_requests::v1::node::models::SignedHostInformation, + api_requests::v1::node::models::HostInformation, + api_requests::v1::node::models::HostKeys, + api_requests::v1::node::models::NodeRoles, + api_requests::v1::gateway::models::Gateway, + api_requests::v1::gateway::models::Wireguard, + api_requests::v1::gateway::models::ClientInterfaces, + api_requests::v1::gateway::models::WebSockets, + api_requests::v1::gateway::client_interfaces::wireguard::models::ClientMessage, + api_requests::v1::gateway::client_interfaces::wireguard::models::InitMessage, + api_requests::v1::gateway::client_interfaces::wireguard::models::GatewayClient, + api_requests::v1::gateway::client_interfaces::wireguard::models::ClientRegistrationResponse, + api_requests::v1::mixnode::models::Mixnode, + api_requests::v1::network_requester::models::NetworkRequester, + ), + responses(RequestError) + ) +)] +pub(crate) struct ApiDoc; + +pub(crate) fn route() -> Router { + // provide absolute path to the openapi.json + let config = utoipa_swagger_ui::Config::from("/api/v1/api-docs/openapi.json"); + SwaggerUi::new(v1::SWAGGER) + .url("/api-docs/openapi.json", ApiDoc::openapi()) + .config(config) + .into() +} diff --git a/nym-node/src/http/router/landing_page.rs b/nym-node/src/http/router/landing_page.rs new file mode 100644 index 0000000000..6ac6a66b80 --- /dev/null +++ b/nym-node/src/http/router/landing_page.rs @@ -0,0 +1,32 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use axum::response::Html; +use axum::routing::get; +use axum::Router; +use std::path::PathBuf; +use tower_http::services::ServeDir; + +#[derive(Debug, Clone, Default)] +pub struct Config { + pub assets_path: Option, +} + +pub(super) fn routes(config: Config) -> Router { + if let Some(assets) = config.assets_path { + Router::new().nest_service("/", ServeDir::new(assets)) + } else { + Router::new().route("/", get(default)) + } +} + +pub(super) async fn default() -> Html<&'static str> { + Html( + r#" +

Nym Node

+
+

default page of the nym node - you can customize it by setting the 'assets' path under '[http]' section of your config.

+
+ "#, + ) +} diff --git a/nym-node/src/http/router/mod.rs b/nym-node/src/http/router/mod.rs new file mode 100644 index 0000000000..a25c6427f8 --- /dev/null +++ b/nym-node/src/http/router/mod.rs @@ -0,0 +1,136 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::error::NymNodeError; +pub use crate::http::api::v1::gateway::client_interfaces::wireguard::WireguardAppState; +use crate::http::middleware::logging; +use crate::http::state::AppState; +use crate::http::NymNodeHTTPServer; +use axum::Router; +use nym_node_requests::api::v1::gateway::models::{Gateway, Wireguard}; +use nym_node_requests::api::v1::mixnode::models::Mixnode; +use nym_node_requests::api::v1::network_requester::models::NetworkRequester; +use nym_node_requests::api::v1::node::models; +use nym_node_requests::api::SignedHostInformation; +use nym_node_requests::routes; +use std::net::SocketAddr; +use std::path::Path; +use tracing::warn; + +pub mod api; +pub mod landing_page; +pub mod types; + +#[derive(Debug, Clone)] +pub struct Config { + pub landing: landing_page::Config, + pub api: api::Config, +} + +impl Config { + pub fn new( + build_information: models::BinaryBuildInformationOwned, + host_information: SignedHostInformation, + ) -> Self { + Config { + landing: Default::default(), + api: api::Config { + v1_config: api::v1::Config { + node: api::v1::node::Config { + build_information, + host_information, + roles: Default::default(), + }, + gateway: Default::default(), + mixnode: Default::default(), + network_requester: Default::default(), + }, + }, + } + } + + pub fn with_wireguard_interface(mut self, wireguard: Wireguard) -> Self { + match &mut self.api.v1_config.gateway.details { + Some(gw) => gw.client_interfaces.wireguard = Some(wireguard), + None => { + warn!( + "can't add wireguard interface information as the gateway role is not enabled." + ); + } + } + self + } + + #[must_use] + pub fn with_landing_page_assets>(mut self, assets_path: Option

) -> Self { + self.landing.assets_path = assets_path.map(|p| p.as_ref().to_path_buf()); + self + } + + #[must_use] + pub fn with_gateway(mut self, gateway: Gateway) -> Self { + self.api.v1_config.node.roles.gateway_enabled = true; + self.api.v1_config.gateway.details = Some(gateway); + self + } + + #[must_use] + pub fn with_mixnode(mut self, mixnode: Mixnode) -> Self { + self.api.v1_config.node.roles.mixnode_enabled = true; + self.api.v1_config.mixnode.details = Some(mixnode); + self + } + + #[must_use] + pub fn with_network_requester(mut self, network_requester: NetworkRequester) -> Self { + self.api.v1_config.node.roles.network_requester_enabled = true; + self.api.v1_config.network_requester.details = Some(network_requester); + self + } +} + +pub struct NymNodeRouter { + inner: Router, +} + +impl NymNodeRouter { + // TODO: move the wg state to a builder + pub fn new(config: Config, initial_wg_state: Option) -> NymNodeRouter { + let state = AppState::new(); + + NymNodeRouter { + inner: Router::new() + .nest(routes::LANDING_PAGE, landing_page::routes(config.landing)) + .nest( + routes::API, + api::routes(config.api, initial_wg_state.unwrap_or_default()), + ) + .layer(axum::middleware::from_fn(logging::logger)) + .with_state(state), + } + } + + // this is only a temporary method until everything is properly moved into the nym-node itself + #[must_use] + pub fn with_route(mut self, path: &str, router: Router) -> Self { + self.inner = self.inner.nest(path, router); + self + } + + pub fn build_server( + self, + bind_address: &SocketAddr, + ) -> Result { + let axum_server = axum::Server::try_bind(bind_address) + .map_err(|source| NymNodeError::HttpBindFailure { + bind_address: *bind_address, + source, + })? + .serve( + self.inner + .into_make_service_with_connect_info::(), + ); + + Ok(NymNodeHTTPServer::new(axum_server)) + } +} diff --git a/nym-node/src/http/router/types.rs b/nym-node/src/http/router/types.rs new file mode 100644 index 0000000000..6533a00a25 --- /dev/null +++ b/nym-node/src/http/router/types.rs @@ -0,0 +1,46 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use axum::http::StatusCode; +use axum::response::{IntoResponse, Response}; +use axum::Json; +pub use nym_node_requests::api::ErrorResponse; +use utoipa::ToResponse; + +#[derive(Debug, Clone, ToResponse)] +#[response(description = "Error response with additional message")] +pub(crate) struct RequestError { + pub(crate) inner: ErrorResponse, + + pub(crate) status: StatusCode, +} + +impl RequestError { + pub(crate) fn new>(message: S, status: StatusCode) -> Self { + RequestError { + inner: ErrorResponse { + message: message.into(), + }, + status, + } + } + + pub(crate) fn new_status(status: StatusCode) -> Self { + RequestError { + inner: ErrorResponse { + message: String::new(), + }, + status, + } + } + + pub(crate) fn from_err(err: E, status: StatusCode) -> Self { + Self::new(err.to_string(), status) + } +} + +impl IntoResponse for RequestError { + fn into_response(self) -> Response { + (self.status, Json(self.inner)).into_response() + } +} diff --git a/nym-node/src/http/state.rs b/nym-node/src/http/state.rs new file mode 100644 index 0000000000..ee7cd3aad2 --- /dev/null +++ b/nym-node/src/http/state.rs @@ -0,0 +1,38 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use tokio::time::Instant; + +#[derive(Debug, Clone)] +pub(crate) struct AppState { + pub(crate) startup_time: Instant, + // wireguard: WireguardAppState, +} + +// #[derive(Debug, Clone)] +// pub struct WireguardAppState { +// // inner: Option, +// } +// +// #[derive(Debug)] +// pub(crate) struct WireguardAppStateInner { +// // +// } +// +// impl FromRef for WireguardAppState { +// fn from_ref(app_state: &AppState) -> Self { +// app_state.wireguard.clone() +// } +// } + +impl AppState { + pub fn new() -> Self { + AppState { + // is it 100% accurate? + // no. + // does it have to be? + // also no. + startup_time: Instant::now(), + } + } +} diff --git a/nym-node/src/lib.rs b/nym-node/src/lib.rs new file mode 100644 index 0000000000..e32c757b15 --- /dev/null +++ b/nym-node/src/lib.rs @@ -0,0 +1,12 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +#![warn(clippy::expect_used)] +#![warn(clippy::unwrap_used)] + +// this crate will eventually get converted into proper binary + +pub mod config; +pub mod error; +pub mod http; +pub mod wireguard; diff --git a/nym-node/src/wireguard/error.rs b/nym-node/src/wireguard/error.rs new file mode 100644 index 0000000000..47b24af92c --- /dev/null +++ b/nym-node/src/wireguard/error.rs @@ -0,0 +1,13 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum WireguardError { + #[error("the client is currently not in the process of being registered")] + RegistrationNotInProgress, + + #[error("the client mac failed to get verified correctly")] + MacVerificationFailure, +} diff --git a/nym-node/src/wireguard/mod.rs b/nym-node/src/wireguard/mod.rs new file mode 100644 index 0000000000..ad3a0d85cd --- /dev/null +++ b/nym-node/src/wireguard/mod.rs @@ -0,0 +1,8 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +// obviously most of the features currently reside in the gateway, +// but let's start putting everything in here + +pub mod error; +pub mod types; diff --git a/nym-node/src/wireguard/types.rs b/nym-node/src/wireguard/types.rs new file mode 100644 index 0000000000..0243133005 --- /dev/null +++ b/nym-node/src/wireguard/types.rs @@ -0,0 +1,5 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub use nym_node_requests::api::v1::gateway::client_interfaces::wireguard::models::*; +pub use nym_wireguard_types::registration::{GatewayClientRegistry, PendingRegistrations}; diff --git a/nym-outfox/Cargo.toml b/nym-outfox/Cargo.toml index abf7104fc2..bfcd49c233 100644 --- a/nym-outfox/Cargo.toml +++ b/nym-outfox/Cargo.toml @@ -17,7 +17,7 @@ chacha20 = "0.9.0" curve25519-dalek = "3.2" chacha20poly1305 = "0.10.1" getrandom = { workspace = true, features = ["js"] } -thiserror = "1" +thiserror = { workspace = true } sphinx-packet = "0.1.0" rand = "0.7.3" log = "0.4" diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 75fff483b3..7b33510a97 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -2436,6 +2436,20 @@ dependencies = [ "itoa 1.0.9", ] +[[package]] +name = "http-api-client" +version = "0.1.0" +dependencies = [ + "async-trait", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tracing", + "url", + "wasmtimer", +] + [[package]] name = "http-body" version = "0.4.5" @@ -3192,6 +3206,7 @@ dependencies = [ "getset", "nym-coconut-interface", "nym-mixnet-contract-common", + "nym-node-requests", "schemars", "serde", ] @@ -3206,6 +3221,7 @@ dependencies = [ "clap_complete_fig", "log", "pretty_env_logger", + "schemars", "semver 0.11.0", "serde", "vergen", @@ -3405,6 +3421,20 @@ dependencies = [ "url", ] +[[package]] +name = "nym-node-requests" +version = "0.1.0" +dependencies = [ + "base64 0.21.4", + "nym-bin-common", + "nym-crypto", + "schemars", + "serde", + "serde_json", + "thiserror", + "x25519-dalek 2.0.0", +] + [[package]] name = "nym-pemstore" version = "0.3.0" @@ -3495,6 +3525,7 @@ dependencies = [ "eyre", "flate2", "futures", + "http-api-client", "itertools 0.10.5", "log", "nym-api-requests", @@ -4454,9 +4485,9 @@ checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "reqwest" -version = "0.11.18" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ "base64 0.21.4", "bytes", @@ -4479,6 +4510,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-native-tls", "tower-service", @@ -5276,6 +5308,27 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "5.0.0" @@ -5687,18 +5740,18 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.44" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.44" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", @@ -6633,11 +6686,12 @@ dependencies = [ [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if", + "windows-sys 0.48.0", ] [[package]] diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index 3c66fcc62d..24c79219b7 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -32,7 +32,7 @@ itertools = "0.10" log = { version = "0.4", features = ["serde"] } once_cell = "1.7.2" pretty_env_logger = "0.4" -reqwest = {version = "0.11.18", features = ["json"] } +reqwest = {version = "0.11.22", features = ["json"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_repr = "0.1" diff --git a/nym-wallet/src-tauri/src/operations/helpers.rs b/nym-wallet/src-tauri/src/operations/helpers.rs index 35dacbb190..9f66f29289 100644 --- a/nym-wallet/src-tauri/src/operations/helpers.rs +++ b/nym-wallet/src-tauri/src/operations/helpers.rs @@ -107,7 +107,7 @@ pub(crate) async fn verify_mixnode_bonding_sign_payload { custom_topology_provider: Option>, custom_gateway_transceiver: Option>, custom_shutdown: Option, + force_tls: bool, // TODO: incorporate it properly into `MixnetClientStorage` (I will need it in wasm anyway) gateway_endpoint_config_path: Option, @@ -86,6 +87,7 @@ impl MixnetClientBuilder { gateway_endpoint_config_path: None, custom_shutdown: None, custom_gateway_transceiver: None, + force_tls: false, }) } } @@ -111,6 +113,7 @@ where custom_topology_provider: None, custom_gateway_transceiver: None, custom_shutdown: None, + force_tls: false, gateway_endpoint_config_path: None, storage, } @@ -128,6 +131,7 @@ where custom_topology_provider: self.custom_topology_provider, custom_gateway_transceiver: self.custom_gateway_transceiver, custom_shutdown: self.custom_shutdown, + force_tls: self.force_tls, gateway_endpoint_config_path: self.gateway_endpoint_config_path, storage, } @@ -156,6 +160,13 @@ where self } + /// Attempt to only choose a gateway that supports wss protocol. + #[must_use] + pub fn force_tls(mut self, must_use_tls: bool) -> Self { + self.force_tls = must_use_tls; + self + } + /// Enable paid coconut bandwidth credentials mode. #[must_use] pub fn enable_credentials_mode(mut self) -> Self { @@ -224,7 +235,8 @@ where .custom_gateway_transceiver(self.custom_gateway_transceiver) .custom_topology_provider(self.custom_topology_provider) .custom_shutdown(self.custom_shutdown) - .wait_for_gateway(self.wait_for_gateway); + .wait_for_gateway(self.wait_for_gateway) + .force_tls(self.force_tls); Ok(client) } @@ -265,6 +277,9 @@ where /// Attempt to wait for the selected gateway (if applicable) to come online if its currently not bonded. wait_for_gateway: bool, + /// Force the client to connect using wss protocol with the gateway. + force_tls: bool, + /// Allows passing an externally controlled shutdown handle. custom_shutdown: Option, } @@ -312,6 +327,7 @@ where custom_topology_provider: None, custom_gateway_transceiver: None, wait_for_gateway: false, + force_tls: false, custom_shutdown: None, }) } @@ -346,6 +362,12 @@ where self } + #[must_use] + pub fn force_tls(mut self, must_use_tls: bool) -> Self { + self.force_tls = must_use_tls; + self + } + fn get_api_endpoints(&self) -> Vec { self.config .network_details @@ -422,7 +444,7 @@ where let selection_spec = GatewaySelectionSpecification::new( self.config.user_chosen_gateway.clone(), None, - false, + self.force_tls, ); let mut rng = OsRng; @@ -486,8 +508,11 @@ where .with_wait_for_gateway(self.wait_for_gateway); if !known_gateway { - let selection_spec = - GatewaySelectionSpecification::new(self.config.user_chosen_gateway, None, false); + let selection_spec = GatewaySelectionSpecification::new( + self.config.user_chosen_gateway, + None, + self.force_tls, + ); let mut rng = OsRng; let setup = GatewaySetup::New { diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 0cd084f931..c34975a3f3 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -33,7 +33,7 @@ serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } sqlx = { version = "0.6.1", features = ["runtime-tokio-rustls", "chrono"]} tap = { workspace = true } -thiserror = "1.0" +thiserror = { workspace = true } tokio = { workspace = true, features = [ "net", "rt-multi-thread", "macros" ] } tokio-tungstenite = { workspace = true } url = { workspace = true } diff --git a/service-providers/network-statistics/Cargo.toml b/service-providers/network-statistics/Cargo.toml index 97d9d36cbc..280a231309 100644 --- a/service-providers/network-statistics/Cargo.toml +++ b/service-providers/network-statistics/Cargo.toml @@ -12,7 +12,7 @@ pretty_env_logger = "0.4" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { workspace = true, features = ["derive"] } sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "chrono"]} -thiserror = "1" +thiserror = { workspace = true } tokio = { version = "1.4", features = [ "net", "rt-multi-thread", "macros", "time" ] } nym-bin-common = { path = "../../common/bin-common"} nym-statistics-common = { path = "../../common/statistics" } diff --git a/wasm/mix-fetch/Cargo.toml b/wasm/mix-fetch/Cargo.toml index 957fcde528..50e5d61af2 100644 --- a/wasm/mix-fetch/Cargo.toml +++ b/wasm/mix-fetch/Cargo.toml @@ -14,10 +14,10 @@ rust-version = "1.70" crate-type = ["cdylib", "rlib"] [dependencies] +async-trait = { workspace = true } futures = { workspace = true } js-sys = { workspace = true } rand = { version = "0.7.3", features = ["wasm-bindgen"] } -reqwest = { workspace = true } serde = { workspace = true, features = ["derive"] } serde-wasm-bindgen = { workspace = true } tokio = { workspace = true, features = ["sync"] } @@ -27,6 +27,7 @@ wasm-bindgen-futures = { workspace = true } thiserror = { workspace = true } tsify = { workspace = true, features = ["js"] } +http-api-client = { path = "../../common/http-api-client" } nym-socks5-requests = { path = "../../common/socks5/requests" } nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" } nym-service-providers-common = { path = "../../service-providers/common" } diff --git a/wasm/mix-fetch/go-mix-conn/build/go_conn.wasm b/wasm/mix-fetch/go-mix-conn/build/go_conn.wasm deleted file mode 100755 index 0066e6d4fdaa888c7eef83431a7037d063ba6a1b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8527995 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


1(>XM_cBVvJfdq>6sq4hGO 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

(CpBH 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 z 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 J=4AN=`dJ+2HSOcw%qbdw-tA9+436gq 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 RY;Wgj*68iCT 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�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�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 {0_uihxmiO{q}GF_V4`8@BHrX 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

9Pf$0UKMdt4qHXg~h73Kmsl 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

=;LOFi{9B0ABM>%58X%_rtg2LI08L4NB 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Ⓢ9=2@*mK@QXED)GV- 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 udu9F1boMK@X~Qw%XFk}#Xs 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᷌E2I$1!1bzcxyzH=DloNircn@6xr3OwHd%e`7%qT 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%0AP>rB7!Xks4!z*uloEF#Q-79(_ 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 z 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

UwCBlnYP zRYWL9H5$;0P83Y`N{ULBKi8?eJCE5>ppH-{37!{~NBifMjIopOPLlx@L zf)3;__DW)OhxS7)n$V8iSJkSBP>yOepcS1c_`JQ6q7rpzHo8;$A@2)n^%kQ7HE2W| za#q`hC_@$M(Si=-f6-n^jPBBYs6`Xnk^3dJDk7Al8VzVgCkno7ucW9%9h!|&?T5Tg zt=?i(pazX-L(Xfq4N-QJIicS>l_DYIM z)S=nv9_@#`*VXDRMg?lnh&JSW&9))RP=$K5pac0|w^tIQd$k{G(S&y7zM)n{gmP4) z0j=mn!JGC*(lR~$a_nz-eOds290P#&Npluq6}52M+-WTf7mOD(S6zvwP->+ za^F^~B0@Q;(STNTqTrkMN{UL&XLApb&pB{6zX`=J(1Xh-fvYE?uiM>QJIicS=`_DYIM)S=nvA?=5}i`D8a zMg?lnh&JS0V%rd9s6stj(1H9*?UlsnVeN-nG@%{2o>~RDp7}K zqeA;3?{c+zi&23ZG@=bTSJ*a08LCi^7IYxrw^tIQN3+2~R2hrFxR>MceEYS4%_&XLApZt?B{6zJ z`=J(1Xh-giYE?uiM>QJIicS4o1i&23ZG@=bT zx7#*E8LCi^7IYv#u~!nKr?nqy(S&y7-l0}SgmP4)0j=mn!JYO>ib~X>+2|SVhrGMg z>MceEYS4%__l|h`o}c5_M=cs+2|eG4|z|i)mw}T)SwY<$SG|bq6}52 zM+-WT|Fpf57`;>bp%zVONA5FfRYWL9H5$;0P82+AucW9%9h!|A?T5Tdt=?i(pazX- zL(X%y4N-QH=()q7wzRy^^95b!awvS^FXH zMYVd1QGpsXqV50kSl?mSlV!U99}%3sr}ws|IlcG(POnby_1SxRFMH3P*)zWqG-|+r zQG-Se8Z~Ors6j!Z28|FPK!5-N0t5&UAYj0VpaFvH`??SA?;rP(&$`w+&y{tp^*(^C zi%ix>2`W&FCbS{`Jnd2vCYj)S(&e$h*X}#3)A%8ntTKA9600 ztjt1`p$heALDpp^>!Sn}s6`XnkXxIUNb7RhAF9!SR%Bl;SxE#aMJ4LcjCSN*VOnC8 zqXvyySIGX5bERZu7NQJQs7DL38k6-=f(q2432n%|%CtmUSIYiSjRv$L`)bKbB0woB zQHN%SiE3*(~s6stjkaexe`Y1sKYSDx?d}I%8%@?n2`W&FCbS{< zCespWT_gKLH5$;0>|U~x2vCYj)S(&e$h+CJ#3)A%8ns&4A98Mytjt1`p$heALDsD% z>!Sn}s6`XnkUN-`Nb6eJAF9!SR%G8MSxE#aMJ4LcjCSPRZdziLqXvyy*UA2nbBAPQ z7NQJQs7DL3Mw9hXf(q2432n%|)3iid*USD;jRv$L`!2~!B0woBQHN%Rtf5@36E3*(~s6stjkadsA`Y1sKYSDx?d}I%2TayS2`W&FCbS{Llx@Lf~*gltd9~@pcYMNL+)x? zBCVTcf2c+ST9N$`$x0$XDJoHiX0#*kVbc<$95ravx<&SfoR3OYW+BQ@g?h9g>k*Un zQGyE8q6uxteblr>TDQvnP>lw(BKu>Kl|+D2RH6>eXh+`1O-qb&)Syvoko_TNldQ}_ zl%WdsXhGIvChMaF6{tlM+K~IWX^FIMll`F@4QNI76OxrgfKpVV4$Wvs-fmiAl%ocX zTDQyokn^NuWfr0gRj5Y`vOZz5K1xu5S~Q^zxlfsvNb3&SAF9!SR%BZ*Rd+9m0Hvrz z9h%XOyi-j}jB?bVQEQa_A?LZ0m05@~RG}U%$a&X5IVS6)1Qn=76WWk_ znrVr&?w0+b8VzVg_UV$9M1WFMq7KbyN8XD}ON?^Vpiyg*{UOJdtjt1`p$heALDm^2 z>!Sn}s6`Xnkb9lw(BHNd&Bm$J85_M=sJMzvlEiuYb zgGQ}c_J^F8OIBtf%20)Rv>@vhChMaF6{tlM+K?NVmPqS<*&nLWfL3I`QnHc=P>M>_ zp&9MSdzER4QH~lkYCRzPL(Z!uE3*(~s6stjkQJJ&j}la%7ENeF?%Ad#()y6>57lTu zE3#iBSxE#aMJ4LcjCSO`*0jVZM-3Xa7TF(iBFV}uL>a13j}~OT&SZU*paQjMLK|{l zZ(1U)2W5Y#Mgv-r{RYWOB0woBQHN%^GWMvkj3{|K{3$os1 zvOY>sfm$@74Y_YNEs@rTWq+tf16q-tNLCU7N>PbAG@~7P=a`ll<)}fU)++l$&RZla zvk+ydLOoiL^;VPhQGyE8q6uxtO-)Or^%2=0s?mT}WWPG>Ec-*wJ0vT!5M`)BJz9{JnXHczRG=13XhZI~rX|w)sO%5bXh18n-ziy11Smx% z>d=gKsfm$@74Y}_&Es@rvvOiR# z0jM>_p&9MS%S}s+a@3$v>tnJ%v*{gRbgh%!{69xcfF zfXVtOK?Q2jgf`@srX|vPO!kLrG@upPAC#;l0+gZ>b!bLA@-8whG0IVcMyLlx@Lf~>1e)<+2{P>UwCA@>^75@|gp`$IJv z(2DF8STis*0jVZM-94D^o-9s`iVykPP^{u$=L?y8eC#MVnE3@$Xd*5Dq4#|+Nso{mR?ljMfZLp2)EitHOqB0woBQHN%PbAG@~7PqiKmzjv6#-Jxlh7oI52evk+ydLOoiLb(hKdC_x2k(S$bS-fdbU ztxuBup&AWnMfN0FNdzcGCF;7Xh18n@0YA30+gZ>b!bLA@*XfPG0IVcMy*ek{UPT=l9gGA zGE|`+Ey!9-)<+2{P>UwCA@@Pk5@~&!><`swKr6BzlB^^Gl%f)KXhu8oK5SZIl%ocX zTAwcaL(VE$nT04r73$G~tdE$ij}la%7ENeF?!%@f()tY9AF9!SR%CxvvXTf;ib~X> z8STh>#I(dHM-3Xa{+sL%Igd(KW+BQ@g?h9g>tiPCqXZSGMHAYP`*G6}X?>>b57lTu zE3!AqN+LihDp7}Kv?K2^(-NZ`HE7iOEZHA&9+#}lLX@Ej^=LuX6DI4U1Qn=76WWlw zo0drHvt@s%Mgv-r{iI|i5ug;6s6#W_k@pGH5~Cb7Xw>=~*&lMAlB~=^l%WdsXhD|s zvZu2?N>G7XG@%W-r<#^X>vLs)s73=?k^NlBN+LihDp7}Kv?K3%rX@x>YS5_ld9pv` z*pii5h%!{69xcdvzRCJ1K?Q2jgf`^9z_dhKpD+7EH5$;0>=#N_5&=q4i8?f+9eIvv ziBXOkG-`c;><>AoNmgbd%20)Rv>@wrll4)83e=(rZODC*X^FJHQ1*vvG@upPu4E+< zpcIv;Lo?cucZO++QH~lkYJHLH4>@N_R%Ri}P=$K5AnU~@>!Sn}s6`Xnkn5S2Nb8Gb zf2c+ST9N${$x0$XDJoHiX0#*krKTlDIcm_T^(C@DG7C|LD%7I|S-#2oC_x2k z(S$bSo@H7htuK}Rp&AWnMfS@jD~SN5s6-u_(T==Vn3fpjs6nIFm&yK+6G&EOA<9sN zdbA+xl_u+>1Qn=76WWmbD$^2aeYxxp)o4H~vR^G(NdzcGCF;TyRG=13XhZI6O-rQpm9jrnqXDhRjwCCI0Hvrz9h%XO zyw{nQ80Dxzqt-$8hn&|-R%Ri}P=$K5AnOe#>!Sn}s6`XnkQ&p&AWnMfO`HD~SN5s6-u_(T=>gnwA*ls6nIF*UJ8olS)=*A<9sNdbA+xZ6@oZ z1Qn=76WWmbcGD7ReVyzN)o4H~vfm+DNdzcGCF;d=gK zjauIz`$NvVB`dQKWvD_uT99>t$@(Zk1!~cRHst1}CDQsv*&nLWfL3I`N3xO#P>M>_ zp&9MSd#`DUQH~lkYJHRJ4>|9Xtjt1`p$heAK~`b1K1xu5S~Q^zxfhz2Nb8$rf2c+S zT9N&J$x0$XDJoHiX0#*k1EwWLIcm_T^)0eLeXh&XUT4I!=28~+ZCi_FqC6bj{h%!{69xcea z)MR~>paQjMLK|`~GcA$Ux6A%ejRv$LyOyjZ0+gZ>b!bLA@-8CV{UPTH z$;vE58LCi^7Gzy%vOY>sfm$@74Y`eJiL|~`_J?XTpcUCyNmdd8N>PbAG@~7PSDTg? z<)}fU)_2MNkaLY>Wfr0gRj5Y`vRae%QGyE8q6uxtz1FluTHh`ELp2)EitOtoD~SN5 zs6-u_(T=?9O-qb&)Syx8dt`se=_D(&5M`)BJz9`;gUR|RK?Q2jgf`^fXj&qz@0IjauI)`$Nvnl9gGAGE|`+Ey%jXWPOyN0<~yD z8** zWZhx1K1xu5S~Q^zxua=`w0=x0H5$;0?0Y3Ei2$XjL>-#Zj=cL! zON?^Vpi%2bWPiw+B`dQKWvD_uT99?W$@(Zk1!~cRHsn5FS|Y68STjXh-ryYjv6#-osj(@=V8gpEJPWqP>&X5ebi)ql%N8& zXhIuuA2BVF)=$X(P>lw(BKuLvN+LihDp7}Kv?K3hrX@x>YS5_lld?bLd|a|J3sHtD z)T0Gio5}hpK?Q2jgf`?pW?CYxpOXEd8VzVg_T!S3M1WFMq7KbyN8S^rB}O@F(5Us( zvOnbPl9gGAGE|`+Ey#M(WPOyN0<~yD8*)EkS|Y8Vk^P|>4QNI7Q<9ZLfKpVV4$Wvs zp5;H?5~Cb7Xw>>y*&lLFm8{G{l%WdsXhGI@(WMvkj3{|K{3$k8lvOY>sfm$@74Y`hK ziL`z}_J?XTpcUDtNmdd8N>PbAG@~7Pr<;}-<)}fU)-THbknWVt5m zqXZSGMHAYPdxmL=w0=qUhiWvS71?J>RuTb9QHeSs<{*d!3$;vE58LCi^7G%BJWPOyN0<~yD8*)R_5^4Rq><`sw zKr6D(maHTKl%f)KXhu8oUSnEfl%ocXTE8LtL(Xd@E3*(~s6stjkQJG%j}la%7ENeF z?(0lTr1hJ!KUAXut;l}8WF--x6qTq$Gun~&2GbIw95rav`YqWXa$?EKEJPWqP>&X5 zz0qWSl%N8&XhIuu-(*@Mt>2dYp&AWnMfRH|D~SN5s6-u_(T=>tw8SV!4H~t6NA`!D zb0jOX5M`)BJz9|U7L)Z+f(q2432n%It7(a}epmK~YBZn~*{NhD5ug;6s6#W_k@q&! z5~Cb7Xw>>W*&lM=E?Jp{C_@$M(SodZn5>TyRG=13XhUvhS|Y9Am;Ip{4QNI7xssJc zfKpVV4$Wvs-aAc8jB?bVQR@$6f5>^4WMvkj3{|K{3$o5LSsx{+KrNckhTQW_OQiLO zvOiR#0jw`3&|pcIv;Lo?cucY$e%QH~lkYW`GHWfr0gRj5Y`vfg8|K1xu5 zS~Q^zx$iYCk=7r}{!onuv?BX`l9fb&QdFW2&1gqnVOnC8qXvyyeGh z%l?pakz{2Sq6}52M+>qpHd!Afs6Z{6(1zT~v_x9}UG|4+G@upPmq=C;0ZLJcIy9pl zd6$}&80Dxzqt^eB{UPTv$;vE58LCi^7G%{X>!Sn}s6`XnkbAjliM0Mq_J?XTpcUCy zNLCU7N>PbAG@~7PSDKa><)}fU)}PD%kkd$3W+BQ@g?h9g>nfA=QGyE8q6uxtz1p-y zT7Mz?Lp2)EitKA7D~SN5s6-u_(T=>d=gKjaq*#`$Nu+l9gGA zGE|`+Ey%jbWPOyN0<~yD8*+Qo5^4R7><`swKr6CumaHTKl%f)KXhu8oZZRz}%29(x zt-qE1A?H@f$}B_~s!)#>WDO?kqXZSGMHAYPdz)#AwEj-^hiWvS71_5-RuTb9QHeS< zqaAs7n3fpjs6nIF-^>1xGfGxwA<9sNdbA+xPLuUff(q2432n%|%d|vV{~-HAH5$;0 z?7Jl^i2$XjL>-#Zj=agV#3)A%8nymW_J^E%BrCHJWvD_uT99?G$@(Zk1!~cRHss!C zS|Y7~lKr6?4QNI7ELlkeC`Bde(2REE-EUfAl%ocXTK_EjL(T(|m05@~RG}U%$oi1U z`Y1sKYSDx?%iTO=v^zM@&nk^*?2Qs73=?k^Qh_B@v($m8e5A+L8BB(-NZ` zHE7iOU$Q^sJR(_{g(yQ6>d}I%M@`m82`W&FCbS{qZH(4Jgs6Z{6(1zS6OiQHo@3KEs zqXDhR-X$xE0Hvrz9h%XOyeCadjB?bVQR_csf5`cSWMvkj3{|K{3$mUvSsx{+KrNck zhFt5cr|%%r`aiNiRHFf{$UarFk_b?WO4Okl?Z|tsX^Bye8Z>JCr|b_o&y%doLX@Ej z^=LtsZL&T}P=Q)Bp$)muH!YFYf64w(jRv$L`vsDfM1WFMq7KbyN8SrfON?^Vpi%4p zk^LdZk*v%@l%WdsXhGI#ChMaF6{tlM+K_v?X^FJ{U)dk3(STNDzeuu@2vCYj)S(&e z$a76gjB?bVQS1Mc{UPTJ$;vE58LCi^7G#}ivOY>sfm$@74Y@BiEs@s$FZ)9^8qkVt zPqLB-P>M>_p&9MSdx>d@QH~lkYFV;Blw(BKs`KN+LihDp7}Kv?K53rX@x>YS5_lT-hITULjeTg(yQ6>d}I%z+`=t zpaQjMLK|{lX<8z!=gIz1jRv$L`&E*aM1WFMq7KbyN8YPVON?^Vpi#?~{UIlmtjt1` zp$heALDtzO>!Sn}s6`Xnkoy|b5@|hO_J?XTpcUD#m8>KJl%f)KXhu8oBGVG195rav zdV%Z@Ij@tf%tDl*3iW6~*6U5yM+quWizc)o_YI~c(t4rn57lTuE3#wBN+LihDp7}K zv?K40rX@x>YS5_V$o`P?CdtYyL>a13j}~OT*<^i`paQjMLK|`u(-LW&Ci_D*8qkXD zb0jN?0Hvrz9h%XOytkN^80Dxzqt@xNKjgesvN8)%hAPyf1zD-d`Y1sKYSDx?d}I%b4}Jq z2`W&FCbS{PbAG@~7PwP}e_jv6#-ylw(BD;~SBm$J85_M=sJMykFEiuYbgGQ}D_J^FSB`dQK zWvD_uT99>($@(Zk1!~cRHsrRZCDMAO><`swKr6DZm8>KJl%f)KXhu8ot}`t$%29(x ztyjtZkaN9cWfr0gRj5Y`vO1IXQGyE8q6uxty}`6ZTCbMe zXh+^nrX@x>YS5?^%KnhkOIBtf%20)Rv>@wdll4)83e=(rZOFaFv_x8G%l=S}2DBpk zR>?{tKq)Fwhi0@RZ!j$}%29(xt=Gu@kaL@4Wfr0gRj5Y`vTiq7A0?eXh+_irX@x>YS5?^$^MXYmts8STjXkZFlgjv6#- z#j-!-ERvO3h%!{69xcdv&}4m-paQjMLK|`)GA)tT8)bi}Mgv-r{b9*UB0woBQHN%< zBX2b=G0IVcMy)r={*dz#$;vE58LCi^7GynavOY>sfm$@74Y?mREs@rnWq+tf16q;& zh-4)ZpcIv;Lo?cu_o!)!QH~lkY9+Eilw(BKtAPN+LihDp7}Kv?K3v(-NZ`HE7g&i|h|MPe@i~A<9sNdbA*GH(4Jg zs6Z{6(1zS6O-rQpR@on_(STNDe?qd72vCYj)S(&e$a~7P#3)A%8nsf{A9Adht2>Zc zh%!{69xcc^)nt8?paQjMLK||QYg!_$x5@rcjRv$L`+1U;M1WFMq7KbyN1kn3Vw9r> zjaqM){UPW1l9gGAGE|`+Ey#L-$@(Zk1!~cRHsrq0v_x9(ko}<=4QNHSBUwoVC`Bde z(2REEon~5Ml%ocXTAAz*Ij2ijW+BQ@g?h9g>qRE(qXZSGMHAYP>zbBG>s;9%s?mT} zWS=2fNdzcGCF;H&+#gdg-h%!{69xcf7Ox8yUDo~3iv?2E; zrX|vPm+TMKXh18nUn*Hi1Smx%>d=gK!Sn}s6`Xnko$7e5^0?;`$IJv(2DF=NLCU7N>PbAG@~7PfoX|Rjv6#-y<7H&oL5R# zW+BQ@g?h9g>s2P}qXZSGMHAYP`)bn?Xd}I%b4=Dp2`W&FCbS{< zEv6;Xx={9qYBZn~*>9DsBm$J85_M=sJMvP~5~Cb7Xw-VY><>9_ldQ}_l%WdsXhGK7 zP1Z*VDo~3iv?2E$rX|w)fb0*|Xh18nGs#LKKq)Fwhi0@R?_ARoqZ~D8)GB3v$a$w^ zWfr0gRj5Y`vfgE~K1xu5S~Q^zx#yXdNb7^LKUAXut;jxKvXTf;ib~X>8STh>w`qw{ zjv6#-T_pQM&IOW{S%@-Jp&l*B%1zcs2`W&FCbS{)vyYBZn~+3%ICBm$J8 z5_M=sJM!LVT4I!=28~*k><>AGWMvkj3{|K{3$iXWSsx{+KrNckhTQj?mPqRo*&nLW zfL3IGK(dkuP>M>_p&9MSD@{v`a@3$v>r&Ytay}?onT04r73$G~tcy(6M+quWizc)o z_hQo$XcP>lw(BKvB|N+LihDp7}Kv?K2t(-NZ` zHE7goWPiwMB`dQKWvD_uT99?E$@(Zk1!~cRHsoGsS|Y8hWPhke16q-Ny<{a3pcIv; zLo?cu*O`_W<)}fU*445<lw(BKt1MN+LihDp7}Kv?K3s(-NZ`HE7i8WPiw+BrCHJ zWvD_uT99>*$@(Zk1!~cRHss!GS|Y6*WPhke16q-NpJXKwpcIv;Lo?cuH=C9i<)}fU z){U}1J4vOnZJBw3k-C_@$M(SocGo2-u#RG=13XhZI5S|Y8RWq+tf16q;& z5y?s-Kq)Fwhi0@R?_tvtqZ~D8)Vf9Xhn$Z}R%Ri}P=$K5AnOs6^-+Qf)S?M($bHnb zL|V7X{!onuv?BXsl9fb&QdFW2&1gs7$4yI&a@3$vYmogRXOpbVLX@Ej^=LuXVjas+M{*d#eWMvkj z3{|K{3$i|8vOY>sfm$@74Y^O5mPqRk*&nLWfL3H%uTXa{i2$XjL>-#Zj=WP%ON?^V zpiyg-{UPVMl9gGAGE|`+Ey#MF$@(Zk1!~cRHsso-CDOW6_J?XTpcUEAm#icLl%f)K zXhu8oUSL{cl%ocXT6f9*kn=*x$}B_~s!)#>WH~15qXZSGMHAYPdzxv9wCeXh+_QOiPS%)SyvolKmmam8{G{l%WdsXhGH)ChMaF6{tlM+K_vu zX^FJ%k^P|>4QNI7izO?G0Hvrz9h%XOJkPYmC`Sz%weFSuA?GEMm05@~RG}U%$a<;C z`Y1sKYSDx?<`swKr6CeBUwoVC`Bde z(2REEz1FnEC`Sz%wHDbQaw5sfEJPWqP>&X5z0PEPl%N8&XhIuuUvF9>tp{a)s73=? zk^KhAN+LihDp7}Kv?DJzEiuYbgGQ}~WPiwcqhw_kq6}52M+>svWU@X=P=Q)Bp$)lj zHZ76Xhh=}LMgv-rok&&^0ZLJcIy9pldFPmx80Dxzqt+_>L(W?yE3*(~s6stjko8uR z^-+Qf)S?M($W2X4r1cTmAF9!SR%E|TvXTf;ib~X>8STh>yJ?A0jv6#-JuLe}&O0P4 zvk+ydLOoiLm6@!M5>%iTO=v^zxuzx3`l##=)o4H~vfn9LNdzcGCF;a13j}~N|Z?Zm0P=Q)Bp$)n3HZ76Xqq09#qXDhRzCf~)2vCYj z)S(&e$jePjjB?bVQR`!}KjgeevN8)%hAPyf1zGPkSsx{+KrNckhTQj=mPqU4vOiR# z0jM>_ zp&9MSyVkVCC`S#tQ}m3_KKhAA4Nkl6>B-p!=NepMaI?XK2B%*Cbm}aFa||vtxYpnv zgU1Zc=$?*8f|KNi&O!jDp7}Kv?K3E(-NZ`HE7g2N!{Ng$hk?fG7C|L zD%7I|S-r{nC_x2k(S$bS-fUVTt!K*qP>lw(BKsD}N+LihDp7}Kv?K3U(-NZ`HE7g2 zS@wsVL9#LnQHCniqXk*FnXHczRG=13XhZJprX|ukMfQhkG@upPcSu$e0ZLJcIy9pl zd828GQH~lkYCTK#hnzblE3*(~s6stjkad^I`Y1sKYSDx?-Lz0zQh%!{69xcdPOx8yU zDo~3iv?2FF(-LWYn(PnNXh18nACjyj0+gZ>b!bLA@;+=@Vw9r>jar{B`$NtuS($|> zLlx@Lf~=32td9~@pcYMNL+-<-CDQr~*&nLWfL3IGRI-u?P>M>_p&9MSd&IQFC`Sz% zwf>vz4>^xYR%Ri}P=$K5AnRi$>!Sn}s6`Xnko$4d5@~&=><`swKr6C0$x0$XDJoHi zX0#*kG1C&G95rav`YhQWavqng%tDl*3iW6~))OY{qXZSGMHAYPyPK9s>$7Els73=? zk^Q7(B@v($m8e5A+L8AO(-NZ`HE7iO9N8aoo|3H0LX@Ej^=Lts6+E5wQGyE8q6uxt zJ=L^CTAwTXLp2)EitOh~RuTb9QHeSPbAG@~7PFEuSO%29(xtuK-NA?Ib1m05@~RG}U%$ns6rM+quWizc)o_bk&AX?>~e z57lTuE3#iMSxE#aMJ4LcjCSO`!nDLFM-3XazD)LqoItWN3sHtD)T0GiuQXX7C8$6x zn$U*aSDBVb>&s<-s73=?k^O4PN+LihDp7}Kv?DJxEiuYbgGQ~dko_U&Y{|+jL>a13 zj}~OT#$d=gK&m9N>PbAG@~7P zZ!#@0%29(xt*@5-A?MAKm05@~RG}U%$VyDsM+quWizc)o_Z-s_X?>0C57lTuE3)4r zSxE#aMJ4LcjCSO`)wIMYM-3XazE<{!oK&(h3sHtD)T0GiZ!=jRC8$6xn$U*ax0{wo z>+58Hs73=?k^K(IN+LihDp7}Kv?DJwEiuYbgGQ}q%l?pau4H8vq6}52M+>svX|g^_ zP=Q)Bp$)n3GA)tT*USD;jRv$L`#i}?B0woBQHN%=!*&lM=Em@g` zC_@$M(SocCOx8yUDo~3iv>`V)Es@qY%KlJ|2DBpkJ(86~fKpVV4$Wvs-g`|;jB?bV zQR|yzf5>^CWMvkj3{|K{3$hB6^-+Qf)S?M($i2|CL|Wf0`$IJv(2DH$OI8vAN>PbA zG@~7PA22O3%29(xt#6V2A*YnA%tDl*3iW6~)(1`2M+quWizc)o_af60X??5g57lTu zE3z+^tRw=Iq7rpzMmzE<(-NZ`HE7iOHrXF?E|ILvLX@Ej^=LuXr6%j61Qn=76WWk_ znQ4i%zFqc*YBZn~*|lUP5ug;6s6#W_k$1UiiBXOkG-`c^><>9tNLFSc%20)Rv>@wB zll4)83e=(rZOCm*OQiLkvOiR#0jM>_p&9MSyV|tGC`Sz%wZ2RChn#C9 zE3*(~s6stjkky*3j}la%7ENeF?zN^R()w=MAF9!SR%Bl%SxE#aMJ4LcjCSN*Z(3rM zqXvyy-y{1&PA6HJg(yQ6>d}I%8%)+m2`W&FCbS{>X*&lLlmaNP|l%WdsXhGI3ChMaF6{tlM+K_vzX^FJHU-pM; zG@upPgJdNUpcIv;Lo?cucbjR6QH~lkYW;xh4>`9>R%Ri}P=$K5AnOj3^-+Qf)S?M( z$Q?~fr1gWcKUAXut;oJpvXTf;ib~X>8STis%e2HOM-3Xaen|F*oVz6}vk+ydLOoiL zHJPlB5>%iTO=v^zJ*Fkn`eE50s?mT}WZx@UNdzcGCF;T4I!=28~)jBKt$m zELoX_C_@$M(Soe|P1Z*VDo~3iv?2Ea(-LX@sO%5bXh18nKO|X61Smx%>d=gKLlx@Lf~<#3)<+2{P>UwCA@{?kCDQtF*&nLWfL3I$l9fb& zQdFW2&1gs7M@&nMa@3$v>xAqNIS)%#W+BQ@g?h9g>!T*?qXZSGMHAYP`-o|Yw0=VN zhiWvS71@tURuTb9QHeSb!bLA@~l@r-4df5HE7iO zS=k?QPL-_8LX@Ej^=LuXb4}Jq2`W&FCbS{rEXtF*^P=Q)Bp$)l?X^FIcLH37gG@upP zr%6^40ZLJcIy9pld8eC}80Dxzqt-9V{*dz`$;vE58LCi^7G$|5>!Sn}s6`Xnkb8z{ ziL`!6_J?XTpcUC?N>&m9N>PbAG@~7PFE%YP%29(xtzVY?A;*)f%tDl*3iW6~)=Ny* zM+quWizc)o_ob#K(t3{U57lTuE3#iESxE#aMJ4LcjCSPtrX@x>YS5_lE3!Z2oF!SA zg(yQ6>d}I%mz%7Q5>%iTO=v^zD@;qI^{cW!RHFf{$POeci2$XjL>-#Zj=WczmKf!z zL8I2M$^MY@D#^+$L>a13j}~OT+GKr{paQjMLK|{J(-LX@y6g|tXh18n&z7tt0+gZ> zb!bLA@?K+FVw9r>jat7U`$NuaB`dQKWvD_uT96f)td9~@pcYMNL+y<{a3pcIv;Lo?cu_Xg7vqZ~D8)cP&iA97;J$}B_~s!)#>WWCX3eUzXAwP->c za^GZHBCX$+{h=BSXhrs$B`b*lrKm(5n$eED#I(dHM-3Xaen<9)oO2{Avk+ydLOoiL z^%j%$QGyE8q6uxteXD7Sw0>9ihiWvS71^m|B@v($m8e5A+L8A*(-NZ`HE7iOJ=q^} z-Y!|0g(yQ6>d}I%cbKe?5>%iTO=v@IW?CYx-sfGg%)cs6Z{6(1zUeO-rQphq6CZqXDhRez#;L z5ug;6s6#W_k#~VQ z&Zy4e%at!b>F999Nk_-OeA3bQ+0Q&WlbY-I&nX|vRh`4{oOEQVbC}in;7Lc3 zI){tYYvs9bSFaJv^B1e<)Hzh@s?M=`?r@2E{O_v!&XbOg?tJD^BxiW$QK@Ff|MASD zqyMAMXPt6%;;v^NS!bSnbmHHhd355%Cm%&>e*F9L-l|_^qkB&}I`O;eK5jkv$a>DR zjt)PnK94%lw?6CW`14fX)u$XCtIuRTN8O7$$FD!-=;-TDIT{;v{f1MHBK6$y)h8bv zf0fFpGpcj=YBf_QlI!O@^JrApQC*Kd^^~K-*Ql8~qskq=LisDz>(sHHP_I+hW3{ic zRiEqdjH45~y4P!!ze~;4iM~hW)H%9N&DHafI-@#=uTuUK)p63Zj!N12U#jOnSM5Xg zdcXRN>Wu37NZwbS!`G^gC)N9@*OcmNeM0T#DRqBGCm$Vsn)+N9pL}#USLM_>yi;A( zvHnWkhx+`{FR0J(b?SbkU_TXY-;!AU#JI^`0spebTdzj+Kwq{OE-zAC>AH zu2J_YuT%3#bsYXwbw8{=gSwtLNj-nN`Zw?!YM0McuUBVObIVcxK6=%svL}vJ*Eg&C z{%7_00+l;iy+)o>^Ao43%x|jfe^>XV`mLMQzLZOK4y~H0%;A41|D<|v_1ID#)j3v= zkH1`XsO#Zcb#Lk%u2b)Gy4u5gRNuF#?_E82;?LClr&Ly5BlY~KGRN{*o#U@i-Pfzm zx2W$@T}L%Lbm}VepH{zUyjmA8t_hCiAaUzjO6ok$N0GslJ21P&qX_ z+@iiu$*Ax9=%3Z=)EWO%y;fZh>U%z@@AYt_y8evnQzueqROj%s%C(w5ppN=m7s>T| z)oav=)EU(|e4l!(PWgMP`&-p-{h&U->WY3)J+IE;ht&1=)qARIBv$9}!z!arq|T_$ zLH$OL<+u6;>bLL*>a|~}?)ge}kLns-qB<`-<>+vqdhhqC@97`a^$*o+<@cVc_l(u^ zr>VWFf6I}|9;x5v;m1_p7ptAB>!_~QGt_g+2Uq=eZS_50tahvVkH18{&p)W$sOyO* zhHs2>b;(?zPC=zzf`?Oo#PwT>*aU<{pvNhso#iX&sWd?qq?g8^3TKv)x_ObjsQM(z{IefqR-v3H<{V4E1#p>U3q#V6bb-r0;)ZYZ_ zztm^?RP}fMCe{5_YL9=Z@_(hyv(#r&*TcW6nflu`ev8Vh|7IPl6aB6FP5idHC*@K7 zt+2jE{kv1&$wB@7IQk}a->0khR{zZy)j3joEY&@a>hH?oU8?Wb)NfFF|62Wa)fv@^ zUHX|_2ue5e@@+lI*~e~I)|TE*H3@eQS_PW z9+V?>4!wH4T;=zq_GzhWB-iWIXI9t452)8&p`LrTx~hAM)YW?K$w!Ct)P4Pe>R0bq zs?Q&(o@4d+aI<=ix>_$%-@9BtNxk+L)%Pg(B|B5kAFIcaI-@#=TU5_4sUCGAx!$V2 zcXd7dvdXA^9;<7lUK6S7(H*Mm?^KWS@mH%IJx6uO^;XrXe8N@tAv1L>^}55asMpE) z8r7*DN6IJuUghQb$?CN#clcG+tNz=67*vPyc((dJlq2QxO7$7kHByUVl_MZ4D}nT)cahbzVp9V?=9b# zIwx*ZpZRxGuewIxrLO86|C;*U59bw3o^*VWcxBBer9Dl9q zQqLVG^;ll>4{D}PsZOM3*8f&JyGPxFdflj=AAeB&8@pX~sM+BTb#2tYiLXFV$;~NA)^+tjhEZz9*^oA{y@#uiPRb8{DAsi zZc+b^{zC2gv(>*{_21S}y@&N9>UXXFo*k>dW0CwVQ^!*Oej@pup0DmxELZjWJ$$`- z?%&nko~`~3{koc~bMzZ3tLDe*8ma53&f(qa^Qy;(Z%}h}PW-+4ZK&Dd0`(eo4!OFj zb9j%s%Ja`t-@`5HbN;oue>EFrcD?$n>ha;d>NV<=>i?4t?^Az!epUTl`$l!I%Exk5 z=TNBEsB^eb&HhI1Rb@vtKT>}~A~id_Up=qR;hWU`sAF|%hw8gL`aL!KBQ;YeQfE}> z@W<-0I*~e~I)^_|kJUM-|9%{+WBrTjRy#bQ{)V0SPxbw)|Hhm+Mg5KbZ|ZyeGj(sj zsdlPPq~2##*Au^`K9BO@n^mXs;REV9b&k~EwqrRmS7%h`@Ga^+)QQxw&QRZ%I!9-! zUHo76-ZVP0WlImrHd7k|e(0UjJ~%2^x_ZCOm61HOpm#lo5={w(9F*^b~h}b`Mw>~ zjyUJ!N!?y7Gu?HgQfKcSJ9bPvc0}xmK)6Qu^6$s@cR_=&Kv?^ufFs->Z2bekBeecO z;1L!GYyS}N2sa2@|1j_ft$ze~gayLd9|IoY24U;xfJbQkqrf995Z3-N;1O;Rw*GP8 z5nBHQ@CXZpwSN+Lgd2pde+qbn);|qA!UAD!0X)JD!qz_nJVNV_1COvkSo>#zN4P=Q z`saX0X#MlRBPZV5kj7XC(P{p)}uED&z+z4dP+F2Wk< z-XZ=1VeQ`qEy4}L*1rclLhIiL9$|s7_6xux+#qcI2f!n={zKpq76@zq5%35%2wVR# z@CdE{1bBq4{}eR%UHcQDLAXKq60p_{@Ca-F8SwbM#_tWn)_)E>!rFfUnm-8|gayJi zzHbn|{4YU+(E6`{Ls%fJ{nx-F+#qcIB4`j={|)d63xu`*7I=gkgsuM$c!bt}4?MyG zVeNka9^nRI>wg3uq4hrjkFY>k`#$gpHwasQ3V4Lpp9UUbfw1;xfJeAN*!rJ=M`-<7 z;1L!GYkv-Sgd2pdUjiPX^~=B`to<*b!S6MGZxFWrSKtvAeb9{Xo8k8iaD;1w1ww0p zZ-i_9lI|1%bXy45{KfY*!h-M~!Z~0F*9Z%Q))3za*9Z%Q*0=GEa7|ta*Z6yZ(0UIz z!Zm-v=Ne&wzZXb%fxovPU+V(D2-gS;%FDkA9|MkXjj%vy<@lZB_XFSvt)IXzVAq5r zv_8k*6a0R}H-5K%C%zFD2(9nnZ^oPAZ{kSz1#skZ2^_)}e?hlEX#FmPzX33WYlHo?;Y;TmCq(E1zkjc|>y;NOV1g|x4kK0@mX-w4+T3;zAv5Rm3I(?!^V{MQHz=7X{$ zED&0daY11W{EcwUKsiKbB(ZIV7U~)BU~da5Lz>QBeZ@yei5z_76`51fp3Isgaty2)*9fhj#y7$>!h+%V0`~g=L%2q0;rkk43t_?U-;ci$t`Qaptv`Toglm+=_5X(U zjqvXO0PKH98%Jp2?*+ozuK@P9g9c%N(E1sCBeebw{32ZA?*+m&{$3!o{!YLVt`Qde z`|m>dd+?3l1%4O!ZT;PVAzU*6*7|$#jc|>y0IWqi{N4J42#k;4YlcgVYY#Bq{Stov zAjUw*wg%V&xUDZi`w(Lt!UEw2@N2*p2sfa6_X8LY5!N07z6m_S7J2rFo76>iSul*I^i|{4*EWqOif3JN3 z+#dlQ@YneJ24U;hBmBjnW5D07uK|y6jda%jTEykw_-*|bz!4S*YuA7w+#qcIB;p~o z{s8a@3xu`54S0l`-wOP110LbsZwC#+0%7fU0Ecjmu=P8EM_Bw6;Gn-oXnhCt2n&R* zzX^DRo8JW-!Wu&BcLRs8_BVqLzt{M^LD>3RK#OqwdqDHI0*A0bSi|=X!q!g%kI?$P z2uSZ8eisO9zYlQ`ZVg`=J)4+!u)Q%F~5t~=J&?^PAuNWduM;Y^HT6_V>JJzQ5bGboO`M;(yNKKicnw<+EksPb~c} z*xwrq|Bn6sY5RR-<6k>De$=G*eGC86{{E1q|MJA(zqIr>HXk?kdor`}?eF4q^Zi}> z{j;{5TbBN79}WKc()@nU{(i^C`~K9x@7dpp{r#@{Eew8Qf7h&hiyt%aC-2Sg*X(c0 z;=i=`pYI#|js5;v`@LrC>Dqq(?9kACY2{t}P3F60f8SZYKV;?p%*I<-__h7LXWPR^ z+a7<>^821`r=L0g7C*7@8yml6+tsy|_oL;vW${Ng{g!KIw%tv}R(|_^?eb^y^_l(s zLHm2p<=6I)H5+fs{x00Nm8WIf{rbqHvvqEM7vD0!H}?0PO?S=m-LmDk<{he>A$qUYfes^-*=YJmoA=@+rod*(zSlv$hT$jYxev5 zmT$|Im!q@4H}>~SE6-2ceE+g-r`Hz$sZHl+?C-+GxA7(x{-xt*%k%oJk?ZGNy<7T) zmGirmA7T{yJmmCdtuVM!SD9XpT?N{SN*A9`ITRR zeffhw{#VM#-1-wg(AvKKGr;_YcLpGv6!IqwJpT9YfE#o8?>GEf4D2NRqkrG88{|K7 zIvcH007yr)YG`d9Yb7=OG!Iyv*P1v}RY6>_^(!=j}Q* z`pU3sq}#7Ej{LSuk zLZz<;14r~}w>a<2rZw2T&*$Ay6X!DCGHvxPCZ~D-s&$cF;LkGMZhkT8PW@Qa22nAa z4#xw=$Uc|2wt(9Lp)@Jr?T7Akl#L~k^JzH|DF)_m2?`~^R2A!Ul#AE%Oq_uGk5iKS znydFXnrmhb#CfqZu1UTpR)lO3QN!8p4Bgsi7DorcV#qjseJb0zmv2f|82? zlIs}c$|8nlXWd?wd2^>dOuo^PhU1|hliU1ghr(IkxF{yw@tt;&&0ZDRbbFeOySwM} z@%xkfS$94P5ih#$vkpjiN8O_EnMD_l$V%qe`i9XYciP)wNNqPJ+di9*d)^XhYcoJT z-VA5w$KA0vBHHuFRIr~VDq|yFo_hHwR=>BE{)Tjyr#thrJMGDQ_6)7sQ=8}ojWKUp zw0ncRhrZ#7@V#F=&yRAcLl5ruX2TEJLEfK_pvPS2BJmg*87L(($al}P-upMx;Vj$f zPN&1n8-`4*giOlHksM?f7x{-W-_B^*%V>saA%y7(I#z!tDr+{5!?Rc89wo}WP1J_g z8+S!Bc`m3^wvW!N3$gQ$ciMx@mt0M=ctT4s*l<2~L6Dlf?F?t34AK2Vg}U6of(bGp zA1@ypaPPc3c7Pz08?4w;<92Y)2zT03^f9EOssZ348}~yCB_Sb>I|SEl0xfCSdmm&T zcgH!WFP`1p{3dZWCEiWj|T@M2iZ*o)LC0jTYAqI0|?fjSRe%aJC% z)AG$OCbQ6p<1c2EQpOcTh)>axBzZ5BQ41Bfrp|+P- zD=X~5=AE`RDlk**T*54Jn&SE4!S-iI$A`Ne4;tj?V%a!k34ebxyV?_@$HiOUU@zD% zpxim1-kVPI>7BOxct#n4#)e2RlTmkQ;v|UEd_L|M!Y09VClj=o{qYP8eG0=_-t`|7 z7%Q{xIMkg3^ybj57c<>!p;3mt%c&{|WNh!_aQ11QtNyeL4Xo6p`7EAIyBA8?S}Ukz z$%OejT6VYp3JVd#!8lWsy!P~=mp&rV_QLR^r?DwL*es=GF^?aXFzXvs2%n*1^$G~N2fTb9(F_86HwJPVzAeS>r--P2LVs=w1d!>WlFjkr%~&tZU# zfbsa8uz>dS#D@PJF(nkxN&~j&EV);+&;u4jX||gBeFsPlz!CpWDUNxVQHq z3kz9ogNR|wH7!t#uu;>vfF{a&QS*gmbdDJ=2E40cn^>QsD4JKHWE{a^Q1a^=XTy)e z6CHV)1!+NhoS}^=6EA?ajRx}xL4+P!3$;b|arR8}@wWIWO43I#*%$;-p?(f_$-=3D@<26G{^52X$Ud4W{>gL!uf zPAc`w{Pf$}DjB1lO{ZNwtmJ1yG>E9kDRrlNF;Vr-nQQiO5>H<3Y&PgIQjPLKXxV3@ zyo+VHQ*Db*vMIBP#uKNSz!RGz!3Lv+E2cBEK60n6b?|U}M2a$x z27*~$D8%)R^9wf2;kY*)W3n(so-Tb6J1h#e0(UAgYY~`GR^Uu>J*ci(c9^C|3mr_~ z7HoW83Jdk$6@qr-6BjgXZa*rdO+vt!V2XmOZdTXa6UVt$>QZw6c~oZj((qoHtLfN?aG6`>6s9O z{xb-z(bdghnqTUXsUkV($e=O7sSkis-+*w0i8Pjlv9EX;T#EUqZwlr@7mUM>JvvNw zvJc(f92H(}cLhv<4r<{!a-kAJ@}^9u+1V)jh_LJZp^-m>#68)1FJw0?*cvgye;Q*vUY`YI5nHd2JkQVMrD zOW{84`+`yCi^mwL5=@Y42|`;>V5cNjks^r|Jd#+!y3e0_{f(fWzB#oml-JrP`p3)+G`y{O`NV0;T1li?25w;Ss`#t*_sWjGp% z@{UJaOptqA_PEpL(swW!d`veS$Ez}@-F~_f#p%FdJan36p0YF;VPkeaHH`DaeztS9 z2j#*Z?BmkXp`6e1DP|NQ?+z{oh^IcCkKWrguA^xtOJ2)xooVlIJPO)VMMs)wH$F0p zpJMEU1U$}Xf;x|;2MIm)lIv~`n&u)xw&kljVtb<2wc=Q3BfTKv%B7RdP9U@ACeuvJ zlXd5V1rSCjY?BX8+%jV{NMVNjeD?@w&#aiAVr{-R3$Yy}%qOu5hEV_(Db#TsTWknp zKYES|78^4)OHo|eh}WWM%qC0&DCWuaVr#yd{^7-7!<7~3HV5-wv^E_giLfuaQ?<%^ zibb?d6tCw*YM5=)F4oq#cGtPgCNb97&vwdz9vVe8$O#sPu{4TSgXp1?E-8~}{Zq>z z`Q?IYl#G)QsmxGUWg!!SSL33T4@bgWF2iFc&s^2YK)vdP!-R7>+vO_p1%}qpo3IpA z0flksp`HaJvL|9qfWxyIh~2cvlL8RUVeoyRIzK+`)JRRFWc>}gPg=OwOG~OI_+zw< z!HUSCOLwnQ8kvq7A^pyC8^p8X0lFJkFBIMY5+NL2q7o+gXoU4W?5gCb zQks9+l>7m^ zgL)SVwM1w2NQv&`O+;EF2?fUR>SLorL21J>*2TFqU_ZjR8f{WrnMGKAi{~f#8|-lCE@X=)N_2gLeHk_dwvp~&t1pbA z6(xb1ORJ=wDjt0asMQY%Z4anKVrpYEtr2k)~w^ zg~+8YS*7wxI&wql!59oGcS;;I+7yX-B=t2I<)=_fpJNm1v^(pCEqhetx40`|77BN; z1gM8KlTAvs{h>P?MSWGR5LUGTp9wTJJrF{3vB!SM1j;3DG+akqQFX4Qpx)=y|+G(kCh?ud(vaN*{AY>Dm2cgc+E@m$~+r>f0iHdv-db>xjUJS7`sm6^^b(b{Zf!iI)vhcULIP;Kwh zYNnDM=E(Dl`AC;xC0*Q$DiUOEi=C+Vy((EryV>RRe5kenx%4IVAuF}EK75sNfymaE z;8AJt=|R8XwhIbBj*AukVy^aQHCAG_G5q@2Wo&G_^P)5EPKxu~cV`TaE|%DOUZez` z@Z!8@fSxp)hyHhg)TfZkvv7bUt^>zD3=T?*@j2>F@57^b!X~v=el8NN-yq1KXUYwf zY8Ah-jHOAa(XOHan2r1fyW<(gz|tt!wnOIu3dTr;d?`DmgpS78C>Kc)Mz~<^VZcZC zLAFh5p+t~(H-zL97NxJFLGQ>*=YfhGlVFZG9yQ2ero4}p1lrIu&X#uu$;N@=6ZZ-$ zOgtzRJyaqq-Y15Uf!`e;)_Urd}a?2pg#_6N+Gg0(s5J)OcY zz>~29&`!96c6s$2QyHw5dZZbga6#XaE1|i92j$0Nn`&F7>NGx^FBAZ?4ZS09b z_o{s{m{MFQz&=MjZ6qtsI8pn8WLkp|@y z+Gb@Qs*JvrAB=+z`iJBbDo^#kN|vs&VFb#_9N#J{sj*g`!@^a6J1kXs+s@H*H#c(H%5 zf8xQFGFv~ZEw}~N2>SG)us1;oZuvN7q+^~>|Tx4A&Q@mjj zVcD*Zvl&JYr4nf>^fEM0cwNM;0xI3W>?oaRvlLAWLKS9;rXR`@v~fU@>45ZITF0S@ z3W&&QOGs#s#}pWz6LEXK7e2!bTIIM*iiwC9?R4N6dC>X>#|_aNFfwd1%dyEAFDn@x z#Kinm`7Kp4K2*yXG&FY!Bq5t{A|v6S_a*lC6X8!Fck682CXiY-B`a#c5IkXSqt+1>^hkR(At!BR9;%6p#a?t4w`^8<1OH_{ z-j*KkY2XuodJ3PaxEoRZcEENe_NZGZ_opRH~I7I|^{w{jvPwbg0~`jh`PX2`jF#o1Y!ui3tPhvPPoUL}X@Q zW|zt6?^KA8m%f z^FJbpu~1FbfTYNgwU`co=wu0cBX~t1daFXGdr{q{G@2oc5i*CqZkvl)1Dly89v?A6 z!cjZQA6s=NzsTN1{32+Q7vs;)iMUT;C`UgJ+56Rmgd~S&oJe>=h(gP;Z66c^h)~7-}68)APIjSmC1QP8fCItm; zl$taT7+F-dR<|}Q!hr3+61Tc^n3-}D6Iv`VaJwq<{6a|%$SF`W(nky3Sc{_d zM-m?gFsc6p_)(U<02E$(lU!{(G78TR9(1o>#m6?ISw+&L)%+)EP70G4W+i#2`Z7VCU|<9UU|L;fT5Ks?XvtS3dXKv`DSH9JMSxTv=>3Xr^K zCNpq%fsZ1LsW3rxc04nk$fF{9j3qzGUt}M$Q8aBZGl|G739~?$;i{bnxVBA4p5;k? zXr>oF-KgBrVAI2gDjPnIgK>(I9&b~%-;G*poKS3p8L>@0uqXJGT=fQ2*aR^Q4JO`9 zF2~Z9hb4nSX4;^(mqO9a>nl^T*s7(Uq*oVu_Dp30U6~e;#wbVl23Z$3br9zg{U~~h|6RH zp0yRF9HZh!9^*PZjuGm;%vU@s%LHcSMPw-FEF@7$AnrM`^#3Ui6mSNIl9R1KHND07 zOD~>?j3-%e_eNL@#s<>mj+_Be**9b1op$5^;DD#W>?~$5mwBed#jP?R$3^!nvrg8r ze^@iM?19LQEWr`M$$`XOvbd>5Jk0&KabJ=Gse+YlpX|bHJxXD5_7_@%;dLPO;F(pG zEhp!mK*vhVG%K7|tI{ViD5!c75DtLgBv#;BV2Q4Rc0jLty+#2u)#T@SK7}(QR+HHh zVCCR$8&{IGG@b(XP7+<_&92F%v(RO54<7^J@q?US_cCu@qkJhAC>ShM69uZYF#s!1);`jI4IVI>x% zMo}Mj=Dl!E%Ol%dw8#ELFmWN2V#=7?_su{Zj z;?96*yOooNPKJp{a;1VPQqDzy?M&Dka;&#eZKkCoWmidARz)^B%@7`$`TKB`w?e_$ zlz&sZ-TrawkEiupV~k3HWj5;bRF;$rdah`q%~De`SW4)hU;}2KH%i4`rEScq1Fl_6 zM#`#+as2Z2<{E0k8jh}>gdHG4dyI=5XDi9M&r!M#UYVzq$i@~!Wt)R-*|e)5i8{KI zGRgxxRgY!qGs8~Se&9b*70Q8E_ki^c^elTi7Ca}^wVVbei^(-)slT+pq$kd~+}sn7 zi=Gmzdp#T?_M!&bVE&9TUxxd{^K6X6Fz|g*twB!l1WFvoM4MA5J>?5K;hz5mR^B2N zl*iW^z%t1T%+7-n5*Feu7t#r^P0x9dA2DfZ&y~PeDO7I#+2%cCZg{jjJfbE_Pp!g5 zQGlq95=LN6zf(>8pjIZq)J3Y3>Ot7dmvSqjbH4&IC)a#2^s}>U8dZXa#H*61Ey4Jh z>?}19NvKSC7D`_tPP5s38em+g#W~!Wk=#eGf}vkwkMw1!Q zXnFMhid@UQI~b1;g>4$Ns2WLVG2(hV|yPe}l4;uY|(#4EYhFm~#Lnk$cnl4m>0l=Rsl$D2XZS zD1uOXbA3|+3Id;N1j z>%`H>2>XpO5NCXqN3I;C4a2phAJ4LoR3CnM*fr?~x(n_3$f7#zoSa8fBjdwb0yCnt zfuvF%c_Gho_%RKzpEOeYWbNnX0t`=OFT~hC+nE=k(Hi$zMMRM_TE3GuXvf~pysr+6 z+L1N};v6xKV5)^q2MCz~M4gfLl8_Mn7R|l)esIr&rCH(rsE(?nh?LhIsGbX4Z>Bb2 zA1)HIuZ@v7jk(YH6m2d@GKOr%q^0FIwAv?pK7v}zQQH;72 z2Nb-eDdG;19zVpUg+3sJd#FyKb8$@rrWGI`IHnbb{JwFr+g7ulxDj&1`~sI1(am@i z>@bXb)K$85!Hzzg<`-|D!(yZBwmuC29InW!Mx>>|OZAR%MNmHGsZwmFe&iuEmxnf3 z*%(R300IZrtP<@&1|8-3Gl*t!dhLP^VdvaqRe6J`9+;#d1HjS<$~7?}j^KemueI(v&%ga9(W*? zdQ3JK*TA>q{H<^Q?Yy`eW}|)#M5-Y{euR=>O9(i4QpEkqoE}pIFn+v5c1wTa0QH@( zW*v&2k3Ke%$|sV^en?O1F$E5KvDDeetcOnI#E_fij;-^w2Qn=zlK7IU7M5Oa(FKQ` zcF{k<^T9Pr=3uXftZz^w<`;*!35rX?(N2^@?v3YAT8T@KiDyvo@Q6?6iONJaJ}+M8 zq3sD&96ZZly2?J^)zr-NOZc0K>%A9P=BA~Z9*%i$)qqaxo>E2|Tn!ro_QYK~Xi6oM zCk&@%-s*|u^u017`_p{l>qE{Y=rtJvo<{&@V!%T4>8Mkr0cK1Sm6DBVZ|hPB=uoRN z4}5f^Q}Pb774ir}#*7ClvL&<(e0)n7X_P@O-O|(8Z^aCQD3ng zsQM2`$FUpB9Faj3gA;9}W4uL7eL-S`8}vA2`LrmhO(^9UFfDwN{&#D*hvb_5DWL?elQ=2OHzOWjb`TdyP7IgC~IpQ&RWo2%B^v5 zmiUReb8GrGmcf};yYeNe1u+9GBuLiLue+jt0zdZBwA83;du$j=tbNM8<)m=$0L6?m7_xL@6-q0HmffA6@u7-v1^<^TN)Qx58kH`dnGMLSNHoVe!#^ z0<|ps?nj6Agkq{LlqEpMT%TG$=fuQ+4siSD>3r}KH&=(rPsQjSZvp6K?OPGI2f0*r zv{8lipimlvJo?1Phqu_BQ40hZj%3b1&ZEn@%slGte5~&5bqa1sMoG{{{v4SfrBb$-@W3rhP_h}yE|Bdg2tvqb|E(+qvUXq9P3`1-m0xY&q-(b zDi`6>?a%dX-l!Oo8%%Q3cZ8efJZ$_TQ+HA7s0Mw^OC-H`viQfXBw3o$3-}%w zHEj>A;hBMx%;}lBUYWkp!H1vTlOAUQk2@T7?($jdm~xGNMP}^@M2q3m4q8qhV*f*ymXxHJ9}$w{zxYaI8=+)7c9|@)(w3)Nu(2 zVg=i}EbO83A(`}WXG3^Lq;0>&sq&lZ0%9h`oA`bDy%L0g$$RW}&%(;EBjQr%OGMX6 zdk$4dMx>*bPmchWTBrpFiAW0GJFBkDAkjhhW9R5;1fIx_Wtw%?wUo4Hspvw&XsDrh zXnBB>bO23CsFM4BnZa z;Y4g?p9%S1jFSrsOX8(Aigu)vx@%BJKnG1@2x*Cymr!<{p)}qo&#*L;h=Pi#ZC)gGJDZ3n?Gi_$sk^-> z0h?BWW-RO4%G%JlkZ4j?6+|!yMG~L9rP;3b1{2`~Cq844Fs|S-zTAx17Llep9wM;} zSo!4%6njZL5L!X+Fc|s0@H$Gg0c8+5PMl(9m5}FE%;7qvHW_SmK7dk&cCHHgsFb)~ z;n5m37q&b=EkzfT)6*@w52auM9qnST>xAvmQxC8XOhB~Uk>T1UT#L=aK2wUKR|CXh zVOy_$qupR)_-CDx*@K6t79$pw^U;SaH5RSQ2<*p#qm9pog1?Fn30g)x zaH_3NpD>%NM#wu;k%=o1G~v{~6L>UR6v(U_HZ25ztQ~1%Sb#(He*GdPuV+SoeIL(J z2u+T#+1Ps*r&(XWa3d=}bMc!qWvmx}N=QuivGn4LPvbfFtBXrq615M14>W8{7CpBN zk9s8_=fC4=!rFY=RKs>>f)Q2dJRlNW;y0(2miCfNVg;Ap1R<9jV7EU3W0fJfvWF`J zs}lvWmT-FD%V-HvSRAOF#?p|0CW@{pOT--Xj-wlGOK5W|G56SUDK_U%K_}Zg<-*m? zf)BZ?#)phm;~y$#(i#e1GzQP1-H29-8c=m{v^X;ICz(W(=C~~{2R5Qq`j}`#*JD!- zDiQ_`x>gcfuO^jDc;U)v7lod z%Pay18ZwV`#PUoq-<`wi3^o7VZx`HylzG6XSa6ZY6#4j0Z-%#Y>AH)%vM;N7E4*VL zK=v^v%L7H0ehv5{up_JXl34Zyv|jy?AQoI|qd5f<5ZxekCM zH*7j>bA&EOW#RO}5YL4O)c7jPpQ1KfAV6d1r24IS=Pt5WwZnn$OKRIcmW4aTN9q8U z`q=|ngHN-A1$t;KrjB6b;#p4f;lS*X@=)1qsj?dj~^TeU-L95X#uHoCVv z!8Z$!3x~;8?D~z4R9ewju(!qKP`@$&@iD&&OUF?1(YM8`i#IJq?GBieGGVo}Ti}fe zH3gr{PhrW*jqB-?=~PXzOPF^@_qq2Fcyq>EZN&wqKP*a5Yr9bdz~|z6mxrc|LYGQ+>6;g zdGO@P<9i9e$De%i$!1#04<0>w_%JQ&PwwAC{Fvqa2M;&zgF(!6^YN314<0>COaH;+ zC!gH=dZ`XRdGN`@`%hF&7(YQ@bGUkpkB6l#5Y4&t%Bhb7WOS*JKE2a=%T9ZV#{Tx( zMN59M9|oU^w-`s`Z#e^GK$G6vv$r^>JBcW;L8_1KbaAz&mw{uy|6nru1r&atAiZ8E zA`wtHo<|nRF&OJ0?PD1yYX8}rPjLy5y-e3b>3?t__v?BP#wvH`E_Y*J4`GN}JEBeD zWIWdZsRU0lw)!BSIZP~*tgBiOF zHQSM*#Y>D%hqDiuHo(KCgpxhn0G2c2uHq7$1D`-nyg8sAuMhDZ&0AUQD8v2jTxFEG z=c){McWsqKmzxjE^s3~`NQ{Z_^PLSb;+Oe}k4u1KP{bq2Yd^8(G9~X){6_ydUV}CE zU~}y^hbWFxe5uM{@joepVXT-*M;WDGF)3qlW`}nNmJ#N{#WLK?RZ2P6m%NH4= z5>u{5#!s3_K4~U-+)VPQndD(J$%ASVS;OZ)OVHeKcrAzFmk`PBLuH|{B{+kkk|5Nm zu{xF$QP^mbua^frD`ReE{R5oZ%y9^MIZqgga;mhB%;8U@Y2S|b%lU;7qK>)kFh_Q8 zX1Sy^opU8{41zS&nd_Utk!v;oX_>njIDy3Q95Pg9I z*Eu%!<)@mXQ7g4_8T2HVM5;MxwQ;|hWHV^xO38Jjsphu6!M@=QYOmxg*@a?giM?IG z)3n0ywz&P8CeNyc=C@R`6d|iKFn)_RMr4dN;kz?GjlK`&Tn-3$%(kNM7f=+KHnnz@Pty4V`38AwYL{^sIa zJayMWYGxK8aQbQSy#xi~E=oc*>3>dYMFdBTnViq8g2`=LDWZ#uo$L%D;eHC8i>owe z+%qUtG;Saq<(Jv?@a*I=H-)mk@e#+xcwdZlL6uze&hxy;j)os{EhCSC;NIi@w=sZ^ z%LtVcu8zp2c*h>C*d&AZk>DMWVd6N*6gVnHL+J|8e7UkSU$)rnhbyt<(_Bp^*^oj_ z%E?eiMPxuK&jt`@SHsNTCX?oGoj(J?E-#foqqn$9r;_?8tJClsCxGnZNSV@!q9dze!=Mp)4wRI!0B_cS<|HuN7jHVYMk z`+Ks(Z+hVR2K+XLXp(qFr{LWw9)s*$_z%3hbw2CJtynJo5so9p5S*)qFVueV!o3LN zNL3qOSIU+t&1>rw%9wkvr!YhUk*)pm_9m&wpUI!T$}!GySonKR)vx)2lg?em4A= z^|=&aTQaX7D~3>rJ6AFSJ@ObG0rr54U_~~S>!FsoBsC0h9=h3KC4?N}pw|u_8y;*T z+`p%pBt-$~u(o$U`+Av16 zcXTZo{UhDIAN6pJptccYS)+(Xb19lQdoo9-Uro>;JjC%FTH<`z#LoRn_1b9u?7Au%<8p0ijTB(vKy;p-z% zrH;Afg(mTFGKXSjM&JU^T!%%+*byLJ`ddn>l7fHs9_3z@9@7+)O~hg56S;k%Y>)fq zfJTxdoI=5=jRXi@#$+;0K$vKNO|pP-wn9PZn8L~$bc*@Kun<2_TcoZX^oN+fs}uka zx!o((1f!XA(7K&j&W)=A7_=*n}aeT1iqBEWO(&_@6sWb{diE4_ZXz{b1Nl$QOVRD*Z_ASd7AW z(;*kc?u~ruNzQBxEdZ4Q%V;@$NLvczzLU{xLGfaij9^se$V%@wiGxF&}DW zyx=g0f^=>xLHC&D>SY+O8q1NC{z--jHUR4Ruo}ava2&M4iz(XDPh;2$u~=QwurcbJ zQ@vrtq9`68b8g#WOrXBN+)M&9HTY>_#l+eHIGc%)JA7cc3?F+Rd!sp5TwcI|Wb6^M z-2Zu!zmjbL7w1HyUWhgCP@N&KwS0zG3w&%TX^h#%EprH?uq~5{81#w=@AHGpmrsYC z3^yor`+Xeps6b#|-ILefVe8w)Tj)gM`Q+xsUq<11J!~-_TAP0wcWv5ul#E z%rRuv`_iWo74@-&263Pv-qL`1f0gTQInkMkg^KnsAJj)7f8Vw*G!MVeg zH}f}oY$#$xJi)F0q5Aqb@?@4E&E4+SXHP(Av@-Yg$r>ojAOYbE;dbEMx88JfFy5A7wiP6^KJJC=cL;13GnHMe%Fs#IMdRj4oBzZR zwZjupnjeN;Ckw4JSNiqGA4+i34VrvLoS$SpgL{T@(>FECZC0Y2oTm??J+ zwE1*fijEd-1db?Zi*U9uPd#`hm`V~QDml%k!3p$EJM%}GY+Pyc)zEOzt}HHG05H-z z$$W9lWb-9-bnDD~Y!ZvA`)vFHeqTNZwkFMlO;)8HPDX9M8&oLrxN#bt5b)Mlh~+rW zMrQoPSOWiQ9E-F`Vz|ZdHo9_H-g{tC=eVVAzmF8*w>pY+e1v($#lF!Mtdod_Wl-!~ zB|Td5r+YGoycgXoj(0BI0J0MUhrrOvBxKRW!GfEDgH&xKI@|}k+Zc6fYQdaAXj6sC zkw}|$8EP(Y&CX7SxgFQt`eG_OJ_;WSE}}3)Q#8~Xkhp@u4Lcf(6hB`KhFmT>i8z~D z#zQ>WP%fHJ+m1h7Xc4Hqk;$@WEpwE}_>$|-odpqcnRgTGzz7v78j+pPeA@I3N!dSUZg26OC=4&DV4D}WIf-L9kgE>4_ zc)5r#HO3dP#H&J>>t1XG$*rqH#Pt!lI0Y8|+lWyf4m`Z7gzPLPVWJH^)lx#s^YjYq z+O5Z#guyFnc^+Cegg{zl3-KN!*?(|lXj#bqZw!OZg<4?6RmGr&h+4K`6rD=((u+Dd zK#x2yPbS;ypx2$JIe@JcHxcvxtfl4NNGxAhCIL!=8wo13Z-oUL)V55Y9A~THd`hOf z3S(-SFfViwv<@$0lb)M+5;z`MEj31g_b~_#q7xx~GiDnWS5$7kQ5sk+>LPcIxEbs0U3NB#FwqC#` zHmgF!y+n)BOD$Sj9_T+c_3E)n`FVI+d>)aMo`=VU=fO$Y1-Nqx3WcL_rH0~><%095 zq}&2LEjEv_rAFOhT*<8_kY;IiJWDuExSpX;?(!{%GB!-R%1G{;xj1w^$D7CIfT}@Y zs%;inus1@Hh6(*nbY+5c~%fG5Cm5?S9akuVjnk0kGHBx#nuOT;KM=n3T(=A;!9 z!F1OOERN`VT;7%g4z|}1^ENk7wrB7f!Zr*(skC46j~7GS*hwTESPh)N97^q7H~3oL z5VB0RVK{y>0?F)aSthX(Af(Q_b=%gIRME(W77t^N^U3ZAZZy-j{6rwh3(WjwD51eP z0#=e&=z08^>Ox5;cNLF=%zNbg}Pj~=FT=z+o(5+5g5nP&Dk8qz;rk)i1FIN zGMqjX;fOo6k3`Tw(NxwYQqc-sEUfg=QhW{+ZWf)!Zxg8#GvW>*F6PMCA`Y?{jM)$J znHJu|;_#F&29&93x|Ue@-9OL8ur_vli5xsi7?u;4HOtH~Pz~r^lgcf|R|&d5{*b?~ z$iMi}q%5R#%bdlYE^)RUN5Q{clwnnqRTYJrQdSjD^5@*}^9805-{@$BZ$N%i&BsaG zI&SO`|FGjMYVd^&r>GIl_5&wpN!1H1sbGPX>sP>~N^}gW5ov{49%+3EIH@jyl^cS9 zag7qkw{lgONZ5=kqhvthjiYHbC`4Qh-n1?=Ti;-x@rJspR4Si}e(G-GtYRgq!MRH- zRz_tkiD6MQXBw%vuUXf^z_kDwk#S{#|3*tFf5t7Yebzt8pYa||%eu`c`22^sZ^#`* z4sC`M_r)O+i=0?}@=*%8K{tHk29@yf0-H_Y>sj=*dk&W&&xV|NdqD*7A2NLSFEkd} zUY0)8KDy-a>yc;X?lmW|`IJK7Zo7%1fZVb*z>DtW8=bg-v*~o41LSG&_c)JrKED8i z$G2l-04KPqKc9BRQNtu);pVWYr`G)+CV>zoO(%d=DxS2QP(azV%;A1GFL!4B-Sat0 zSs8zmHB72d$yf#}9!$SPKLjeyYW>~*^k>t z3lWU}wCzv4_WZX@j!3|x3j9-}oY|9>F32gGF!3S`=I*(+9ogT{Kw0M(c@B7^= z!`psD^v0=6asht~x`m=egtHfdfUn1Rj}Xe07ze8??C=`MT$-Ak7yb(&=<3#f~G)W zCq$^j2};d21e3D|hDPK*K_-6;-n9z!{NO}=(Y-9|WAPg74H!ltcjZy+ssWRa-77W~ zcKmGj!Gi~1H&HHm@vO=c<})2Uc4a^q#u(eSMw1(v@c0x9csP^9&~Kk%M#)jbeBusj z|F@3H0Z$_yFVD>D-clWd~SWLuh3%=7v@u?{251vYRs2=ik zjt+)aAGJMtsG^fA7Fa1)UpSCrzB+iH#R_LG-VJgg29C9B$&*iPYFaFW3%HkXyb4@G zjf>z1Xu;>*(GE-_=u;tcCHZQ6QAP%~bhkGV*ltDcy-DtL727QnP$?TXWJv-}tuC!l z#9HZyk8ThZzRy`deCmqPy0Q#^Hk=l->WF6!g-2>^Rm{Hd?N0ub#U2q@K6Otpc&94l z>zI#)S?a01yP%v)BX8i$L5gL7g;KUipK-0!WgzpGi_oRIMtXG6%Z2KnyeM9M3Z?C$ z%fMOy*CgVR!9ka_Azi2I8?I}3TQJVk7ov=ufhO4`2=_7J6$4KyGJ9kl+(hC9>1N71 z%O7(LZxG2G!&v_35(q^9$vyMCbiU<(&0GCQa;m5j7#t9)0tix=h_m*v!{F(sFFER zoD*1g$TW{c%Oqh5zLU*dy;P<_*K^oD~RrM@UQqV#A;AgOwPV45iC_G{&IZt?F~3(DPxin2i85-8>Np`BANA6;gBaLU5smHo>gTgEo!y0sb&&O zUQOdgSRx{GU?=5Oat8Dg9%gDDM~^C}vg{;Q6Ia1+Ch=vgiIbD_)IklqIdB6}y_$`b z`W>;NIoA0hI%e!DqYnSfASa5Lh3cEx)OcA$!g3W3Xeufut-pDs66t9W8ObgPqS+&R8syS9 zJw>sWo=8R+?>03@kQ7?zt&ImTRCR}!D_y~3iIL1Y6#ifxu@1FJdRR~_OQQjBBC3t< z{tor*gf}`GQ^=2V*J8nji3( zJegC#Ld%I6IuV*V4%O3NwgeR$6Ho~M$`g}}B4Gyzf5`=J_!WZ>zh*HKe?YVmb4&!= zTL&IV0P|e$n2E{YO|B+clG576N+zfZ{Q7MAk5FAB43KTG^Y~ng|0VX@@h^y(O z_5qUu_bLnk7cJ;507LOb;1^h5H3MPFAtFO@V5T=Rl;D=*ke#%jsT~agTi*y!H%Man zz}U{%xWL{vUE7Nmf$JN#vxjx864*{s5;z>>jTmKk6ai>!;vG><;_f^XLEsZ89`lKN z$neICrA$byf~X*jFv1c4aC-?CENdo!qS5dqzB|HkS5D;foG8~e4Qs~$rGrOary2@B zS-vQjX&A^m`rFY|3+2k&CDJ+ls3QaXEq{R2ENXs>he%Iyb1=WK2Wu57iM|_W%@E2# zSny_xWkoOktut z$v$cXx%Uyr%p*wLmRT-9>uRzf`l9emNEBHWMQA^rgvcD?F!AuOB(RgvI5*9}9i6Fn zF6#~|N#hV;e4TVnM{v>BI+tbagF2oPcXKKBzQRhC>!Vt-(?{)TeQra3gjCQHAI*lt z7vqvf*39r>eFQv+dj)|G0vJ_**f~=0$T#nW8nv1bIUUMl%@m48B87#!@A5GJEdHEI4 z6wJXsg&p%Y;u4hC7MFlHT#r+{mpfO8BktQNFEgT4Laj1QajbipSs4VAH7?mHp|FOZ zRwaCg<7k`nsQeQ<{$>Y^{3N8v|rUG6okWqIufQuqdhST7V^D4 zzOv-vn#9|OFm($P8pl|Old|g;y&;a$(lBtBX_%Bwa50WNwk`X50hWC7xo!m-@|cDC z9>MKWl2tHrmRG(FQ|yh(=T0bh2Qv0rOy-PF19d{HBJzUUG9fd`NRoiS(i8+3CqaJZ zxU@-9vSWFh{mOC;&S!XwbZUuqu^wZhu5UQ?q&ts;$&4r^j2fP!JM-a4h9!wBMO=ZTAJVRQxxvSDf-;*Sii1i<%V44_sC{P3 zF;sTTNS9%a!9C%4=^3T~bLP`xufeA2fOBQ${Wvppo`9w3qT0U{4smenS0A%y%*qtp zFYdUgc7N0f^r?SW&p{~2b90N6OHlFaihqV^G|3zCA-^k-n0$Fclb&H>cq9aPWh)kg zrio<3^Qa&Zh6yKF?*?L0Q_*R6r6pdKOxy|+_IwDPRrZXE2L&RJ9~n^8f;rTvv^`Ju z0}r=%V}V^1x0EFNsH>kUiHSFn>Zzp7Dbc+U@I)D4FAvDvt#kmm!=09&zIB zzLyOkiPXH-&S)+d*+WE=lyn$c=Q(&BXYjleIk5ywWDHNIsi&L42UVvFJVYgI8rxaIqF?ImPeJv?3sbgk)?fF zhBLXH!%;{kd}(qd^AjIOQq_-r4A(zR@3#u81F^Aq#WP%Yh}jAL@Tq$!rXjl0Je;qZ(yPlPOfbu5+k zT68a=VaA@#a1qYnPTMR|=!<}Ox0J*X#~AyxLL&=nf-PeNH$8nU$_Yaeu?tX2!8|Ho z2e;|f#1gF9$aHDRx{K;`jrSjw_}hXDVi^kS6y(-MTzc5LDN%AulG=To&F&%$C%ge_ z%65VKivsXeE*Zu0T>wdCamv$eG2|F^eYl>ZhUrys3QW~hdABv;HuJ6TUc7=0& zxIN9L-l{~>@2U#H)?5WQjj#%1yO=}K0UDPw;;~!LCxC2|aI}|YS}ZP`*vNxtuqzKG zxmfa*aKigylkNbk{YlaZJdFiUi}9?S-V|>ieaLptX}r5sZ69!-xT#SxDMg(YjzY;Z z>6MYxQ>vACT@#i-Ht#BllS+uBGt&5sur^9!&j|PJPWvv#(>lz49l~Xkzq`g`=b?T#QZ^7*GM3I9<0FU{t7gk z)ifO(w}Cf3^Mi9|R6mtj>%g3bL(&qQDpI}c%^2a^2(f3kN>v7KQ|M^6Z&|+Hr}@a9_3hnxFD!O2W8 zx4ZxJSg`yf%8Kd6sniCl#2!xeXiO^zGiS)oLgAKLz7-0V?EVo7Y%D@lP^rd-`_5gp zbghPB0huRQBt8}ru$Rlkz4{tXK0Kt~kl^w0*nh~f7R&C4w_>pDB8W;@t4O1;Gd|KB z5?MwN@fl9w)75*wi^t{V`n6#OcO#hJr>4W5bw9v2d6tp+vru@&e8Q{8B>U*PBCCd( zyvdvm3%qch#(op?W0ts?Jv&bW1kX9hsukBcTnlB9yr$7tC_|kLbiNETQ?pFz1DNZ7$?s{|K)` z&!?`9*bxbXjFw5t*{R|sB&J{2>=d37#BezK8nF&J2+=>!`qd>+L8hcMg6LA6&<4Ywh+(mdqSf(5 z*V)wS;4y0*Bj&!o!A4raOo3xw8sS$XDCjHWI`z^F4Z>0tTNPF_uEaG1!hT1Eo2;1FiT=0FVq!D zhmCn8G|RbF_5TvPh)D6XOF^a;&}G;v6Yw^g8|bGfCYZxGn`Fm8$YJ-j$VQ`8 zjt1DF;&|oRsOiqj$hz~hAY~SDS1htNBsLY5X=SpY&eYL_5uXU#dOf$up0YHioP6Yx z1qCw8Mo&F*PJiwmxfF7JoPv<}=!$~t(DjuSF`SAA=0fCJq z47Nqdh;j3`B_t0dRasR-&bY3E<#$+L*q?Sy!2&tt z`2!7ZnHBg23l^j+-LL^cs2$E@pdb2TaAa}Ds4(!xa5rGYP$Z0FQcRxHj-1$){}5}7(x#HaYBp<>(ska8tek4Mm+<}y}R5|9lB5Nv19vs!-G zfsxEra^S^0#-}6|qMzH_HG@T~I56dqSC*YZVpV_GH>Dtxd}nMa65fygDej0D6N=k! zyEv0)hMQ2Bp}gjkUXEq$fnoYGyX5w-ObQjxU0kJvlTF=G5RBJ#*UBboSICCu-pq#s zsqyhLG9}5lse3X(Q_{lMz|Q!inO3yNG=FcQ44aDa@XVGj2NQt(<{f*58_L;5@i!V%-q2C1a6~lJxQ8*Q#3Obuoi8DAY!MLX>eQBe45>5^1K$O&C{nn z-jK8!SG2fEhSkpu=ZUecQ&dQtrhuFc-K~br@?e7ES}WVguz+7DHV~R4+NobNVUmLN z2dd3}njIvg<)mF3;_Xam_|r^Yg5I&GGyA!5r@C#tsT{Frh-J1S zzFGq2vF(-Os`h|8r}-u`ZUe+U)I2HJAfbwSt9YeyG~$|z`l?!{ zbkH3huQyZv#t2EZ8*vZ$@Og7`s*vQ(S~NC$W!hIu)^4;lMz)!xXTPy98e=56H0`fJ zV^;SI^De?yiaN!?+wEoATvEjCI?_zDPvIpnuTm}z9rsrmAE`rceAU#g?9B}|sgYA| zzBCuku=qyzB7c3-#NTG3iA>yiaWMx9oSP7-;=}{gdw6uOJ8r+iCKsL^Y-ne8-2(S3 zynMEM8{%&^Qd2};+|b0;Yk(eHF@~#2QW2+FARh^SC@VD6VX<0sc67BPUex%x^1T{g ztc75bC5lm;j~Z$ci-vOWwF8e%dupR0hSG&&T-?d=7hWpZ+r$G&(<)1(l#x~BVulZR zO@325@PsdU_hN(WrE%wMgy&;-p(q-Ljn4H1n& z@~t^;L~2UID_#?4#eT6Zhx7KaH_@00>^7ma%q>BmQz9&&G}_BvDz3PgLqH8#_IA#S zO;5F0XKb4LdK=PF@!&3l{5M))@H05;>FIBCl_U{XZD>ifrfIg=hm`L9t;LIDtS(<1 zZ$$wM*<0M<6_ar0F;-Di8J1TBxUe|sKz}R&1=0LRZS)9QfBjY zGR?8unT*Yz-TH>4Ys>~}vN#9TbQQDTT0;7>R?8@d4{LC=>9FvygC&yX6fkHf=@ib( z@`1}9IQAgkdXr_0cooth$A!<;qN?H)cRjkoN0hS07uhy(Y#{sw z-n*rH5w0bmh=mHJ~qrQnQn<|t5^(g#2U|7J5+kef+`YR!Y zX9he>*`oEfz6c2)o(?YJG>0SvBCZ6UuQYA{RbVG=Jm7vCUA1>lUa-czlEiuY0uqo|+gc4qRTq(yO=_)6%!4nK-LX@B^t2(sRQ7#h9fqe8KlY~w2 zMmINLm(^~fnr0|@h^xp-1WGbG&gh881Hvu^kC!g{>UiH{#PdtLSLuR^@8M6Fm0ojj z_v|~mQuhg+!D%8#ib;IZ9~_0>uydroiIg$NFRC>GH_JM7njQ?$bYEm2WVEeN86@OQ z51>3S$E@lZn%q@t9l@?%jiKm0Oca5Qb+^C?5^TkNc6e+wxMAkNAMdk19-pf?(Dh?jQBc^V`~YJZ4jV;vnZfcEN6>_ zNB3#ZBk#0js-lYGZVlZoxtV#5`GoK>832U4C;R?%K$yrhmZ z@V10(VpDWsxTVT7_AzGAyLg(b1cygm0>tG%y^A|-7VGb7ex@^x~-Y zQiW3K?2micxu~y)qq#g~4w^Ws&8~P9XVYD_wrUD&6%KLgou0?&XpIS#>f9#Oh2fAS zAPUQm2C;Z3E=TQq*Qq>XaJLv@R6u?7anw@e&K+eJo&gZh_hLL8X}J>9H+@P9ImX~f z57@!mCI-X7#VOajWPs)neIo)pfi?qGa#T^G&9n?uZ1q5U`Ie4=tBSDPD^V(XJEe*! z_Dt?;IoOUK<8?mV@NF~V%YFA5`7MY$c;C1; zL%vsF+g#x+97@|vnN*@_ic4ikVxXbiioChXk_4LC49OoozNH#a5mqZB6=6j+pkkb^ zpavd2zO@=qDXgppRGg;%JwdUqs0I|*=8p8}aZ{Bt<(1U{gluk84X7Bar~yshTxChWZfY|ifAHj%)_{)CT$)J= ztEmB<#0qKvUgNntfLpp#fZ4S@W%YCxy3sv6L78r1-ZS5pI;Yhy1-w|9`Xu(^`x#8VOeRHh-;*%T*WX|UK69udEL%3_u3zhcjvfarY>>Rk1KR65G|SS#HF)L7siyr^Rtzb7pAL`F3EY6qj*s` znexYiF0Vm6q=Rxg>0*hQEsxgzN_oO1y`%0F&3-jgk%hsV8mfdo0nFyJ_IM zQaAPFt9Mf$#VCU2ZpvkmW!==^SL&v)*qgekBU!ndMiH7CVnkfi41G5RvA0~7S2E{C z_1#nwUA3F)M3*#Hrnus0D#>G@X&y}jWm7i|lv3i$x@jP7?52TqNzTzt16^Y`4W!F! z5ThwbSM8>X>nhzekgwcLLzES}DIzTGrWU_aH-$yr)J+}9%H1@I(9}&M;-+p2;#IpT zNb9?)B)V!h)rl@?teh#W*i9w*mAYx5Z0e?gvay>6(#CEYNSEXs-89fOcGE!G*iAvY zYByC}SLvpKeC2K$qO90W5n*XJwfM$v%7(RL&+60|&`}MVROH-p*Rnh&am&b6y?%LeSpLGb zDHRjc<KS+%Q(be647s|uWx+TjHE5wB3>cweQ$QK3Q>#ow>Frmji2C>oxP z>V$WNW5aURX1rL+*Sc5TnsxR1_;PV%P+FxJb?IDIxG7d7bAfBPA3xNNd48>>f?6f8 zeG1p*IXuZ%s9qKAWyWV&ZW##&JsAz|Xt#`5GfFPc85?eJn_E^K7xU30JYWpyw@BW9*=092EY6CQ&%1pXwPXCnwkO2_%%{2 zpY9$~#l!bb%tq!B!LWFtoY}0iE~Z%BRUEnB|Mb(6e5s`uw*57c~`C4p<5n9ZNo_6D%bqGwzTO`DYaoAYt#Ag zecHARd5sS@ekk|o8ZNAlno>&>T%|_RILoR#rLAv4DW%T(pPziKE^B4aNi(z((f{jm z{r|uW;Z>CLyPRCKpN;bF32y4B9G4<_iBXaR6}6M$yiUknflp>!fka6K3iS1GacBUuP)sD8^=QKi zc=N`6;s`3t4fiET%zfUxdGmJQfFR*?NZ2txER@%;1A0Iodkp|ReE}kR#m>;jfb-Go zR}shaX$*kOkm0o!O9X-JuU|*J`oj+)cZ2qL^o5fIa@kveehd#)6%IVWP3kzdfr|&a zqc=SHXaxuP)8PmA#d|1Gld=}b8nvyCi1|^_V}MhB94qlj*!W0=9upX{ z!2lt@R32M|X+01OWf8~ag()!v z>LUj9bVDQ)R3v(r?$)Q>V%Up%66t!QtgG6kL=8s}d;z@2i)u5Z+KsxbhepcFLxYIO z5^lxw+^m2B;G^(1dr!uf;{69MgnX$hNwR}!VxaI$A}G@;G#QSQM~sBvT+OMnSqRP+qO zh3y->qK1>1cMCgc8}3*Sme08E|L(B+{OTql>mOo zAGCpf^ICmV1i)T&@nmEv9(K=%s(B1>4>t}Kp5Ttb5-F~2oKFib^+e)rC=i$r0R(o?A21#Q2-i4uIl{*i?a^q6 z>kWE%PvQd4vz)_O%xBK(VGKd0-PvWK%tgTo#bIy%>}8JQVa6e>6qUL)jmA>h#xpWi z@FT3~mk=mCj=VT1IK-7|b!a{_Sk3a$<7xypRI3r#nJFP~!##c8a92Y20#{6#-zKU_ z@a;*9<^=}ARNN$u{lb-NO85m&44<9h($pp%U7=#}eWTmUPjRzoQw)w8X?lrZXk4pu z>&pr1RjFZIC7x}*u_YoH%GCA6Q=_zT4N1{4Z(jCH>rBt}dTLd(6imH>?E&kc$M^QdMn4MZ}H`l z`oB*#tX6ur$y=>}|G z1j{j&626zQn?>%Q?}eAYq886^O8Akdxj+%ZUPD?=RGS=7LQ_Oev+fq zNUb5m-1~XvZ$had0x#aKC-<5(X9W{OuIkn&Wt#`hi=FzWj3cX$g9A^{OA1=9*XFzJQTpv$XrN=@BDDcpx%7&y}R>;=mavjw1*tBt%Ov7{<)fOItiows~J&LUMTe zZJYty??YF}4ZUuyrXq=yG~r~#!1=BFn@`H32o~>(@%FG*cxmiMxx8GFmf4EtJhLw` zDoEgQfkK8efL&dRNwB!;@KyYG4vs3LiI}+7ZF}6uG#{s1Xxlx? zMjl0si)C2Y3?%78JwDCOx-c+bcSrNICt)Xq&j&7{;D!6q(hl0N0G=Zb~!Dw0?9 z9m%3uB90Wb)PbNg==UNa!SesBG1gnB1s+P~ZPalZr?8y%kY=D!-IDAUct;=s3_VL57T$? zUSZ#+YTij~AThK_@k3!eerUN=R9}RyWWZhCN=<97*mt1O~Yd5lCC zRiX^zN)%=arf=70xkOT#?R@CUzM|9=vNAHu%e#l*E_1n{J=FsSy9)Pb@NZed!d{mNTel)#J9+=A0=#TAU~$xGbW>C{ z0|k){LpZg^WJx0?i>e{aTDrA*H{O(jl}Y=+FOA2Q8g=!gY}Pl>ezfsbJrIB_*k5%d zX;JuHs#qL66B<-Lc!};Wi51bHFIEyb&AyaNAgW@+3L0bHKzkMMeAP&kP*pL~TE3P~ zOjN}tX!}|wnxu+_R=TxJVxlTGsUoXoRVJ)r7nE8pBTYgUHSJlB-Y9dUh78R<*qok5 zykg@9DPNczz%!tqPwz&rCfF&I`C*%cClz`Onv8k>dAsxSK5e=TTXJ7DKDw?}m|>rngR%FI0=rW_Gih%rb{!EGOz}(Lz!ARB4lZWtovWeA-q^n`RE3 zg5aF7T7gIDwpP@m1sR zI2-LN=j5wJ9AB|Gzgk>Gvk4n!&GDLESnB)NEh5-&6XXucQ)La4XBYGart`y1|Ael^WK&R_$CqY8MVAw~hoy zkP)AI!TP;fHvd&~uyfm6^MUxVD6sl;gt2t^@fM?kF9Gwo={bsW<$`dQ0vpL!N?y!- zYlGkzMA7A8E_V(Gb`-8z^LqgXk413wfeOTHtcIN#73CN@7qCiyts`t!y47O8hsi5H z%0TUDB|^%o5J%rGR&|4SlfkJ)aw9UgMLknPqmwa^QX1#jMmWil*ElNHnUKvFIL_Jg zCxdM=U}2h1J2-}U=J63a8v|n0#PFCnb!Md|hR38aHtW(rK~+gr)h1Gp5^?gWaN051 z#aRNZ3gK+67|})ahKk9#DaDujos+%Y3N)4wxffS~F|~pn#0s2mxY6#th!nMI?N%Y! z5V5?gUyfcw6PTD>$JG!CP(=`;|DV*od7NZPRWE+;&8(%DS($|y7-;tH2C90SVFnPU zy1IL&p*Om^K}Bh^v$Cp^&dMw@t9lv0$0j1+@3xFKsZ2=kTO6Q z-Eli&AcRVQ(wU6u#d#KGlcs!nx=qs58{>cqIIwpdQoS%fY?t2lpmF$N^~y?j9fuQg zS)m+r8`naMr^8q&rMOc%7M!?MKPiZ<7!F=~Y9Dr0VJZ34-pi-bE*{FD>$$WU`1H<` z5OPv8-vWcU&x<9LZ^s7PRfy+!d2|)5{!&Jda3vQxQv;g&3@RE*I8TlX?tGMBy%NUG z6FA4lFUd7d1mL7zf>veg6jm#i5R<74vx>@_Z0wqqhf!F?)Mzt<8t$G2T#c6x-wrX> zWJ0%@Z}kTV?QZFPN~IO)j!w(*B^7-*V-sB=#cNHR1~9~cj=9B`;*PTZI$}oBb>^x% z)Mx-+8>31=1C$GD23m4FajpVcj>^``K-t@mr%@wyNh&==I6zeBzJLHY39G?TE}Mw; zaH6#&=R1{GA=T3_Yz^s`S3OfT2|XJ2xE5+}qq?~Pr?j-z;k`a(1FyzYz(X2Tuk5@ET^77zp(e>-aAb}OcL7(dF^*OWOe`$GeCz@*ttvE z>Bmfcq0D-G1+86Zk61XPuH=$QJq|EeXLZy%wXmQv+mvW@3k&v3khid)d@Tt3#9}_T zB`}`D!kDWlU6{M#zz!F$ViD5LRP?GrNN~g!tX}I5i9zw1CKY>oVq}yElGt$Unm(% z$r$E_k}=f{CClf?M~dasMDB|KcvGxGF22m2_UM|ZxWR03kgD*m10WxLPcD!wE;a>0 z&J2{lrUo{8a|&SdgW+&v4Fe0N*4{uhPszAD5DSkl*uX82h_92CD6B2bdLVU3oeP36 z*3K%%HAqn?$qsMRh^61S@Q|a!nrj7ICSgXcNG~pe%519XVlvPLG}!;;G6@Yd93m(> z#j(~|#TkF=$G9&p_Yylu2NydFYcM27SlPpHJ~B7C!r*9Qmbu2iPr%KKH+zJNr(KZ=ZSiG-4mAl$f^2!)&7$GObo(y)UWv+oO?D`_*Z z>Ck?=PXh)=*i_Jsn&fPW-jY<;g2eYe-cRE%D-=Olo znDu;8-rBJ6Ww`@31o2o#LS{fX37Pf41j{(c6Jj@cKBXWL`Q+U2pHH%e@q9u$$U|^) zw>alc&eSJd=4*DILFzIu!G8YI?0O+5bH(J?&wuH?|Nu^D9FDH54x@5Zq z38CENoG^L}(7ia2g4f{>4*+b?yXc^{}ddAE`1g0Jo7X zhzTAjq7A0ERQeH~lA`%gC_v-LI|qtTYq+Rf3LA;<;qdV=!UE{nxK)O1K~Bg)ryO+{ zQjj0LC9ONkLN)D*+Pf3%_kxQ?My?jBgrmiGvNfWR9|lf$vAdowC}vb1zKqr#brFhM z$dq~pOcIvXR%X6g92n+Rh6v-&*->k`lOasCpG0h@Q7tn#*QZd{L7smil8*CRAY>U9 z8x&sc!&sD9m^)F#fS3ME!YVt})5ZdW?8Qph#dk6QO4iAvhl*rS$gyjt4GRZX>U7)P zPM|JnyLxL~D?VUW7>lqK1j(cKGYmFc#L8NR!s9E%!-wujB<1L-<2dy=UpXAzhO<*s z7S{}d%aOPa2AZ=l^2pg=EY9T;Pn9K(uE6SDJv|t#7@e^OE=g^bf}9JZj9sS?nQVJDk@wPU|+5V+rcCL5U2TmWE-*-1|YsBGD=P?&j^J#Pn znRVwVhj$Vh2ot&voUo(LvDW!cFF)qVsV;{B#n2#hJ1VRk3IRBK`e<45At@#R;V@bZ z1g9703UuIgFD?T?+l_$`-i%;N`^)xp7Y8u!w3U`p5X$ms``V_}V;{M4v_HQBrkB<4 zJR`;gD&KYv5f+$-V!a(?a0DBtSBgbSUow3rQg${EAnUGbuZ%79N@ylElO%yu~XpS{GI>oscPR68yQ587=5kILu7C+4hnS)3p zrRI9e?9wZ%##dysAhjn-p(tx6@G1r5a65N2n@`EWmrfvZv><=6Am4CJO}8kgS@=?q z_D4Ktt&@@vQbAc4eqncjqcCAgg+LwQo0nb5rmiF+R}qF{OZZu?I>);sB}(FRwArhs z5hha(Rgs}HSTJ9h!+MB@qi=C#X6_=CTJA7yy&mQ1tY`Z;oNloP7NWtqN}p=`ya&hX z+3Cok6_o07j_vF)DG!>iWK?6_pW{F&)&n_EVeipXS-a*^WghHKrGy&O_oVeR*RtJ2 z-jUA_8W^>6v>=+nG7FIKTx(UU3NTQv<5AM=&sEtE;;phD)E)2ZLV3n~o*C%t zzkZZiQ|G&|A37}f2Hq@akZ9EpAy15yF|fLf_z!g-F5YM&8Xg8LTMEOs*SO-b0k!O zv*YDkmHTnVDheAkM+n4%!*{G~Xg=($A1@D!f}e5RqBi8b^BTffYzF%ppwfLU#jJ48 zO62nRRm8&FxK$iU)LD5h)732bc3-M=G-qQN1Cud;U>qqcwa9MTMw@A$3cXz5jIX0mvNpqIne3Dhy>el3X$JE?xstI8 z4)!U)b$nzMusWd6*m~=|(M+ocf2!kF$lj|-mo^Rg8b%GaQQeOzDwfkObkd2Ejgm9$ z&f;;nwXtrYeS$l8AKX}4VjO2KR*xuYvLjf8Gi6TJQT;J9q)z``?5 z_``|woTJQQy?GT!wadBecOA%W$YA9?`SO#10#N5-7gu`9{0B;@wYCe#uk~;elU=JE zR#@4j+)i)HMBwy%I+tfD>g9e!X%s={@-JaaE!;nsZn|M^^$OvCc4ltW;RehT1I*Os z4$mF3#xqO&JYYCWlIub1l9S}jVx=T+BgFM)L z-+a0Ps~Uu=*m_A`XP{?}E$mHwHzsLb8`oG;6T7)glNK~0HE)hf?e&!xVU+;UPOu@Y z(_dK{ASq-n@;eBBa7{IfNdG zHA6?Uq6Jm52&*54p@FSF$jEt1ax8H{icEl3bkHzd0cU;X8>0Z!S;fHD8m8e3s#drq zWJ!@e>a6457u+$?UO>cNw!g!LD^qq@o2D6a3X?|0OXX^om82sA?c^cd31`!@YH?^W zE>~77@(7A%1@o8exFikfy*-4(I0=QtRimWOf{CF3I4xpg$%T^yNuc=%J|!#H3{y3+n`Up3j`s8(JLa zzA5J!V+QhYrVi`FDv{zW?;GOcA&bGLqm2+@ zG)IFp%z+f7G=D%}qC4^mq}COQF~AT7yU;U|C^m>v^OYh8KG+G%y}|jJaFK#Y@iI^^ z83VWl%EoG#QpjFWQfi$0n$N1516P3+ra~$>6^M(VVchI5DIvbv6ChlkYP^E^ydN9B zk0FetXjn5vAAN~A$AWcPxh=h=6s3vaB|~p~R0~~F>vU<&#-AnUEMwE+U^P|%Pb1iS zc>rIaeF!+Q;GpEo=(?D(=sA{Wj-lGwgDBh-3i#Auw4T<`%;7v;RY7yvT3tzKfhcQq zVFO+iu{sZ4$s)RJE;uN{lu_CExXkzAT(GHdZJ|Y%VQ-rWxYr63*^1;aa?&m{;1VHl zVFX)lB4sG@LguXXQb@0id2xEhjj{r9f?c*??;x<7$^i-UrJctW(08JTFLdU`0J|Tj z$fP@N(?UfhLRqJ?bHC-P4N!y>;Px)eAUlYqML=DlT?L&bm^lb#8tXxkVryr&GP!~* zrP8&)(lZ&Ccus3=*yHms&54UTVf)>0gvl;901{@sjA?MXpdD>Is)z-ZAZ`bAS{pzL z68^07#BfiCS?jhhpeK7q5M$VM_sFAzW4$}V;TN2M?Lv_BsNI5HWnh*4lF#8s zPl5u?g^6aKr<$V0!I6z#FDS;$-gFsS|aG90?B0mT|24qHg6n`8cj($B{Hg9-e)D7w#2qG0-a=^NYr!ziP~< z$vA^nawiS`Of>4shyj4Jh^l7n?Ww6VH+WqfYyGF609CQB!W_n$s(^QNHRB%=-C?=>2~ zmR6C|(;b-`h?Bq|F#0Y%N(d$vHKIu;(?nGsJ!F)nNs_F&6U7({pF2%VURbAmRW?C+ z=PIpf+T&9_QSAC9O{rv`eHy{l5FIRLIC`U2=72z!Ql1s<_9KZ6$!)o>?g!NZ8y7yrpt4v+fI23w@EUOU3eA%lvnkdZqu^JN6$P%>>2n847C}@- zhAG1%nV#SW&ko}AacM#+UOn<|276)6BV{0MA1El!OV$0Xn?cV-!@YNvI&bOh7P;NC~kj1JU@7y%I?%sTvGmiDI)qyJnn!=g= zwm??ZXU3TYRN!`I0;SO7P<>!5IslzTtL5~PpC<>#g&qrj9DeT~3-dT_Gag3(Jr*V7 zwEK9N&4pgGHQI5{I5gi=zZ={$7T)n#cXxd#Jow{H}5Ersow^ zxAPc^W2~M%Mn@g5pVn`R@%lz>NuwEqg&Uk3gtZ30@tA5x6&zy5rJxQ_6cV{QAC z*Ed&yHh)S-SWkv3$=Wd2P1PQc5$6hD4ysh7HOshc^IU=;4k6~MkhpjH-_Cp9x|I@?ubteZ8+?!}W!hg-wml|!xd zRvD)YZ~=@L%pzMDnHR*@Sb4xefrv85d1X+pb_E(QMNYsf!F`0(%;e62YiDy?v2I33 zFVxNE^y6^00LzQ+>k6jV$lzmp?QAap#>nWl*;rYxs@&obFizP{(~p()YRGnEXPj~i zV?tTxYS9ZT7z?ie)xuS#H1Y`ZkVV1OdS^ac3MOxHhA_cRm6MJ#xV$Ko zL)M1P$w&!KM<9ZbIec&}W{l1Bj<=1|mv&ohb}m!qzco{vG8i-Uz$(q*%WYY$42!U` z+Fa1IKDI#R7{UeQjS`c|;$0E6D2NrfwN!@N$0{R0yJempLRfJXM`UuB0tRp@?~%(q zEnW`mWaY>O4d7kUOVD8=eGopb=HRl@>WQZEDa;&RUCR#h((bLSXXth1FsYU#*svKf zIkU-vMq~xnw`(CTg8GljM?v8nOh!qu)C0_2?yJ`{d%~-1jP*t-1Cky4jzkYJ!wD+SLbn@ zcQC}3@GAUhnnIqUaxg8AT`Kn+N$7Z_)d9Y=rx|)7Z9)|p+5mCp_GnTp=f!=+RbDR0I-C{PPPvP z;c$^lQ$wb8Y)An@4b){2S}`a+GoKAbHpTtHVQKizVpv={7go#o;Yltw*`gzYiYS|s zox2YKhTFgRjW~~Dc(eiNW7CYl=JP9_72M55^?}y2?lrfXN5zU;do>E@0I?ZzyBNF> z_7*%Z00RH){fhZ|$gW!N1}B}O432yzXD<_W7O69at=b`0Q^lGF5@kFxJDU73*H>L|HjI?jy7iqv|vitt$+0Cr|@ zp~I8(hUp7AoD=$60HCpO6xQ+1VzJ|!3=-Y-RP zs5@F4jBsWM!hR)L4)#ow)jRC3!gUh+_U+$$7zY85M6R%Tj>`Omg6NJA5$}-R#%4l< zmC9RPw0fhWr4%vhjg%)*Zwe55&3LWX{hiBa`yGV&W);O<1qx)NpZ?^=C*zzJrr4X7 z7jR;yW|Ir2m6Q-djeyI8r7KfB-)`)gvo>`pgg8Soe zzK*&_!qA6`obIgkaO1@=;+>s1NpUp0gk$m;*S3gl--o2ZQ7zd$G>|0UdlDfi5Sapc)0<@#`50p5hd83n+z#R(8>+KDaYQkMndhgMc*$ z9AVYDqH)<|R~-t0g>bi$E-3Ch!S;Pa32Y0s1KG`X{)(mRm(S zK*XlINfkaVr=fb-G)h-xD5VFd4cFpvlCp)&1DNBWvPbKbEjVlNaRt|*_tHw) z0!8r@x<1y-%lW&Al`}8Zuys!!smje8Wx4j|fwS2t>|Wr3H+2Ayw}vp5%E?~EKqbnq z0**3)Q>I;Xt2j`FO^}XGqUC*mOADBBNoC=V4Ue*ciHhwuO0DY7ca)}c1%>+bg+g_0 z{`tCaMzK>sfDSzjI>0{6Mi0xlb8=~krhplCGP^EMFsvI6PbZ*>ixp0FDYl9h_3+N! zx%8sm%mMhcCjry|5kPMe{kT=CA8|o3r-pdG{&JLzT;?pg*+6kpIolq#_wSqOb~@PL z0(r3BsUR-<&8WMIdw0&Njh+_dJWtw%g?RMv;lnw29>_w!#f6T#D%8rOaGe^gZO~dN zCabK)vJ9nKVl0dzE!N+vgskvXxRxL2uF(Y4eJuZe=Wf%F9NCv#S?UlSRL{$-GBv#+ zl+2{2q?sHFUZu}EW!K@D5I57b4n3sWL7EZk3}%v5*p>E}bk4(x4;^HknfnGXy83;& z6w>EC=cImC+^b8N$|$=u2)BWohSB|C`7L&_C7ai+p2q%VZ?K;r_GG9Dj1GrFa85YP zuAY>nrYYmlrdzgN7U5(NRGpJ66(4TE;8&Lq$R=C4IVhMh$AMEr95RN}S#aCdd=EBm zm=|t&sC?H*YOpLf)6U&z=r?D>a!%C6SO|c1epv=M`$>rJApj$7qI`{snio=u?(l8DROMsxSXaeBS7ws;n zN4AAwGuaCqS9LhsAGMZh=mCGLDIA8Jz?P+)KGAr(yo6JxW#K(bzI=|7-A&B ztw;50u&719gT0;0xD>u#u7dPFOlZ&z&*Q+TtD{Br<@#;!G$FSGj%xF-J9=Jgb@0M7 zH5sQXSQA<<455E{bqxm<*36^^dDKMxr=Yx+=m8U-Og-(#LN`Ci zo}+@PO{!{foHDmD?2j`tEe^<$v8iO$=I?u6ny)sUjuKUt05H`?U<>I|cZh2u>o>-{ zSZ|v#Il7~7!9Bt?i?TX|EI=%DmKiHkGq-AyF-g_!p>x$NiEC;4K;e2klni6(F3E8e zi(^=|>y4GO(EH%B63ZR_y)mfGm#y6&_3|ql?FAb+hoxqT=@_E2j@J+8TJ+7n{+;~!L^$BCX&n;nms99AjJFY4P zi|Y2KoxA%>ZQH9+v%o^WF@@JDwWcpcoBI8w3!9}mpK)xW^V!FvdW416k-ENpWPC_9 zxgB&t(81PS?6+oc0a&MJuaWtrHHGHXrZzCn8XFFH*L4~Y=%qSE&YQ16j2dyNc*g(_ zJ3Rd80S_yuyZ{NaCCo~p|Lz9jaR?6qaL%4|V zN;w5qYlthF#|-+~x~S4*tPyoRh8`3x7BZF)+)HA zN;}kD#>z`6S*tkSs2oDp4k}o!U}_YH;UB8X9&AeVZ_4IkuCUroGfCShD}#NN!A+%{ zz~rv3cDBl}g9J;_XWF@nj11DOr6}-fr@nd-dVKThRr!y2znrI{yh!rX> zpB*7yt0!Ny5Uh;@&FC|ANLW4e-BEqyJzm5bw$RvId1_8+1;Tp}PccfTE=}cy$S{0n zP!5!*q;yy(=)T#NwO0EAmlb6>xQp;nHayVDAd zaCk~@Q8JI6wbL55SJZ-ZJvJ7bu!lf`dU;cd7o_nHSq)m7wN}0TSdMj9Yl@U=B?vKZ zudY>vj)VttV5RL*D~l>bw`}c#RIdBk%PIyVyMyVF7sX}-U@Wh%)S{98Ao~C6*xq(| z`U-fd+_-sFWPo%-6Y^b0h|pR>ZEcmKq2fuPXzMyv zbPHBD8r930*0xno?_l$S*nn_5Q-}SG zMNu%j7dv_q&tS{ zG^UnNGg#J{-DC==FkYJMX=GX*5-ifQ%{_H8uC=;DS|Dnos>)4sB z_sW|*#64OUJ5thNv)#voC9STEiWra8=vXYS0I0^^BA^~AFEf_XQ=oK~RPc(~bKLjj zmsK5E43N4hva!zvTMn>+)stc8Zf_QKrePqDH;1}suSjvQ0GV7A;r+)ZhGysaJ%OdpC^Zw!0TPN?Lr z89Hm=l~8KIdSB0hqZm#PO-=WV&Y%=dkj3Kiu{_PSy*~;)j7)64Z?9lRfX`qllo*>$ z-NoT1vUL&qGx8%_4X1HjTh}*%+;Wf=xS& zol`f(*!e8}n7rw*QnSAB_2Mp`bj-l69^Pp*)T+cNDReruotiOHxHiu7ULy2)AcUQW zy$x&Fu#1Jlc|^z~s@zUA7#A^cVW`gr_(B=_jFw$9ZC<5yaIlzdo)%agrI1pkOqH4Y zu!_WYT00<=nX3T1X3pZ5t2)xeQ-~A2gplow((|oRx6MuN*(+TD++gyKOKa%C>w}r& zM~@%261fL>uqI}LQef=5Gradmh2qlFj=bqzooNj&^aq#vrx~`3)e&BCdlXw@vhv}A z)jXMJ0K1jK%@}f93R$iWL`adkxrA*8!dNAJe^olp6e}-bUq!l=zty|c!ciKn9&S=g zk)rv;#dUHmdzZ=M;=uP-_N<@AruQLk8p{9>JuPnzc2-&!y929DEWY79>}4$CEo(Pk zN(VuVIC})qCP_GF)w_^p)j3P!hCC%aBLvNHxiMFE+N{BzR6r2u7`T^PP#pVy)Pr(RlsNNsO6>-B}LZcR{4Bk2qmLU$=Ew#yWJ+RmZBF z5!*_Et0^Dp&9ZpsEeJPIIrK!aYpI}%3>~oWi4Q#Gfy}2|{W@x4eFtkaR<5j?Ch_F( zMXg~!d(SrCC*cw9Arv!`qzPB&Po(9;`@nqaFcoN>{;9#Bw~Ojmsd&E1$_PNi_#F>g z;$?ZLi@x-)iX0T+WN~|krVJ-#^yXm&@Wwc7MykRK4>K!RlL`%ebm;^R+Q5QSP3#6f zK(fZFsKx?tC0cGT=BSeaN)sZe2O(xBH^ylSgUTgM5cUUbp{!vk86m-t3`!r!wO`Dc z(PujuQ>JAvEoGa%w8pONr8VGXFYn9>5;7nx+|sRfZOJU#0l>DNAb^ph6hTofN+Ada z(j~wl!_5(#Hy&Y#u2Z51AqJ<6B2RjLE)DywP$IVXsd7#Z=Wq^QJ3}X+7;@(kqGDEv zQkF|11zug@X)iwIVW1N`t<`XP8#uzLYopG_;y|h6Fx27(j+9}T)TvtFE0B2Dwp;|K zk`3dv07ZX?A&>ClwKLXz?s+CivK~~_m&0Zoz#T<|)i%JTA)H}{I_EbmgI%|*1;(X) z88E;Xr!)ga*!lgosm&uFTm`8ADNpRQ|I3P6=W}3M$!om%#}h8RMw~1R_h+NR}uV za{nohq!MM}04i#Ft>qC0cRUFnji<6{xgzAe~^G(&3$ZN z#Q8kShx-_m`!jl%x?3>^4`#6)oVR7rxzJKE_|hD8Q_gjL5TnnWZ{7 zvh){Wt#xooEq3~VM%e(7p?4}F%(4*`AeD3}A%#~^G`yVUf+E!}l9az1w=V~dJS%o0 zVU!J>6)v@8AFU7wpIxoK%}mm;@zDyM@Qe<8Rn+4QiSl$2wz?wNP4cHpB(0K zWKChp@->6h^7O(Pr7au?Uvs3ePK5*!ECVQw4Y@?#kE;MtuhoLt+@|x9Y-i4>){v*L zN$nIYukJ{V8};Z3<#Nff8X+sEK*RCQddrqHtu2*VV|8FnauHlXifQBDL1=n`Srb*I zsVE?vC@A(*fh;3_lysKqZ&3qG8iQx5k)E(Tj zk|$F_OR#%zb1jgUES-MPw9&c$X=A(jI|=1c*Dp1D+=zs#3c0 zrIs=PbOoqFN@-5nvhGTjB9%#QUSZ0TGUHWGI^2_U^t0jxq%F%>8^cc8huzKyYg4wD zvODvr)oKJ@T08|QI9%A0Rx3o3hAcL_a-Av*Y}ZWdJamxyBg3hCSP;^swhBHVH9`Ce zzJ4is8H%d{{_f%_$<0%%G!a|mWJ$FuRm|X)Bkea@#|B|;z!LI@PE?TcRrCik!xsmz z^i_RiX(|c26;i2$C(tbFWlbx^wXnb_^MN@N?7-KmnDYomA1uLTd`VVXvYaL8PhwM8 z2^o-ManqNCE0`@9@5jxJktc3Ld$ zgD=Mx0F_(G_G1KKS)pKYy)qZOBO0mC?{wDYdbkwA(kI1&L0~dB1=Co-gs_x%;CtHy`*wbQcaono`tAnDII?i_Iln7gDu%{D) za$vn%rK*ICr&#P}WI$QV=GwsR@R}z!!j(>|2jh=Et1`6QNoZQjt(1+<-hp&9bf z0c~!xqEJE&s<4XBi*IUDRe-Kh0=qHR8rMUnnO%eR!Qd#sYt&W7Ew3)L@ug5T=!9X_ z?nuwcqZRdndn?YuDTa$hA>xv5U1NZt1*oZAGbgwz?$OQ#ijFR^mZf4Xl*47~9~lZ5 z0eK8DfO#LN8e%XlYb|u(k3th5fCiDoJXb00o(hOPo3tw}<0i`@xa?3pGU!ChFti|s?q#GQ>4AVq3=`auVaQ~yGO+Bur3F;f_a=6 ztA+uW?b)lRerah!nPn|k!WQjiTNv_q_ZOO_EjEO)tryLOUlnkd=MuokSL&0y3^g81}s9GLp&*=(~fAc^@5YJVq=#t;+6-zP=vUPQ7B>6+Cw zaMq%x-Rrda8*4&KNC?!VRkUY#s&4bKbqS4fa;<~o#s=%qUP>fubZ}v2y(-&$&&Nr6 zIkd#3y@fXPWP3$FqI$K*P0V zIP<>LWt(}7U2n5^dp%kN%hFbNleL0Ejf2Fyt?p0 z^tTDjgVqpB;9SIU>bVG9VWy4M0J-=CP)#+;oFwgZvd@VqOJl&dDB`T%f~z~iwHzmh zCm03YTJ+nCCD??%q7+r-u;j?o=56?OgdEY94oyNe-bqB&2vMn+G|B~BX{XES4>otk z17AF!&Gx((rUVfrUWuDST}c*{?Y3qKG-BY}FoOKrOGa;rZi7iI21R~7TjSN4g^RL3 zltEugYubjwb?L!3l_DUA-a#I8$!-?3&Q6*LrKjzEr6>Vqjial zu=-2|2A9YZaIv|v5;Y%`J$7)|XoH(cpzmj+CgP;TcNpKK@vhS*ci3hbIs$M#(_d5?{5 zL>C}XydTWof>bRO-tzf!vr@*q<2O>8%hHh^W{54RxGD_JSSuQ`Kj1WvD!4Oro!~_P z!Z`>K_A~8M46%m%sfKO;-E(zoWe>mj0c)M0NnSG615SgtTDQ8c{Bmt15Q z_|avY9tRGgbY4CcT!L*QJjOnn3r$$f+!9rTqYQMDWAP+#LwwRh`reTT|yRR1}C>9rCq#;aHD@| z*jmfc3k$Wy=mrs?jF|H%l^c35brxljk)0z;-MM?CKiXL1K#0(Y!!j6q0=^BArk}{( z9#fWtXE{@fLI!Ui!6@#ov}le(1qhLuO^{guw1=}AC^2#MdzYS8uFPbBC``XAHUgPc z9L=(~p&VqnyJ9=);I85}_7C-!4-GaD6gYqS*pZA3C>$wFw^p7;oSU)Sfv>43uPT#M zO@m8byEHO~qRmlx>BcP2LYKO-eU5>KoExyco!mp9=G+W9*r7p};Q}SN%eZq1n<@{Yp|b?u`y_gxeE|~4w4z`aAsoRP zdJ&^CBM=O08=+pR-}xhZt=U9(MAM{oC3i+-o@<5;6-;o!TzSuN43dF!kaWA*%&}Sv z0fytjxFvS_7nKO{Bx_4<>@t+?s0L@~Uk^pvyi_1^h0f(G`QxS5%`Ai6k@C90fJGG; zH*;1-f~@#b;48X>a!eR zDc(iQoa}ZnqO@xUVuHi9uvs8CMEKH+1!Pc4i}^~>qAXsrg18z48fdN4xe$cGVFw6R zb1Xcof!i{`a&&dJQ&=#V5VCvObW(URmK(*_%58MXwYAPHY_MjA|iiH*%(khygLLNaK1c*auF9CcC)y9*Dk}^ZYIT(xd<;Hw8QLcsCJQodb zK$NrB#*?i`M+hj?e1<_bcN`%a;ZzZQ2yD?jGx^C{EGm_%qeN-3-+OZ%ABxN3HB=F4UU|Y;J`qS7s?`|XfWpz)9p*f!Q(b{4jQ)x z4&B(U9Dq{bwrgnTZZCibxsj&mFJV=c;G;TgTKUbg&SW&R5fXA}UAEZ3RC*m8;?43_J(VX&Oy^@5$EodCy*YnpXO2lm{39Kn9A<#0=} zf`)l^bDDQJsmxio$)Ma6lP80Kx0Z@Sl#EPc*Ega^G1ysbxp;xH( zxDu^2v*E>>(AcTP6C?Whh~r%KJU$ZbHqCi(;87Zyqjl`srQ@Y|Aqw7nhudjkQumU+ zY8*F39{GtExNvX9Q79KGv^;FG{C?3~L6TZQjKH`Z9O_#gJp$+J&}JNUAi}Q~y373* z&PZh!EJ?;dyttH`1$goo>2rXjdzX|V=|wDdfRIb4o#vpYHG!3@(F%5WXpvQ2vLL@< z$f7I3Nr^1a!ONR-(SZZHzgux1 zg5MgQsfzXiQo;a3r2$eL#Ri3uU1+K9a1U0I)ejJ%OR8;m~-&5-f3eo zFvU0msR?LgJbSSmi&sL8KC-b;h+?OJ6bUIH2~d$kQU@k@a&Ed2AVhBp5TG_q_e@2l zIw?SrXPWO8gpW=QrMv0TLqR+mqL?mpsD@PsYKAIn!vyMUgM_MV!xX8}^~nSIDlTMG z8QY*C(p|U!`7W47SAMdno5|n~BDqD-1rbMg?r;7eyPG((D6|%+L}7N%egQV9h%D`co4Y)m)B+Hbl-YVK1q`zQwt@e8&ZG( z&1rf_p``#pZDv6P>9h}44v}iZ1gNz^LIm3|L7MYGL9z=*S%~%mV4wm8xKJ$$fWfMG zAcOTWc5|tjk^>6VBL@?zLk=iNzXKJdJ#R*b8X^xBpgs>2B0momq~8S#Rsc$vZo2Fo z=};XCfPrch;6gPi00t}LfehBiJuW&_9TzT88y75885b^Cmm;9ADq1Z&(-hB|lOCm= z(-A}Ck2Q4)fxwAZ+AKh(=tB7NFkUp)Hn|X%9EcZ5r?8n0{x#!K zEKptwjUl{{LD@n1t!ZTiSWXOjDbSIVpP#bP!ZA{Y=Qyk9~r#&1r2`=Bv zd-0Um+o^_G=rr?)NmD$X(+A}dL9p6{llwiM%6nQ&^MqGwpyk0c!I5&Ok8-X8QZ{Ln z!;XX2Fsm+R18=pu8{O&A0ah<8M6r2zTn_F=z2*G#%1x#?0FPx(JS}gy0h8}cG=~rm zc_nUOSwwPo!m1cc2dE&WK15Dg0YnazZ#hT=I3s%JZV!-$t6r!gGc(^Z_JcaEWjn3t zcn-O>J+y>D&lKI|Sj!2x;djjx{P0?rtF7(ODwvpY8_(Jm=p{L>$EUNx&^DW8B(t}j zV`60v2K8aJL6>spD^@`d`ds$bbsG!VrdMKH%D2uqxUC+-19yrm@eaJD>qBANPL6yD zb`&lF8GAn4Ld15rjcApFa(CddL2Hp|MOU=9ei_`0XJ%%;9hdZUhKv#4@$y$j%Y&z{ zb}v7@jnOOJ;W7Kt5iyTuB=B9<3hIIBHHmS6u^2oa_$D$`X5lh*1sMd9>fKcra9>@( zJL>`-s0&!d)3h@C%Q2oDc9*;TIxuI4y>hUlqXitMR|lai{di?!rPE_ync-H9W7xqn zY`3ts>jlNSHn$%1xLFDQ7Lof3NCPJOX}m~Pr_f7fI6)jfu#uTslw?T5|8y0XOepPua)2|RO7`N*);#W zg;Gj$8RR;*v)N{{xpf%$=QnuYSaoT#B}u#M>w+KTwihpIyD!XT8-=TZm8rn_0m4AN zsB={os?+<4Yr-Gru}(E%=W#(bcR1n#>~XT4=B4epwY_dJ0^b>)8sPHG084ZA#trSV z8Cb=9)F>sNp~j%8WN_zh+1&-LW}>}z%{*@*-0nFd!=}8}D z)|Ps!_NJ-V-tCLxQxEitRCH72OhqUclx&XPRqWL1uMZCL(t5+i8ZG9lx<)mB@-)h{_hDCfbv2wEwZ+Ao52n!Q%BYP^(J=D#w!ye?AF3?YwL3uEN+(W)il@{5L~5J zl&deK{Vv*JldMpRwXCy^Mmt&F<6#=t6m>hlHKiV;@28!!ANg{N0x_-fJ^i^dSdo}6PA;84~^ z3Xc17yh5WW(Kyi?OHD%syo%BZX6Saw!Uwt+HN4*_4xu0mW=ILZEDw^(x9f+J7k~ec}0S zMfq9wtDr%;mg+1E@Fs_>zzR|dSgwL1&is`Ny|m*78YRuGDJXYRsA}caVTE5qWyy71 zzvRM|xzxb{XEXWud~c;v*zA0ma{mZ=_ z)lSOgfpJl`v2?ZGxo@ESjVI4jmHX)~WX=4ACVS0{qt5!V!7|+7%f~twJArv}p*Ym8 zq-6@=T^W_sIVRz;DP@@&g{r^l6 zJm>Jd1rPuJwEpJrt#K6nJN|v!9Z_^Qe)sVFD4vJ#Fg;14=!Ykw=zrq-SMhxW-(5V+ z^QB3J_owmq>1|Q;g+>&;YfBV;b!!w|!rwoE?>q7LyYc%WJk0Zw=_tB_e0Ssfj_pzO zPW z>c9D}>fhUdn=rqE@6Y3Dpq{(%Y@br^_u>0E{wB=zC~x_iDEc8yc{P#0>_jHZ(tH7z=W}p87c%Pu#%eo43m(3ECBFX?p3mvOuf1O3+>39% zC(LR5Hu>L%-xu-x0-is^!!+hKu!d&ecXC5kCtrHmyT{eYdmb>assUG4j+-_Ie60Js z^|wj?$c<4ngJ%KH?;wqQdl0`(`iB0!9p8V4bmk|o48AYm{bL@X;3IsqU7myQZ^!cr zJnzQyn|S^j56i!KE{dLo=fCY%dAdvC zJpBE5e81+=QS@VY_&5JucxDuR-<^QJ74Ps|#Pf@Ip8U8ddNInn<(oh=o_#3eyHOVD zB)z2lr}6jg^XMl#qUiOHRrG%GU=+RMso)L1`Hy^g(i5X-3;w@_pX34gLq5D2Y2SNS6m7%v0nqS#d>h#NQT9`Ipih9-e?a-<)j|AT#JltO zHgGMZ@%MK9{RyOf1J4Ka-v;iXyQ64uAj|g$DC_U`qtD~rk0Xt6|8`Flop}t(0S{jb zdY*;)9JxJ;KKQIC`YZ7AlYo6LVBQ9v?L-?ScpinnzmEJLcv2Mo7I?GpG==Lk_eRl& z0QVu}JB0Ut`dp*|jxxhGf5A=AA9z^qG`_Fk;rn;$?~md8Z}Ch+7O2NwfQPV`^|xs! zwwcXS!kB-=MSaOJgkuTE5vEa>QV&v}i@pU-lw+om7LG?higHNLZ{eFXkQV+;*<`!h zWp23zZH0&Fhw#mG{(c#LQyxDCEaUyXYl<1ej8k-|1hun?}JvJ zhwz(q`WJi?A7P(xo5J}M_&$nf1CObri~k{{G2g%9+t9Haa`;=1!WfCCE)JI4Mn2Yo za?G~lyU*h{zkdw4>~?&ee*aN?zfb=rToe6)bg+HcPOKZ>`~DpSPV@ep{{1BD-K+8Y z3)bHTmfw#=XC58yZZ7jg3+Z9n4qTYRfG|NigWpnr&C7T-oz zui!WJ67d;4#OdNPvhq&A@;C8(7{3WidRW%y@VCLs_T;e&X#rpj+-oF=g+Pq>~_oQk^ z>ZBOy99KD(8XYr-^cUeh^#aE)+Dsh7I0iC5$38R8nQ@I{G{--Ce6z>42Y`>`8uP#Z z`H)FGFU3Q-{lmH9>=oVj)3Qf)%(|ir%b0Dh4l4z?@;5KukTY|7@22(ryR4t z6Q?c1?|8gwf4=`X==~pfZU--Z=2$k?FwGu!Ip+GtSbKc^3*@KV{xs^rK1f;n;`3BL z?#-)y!#+b9=2*e8lI8Fp^)B`I7XkO*??InBiocQff8v{VD)kWO6}!Pp+5{hmymG9k z4x%jc@4N9gY2Z+^4S6F>VRaT6!og?RX$ zcdWe(%SO&{tIn4WE!18-) zx3YIWbxQG{`3P@##Ibd5kU1_WLKD|LL%+jcxsawy~LqcsSQ!xy)~P^izQO3p|g0I^+n?_v86J zJX>a9!{d1co?pT94|tw7tLAT{hjf$PF5cNVOj|sN_kV!L#z{KjJ$c;w@VAZM#@$95 z%XkpqpTyG!{g1}OIV8(x9SBbt&ZWp7){%TRba3uL7?+kRIyi4(`F7bX&y-C%ST5(7 zoNKaf>-eS|8h!hN`_+5SN14uloS$-@>dsF|yP2aB&Nolxd*46X=3`w+1MAN*#>gxE z4y2uRpqx?;h>NnrF^O|>+F*P~Kf|l={03-c9XbCin_Jto`{?G}(Up^1@owBUF>Pwv zob%MHq3d19Po5ZjoVVJ2^sYO>4-G@PvgNIVH1dXigR7yz)ycmId}coTdHiNuaZXFU zMmjIzVVkjC*}kO1=n~sU@Nm+^I@0H0bhP1@@eN!}S(FX-UE>F#?3y-UId+{~UXd13xD$;%b?$G>e*5B$N0A8)09KMXVsjQc+B|a8v{bT zb$zU)>9r`&_&MqG?0%D?mpo%%q$|TkN9nLm#u&J zp6x|hr<_suk~i#+)I;nC#-B;KJC5znwq(0fUa7;Wuh~D0 zE)}^z{rF8kC}AlN{QL9xd*^c$y+4O<*4fBGAAb|(d!DP(pM~$Q;T_YBo?$xusjt2l zehNIsmLweO$~;nMl*4>1%i#SC;F-pDr5~4N6CdZP{QeDm)8^%S(}&-McbuPYI|Kme zaq4o;7uXiN@s9Y+{M$EYbM^Z}x2Zg4u5RXU#ADCjKKvM^C)i%p6Qqwm5z=OSA*=`I zNt6R48>Ef6IA{7Pz|%j%yl+2@c>*5hc{aWY!+*s0$AF_h!r$jBXO}D;y2~mWwK7h%W{Z|&%DOR-^^$K;~ea}kp3||OuyznRW@PH;5XCw z{>Sk9OL%_ze%SSRm`*w#IEwn=@2}%|CVrcGvP^ewW&0q0=6R~DyYS7v!E%U`|5ygg zVmU0EJ__-Bp#KmD;rX6^p!egUPl&Wo|C4XKj^+KYhNhR|J@e5oLpbIkpI!r=nQ?+X z7tYbBXIPF+Gy5<3%YMuJ#P!CLkfB?YujRA&&AhKW6-Au?P2u+*d=qZh3)J_^_4nuS z{eO~gko2>j&p55>%DS<>oU78`#rm?|W6E+&K)~Q7xn$P{z=M{?W26xg5m?^<1l_3f7(CbH|62b8P(SR zC-{Kb&Xi61uGtsa-fUymk!{B|WE)c!D9e-qpWoNCn;B0x;|F&6OkXhjlkKA+&p!^? zdJsG&O{9(enes)xGwomS&2-dZ?(=_%aFXA6e>}S}!Yw}oY}lDy9?Xu0?QD~Fdu?MD z&&={5Dnbo6uupEalR>K;UbH|-q%f+HHx0y+E^bfcW`SFB4-w#Q-|hN zTz)yr4?n5c8YH`RW_e|0tG8^vYeFMLuhlyz6k%(- z-?iXzfm!D=D-8sE9Ab?&8Feq0 zmxV36gJA{8Wn5D}7*z04?IA74#50ZWI#2j)Mnzc;(dF42Myd&{9rFD-{!MIWdVgH_xvS_iDNS}B~XZQM*%r^^1eI_f@9K@4!5BSHHs$T4tLa%bRh9#%!eoNwWTv`!UN8+)LJI2of)>g z;{6I0a5%!N64!Et(f~PC9b(j3ts175+q}=af?P)PRtzqy&~g9Av+Z^ioHu~gDQgth(hME8T8kN9h^{BQJ4lU=kD+lwxD+^EQ3); z?mRASrV-BWs1PYgNR4^WX#K(x#{3FgxHTNR+{^2>vA%S7Im9JiNpuc|PdONS3r+iS zD9rGxrx2^1)pl=K3yxbhs{yqrR09sz_h9I+hD%$?H+!z2{+GF!3Yz=MsiB8ACDw24RJC}NqSj_6$CIROR^(%?;d~p z2Gk|aG@501mk&P}#?LkmmZC$ZTMqHE4Q#3}2kEX40@jf!1{a%lVYrv0S*k=sh~brh z&&iaf-7)25q22)_OZp*rvlu|Y^ALk}x@0aHLnNK&GL|4;!x@Ve$#UCm2~6o=Cp46f zbOOOsGnR3)T0o4AoMA?~wh|hl4Nwo46NNOCfobC~J-N6sVAvSAGMH3-Q6guzFpH!cpRz_62qm@>{38!Kn#(3snrWi%u`9k!H9I>%y!_@ z3lwDB{RT8RM5jnOyO~`IRLq4sS2AoAV2L@%+5&V~k_(_Ep3xMRa}Ay}Ax*;%Kf?y2 z*~M9XB&qm|o%mV=~-6%GtuBwnwus z?JN!-=)8264mx-y+MU_{l~rhk(dsM?0(iO{*@E>=&q>tg0LWRnVixY4wIJVVc47)6 zx6S+8RzncZ50LgSZNlQ*O{}Aixke}}c;$H%A=J4cqfEKiSe^PnC)-L+X9 zt+I3ur_=|8AOjR|KQ_!ycmfU&X63gZD0DaLVjr5hKY|yB_k+*sZ$FN-iX*sNd!40T zcXgV2t~Z?AUBjt{JWf6gvff@R2iRDw0)UBEjso=v6A)hfWA(d% znUhK@FE*`x**KITs)Fial`=GuBNmm8WuwpvEP?P;K**3=GHz%r%K^iY$-Esr%y6bw z;MYP?#StwUm0(&xs^D<1^RUb>%&JLO3cHmE!oCc{VSO-*pogH|%|n)H-#lcBT^O7n z8WG*Ic42vTb+8DPXPqy`JojGQGXr_SR`y&p`*)M-vQ7z$Enhs)zuxc$Ien6Vs z#*W?uLB=O=zPs3kO)yYB?rIUKIosa-GpO@sSvBgkH-;T}G+_d7^s*lhH$JwDrm`@Y zb^7oGLQ{i^KHO&d%ij<#?8R2P#&{L%#HqWh7^7A>tKdoZo2|WRXTe7SOlO~0OI)|V zwxJZxRbw(9uB%1FO5$b#z0QBN*d7jH&aodxu$s4BHDyMdj3E_JXrhhwLL2eeL;0}! zKs}lYSXd`G@~(!EwT=E2I^M4a$0pm#Tb)hP!3&jU`LVo#1sQ&L5RE^N(kE48SW{Q1 zcwIRhtu}@|J`YQwdT?0|O>)}9D{B~P)t8i5P@x)Rv~hkNO8jytBCG&bKL0WWch^=h zM7GZdX3`ogHNl}2TBBL{ETy)s@FHrX6iinNV>SE*m}b&%SDGOueCJ)8%XJm>-g(#N>D_<#X84O-o2QqVH_hKW_XT1TOPdtAHcu}zZ-U;j zMVA@Qjb1jU*sbjwQ{vXfZSu9+JcpgIxUt^t&6*$exp|2h+Jb|s% zfH&0bQs6v&6hY>P;cIl<(Ms#iz58a>S1Ii|NHJ|{86(AP{!+|@3qd@4?_w0s-oWsm zPTO0f{@z)B_z~ve%A!&8kcj&Q%>gg2&%dnsufDj>P(oC_{AIFS4@2o9h9(%=Y}BHv z90ekoig4$8on>@3Kf^V6YDeZq6#I`&Was@^t-!)+X}Kz+m@JzvmN6fj$gHNer5P&* z0bR2cD!345T53^^{2ldOUNqW%SkdxGhl{j5+Iw;Dot4PeM&mZx#u2m zzI$0d$_uSE(Oj%I(Og};a~4l&ff}ZS!4f1`3RzFiH&Lqp{2j7wEUITR(qBorBK86fmu9$m@=lVU@Kf}-=0}~;{S4sXAC?g zGpZ6S>Cjr~7ArxbYJw^SU3(>&Qwk7`b!G4VJ$GXDQvDd4wMA5;jnz#vxQLCB_2-rc zduOn!<(;~gRMYUtR8BYlzCGr}!;i7dR=*lbH_g$N3yVv${P5RR_v!T>-Lq95K7rZ@ z%|ISb6#(BEpSe-2vq z+!*DUZ0WLLarr4v7*@SWpufIuB@n9>gyneySodo0-={wP7+t7x?U|Op`~ZU7mN)wN z^5gYsaK@QrQ6<^0F)-|PzF*e}egaeVwLnEZle^V!S1 zdS%s5i&q2Z<_X|Vhi?0v(Ba3Day+%6+AACV3!Q-7Q%1GeVu&)le1)-wmjmhr|5rJ_^fD_&xZw{xmPzA=y|nGmLfGj9u`vF ztAnxc!QAsq59ua}Zm%xtjfK3}7l`J5<9q*OyzK`*aBC9(K=Sga`HJX+NsRxJX8fIv zSMpcfY&0h(<6h$eeor^18_njm%_P1yzI7^zZ<|QsLk+xdCipekXvSOdSB&SL2H)_% z>B%kfG9c=WTdC$lTGd%IC-B^H1dSH4VOhP(I%$pUKv!xixxyvjJ>z zGl}A@5$?uqPDUR@?c~K|^mX7zw#g)V!xlg!(Hrsgt<7ku8T~j5i;*|_uzWrwpP!S@ zugd55u^Q2j%I9Au3g7D<^Lu*5j`ZIpO(+R1v&o<&l@LD z*$HBQpL`~9bW0rJ&r?Z+MvD(e&08nqiFgwH#`m_#27ar*`R>N(597EQe|H?eA;xF( zbzpq+^{8_ETE1%jS{(0=cO|G7e*M>2{xy(188@51A2&W8$G;oL55@8C#|ct@Cr(gz zv~)ZLUcM`i-x{MLY)zb2etU9lJe^F$jpntyq8X?lMSLI#z{bCmhL6UrNS~6*9Eh5C zMz2E?#Xl6sKOEz;`PMjoQ`|&zC-D#RUE?R>_&srB8t62g6Rfb%1oZz&QWZ@HqUe#J zsnOhCq=#a9is#ocPPQ@r5}4%Q*f*JQ;nbbgO2(9zQ-oRo)iI|2Ji4 zDj{;5mc1RVEpm^_037M;hRyif0RQs%JL6X>;3VDy(Vc=o#t>j+#RqBw8h%;cB=Oo! zQS;{LH}MyHR^wWTRx`ORzJ7|(H{pnGFa%IHM$Jb=Ur|t#XgNaNfSyRG8*%WtKz%;G zH)`&a8cgYW{5T7HVmuvh2XWWoVa99XN8{HW_(rSfhUWXn>h!7P%)}$uA@KL_C-Fn< zBR4nxOA>zw9UX$oLhr>5j?E_~jfuwe^aQxM4}6$v#*NA7tqu0)$>`m9-iPP^!INx> znp>iuZET6+EzvLI#fR~H6wk+*7~hL7zb$$Q3TG>E<6{c^{bT&if0NPY(qCW&+Uok~ zOL&7?O(xS|+^xchNoWlu-w-u#jNX81kxKxe%D6e+DxA6j*E$H)o<{VwW_)|Rm32XD zB=L?d(e|y;4>yqO_81ygI?5JY=Z4~e^(oQzNuW!9l!BneVG4ph1^B5OqpxfOmdSWW z{PsrjU?bid|J>I2zc%9EY2Y*Y#$>WRe)UxRnkjrH-#5jc1@idcBy{ukc$7eIpx#fx zY1+wl@OT@pEoW)01tkkiHYGu#u8X!O-xtT<3q~bd8riStb8O`IZjax$J^s1v$uB}l z$KSO*e$DpyUE7oQZAX`wNPrn{DMt;^J3;ED_BTa$H)i8K6Sp^RL;Y`?jGhLNH#g%q zH7EXw6#S1k`9>V$lX4P8Hy}U0*fA%d_(7<&NPn=9i<#CKS8eO=(<1x{5CQdhAaBK9dTbKcj{7b+V{~~%T z_<%mrxIMXz4_;2AlsLx40VoMT=oG4BZj&k|kWG~Si0I%=(E%h+CL9pA5(k(+9X~3* z4JwZqaMXH?f{2CO!T1v2yDd7n9T(c8+Y5_ZZJ2@F0 zoIKGuz8$P4yBqI`W1y4I#{R~Ecz^SN`bMEM*YBTQ=AM*4nevPn)}7e5l% zzciJ6aVpswe{L%I^C^r0e;&se9@#KojN>oy*Xy=4{%tz`S9$UGaq=(IjenhP{L6Iw zzZ&s7o5>C|UJ~B`{#}piCt%t{^7+a5?_;QeIL7hxQ{+kGMm9k65il^eLCv65CdEvk z;3)ezsHJCKPBF| zMJhiPeVz@O#Qzw_$K#JfI02r-uTJ9EPz2d7e3Ik~N&G1`{PuVY+VbY+1eymwq$f6} z(G|9!i*aE4d^`(bQJj^}?eaMxpUvnep?DfwQRFQ^yaUgEpuaBO60bm(*s(v^h@q|; z$)E8X9e->5{N(XE?LRl-Uq$bRp8o~@LSHAxW~oY(#?&Nix8_uHD+igIz!CPY?dVw( zcqj#H&xsCA|9af`NSyq7oO~qS`r~o@WAT%sw}5%cBpQ1fy{YlWIDxf*`cu+wLh;~E zHW(v+>iDnJN7}GuznnNFi}TzqvtwPei{-9QQUZ zC6|-cq>o~#tIx&Xog^P>B*)`FOX5!_@fVZiD@n2yRsrShAJPAl_>YnV5S%^?JAvN=gH0lOOVy*>V}IEF>_ z+pu98@jH_E6(Tc}@!y#u-`GeVhYTG&kf!9X$?#@!NAk)TgQBA9vx!JQ7!o}K`eLfl zoNOewOg(aIl7Od4{aZIKs8UO)826V;AC_2T$XUkr@@^TqM6yd?h6OYrmmdogUie`#vy2PYca!16fmka0Id&0UY) zvjrV`%a-f6f<0h~8d|6{q2RVtjJIuplE+`yY>@`vA`PD0+I)2Us3sb_aXSc(8@Dxf z#E*q(`8aB*9n;b0Kr7}duwXIMnuz{MDlBR;c{{q~Bb+X2#6)R~PrZh`FIogn8vI-OjIe`_lK=v4fPspLe{ z%x{^7LQ3L)Gk*ix>ip8YAQ+_$LbB@21$6UzY?ZfC&sqcTA?ef12Eax{xUYzB#tXUFDto5!onIPT4Kp_%7ro-~n2SO!fdEtv1(K)GQxxKO za$+)htZ)Vw>~K6&|HPC`h+(Y}y`srEFWB;mB>F789vJhQZ;GQ=yg81(BDj!;%u~O2 zq1G%zm2)TF-W@-K58gix{ClDdYM8Agf5Tqz7G#d^!IMEf302)8P?G|aycO7zA40VN zHXVODj{h`{KNTnPnf^{bW!^tJeiF*MCH@{*H#8^e=eaTdF62qxfSO?ZyoUBTWCnGG z&|KHpf@d1W%XR3LQ;i$s6ODE)>kaF&$?6D=_@>mt!of%j%Ng~-L(@jyvn?RM4M;gt zZ0VN24cs&=bw314VhNKI6Py^lD!CZF;!^ZMWSlsHhPW?*R&P849TFBmvJap88;`-~ zW0PC(d24bIpYsX56wheVbupVf6Q9pY9*@r_U?P?@9>oC`oS+lqxzf1Xk|*Q$Q3;; z4*0xQ(zCy_RF1<(rslWYJJpy{HY;#rE(B)~dN?xU;rCYkZT{Zo{GFy#wi~oZlc`C- z@IfyC)t_(9M6Z~Q{+blikOK&+8BgfnARj|28gd(|0b2x>o*^OZK+|}A2TF8fg%(U4{Ss_kUlK2lWEy0X%>ucl2U&iql;>PRZiPy%->u8PRH*IqD z+oU$+&7`DGy(Iqj8!fn|N_$E2?a51s%j5yHgHb_l5qR}Eja*I4bukX$!FY%NI0=}D zKi6#h$VB{(iN@c6dC9jXZ)_%i)lB}n+4yoZJ|Dla8UIo<-Wz|a+4!D`_>B{dzaZ4- zn(@Cknook>KyKt)N}d#d6PWoZFc)=CrXYZ@OEG>uDt-)JJSzF+X5(YceG+^0*pCwWfeo6udqDS5U)&&7w5`Nkm%4*okDA4{I!IHv!4 zL3}1zNDiSAkniLyCwce6c@@Jffy`VN!C-lJv++(AN(S?}5gv{k8#iE}z!V%ed2+6X z@}c9X@$g`B4N9ohQbbDlwnq=f@lQ4z?1|E@ZT?R1_xHo)n81~H1Rb3V6$y&s==M$VHOUG5eFq$v z-+^%qoWp3z0X#t(-X(MK!6x;_M10FN=i;v>$(NIBZxCW|mEIO;6Pk4JwluGYL}1+B zf*y@;cz3P=5)3uMzH4X=Y(s%tZpO6iMv#2!W>EauIQ|S=OdpNGxHrWUa7eRYxD4YD z#PQD~3mQP_i|Y~?BUo8Mwc!GnDg(hS5&URdQ6r+KRl|NtYHvuM02=A4hkltP{EpkB ztv5({4f&jieqFF9-<>otFyiy|EIWyx96up`Zxa6`e_tE_QW8Iy#5;lZ1{oEwKyxcC z8R{$cS!h!b)WAc%^|j>t<7g}9SOmd?AyK~h8#-9t^P7LGXVM~xb`S&xkAlC+`kSLI zMtvAV|37Q*0e4qb<^7+v_BrRC+wW8Jq(Lf#VhA==bfk!gIvDJug3RcsGos=l7{sAl%&#{8gZUHYPj+<@|BJDRE;N72urB$1 z<_JCSna^>@8jsB#{S#on==PErz$?yVv$mr&4Jdx&|6;$gU!yin^tEg}SGx5xPJoyV z0WyR@{yLb!F@s>!^}i1-YgSrTkC(DAXmn`^r-foI+rWE-H4%+~ShBgKHb7EAI01Ls z0SVtbOek~(`!yOfW2JqXD8IE2^y6`T>v#FdyVH@EOE=1!FuzJaW&ucdR3|`}YK2b< zE{0BM_c3*IY(i2imx?qF+rz@{R_iXMJb6y@f}QF7U{?oU5g;Wza6yV9Q`m8VrE)pl zH@QkO)=xABtPy+>akHAJQdO&UQZ1>~6YRm!K(AqQa8?KWOpb(A1IE<)YArRzbVsv! zjfPn>d4lPEE_O~WVQ>&+kmX>g{0Y4)l3F!cF1=p-3JAxG^5p*a9eP#2bVU0S84Oshy0e

_7L-@;!Og#m=I|o^p}tJiv;;G_U7ZT+OI*GHneq_%D=JgDj0yn zS8Y3tHyYtokvaMHWIbcJ@#(M#+5^>Mdwh$;?AYRAdPpt#s(Q%ZM{NU9iTEfDS?UYw z5H?+gAFn(dTlw!epM#VDg1*Y6$^o?$?c)NbD%uJCYR19hFO&;{p>aM-&ZqAwuHO=v zSK=k%aQ;pIh7?o(G_o}x`?PJ^?tc5HvrUV*Umg!}Ki{-6>R5R`@7`NpSGJRHiVsU& z5*nRpj(z_uvrElaXW?Pt>?$_?P^RyPGDynPS$HC|Co_93^EWf*<0*7tuDen2V@;>w zkD1BL<>mJug$gUPaC>HVaFiSFlnLU}EL@ZsrZ)HT`=YE^k%g->`$KuvHJP8Ch0`-T zL)Vnwr)Pd~7B0x_!t$DnGXF}1AwYujbbNg1$tQYmRxg^uB;h`N;;GT+AbJwoU7xiy zo|I660EyCP*p#2wE0VC{$C?GC$~t))Su2VyST%dRKlE9@0t=)s4KO|4ot{n^&;V!H z&uw3~{ZQ*!lv*{i^fbl8v;x#83GlPVbMu7cWzmJ2Z6?Ogsn7ZrwmIkldquHmf%fuz ziuRcCF8B(Mgj}c5!?OL&$}i~4X35OW6U`LLv4p?!uf{D?I0i1! zbEGx*&7}|`)h#l6MBfB)cvT>TlmKQl}7AIT0VOp{fOA_OGM)E;;9;2tgj?IeLgK(2#4E%rD zFN7FO=o2-6y5>*S?1h>=uPvyd)u2BKIKpmyYGDkfT1+-@9`in&cM`X%j`97R!d@<< zC`EOJwRBRjGgHT&_*%uzE^MkV33g%d3xe+#?2GcTJf|s?45f+gpxcX7cl1HcEb=*_cCe1ACJRbDebUQ^;kGkK8i($Oh#3On$+REr9jH*B{` zm|FpV_O94|m9Tdu>;sG${v!>)*zG)tkn z-s~M!^`onBkA@v2ewgCK@%IpNG2Uw-0$YFA{WUGVmk>U<=XJ9eu{rR>9nhfMuBh6T zRe*Z6tc-lSomjEO6+1~=@Fw7QyJ)zrWkL9q+ai{X)4Qb=UtxBI*w-RQ(%UdR6KtjC zo5fD!xdEWvg1^8d*o45>^N@UTDPW@|&@V|IjZgyCQ8nAAZa+nUV^3o_78ek>DY`*} zz^>HFY1n7j6DgKKzlXN`+Sqjlz(AH5(q!hpjA+1=V^hp*lFiKP*>uE2@X^<2E*O7x zC`o#|LZyUG2{GbFP%6v0PWEWRwd!drZ?aCH##yvR_dto$e(TF*iPp*WR z=$PU;(sB9N@mzz3+|x{EwvtDC87^#J*o&PFF$3qr%!-ueWPTsZk&AhJYR9zvRAgzi zRTe>417H`-hH%czlNvK$De$%FW1L6T(kfZ8ot(cdRC zi@3T$Kh}GgZtLVb*-wd1xrG=ct^K%G8>8re5cOoVe69AhymrX>u66fo$*aV|&^N)j zWp}p1gDrai<=I!Y!ZSVg96m~Wall?0u=fW1fSedEyT8T2Uu)azVxsE%c%Q{iVY{_$ zuXfn89rkP6zHK|ZV`p}_eQ5_%7#Hp~XmbZ`!Jsc2^n(U%AKB%Ze*YNb4EDf)G3K`h ze9oY648S!bW`Ca~6H?X-PxNf4#w?&}qy?(E{Lz{vP>< z5^Io&A5)3^FEx-7Gyj01gC^CJnT=%EG297V3rMfDLfD1djuYR{G=VLX9{xk&KA1^- zod1XYdzReDt>K^^JG2J?9MfaR_Rzp_J-$fa*A5!m(9&Kzt=BK?h5TJVXg3TpmNDRd zJ4Hx{yoM3LO~3)z9jM6jML89y(!#tSz8JQF#ch)(w}f!JfnCt1tIZH;bvcn(1U%wA z(PHO!bal+PA982TU1RuEeinXiKQlhz=j-vi5mmwTZ|xnocRhOfz6o{yZni_EZg)YX zL)Pn;x5H&^yS#02t9?y@)MJe2Ou|6tFLJMi|7E|-eubWAJTmzZWGhFtA8?GSQOjUr z)G6#KSpoH_)JoYHwI6yvxFg;(?4P5{zSD#18bS zJ}D(S6Vv`AMQQ5W=X zT#?U+lJEF6K+s{36@3n~aJXr&=Zp4`;^kU8njD#9U=^#BAkBJFc$~Jxdn|$;#%D77 zxh+%3T(H}NDG1QEC$w0s^pG3`4wnbJEU=}!_~0VcG@Uo)(tY-!^?MWcvKRU`_cWrDz)XQ zv8CU~!_&I`Mv^$S68n8qYQ$I20}D$v+SK;1sOJ~T#?JNwJ--&$d1iBIsN3^fD|Q?0 zs^=I4wg$3I!H-YD=lw8MybBVyMsidPi(pH?UR~3#T?*T^i2XV#v&F)@we6YMpLv-b zn1y-5ywQ+6p-_MBU(=r@g`Fy~S(X;Ft;NWzwgJcw92F2ulcV4m8o)5Bg*BOF+bzTg z*^6GV^A)pOA0ba3$JfE947l`BcLj)B7A=6`14qXsd!V^s z9s%fC!w#>7Luz(t&EnRF_fbzO{t=sR_5((KHFzUtd`WIsV$Zaza$BC;NmVnb1r=r5&)ON-?1|F1FB))s_j>`xb?lOVV|n)UCnNfzLC_4 z&Wl2HSCoFQ2y?3TUV(Mpk*hWSf*Db-9xByTzz(}u$3BTx!ctG01iN*lTjM|IauKeN zguAIluk{dFtW~lazQXRBz)B0FZNznvA=}tMozSET+_9LzFVIR+Dn2DlwkgKPCkMW> zX+AZqBjLsP`1HW{7_ecP9A?LwW*=*Amt6FB=U+#`g>CA50-uymyG!e}3~GFu2?}Sq zEOX}C?X<#{N-8+9uv18VD1Y05bvwB3=Vf6Z(43X{Oij~xcwvVXY`J`%fRz)z&c0O2 z)K0Ez`X1%_xE`4}7{En!yR;r>`l`AuN2}!6HFdkL9+7iJtUg9S(#PftA7DinqR7*gJ*4TLh_pDLe_<9-8?8`f3wf zaHqCG29*}!q90i5p^!`yntz4pvF?&<#w9m|@U2*rIv+{z=^*E^x`1PRiYV(db=+N> zz!_ptd~6IY`T|q(@h+fS$tv_)M&FX5C#%^LfGY|Es|zHSnk}d^sy*tqTixb@NQ~v= znw_Hf3IWt@yGSm+kR)T%^}$WV99$9juUb$Jz$^zaQZ_a+1Xd9SCUr6&O?(b9fNe$s zAl5lH5`m496)2?8X}8;g-x_$*Wleyd9on!%8h&KmzrkY~c6P9{LRb;PCBbeEgxqix zo&jgOuW7HkEpFKrNG|qp(;mfq54nG;>CZM2VLN2rG;d`UNvE}TRbkOW%p5l}KvO6H6IO%1N>i>z#8;dnf^Lq$ zi@L_T%vqOxl3Jx3VQ=Z>djf!-W3zzs#>pZg)57fV70@Whn~1#u6_9;wZ6am#pi(3L zOvHYce2fF$K;Vu@8EkzTnl(r}W0Ko?82wt%1t3gIJvIddYZ4Wc+hm^>*#*5(V20L` zut77=0{~eJ$zx0mN%F%gB1mad{H+n^p9Ri$9X!yn3OI>Wfg~|8ZY3e>IHZGP5+a); zdkyZXC%dAHMXva;r1ft9dhMhZWN1apzbOiAFZS3=I#&i8?9ywx%g=9y zzM@#l#-G~ublab3`?GDR;yFz_vSIi2*t}lbf*?7``1-uqYcENkJhN#lAQfi2_vw#=r3dRe z+EtvBXw`tC1Xy?-vfo5buBQ6nBbV(Uw6Pg5r3DBk*JwJ9CycLvVuK?6l6Xb>#S)0T zVm}4i{A$jCzs0@!I&diLm_*BrW4^~FPxe7KU|1M@LuvMP+eh>xMJ5x$M(E(OsPywN zOs$~b7We_$kzs)dTUWjiKie?f00*^*W9b)s>w@DUnLvOO)JQFsLcU!YC2zLKNfUsj zX31kTSB(f96G8bSb_WlCakA5Y=}l=)VoPs!8tKh%?O&mD8~JwX&0EI&hqpBRePVCsTI|kl zF&so4+S6>Ws2}b8GeA@SMc5hpEFX{GO}ZAHLcCu7Kh=z=27byeD3Aw&pbLO_B z6mNc3N;m6)*a~I@+y6VM27}#Sk!Y&WPSJ9)BaC@HIV_TO*eBLB$Nm*~3Vs<730=4i zBUuF`)A6(mG0tm$6l{wxgsqLELd9D542&>Yq=49nl|U9vNcnt#FZGi#Af!Io_D%(; zWrkCUEvFWc@e^!W>c8Pv4)idP^UK3oshyF6$7KAac0=mdr*p(IEs33dXmVZt^5KLjzgw?z!2P!ex_*X$khcTw9T8TnUXe9Hz>QaADqr8P<( zkunT$Vd+wjc`TNh3a)A$PXVv&Fk(?q50fVdR>7wj4AJ&ja8+#_XRtu}mH`<=*V(wMIFf2IvUzD*S(1-Yb|;b{Rs zx|E?j8nzy%-^p|6MUh?Hl>Ie!aaldm2+a^wi5{I0!ot)Sq(sudBVLP&>Fb1qdw5+$ z!|jdC-_HCWB8zw|wzm)|}cR2)HVGNw0r29OBG{78L8)HRIBlaEJ zSQggA?4Oea(E%FXkDA^l=jy*u?%FWL9#Le0KZ-nS|^9=NjpOBsKRkH_yOcS?>6oX;=<<(~)f)mHpeIa;tUp~cwe z>{hO0%+Joh{J(ClHqzV+0`@SCy1WxE>DZ+mi(4Pwe?N`FhR+Q35rgm+#-V^CcV06b z*o^dP-=JlOJKa8RA0xo5Bu}J;ECjW>gI(jK`c@5&r(Jkyve+LrQN`!O zR+=D9Gf<6ZoH*+L3kvl+P%J0dZ-hiC5&g1ArY5oKAWb)?j*SEY^{3SC5Se-)(wfyq zw4)7gyJYGbk*USOP7F9~x@78=)aIc0L^AbWymeQ%UEFs?Uy2Lm_iM;h-~T(AQkK>K zcQOT!1MQ)Cd`cI2rl^$%>jA>_^cpgSaL!sX)P!3{$keZyIpDqxG8QdC>C)l3 z0bt#wR~`*pP1o<_rC~C4>t7{PD5*lbHDv0<5YA2=7ICh~)Sl7m^EUYu9^Nj=)H|8a z$^GY%OudrZ>mpN2U;>WXV*lpvWr5TG9hoANDsN#f5UF}Bry=_hagQab`t@j1HSYhM zR88-aDmg!wShCQn8I);DI1SrcG{tJK@;TcwXGZQ{4dU=6qn=+-~k&x6<{ZsdUI=ifp?$LFLw!n(vxb`Wsa&(^c` zFtcs_=xXyq)7cqYV4q(g|8ONQmzF8?L~HBL(^yFpjclp`*z z3k@J(?5WKlOlf^zuerXhhmUlFj8B>XuVJxV;Kh>#C{`K+L4;)YRT}{? z?c%rtx>o|+E_9=O4nHFhM8O@h>O;3l$OuquXg4j~?GdhbIadD&*M}XOCUE8ZQ4f!3 z3tV3@=UKy$-QVqS4~J>nh3=kidpX@g5M9bz>_Yf-)`tV*(s5ZrnVH3D+%dkNwCstP zOAD+O8~&f*ZT(-uuS^k%|Kjnx8D%9Hf^b+^2hQeQ?BxhY8ytEY()F!1(Eg1 zBpY>xu4(f-wjJSvhA&DeoD^0na9C=`r(A~K<|m~@8cUWv zRVe0mQ7NhaXUPXQ#&tjYK);UaJ$e%oWI zJ(>D+ISIhaXU(25wp>QCHMsd~iVP(t`ET}2>ip8WhpAx)mKaewVPI^#X1)uafh_En z*iyxdN$ zhZE~|{u-8fLfy^~%REXfbAH{A8)2D0XKtC1ZK`>Vme5)A;aLmpd7Q2CXxMTs{Z1Cc z(lSxC-SfXD+3)^AmU&kQx1^3>a+_Et0VDu?8SzMgEfeVY=ltBUL|b&?lY&P0SN_De=lqOv8ycrC5sIrjn1W<%aUb?F8bq)zBtpM3{BT@9|)WCg=>Wc zYuWE9RAUFMW&6vElh9})9gruB=9NLkgUPrt3Fxn0E9R)jrUBH6?5Fg!18EV_S=%;> zvf!XhsEQZd`J>6Wv2}=8j^kU!1{y@?Dt?EK$_%QQ0jNH&O(*puBBa2{&kRH-?E|Kb z-%Uv_q$7_@d31*lp~i|zln8?KM+_!%1eZ6IbB@*SNgc%@+#`QG&;W=mRR*(Tk&LS* zdkDv8*mMlaShMJYY#8$B{Y+2j4)r(T*X3{vwENB{WF)gq8r|m&C*v~4-0F_Cnp`R`oZ!8GW(TmQ_(gsaojgw=C+Ak| zoQjd9l#!-xTNUEBFO_Fi4nT+YSPCC>k`KbLYc@-(muU6=9kSu}Q z@BmWldFDY?JG9Cgl{bv|IX(N;ioH^a-eG%#$i0HKQ>43SjB^TmuVQmp1GZbCGas^< zGQJ`!ZjvNZ@J+DKB8kSHT!g(4Qy?^wPhKknJ+v>hnQxmV<0|xeU{p`XC-+L4l+>!= z$IEiNT-n&_y(Ylzz?#h?ER)rnr+-$To-OQ|!k$&1o{vtoUhdq8*(G{2h73(Zl%PS* zV`xz1kJfrwHlvURKsU846+3y0O#ziz3I!i*xeXBkeW%G{(s8pv?k5`Nloa_Wqf@eL zrHW4A2$IYSkwOJh$QSd7w0>>jw_2wH(iEj0lRp4u>q^o1*JuMna4AOAx81AjEPv9 z&eVN$XI-L`B5XTQVtv##P4&F+`()f4ONbJkqtVpb<1G1tnP49uxwKuih#K?URJ zDAr}lXteDmGQ)i>-amkLcJn*(jYq! zj?RdR!XN_LXoOYL1}Q{UVnU+mHJ?n%44*uP%a=yd5X0q5$1O_NfPCjWcam{E$>lxB z+UlG76ifKgC&@av9TN%!j{En7P)N#4*c%;tm*`!fH_6whk%m3cW4CnV`bK0qxzA1| zY?JGb=<{Ry0Gu$!EqXux-0`P7@@xXk)UNNbn|sLb7A@uHX?~rpr zp0Hm}xQj z6epFI%Ip^8^hU$MTTA9B>N2%+T7EuY3P<$Yk^OX}6p~oR%oWNoe3klKy~PBwTgeg4 zlBMb$h{IXR9`!mSd%72+;_iJ>?$J^5(q)_F3V3x!gzjEudvY7jPR6ENZRAKuF!MW! zYQM4F%=geOuN#5h1UXZ83r*{*_;LP~?qn%hNRj84EzvI?6m=vZUJXfanxKJ_jwr2j zQXjuZ9zwO3$)g{6x2}^8dAc0bc8L+%50a(G^H?r0aGq>_2GSM?MP)2aw>lq#-$35- zaf+STIO&CNf#=3zC`UGsoWlCU0;!o7vrnBQtPAoGw*W^E*803n^?d9OQe8?3ps){f zbQ9tP)cs+6sFVRn`)!F#YP$0D}x*q!B84hqh%r5)WX$o79@)S;EW3 znL~q)p}tSB!vZNAlcL8{OXm+(S{?l|MU+2;jHbX|byA6(lYJt~N`d)!Ed>dBqJsO0p00j>8E*3VGJex=EVgUPmV zU??sF?QUZ>UWqZ^g`CqLX!ZA##IKk6WnZ3CRz+mMT(|eT+7Gv|0>KA_6MQDOAyAT6Pqidf)9q zS#Y`+vFNd2j|YEPfNK;7PJ7w?+-2ovao;Ixni4 zSGlhc$->AqF;KIYIOV3(LrD;)aSW+wkp_gK{y^YVOf|kjDaE(36iC1ZgTF)$gmU&J z`$}qODYjLL~T)FdAn9LE}_%p(H*PxA=`S!_(Jvmh(YDA)wtTpz=frTO?3^FhKE zl5*N6sVgHQze7e#t66Hn5jPqOk#|$gXhr91qvdcFu>{~JFiN2y} zX|Wr0XE=0=d8FQw*`rYsv4fZ@hcWCM#Vl;Dwp;FVspymW<5(8s{yQ1bNy@{&F_UHD z%FG|hD4Ry)xeXA92EDBq=k!#t}8n2<|XFsw_E&EWGWtDUyiTd4tLU*{yCP)F5G}26C zk_aSB!)$U3ItYDeRj95&i5Rjq+dhPI!~}Sy{|TLwxYGH;HfL zqi=mcXY~B?d-#|)6(d55Km10bkV2t|YbKRyBT=F{*waWZhLeGS%KH-$6Dwgwq3A&# z?iON7u!JHcA00?A{z@?CP~C>$a%CE4J0?2sIGB8N3|Xk$5p6WgtHvh*0uQur9Bt-e zjqoRu*|+si`ls>)?W$(~%YRIP06itr3>Fz(*sLenwl`U&)hl|cmZDbA4h4XdZPVmQ zy83w8U9R=lkDXWe`O50U7>y7BMGQ{)Z9$X}Ai+UT z5~5?^Amo6kR4_plahWeQcrigxh}lu<4RJr)%Zhj;-_vUQneS_rxV5;&b5A);9aS$; zzdu#syM%zwW&9c#Zj+XEZ782Wds)2GxvQnP^D8XC1g|$xJY27RB*SZj2Whxi>4n+@ z+3_Xe+OdZ!zPMt4gO93(CjJ@Qz3{yX+q3X_$|;1AO3r$q=9>^{?$71^aa7GWa(^?o zH*$NkT=C^HIwy0oNly0jK9kR3&^eJ}I9#71ktZi?NB#tIIutk@nTaG|X6 zbU5{s!Jc4R{n>zp@0G&eOarxE-{BBlo&&sTV9%;kWu4e&y1=po%|((hTeB(xD_#pt z6;onhCwx*=08=ViG@y%9q#Dpg1QAz^q?{tRn!bwaT*S2)NZj&v75xpC(NjT(a}u`# z;mVmDjS~tL8Jd_*3M8!toQ#ZRs!hwMX6yKLIU-tg2_bUZJUO>4utrZoPw*W?cO>*L zf!=Y_()}QwmJjcP03o7%C8E8iz7hAhj&mS{7DL<*$wKL`*Vg>r8Z;fa9#Rj7*X=x` zAQ`#P&jDx*7Y$`iS9-E-y}K~R3jKk{ zSS0(AB_`cA8rpyiP94~ET3HWMLxgEs!Za?hz#=O@-u>316A4@MJA5itRWlskq5Q^I zya1b%w?7i^Nok|}42-mCpBneO@Nf3J@F598pYU!2`S5p~x^m4!9ay`qa7W8-Z-tdH3-fMSyzXg*`&)Kj zE39tW!!2Vw&faSI+b#0RPD1(hqe=SI_x!eBiZe3U)i=h+kSuB9%fwu+-GY}dCXq4 zwu7paB8Z|P=*ilcK^usLl&th(Q<6s4Wu?gZg#k4T#qT!h7VBcJ4xG)Ycfm5}NCT3H zQY_^RLJ?hB*tG@Ncxe{R9i??!W{p~kE#rPytw3B5MSH^wHSlD{9p z+Np1X(&G0f1FRVP6iBEcT*;d&M8Jp^%85B8G-R8cl4G_lWtC^=U-4Pl zM!2wrZn*oPmbGNtj736Db1!HSg#^2)$5!@0z563;2Mxr3S>Rkh$M=NI_H0E^OUVYc zMM%KV^#0!*lkfngaMo_50F}5e+A(~j*=+~w7)w&^OiRw~Q_cyqk8!Y#Y##QY!~#9@ zxea@wWly&N)>)14dc$7R(N`OGPuuQqr@M7*FK}I<5Jz|H^nPDPp-w-i-_Gy%AKLZ| zt!7`gLk9fF0Xt&AjvN3pjvBCI2P8eRMhFGZ4(TDzCoFC`Spq_~g)KWmIlf_C#EpLe zPsXa~M#MS5K*^K=j^L)uIwS*4j#eAQ160hIm_tyF%=2iBP++W+nY;~9Vg&T2T zvwuvsoyhH~tOF4{1GH_0>_;8%U zm+9u-$J1rA!41f`Na-O3r$uNE7QgaYES2r(c6T0FmKDj1NZyeJu|GUR8~cYxuIe5e z{;h>3wpL^EE6K}aVvnvFV=Knk?PGkUveK{ZC#vP%e%rs#=k>AZ4(jtm`|Pk@KeE@( z9AgW|*cD^^wlVg^pg%jv$R8fQ`z76d)$kRMjzP-Yd&u?~vLlB4XyU+t&humJ@iDgB zkk1?P^+aC*O3nV#>#z0#ozeoiom3}j&M-%$GSa^INOX*|P#PgLJ09&I(xQaX<kVWhX72=t{SrCL-wa3 zzYSVy3x@3YA-iPAmopfw0M05px!+GwI!aqBGTH=KZNiq3eu9Kvsf%j!#MvKDwyk!b z)a-r_PuuWsUd%E!t{9<;!LE-QYe$c@lgIi}bWi@FJdd?khwPBCe(G2|bF3{JYnP4n z6~kwb8*BTGwIyTy^085D`?zq5MM8LI6Hrn>L-a!~J@!cMlOIpO#7Y7%$=(B)rI0r1 z6UnxpOqSxjphMI7%mD1*JL_4w(FJU@WZfL&*ZMGmUK!1~Tz8a5J1qQoG!m^(D47cb zK}tRiAS9-b+_tpBvsni~XjX6X!cn#TZP!oN;qj))?kRATI+!rs-$?b2^?9`?iC9#eWierm96OFQ9@|wN#kJVg!>) zf*bBosw}7^aeR2R1;^V+(Tk5q!G_FA!JgyaOTL`)SQMrB(E=+!(acTgBw-0fmeK#0pnYc78#K3Xq~5buNAc z+enweIT!vt(?f705?mn)kn`anPopQvtK@==*`3Dj`4GJeFuyar7u_F4Z5Lq{y9A6bt2y zR#XPq!}t9kXkKO&H6zk7Yg&n>`6d}tyQW8#WKLGboC?+l4XP~Sls5Tp2bfv^xX)db-knVBZ zt%fd(BjfMvAN>0eso8WWdT4)Vf9ImG> zYlMRWXvoqY$Qkzf(*72Q%xL-68$yudK}Yhx_)U0(N+PkRu(q~r#PYBs!;5>7mL#D? zpNRMyC+C_^4by5LwvE&7ckxr(sgnE(1NUCYg;c>p0&G*L&#-NY9AlwjC@AE(XE=JE zj!xn^iz-y6;@vAEz|x9%%ZBj33M?4|OR^gKhbJ5Cf=f1eb}J!_L2k?mihTibaK3SF zvk9D|A0KgGe}Yh=lkB63E|4l!=7$iItLo64o$VJ5(Mc#}qA>aa<)M12I|JKaYJLS<_jlNzKl#hb46)I`!yr za3U<0F4rJc<72?89}P1A6MqcXgZTJ#?hc`XqohioMAE*a38Yaty23vRSRrk!l1IlS z7EkC#3sMmgxFYL@w6f`pWS(uvNU}8}U?4k%@+X7xo%(qf85d&=uLsHk%!_^eFxD64 z;C_TPbZ;}<)wH{t_CV8CHJzmJX%U=VhZJL0AcH`uoM?I&nJqtMp5)3dC5yQSk)k>8 z%>lT=n*_=&VI{ZSQ=`7%`cb^i<10Ks(#Xr~V_Y58#^a1vjjh>>BOzc8e_7o6Y355~ z-oCPpx$>tjy+9nD9vSCUGE_qpUc2vP|47@oox&E1BfOti2C*iHfW}aIm5k3m!!F8<`X|)Hd^5HC zQrs92Mf6Lvr%2o2?gE``B5NCc>OnLyaB%|&i3a@*`F6#@Kus`_fOjl!sZ;7YA_YIn zfh!bKghmLe!S~TUEx9@VeFoY7Fo=Qkeu8nNT+8{W<(L1H|8w6zg?~=F zpO7qNUGTOjExfkk9!wcS<)nvQSR3P69u0#zai6$TW-!UA7ZWY z*D~YfC}(AUzD&212uUK6zvYMNeEDW~rD~ai#6Vk@}~7(-0R$s(fKS8OvVFy*yfp@Lh9N;0k>xPQNLz z7vF-!A<1nzlq|+L22gt$>XO2j7U77LieBkyDlF11FCseKFydH=Pkf>9lMChFo?Qy! z9TB+_)_A!^7O8fNu(nIp_o#*!Q+qiLdscb78fQ`}x=`cA_pLgWUexLX6}!J;_f`BH zWN+0)Ol_k|>YwZy9Cm`83x=4jQlNo`mS$MdGnN>yiIjB@iIGJZ`JG~cp^y>Ia+C?y z)w*mCvN?c?`k?AI<62bxz~&IJTthx0!5LX|6zEc)2`4?cY9~~EVbw1Fwp~P22!DSm z?74!VQ$JLOYRa^VKa~_fVx1yFwE&`U^O^TOBrT~Hl#5qe;5>)CmF%XRIY=EuZcU$p z=5$n_R;y1ZSM8LlomchCtBh&6@bL8QZQ1tOlI`u(?ZM>JxA!x)2bO1TZ!cs-kvg-M zlAUXBXW1*N!Ru$nDOphUTL|PMPSS~!+`#r9K6*xJfB%fehRHLkak9TdX-ZyPjy0Ma zVBs(`;2uS=F0IQVtt+)+y|hq?QVRDFMCRDnh1J6}K!Woy#T&s*=t7C#;C1>_)V|Hq zow5&rPTXL)ky0Fhkc)7Sr{2!q0Ps`pS-qU^JqSO|^kTTUqIjb5j ztok`MdyXncHNT^LCD7L;%Hc~!GMEv+p|+9s0AZd)@TAyDq^iobs~ z)+@+s^BE~QXDQ!d-N1L4k;SNveDuxD(LY+rrFD{y!`{J&Q9?$#P;a!FqusDvuW41l z67Q&kZ(NJJ0lA1VD{f*2^QREu-31D;7cs0JR^VYQY()XT+Dn~7It2Sr>Oo``5L!}% zGvw9DWz$RjbcXtH3X=fjE(zGx!sl%%5g$Y z%rG}x1}F4`b3drGrtO6q!QZ}$DxO>J@2OW2q6bubmx8!1Xu9h2tGBoCHmJgGQE$g6 z*q1{W7j{u$7juZYCIB~DRmCmZ43+Fs(I~NA5-FO+q`cD1;HOywyL|)eeMMJP;}+=< z8K5hK(E&*ylBKIXjYxl@N;_EvOo**To-9j3_ELaXp*SSNlNdjsbjARuNfqYF3e6|Q zl^W|=HK&0>QxI3N*|(DALOOhl%7NHOD;PiI2FV$?RS4-&$Oz(3_I2P+Wd@!lSwt0k zM2IBFBiHhW(9G{`ZK|YQu2ubf?2wY25G-;9wZ#Qs8wg$PcRXjPT;xBnALc*sANmi{ zANGu*6YWv^`47Smi+FW!fN88?$yCyEB6PvyW zJBuxmv$1B!Q+AuXBR})0l$}*{uNyUNZf@I6ZNII}`E`)s(rEeH&VI;Q%7wn#wpZHz zCIxdK7^%IZ)}CwN=U6}IS>2~%Bv8}f3zBpNx1OYj-|>2C-W-9MgBLwDz=b-p9hc-4 z7+%IAtUzM9a!4~E(g2qM4^VAWD%wb<@EBb!u7fKwBg$IW)#E!nwgQOFQu4}yVgQ1J zqo9@nwJdoThZGBtl~Z}BQ%Y6Gc3|X)z%9F+cl6rzvXQcaSR@>cBfu3fCDO+7h!R(* z_|&ntJN8z`=k)ki_HCz5s{8RROg9~vxul{hN^6QW9m6Fdru^}K6b8Xdiz2ls4Zl+!$LsXE4)_~zRh0E~p9#?r!yX6^^n_JC_7GqPz3@G` zMdzS%r0`37s9JYT4bdF1@wPtYT#=xGxmh)m5jTbxzE(d(3q2pA84-davcL|nEbx^2 z4;)i?1g*@8%XR=*VhhO0LSsz=iwN6la_~TOrU|;dC!L`{@DY_tp-u|=UwTPNvU5@# z0ob>F-o&u?L_2&UjXfpNZSOuiw2vUXarU)10jk;xagxzTDgqr<)1WkZtoFcgt5lho zQoSpZ8{`#nKd9FZR_t#Xu!D6(LI{In06YIPm-Dtq%5gH28VAq^FPOXck49r+j2vBT zev)Nz#!;WxXIqUU4&AwiXlxEj^e2xiX8O3kaKnT^CBzf^Y~=(RS+KTIuD9WD;GI}A z;=@$V`>Z}YyN^|R;-H@2-TEb;pHAiVS9<<4MD=hq6u@+m#gV)c~Qd*Yw#b zec`J9FmJ#P9EcdO2hKSl^cB0B012nq;_)6X#*7c7bdyYVdOMn4pexHd)@;79|LA=D zBhE{TN8B%E-hxGx?X9&5QyUJa8u&&Gf*kQaf7E(sz)Ri{-I-zF*kG>mS_@9KfisuD#pEp=BiNPw3*v9!-C^vj#`@YKGmK zHn-_)_h=%^9Mf;dQtU>)V36Qd5~mpGr?iaL8J=~x1A-w0P-K|ZE&jyY_IkVX9DS_F zLTxg<2C{x;w=DvokUdyI@;Kfm$Ym)p366>>1b$pHtCCzOKL9Pq^(tdlbev$t7DL{F z)9HyA_Pf!dWz6XRy!Ckfz=>wVcNHgE8u!bnQ;vstwkMH56&_Cg(bOJE{qdBna(^`YANXL#7aHf$@nFmt5^3P>#_7I)3q2s|u@uDwSF zC6EQ#P1aRjywEcsi3>f57qgY}7F{CVbcmK>d;}?HW0Xs|%(os5)Dk5B-4;+~!{Fx{ zKwDl3I00%FkFX8N-5_B&z2byuUR2?|e~$D_2^3Oc$yMW3Wq0IudmhSdnL)Zdw_|fh zOMH_z+*bX7K-PX>OWr~Vq>vmF(ieD#9vPBTS!ex3@SWs9%XZb)7fa$fdDH=1@dDgr zU=K2PL8hgMG{d%Q%w)F8)riE)lS%+e(2!X~(dlrY7-phXsv3O2kRvMdSnfrY@&(`3 zfMG2{22=t)ODL85pyz0K0;~G)5%xJ-Zbx4OoPq5KVwUJx8NREW1-A9*EDA9KYaznM zGTt>y9d6$22WCiSJge}tCCP!(t1(h>oDjDd+WoYuEv<%8Tl^h&W#L|mB4>7Qmc=c_Q^JQmBC13aw(;nBrJ$ zi1tz!?iO1D31J8GzvK^WXREe@pf33m90ZF1xSFL+I8PU8b2w+r`vp3pwbJGIszwL! zCUh;sh2%fQ0lUb?#r}o3Z6r&PUZ4gz0_x#N)m&JB>Q9cD!~ovS!pToyOeMiKr8AJ^ z!Y+_v$PJeigsCAaeu(2AvdK1`zT~Win%p@`f|vC@5~OTgl$@<1_sGtZOGts4f0ZPI z;UzIH&#IJkNLFj!T;;K!j4xq+j`t|n{kFROIcDG7UJrL@9Cy}zWu3QF`^#md*wM9c zm~0rlA&xFVXc6opWsD0{%eADA&;|0Fge796co4-%X01y{SxzGz%}4FCbVrVtOE*vU zA(DW}(WFtAjzSry*PU%I$VvgI^7q9A;)ZjEe^FZFyn0~ETM2-kVBUkAfP|!pmAuTb zL1mfGNl`>HD2X|B4b;K0bg*3YC9FznFuI$0ataC_ec{Zr0*8p zY^AYDdJ1I_{4>?zb8E*v`t#f-v&!j2~( zvhYPDMiZulkwChlyq=?n7~$SmBFG4VqxBnW_S zQnCnNkKsr=Pot5HjGsfz4k5Ow6bAk(^&G)MCbURaDY?VL8!#gxuCT*o{%+OYsRm-W z->ZhWZ@bofmuRZFspT-R23NVymUlyl((Br_@MQ6U7myAR(W!wEr&wlmj)?}b z23W-+>ucZ$XU5FTvrEyYtLe)kn3GTgrz#(eY;$ zfBj0wURM0HuM`6;LrBTeUh@R|;1dW>kC78v!&F9(i>zF;X)=dO6}D&F{uE?@=A}bX zRFQNqLJO(o%{>EbZ6Bq#W26Lr6yfH{{L%AJk9-qPdNM`Kj>8epLP9MDY_%1Cv7&_2 zxMd&Mj$9TokKB$>z?*b`O)UqKH_ht|0 z$SnHtNNHCo+Yz+I54XFrbOXP(##rUYDPl-Qorv2o*YZ2Sy_g~OOH(9WR;!h`r>=j1 zXaccVCTY_8$&?L}!=c@J5x8Wz{Nt=23@i!&A$sB0!d}Xnvu@S`#ehosul8HnQ^Gnv zJx>l7ohA;22$ZKXe^$O7MDAFA1eBNIZWuQu2S$du_NX>Qj@Ai!_rYheFbuaG-%A=u zyL&godd{ns0L($b$%cILyW!67+RE<&v7>gdKVaA}E<=FjjgiO8B8-p$6fotM2wyG> zJsM$8#!n?j4Tl;t{#EvsHNB~HpP%1sPEo=ShmDEkRt_q0<^*amUViHgN54@5K_{$x zoAce9yd;2JkQ@2@*W`X39t!~1B2fJ;Ds1WfHGXU*TbFm9_`C{gvb?MZRtV*$W@l+F z!ED9oE{HV;j;r{>iY?F!;>z|;sn}tulXFH<-Lkd06@M(ZJ+u}?b9iqx6j{O~uTv4d zgGB)hgvWF}7A(p9F7;Nq#;dM^oC#;U%Du*C05&)G<;L z%3g8Bj)DFsi{b?`mCXJ~G6leo(2}vkR>o2tY~;xbc^Gs1f&a+<(fIg}2=|l!L(Nm1 zAY3mld_&dr&7U-~#WgGj>edVit2EA!k*Bci$Fk&E_FT?eO6bKZ`|&8SO3aKORuJD6 zNeo(y-3iRQ-x=A0@!bJRgm2ZmN1-WccVZg6T9XPmd(>^i@Jh{It?|MOe_TUf%Z?9z zT<}G~PYk|)9>CW_a$l82Vd{G}KMTiUw`$vQZKdWRtY2QY`|7@`?%PB5YW7+b?hdQ_ z(Kzry@26@6h}wB6TfbcXgAzP)HC$h}8;IVh``tAZRC_oNPwIj*>$a?}(z3VJeM^W_ zI4|c#vw<$~RyoMpkA)5c*uEir^q6Y(07FuKLnRf4mx!nb$O>tT6a@3BSRC_FhB~rH z@@~)$Mzr$GnELP{K{*Z7{In@Pnfq{amEMX;>n2lXBo{V-MGO^$yNmmkl2V1afQrck z6pvv9ir;u?pvIRlHy(ac7?WkX6o=LZA|+S%hq~bkIL>jjPS$vAnz7%I`2d4ubbIDn;$p%PSaL zEg_lA{S76%u?lu;+g$m7G5QcsC`P&}<= zyl`?!%a^ub%qO;#y0f4a7Paj2$N@Mco89Ut2U3u#;O$Cp!PLm+#Iv`F}n%1qBo_KQD9_@EbPNKwcY z&xFCKBFq82p|2u7!-VVoNi2XS75fsO4s7x2R{1oOw=r+n?LE>eSWyr55VxarUMQfw zGJJGSFKmz`Y+B7R@_w8UMua^Tkr72i&Ldz#0o8F&(XKIEB5J-9lk;t@&mTaVaB{whXTMJIns_Lji ztNs<>!y9T83{5a2+>TC3@kA0;t8!YFT)K2jez_&yhx0AUd*^)l#xmK{U3%MscOLm-^Ou$%BL<=TXOhr9WGY~M}qO3Gp#mKiE zlJib{Q)Yjj82KA+Z_3J=+JV90rJCIn1GUKkx6Ui$IW6D7NKfKQ1LrFleN*HmAkY7k zniBA?fNmUy_tlLJdCgY$cO#ik!z^4vIiC&oM)0@eK&Y{TbrOdlA$;ZW<-B?r9Z-tZ z)5`wY%bW`)8F7Husj!Xn?!L*wcB~;X>Er8#u%}o^`3RsT>=Xd3ezG>O^a*BVRWiXw zGG>h4?j#d>l0~IjA~6rYwNx^+P7D&D{xUM$CN%X@DpFL13SQLn7`c~`noE(374mcm zL75I{y^wW^+=y>e{|)v|GYqYXSWZ-=Px38!p}}U6mrSBR9e%wNT_B%^xjs+y4j}5j zIQw$|pP)+xUWAk~yk%qpMVlnR0(yB3k;X8rSy0OTj^mOEW&pA2pDMZsF>O zuRzE?reX0&ddlT5;7A!BnUGl{lM+dj7*}XBIzLpEL(+QJ+@gE=NJf)9%lWKQ*oEuvu?{L*i{p>t=p|*{BJ1jQ z@cf`%jnix`drP9Pp?Wb*EE2b%v{uMQ~sJC+XeKmVLw^w5^1%$bj zMMDdP@l^o$ zw9IZ5UmPD64Tc4Swou!!aL^YBSo;cCJoD5MQw?Z-!fp@g8MN--16-L%q4$%rKcZw9mp ztwC{0Q9g{+K!gr_B_R!|oaq&f;G^t9mPyb%ezedeu_NvjgzBsKQcx+6G$;|Cx}afN zm?|Sln8vT^0dAJA&mI#haTDfBF$r5QB`Lo6Fg~DJ{*gNGXGvq06p4SIf|z~6H%+Od z68IFGDM&VaHs8WF&pu~cR%a+khmhN?>R+&}jkMzwc07?51E2Pn!Q7a{w{nkeAn3b9c=qP*mjrU zq}}g4*^Byh$cJ~;47KgCny*qCrSR$^39fc)tRh04W^7O0nxPO1go-G3N9W56_7jNZ z2S{E74dg??9-53=m)z)^s-T?4a++Ys=VX1)s$L-a4i8)_oYQCT)wGzekQMnXUQ|f+ zI(tKJeS%-aSBfK+)!6FyG1V|%ZvtkY`w-3TMd?8BPeNMCy%)+i zDE~xy`y{G*kWL_!fmU)I>ZKOB^5~+Gir0sr4S2JLd<=tV*Lta`+z+LuPLrge&88(2 zc-f>-jE_`HBrEodsLMetG(ucejT2Ow|;M*%fHQ#N-on2{I&M0Wa7Ite?~ zWOgmNf!>w$0c~9X=IFTOQBAiHOQsM_Mmw&*2^6;yb(9IEfJSLh;=l8d$!AY1E6&NE z!yl6{1JQ)u$JP7a8F3 z2)JhWji4K#!R*19py8iR6IGGYvjhc#X3KB&ohfA-D}z!W^j7zkoMWsCzGrC&UV}^$ zccL!L?oXC;F;CU1YVb_Si_#^f;ttOzn2oSDyP7PNw8ffpW`d4avl2$1qmdqAh1h=qxy2bFmZ{FM@Pxg}_cx#Lye<=6Wsx5GIKWe~N{fK_Q zBG)U<|A@gX_l5mTY0WSV!esf!2+r&$M^h88Is^)c=LaX^P?<%o)JR7(RAPTwnMJg| zZ#I5SkFsvhvdtCfRCY4K>;v6G9LVjx+;_#;p)SJKskHTy4Dk|l4)3$w$8`_RlQmaS z2K0YTAEKL_C7TIlW3Y~N>z!N4Y~h{+8=4D~EM#$%G!P=b?MSw{_$PM zG%{|(b>`O^Tf0{Drp#H7-=y3znfod;qCz<@_Tp4X>B__Mc>VDCE4yvb63GQ2ZgW~q zj>UQ&F01(E6-28*+#FIhFBQYQ^x0R45Yg1F#UYC$$n`gtE1UqQke|#Yp~3qhFIB z$r5xL#t|792of0!aF6;ZPprk<=MmD7=?vt7Gb&-5DH8&#RF6Q;tVbJr9+T5o`B#(H z;4o|}p}QC6Y7YAT%W<#tCg<`Z3YexA!*}o~0S)ReDG9+y)e~%PY8pkzo@x3E@?>MD zd#On>0=gYV(Ec`30+1wPsP0ueCpK+S)2?dzAFxWVTcXpe}LWSO^0c-bjDyBneC1RE{lq{Yp`U|im zZ~$8l|f7`Z*qEg>wk{@3pJAt4~sn=AOU% zdi7f7(|i4G-uTS#Z`zlD61wW}aRN5JW52ftdi}v(wl=BED0#C79NfR{hqg(@*~X4( z`?2lx7*&Z=G6JCJgWfFYcU0&T`=v<7EtW1+;(n*9)p^55FYJdU@7ZU2_1T_%fvr-! za0B&`ylSA`Rc*h4mxZdgpoGLOEVSxBkkB}=7jgMx=2vNQRjN|yDKnunEEFf#G##Hd z5rokxklgEtzTJ}Wgi6P_wqe>5rDKw_KyI)jt+!2 zbec~M>-hAP#ao@>r7;sVEMK3u-JqbER6kxChx=`VbSC#u9nCkIKqxqV$G=Nj6PRyI zu-RH#(tKkv9$-A+KVyE13jLU#=npw4E9KECXHABx8d1jwk|`a0PU=_kCK!%gLn>4V zb5eWM!j-%xzD26D;*Qw&Moh!~*KyvEk`0-%4UBXbS8wsBs~1hPg{WDnls{3dmXbU<7+6s*Ey?4Uq_T#o5g9 zO_Nqe@#?#*FK&a}3h}Zv-+f860;tX^Z$st%sL*2eWww_MLdcNY=P?ns?4TYyxaWUU z_8tIMmFM2?dY*UfGL?auVSr(VnV~m97*T@}B}7rwU=kHkh$k^8<=lIclkX;{=aFT>t@?X}l>*IS@Ng zb89@y-xuG%biA~Ny>u+#lL3(!0~Nm@M9f>oA%R&KR%tUwV>j1EvQwYTm%s8LPip@j zo(RbTeuhK(W0Mg(@m!NX)x<`D7&h58P4+;OZ)<`Ck`W@CJz%kf!cj3Y7o!`KjcOnt z&g^Ap^&(vqS+64d^=^}GZ?aQ*`B}Ym;c_B>l3KEL5Hgmbim`x<5MdDz9GpBwD1RrvqR7R_Fk_G6;)2E7mCd^0ixu zg#jZpQ5vcq-5h?C@_xwissqY|l9L?-`Qhntc7wLeQl^u~h*OQv3Q288a*Gl%$ac)g znGjWWZLg7=N_X@|?AAU>ZFBNE7nL-gny==lAgG2Pgi`iOYI`S(lp^tW4FQ<|YERfH zxs|}$qLtLz;212`O@*p5BM%o5MMu7tWSMTfz9FpDjimnL#*fN3e%yoO%)l}!sfDe~ zm_gnPT~w%x9&OmkDt57&yPU%oCYO7{z#77wMw^Ydmy>~yS|@ZdZ?81i>Vlou*M8U6 zm-l6|b*aK~3wB~(d#~9}?+ddR&S|u>xf9ZTMk6U3z!tX+Q9d)j2)YavqFOBfLme}pb z8pDf?_E(MYk;bSl&D(vA8s8^+v}+gp5N3&c(yL{ck}k+o-dO0pn2 z)MtB!S9;s4y}@nI_YB}v@o>s%==OXzz%4x){|T+7cF$?G*ZSII*%MTsl~>whKhRGS)QN ztg#BiUx2Ght6kaZ*RH8Wk0pu7weny|RRBb{(gzyic11tGrXRBgGU;b4h)(S1 z>-yPAt+t5CAf&OMUC=LF(hntZmT7({E*fcT)RskV`ETY!{8{t>)^ebJ1ZA?jYLjQ6 zSdpM=JD|#A;{MJyE9^YC6G{uojyCNi5cm^q_GFvA)aGxtvG_%pa5X1_@?o2;YqLML z`FZW$pPlyS^7l{Lyv1%Ue|xqK`oCY?Yz)GOWRzK>fZ>RE0*2#D8lpn-dOKYg21Yxv zbFbyQ7NwXh?w}u!wcF$E_SbfQxt$)#X$IX%yRB`vhui&~c1*q!6LP8x}GN+U$wNWPJytY+$LLZ?_lP?TdDw(?L6A<>;{a9d>4iuj=sgJ8W48TS00u z0f1y2c$uA}EUV8Uwz*=`+LAme>{3TZ&>{ig?Kwmnt{2_3yeycD2`Ov^eV``j7T=p9 zQmIPF7bN|$+k6tJ*#E+;`kA;z7I}8+^Tj~_nDgIJFe|u#Evf!+`49c)_OtN+a7V2w z@b=^MYzseza1~){AzkoFkS%%&7RlaelQT6k8MED4acPZ-wh2)YzQs?oq;;_+>%}t` zonXHYQm16>f*hv4_bou{@^Ze>r&MU{ib5EOk|$gxozm4YC{T|;C=K7nG=t5T78>kC zoJ(T{B)(}n^#?WOrjWjsv-!DjLQeI6k$HEdWM&C3n`DKTExlgF4Q+_?$?w?y%&#B` zQBHcK?46(UerEjnBdTD>qB5r5^6f(vUWPP$h$Nack{V4bpG$i~-H=`JBrnYoa1N^% zqJLUdGyr&^Mu<@`%q)>oNMagS@Re`LZh~J@&dPLZ8pRIkT(HLC;~>!q#7tJd{G`f8@iC} z4?Zx0mK0V3Q$^@Whf2IadFtXBY0`6mXeF{7?2Eh?0#+6_ref4$_-%orjDA<} zI|H$-xTKMx6IYPnl*}eS>eK%f2;?v54wi2w>aEq~TE* zqWC-^OWC?IDtol`!o~jMO8cY|3~+i?3HdFk0#=2{Q?!eSSlL_xvB*ZCin8x4SctZQ zJXD*QO+@{OnKH@azmwKBT9A6A8+Zm33+f6e?E{sxp&-dEcw`ChunQpubV(+>ld8c% zXdB7Av9W0P7Bd_)r`l#yQlgsBI%>YPqqg>jsEyiKzSdZFdNM(YT1YO79 z0|NoimqocT8G>jFDv9AYO!Kb-1G_Y5E0tmpzglPrlkzCF3Bfq2}<9@6ctqS2Yb{swfCsZvUJNQI#o;guHi{XBb{ljM?27GBDbR0nzy4D_`<#i1Gqs zMnPA4RLXopz%@0Mx#U%i8f^)V^3^C|NVgcmr<%$mw6EW1ksLmOoxLbk{gL_liPWD< z@S{>B`m7Kx4Ync(5AJ4{1iLsy-(z&a%p5bqJuet4a1@{1`4Rxf`Pe+*I5+1JbnPzl zpRr-S&#eE8{jcyHxW2Hvrtf14eVGnue+ZLk%mO5*%9cYY?PG&aS z&p7V#oHC0+GSN(?vidxd4?7epB2`pc+T*ZMF^^l?M%GyTl5nlgMNGhrafdf1Z9S8H zd4k|h`ZsDhN4Z%kF}k@@kJriBU1syD1n&I*a3u<ksRL{ zrs@I4z+j)qUDxnv#kZX23dbdQu1Cu;-=Y?sj*_RjtulF;xeb@cntahHNBgK;B&4Ou z%-liIGvQ$4GfhZH#~=Caw52O-rXRz_Oc2N!rDo(uBlL@9LWKcqM~9$9z#-tj9|emP z4HY$B$;_JM8ljcgB=aI2n0#*F2zcxQvlBsD&$2Y&O^PJmK?b0R#N#DQBu{OtPG;sy zS8nG@c(XqSdo;T;dgbP|<`KJGV988p5Mdwaj8C?M!oj(NERL&mii8^Di(Jut=M}wT z<0J{BGX?HY175ld<5RpFgRB~?%03#CIoh6=1iy%dvIkV>kwGjC;aq(eJc!{9#Px|6 z9c;f>{l__YDh7jX7Wr;XUvPgOFiiiA>wixAv%GzW&2v7B>DOS@_HbWxc4Edz#}7&~ zrZ#UEoBb538P1D&t#HKvbK-!V`n@VfW|O(H$c`bqxQ7eWm1VBX<0(}E4xU-8@w|F`f{R$K87c;UiH3;hG`uw#_xDpVJ1 z3PnUJ5nr+~W~v8(U3x9;D8hZ{kr2LE(i-@lDrL|wMs;0KQV-#>I=5F;5v&JCRoE~e3SMv@$@NB&L`)5YYWBqgpq>rhy^zdIvn6Bs z$J>EEx%^pL&_Y7+sHTbHoj6GOP4Zp3I%l{)k%ygcqNDgKAwpd)Ds89bn3^>?q`gW_ z2J{Bcbk>J2a2aeW06D6WA{E1soymxFBmh?35<*%d=qR5tpdteEeykfTE!3+kFR zCrFaiC*9Djd^;ndfr`>F1jZUpg*=l)EVc%?x_%;7+S6j%E|9U@uFU&Nu_Rx_bUo+h zeU%E{HEZM2`|cbQ<`S6=Zi57udLMZVdSAg~<=Uj7(U0T$X5%P+r5pL=BVBWLN+;ft ze$n@rm391{7)ygin8Sn#YW?(j&| zVSZwXN!^JJm@QBXdQ>@qnN`WF_#}Y8#43XWV@b=Y`y?~T@+Xb;SU*^(sqi1+-z~m~ zri~a3m)!V0|L+)@y4iIWZZL}KktEb{MUa!7>d3O)->>v@loBG(Mt-FjJ}TOWdU*DE z7wOfjD8WnYo`yl;TKryzgvTrKt_aaVl+LC0j*^48jhB#uri1R*;(UoBUH}v4kf|(a ziOHTUjfq~g$Ffr^em4gPzH=byUy|ASKd5GYk?_RLbCg zYB#18=V$m^s5AWBsHlx}Ygc!`{#@otd$6-Bk~VrKi@F2F@aa5n4V=qNYK}q@nFdiD z0XsZZ6bmGh>VuJ;vuW9CI-SY%)u--Z?^NuZt%R7PJ??WOqChPX^2c~))Q zSoB+XP}dWBl%MdXe#QHl@?y8w`(5z~!rmZxJ>g~pv%_C_%=}47Gk-CIX}ndsSQ^3Nlo|!St$3J{MHb5A4b;ep^e@t2F`hAoQ?be;>kn65OMa>1~5J zqj@X11VwZ~;ua~Rob+l*NE8?QiFNwqG%U)tcLW{gI>VKi8-yvPkB~WbvHefd3k&ll zIhgS0Q+pxh9q3$dwk)Klfzx5qAiuy#Zf>x7V1?WX!RGS`)y$)4qc8DQ1mHbKs0|BP z$-Lh#ts~9s;8JD?-Bc<>LKubCo!|rBagd4yh_W(7z?%YTaby74<$0xye--&rrG?V4 zGrxHdtD@D4NLNFN{IQxroDsSek=brPNXF!l{1p!ner!L2O!Q4lpG2IuLSIW7D^X}` z&G7;>T8sRqdvt8&>woM&f{Jrp+I3w>;8s$ExNB06aol!A%E}yrkI&D@7boYcU)ryP zj}h_DO9QD6@E)OKrLY)+w-rB5x(SUB!i`*pcb;u=djY5DoV}TIa+tN+hKSuHDn9BI zD6n7p&BTxdyDuor1^M=Ji_b*hzt&*(76m9%q!(& zsQo}GArJ`;s1SOI!crz=DlRrZoD3n%(%=G3k=tj9G3N>=Mw12Jg=mPgq;=7!Usg+0 zKqN7qHifLt)JE^7uPjrCxNL5D+Bd_?smI}1Y{%yBreg2MZBx@ zty;jn1Scpgeob&;h}hp#Whw%)rf@y(=}d#OsefWiNMEfu)|>H#v3pFj{Ratrl|ly0 z`1@qTD)<#?dI_3H^UEf0p6dP|J_0NR+fw44if!2z!iXFQ3eT?aL?%8!(e%OTP&%Q4&bM z@9zfyMTgqtaD*Kh2a!voZyw07v^y)40iIk15gO1VA*mQ0Wv>#b%z(kOz)4KqH!K;D zqFT!R3hY#a3e$gy;-C8FdRZOzFzoB$+JdbucwM-?%I>JLhZS(WuF5Z09tF;RTJ+D0 zIUJp@L2Xa#$_GFK2_dU&lOfl%x6)XSLQKrX)5 z)&3Jz=uPbXD*vQP2I7L4(mH!rnfkKlNwdT&q!nL!B9XW_jl^etyE?f)fZ zgsecxw<{5X^{PmSI_ZgG0BQ>dd=oZ0%aPLks;mgz3Wb&C(CD5AEeB%IYDtYGXFixn zl0af~Wk{Rt+sU_k>AQ~oyC^Rs5IBRnwd%)ERluH<2-kJ`nBa9P2A7b}imT7a1p zN|0ctcTr!$>yf2Thj(M)3a}tK??i~hbg1ATjB?^BxRiImj^P%;8*u+<-ZNZ+oD9;B zX)Ef;F{t8nFh5sF7Zdu6+O34j7%D>2z^yK-d#o7c0oO0&IJ; zlX|u#JPH$3lEw?bwWMwq+QRJ$}eAQx+FrOC94A&dAV0qe-?FKJV;7(PFGsEO83nP(A7+$qDh~04+E-Apt&;FmXdOe<#6~tG0}Q@NHjnBFF(#F$ z;rnL(I#gN1RuqT)6XxP8LoP7A(1heH45AkRoYfAvz`|?d z=enhFNC6F8;Uu8U@FH#G(EtZaJ~KDEJV-#QCJU6s)|2lv$K8U>4rU*{eA_ zA&-Ng{aPu%9+kExa_9CFG4s7((W^rX27YEhb0AaBu5*CciaRtYKA+Fkm)Nq3YzBxZ z5&|kD(~wzETc8Jx??7#PGOZ(-qrj*!^mTW7B292#mPS|yZ8P7S*px~RsAVG2c!V*5 z&~odSOlwQXDccK85Zi^xA*5f^Z$%>N>qKkd0N71*8WvDDwKXTx`X3E`G(Y)(rYpUM{5E5y2= zzE^(Fp7B`K3w_V#s|1oKk*dEE-kT(D9v?mHH6&8Pd~3= zo5+q%Ch;`61DiZ8Jl!q4Na3e$zD=cC^i1WpWbX;9Z~^zt!YVS2_^^0mK6$-6>(gde z*M%GE?D{%iUndn}ycO$-(6DZlmTECAP0O*|`Q#Ix#!}y|e6EOr!l8PWST^nzfsafE zH|;kxnbwbcDw2ny#Xqg4z8>w-W&^9nv49z;BYB>zuJyHYkq|akiK%4uhJFdo2}PUg5dVithKWr*h&Cd3D;}`nG02p%krFXqRq!4@$@c?VBV+*{aA4Oa$u&Ddkh$M?OGa-D<@^xZHSzju2QT+~ixz_$YjK%+>NU%?}jbMHIpgq}-YiIbHK&`@$%$>TEzGaV3PJ>A|ojz7tURh(eG=MQD`^H(E|9_I)j0 zUnG7{z<=tM6VY4a$2)=`SBs198a1~;Awh(y>m6?nYdL}9M|@Y7YVrGkLsULzgF%eq zS_-BLCeV%}ukjCxNVOj9dP3?^GsJABTqy3CpLp&wrO%Co8ornv3rp(;`ba0H4&(aa z$$LDUZJ}K)hn0-PvMaEx$`flZ{|UczG6xE1k&FSkwl=AyxmxNYshGsJ52U$@1PzSZ z(sV^z5;M0EnJ6q4nNL6I?lgqd|KA0|X58@6Tn?(f5M!8@`*ARHcSkRQaB}-(N86{`WK(I(Jegl>llLI^5DQ%6I9*D#gj+~lmJO65 z+GwMbrCLOxI{u)X6%ej?tRV={pzM5-eLp^#R{C*(4k#~FyWEaTCReXSuVe$qdS{VW z?by&shAGj|PbP)mPqOusXz=Pu_9vIlP#m2=x&bvn_DwWMhN@~?!Igf|BwId-C#LDe zlh_Fj0=jt=okb^iw#6;MQUT`peJU;5Nfs8GPXR6z-!KyAT1JXxoyn+4n?ZeIMEVQ7 zG6KP^p&{H$sUKS>@u_~~UYo@1p`liw0y6@5ksL9Z zoT}DsoRrChI0Nao*$lh;7}QgpVQku2lRUx&a1cH1-qbgy^q9OuNK03yvO}LlQ7L~x z=>KE0{~JvaLg~Ek*yw3~-418Fx$fWboBait*IaXTa`G&Lt@9G^-4M za$qs?O7&IrFH)a{DwQ8(7LdahAKKSi!~I4umQyX9Vz9BKu?q1x&)u+x`BMP0%#iD^ zTKKCO+v|A?FJ{NZ@O;r;zyYv|k>D;ZBB{NYrkEpWUk(XQgcsJ(GI7svy=X9SfDm0# zq~u(3syYYiTCC3q;TtG)GnpRk?3c3Z#P3c&5ft}B)0|ECxBc*{*w^OLnc6s#G+Bm< z*#a)lU>!{Rc$9o#;hcCT8u*bFKSI!prD&0U=8<ad8f-=Oxj~CZii^V=C1t7a<-ekh3q-Hl$bdudvmSQi zoBNPFoE54u_B+c}4_o?GDUrm=JMt76_eJQs==5LmMvjj6qm+m)Ebn)TG?Du!?mn65 z_+u7Yb`cfP+LN?SD7i~quJ}KSiH*r75HqMfzEhi)V}LZDO!h_iCbIKh72=+))d~rf zFz_PC<0~H$G9t%oXOUHVvfwv-TgYQfkL;tE+*LI0nVq*en8~X!V*{;dpKAP)B8*KW z6-uqp;#7;Mh#CwxMdi?ciJm)G5-bqWVxb2j9ihq5U7U_++bMmMus|_;Dr}V0pU)L- zi>mjk4y+)6pot<6dQs*{O`EbN#Jv(XHEa-VMV%g5JtkLPC|zN9_@Qw7R{u6j&&zE|MG6CGpyFG2% zxu~f-Lo@|s27&T*P06N8o2W<+9`5&;Unlik`BE>u3jn~ikTyILDm%Z*FRZdlt9*stO}yQI`zp=tnQX_L#dlCX zmP-oqk>#k$S4kk1Kn5}4)y$k``AgE!EwAjQ1eNlt#mj>jePJPxo}|O5HD$Wv%Au61 zsg8V@;;H0ijVlvg3on9=*Q8^`84bK;NaTs^Ov7?L-IDDt4`8Lf9^o$+CC|zY`LAx0hf*gopZ3;j*(p6_m@^~#ASX{KQ1o!?*HlQz8p5Y3XmYRrq zXGSs*q4$tgEu?s+`Pa=rXvyB8?7^*-c9CvD|*1 zOs*>3nlfYgh^In)&&Btu31PqNdkK5R9%pCrUB6}5R?q^~EpZWode_1#onCF*tL!Z{ zs}TR0)i?;gin~wbD5);{P&atYKgKGvpb7g+H-EMp6Db&kCu2smYIvF`U<%dU6?J}< zYI)c?BEM_x!&?8O7TfS?b$*7J>CxaR8J+)|>wkkBAB%uswL{%#_tp8PI-2+qE;*K7 ztd4v@RvqTVm;!)Hd8j2AJ4=Ir#*!*nGh#F04H$luZ#X`3M^$Oo#kl}4QTq32^Qt01 zO{gyR8yi=a7Zx;$S=}3R#8a`3y}Wl3WX-*-#FrT~-i3=(Zkg;TP)|o(B`XS%vvt0f34#Y{16RmG z2jmJWE0f8!$vHi2wuPn98*>iYHo5j_WKsVL8_>m8>2!{!cV(F3amFTLG0?+4tPD%5 z3?N=s1t@bI#Sc`H+S;d5vxD}!O9!Jalo%F136qRChs0&2&ZE9oduMj{Gw|4n9a5iR z*+Lu~jEH_GzPrv>sYHwzZK16V7%Je=OGwy($trL_HLr#U(O9cWwD@u>%MwNSIbnygEp?6n7g8zt?DL# zVw8~uk9}nv?9Qj_{n>i|OTBNax2^TIrJkM>L{V=$df1YBe}+=4Y=al~_pSTeDfPZw z-_h-KN08a95Vdm~V5U|!*b+WbyIt78xdKsHeW0J!cF+D_MOS|N#3-&YFVMr%aybDJ{#$|tWj*u^!0N@bUeuw|cDsy6R7vJ+E&Rgv|fhjeefu zgAWbU{o|VOc}*;e4b1PTiQZan$0bQMHhE-!um#o~UKNOCXbyx~@H=Gkk~!dGQWJkR`a7>mwAX~oMc&+dyn zeEUX46XA#T4f8L9wJ-cVPuqTws?PoroyWelJ51MRlFOP|Bs4^Kd*Syu_ zYst(krjNy8m@5Ek%wAem6d=?vPf0zGLs7mclpHCA$ONuzWDYB>Wv(QE%5zFlw}4Tt z*H@I?OB96AmzkH-6UlSIxL=aaBgREOmt>A*I?h*b*0F+DfF5_v8{eD3YUS@G34<&k zQ31h@>Bbe+$p^jdT7kq`syr(LR=BoDSgTxD*T+QeIMUzI+aB)ikC3fQ=!{v;+ehR7 z2Iajq-d}69*BirYjp21R0wa)x;)&jNVQ>3=Z{N{7%S5&ye%AQE!FXry!@@W$ z3&{-oOvKmcXWw+{R#mqLI6oR~B2cxCA8xB~2gm}0L zw3Wm%fqp|d?G;-j^eSP%ijoAA&nl*P=x+n^{qwyFvJ_daMmTV?@K{l+^%dwRWhvHJ zf48UY=t;O4Ql8IlvN^>1*xY8DM`D>~KTGynNzhyS*p@!_Ss!263_^}#4ztawWGW{# zs@isR4Vk73i-_4+Y(MyWG`uW;wwI|p0Fq;iHk7wy@{t}*Rx z?p^HL)6Mowvu$nmH=7aOKo1}uI1`~dq z=n}LpDkqr%lG-96c&Een=1RP8WtL3kfj<6FAAgX{pnb&s5yN8FHQPEWku>|dW*iCG ztMx)>FdMQS^LUX=L5CI?h~!;|1p4u$S(JO3EFnZ0tHtO`tkv>|(qqAxtx-Zp)X|LL zeQ-*%EpE2k``BH5?ET)(_LO0opSbQXt^T6Yu)N#HKER_7N2HzId%1UHt#~rTn56W| z$|O3GK>&hBEJ71Ur5;9G&vAo+#;%zNof?I3uLNbi$duT|(q7)|tD60aW?S3LwkX=2 zeQ{Xwd)xf}Hs;{oW<2uW>q7@`ZSxgv7(x2m`SBRe=?()WltoA9yQL|1v-_jb*ygg&+aiOm)c_j`K=ua$ldoPI*oqkQ@6T zPJ7teVsEzOdfCYxwy49FbojCk`uIkRZEuNW{?m4QwcSqW@Jl-EwC2EaoCfT(xQm(@ z@7c}ayk8#0Z#6G|#VV*1n>l-l&=nb!1WOE4% z(H$;dijd5AM+28V}2N3Q$| zW)ba7W1ANapgrj;i}q=M+tJ@n8sLitu;rfaZ%_8O_xoq`ZDTe1hK$0k?4QnUvw3aW zq?nd7&0{6559DH2!pSIuf_D@`%mxN863dG%Nfl{ol1&4+?aPbE(h&I*>6U0#xvyQk z97+X_bG-9wS@kS@*>#0hIUC_F)T}z$Hoz`z3HP+v-6Xg2?DOP;Ju<+a8{jVt0KBxN zsrWS3Z~m^W|1N8J@mSm|wUf3Euxkd`0|We=fj+l2ENoQ*p&c#$aSO{nztv~A+x&K$ zJFs-sih+Q8mX`YFc3a=>SG0yTt+pDC2G?KJ>OZjC%Pm5%Hn-Tr^ogG~wfJG0Lq9Y^ z4L(0LV#8qrNgA8WS5}2;str}+$OGq8hMc(E5s_#50~}XNu#>q`Dw6~JH85px<7}vF$S^I|@Bn^_ce4e{XEqPCA9F=_Jt=FA zGt)UU%1-O=FLq$-mkvP2O;G`}UubTlJ(Lrf(_wTRgvdzG4F_AoRB|?9d4OuMl+tQ& zedhPUb({dGF!LZ9X8!S!OD~rAI%=`i;aw6Xf1DY1QE;Xid(fT^@cyC`QxDE4QpCMw z0-W(_<*ibl_b+V%t_?HR7GfoQYkm{$?-YLLIco>R=5W-lsXGoyVrgI@-0kRo=IDDg;T z9COm-o1!soJeo{!LLD!eAVe8N%Y{*j$u=e+JlEg0^atT)fW~_Y@ZD4yZtLy0_Lh2b z4!{{6>u-yhv{39O3QMahBK@^l$T1`vhW̱-=hH-7PP789Nds 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°eH<4N(3T>H8W?7DcO>#6h;xxSfTH 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

`{sU>qoh6F&0#N`Qk zIR?kfDLku+vak{J1IG*7k({Naur0eV1#q=a(1H7~aSF`>r4Dv*l{+({g5#ajl!#TY>C&&8mdH4Jg5qAK}rmUP~ z<`?R-D+Seqzh)nQ^*+YA)2`b`8?}(xMMZFz-zOb8Fg=*l$x-`6>;~w<-*i}+xS$ytUwvX|%bq)%3YnNQ_Ks|r&U`iz-3h@qEP zCh~jQVW@1@FwC6Jo!`VEyfw9D8`#y@37H|vAHdQH<2Rj&7?Pw7IZ1ZZqe7!d4F0UI zK(30qlpV0iX!;iUz;#0ys$nDEX;K;nJ%w1sNUbQ7&*mwScDu!wE^%h}hy@04N%OoJF3qGiZD4&UVbsVZqK+lk34*n}GSK;}S>; zOE!slWsN0R(;wUeDnd+pX7YRR=Q;*kO5GJwqE+J=Z9Q`sO%A9k^$ZniA&ZA1{@F)b zSdQ{mpNn{ER|c-yIFV!s^2beSnyQAxGd3Q8bpgO!He3ik{f4&&q(i@mJ9n&c=SuF} zwZ@$#+_`6sJ4?Cq+coao%$+~1ap!UF{Ea)$)6!h3_#`d+k?oEJ^%d^7+jKt9ZHX!9 z)BHMuM+x(7=kgBs>DR^ldP%%OzbC&Oe>ry+a1&)#BWqaTO&=Y~jQbOmKU;^%E;cN?=nReMG&qF>7Cds~RR$QS1kIobu$KRb_8sn_W0***sh$Nf zMX3s@%EfMwt>kHv~>3cfJiPo|bhXxSJHSUfNKZbJKN*A$f&9z8}PWJ&BB zM_>kpFiJ&2{4;>iVa-S!{A( zY@y|dvj^I-2ih?Q2F`~c7>+&=$jiq%l8MM7wCAhD(E&y@@@2Cc%lq(m@!@DH)#$~e zSM_9o+q{<`_Of{SnS+@zK+_Nv)cFDW!2lR(k?TD&zo>%oRDkSHn6}zeu zw!^x>d*Mkv1IMY@s};ulk36Am1cD@gpcQ9ri)C!%JqR<`UC0qVA_T}QV>pvsESz1j zvnqCN#h+HSUBcG{Lx}Rz1$(hze<_4N7W}ph6HlqW3oCY|>N~Ge-Xh#vv3n}^Ld8E< zDd5J9)gG2H3%~W$6efwyJxzD>adBYhOKH9-5^&Ak zz#dyopQ?l*K(a_W@XKm`VNK_R`vRFPXy%E=b!frn6g+tVSe=7kge2G_tlGo=xQAc0 z2VdpWJJFA~hmSM=`#6~9Uu(bhVirAlCNj?vZ=}TxK!QD-FhC{~dTH)O{!2$q(~jQK zK`n;qafxLLn-Js%82x7F73QM0uHnYgMNa}p#`Oc?T#kL`~?_7B$WngbbY$l2{Kox)@vh5{{Bx%=r?I_0jsCyJxs)PrGnWf6<-{ zovbj!pvx?p_YBwWX}{i6mCQqLq;@cArO8PA6(^X#67|3-Cs??E>vQ;QbHbT?{~K`G z$X~(}7xV2>jyK{RuIyKQTgWF=#P0tAqteGfZNaA|cH4bUqa`w^&(CvcQs{azpQr`9 zM5dtN$nr($+4LulD5M5-Na4ud)-$|%)du{`DfWADuav?z}M|LN|T zd5*nip52Az-d(Qc5b=l-qXvyJBryp|Oe7{IXriJ?44SAUA50L@AQD9dLA(%A@x}}B zh`}2#B%XMqqT-D=-oMwoo?Xx!-_P&+|CeQ^=IQC_v%0#vs=C@@g}PqMMdFP>HttYr z4F*ud%nar71eb7Ml^RI~kPRs|KaBW1W&NsiQswwDkqU|7kdu*l7wy;74$ck;$edLp z5*`fcf#_l%KFp8ci30-s<~8PK;8URwr4~sCF%YaU^CsWNZWQdxxCTWRpDYY3`?n7Y z?;PabKFGgw5Zuv|`}@cCr%~?RpJv}=^7Y{Uq5|&73I4c!G81C8-O;+q3INd!<*nBbO_Y??xJC&qp_!7L(cF3tgTOwqe_ zfAKH=#c?NdcZc5I{ujQp!tmpkz5K0v*$BCFFMk(LuthsT;Gg-KEQvs!|;$NtpK_$hZk^QWL90w6}YY^bYlJG8PU z8XqD=V41;hIVA_DOzg zOqiGe^$mY(JK-yxa2?R9X>UcgsW9n{>dbOm|9#$!b94Xb=l#*h`h{`066ZiF-Q6nP zlCIKS098uDEs0|V)!RRrgymgtuI1QF>uSg#f3I{l^E!hb zglMa!O&+OMSgf_=IfZD%!L&xPP1Y3}>%|73zmo1M>1p*{Df6cP}?@FE@8DKYuSNWaU6t{1~z;CbR0k z8&7+>N-ph^Dh+BeEx4&p=uACh#Dzx$^# zj7i@N%b2AwAe1Z?e-5rLy6aSuS*x!p9J7J+Qtp#u@Y=)$41(_iHyp!M3B7;!7w)}Z zxOacyH~a##2-Ys(i~Kv#hxDYeQB^AywR~V3Qk5zp0T><~KVK!%fa%7Nku{K16Ogc? zG@zY=TjFa`u@h;FEUVf&Y*GD7hY*?NFJq)Fk)hB>&VTy*G(~u!eG|EEoq#0;#4D{vfhbzEuorkEWbPTCXa>MW-P> zQW30B%1_y226Y-{gzxC~v2IgN=QdxrGj+R)!!O8E1t)E~iA^|F%UDf?Mtj70#?dN8 zWa^VaNOTB>z9|B-=v51yLm|AMt)ehAk^hS3Ku@C$yr%mkIbDF}^Fzf3_eD8f#GK3mq%&8qp1kfCA-S;sEi;DP2yiZa+oCk3mOAveAM65tE`wEvcG`--hLyWR;hT&pFP2z z+7I_6$uCo_UN>q#4UtoveBcWa_eFgU07-Q()o~covI;C11M8w zzT-qW#O_6;n9a-vp9McX_D8Bat75-(JTZCMMp$^?R-FNrfpswaGNESCtInc4cuD_r z6782ne~zznrE4AcLUfRo^uh*rY$=%`cJHDFx^8iU!`szN?bA~QWEz8mFqlRvCbgQi z2_kIN)h?kWxyw7O+l5y8y4PLf3}GdGM5{+namglq7wG{^I4Xp} z8odDDjK{c*Pa%4hu@&}p`?-BRm)p;C@e%CI3|Pq2%}8Nw+;k!3St$;HZp9)$Ev`uY zIr_CCb$6u2ds3#Dc4EllSV|i~Mgv_0lB(mS=u)+$tJl3KqOX=y0}#Q$7Ya+U3M`J0 zw}?4KzFfpLg0u#I_4sTb>%S*^9wtJrxG-pvKRlk49L_>{kK*p7AG+P^e%O<|p-G{U zILu{8k~CEJidGlhMIm%K_BztT{;}&Iu|<_cR%s$v{9e@%);o_TV@hPZb_LjKf$TF;=wmEm8X&{_v)$?+`h42NF0fRI9qO%fgdjb0Ce2jN5% zx)?KLlEowol2IdrELKRqAwy#!=VYAvjW|#a%8`dOcW+6%kB-tF(W`2QyXwL%b?(+W ze@mUet1iA1kAti?&A^7bP_;U2!~vQrgk`i5d@A0WB-Dl}yO=@gag&m8zt#I&7+mbP zYjRJP-BYZ2r7(K7?A|T-_rx$nY5h#}^*GP){y6z7MI4_J^_n1#0bnlB#_%;(~DR3dHg1ihdiX~Eor<@qy6tZAkj#LD~rqypC0D){@g;X}30*>!$Voj<3}Evj>NM--m1Uofn#bI;W|?s58J zonK$)->eJo)Va6o9QQcwaA(!KGug?lblnj&!sE662|T@p=e1|G)%q5fs?0h#HD)3Z zonu~qhD;aXH~)(#0&!I z&S1c57z}I_gOfmv&)n@Q^j~L-2Xk-2!ti}H&3nPW8NyqJ;FM8zlv1aQ=hXZtq~}PD zP9Kvv&tAZik;1;DZ<*Sj3xTy3WvqUSrKswnue)4s@U=hQrBWAEdptxZk%oJqCVjYu zgX&4=vEUyH;bEm?Ci(iD8CI;kRhT4r!mRBi7SiFw=5SIoObTNYp$7K&awf4@Z&G(j zbGWpbBIpAcNJY8W#}|19Y3U*c=9%4zc5OF*9eNyheK&tYH+N+Bcxrd1kq<?L;BSiE&9S=^)S*^F^4JZi>F);d3xDaw{(PtrGMIVAS4(oEV+jebP)%%! zex2?7-fo|;P}&7tgpRajxH0z z;#9UZF!m5s>!e@7cJ#VcW<<&y!#4F9G(!uv3ha@%b8r=2R8w^wdy7!Pa~1J~$0!2b zt5yZ<{pILhe&fjG2mTv=O!9glSJ)hL=r_4n7q~73|xaS)>z2$ zjqMX))YZ{7(263Cyo8l_T+(FD_iXt_1*6eqCE*0MwzQr8?$5`eRMBbi^ni9WO0a8v ztXW2LIZTQ5BGk@oX;=)PCT6psYuL$lL)0SY_dOcurTU0t>+H|UC&EQ!6@^mU0yOy@ z(HgDWGP^sv^mG^OUVZM{4!z}U54xN;rHCP?B-L^vyQD<9#q(&>wto%gv>e?|nkt|gGTa{gZPZ%L17F7XHPP{=K2w8uevgTk zT0>JV;=>#WbutO5^my$+Db*vrRXlrMc%LQ z{*G#ntn_GNRS!g=RnDWIXE8}A>wWy~vi`sZr13V#GXsEU#{ENP5h55{Xu;xDpSd?h z4>FawN1Od)&F&GYAU3T`A8z&!HM=L8-Q&&L=Jx_#n%r~E?pZGvNr`{5**%47p1B)V z)xFZ}U*(s7vDvL_2GidBLRz->t2iTY2t)A|SANyip6}dZJN0I<>wgwJk!yL=`L|r- z(=J`(G7Bl%J&|q1SuS1RDi)(@{sJoh>sML-|6x}mGF)Y&!oL%(~{pP68=?*KD!Nvi$QSS%F$cR_?= zSRMQ$;y?5!)?T7SCN8W*A3}?%6Uu20a=tkDi-^aHwkE~7B;%tPW(R+=!XTXo^2dR_!6IvF zRpX(tZ1nI0@ig`uqf-*))k%LX`qjfyWn(hKNT+v{{XtB)ZG0*25o#_?7<<>N zoaEjj6-@rvGqc2DVqo?bd9J}12kWCUOG&k=Z?0{E=j|@H>WD{lu^Xnu0-`BR`|zt$ z$nhl%`7Y6&A#G?@oKj1nJLX{Z3Ets*^-glO=eE>f5Sx%rFV19=n+=K$Izv=wz@$Hf zyaisgQC-Q-c;CS3NO{6C4340=f=;0c9VENqdZlO+8Zp(8_OUP^?Vk+t14BnTc;HYQ z*FFrByZMF@ezSO}L$@I6<%Z}WuT^l)pW;vuV`17;ea#F4Ih0j4gpPJ&ku4Dq&G#uT zYR2+|zfM6Uc!&(}Q`pB{Qw=S{i!{2`;)wR?@{hU{;Rs7Xl9BBK{j7FYpM;nNjl{$H zyu!#TNYy?f0f zEyw3)v>h9qdUJK>qVnA}F{nZ;me?oB=%|CGl+>e}uLENV(P|_olA3^Us;?7N#INXL zY$9Lk12>Ae(k>V=Ni;zGULZcpIlIUXC(!bNvI>`kw3xXn4f6lM3n2__9P&!c%d3_$ zMkl0-QO=U%PVwL6yRx-vcO%~rZV_j@ZzA6{(FUY#LOUkBqf?LnVWFU?FqT^Ix{o{m zgkD0C-9<<+^uFZIP5pV|xDzaZUP}GTX}B^?uS)$^ZYV{=);b!^7+^)je9Q=-F>EV7 zgd8&&t<*H9Vl-L z_wCI8i#aMzSBPSLJ{A4`d@c0Mz@G{(e#=Kc6SK)^s1qqz4yVbB+K(Lm8~c3ZYCpC^ za6fiiUgpvz?rRbHhN_5-jtxx4cblbxx><9QyR_N8QSaB+r*G7|_4WReW`9+4xRUKX z$o1t3W^?=@sNdk~6R=EwaJf*?`*hxJ;S-06`kq1?x2%xhnHK-F*Dx?Nku%j_SV+z< zxW$EVfx`4xcJm9#i3NXB!JSGN3Ix=9@KQo#UE*%LHg<}~YT~!1GI^sSs*FmUJpJO< zCn=RplEG;=zFR{dCaXF&%#?r#M6|`IkIC*~5j7?uQ(NLi8fRvOGM|zOpX)RL=69Rt zTwRfdEPdp9eyr1kL)X0!L18o^Qg>lf&kLHkhwANmSMdZ%sFz3QI9XxFogA0L6eRw(+N4Em!V+sGwXcXbmF zqEvwhqoNOqz`08tF`@jyY*{ve97*8cytE;k*_zoXXC;%F*I4f6ZWIY{K=PF z)TD4ra+N$<;xK-n;5_DAm@dtRQ7Hv?OJH7cm-uiiD^K2EV{%eCh)y8%(1vwL`(SqS1CGYzJzK!5j7srEy= zj-{h#dca1;?h2P$lJ0W#vT8WgVTVS+d*Tp)WKm}<3dtG4of*P8j3HvY7Q0tt_gw5> zkZWALbHoGV8ryfIq1z<_+Ep@37;MBn+L0*&f%iZnaLNj%-Sk8=dbB)c#>NLPI7RIx zy?{ZIoP|DZ&|rmAY#|M4VOaKK#L1BzG)o>WhE@?9tKnAI(| zdu_B#MAPIVZX3?N+@6jnb!IqykBb+IWFkfNLv`fTM)&iLctrjo&sRJVO}b}RIK@$p zK8BDxTIXyPt<*HnLI(Cgs3mEOcU#IU8B!88Zc0O(QwWRjn*%}DrjAZy+kk*h^V?M@ zJ^1pqIC(t|cUQx12XIV8irm&|3z7!7sW zM&y9jvhGo7s=q0fChGoyUO*hfnt++V0jqc$`hjIQxXNmQebB!{&`6OPk}mM?94{loY4*;dLw;czUH2)|E;PjIH+Ki>RI`rP!SHLJ9U$QXru> zJ|x6470F9g!h)Q82}Toj#B_@fY5TZgj?NKu0#HabOzVV5T%Q?gK^tRxx~#CLe;L^as|1PzJX0l>8|= zEL5H-+f_RL)L%#HD3g0i?ryvs;KPWw*F()dx6Ie5-?Zqzu}A|vRCJu*AtZaG=y~Fv zy8DalM83YXF}1f!?(8zW{F!BUTDjr$GThaRn)p7SmX`$jaN1AU$}V>hhYjttRjQ@x zmM~PIT(2WiTm_>%+EOSW;d=?1Qv>c%Avi8Edz~)zgU-uLIOTwxlq#z+AbrNO;kC|1 z(3Hn4-MgVzXxeyo0z1+@#vEIyQ-)&=I=ncn0Q_Rpdm~(acrq-Bu=}nOoFj2pTJj&1 zG&Q)H5ESO>qsxA#j8<+^^O}Cle_Zx=l--K5KbaSPS{V|Ggp4X8Xq1?sT07Dp704Up zqPn^R`^AE5)k)1YUnQFm0A$IdcT^G~Zj*aW`Aw^FN7eZAuoD7p8<~$CHHJvg-O~3l z%)s+hk~d9oLQii~)OvhoP30gcO-@WyOirr(2B-WsxUg}e;@!sSs~nv!^uo8@@?!dr zB3pvv>Ych5-OXAEy;<&@g5HvE#oH9q5$7K5R;a3sq(l>Gf)=u`#$>zf-s2!Q0vT3t zVpVd+=i5Jv%$LJ#N^ zQwavhqB<&P>VHIjEtCZ>Q#2P-Z6VDe|JLS13-V3D6^39lJR}*KL~oHM{o>sPNqjzH z859c%ECD~=`3#IY{|JZg=`2eGi1<~e!y&$O0c#J*=IKu@k|_+A@ptScGupf$oUE!5@Y4!1?VpAen;PTA-k(!&7vpf7qk5n@ifXG?S6vx3OpYKUEez7~R&NUI zKN2by&~URYu8giz-G?pNRNu=c!`f(;md40LVL+hLY{8R#T2D}19PE81|8Ob&8scEQ zvB~B{h0;;% z@$^6anAB`;8krn_r$c}+&5~;%QK}b4|eaEi3DmboQ_5bZlipB{ILI}!e`^mt>XSs zsovdV?f%hrzoy+k-JU$w?jF@WbcHbZH)Q^OjE~((xjzw415^it(_|;VvsP}_n1(o< zpHuCu)NKaSy*88b0er{HqRa4gv65^17mZiZ!MF|hEc;on3nKFF7nPm@V zi#hRz;cOh%7DqC>0y{f_YIwJ>qGrv@uA6KrOw~pz9bIeq;OatD%E>qm{L`Ed|2oVD_!9{ zT)W-VD_nfJPMjiyySVu)T!ClOFJ9s5t53-l49}^|`{5BEI8XUek>4Y|e>iskEQALO z?ty~4zrb_6nkAtt*S%D5FNcj*|%`c>V4O3=pCckuj24T%COQ%wEMdmi&UHfAyd0m71dTx4Ns7w}PvLpbf@ zaWzS2jGB6^4N-;S6`@Itm1YQV9cJD!Fc4Ds&>vk}QW}wNRx^^_J~j1)vO!~~OnxB- zC*5TGnla-f^5@+ts?#6~IKV)xZ9cqxR^QN#0T(0tFCobHFpQjbY3Cw(of^xgqCN=p zd)xMa6eF(C28+cNw}k!uo}nCh7@ zs0u_OG=bAS&dRct?%r`QDmjQBA-V`+^#ZaBqEB$yjRScW_H;{7udN=H~dO=5TYf zzf8O+JUu0jStbPbUF1yLlFDmb!2u_75!9k1m)Hf=xr$}?1k)hwAP@_Em<9De@&{-c zr6j~BnI@SqG@3jtS_>PjajH>@Bm=1s2-yH4NB~DdVt6&mpwN2HUo94Cade#+SSaV@ z2A!fSb!8CKCOi6* zQY=ZHVP^fF8bLiQ4uQRIzcs5TvHG+En>slZSkl|>u1DPL_7lP|cb_QfkY@)Nk|K;f zX>@64Xg6^?eqP^rZeRaiA2)Y+SXA%c(Sx5i+@CnypEO*p=PnqAVek00(6?(5rm#H)7;H2}^@{KdSXm)Oy$*}a2#koek< z5>HFQTv4OoH;}H#&kTKoVc+cPH>Zm0oTY6Rb_`NyAGfK6K&(x^S*r#;a(p7zo|aCT znPtb3FyPtBC6i3n=$qFUbQCAn31jEE8ecsQA^-1>m@KzBem zuyBAsu*JHyCBdh#SYA$)z(J7?P|HL2xI4XP{iw!&%NO5(?T!y1sMeib>O3cxqlM>| z@M&1E5avGU!&lfsiB}@ZMElahwQg zG?7Qw?tPsv-Mh2FJ;*F>koequ8hE#OcqL|6XX(PTOQEp#?hPfXY^R21Z& z8ClO@n1xgRx5~}Mq(lUXwF8nLvS*yoqYym~9qaBc;yeL!SSxfA>Oc+(UOFNX79EG8 z6`Vvn|62CI`EJqVp3%!z>S|Z1{b)T2i!{kYoi(Lu?*XSoP^+0R0U}PqD#bN%q_hYd ziI&LKtP0Ihf(I)`m+Au|8wUP8_c!Mxn8TH84;lQuWcV;E(d53-@hp&7LP#`5&j@>w zmPq+ltfrpeXZj@E^LjVBIhx!px=QiY8x~*K!e=V5wzE@WMcfL6jh3_boc3x9aF}G) z!aOePr8}HoA-4CcDuA|O#3M;>Gx=hm(Rz`smh)7siIzh?PSV!#h61eFG$u0{t0C=R zbYRsvxsE!=(Zl3N`bcfz$}qub^e@Y+Fs?^waPw?!=uxU^=fQcN7)r9u9B_xH}g>nd1ZGzk+o z#{Wm>s~akKW8!3D@Tc81+d^YM1Qo0&9ok!H7v8&ofu2~_|HTNPIHZ76#7ywhcI>BSY-LUVzy}ABIfaEavGh2PK^)11r`f_ z*J$!LqB9YyNvqC~U`4L<#0O(i3zA8(!{6P$xKe_Fs%=44l*lvukfLx#-=S1 ztWqF|hpd^lfLw6O9Ad&txfXGux(iLwZ5t4KIx#a)#5;;&XxjVKjO7 zXi9f$Q;l>Tb#oEMvcZqg*ZkWG(`mPa%5pY2H;e@^k0Byc(#+s4io>O`y98(8F~_qC z{qX|M%S+JLs73?HSt1Y#u#f?(#t2+73t{YuSHqBb5{%G)bDLt&qIp_i$5G&#T5xf~9f~fZde|PXVD9*hh zXwQIm-@|A2x6|E{4_e%(E$j{&OW2S6kKOmvA0T&N_J)wWU2*SKK(Nyq-TX$FZI0e( zbh8>MaWVaCqr)TP>2xw!Xe=+Nj&BC2GQKKlobO`qAnbdohkLn)w>zPaw)n?d+`TPf zWeX@IXO8>2udzq#tLf-us>sKiJ>6S935J@Ad+^0dNFV4H)^zhvcXOx$AMEM=*%K#p z3$<0}jc#szH+OD@q=+3as^D6Yk1!L(pMeCI-oM?$9mCcpiZYzt+d{mwPEJzf{t;?T zU2IdSpVQOLHa!&KXY@?Z?1|OKsXhJto}84-ZgC8)Nh8^U1>T)K*vR#25BExs;)gxx zwFg>AUi<6uebC}=X~7&-+sj!eAW+gl;McWyFo8%=G6{f2@~ksiB+3^fpp8V*AhmPJ z^Rt}SYMsId7Ef>l;i57$y&0n`tm`COjbr^r(t#;0B$H=(il(}-q1DrMOkt^Y1Et*f z*NACLze)}(su??Fyo;5m(fa5B6dcl2>hfl+md9*Y$nxm0>J^yLhN9g@*f$|bCglQwK!n^=bOr*bsGc{7D$=~(!ZWJ={x zep_~fdH0p_j#|CdZWe}0nkl3W{&sM%})?}o7x zG#;65o^0v2=+R15X`CXd6iKBwen|?^%3gQ|;L^Hw8}Tvzuwq+6R(0(lVS7__zYIyh z{qrh9V*gAJ{G)%`!+q4F(?9x+JrwpV5+h9CwMAdJrsL>L8z@|$1?U63&lw*o+)}gB zl1Ql4j?nZ6dqR5sMzY9uYe}Ha(h#`0hr6jq@%A2)0F$yXjfq9`5zMTX^dyK{ODp#f zP3w_HFZU8Nz=AgUouBA_=O%{eV}j!MoBf9zBGv4;D+%#*>Q&azgQJ^mVWFfrGNFJP zP}0jJZig3)rsF%yW;u$=*b)b$_L>5VzPJyRRZ&?1@NI||A|Z!QhLz=a>ietf?c@RJ z+BHj4km~k)%bG84))&;qN4S#~dlapP_k4C^=;Y*p;(_I8y#mVarS6?Bv0r8;?qovP zNQd;B`j7}KdiRHABkO&_x9=m*c(zz%b|fHooz8ywirYX&V}Nwc?@bmw11x-oNLI)q_{J}aPT zDsoB3)mL-oQWvgvwZ!-iDB$;TdwXWauBU>r&QHSlE+@r1Gu~zQR?(rHOcY{BZR`+Zx^s+zx zyJL4$?=Zc$`)hAMqjxyAx0}(s$o=@<=|bl&>*JR6afmYDvuQzg7Z*9J#XsHV*R;8F z+rxS7{s8kE!CPpx_t&?%8`^}cMz`T|U0ngsiXqGj?u39<1dHvtG9FcIEUiLe3#D8* z$rrw(An@hfHgv3ywYf*z{1a{deEoW&%{|`cpK9w&b`X_#q))Yu5B7_DAsUyPMmMXdaFCMIV2uaCJL$vEpa8 z!$<7_B2;&-)c8Fh2K!bKp9p3U1%Jo>xax|vrLn+LhqWF=l5>Z8%h#_lcpT4xzq?S+ zrlP86l){h{K~H(Jbfgdge*7TMnof(h@(^!?(v6jLym{>j*pf%Cy#IWX!)?&XsxmUCtdaDVDmgf_Y zfVli*pz>s=B*AMjmz1KV#MDUQ9W@j|Lb%&m2-iL&n%|$dNA(Re`nqHLx*2^v_nES4 zALIx6;kd}%iti19FjFrwkI4}Ua&6M9gGx&NggG#nu039mX^mYf!#C=CV~(MoJsH8v z*=9VscjwUT#!MN86if{*-EcjHYKqoU7zqVqjsRUFks0y~qjjpiL~wWXb*uV z?k4+H1Ft6e2drHhPD%Zo)Xx*&d1~rjPw=Utovjz3@$Ane_;z2J7?RXmecdO0-N$|X z8*;Eu?Cs0X_Y3R#k?dFT<0oAFHg)*{yozQ83m{NJ3B>HI0Vzx_ccmm(K)o+jUZczn zRZ6Xp;8_t=2<^q!@V(}C`bmhUB_r}RP#`W#4xEwd*sGRVMz4WU{xQ38s-&B`Vei9JlN{) zYjvwyLq-Q)J=iZD3^RPqV80AlfEu?E=a@EsWE<)%*FVfGxZ?`N0eW2o5AA-1{bPU@gJyw27oMVCUmzA2rCD;dk0j%ziSZ6&K;m|K5j+w zsSe`KnzccAK@Ze{KmEC6hu3AyKtYZVO?>^ErQlgSWqU(ml(Ni6Y0h3c*OZ(`tjyPH{)anTpTiW@Q zM%N7m`TImS6Ht}cfTN(AZLv^qqE!&!9 zaMBQ+zL}+b_Ha%i_Wn|og2~&%!Um4780HS89ADM^gaq+0_rn4U60)w~=+OJM!*n1X zw1@to3SDGY&()b(!3}t-}KEgyWFH!YkT?31b z#g09~j-6oVJDwf)NPYwSaoCtJkoc-I=ZPydr-tjiu08 zzlZBi7v5urpgA>JzU%yl&VL|7;V-^Pj&}af{s=a^_0@%oO@m#({~Ih5uMby(Q*WH* zxc3tGQ0gB}lYcs$8on&Sh%L5zSeArq68Eh4mw>o3+P~WSr9PROxD|Eo${0s233l9^ z;(cii2#Wf5NlmgQ_Go8jWeGd+!H)m-m-h0%a+g>96_w=A?y^R|L~^Ig8~qiH$*+<@ z|LIHm?l-KS;A@MuovG$Uw(}LKd2v9Ye{m?G!-_kOxiN9)^zw^(CD-9*u@B1+QhvIR zUnBTTAOEc2bA9~UKFQK7UI#0+sf-xFKgLnoqx=)2*mCc#+0HN9j@Z|3=dTmIemj4I z;NQ3NH*S}F3d?PO?e4j6`nBIoZVc}1@A!q^NmliAZ|?8k+MlRz@9*E)KRK_?oqDLB ze<%T`9qLaPJmXM*=Ap^bqI=*7|KJhHtpzui{+xF-hSTm0p3dYcc4zankf)P^yK*|d zW2bZKN{xGir4Zgela;Ca`+R&J%olz52T#j+I`>rP@5Q?__ps81dvQ+Vmp7}| zj?0sZAK^Dk4%7hd{42>wmoFqS|QkUYEz2H|BlGBiKS(GGxSf|kV87_IwrK9|< z-kt6JLZ2Yigp4Cq#B2iD1cMvt3=>{*jO-M#R!l&aJ9_yQy^^J=yS&|B(at@#d$^)K zT;A>;8xGOx{DW^?@7$ab{*)037C&>h^7FPz#=7gb@;7Xi%nHfeZT&q~jk$SJPTomt zmM8Ab8vj;Jf5tG}JS-{@L1OWyM|A&oAkh zEJPpZ9vI{w9F(vuwZ=f9{#|$NP=DRfWWL-Mira>?YijzJOH!X|m{{olyKB?8N<-6( z;QyXRbsFl5_n*G$3j1$R(^uEKu5|u0{9+mPjV@_~{yqMGj@vbTcEPSR{_kN|A5`;^ zbXRF?N|#-Q7DiVCB?bO(d35#V7whoF_|o3kKB&%ol$NB+a#^w|-OoQ)%d_d-=YLl> zROnqbPkm={JvlIi2jp3kKC*Lz=s-Ci@0W1*)lfFT7r#NN+1N(i`ol5S!wlCGQjc+A zH~f=-0}XLk+%8zta~Q_CUB9|uPs``u!@J)9pJ1tX=+2fnU+CM&suZ@_7hCJvV3_|) znz+L31AjYUz`#xUaU2v2`SRdRAuS#8V5y0_a#roTp8rpf=J17~-G*`3{&sP5jAa@a znF4ECm{^I^F_ES%iR-X=_Z&3B369964@4xAB8`?e>-ku^^++M3+De|Xl{{_tZQBg+ z{Zj-EX@?)2LTFRAEA)hVr|``w;^lN}zg5bvWJvP1@|d1(@4u4n=yym*`>&=u`<>EV z{MXW5{nyhm{u}AH{5K1``ER@3Vy^J*up2A+?^2}i6@K8q-*b2W!|ccYN6j!f^{_#O zpZTArKlgj3>nn${RbcD4@iIGf1MuWe_K0| z)DG_U2mgCnh~jJDa6c&=9{-8Z|8akEe=PhN9@~3-5riY+DR2lV^)McGe<@6J{wS9o z|UbVHma%*?h*52;n%B@+!C^tT>=0%3&rEM&f&ru&gF<}?wr31nx1Gu|$ zYW;b&?y>=XW(&)LYT0OV6;m!C!{@&W|K%&3lq)-vRc-wA5M}47-VFo7H3QtT0sfi+ zsv-%a2nOvfWktY6%;%%(jRT)mO{XDDKg&Bvp8r_?X?yW{|_wXjKXgL~&`g`yZHx~Pd(VyS`cJe%gK6>WocJ`YNs&U zvMHKuWT7iaky+}-VUdr|@otg#c6aBXgz$cf5BTAl;{9iiXYSQ!;``ZII5~5(Gkj((#sw&YgpdD59798G*%Q{eWUInKehkiGi*8r$wQgtb z^=>rxc20`;4&KXt?0<-uRVHKgSTa`-SqS~MOtz;{VZvDJG}2)8+&MU#JG)7^<5H4) zJ$W|D5}3OwKm2d~6z7ll4+;JTm9u%AW~igXWTA$@3HC%L3=Q0CL71a+Jp|-#JzTLv72Cmgf8}9=Gx4v(rL3G6d6LI>cr|F zG7&TnY|PvkvN61k@b*pNwFrEqn?_W(Em#iUBy2Sv$ms^70l!%Z4L`nBaTU$ ze5?vkB4LmK$0UYH=K9_|`LiLo-M9JnFMQV~=E=i6X_e|>p0xD!Fi#%l$#40ExLc&# zXx7`9=a#GzGDWPC#5&JZ~{zq^evCMpu zh>ccCCwBY#{oKB8KTD}ATe?EL3&XQBQ;1SwhbXT6z_B_2BnuiTT!8zOe?`VhlJOimuYq{TEnw(TY%bzVoW!&q zlW8Yqzh77-w%#P;glnRL;rGAtzh>O+e>bxR{?D>-|HTFt7%Hz>2~NW1WEYg(Ck)iV=y2n4P?}ya>FT>=9)EbvnZ}P zDE)16P~o?-%BWgqq`yPM1fD~w<;mzL1v#fG%(YNw&5MZWYCYev?-F$lQ-p2U(R0 zxn$f%4IMkbnITULDVCb38iJoHf2tiMB|cb-Dq5*KjTMRoHl3)A$wV4ejlU&+Y!vq* zkM3M?XI>~ugraC4I&*7cN0Ito_92gi6nAUVr^;!&`b5w5EGS#UGa-EzHUj&*^ofAe zlj~(`N6+fqZCPJQ4njYQV^z6G!XVE6z_d^<;3^2+4!k#8R8#y2p;w|UWXlvsabGJT z7#qD{!=|%rSlm%oCQ#KFuZ1Va>12anTT`S~M>J29*Ly5H4( z9Y*2DT`r4VZC;}Ti(m_C>Y^JopuWz&gBId(ewo`NRNSsmB0SyN$f}MnO7idX_oeVc zG7)iT;(BqOgUn!9^)g&wHsr;MZr1WZ?khEOiac7UX(*`;6hY<Y67!LhI@U|pe5J`reiO2wV5-|`phv`Irkm6ufIyU ze(3y>3FdjVYp#!j9XOuglvbFu6LF~pgIiitoCxVj>8wx%F7o)!=AplPF@#rxdj($zVO`*t zf0@#`*MeUcJiok3QZ3K(q3}ZRbAtPa3uq!9ik;nw^6#VcW|!RJgokEehMAc^L1{6G zGM(DJaJ>0#_d09AHY2!8aN309Vn%NdDoy+FL3O8H5M#K6%@NxZ(6Z{N5TQp|>@)~YdNih?q>g8(6ZK}WwMavZ z^P={0H}=M{Ef<>vF%Zmub{ZMOm1meax#~dJ8en6^%6@@}P&yJeovt?c!aHy=?{zvy zqBofS$JdB{8j68B8gft~4Y0~8w8Q@_Mcptx?5GxTvAh{&ZxpKVzIJWT*E^DCZwnn+ z8es1_2pe5$w=kvIQtD}`D5kFM_<9ugoh^+HzTT1NzT~O!9l5vK^LCc5eyjX?JK92& zTTe^9xBYG>FNKXFv@3mLsG&dxjn)5m{l7N&Z#V#&Xm&8G4@fin>Wt0AZVsb(xvLCV zR9u)jSFN(ah;Z5WCH@$ht5VEcU- znQo4I!Y#tq=~iKz^h;q>x^37l{c_ko{Yuy|-64!lzZ!NcR|{a$Y!YMsPV|$2f#pEe8!SSmx4eT)57q*ScVbk%b#w`gg~1iz&0s z%`UykgOP_IJtxKPC;RTmI@4`BlzUacsE`7;` zS6%vw3$MHMH5b;q^bHr@a_O5cyyMchWtoy}K|otvpIO59FZ#fDcTjA6E7VR#uJ%B)<@6 ztt&U)5j~%_&FHu@*5)wb7+O)>#+kPX&}!so`(6pV@@W zV(mC1*GzcaCHj(Q?kxNeXQ&Km`Yb#>t=gR>N{Zl7ig}bSCeEgHNz4AkODOdoeAIyK zjWxS?S%Q=)O(CI#qWaJi_ST+RXCc-q*OgSm<+y{6wfu3Y82z{eXvaD45yr(l$9ojV zCDDV*3stf^+WTWnT|uUZVK^hlEs|!#FEVc4ouF1e#w(s;Qfrz1$^STrP=*yUQ)IG- zPpy`c&Jx!|A5cN6S5=?H7}0A`Xmz5B_k9Nfv`K6sCyAoc~9`L{vNZgzl`~lHQa2up#T;XnwQ8bm}D@8aarN9GL z(#Sc4JNg2z6yp1(%HllFdFop5W+4#U;hTK8*~i>(B~2?=HHBOYXQd#iL>fIeB30OSQqU|+8_~ypfuE`5KWAu-QsBXYB;Pq?X{lscMofrk|jMWfvFoo>gs7AGv8xvtvS|X$-u9)%3 zh4-O=AEGNZc`b?&_ui9-J9Bqe?(aYp@9xk2Be{vc7KCtCa0`P!+mdv5px}8usp7eYw(T7aBuF zWZDI7aD9p#8=}ODodu-)>WESIax%nE$4*Y!8}n8wn-(y?0c0P=J5zKE9rYhU9hBoflHJ=i<8L#*0YBGtoq!5yiQYPU7sLwJTaVgqF zm5@fEA3K#1Y91>FsHSIjbFd2p<~1tzFtc2Tg|Pcck*hvBNxi1r**}4x0MgIVJ+wX3 z`f?6uj2+_MzsLT@7?a21Rk6EVgM;P(3wyaQQylHNrEA174VCpHpC6Ij+LI6(!~Oc=y`tKIM>a-9;7ii*X3{N4$TI3SvjNL11ZcYUlQ zbmDM+oGz9sf&$f5l$!d0DgY^wHVJDOXa+|4Q6+_jUS@hF8In?iSm`T#E+Zh8zKJo< z02rXt3F?#T83kmZG*v`mGlNLlCQD1PMV`(fl*?)W#bVgNwCqT^7$QXI`lrwBk2cYE zPoy#s8LklRNw~6>GEOaA=dfF%IF_)M_nLdvo7L!Xe|=?N9zw?QGpmXtRY=(wi6U<( zQfzA&ituGQRAxhlvZuNDu2xtB14V2(>ygMzg`hlXkf#92FoUsHwAa_tU1&!NZse8% zy9b?n-nkc?hfkIzdm_1?;y?`(JgSh4l@=a|Q9u`TrLEl{AQxM&DHcu;^g>e#U;Z-v zRkbI@TN3g==@jRe$@tbC;FfuR4Xl-8cW-Bgq8rSIU6~fZUUmy~Rf&pW#ZO++mV+^L*EQ5t?wZUT6`Zv8VWfKgR zvn2*=vJD1nv(d-veO)%)V12gAU_;h&g2JlHT{qCK>FVEjQRFE1sdG{*(`&Dv(*MWver}den>XK;LvP|!C~13gTu4YbM=0+ zY`Vb_*(!sZXD#y-J~EqNaEol2!7a0O2Di#uPSyLZv+)MMl+7}@O}5ZzBXW1DF|5`TQ z;4aw`gI~|0GZnsTHrC)bvIPdmWa|umGaGr9-hV5bWboVBa)Y~N#RUrgPBzxyce8m0 zzn85sI5z7zo7d6zvxx?OkS#a(!z^2<@ZGcV27i<-F^EFt9EI5e74Tu-r1=0^nRagy1`#&s}24tYdK%x z`(_gi?w2hyxPMk$tndlhID-ddiwz!_tvC4VZ1e?s|C?-8L-G#h8|uxzox!?O(rCuL(U(fdDU^9=qeTW9cp zvQd{Rd~!C$;1Ss>gMZFiFH`tmvWW(#WJ?SlnMF$!J~bO_@ThEo!D-oggGXnhFW38H zvRMZInyoQ7JsWw2!jH|S7@U!`{Ns|}u;bzHCT^Rh_>&(BsE zT%2V$DExwKyuk~z1qLt5))~Aw8~Jy=za*Pt@X~CR!OODjMujiQ#v8mmTVn8vEc%DS zugu08yeeB@@ak;6!KK;g<$8ZjHp}3$Y>mNdvynF`{JLz4!Rxc-25-o+n-%`|Y`no6 zvn2-qkwv#Ce0et3;7!>)gEwdE4BnEBx>fIQ&88c?En98y_N?PJh2N1)GPojJVernZ z<#vVNl}#{scec#nJz4P%h2NWvGq^HaZ1BEpgTYnVm=${e&upH-`?GZhAIL`CsqhE0 z=>{LlRvUac>$pqdk7Sb!uFh5%d^BshTj7so6AV6{Ei?E;R=h{yPiEr`K9wyt_;j|x z;F@gAy?XylHqYR***b&IWusOqd~G(};PcsPgD+$q_bL3vY?8rs*$RU%Wi6`|{&F_K z;49fOgRf@Ae=7X7Y@ET@v&9DA$Tk>UpN+X+@88Vk8GI{SXYlQ8)B_5CC!22Y-E6hN z_p*)$75;uU$>4@;g~1Q9>>-7Jn2j^|QMTCN$Ju&=pJbyS*85MhSq4AL))p$e3ikFx2{%roR2q{X@`FeweeDtGwU(9D2Eahtqmh+L1DZD11Vz4$}VX!W5 zd0gT3`FMj3`4WR!zTRM-k9W(kIUy7{7Jsf;GX%Yw-o-c4gNNtYM+%>mk2mG_z* z@&4F+p1~RUI)lgMqnyHL=F<)SEnjW$_`Jg_{Dgdx!CCnVgD2*AAS3*we7wPv^92TH z=j#p5$w$X}e@Z^Z;M{zb!FhR0qVQAm2?poqiw&NZZ!mazJ|@-sGxB)`&&=^M&hNAG zQ3b&T`E-M4=c^4a%yIKY_&NDRgNyRz2G7m2lETl+#~VC9Ut(}^jwFuo3-YlBFU%Jh zyeMC1@Zx+_jox39Pd9jJzS`hrc}K0nm*kTSUY@Toctze)r|>KD2?npqml?b|FV-u3 zX+F;2HThzL%km8dug%9a=>2v1JcHNg>kQtIkIWSQ_k5DU8}k(g|B<)k3SXX2FnCkW zQ3d?IIWJZOZ^_3Qyft5J@V0z|!Q1mOje37aKF{Eae4W8N^HEI-zbl_^@a}xI!F%$K zW`*CIPcpbNUt#dRyrrAMSLG87{xe@@@cz8mUEvSp;|xBSFE;p4zQN$b`Ir{He{q_5!e4fFN^Hl~v$y)~~{L_4*!O!yL2BS(gP~omJ-k`56F&HWv491l) zgY-VB%rcl())*{QS_Uh;Sean3R9R-QTq$-ayrweFU~Ofw!Me%@gY}g$L-f9(GS6UE zS!Xb>j2f!&N@cpi#>#4gO_h#e3U97VGT5!M!eIAGak#=;Dq{@xsLV6iv$D=$ugd?& z(S61(S@vNZznTwiy5@Q9(KCQ&;37MeLwsTUW+%Mi}UnfM!O{@p)D4nBQ|}9+0y zLD)`A!k}1&?L{7-{dzGDJBUTtQS@Fzy^|P)H;8%ISrl4R4~b#eMa;q*#X7u647Q=Y ztC)h_#1iZ-datG4Lkz>Pn1MaT8tf$ouA{xTn1Fr6BJ3-A+fwf*Mqz(34j&o5d6yE|%a3(Q`fZkzxeiBIe*Iu>nVm z!49;?#5BBBtimy(za#arVjPYWi*UT??L>Wo7=;tX9E^)~I7tlNK>K7d1*eE*c$>&O zQ=ckE;WRM^r;9b15d9(AZx@sB4zUdH6j>MQcZo4LL(IXu#X6iR25zK1DW>2ou>xm{ zzMH7e5#w;Kn1lC-4LDB>b)|j2n1(5_0vCwBZqyfwakxkEe_l+$7sL{LQDiq$e@TqNm&F2nMf41(UKS(pRWS!&6C3b# zF*JhqH^dBlQ>?+a#K1`EZ;MG-5sUC0(Q^y+cf~M#Pt3sg#R~jDjKk#5}Bu z!f5Iriy`=ln1P>)HTanrh|&JJn1Wx3CHSStZlzumBk(IR1HTq)@Eb8OhW2m86#P!C z!0$!hSn5BB30N0P@JEr2qyCc^fj^5m_>0(pzlx#pwEre%;O}A$HpIXL>VJqS_@`Kb ze~G?{)c+O}@E@@R{}oxB`hQ{!3Q_?cCwV4OKVFK!6QmqGQL4j}B;RD(PnHt!e^Lp0 zBsPWmDN+=kD&^p5QUjhYg>Iw$3@HQ8lq&En$v2g{S4zOMr4ke+HjTO@#h@$|pdxvu zQ&*)3)TA6_QUmHzC_%d+rJ*TRp(Ximr*2CL=tz0!N;Sx(z#X(VlTz>;sSMAR_?^_x zlVb3EsQ@pKJaMjGl!F&Z4S2B>nnC*|QU+cs)!=1P;BM-dODTATRDpiUH?84o)cZS;z%fz|j+Gj4oD^J6`*S0_RFOc#qV8^Q6#P+UH9dn38I6ffQIreW8?si=+x%Eb;Z!mq>BARLa9;QXQrx z{|4HZOL4eDD#DeLcO&&xQWUP1^6*|s*hGDe6oeTm3D-(RxK8qHrhUB>h8v_T+$h!I zCMl4meX|sYS*ZxONS-a!w@MMXP0GUUQWfry{99??DaGL~sR(nDXB+k1QV8ymQgE+S zf%_!3o%a1w6dsVW@Ss$Oc`3Mq_Crz{9+s-`h~(Qz{iqa&$D|^>Px9=de!mof1t|v~ zkQ(qoDU_rAAt?hNmTK@3DX^RRqf!z+CY4}O^6sJjxDB*^u%G%1QW(A{W#LOw6}~L_4$%IJ6o+N00AH1agVbM>LhyAd z1K*G;@J)&3X@5(Kz_+CwtVj*`jubjX`@2#az9&`T`;z}K^$(;Z{7@>xk0gGCdR2|4UrTBDjZ}f(O1}H4erw>%DCOW!QXT#*`5vJC7byaNl~V9GsSJOYga>JFNPhT-6or3EY512^ zgnvtQ_>aUNqWAwRh2eiv5(;u29w#^8@v`q>dfy3h1fD3T;7M{Bo-DIRX#bxag&sKv zPm$~JR5|b{?Wf5}c)DDIXUN{isGliE;8}7OdgU5CTlN=e7v%($Tg!FWMh-kr`?YcsUMH7eTbaE;y`3C` zLAe0i%bpjhUoS^s2RR2j%5~UD4!lJB4RQ*0mdh|C^Ovc2k>l`2xd?BPy{}O3Do0>9 zISaeXHP}P;muU~n3D{FE!d|lXRqDOv2<#(gVPClh`^o;-Xzwp4U_>s#0kZdX>I3Bn z93*GqV7U&5$bmO#A1Wu|Fu4q)GJli$&2kJ5m-BFh+<+tH;9IocBB$UexeQ0k>}~2X zISOx;b8w7YhhybHh4yiB5{{QkaDwc8hx$Z00^@QPPLgYIvh07C_9=1#-X<5}RN4C; z^=WbxPM7mAAq($Qzg-T)JLD|9Q?A3i5$N;&u$?W^PzTrHR3y)yrt`WiV7Gjb8Gl|5fjUnfW4dN~I-$aT0;4t`1d zCOHi^%T<__{Wa=a4Rrhr4Cr8|r)HFx)F= z;Xb(z_shX=X+I#R;X%0y^RoXt>WAbcJS>;t5t)Ba{iqy=$K)csPxk&m{eC$L3vwPl zAPaTs56WTqker1N%XRpO9Q={?N98npOs>MB?Ei`S<8l%{A(!EkGXI(SQ*s}^ngLyp2X+oGU_$Te}$!Yk$T!kOV{=cYyC@0}Zav4@- z{x|iH(g@37kDTiTA&cd(cI{aD={zv;aavFXsSK)WE zUpT(0e=jHD4{{mS<)+8^n);7&(;;w8{v;RS&vMgo%T2F;kt6U|x#=e?O|O5G8}N5I z)bwC#)91gOfq%$V_^0fnCs&2P40B;-g2Yh0~M-JY6ZlGZaR@ycfXWx}$`kt7IToYOt9S@X~&cl7iuDnsgi(~DMfg>;+3gip+uoy$;0MK)1eAY{YoVauTrwG zg;IxCD?yd^mP!(~Qpzx(aEoNN)mQf=&b6d@BbBMkzJH1yiv))o0JCZs)TIX zyD1siU8%tyN`NlR5W-3d_Eajcm*S)QT7=$80`^f#u&=^6^?phW_E!opqIjB7AD~3w zKqUtUDGfMS37tdx5G4(VDpfd4@t;dQswCmfN*NAU_<7VvC~-JaDZ*P6;e6_&lrS8v zWMNFH!&{ZW1+Qj^myiLi$ zsY)GAQ-T-MK3z$}gi?jKEB;HU-=QSook|(rrSMCs&rssl_;F0 z?JR>PwV3T&fh| zGR1o(^|TU&%auG_p$Jz|U#W!QDkTF~D^+-};%hbsN}%qa!9TM=4Q z-=l=#UL^zfDOI>%@wcJ{{xFlo&j$6yOoXa~<`gN(3HLvhY5o4)0e2 zZD}tkDfoa=h7T&N9rcHl7<^bMz(*7zNc~YI3?Eanu&C7G<4UkS?N2Ca_@q*WPbvQE zsXwhG;WJ7ZKCAE!)JsYXKBwg2^GY4QpaeV8{-TnCFDYgCvcfx2e?^JIvQmJrDxMpt zzotas>q-v3q154+n1^IE?o5)ik_7t-=e{K$N;qO~H%Q3cOhL-Aw%wH32VGOYkz)JDmFEY6M=P=Ad6~ zz~*Xb1npO<8F-aigDup+Na|OsDcDl2z*eg77U}^t0k2U@u(irYQE#Kh;I(Q2UZ;9S zQ*WzAU^_JjgK7h|S3@z{uU9j$gIa?f)xfRPJE#f%S0k{8nuB4r0eh;U@wE3+GqAT>gMHM%1nPa&6zr!~V1Ly&k$OZ; zzyWFr4pdp3`XDs|2dggGJ)wr+?P>W1eKV-fQ)X&0ksSds=kHP^J)wpQVZ~~>RCknh#G-M)f_ygHsF0~a53%o zt7%wJtMCEUzl8dOY7#!Amf^!HUrPNEH4YzDi|{ekyNr5Kjl##(0(?UCq^UotM&MIw z7Cx=k;WKJ*IqlD?X;@OL@Hy4Lg8K7n62738;fpF;N&O`?3SU<9@D;TV%W7~H?XRk7 z_?lXUudDvm)Zb8(@J+Q0-%|O#)ZbQPu%hPSJ8A>Is|MH5{+^nK@2ge#f$Gmt|4>cB zkJK`(s(dZ=kJUK*L@mNkRnI!=pQ&N^xtf7rs8#r->R(TLO-;hD)H3{9BowqVJWk`=s2{Jz;R#w1o~U`ZQ$ISt*w=+&z5Y%P$ZE^28gX;mm| z{@v6SEeTbv3^k4Kq0Y28)U_fsH1A&OrWS>kmV>s|fQ}a0N4u+KAlK@!nHJnn{TwX= z&(&)1JS}j5`uSQ4UZ7Rsg_{2$b)S}k7ikrEvBvY%FVSM~Qmp_l(}Y9RFV{lw3M~Wu zS`9YW0*7h8QcJKeM1)iloO-sS)S_LLFUy1tdS_0momEfHkdye{DS`5z6^6+j=c%J%9Ed-NV z2F}uIaJCkBf%Z9C3eMFk@E*Wj57T%u*+ zQmqb`X~9=$PitwoT&utpny*ZKr51;)v^-p`39nMWR|~^6S`KEk23)HJU!#4UmWJ!K z3f!RiUZ=iMi@{A=9&XkeFslXMpnZ#$f?KsR+@`TNsc+Y!aEF$IJGBPfr3K!iJ*TDM zZmk0MX#TgU@70oUpH_tXHE)Ib0WAs-YFU`q>hO>je24bKS_U4`YVfEQc$fMyEd}q> zD)4^I_a60v7K0CHIryL^yiffhEeIdhQt%P20w2|UAJG1omViaA1RvMfht!|YV(>|= z0H4x?kElPbh2b+=7Cx)hVMz;CX@5>j!{@asd_nVnO#MYI318C6@MVpELj4sj4$E2* zzN&dYrT&^0g|BOQ_=eVW8fjC1Qwzhlv@CpEtHFvE_?-54v^0EItHSp*{}WE(h2eKv8h)=;;SZYcTiWYd0{*C#;7=O+j{4794E~}O;IEqJd+NVw5%{~7 zgAJ_#|ImUz(Eg{EhJR^Q__yY-Q~yUx!hf|g{7>UQQWsbp9>)ssc;@+u`UxxoPh>fG z5^KPdS?Fil|Hm@W!)ovp7WjqwsVoIgV-arvJyOtvEQhBSqz@d3Q%O8 z->FM10%ewi3adet`5LrqECv}XK%II1pl+}TG+7Q>tO0En`jd8tWuVJykTd^Z)SIy+ zJcpIwxs3fy{X7AqSQ)lpbje23=Rb?WmQ9br(Cb#L=^U&k11wA@#t7Fm{dbUT z&FZiX3pO3M(e(X4Yr40)$?I4Zwq<@gxJqcpk}$|Bus!oN9Rbwz`OlKD11rOh%y%;N zPAma$U}e~uaXMo}2(bk0!t(G&CN!P5)%5p23&XA~3%jv8?9PI8c&pHZrD2#=U{B^d zm3l9hfW286_F|-U=28t1tr?!EDa~IDxA#xbTExDg(cx_tPH0zu27%G;&3`E!UXfG)Nf}|cn8bF zJDH$Szl(+843>p=vpSr~f=zcVHGTij(r^~5!r9EPQ=h| zc}?mISQIW~dANuP7WKs}441GhT*~Tj84KF9r&$^dWw@GgIw426 zm&M^4R)iVm<6QQyGAa3jmYO{@wxGky;3Sr&s^SOIQjo^z>hV-dKW z<=_t1fIC^}Jlc1$49u|_+|2^#Q{TfuHs_--BZ$?Eoe$BksQ2&NS;kPUgzhgpc>ff_4{DEa*oz>xw%-4qYpI8F^%u4VV#;&FQD~rM3 zSONadJl9cgun7Ev<=~&J0sms5wzU7vGVmW(ga5KXJL>Zj{bc!r*bXX-*n>SyU;=+(3E zY`q3WJ2Cvlvy{KQOr(j#X4BP3vH}#+%hwb$uyk7V8q257{z>azjcG4U020hr9_Re}5 zhV&}zqWk+%zfn)ZoAfg5s`LKTyXkS*T`$5Ox;H{StVdu^JqLT~b=X@E4xqh{o`!w( zD(t8G2U72^Ct*Y{!vQ)QM17zhgM;(}9ISf=Qy-#7;7~mWhv^L%)k8yQzgf?~;d%{@ z&;vuMkJMA}7QF&T>AqpqN9zd~(~Iy{-4mrgMvuU;dJc}$8*scHx|#L~dInC^YcQ?{ zhEt!Ur{HA00;lM{5!7$f6L6|tg41;GNb1w|2u$cXc)Q+!cj%#8Xung>z`OJsoT2+i zQNLSH!kKy*CUriV`Yb&TXX`~cNB734&()*w9z6%=>2)|?58g_9N>9TDdKE6z{bQ&v z(vxtpUV=+>HkSHQJqDNQ1(?=7|)H8Y< zuGNchoi0qIzFrT*4SE)C)a!7Q9*onzSx>{PUWHq9|0L>L^(5S;m*IAuPo};@kHejM z5$@8xQ>f?kDBP{*;U2vK_v)eBXy2!2;C{UV59q$B)DP+jnAc12kj|!2Kdi^#5xoG9 z>YnM;kLeM3pPqyF>kU}YLkZd+&@=Esy#^oB1GiIuSWm%6^fG)@=XX$lOpn8&o`;X? z!kyHg(8KUaJqw@G>+oqkco*%@=xO+@UWFyyKZE*ndJ;abm*ERKznl7tdK|u_7vamg zcP8~$^e8OrIrysHfUoJHB<-*3Dfot7fp6-*S=8Us6Yy=l1S>k5P5m7`2H({S@IBo# zhx+?^1b(3B;D>qxex!%y(q7dw@MFCOKhXpCQ2$gHZY$-|I>EgI1p`4UWNbY{w37^)f4bPy#$;7U|vf7I3os+H}dcV zLs&-rL?aAOGBWUFqXz$H1k$v7j1)Y@sK8SV-*W1w8F6^JQG{n0-WAl(G@|eGWoSRg$iQ=r8a&SktfhXwk%Si*Wq6^%*HQNwad?qYgclp$_0%shqVQ59 z4=*!>4b(3;!te?s3;jkNHaCJBX}{7)!>f!cY+?8}QNP+q!j?uEwler;>H#ATuQ7_S zwc*WDZ(~H^wMHIZX9!!Uw>84Bosoq>qYm2}!L77kZ=_)dqY673{%zDd8A*79QHGrj zzMXo=h{G;M5#DHccTm5{h{CQ$9(FT?oz%M zy|0mk{fsi~Z}8pJBSst!Fp6-X;oU=hkP(H0jXWG;2z#jyHNtS1k%dvC4sSMs`)D6- zq~Qpo3P&3L{nT$Ul5mt!hNBIBfO^b`!&{9a9AkJ7QXgwX;W#4?#~VVP`UE2kCmLB8 zH|lVb5jaHqWFrZu7$ta{;XO=!su6+Hj4YgP)L_E!AEEtrBLVL)O7KpD9i@Jk5rZ>~ z9K748!#KOyvGpkr#{aJ!}&%Qri?mVU<3=aFEr9{ zkx_+<4gUkwml#R7)F{Jc27i!x+K9vDMiH(sybn=dX++^FBM(;_!o$?>HNtR>k%bwf z4%ZsNM`&MXq~Us_3O5-3N2zZ#l5mqzhMNuk81<|Xhg*yy+-i7>)VCQ?xZTLZ9ft5Y z^_@l-?lQ74XVl?tBlraEdyF*PYgFMr!~Z1p{YDZVFv{?t!Jnd@H{$S+QG|yL@6*(e z7*TlC$iriX@C^0)j4-_4$ijkAhYuLRXK8=XNW+JWDty@Rm#9BtB;lh*89rw4=cpHr zIDFhF!Y2&x^VFX-qVOpr51%%K7pOmDgyFMB29}H}e9rK{Nc;0f624#*;fsdw67`pi zAbi z_4kYNVAkMqX5a(r z$D1j5f?0tln!XRIpJXQB$z}=u&txA__n0wwidlfCnnIQOX=WInZf4;bW*wes20y0# zEHe$gW)+@o`ahvAnn@^`Whk5cQ|gKthpJhGn(6(FIy0kCH}lXih0m#*W*Ay#7TRVV zI%e<-+FdgRxmkwIO#UVHbIdqA*DS*GOmB_)`DPSeVCLb4rtlSYpBaW1nOS(TS%;UH z!LMn*)J((6%qqOx^nXMB3Ns1)W*Ig&`M1=sG~@6pvj|(5-tVYiZH8e>GYeapbr>*% z-_w4LnS!m&3T$KgexQD>nSj@sCD_*V)Ty^KLojHjV0*I!uQ%C`w0AILu%nrWoy-Qj z!3_RHduKBRLuMIvG1<@5Z#1LuCNl@SnswOC4E{oUcQXxpm{k}y{l8N0X(nMWvkZHi z{5R@-%sA|87GXcr`#bgiW)w!uJRD#)UHH+|2by6x$jrjQW*rVOgMZLI)J(%+W)((F z|DV)vHj{9;S%xD_{ulL;W*pvP7U3w<`#1H`W)#NEJiOHu{-Hj`48yTz7LGIPaJ(7( zm-Y!}8csB;FmC$)qdv(@!pUYCPBFP~VpG4(jKisB0ZucU4$g1t)6F1Em}z*sS%r6) zemX*2xYJC)yUZe-VS4HMWZ`Zz1ZSEVm^3SJmg%EI=Y`p30?si@aIVRk?x1Tr|IduU zd1e95H$8OhyO1&?aDkbF3(W>xWQOS0Wnrv*;&+gnlZS`EWn&8c&YC;LvW9ofqTsw+-C;PrhUJe zf(OhBJZLhJdftq|LuLUUHU)|L5iB7DH~D%2k|qwpa! z4<9xg@DVel(*CHKfsdIrSTy|_^~cQwe8McjCrw7zpa@TyQTVi(gU^_C_^cV!X)l>+ z_?%gV&zpXO`U_?fzG#-=OC~d^zidX~D`p;+O~Io6su_Z>nQ8dCS%Ghu+@}3aGY;P} zi|}pJ>rk(lQTUFThwqw#OZ`1F4Bt1i@B_0BKQw)u_K(a2teOS*vDtv1n4xC0e`;pn zXJ!q4ZU)Yw{)L%>Uz!zIGkxb$|H@3jugwzt#$@MF|JIDb@5}=H-t?SL{RcAw>t+uA zXg1(aX6ORie>OAl7qbR`HT@S-|IJLn-_0^?m_8r%Kg>A%(=5WjOz%b1|2CuWA2SdC zHHC|*|7V7wU}fNORt+9+1umie1SYw z%X2yP)2#?R!^*)ktp+^H3SB|F*UG@Ntr`@qfS4gIV1V|^tTepbs=_NQ|25S8RsuG+O7KdHwWfZR6@x9T z0=(Mtw4vV8iojM@4hF0myv7P#OM7c81>0B^c&+8Tj{0?00=BhEu${%)QV&`&*xo9@ z>n%?^>K&{I>}cg+C#wN(utGuFJ6jnTvTCr46=+ZWMk@txvdXZl#jmH{&5FbBRuT5F zyd9{AttjkiPC+hvJ6pUCEIKcAVKz*QUUUSc&C+xcUg5f!wUAK{cbA*XIeFwv;w`T&$3c*wpD?1EMITxbFDbM z$11{kmbVY}`BoIBtUO#`34N(Aw8C(am4%C~I$UA}`_aDCO2K7T1*R=uf9lJv1YBX2 z;7W@{sIRhOaJ5x{_gbC-)Yn)Mn6Ywjt<`|*tk6K(*IQY*!K%ZJR&WsYO;#Fiw#qPT z@xj!$SW&pu%EN7zX9)G}Rs`;_@^Ggm45hxy3d5Y0gS#zZ81+3?81A)laG%wH`>jxv z_5)TH9<=H(Z-s8Ae#pwe!&VI*v4X>?AGOl(m{o=MS%DGM@3+#hV3pwmmUkre2dyZ4 z$SS~xEzd2~AF(3vQ7Z=@vudzt1xC^SxRruWSQYrBJGVmj-2CG&ePW@vm1wXMW z@Keh-iTY<&0)B3l;1?E~O#MqM25VLUer0*4Q2*MBz;CP^{MKr~@2t>mw1019;15;} z)~&!)>OWd3_>)zEKU=t@f3w(h>c3kt*su!l56hFF{-+gze_1*Bx7C3E zSfSf#|JTaE|EwAm?7$t=kF!(oc)J2muzhz@KhaLWlk5^a*=Bc9|DPR$9=iZfu{|@W zpK3?oX?6~tZa3f=cIa-}&$Kh}EV~B1c3>v;v+WcV?Fy7^Uy{0PC!k`NplY*O)HOQ> znO%Uo?U_y8up`j4bI`II(6&Q!Xm{)kbnP1Cc3>{`W_AjmV^`q0w(lP5=h<<1zFmYD z*xq^6FSMi3XXoKXwlJUi#da88VrSu{b{$@32UE0PZl~cDb`|<<{{rgG?IgU?F2k#A zzL0tgI}We5i?F5bT|~W=9fbiq53jL>#nfBdVc5pb!fWk1yv`0Tp}no0hVASs4BGys z)Z5!hc)eYQ9c;dgdPh4BJK05egY8XI?`%h5$j-wqwy>P~jdlp$WM^Pky9T@2ffclO zw^Oi(U4dbnucY47j>BGd0rs{%tEl&}Be1WXgZ=CV>~Duw(;l%iaDZKd1MR@Q)Cbuq zIM}YhAvRw_eW)FW!|Vc#+MW#co9zf3Zs*_#y8%bqp|!N%VrSqey9P(wfpyelb_(8V zSKt`ix1Rb~I|0YpB{<$@8>mmPV{oEffN|Tik@_S%0w>!!IK^(j+w9OL+NatXIL)rX z>2_c<^@N>*x7!tXhwaN!ztc{@yX+F2VY4mN@3v!brd@zZ+q0GWEIR^c+c`MLZos*A zXdCVK*cmv_uEP1Ye>?S*orDYQGF)i$9n=@uak$tn!X>tMC-tRv6fU##Fl`IFs4us} zaD|Ej#ou?Qh!|Sg~vH9Xs#{^>^(Qe9tb!_ig?t^$+Yg{Ln7Kk8JN_)T?$Ber)IA zCw2pVYKMxne`crQ=XMo-Vf!Da{-vFSHM;=6vOP~w|JshgZ|n^G)~>^l6@4n9l!Uv>)q zZCBtwwy#9}UpoQ+vrDk)f%xaBALqp2@lFAr;0VuCKhX)plbkF(*{Q?-Il&ib_c&>I zic^KBI{p`_pXMat=}sA*;qaHJpXtQmSxymp9q-H3&vv3vbn;MggjcA`P8cdq7OGAi zYEH0BJ9E-dcdF2E{I60sofx#70<;~^Yt$Vl0$nEuxzm8noY3pEpW|fUxlRq9=LFuM ze!i1}7dRDoq2qg#y3a|#i<}a?*kNx`zr+c{OPwsd%&Ei6o#5NFU*V*o->Jgp4zEzZ z(uu>XoFZ)Dc;BIZwG)Lcojh#i2=7u4IAM5=lZCCFI&9+v-=qCnCk?N2s<5r&d!Kqc zCjo;_3AT6G2h^{3Vz7f#fE^vrhtxYc5qN`>gPolQ3^}2XXz$`=;EhfV-sA+T)Vn$f z*v%=y?vD3k>OGt&3_E$)(-A(Q-pdKY-cAPgacZ!y6Zn+&eohMZcPcRA_&%dPz)8S? zP6-Zj*yq#-J25!KDZrtQ=L_n?oCu6MIe4?vfWw{Om$Z*?(r~0xg||5V8ud|55{`Dt zFy`>DsNd?u;TWd~$2#7xsgH9aaJ-X)6PyN|=!CwZJ?>=SB&P-^JArShPjQm)Hm3}y zI{Z88)0{Y*?&M*@5x%E>yAy_YI9Yh7Q-^ms!5?U!;iTc+P8H5{{B`O{CkbacWjNd6 zKT@CL#Nk}02=8&cKT)6OMBscU15-`~E^ye-v@dibaFLUSi=8T5;`o1|eW{a#%bX%i zJKkTZFL$DFg_DOX9pN|XtDG=g?PTG-P93gsg1^(Aanf+DQ-$jse}npZCjmD&CAiUH ze^B4##NcM90JDzgPwHEoDBSAg;WkJ3i~4pa0(Uq$xYKFCT~7FK+H+18?sn>MkK_M` z`d%jv_c?jE->Jg`j{jfU4?0PhcgpaP!~dgx*ona-P5~ZuJi%e4pi_enIRUx|R(RM+!AG15eAMA|BdqY46Ng2o2p@MmCsKdHiNGhF9DK@Y zz^9!MT_P_$<7D8oP7Rivz{%8~b5ihmrvhJad~}<=@S>A|FF7Unvco*oUvXlv>=fXu zj^`BWuQ?I;x|4%%I1Tuw6FQalx10=o+o{2d6F80fJ5Cb5>y+Vp4nLjx`%WBw;1uD9 zj`s}eA30H2b@K3IrvX24LQVHTH+}!_WZ-8`6@Kpc&!YZ?lZ0P7Wmt23Ug}>t3HY^B zg5NmoZ0g@SG5DR6hu=GbNc{&V4C_t?{^-=;PfkFh{bwf$e{o9iSH~+;|ILZQ-<<+% zI39)iA5Ikh>Ez*Gjz^{bw-bT?IC=Q5i_0!!fJj1QSGhM$${VX>Ly>11b?fPu$q8o#f zTY$1FIMfw43{^J^HMb6#8+2*c-83}ZDl}a`r*64PXuD+I!7q@Ir;XpUog8Cpg4F|hbIK=f|O?{}Fgu~nljJm#-)NghZaJXB7BV68!`bakp zZ*fa-l*Vx&bqjEu>uF7Wyc>lR+&rA<3T>#z-4LAQX5nPF z4yU-GYiYmD&BCc}9Zqut*HNGDCSk%Y!P{MLTk3bX5qPJYg?G7iIKvILqy26-4QIMl zm~?rN`YbmNXS+o>$Mv?SKG%)Hd)yqH=QiMcH*`JiDK`ZdxD~k2^>v`W$W6e-ZV4`N zSx4$i-56Zv=3&}xz~yeR6YVS9G+gOc;VRd61NGHz4BqP&;2PJ{nR>>Jz_o4;u5%l3 zy&DYCzQIkwjcyrka(Nf(o836fx<$Cf_1;K*s~d&e+&tXw3O7;T;fCQ(Hw$;U4VZI7 zU1{I#X5k*U4)?mjZq)a=X}I65!2@ofJN1KZ8s^<9JmmU%P(SP@;1Rb3kGh^P^NenGZm>7)MK=W>cPsD-*Vl*o zlWqb&_W%!ZHhfuG&arm)YgrB(Hq0~Qhqwq5~4?lN>Vbs5H!|+Qt3u|s2e&q(Ew14ep z;5Tj!e(MHqrv9CqhTpqo_=C%bQ?I*m_@i5ZKe?U})PHs(@E11+e|3eC)PHls@OL){ z8?JB*^*`J&{L{_BzuX4=+YODP{U0|A|8?u|KQ}a*y1+B=I9`Lt^I(kn2|Nu?5inyq5d# zpne@sz_z>y+i}mG)Pp<-+w(NMp4VUp?z@ZjjywiC@dCVoduCAY%%d>G^RNpS?xubt z55t>y4tC`Y*o}v0(%zkCVGmx1VID|Q@5z&}7cary+&hbUA0B~yc@FmDb=aT#X44+w zaX5e%;6N_Sp+1O*;9#DCLwF4i<^H*}590|Kf2 zSvZ>4VT=do(|#*Y!!f)H$8vv)`Z%71<9QiQ;Cun~i98PDya*?8&qC^xc^FRNS$G?- z!>K&Di1ukb1*h{eOmM!K`t3Xp@8CsvC-*L)eix6z89WE?=5;ue2ba>GZa1GDG46nnrJa{kd>v$Tj=M}ht^EK2r@;KbY zi*PgdW~gU*1a9G3xRux8HXd9{`*xm&J9q`|Gonh6i~C<~iR;{Sc4C!@LNOaPKDSM|lJu<5_qgufzL!a5L=%o`w(b3Ve|B zEcJ(Y96rp8@Dc9aLj6%5g^%$(EOKEh^~ZS_KEbo_NnVFf@!&SvpXO=!46njxxqmzL z5>LYCco{y=*$(P2@EClN7vM|Wvy=MEJOW?gIauZm_$m+WqWv|Vfv@u#e1iva)ZgSO z_!h6gx4CaO^$JhGcX$cD%h?|4@9`LXpBLZ<+_RVZhdcs5;yGC54frt+?W6q@o`Ik8 z8vKk0_EZ0yr{EX70>9+G1Jr9g0l(r!_%#;}QvZer;kP^mzvC77J!g5^f8Y^V=Q;Qz zufv~s@DS}k^ECX0SK+VRf0+7jJPCj2CD`DeBh>%k5%?$1!@sz2l=|O12>;<3_%E-) z|G4iM?LxB{Jg(XQIXe?Lo9h4n-#czMABWeErrpO_G9~Y^) zM(mMDs=qH4$@KT7Be846UM7;_@5@FO`1^8^WB&f;NYbbBefdb5zpoHE=I`Sp3G2jO zF*4fUSBhl$`&%NF*Ngqu$N+zTTV%VxuN;ZnAoklM-TnO?k+uH5N+fop*sDgm`ul2; zwf??(#Q99@H6mU8ea%R^zrQo$d@lA{kraP_S0vrv*N)`R5PO|SiodTLS>W&Qj^y7Y z_Jl~XzfX+J^7r*3XZ?NsNYZBczCk3--#3gL^7oA*HMfYpaU|8>Cq**-eUnJ}tzy3? z(#PL7jb!-yW|7!0#C~t2tG{m^N%!~nMe=VGdy7c2zi$~y^Y^VHhx~o(Nck`2`!2_zod zwl-KWbdfEPIOt10Z!Z>f3i{vqE&=%gk1J6DBsb^F_Lka(yR+|wMx)FjG=LE-rm<~Z zulD}0-UMQtx_s{-+1^Dn(FaJ_@*=1jh%G#ue?lH7vaJ3J$81&nuk$&b*yrSYgw1g3 z`+k?=gq+uM;e2dynp_s=3TH+xoFx`#{3ST8CGbGlS(;*kmcNXWXOK?;<7jpW+iBrCTAKC9mKO^}w(w>9zf%5r-f4(XF z-}dZ@Q{ZZ6B7U**k?jQf6G_<{&b68&hTQr^E1y%?N$2~V<(v5n>id5$5Oy)FrH_hCACPvBoI}G?lbMj#M9m4oVf%?#S?LEVtmUPPalg@kk4%4 z|6O0DoO*C_*4F@wbCc%eHUCldRoZzh7tRoiQ}z-ZRbOSC)Lb|tEKbGC;*@nh%7rt= z;@o}-jv5ckIbY?%dCTI|xh&4jj@(_5vz#Ycocfo=Deqi+#ec`2cPvhmOK?MP!92gl@VHfcm3sk8yU^5^G)P#`?5Q1;`o9Fx<6fyCVhnb>d0SJCNj z1#~3<(E=najsgB&8nhhX6N>zI;-Uho0tl=oLd|@U5eum%4T9&q~i%=EAD@j z_k=^mbF1^q|AB9cG0JSQ%SbDL9yKU!1y29}a&75W}AE(NYaUDbEtx)hd7hFZvh zlbSInEaNCRDf9)S#IdsT1ibPpO+XI%!_Ww1cmp+W2ew@(3(c~4HQTESea4@m-0n;d z2NGu;rZS70X5hb|7YehMz>Pu+1rj%lN9Yb`Hr|=py#3efYVUir_ut}?P{sM!%DbWG zlR(*o?oa4wWR)xbw~@6N8%SLD8=Uf0oy}IB4JT}IIKT6wJR$y}YR(>_9B_os|K{l` z?M(yxH&4^WqkMJeAoS~nz-H(sO7WLkk}}xg``2*J;O~l!&G?&W#Qz%k0{=lrg_$S=yT!+7@VdL*w{-)Ftaw)X|ae>6YeNHXsb~tgu zW;2|k7Dv}@xF*FXEzI6B3sU;O6Hn4zPAfR3XBH#P)3E$1=^;Q3QHf4wF1)d%;Xj|}cWVkTFJ5vsUOnfK#hU|U0a}DigSlVFw;bCi$d1i4 zLTNDTPD%mRch2U*+i3Cl^Rk66#T#=&1vdP$b~cC;(T*i z@icR0TbxCtUy7Dn9CPxs8e87wbFcG>#WCe9bz4%Ye|z zDVhsUZa+7?UoVq)!soSiZq9`#w{aWZ@0ZD2cR}K7+<68OiV(iTq^`q;v9vQZo5#oI5u(EU!wt624y&+&8+fW8`?=9J{n+lsNsOq<+A8n$!#Ab9`&QO-Ajl)Ot*b>4L2rGO71ViZ;nkfAT`J z^0yv*{{k9|_+$Q9>Hi!CdD)5WdvpNF+&Yd4sElo~NoszrP8{1gCy8e5fKP)3cLXos z8Y7cKWN^322TEUx`cCY1kq*hnC4=KN3C>dmqUTpF@wp#8h79LgAES;jgRl=nb~7!s zL4~J=-uBLHiOS?PhbGwzlLOQ#ac!|yXrYt%d5rl5oe&qJBIIR zRF-~Wc+YCy+t{X|Wk}lFdD4$w#EqO~V*Fqg?@^~fp+I8B5GgL1@*l$cH)OIqPSO6; zrT>-`=`o$1iYyz%DW||m68?n>(^E}2^L04V8tP$hirU;D_amw7rRiR&!guuGrs?=5QteaGC#d`|o>zXI%RTdGe;ZVF#=+t4DW~7nwEp3+cLcA%MC}HyMFyuQ zI3YP;mc<^A>`|>5#TN)X>5QSZn6RqhQwudjhEq-kKRS75Y)_yUPy!QE(`vivYM?8y zJ>^V=XR6^9dPG5b!_2F@z#xi zHzD}6vk@Ro*Wcy*4e+97r7f2JGoErrCW@5`!x$ z*(Q^DHM4~vl~Go2`5vJCaT#z@4OAq zG`q3*rlAjz;k~JO>#=2^FHw08IA%nTWwlngs`vMF7Fs;h`?E+R7+EP=qIs99h81s0 zwf1s8w|J&n4_drUm&qGG2Hvum7o0r+N$+pcZ;$XlCy~i;jC|1j_Ie_|5%JR`|Ms;$ z`e>t?ac`#_6<~N}@r_4ykm2d?{DX5R?2jUQJW19CsCa#xJK@FoAuwj(+aJAx43E)S zw(uluQ_(Ecfpr~oxJcFUsk=j7bUMK^6}$-F&&T8? zjHKJZ4Rq5$IU&yjhDU#A2^`Zg3XtAK*CJDHOEl*UwhJis8Xk#Zy{;EEyd%K??3=CkB||mBGIvx(ykgxvOCy zwxMWlYnB#KcLJCAWE0*F;e}ptZs7K!EcyK6ZoIS5Psq@2r?e>fd<8kWI7qr{o6%Io zVhMYIa~q+U!TbikFNMk?lfHt^U2SZM$ZoMJ7Qa>OPa}Xcp@B{Vc$HO}KqLH{p=4xA z|5wd>0b4(mie!pL!6u8#i=xb_4sZ=zatZ0Db1@v zLDoj?P{v)fkGoa*IeQdO9leG+EiB#(`1V7Ck>Ne8c~ZacW1oXEIjEbiKbOOov>R0) zsm`nLO#54k?<%wgnfBM$;(d?(EcLqJR&`{x+us!0-^}1JXRK9z2l4+6{f$g~Q#G#= z=WVy6nrH*M1H@Jy$h2pI} zugb5A@AtancpUww66~O0xTL(RlJ`0xgFCHoA*tS$*gGI8x{?e+65jdY^yk0`r<4p_ z%9r=}aezQCB2#Qvh#TXl%pzXFp4V!{q-lhb798ow1rGxpLW0-PC}aXN*Wl&ccQW=F zXge|^-K_R@y^eC4TfEu$%|{E72{2IyDCg#@u&2=Ik5JZ^M>1YCkkzCP|v=apP= z2QA#wmw}4}5@*kl=*Bp2>D^_n*qS)t$1JJ zo8TORXQmV>_&*w@_U6egDl=! z&6Aar5!myJZ@15z=v;kGG(J;)<1Jo>RetYb&nv#!vxu+pBqt7@8I)(^FY(Q{cv)6_ ztFg~QIXjy)Kf#6GcB)?!NKE~Z&+!{@+=Qfen#OmHeBgg~VB3ZC3?p%cr1&K`*=a#E zrmOD3VITSnnW0G!Tj3j-!InmqQGezwskf;bII=!q}2&ym8P>Xhbu z)fE0T+}}eVS~!LQ+5YFHWhs0gH_cgVMYjOV613dH#rd>=ze@KR_B^87JXfN7*J)@) zw*_~JZo7r!&@9`fqMP)Q;HEp0VEg8<45l2Q|(#-R`V7N%OV)JykJ$KDea!oP5m7 z%`w*CN?W*2mw}UG;%?!!dEb#U4#TSer!pFiOhfLhdH2O}JsfpKBkt$;-BN{^pZjYh zRMjy)a8il}64MvJ9u?e#>zC+zWN>c<{4FF?yOY?@BWcIAZ(;PA&$N+#A@|k1Kv;a` zZ&yZ`;~)na&T{otxF)tbs2&<;m0YIoUn;B*oneHv{bRz4Hw~^ODNG&ghDMwG&$8>F zg`^10cBYehw0zziY)7(((4)u%b4mph8j5WM8jmDX=2FNZKT~s@rB+$XWz5O=O+`V{ zGi?d{Q5P{sd#u2Y#<&0r?knGa(jGTEVQW&5A~N7}&tMP#Y*M~*DUn$g1W zmRmfU!zFn%(S?hpwB|Y6D6O^fIesmWjVQx{Jsk95F>;OFE%k3fC7zHJL-Wmd_EAce z)n5#h#Gy2L6q(YN8@brRWlM9AN6pcmwv>Ep)gqg{u4c<8X%5WuoqH$_JskTJjaTs> zj`H!Xl)71?k%`N6>>naC*^rifRyQSew(+sk+2Sq0cL`dB@@d|^@`3mcV*3r9Kz3`$ z-$BKxo={lmjE5KJCt<9?H&BKZT$GQG65liO0p3y0NKYcC9LK&kOy^rEP8@ftNu28J zYLSx#&$JFX@b<>PFOp&t-p3R?n?G0&$6mBB>&Tp43BzpE=Ad-yV?uDTbI#()c=!fs z-a;n6FEvlb!+F@3qY*I8;VD+BfR5;1W zs`;woTIE!QXPU>I%)siRL}aqJR`YUPQOwzV*R3YLFAJ=8n#1Ey`de!_$w+2)Ccd9F zPcE%2!M*|&rP{M-hSD9IEPP=MU!ih;ZzR#UxpvX_BiT+%HPS~CSy`= zgR^ymbxtFArXEJ)J05LBhSyH>?jc|Ip=4Bs08Bls)%iT_`>l6|Sn-X;Hw~>ohR0Dr zwr~|@7Bx{rluXwdN0~@`v-HG8mD>jAf)$_PJx3bDGv_~f@sjSg+wn%nVZq4c_b8kb zs4(?rcwuSK#P<@mL1-iz#}L{kPQ_QLtj+t(DGiUW{B0?|tI-Xdofuv{&AYWSPv4@Z zsApr^UJJ!bK5X+ocbqf5!d~>ROvKqFRcVKF#K3IImc| zc1*cDp(l}v?>6~Be&=HQ7_CB8sV{lJLF!|1w)V2g84J&}<1g{uiOwU#dqneg(B3l9 zALvwl+Drq*E5As^hna1&Q@MC_T&Y==aRt>whUeMH=}LH#OJ^MlKMD-O}0PT+wpbP`Bl7a&O~_J z1U)f>aW$z1Yd`2VWO!FAOgI(WNHh**aCkD)fK|FZ$NBB*OD6+f`9R{Y!b{DEvjA5k z10?UV$g&09B$AH3=3yi43o!`YL?&om|UB5p=9rbkX6E?!b!om2=K2 zz$fwTjy52}lWRz9;l8z4+(4ty+|qP7y<~7q&&w2Vhf}mfw1TCqHB1nfg=V`Pdet^(cW6T2`rAEGBb_HZRlp2wtp86DU-dMur|orb0}E ziQG-kM%9qrVAc+|dEYsoSv+YlsrXMuhG*7;^J*{+vNf39&JPyvGdNq(d5b5H%dv%L zBya|fmLa>r^z3EF_q}r(o;kvu#`gm1k{FH8j0pAXv2uz!pd^Olu8cG_DZc@Q)n&CO z;{t4Z9Jgfj#Lw_HlE&n>o465QUc9U#HgB&}37&~>etl+lC?7`$!`q^H%do9NU!n#i zXvRr`#FwG#SH<^((+FOiN)ssAkP}n%3NpM~bon)D#0&bGaM`pt6W+Ku7;1?M8VjTwO9jnTXv*mj|V$gbb2FWB|F z&lzL!0Q#qm6Rr@d0-GXsKxGR?rnYCBC1X!xnEI{)^Bui}!%3j~ke8W4F%| zY~Ju)@FoNgIw2fQfEgs%f_5TP!F_awk7ASU82h!M=yGDAjrJ7g7pJbpyNGY736J(6 zQ-H%2CVUIFJCMyX0kTpsJCpd*V-7hT;l-&mfg1SNM)x8UU!2J>e_#Oik;rDw)D2pl zYW?bThi5AI9eih?bYyt)JT_Zc*4+a4aHfuI-T-~wSsjrMJKHRtT-U9He+^`KV>M5% z>$b<9l7rW$gI#{VIS1kCq7FQTZ+G-OGUc~U^W^&9t2tPv{QhE2b$B-gI4g9-ISICA8D2-tliPK^!u|uY zd6jg7Q3d$Ba~Hhweh9o765kWZZ5HMA)x2l1^+f$pH>Ox^;#9#+)=P8hez8BCw($7M z-=^a`3#~*ZzPXwwYlQ{x<@PDGHlBhmt$5#LYcR*09`H;DsfO=es1-829hx@|+e9=S z*$w81j<2;}amSsx@LK5ju6q%d-DBxy=gGr>T}KWM;gor!IRE@fToAI%~?D^6_5!~9*1M|Z{X{N zy)Uve+)P)n3h}ROg-2anWu%44*g9bYwVV zbyP>N9Y^O;7KL<#)+vSEO}ARrO)ogf@c7T)6GUk@o0st?_M#Iv~TNF~}B{rL;ZR&mbwkZ|FHvez8qeqgA}1 zE7z@b-^XB^HYc1y`av;Y9|FQ|sZ!AatRB9NQF~-~w`-nUO?eJ`Z*+{xk!(r19LZMJSGrX!p4?V41pl`z zUT4jdL&|LI^HERg(eToBTUCen{BC`VCwC64!2c6u3T%YtnX3ynOX8CaR^qxN6yVI@ zRc^( z#C8_B?KoehiKLEH%_P5nYkXlhR605|Hpize`WYF{Q$atj@F|+-->7tZh74*T^F3-| zSdcsY)$vlj)uM>|O6fr2v}1%7KMK#WXaX{ggZZ{>{?lIXVmG~MholHO?j%xY`Kf2~ z?R>PzN>hzNY`j)oe_z|4+U;TI*8dvdQ`0 ze&IFt+->m8u(ucg{pe?l$3#>%|MVvxtuV6~O{1hLUq$nWsf8ybbJw_s$lO}_Tvz&G zVG>-6OhKn9SV;O|1baDTx1&t{p9@d!87QeIp~T;UUecvwhBg2mkGWuk}Kb^tq}9>^3~LDe2YlG!)0zlH1~tK@gRSoZ-qajIYf@8L5W ztwx4ZT1t<4l*9E&?17HiIm!BPcxNGTyWU+1FIGOXU4w6NG#(kAxzdu#P%{cGLs|4a zeiPE4!=?VF`i$Zgcb_dwt3OSq<4Zn7<)bplROxprx)^Eom9d*D9dkwszl8f5si(>3 zx;6N=4jO<=ERKATaRA#{+nfYYGKT?P#-83kNd`bcy4N)^>D35E3lynOAE=b}y zPxp`paY#xnaD%%E%7U{J%QJZNLX97eQr^~-!jICBQClQq(%IJ)C83Kr+~|H>E|7Ru zDE_@T(n#xdj+Vzq;>7>vXrzg=|B~{!$^DAd>GHYmJ*2u1-H#*@N43DLkR(=5K6S(X zJhI!&SwAOnE;j)r4)|LreeoEGen5uuU5MraWzb`csA!_>vDN0>vpnrRozom@(ro}G zLn!lNvT!+wias92NO4LqFJpTZjX|Tqq*ql1QnG?zO1Wt_M+YJq*w*8>4ViF;Dvo+@ z2KM8~UMy<%nc}JWTxs_Uc;+PJJiakqI7}kLo1l5}a9w-s&mhU(VzMXIou9@od&Mi` z%KZR_*9+gi=yPOve`#L3u5@D58`*`PenfQ$#VhN+z-55}7o_kv;JFE9Aw#PgR;4Dh z;i6CQlSfFp*JQevL{({|H0g5g8&EQYGVjXjxZH(0A%khJF|)DFN9&O8TRvv3-!pD@ zrfex}5QC&Bm+fcCdH_@pn;IWa5*<16#O2H%`n@Jj$SqN>)W8*jq%a=E{gBdJhFvMe0OVJJ8YfM6UdJ5m|m2O^T++$+$Qki z{18}SZ^fh#|Eb9ECTO0l7_7mbk%QM+PaIWysqDUH@xI453!OxUH&gSZ{3<-dJ@Uwo zZ>ugp)n0CQi&c!~_g;Kkqan!f)@WYAXKAM>f^1&b2UX`+@!jF3R;2U4woZ;Acs`F_ zM}~H%Dv6Ms`hSM~OJolvDSPG5RdF++WC&$v@Gvfapp!_-R1O1u6egeC{2uJC5ay7` zZ3pf#GG!Wtyc)Y8Dv3-OgH`&lJVH|w``yUS)DhhY)QDEiEmbL6NX_tVg?b^wo343# zvF%5Hq3)#VS&GiGn7_@_4$^3=`HiBwTcr{&j~hz%Mg_0y!Pn?6WN_aqTu5#)d=>i` zBm?-YTU4JKN1I@2+m!`?%F5SYpq`K4GK(XRNV55lZEwN89aVCpV_SLM_SLykO*e(G z)}|8H55Zly?nO607Y(b7!i9!m8-=DKd&uoGU9xwlJD#u{|1Wc!13p>Ec|OXir^9*~ z+pB02l4rKeEl=BN1X5b6iPm!Gz%#YE2H%Y+)HBK(uX$6k%|t7a)TTT$m^z!GqeU79`3S*Gy5_}L&f@WP2mA5uPtX} zg@S=YNA2QDbf3B{%9ABeslLIa5sXw{oPgoU{L;Unv2e7#OFm_zVI|HUMUl@8*K=RB zfFl5nL6eXP@GT9LS7hwLeiS9ur88Dh1y@sdB31A8-G%T>`#6Q~-{_A1QC=YmT>{*T zZ9ls5C3Qe=6Q_6yKiI9mf%~HsUoCv^Mvov9-^-dOFT&i2JrmgzgjIU%QN5|5dkkKA zKLl0|@x6eqd^yTnr+G3q-iEy@T3{7oQb!f18Z;WYF^oVazjxuAi25TF-yzLAk1hBL zzQ|q~Nz$W65s( z4_LgJnkUDS)7UQ{yFn-G{8HU)P28#Q_|M-$1DJWE&d9{)|NaT}EBEDu2Gai#Pjvbt zr8K@2-a0D#Yi=#Enu!eWkdE)VK} z#=! zEOf_fQQmKwC--qK!@dsL-Rsa&#Z%3rg&V#jTAeoxVJ!g7LMFZkq~yqOr=c_(Gz?`7 zTcTn-Qa-V=#-VcEl z7kuAFOOfGyt9f#bHy?31D3-%l86=gFsk^Ic9375ZG|Tk-C9TUtE1bazPnsXN2-7eUCcoUg@WuY&By2P$RbJ>U+o zc#ZIFirOQ?8>r)x^Ml^l2OvAXW|{|vE!myN2U8!f<2xFCh751M=E?cXRU=r)L^iL` z8>;*iubum&6<-Z}Yolh!@NN(Je>g1H+Bd$&A1(_ZAE^eOl+M~1ga^W-k3z1R=r;C0jG*TwJW9o!e; z<@d8h+X8Y1|BDvyH^uWW7+gDwzKHDMvk&=YRluES#U)Fl?PNUmf7cnOF>r2(dC1)Zz!dyD zILtuHkqM}>0)+QrJBW@WyQ9w40jY+O;ufqH<;g3V0&nn;9WuOTnkRS1T!*~`vMVw* zTf=zRy$hZxc!{qR{&g*$yyTG0kFP8CUdWDbYqt0vai6y0OT~92nt@DwvQjU+jo3D$ zUC8Dg(LB{K9(AWxW0`k4g*h=s9z!~ayZqXc!M&nzAsI(*$6g)T?IM|Ri4osDYGqUI zLTifOgBFJwp==?!kR;F9KbM13C_}z}%#EoYZTAE58G=5vI5b(={EOnpu@`tVdpueC zxS+?;WTbGVP0N=svGCwq#^irSwPH*^+3ylMEphdx7wXP*C;b&reK3ysMh<7j=HQM@PI z-tZhhOM$>G_*Ov!k>RE5_~gZZ&RF^{vYSWEnQ9zT{qsq8lNDcge0!l(WOya?aaG2l zS=i?zyA0FxajS|S(^Kv#cxGH%hwtZTFETuC1@r5p#5l$vR1w*{%xt`Fu2&;kAM%)A z0{-=psb775=&zHt%fV8$>(}r8S=4XR({5RCaef4WKnm`UqbDpJ_d5IG$&EGru*<9T z%Sd@IQioGP()1D+eh4r0j9b43OAqoneh}V6(Qu2VUo7^Yr_@eJinF0--7bVcQfx5J8LiFt@STl5LWWmDJ`kVGYK~$*f$aDaXpT~3sLTj1;IAGCcG2%v@|AqqWFxy>oSbReaC8=~jH-IT>Ut&ws2Uj(^zvzyr6)nHR_#Q*2kjd|znkU`0z}wl|p73Oo z?z(>g0glVp*L@ElzWyff`z=Bu519ZPsjvKZ-ZYyOx?KN5vno+hde!b!xS4_Y$)9 zMsSe3&I<5n68whpzY`5m4UmCQCv1xT|d$?Bg+Vk~wh(LjW?>uwKH1ASapMVE+!;5oY?;ImG?2PBfQC@Hv4h z%#3m>uE&B@Y}8GI7#M;l1wO z3olNk3Dm{E0cvdVKF~brrM90yiNz(j5rT^nN)it{}}uWUAwwj!&MY{}X$FfNkcij%rX>&1IDPw#Acc zp9S$Rj7<5(>0Tk{tnoQmR(!ixOLpIImsmJCp9H1MGIovv9LN5!`5Z zXD+xV7ViGb!~HF|W^cNuEL>|a?a*Lk3NJz2GbT7~ky`$nW~Vx>>hnUZ(lwZ@)D8SU_K z6eF_{wdMb9Pie#aPkW`65S&fZjR2KMAsd=S;W{c=^MZ0wjjOfkOQt{ zCV)?0EBz83j;!U6z@A6$7On#qn&75T)NAGQsGv;B-z3FcWNK`qqJ?Bq{yX+_If&gE zeTdOrYDIP9huma|5|QD2qoa~HfV_bH6=X-21xMPa8crspF;H&E{TaLbLP1xKT?^(!r=l`w z?G|2UzPH_T7EoSr@;izCL?(M&&+vhgy|~%j<$&z$CF?<7jS7=pHz8VyGPkXTejdt#kk5mH-M~DD`XLkEN`(u_6`nEJCm?%9RmT5mAuR7E3MdVi<7qqk_or&T5{tyBgT*B0HlQx}B(Vs`uQ+@Ju_A*CIE; zzm3IfL7QOnJ6d1t19R{)v$ebT-6yR0M&LUZm75=pPi`#~UZ(}rH+l_;tq=WE3a==O z2(m9m0dr_}XTU2jAK40g%qbcwg-m`Qq(88Q7hy|BpCY^b`tZ{u!mC+d+-AAEt@y&U zr9$X7WOyHG-oq7{iC|9?5ubTY+GO2t8C=*tbdSL^Hfxk5!u;IW0>My#BO}O=v3ZY zq&UUc8%}8*mOPM>8z)l_ceG`;xo#ticNd&`sH4TJqnu$bNIiAOnfhCo~&;V$NmPg^Ep>{3)PJ0xl`boYLKUc((r#9#Sp!VCTpHtz+04q zCCx)NsfOWSQS?dk-Q^Z99skvm#^No}JUO%a=6~>Z3oqk}1@5;1&G`Nu34TEPkjd~B z9PHV`GRqAu;i?w0GrU!2xQg%gv3oQZUUAYG-qn}j9m&R9=w4Yr+FEXgAJqWW4HZk=hVV>%$jZKx z&T$Kw_&(4)S=n!ky#un(5{_g$elK-9!ZQs}?tpzB|KS#Ix#r2q?gH$qk-bh3d!Nd$ zD!*m!3-Drfez)WMEy}+<8sA~f>xAu5)D77;q$D*^`Bfbx-5qZ6X5YX85dTTYbdXzA zVfZiHGdCkj`%_&*{VN@0_AVOqgy3>_wv}PI!(}e8T__(xOOLCgfpUjSg%w) z%bymkYS1g(Pb{9?(Ix|FThf>Sdug6MA;=jZr-7R@i7&L${klHWPx-t#*d9s>>Wxfv zLlrF~^T&6wzmM$blBo_FrhA;Ilq=U6@%aROj|^vu=E$_M;7Y0t+2dZC&spsjY!IzZ zd0*dc_}zg_?kf7@Y{0*lGYR|55-h3YD1NFkarSPqlz!zWZdnW1k^~Q+ZpZ}IP6ICv zqOD=yfb8~L`%Tr}RQp)t-VHB~EX#Hh-@nm6$nd6U-peJpn_(6G3dtSPl{ijHHLlhD z^`|%?taW=^y!%#Dm8df^ygxNhu00h0gsY9H4QU29RJ^J$+U@sKw+wdEA7q{~9siG! z;T4yXr2k8Weu@1XWaqcgCdE}(oYuJ=;l=q$Sa-(vF!~)Cp4^DW7B04yxiPAaSe?7h#=xbznWJflCt@}9kv&e2Jm2`a9`+ghTI*p?7<@=Q5 z0V;$H?VMthLqbzH++RmkQ!KdStyJ9<8I z_rat3{q3&xfj|PPj|3y#f1P|FJ~`k%i@hhZd2N_*OS@4|Bz*4P+&J3N-oSS}T8Huh z5ncjf^IupR*g$7P_V^iCu6SxV$#5IMGwnsy&JOQ8?56~{bQ3m z0A8F*6Oc#e`r-dFioquFl~v#Qi*m2$U`ak@lkxNLK00t_zRm927H~8P#-i!S1bC+g zevVDH&Ft*}4|P-xS~b8e?lyR)0m`kj-$}ZSQC@SO5(vw!vkzhKiezcdj53w?+XtYn zZYU|5;VJmeK&O$3?|IFe`5Dt-l#c8QN&dzj-@kCz!!s3f!{> zGb~4Js(RJMrOiK6!DmC;U3s~TsgO}5coWS=Cc~*3cmbQgWn|CrV%-8&i~h=e0A6|R zdXd}}!@oE(JactUW*Akm--+x3jLnwe9quTLmxOOq)CL*eH9`N6g~wo%Z9IFM*KCtr zfM2`wE#54A=b+D!;nmW-0O@4Q$KK|3%f|c0-44$*7pHU6Ri)qC#o9$4J=-|3M>2|wuew>Wb;Pw|5DMaK6biy!ppDH1mxnO@SaB| zKKg@fK5rQIoV>Z&c)Q$(;FRXCwB_NS;3tumEf70#q6P&K+X$zQT7W`Vkr487sg)u%ALU zFDV;uxBE7{nkr4;9KJD|8I_RX1#|^JyoDhe4M8=Bao8NH;v2^?P~vQvERgTrs!dq} zIzr}u2+Cy`cPmpYWN_USE+m&>p26M^*+<}npp^6;H>qi~UghV_CgJz4#d%qWCF}j4 zV&9DHy4XrqB&>*^wY}~DcxD{<7T@pD31s4$u6c4Ks`Le`Hb@52l;WJhuyT^3k8En7 z|G`~KHW&O(HvI=bTH)OmnO3qy(f;$`$9_qX7W~nbS16fqI+E}a^dd6htkmJio%0`K zUxB2U%n$Rd%@$6Ud%)uD!gmk)5t)FpG*9l0K8oEgDk&z}q}dKSMu5Kr_qk^Pntt$I z1)33w@@qI~$s;o0%%F{cfRV(Sf}TzVRs0;+@jG7qPvJh9SFMjL zwF38(TNR$^_dQqwoQ(feWHNkGN|Jv61BEsRyFG@e?E3d0oj6W@X9f?r$?!~tEWm#W z+K)_yT+qD6U$UBtI-=O>%s`nT2=9-uE*YnbMY)}rle#~$tO-f1+UE^_aS(ub(F%tJW4<&cVB2;A8aq7 z(Wq!+PN*6(=VrZSPqy=(U){mvZor?gM+Ik7neX8~4;kEUg$v2G9QpO86?|tmwyrcb zP9EGTgyraL$^(s`;`g=1IjF;u!RH+I@K0^&V$XSB%Mm@q zsw2}MZlUH@>1*C-n)_4OB-kZO#yxoI^lM)0=x()w1dZ=kSV~cf9YtCZMUv@a|Eu`&Y9%d_#jm2i{h9 zhe^e5xK2$KRDMsp^;<-FXYu_9HU2ir8>xBcu?3lU-H48~js1K;sz8#3`7)I53K@PS>N4WpS8S*3VO@hWH8CrfAD*6kn0b7#be$*40 zV)|19<@WLSv44#0qOUZ@UWE9^EkbiKlUzeb0V;d%0b0OjJ}b>A^SBRj}s`iTUo zis_o5AEg@8_61CMk&<`wsP}`3Q^o* zypgS#c?>4jK|vYhKEVA8WN>T6ivsg+$B-XLYK9s*OxoRrxa>VaeTq_hN5@ z?4xQ1eTmyHz3;5jYL8C}dK8(k>WdqVLta4lGy@h+)) zlAt$|5^zx$#1=D~f1+LJO7AZ#2>GS1mq;@JnIH!H$#^#>-^p**$%EFC-UJ|fS#=-E zA5O~e6>OdTz&QleFbh{*BA?emIwvvc8XwRlvi zZ2rvhf7Qq45fY!{ZODc9jm4XAnY>9Oh39&^bK&i=cvCKuci887-tk;`2Q1!<%jB&X zCGlP36>JmjAErGYv3MU`CU5u~!Yk^P%Y}E!;?22C-fo|FttT%DHT~Dbci!TyxlG>d z(ZmH@L$7>}mw`OAhgmN&gVoQ9=AVn&@5wyur!M9_N$RtHYI)11q%LBmKAK1B z*>Cdq8pnDslNWO^mv=-KBW-ajePJ1EX{$2lxdXes7;c73hRVNv-1XjQ3nxEUc_&F~ zTevD3CwBqz&u^kmA4iJN4cX_9$)%=Gd6y~a0rSJ6nM!f!-x@cnp{hD_|$25~#kZCqUbT~7yeTWvK{4|?3H>+@(Wjh5g<9!Oxj2vI! z`!)I<86K}Ml*;p8AKW>M-&8=-;}(=qytoy1Gc4QDKMSy+x(YnwabYv8#kSjRBp$@v~ z3^P4pyV)xa&kQee5|obrN+e&)4DNt{i8uR6P#TIgRJ!nHY*JzW zoxKURf>+zh&lmVgPu;=Z6p%wZV)JK$d$3FMG)so6crIR)sn-6tr9H)a_uNn4lh6LL zp$xYBEZQ}S<`31sV%HPo#OaeskyO#^luIQDY?aF0>Ry3(0|`Blgb7J|D^K zgj1lhC+|Eq4e(ifdZ7WxaC+&e{F0rR33=UznC!#jzp&h{@cAD2#*c<)+X#bk&M7*1U>7Ab%%Gx3TrPu`_Zq+aNgG(xe=nPjdaq{Th2FLW@m+^TOeT)pJtB(nU<-K5~nc-AL_K$RT zsA!)wSN9U&nQ=+({A`c^xfNN3CsW~+~>?Y(1VPJV@Si|Gt9w|(K_fOGA3-_YN$vRxYUvkGWRT}gmxTHi+ zUSn>$gsdVsBq@qaNq?$wvMNzB51bs@b_lO=Jx|_qZgLyJ|7KLt;%(GCX#sVx=ayT- zn?74`^}XvYoGH9|7H)@CcrEhAo$zrDym$-O7Wek(Aq&TmST=uMsdwJEb#o-ThTdHk zPTtoo4XeL}`(5K?Vkobwv-_W_Sbv3R%v`}W@>=AA8*Jf@Te!ULm#6IZ3+_;`vG*7} zQ@11Fj6rW9(;NTPJXz71iTy()A<9&EL7`xvydEOdG%U#*3NKcr2@JRrAN&_1!~09~ zWRO^k{c~ipoWgKhGux2U#G7RCw&D8?%0#B^5rS-CxlJ~Fh@)sZhWH9<*fPZ@)ASwl zr2Ovj=EIXsj%wH7e?7VtnfT}tGB95;8{5a|6O_fUx{7&m`usp(0Q2H9w7vP@LQTCx z$#i@9TvuM(_!G_tk%4WIzeN6I0sSBBSNxiNL`;$>0?oX0P|ga)e_6JJ*EPswv5X$& z?NbN3MB?lP62rY-fp(nK%jdfC%zOz_Rz)U;@+x&mo|*5C{Uu~~sI~rW8_m5qC<8v0 z7~a8S26`Wv81B|Fm~~7|NL(l>Lic%3QV;4Sq&^cr{`W_VjF2)P5eT*z1;%&&KzAOLM_> zw{XAeQojUl%u*@z2fPdleVTms*Dxfu7c7{*o#j7k7(4vb$=;8o&XUh{`;%%Q8jeg! zozx|6F1`Qf{sg~aw(|-+NX0L+DQ{Vnzb--P<5M2=%0W3Mlz($F9f~RCe-!0EIhmeL ziqv3xulj@0<}-_g^U!)LjEIn^rc>DdLZPG4u~n)&E897J2d@!4(>vt13#DjpAdLw~ z-^2ZHK)Tu!7cM8DnZb@;J1Zc$)$3*w--%4=Hq!yg6s#Tg&d6TYi)CDhw!==|lNPTR zzJ1ZF$nf|Tc|U_P-+deVOl0$pY*zh5wd;qx36yu%3W6OKoR8}g6ySJkaPKKxNM6$U z9`;X=oI+())T7BVaY*rMwU3s&JWF!L9~|S5;anvjDEE7?-G`Eq+?*9(BD_DLk1hQ2_OP6CKmfN+}vj6%manjmwCmfA{)QD;o*vSnxQZ7U#o znb|}5KZy*lz2?buPJR{V7#ob?D zMOM$sJ?!_h?@6y;2Zr5GrIkvh9>n`sWLoJ# z6`lVpK>es#(@J+pic`U-ym3}I$4Ph^T|g$B&NOSbuq=lZIYm(*ySQd$%U(Bco>g4( z0MW&JeVR$7=T8YA}+ z?ZbXJ2c{BTiD{l!xMQ@fUce`YX?#Is3M*Y_&b)B91mD?(e<)k#dU$0!GR@s6nUfKx z6y6mr+9x_Hp~-clJNeG;L1+EUJ?GVda#kp#f(f`ZM&pqQ>VU?yJIxq^1|S)Z4^>hf zCoL?V&wCGAncIucPpH>*=i~tkItnR=nIc zF2iw)v(bh=UeWyFSnkS}jBy}LTqh|)y}U0-ypg#p1o48m7fM=XV?%*5*hWIEen9fK@p&&O^$+h$1->h1kb>P-3kL+~p?T#CzT zWP&)WgOH`dE!ejsJBV06h(6wV3f4?dcj2=K-S}6OlRqrM2Ev);x&DBC3zC8jaIBM& zE&oQlU|;kKbc*s$CvaEC-xM7(arM=_rstTeqrRx-NS6kx&GIwk{(T#cqNJVCPl+|>~Bxv^DG*L45zwk9{w8&w`2bm*^ekB zaQC~^oa$Nwyse$0$G8F)8R$`SWO({9((qzz%h7h!pKf}fjEd`sUYu2n#sj_Y;F%UG z@4wAQk0^i)FI~qc6V6K5Yam(oJ9NFe(pEl2aaD^NFZejQ;tmDqZ+6wm(pTm|$RV5;qq%QGY%oU3HJv@`nPid8Of*!g(0q$I(Z~WG7Yg z9?r*iXa=$e{TBP|?l#2h{1EF3UrFJd!1D~MABxhpDOzX^whd?>vYXT?|B20^-g8g} z?0_;VSmuggpaN=uOi-sZM&1`O0{d8GH}Glx^AxGx5G!-?7OsW(eQI$WCaY{=c?;Js z*nda%if^+mcFhm--X^THuL)~VNLENM;2ulgHer=gxR9)nCS&h{BzNZ5RlECDKir#R z)!|@#hN02Oa2n{a?@Hy>8hEc!cukky0_Bet;2T{%HVRQ;dR$>RV_eUL0eEJ z<6Rb|FC8yqoOq7#u7qpa!p?%h!1w4lGMvu~;>IywCK4rBL#u?=l0T7fN{*FAHPVYs ziM}=<5ue7W8#0_96vw~1623YZD1nlSN4v;ceXgK7+$e7#yqb_@OTqVXG!PkH`9l6z z{$sDpuxFsmYINRODz3mPmCpsE#P1DnLP{WzARpO&!dK>9zp^)@Z(YrkS>YM%r1~8#Dqt)_Y8HOKS)36%Fq!`5D-sM8Ms@{s%hq1Uc;Bb+a8{<@jpU}u>v4}mCakGC zEV*g2I`+GA;F1W3$Kkx=R#^4$X@b&`;Vjc({on)x2hce*>rS##SCv`9J@$>;# zX6XBlus+R~#+CIc=o@5k`L32f8wkz(OpY$Wz+@!d$dp$4aw)CxUd4y0V&9e5QQ`9& zioGVvd0276GT8LNJ{H-heB~Rdq3aQUD16Ji8y+p&-`3&#Iog3tToX0V+(&tU@9cXi zN9fX5ya`?#c&0Z0!1oloXz`|Mo;(9potKa%BD^bF>IP}vSc`W*zU|R)Wa3+) zc^9z7@H|mLWDnI{`GE#$x{5c^TWRrH;M*1@Bhw8wYo07~&7q0dEaAw;Re{-ismW8p zN!}M0uQQw{&>&>u+o5^#IL#mGccRHgUd!hRC_d1SYa7OYf6 zqnYY;Cz|vu*gJwZ72|RPs)!6uUZuq5|H^DPruKL7ojr7PO_8ssd1I}xlH0V)($UXHn>hNC~FT$PUMQA%qI&MkLKi& zB2vGB|6GbbAt@Sv;8lM#T2I%JPD-Mrm42p5?_a>Ij$NAKOh(JDi&ec#Juw)p`&kNR zme-tMw##S#76gISv0%$|FjB1dVb7w1YQ}Qy_@Jcz(CbF((ek;jJm>Nt9*-eYAlp@H z|1~nNU>}0)DxS+Y%v1l~8&EQZ@_vlmGVrFjS(sfKBP)#ZB=#)6vumeMieTn=>6DBa z#^>X+7=3AR_G^y3dbLQ2V4xJT>n9;3wLI6`X>sb~lZ5&qldUs~6E0Sgl1H~7yTgw@ zV-MdSdB4FkJ!=rYL(v#ycrU9j!*X<=hkY56K}CvB9&t`3e^P5SPPTd8m7RGU=vS$- zY9M4aVI3(bF`FtGvAc<_obEoO&yI~<}z2TD-q3r z?CodxVQ`@ZUOd61$>)D!WPN29q#uyU+c-t@-z<0v`#EIST^f1gQmmIiRB`f=E#?N^ zN{pHy!AkbPq?P#ZNwh8L7mH%=&I z=KeJHzNm9UZY61^c(YQ}UX6~6ye<}RAihJu zg-lg_sQ~_OiI*!y_eFL%>ALE>$Y>o{;W>{*vsWA6dgx7LcxNNCAjvadZkzAF-F{D1pAf$*zqRZvyj1+xyH|*|J;^SCKxD&>`|)FIEibOmrPiu zh2M%#HS`fOoR*3cE?SPs6KaUIvVzrtNu7))hptp%Mf^Xv+M8=-Q{Jon4gR~3DfcYR zlY7~I#%>px@MM!o<_U6kB>0K9+T#6=|4Cup9F6Z!&65i%@z`%eHnS(wD8-Zj*LYhj zUR`|aqgKe|_o||PM*KS=`ePr81pR9iizYi_W4T|GG7WoDC zohaLgr7!oXa{JUfL3K_$MW)Aue#P|%Pp zUGsRfm9?(GWv>bxppfDGKi19#&ZesU_jxm6ZIy&t7YFo-@vr|NFK-pPxC_dDizl z>%R8dYwz9Cx+S;sT|;;qqz9dqD|CnTe(Jf3cMrA?qIt;i-eJ7vNaD z8*H(53S0dLsXgGib5^(TJBB!}IgGJ9xhf*JMQYz9-{g2W;9j`>RE^AKsoC(-tbekH zCKuK#iZ{jbWDm_O!b{?1{|4{rQXi&{RT(H1CXYyKkxTH07AO_wsPj1CMy;-9=1eyw z&b6Db+t>2cxhezYGWbQk>NY@Uq$0>%5& z@}&L$L3ru&&8){gO16#V)ebXlW$I^&Cr=5ehJ8)s{5$!?(D1M4{%7!=UcBDXPFI+Z zQj6fZ{xcI>SzBt(Usu5ATHbAhbwIkYN&d+}e>dt6%A@~Lt5TCY#VX+9&Ri=ZPA}yA zyV~;PqSDF#p!24ph8K*q(vT zLylM5^gbzam&5ghw?*>uhBi1P`B$dB`D@Delhjf0+^ne+w)dm)$nlzz_Z%rQt*B8u z8fl64*QGANtXGafi- zVld><52=qpS@fh(>S9qJWgwR)H&}{XQM{AzE=Uhql&M@z_sSyc*`W!pmIC315pU(wwAjOF9R~@wTUqgXfAX_{~3y*x@@Pt4eNHu)pQ0-ISyNynvzY7 zR^Oz)k2mR|3FoQA>xw=?F1H>t-=%E26i-p~GDd`fjE285%FHGQ*P9;vhAYJI+tjl6 z((VR{H(4W$H{FQgyxAvpHi0+!5+iv>>KVjd78kpxiv4K`u@6X$xk=xpUUF}&Ba>Yh zy@@;!xx{duEJye*MOo7x!*{wWO|?a3vUX?cb?~a0IFVPdeFJS(yob$qDWCRa*YV|a zF{lPTR5?2zA9%aToaC_1eV_USJXiF&&A1~I`+dmyM=vNxN)}b;_WBIXNTz=s8=I=s zyN2QY5@y7%)aO-tr(rt_%|$M|zq7m#2zwHaPODT+IhYRR4>!8%Pv#wyoL^{E{ zZ2f&GwA-Khh2p(PCwdX~w;{(Xvb-6D%|Q#1=C!4Qi<9BRAo5%4KE?YU+r6l4;~0-? z8FHk^R=4_uH$j>=HI8>6_1G@4^a}3|?0YF5XC8m?rV%~|*~w(+*B^1b-&3o?b2E-r z*sew2BbQ#XGUUlCCr;rM=xn5U&0f$$`yZ+4@Lc~{AKNR?lgROIu{@c6*K0yUN1B(; z`)VcsDu+LNF!e5#-T~M?i;9rry=Qs1Kh0`SQz|FgLS^oWzrq>%mEmm-?fy*d0nd#W znVIyDs55fBTcsva9)$Z(%)BxZ+Fhp6;^g6-$%E97|Y4Nvj} zg7#NMBM&2aj^>7Rc>@h;w+*<1Nr#uG(mNX4u_zZg9@jwRNZCi29KZ5cFNlx-&XkAY zMZJ&UrG=I}H{@#8Z%}RIc-7>CP49mQAAoi+zv)SuCI80Q@--bylJ~pvZz8s@qq)fO z+_rUjBSwvDqLGG3k7;ExO?epqN_kE0=Q_t28gqlYvAiF>jvQ^V@h-VjGrmKU&}2$? zUq6$|$~kbpbUeC~C>+K1k{#uBx?M3eA?=kUG zQtT*rG=Ftw*K2Pw$s{Jl8>V=2t=GrC5^}spEl;lXRwukB(wQR<;+0G{)A!Qe8}MA? zlzDeO?3*Z_-5(v!yZaG7q!_P`9c>J+jQ1|tG;o|`_Gm08pk>H;x7c_WZg)KS+GwOI z(p}M_@H*bn-ltGj3#DJQ879}EmdIgFVW{Fr?m?Iwz4)s!nPeKbAb7v2%#wwtr?7hl zNr_6KWr`U!Qx?WwAY5mZWRe`rj5dzPlS$FC-U$!HYWgVb$D>8a`E|SH$)z9vIu;p_ ze+}0Yt~Qz8F)p*pd6&RzVd6xZVcQZ7LXPK#z6)BgV-mGPRYtO4$fR0)D|eo$={v$~ zIM#dM0Wv=qXO~Ci>7yetAB|jc%b46Mbu6VYop8xAIaQR?I<91U{cxw2b!Rr;=c9$l zxx;Cc94T^@{71qMpvhGzhnmKnHe|cF)jdtj%6o6Yt0x~hqSv!dh{_`85A#Pk{<_Jp z0<#XeUb*Zo!x2_x9-z2!B1y`u;C%qk7Fnc%<(;5-4U6%%z>?b0Rh7tcNDc%*uctfjlg9gmWvtqoK^LX-6$V>Hpg4fx^iJW2mtEPC2M{@j? z-b&|C{AVyTQoM2pn0dS+{(0WfU1I}@yrboOSQjeZ^_Ew!GMje^AIQ|uZP1mxlY>q* zW7Mnga-zO>CO}spHxWS!xGjHO0r#;$Dd0YYKaC=ca&C7{XIsFgGYY(`;kgR)BDSN^ zIOGcWRm+o=@iz%iT=_cgQ7}(^omd$H^Wd{212K+EL1F&o$7VaS5*I4OP4) zoZflZH$;wCA!>NLIQ<(&_$btoW+NH6Y&NS~aZ{O-yjL_2+hu4a5{z_E9WAejutc4c znR1-$%~qVBu|0tPM6MuaSdP4uss+=55?C1pQ^>fcr+6#i(Qv|}HTJinJCNh;w>-B^ zPgW-6`nIg#Ng>EV$2t5BaLJXtOtha z{R6qW^G(Us%HBl}vg9M586>g30o{e1cV`He&RI5ak0SgvB-3E`oR%(l$1OwNLwMzK zCl8x<(PHGhy3cS@u4*Dn8l38nXV=$nv2wO$oi!a#W+a{I4T48i2#=cBUx+S7u9V)i zye5Pts)yz>UKMW&oC=mxx-z#$VBZ|M^tl&(E_sd#0O3y*(hjKY4b z;<;(6jE-{T72^$#E6uaLDYSo=PT7001p5z>%eR)|D1A!?e`W85p4Ej7gnwwi8ToIK zad}Bqz48ymfFA=|hc+RX;M*+l-Z~WGjjYZh{ot#`aS5*G-3Tu|^nqR<+lJ^?eE17k< zj$x|JK+|be_a-QwJmvTU>{lR{fxlRuJfvYW;q9mmQh{CO$zRF91GC7$9no{WIRL9! z2W!z+Y$MW6PuAe;S^sv9qHwTpj9h|Gvpku*w;_CS`NI=@R%JSXIV3pqeDC;& zW5ch!YW5D|+^KlySzcuvmi=JMuqmE_=`#GjExelE8Sq^G-2+EzbXUc@!17#;?wO!K zeqrS#doH}y$JX*L2I!hd4?vHje#m8@d%T$3>@bV)g{UXPue;E=E3U>|;5AnX{si04 z(O1avuD1?KjX6Yk^39yjsYI7sWeViVE2I=I^t!`y1>$%CaUAdFf8f=yJkvsId)e?> z*aE&Yi-mhw7b)HomUoEno+NxATBI_undL1ATU;G)3Ov^}zk%&r=x5~oi%OqL7b6>S z?_$}bCtAm#vAwBD=NNl_U{201^5((g=fYzaw(p?T$nnmwJh_3p%&pPLNk~60a07#! zv^q2YyVzT$c(t&-7`=`h?^4UVt8FxLAL@%_W&HA+jDM5!O%G%ItLuFU&()VNvE7dL zAjkWUeTmp468c+S9nv z_N$m?+Vj)Cmd6~L<8rS7JXc>vU^@!EgBNxwrAM-(%$?v{x$IKSN_S(H`B4tS3LJvd)c15itta6 zF5jtf<=fDE8lJ0v+pzr>rQ8|wFGU=c^1v>O@Np1zH#YI_i_~P1Umm^*ng#X zS6SXSXHuV;>tBrg>&TbphPTC*hgliR@TS6Z_2qhOZ$eo}Fm!W~ftEKhof*Pi)OWO! zOa1bQK&db3N9p#~$ooL?&Z1pDi2W1D@pfCDoNtXLJQwNwTN#&sS9n|Cx%wgl@LSj~ zQatw#?=6IVjrJnF5oDL;k?kCfz2t7O^wu3r8n8d^!AmD z<&xZ%aEQ32m_@tPr5Z;MyZAeEsifvA??#mxIXx>w+;S>D=XP?0&ngcHPqg_Xjb(FrS**?9Lhb_*1z zqvgo*!pDTKL;49w)L{g zH23{( zxH3QKdhZH=u6v#SCRYZD)B!oio-n}hIRP&cJ{q-E_2Tjur8(c=^@iiR!TH#{hc+O` z8KNBfL&EPfYn`&*DUR(s(F{wKC7qF$-bm%w3D};3>LbUSWO?#R->(S&0ZDnf`kFJ( zbgNV;j#l0jc&>gl?843+bkd9sD2knqouX11}(G`)QrZwbj<_A%`0 zMOcb=zar;dCFb-T;f)aUZZ(&aDbS1q5~J14-X^?pl|rsE9wP2(55&AlGx1Y032Tm8 zA-$odN=1|Drjg&`72(Z>)v$*|<(aDYVg4|3iId07afHu}89?|TB=yVHv1MT+y45S! zGv=1uK{On@mlfwa>z4Et?+63wy0rn06rypft#?*Wwp*>it*qz@OxK`I$hmd1bxTfl z4-g*h8jsr%x^zk@KpX^-7)ra6RF-Ae~wJL$B`e4z%a8k5H<&$3kkr-TZYv4KS3$YCzUH zVq~`S?onxym&-j!+(%UW;WkZjuk90rYY$9{cv%2xDhzq;y~h==Kla(^S;c$F^5o{W zmkBQ^k8(eeJnG;*Pae&X&(-DTtx3dqP0=RV)XB-ZdOm2zHi^;nPH&2;Nb*>u>BOC> z;!n2T$PM*N2~U(d77u5B3T|YyqxYWTx%RSxc&^OmSzbx)rBz&exy##mp{nR~Y?8j8 zm48buuUPuR%I$I={|eVjX5H<5MrLi1&)LaCXzd3fB|jMRZn>d_&mum7@Ym1$t49cl zWjaXp?d0uIWw`W47Ll>7p*WRkb{yfmEm{$N8`3#fgDHe~XPRGUuk>TFOGaI=eFS}l zT&|^sxJb%p53^4MHFzY-i4L8hnv5K;oirxWD{FM`5xyMh?xvYd z@8zN0eO@nkuAh*5J=S8s9`VcJRHwD&$-N#r-z1H4m^1b+-f%dz!k^|M4Dr85dyqt@ zQ;4`TN!g=vVs|qG&rIXD=a~E#R{6?2hV64{4flJ~R66CE?p26W4LKeovK%S0ly<4* zwSp%ccTn33Hi65DKHx2ZS22vj_u}{r?88$W zv%U-+eAp}BE0%-Pi7*F!f?N(>V1cssaB2_MZjh`!tZQbV6TmxJM12@!fSfpR6x1S%tU3l1iC^P2Rc_m$7p?}Q@t_#Q>O#?ZotK|Mma zZ4(*WBt~X;?@YXO^|zOe-&e)I-g@KiDN3}dta~H6->t%X)N89!*NH4104rPZZn8WX zTSgGRF2P)Enq>brcmqrI@E!n|7Ul@&A4C|7UPZ!@2G-sJFG^}=Q@%+=Ck{;PwN@ujkdhI3A+#VMEbP3jV(^oaX#jKpm;A}I~t8c&c8*L zCrh_;315VSC-=Y0{mT_Qm|``&Uf!3A_W`ym(KpEP3N25T_D*;#8o2=J0ebL@rn(v4 zf4qY#|1zvyoc`+^_<4B$GwZ-xSr`r;txbGBA3ugmLt38@(F(*>4bK%J$g&|;Yc6v zI(V*NS79p&U58vkQ|ve`3EfM$y!Uy736|&j5N_FObFmE?* zrG-v0)?m{a4ML7%CX|ts%zkt^Xd>$UE;m19aajoV{#Q&gO*inYSMhP?|9fyNToP@D zRST5FFVN}o2*L0;Y)N$ZUScE<@h&3vc=`NS?A9u_9mo%hT^PoG&TB2d9T)o+6}xRo zzx|{9_E7I3`EB|9*KfB|vD=jpyHH|e4)caS9-H>uO}zV1R~7$q6F+woswnlh5Yc_G|jn7rg@%=iYr%oa0#rl1Hvw&_7lY z#}bp{u(kEvpNWw?(mSCKvrhROJ}^k$J$I3c{d@_rw}r8Dyqd(`E1xf}Ppm6Y6BWCz zv<4nhC+9df5-zid*mlmByk_#-zYx2DJZbF?Ebc}wAC`rYBgwLbs~h2~ABvxcbPgN# zDDN&P`-PGfl{aZThUs91nQZ$9nYWE$o>=^u3mYgNE*^Qk`^4&vJgRsGj9JLFXfr*D z)tf{Y8Khok?Z=h*rN(#@6i~+X1;ExR$5=3sBi!tu@LWBV z&9grCXCjwh43lys%gS0q!ZVBU{FB6BtoOa*lqTqA?AjvvR=O^#n;gYncQ?+f@I}nrjP&|M<1m*edXu0G{R2waDkW`KVd*MUqY~Oxfy8J!$y==Q zX3DL+r|u3e>!|qdJ#`s)Bj=fk^Cx5YL2${hc;Dd6c=;SQa&e}$g0(8anL>%t^i?mV zZ>*r2WOBD8aoef*=bJ1EH>p2JcnQwr{wdD9=2h-XtC!CWWOmwv2m_EXr1n)cuw;2E zST5nOBb~oJJ75%<>|F|Fzfi(KEDx)B$mQ=thH}^dI^~e~@VeKM*m?4~`VwL-Ln~D5 z(So4`tRYOkx2-Z`r^IMF#k;4kX$ew$W!L^XY}TvzH6=DJ`wPOpMv@`>NnGA^GvkyQ zIAl>m=k7vhW^IycWfHvMn$XuPEfb<(&mD&BTew>y?Gq zOYv?i#;b6;xpO;mteM4*Q_+2?ZA!iP5`?m*=0x4rRjTt3Mo>K5^vYvH(xy3=%K ze{E{jXDZ^C9MbllCf}RR^=2i&eWq}GjtrMQP^wv;w-%fmi{t{_nyQh=mkJj#jq$H$ zpszL>-^^93jUn$H?|XP@l5h@LrTrS#cZyf17;gg|fLmv9JgH_=o)Q1@y@T+o8C*ne zd>7u2ir1hRuQNqcoOf>;iz^{-o_Atae0qiVo8sMGjF)JYQ2bk-EyXe4I~Sg-C9+dQ zc+r8e(!H}7FL6!D7&Qo7-{b{eLwK&XOd#FDI~rb;&r<6;Tb|4@64w;Ih%EGONWeK( zaqd4N&b!{-2{^|q&clk6IBnw3BCmS_&Pj^X=ZHA(dBfo7`dS&rS&B1Le$IB=C6pas z7kIBKj&#@O!MFgq-s1fbW4dekC@;&>yqpfEw=gHy?|aMOrJFdB`>y819#%t?M3|Ht z7kcDKk#mD%SqIa5XkER(U<}>=b5w-cNsGNN0lJDHmYisYdi|BJpQ(2lLlVf|q%hKFJEhFfuQk zUOmnTHyfHjB>SHe784}*8a7MH7(SdBnIC#rDsSAo=krzksO?oH{-&*or>|QXy|;zD zWbW?&E zStGzDuk;=wvxds&zs|r{E7*_JPsuECPQfw?!q^{q1Bks^J`ad)Alhd12f{kc>lWq1 z=*i*D)6Z}n18pI_ndF_^7uoK6adwqAN~KBeYLTak%k>wLP3W{O!s7O2#%-fN`ofV4n=|8yBEOcj$m)xHf zh8J;XNYuHrSz$K)gFDMYcM82T`p4RbyfW)s7{4gacEbtZXM6&yhNmE%JMt`MQ|gku zwO(D^8ki$R?w+$;gBY%T{A_546?wkIsJG6$25*cBv&J55sU~hc6~C_h2vtThxepm> z_a0^(2;+a^wM!8HG8Mmm3Gwq^;`f_=>ODw&UH=;pw~>mUVd96=6jf!5*Z=HM;ASMP z_a0ZgTj?vVhII>ab&nogj_{I0H^LuBx{Y>;>lHV6Kf`mqnY>;l8~fpkmuuUnEWs}% z{QY9Q4V1c+7Hyv6Gq1u^v5TY2v0aTeAm`tYhL>EH$!Zbd(Lr3SPp2BcU^qL%TC~wS z1CA>6xW-72s$T`N+x*Xxo)@p>y zxT&H0Z9;)^Z1P$to^$X#<>0ZF_fHOPdl?5aH+!8D@M>W8saAe&G!Q=t}ky zKn>9C$R+qp3zSEdj39h8(lw>;BHa$Z^d`V_HCZOeGqHag2}VY$Mv^aNpi8i3Nez*M z(}BWqlHM&|L9z4-ZlS_8Jp$Y>a@sjwcw4=Vis#&0s(8(gkXID)wt2rM;H^@;>yMCE zFhTtL$~$pDtU^2gK2^LMkB~P!7vB0(+r5hcy7G_;{ROaX$dxZ^S#rcxXk8{{?ldjV z%#XhIZi46Pi#$5&2Uz78*VOIFygRJ@aHeU=+2Dm=?ejL;vHQVnue zcr`}q`n>pXhYNJ<&sR7&yB9k@Ajs<`=! z_aYcqryQn|!ki6-8-_Brh4#OC6P3Ml^K@n32>Y_w4}Vkm`@Of6y=0x}EM@-?_8#^H zVxRn*w}i}IEuT+z-khhbXJPGQT@=y}cw3;S5hjPTzd+f~l`pW*ohIJ=?(N0iRWWCO zk+Nri5A6#>`#-$Mz{Bk?QTFq!eb#j0AM{ca*w&pw(E5;92kX6Y)>kU)#n$@y8SqN^jWHfCA1`nTy-FD`GsYm>gntaIe^$=72gYNf2#V_lB2$QO%hrTiz!D~`VMk8`n| zvX4sb#(rl=Pxi+^-!Gppbk-e}^-)+SQQb3B4^I$7U&hRt#7sZRpU$t=lAq*o^|79IA#2;it{M(h0|Mcx;uXoaMDOuVaPe!->W$CG#=sfRh&mH zXJCSK?QO$tOLN4ZWBkZ7v3%}t{mE7wPB6oCl}X^wgQRO)$SLbrP@Ex_GeU8CI)4&y z_QIL+w)j)dPg9&6%NeUUk6BKe1nF8tx{5;1vHk^$lWRGX6^Co;VY+rC;IzP>{JG-K zaegDknQA#R6-O?dOa1AbAYH5BWaSB`yx&rB-nN_tio;$o<4*!k3(9?Y$f@9WRGjxL zXPM%#|0?7xOOUQw_%r++@#lE|QN>wlIcpV%O;RBzGl4%d;A{*zss2F4S#LRCC=Q#X zj6VrDwMbWPzWC$$qZDVG<$R|&eJv*^LAoONvoqxQ{+o)k+j90PPCv`3n82UDaAwXE ze*%Az;_SDaLyD8-{7JxxNdFUZPVm<%PN|`$otEXV95OAD4HIGgNszA9)aQcv;?Ifx zw~ABVa!ynn_JD+({RuejNLTg(;Z*d0SDaHU=S;7Oi zH5G^HgYhQ;rycn-YN7aZvVW%H)V7?<6z6Hn*^nSz>G-oP15^&N;<=n40oX&>+R7>E`P&ird3FmZwh~hkCIlUBzu{Y#QPQa-^x|WBWG=Gxf z^s$_$6^GNxkkd0ky0%cChZo>aa%F#BHq##Ye6kze2Puj)w9-tX3&f(@8UAv9m7}lx z^E`GECr8we_nQy)?{3`yR*cYE~PPFzfDf>dP zPd>{(ZV;y$^7*ex+pE@k6xJ!I6l22B(udD+N>TL}%a5MzpE(FSn<(ex>lQPbFOHUP zadLTRU)8Ubz<#Q-4=@7%5zOrX$QJCKR(7uMBg?+MwaX9;h%D#hqL3($Jee!w! za}>&c`TW-;xWHPE!H}{Dtw((z*5~`)|?QB z>;s{7Eq@8t1D9#`N@d;BT2B#+iKsh;A~Oubhn&}2~IxfwX#a3Yb2Z(~N8-(8{Z4zKI%Q4Wd zf-^U%zW*^G*XQm7@GClISZoNF*Km zYY-=E;cC9)B~|BzpoHI1jMp=c*U&HhY|KA-{O7&cKZJ_&erWt;^!X4bl!|l(FM*0)2IL>WVF9Dao zMsSV%+rYWb*_|g(O5oi;TnouA1h*l2h5xv6?`hl;Wg|(YOD!K$o+T{Nda79*Z0wIv z9Gz>$IRY-3bEQ8;apVpUdA9#2{MFed{zz#KE!n4xooh+p&}b8XsRB+QrbsfZxMNcY zE7`H8{#M0V{Bk5BkI^291H~PaM<|T?8^^Lfk%G+h_bc9tN<4Xv1ihUgp>ok!%m*V_W1z1pW+A@kZQUPX^ zy1`H8s+}80CQvg)lTh&t|NDm6(yyyH|9y|u%D?ts;k5SeQk?(3Lf+{2{eN&uXl>-? zP5xNLIg*a0gvy;UbHU2%W*@LkCnb*rB|G*%(yNkj$I;w4DBOgeb?PEb;z}PIQ@tTga$}ZT(Z> zxuIDq!ZGMWcyb7@Ap8_bNtEGC7)EUs%x!+X1elK$=Ka6NY!gh=+x^xmb#g<;8W8JL z>KJn52vfI}@G|F{$F{eb6YF>JYUVa@nRobI6>i|GJnf4p-z!{Ag{v@}o8u~&^>vMt zhpcCP1uwmwpACrjQ)MIYmCe$w|QJEZ3An&Yk{O2{@-If4H;}a`F;z zdcw*5TKwtgA2m!2=Z4o{NH*co!}^3P7dsiHVlEvHQa&Lp|c^Nsj( zw|`jzj$5RV{HbL*ofB}T!Z{FfI{7UUaNG&KaO~nmO3wtG*>DQJ#h-?q{ks!zs;YF^ zQ~i`>2{<=!>bFBM_xQaNV5%$3B{o?*5@1+uD-1FB`p+l8oTo4iEoOfL%B8DOBCiBi^)rH z205RiDhfFd_(cgg^%duO%UPCyvlveP_u@}i|Cr%o7~dq^x|dX)R`M-PVnYJXN;p}& zg!7<(CLA{r(F3+bmwq}bALtoN7&|hShn$D}`u`(m_-^s%VZY7)$k`Zj9`PUfA33={ z;Lna|H~%>W%AlZ{q7F#9!(4Q{WDgm%Sqkxa_R*sBaqQ69Z+0uE?=t(H%+Ad2{@~|h ztGwyhHbFNd$7^hP@~0o+*=S2L_w&=~N`GJRM#D3w0FU}#D_%>^XSNY<0&$Y~EB@6- z9O2L=kC0mgOC&6J$hpq&y(BoZhhJty%seyaH@LK+BQy?|PNq$}jScK%{qSZ&{=_dOqcUqw-H49W42GGjSa6QN{a; z{4Jh;%i{bS;FsY_H0>)q9Iun&_4xRsUh>fMg$ zK)($fSFVo{{|Piy`6X(^1B&t~%w zL4N!eqOFG~~U|J3JUj|dnm_}aYXUCw4NRla-b1g>xY$E(e zRILHGe_doID1%p<{`Y|k#A2BLehwG8`!0=^?ezzi(Hzc(k)u5=M$9ZvCaf~5hNMK@ zQ%jKVGF%=BKH!0>yhF#F_c&9=z z5_oABaQ+|iCiuIRf0MUy6_q%*Dc;$N_h1P;@o#3f_?PQP*ev7fT@UOZM|~BqzTzz@ zfhYcD4HDi&KNVg*6DLxL{d%-f@oa~iA|@3^CC)$L6^6V?{@L(cJIiC#JBK(mkZb=^ zmpMY-)qlgw9W4I6;x|<3ZH@h{=yt_>U-5>Nz?1wd5?)@?tN!f((@dnuAB-F$iIj^d z>#(8iRltRWzh4Zxa<%C|fpWa&k5>s^h3z`D9y#7orVWP)K5;ZpphvnA);Za9poTZu z{}`StkmlIlfLbHRtF3tb2p@ zHyz$TH8{;15!c{m`R~AU1=66ZDUg{k6E(Om2>%*Qr4enR^N#wer+w26F84(#kU9QW@G9B{C$FTF23HoQE8y!?13riFL_B#;UQx(<+usAv zHMk40uZJ#Eyk3g;NC`Zt&;=v$Z)9|?e^3GY6CoQti(Ce-R=_ocZ$#S3eKrGua^(3H z$Hb-x`V7n^Sa5W{VUH@CeiBVNI6>K#gMZ&f-|^3bmnLWqd8gIy{QfaxWBzI0>4aB7 znprV!%AD`Z1G8O$I9~1l2d`QjZ=Qeizmwj=QKWZybiV(PN^jCOZl%Syn@aHSM85A* zEWP#O{9E8>tMo4Zg6A(|pPhg=j<8qJ8%XD0W*l#!KT+}Wv3(bCX~~B7o}c=1ti|1$&x_@;&p}e5cOh0V+x@%$TDX~c8sJzZLyO>arO@EmZw__xH*R{qHoYa77IP&|t7FW%oi zu{Pu_^>g9X3#0Ht5IFav2NmxL#p_G>{sb!^@&w$13F6-eet}BwQ`l#tXBCf4nt%B> zkMNSpcX+PwmieE-a~+K1EmFKWN5GT(+ZOUZ^!F?O?k4|s!rHBPn-%ZO2_^eCbE5dS z+%G#e=AYwLBc3bY3i830Z%I7yFKZIK=b|h8DhhZzppK|3k_Pt!;=EFhutN7Gd=M(b z!cv(bY&@L7&HZr=Zly18*>f2@vp*g^Y8-ZYaFY6j|+#6*8t4fVvMSie>3dGM#Ed^mvmu_nzSZx-Qs#dytZgE0Pm>c63QO$PCpdhC}YX{eHMmnq&i#aL1h za=^-%`9_$5>;1(Fcs$kYM&PEIo?FYyPoh{ zP{-zx$iCA}&Fg6kBy*A&ZuGm1k3=3caU$)p?S$?{E(7(DJDl)p?7=F2Yjpa%)WA2x z4E)^h2QbY7M-yQJnva}=GB4l=6Wnkz%K)hJDY3JT*|sa-l|USu{E_2h4xX6I%SEt% z7&+d5R0&Tdd>-0CH?X~mN$|jq=5LjEg}2$C0k5-sHiMB)rV)JSmN? z#qn}1@0oc*_`+W>K32fxu?QqDNO+xQ=J~RYC4VX0jI6id?TBvi*8@z8m}49fUO|(QOR!#t_?_?+cFO4* zJ=rGsbx!%%k?xn75aR{do`Oz8j(3assjz?_Ap9|;d3ly+3V54;y5bGQ_E|I(xeRb zXJ6R1*-~S^@n^!T6-HsGOXi(O#2KS_yA^L5;d(~zc-L@gXyzPvc}d^;A1dH1BD^D! zkW26};;D6T3*leO_x!L(fXi$Nn@ce}{H^fP!YGWW*cPFmk>ed_z6%pv;Z2$l8c{aJ z+hBR7PyNnM$~~NSHgOz}nYkP#@^-}WcKSX%*W@zbG(}eAC%Wo8SZCAhO%SNmoU5SzilTmoR;-#66m>T%ki<1sf(Q^+!78Vd;LA|ToY-4ZDZ6FIS2bG-f|K*nRvxV zIdQOX9u7{5{^%b9=!&={pj*&G$T|3|0-pXB)d{tGledixG{u~@+vK2eu*g4uVr<@a zKei8}?#S^fiKjNfr5K{hA>HIQ*l9xL(CjC_#l%QP-vv0E6}=VHcIbZOaOFd@NOEt& zo<_rw#tkO_m^1jd;g&1dzNO=D(2;^QsWj#AGK@rP>@vN|UWhBxlYaJl04!sEJTi$0 za+P-qf5kDOH8S6Y1-p{)&(MBOh-OzYPh>B1m&re~0`ZGKQSoGvSk8END&F;qmokf~ z5|US{v`RC)igCPO{kaKvX~c2<>A@`#uUZ^$zrRZHN|QdSNaS*O;lZD7)<2#3u0_aR zghk|A!{7XE2{7pj)BW!;+3$hLi5~Fx!*S&)dwUwgxJD)K0n3p;Z>-`DV!qScBeF<(Yet`X_Sgwdf&6W283OY z?nblexVMjIPB$IqT_(N8zvSRMc&>kvy-g2c-y1pJHp_dFunA}?(sRAemS_5>qXO9} z-Z2dF-l@97E|KzEdva97f;yC}pYH!CK+0~+1;+q`!xAQ~%Yg#6_ zTH$U5(;jtHIM+{!d(#Ln0hhmAa7PF270!9LK;hO2$9nf+$++wl;4+U19tGzzuMqR~ zXrsb?rEtHLfa}C)wlUVwq=W94Ueo_evTar>qqJ$_3*rFTh@w zZ_B|duXtA~|4t?Ra;9Y6PN7GQn#z(!;mc@yKzPZ=2D4t}$rB&(xslw&Eo+6<6zwW# z{8CsuOL{c3Dd0ng>d4$jNXf?qA3@y`Qsr@$LY2*RuEI3^e^9B58BdO<^rtBUzi`CLau$03JvEu{`&4N)E| zyg3)eUL;hVcqBJ}4Y*`KX!RN|5|Yo2q>Qg6!u1OF8OBFibEJ%i7Ya29xAs)pW^d;5?iDh0n#kY?lmoP7kZvLxkaYpu9Vr(yUVlY@0 z+za>e6m%l@L$2UjkQk1XafH2!rlb8dDmQ}lv^}~Ru`33P74Ih+&)e9)gBytGaL-Y{yF4$Nu~f $)f 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

Tt85djVde=KaR=<9;ChUSxP#mVxD} z@YZJ}kGtB-EGh;L*1Sir6v&lsnR(#~Y)RTDQ9ERKTxc)BA0l&wg(gvf=3a<0+Vv@4 zf0g^B#T(y(mv)dof7LLLi(4=91{41U%6f;!cw5=GOCPlL{OplJ_rF9|BlY2jtMylMy+cK5+EL-?`Pyby@=6Od`(4i;|}@g;7=JtNb& z@;Q@xFIS|~z$1cJyO)0*p2fR7na}xwOgYFHc-$|qs=(#nJI?QXC;R$6kifFE&r(N4 z*SL3CJh?mX1nK{>c#Qmu6r75GZzIstNHX}TMW$wKKT}d_xGWXuBad~Zh z#&Z^0Fe&kFSulxyCKhic@;TQG4>(tYF;-Quth$iO!zl7t1K|UbmyU+FGjN033ZSXB zLPTSvxsW;axJwH5N`@{sDnjmT;Q*Zhi z2LAY;&GNdZ)icB#2{PrL@p+!x)Z)qGG=*2+;^}8JT#~n9tk@TFds@6d*aZ?^V~h8$ z)qDTRz7gZ#H7({&wRr7M(N|!#K&BanTD&)j?}O|z@7Kd$`Oif6IK1Rj0#6GJBkgFE zfei0X)#NcJh>Neqfdi6}HScECtet39PDZ-13&L(L_dVv)oRW&**V~7~ScT-V6qWv) z_KDP6akrGk%Y74aZr*O(U^LzapLetS@PFXRk~X#Dpk^$UEkJvYTl#R2Y$q|;EdBehqX zAmdl;=9S07=Jhflio0QwZ{O|i2#fbaFYavN_eVytZwm3VQ4V8lRS7lo#7Edy#{Jgf z{Tuu2rd5sMH^Q!b`f# zO|f`(X@zg|qK(?E!bvIXegLPEWFjo0hWm}>@sfN>t1iVF{he>u7UIWp;JC54>KUfi zI21^pGEI1QyAv&*T%#pdn*U<)Qv6?1<&-B^WHI=24+`O(5ni2gZYDf)G$2pH5Z*zH zS3eieUN;&0=yfZm3+{jJmOOArEF7yJ34U?KyePO4p9`+MdlFoJmBo?$Uzxj(Teybm zySS3IIc0_xG-flZNo4I|-2uU++~Z!oIDGIZrz$6J;CWkQGmX(p}4k}WcvuqDU z;-vC2W(co>dlNjVyvvbHwVRlx(k-6-rkxuor6Vi@_{cfu+F`18a&gS@)#F! zZ>ud{d5br{1^XM<{JrzioEfvg?GN1Nj)rFjm)w=U5!N;&E?DeivqOSk-gCqU>O@`` zI8D!B>cYS(?qaL{M`&IIj!RR%xE9zpCyoihJslzfJrQl-idqLA;7INc=Q)=%fl<-EE&4uE1|e zy9#YXhBr_Bmd{I0iE)~t2@HrL4HPd`A2}&rlG|uWnAd@{&!Pp$@N|iN-uSvP&Syxj z)GVTxC`l>m{D9&myT{>m*5ysA7vtQIx+24Ct!mKcogx0R2V$JWQsGWBubSe;vkS!Y z-rV9#!-pu_7>KP%{}dA5dMK^bZ~44l#P>zEhd-zr7$-oe={^R}big4GJI)g|gU%50 zh(i&c-2oR6Z(liL28cM6e)DMHlv?h`@Wi1=sMVVn44w-(-&?$9>MP&A8FPcaL)nGX zF)aBMhq6_8rSEsQTReGg^A=dUkST8m!%Ob}H96)5SA6e86u6T12tWz7-Rr&yA2jwj z$VLRPlNPY60rI(kMRLYEC*tf#N(8Tt`zE}yDvu*qVdbkI<6MP|f!!^hT(en3Z4*JgZ09tm4$)_b&lc^!k| z`DQKPM}E%tfLk9%nh$&1n)t&H5<=~n%DZufRnEQ0~1NTiG77EUM=Du zLiRu_ctEwUYKI2ykMQUoepvY&PJ#5jEnd9EE5IMa`Ocm_%4nYI#|_;=--YXM8fj;t z3l@*bPJ%zsdN<@g4V3sfd*|;dyILPrdkd=m8o4iJh3oG((*A+&Z4@rAX;*<}5WgNB zJk3Gv+lrU8+U7mvE`gUkHj~y)^KaO3ABu5qMyCGs396_!>~y0&9H+5+6iy@gFJa-L zpg)7(4o4i+K1#<X1@53IiCK>9YMo0`3 z;GI6tiR(pNe>56RV`?_Ly?u2@Q4QO~tpg9oh>;2 zCwO>coP3IbE0$v5us~DyIe@x1IP1p;oeVO4gT%msjMnBpPnGxw;&YJfeqQt_+Q1k5 zbj{qiEuLAF{X`xyP-r_YR zz7r~3QcaPvA(*W_Uceu@sqPYZNt*Za%beLGeP4^muCoNcg(nfe7{xQxb8v-X-y~h$ zoBV{$-6Qa*Uq5Uc#Ug@!5a7`!Bv$B{>!btL_3$nf^7@BH#kCVmcDMR|?qtFJxFy?0B( z$J}}FO#l0iw5!o^WOxDpcU61TZp!)+rI+UtiTgN(!6h)q_2~h%hHT~Tw0OZi?9!9I zH!{2`+P;CrjYJcWQ-WR4yHxwm)9tG~-{Wpkt~buF@;FmT`vqEn3=an&!7uLy;GUfc9`z^P~P zCRsdra)5oJ!PqFrSSwbEeeK*`7SGgQV~fXy3Kz>O^%spdVl})v?cEdb%*-nr1gWrE zSiH3s?;non4+yS$2iIK{#>oQcaZpbp3F1!IXAUaNB03RJ^f5P-IeT}(DTUj zk`0zs_Dfc;eI7L6~<%n5$uUNbvbMej%%A2=Acy*q3KeUQz zYVA#nx7XtRL#>TpC$;vBJJ-UQTI&r?LP1bJYh09CJ0O^pPVR0nJ^f5P3Wn_Oqk)!H z`z)&_5Z{DDy}W8IW4-X6bpxzgOs!4Tye}-?v0S_!B+iT1Zv(uqg3q}(0Zh^cF5_V> z%Ym&!#yMTkz(0vQkFI(Ihf<3RL}^|b44t$yp80`5o_Fh8ylgVxK>9>vc$}z{5SK(; z9h8c)amMj@G~s1w=c#y|-3}J-J(hxxlm2C7cw7bJ^Trc587)9!Uz6I3*FVC(7u>Jl zzoKFS?uZz^%7%9G&{+T>>{^li<3zynF8ARIv$+4E?PZ zuGYW99S~efSGVYz@Ju1QQ-a%J;qK3ci?(%{u~~R8xfSx@?Xh^ZbMclH`uj}b&pbcE z>l=94eHfr=jmo$2JR@L-kZIi%4IIp}^6=!KGx=tKtX0hPldXG;ni^kmU$l51u$?7S z&uPoRdWshm-UZ_2yl?)HlRP3@3fRpZM*gvWixHnnZ%0=n$tI(|kyXH3h|kI7Dg(9% zr01IO%r~q(g;%}1%hPNxE=`OVDNjBL!ZYtl(KiM}a9GmK+5)D|t1i!*yNHn|>B$UT z$ug_8WtOanqu|oE3hp(Rr&jz8SIxq49kv92g8m2G1|QeMne~4T2A#n$hgsY`+Db8XD)B9;=iC>4a2a3niX7p+={^XrtRyCkE5&1x z$n%xOE1_E1uf*?(FU8(WZciM?N$C;W;iU(9x}5SE?&kIlgWE}NnZ__zFfoNH6lKRie5L3%l@rpVm%%~ zov{N0>!i7??k@J4CrIA`J#F!JSv>KaGEQ?JSJ2G;c7m(k+dXUH#!)V5=g#0HNOAXS zT(pyJf~nKTy@TaTyq}3%a3^x9{-r>D~EQ>AN^A=8CX`PpK)Y;PAV%~=wmU%MaCy}M5g}auL68tXL za7*6jqvY6YtMK**K6Lj3Y~<(Rt(AaUp|=q2=T}<;3)refjPp85`I?JAKUA~!g7NC$ zntn_eE%=H0Y~!E*_{bdu4=3%1 z6Ec2CKN6Yxt7^@)a&WjHk1_U32Gh>3et`$Oa{(r5;21y?k=rV4pjlFU(i->t1lKb^ z$^Lomfa6x?WjdQ#>~j&97|L8m7~*#SA_SU z{|7I5p8Vmjf26~-v~ab+{oD1A3n}e)NGT)TW?!B;{7IP7 z3GF7|K6DgGHgU)1(#7`eIOmFbqKyr?R-(4!v|h3PJrX%7F=_YiQ`AfOC?9jIQM^KPXZ)+)zio~3(d9i^B{K#zTf;CZ6W52l|L?avW*r_uK4~ho$P>+>U`q93sySW6(}2? zxc40vH=ml%d^7K4w_zTgB9B9XjALTu1b2>DnI(T*v~s^ii-q=ItQ>S4(x-t>-Jju_ zzIzbhF_hFk+_+b2GrM%accF!-)Ms>}ztmE@K6j=`A6~{;3?8B3mcXwH?=@7mBTu71 z4ASazGQ<&8E2WVNwV_iCxnuI=c7r;x-JYkpHeJb2pdj7|9_xn?- zbCSDFu<7zg4LPqOLn6__cK;7pdN;TGLuxwNJp)!6JqeY7R~kKtOzA(}z*M(0T(MKa zae!w~?9*X8H)%Vo5LX91iuzV#sZdd!94Yvla{S89Y3|4H5@E^mqXTK5MO~38_YuvT zL)>@h7Zfv`NrIJOVO&HXDzOlG)p>&H?rtgfywi5MPmslw`|N)#ciI_gp3mJYvQ_77 z%1@n!cL9}pCTymhTqgKqat!eqD1Q}h(5kH5NB+h^IlG}d=M1+vyyRU1zc?t5k;RyK z6S)5}D5r2BNb}5eli-@>ISKGQD$*%zr+vIykNDAFea$yI8yzb-6R13_70?KNH#hs0_`mwkD){X1U#@+}Y>sa<3$dDR@!e&urR2v`erD>B{aU8{Y5q7VGeclLo@{fKTk#~qEGEPtH(=qzai&vN<^ z8Qy5k>qgu=Xb$Q$l4JFy%u~Gs&NRJ(RnBd$yF|*p?k~IC>&aruz5YLzd&C7uv0u8s z33ihFaj_e1vasL%N9<7_`;~j$7O*{gt_u{XxCNZ7N_JY<3{`lk3+EW|1F6u|AxuJy zN4mRPU9x9N_U`T;HBHChy-i_f>+C7)G886$7uokSCrkh1k!9{vWS__XWG#3D-^*IC zn3aE@%I}XgSqm2ah>OKX^Yc@cYw1Zo7BNeEVL)t#+h43%Cx2Y5qgyT7um7=*Mx;SH z5t#4J)n@W*&g}s2MwO81B8Mz9n-ITq0XMr3VD94_j0~|;-E2>|z}*2)x}1dOq;HMp zTRbj7tEoTQEDt(`AF((5-wCem8Z{i`@u`p zJlSSmPx_6>81%AqM(vXK65pdFcf?a6_9=Q;$p_xTz*8|x+-U%f?>tO~6UgZrHn6`2 zwkGa*)CYBCwYtht26l?@Axqr?Ibq&I**sOA^dBSB0NXV$OE{x~&RRZgpH$>-+ZTW1 zRw-zF_fok@gq#2Qv1J zkeZ|di@m~f1XV=?2eO^Rk-u>IN0fKDyAocapM^ykX&a(6WO!d`UbSxAb%5SLMeb)R zucLVT^+SY}ec!qbs33F9x{|c((P3nGSIB>K1J_{P)fAOT;piXd(Gg#8PWxcBApFjq z2+y={SJJ+UK17Chhvw}h?f^Q8%Gbl6f2{Y0Bg&iQZnNyW>Q%~uiXzhi>ucT}#Fa-` zw=lT+tFlV{Nsxo|1MEmLLcVtk>mWC8F5>E-YWMUc!_=%HtTBzoXzCfV)1xekp$n-A0s}m zvkAN5O?e;thQ+OR#{x7hJbF1jfJ}vYge%bOWA`KOLo^LZ3ok=rT>T05h+E?p*%{`o zCGAF3;Po)?6=i(fRN`i#g~&ECoi|epSM}(%ZdZ$UinJHd&^N+729|`l<8QJ*$N|ce zD0Q0S^sLT)+6)?co6TG2-n=Vp-yzZ-Lp^$hdGrUL*C&kzMl(=n++a4VJ+Uh#)8?&r zTUop^y?JZ_s*9u@jUO{+WBRtjyceKUZO4?nhK%X!#UGrWd zt_S)E_3g_eJy{7zdE=k4+v5j!tHoPH+U4j7GWN~Tyb*8V{m^FAb1a;mTtL78Njhfp zHoEcj9@Ag)z0FD#0c{w-m4=O3bKu?buL(NwJQ+weiX_Z&>+B6*s_@t# z_7c%RWXgM;?$AewyMT&(#8E#D5Mm><>-J*G461N;} zMyGD)LHBweIz6JiJKSF_USKdcDxk8+@Deqz6LGJh{>bKKNAPyKMY-Z9zp5kWE7C4R z2aw?6_ zQW5t3?B4!MxP6U%uUWhcnitK!>!_Z^F8`pXK7cU<$L_2>9!?f$ploon%oeR0FW?Yrv|_N7GF_p7_x;#~tL9#yq? zyESh(ag)$|B>vzO9V9!*Eszsz`wqB;I3_UT&9uisi?>(vqP0hAM0tO6t6Mx%-v6bC z%lqRc%9|Qd-h=Kl7SFUtb&Hp+dC}Spov?WJ$@skbbGHclj<})y;r0!#!x;MV1&cS|DzEKd#9yVv z@dTj=-XHD*7EfLfeC6;Mr#LeHYN6&eA+8PThHQTy|D4_bj=HZ}JX78Q7VitozP!qt z9%0`x_fv~!`pa;OH%s%P^_SEL`;NOCES|CNCyO`n6824su-r|}5a>(L+rg_o& zOL~NTf4ZfA4Y#kcufd3Ld$8ju!9POEtN!Li*mu%xYVnMHsTOaP=0&qFJHozGZkok2 z?eVq68?1TJ+9RGhFT5T)?M}CNro6$C;qtzxdGe80d9xzQd&bSSc*eeh7LTKG331Wv zOO3GatQ*VS0LGsh`Zt;3)UbOZ|kFf8&`Y8=JWW@c6-ElIq*uUI(N!_%=4(x^<%>2ZKHY5 zjOPFo-T4Xk|D9yF|BIm0D3%wne{0`&8tc7xC|rM^Okk4$4fr(7ds!b~em05C2-IM* zIzDQ9ACJv@i?uKJdxrf%oHrAmsXuor_Y$Jk$h601&AV(GwxOozcuo4=ShXHHrEeTp z>*ve79E)e_Zzg#RZ^)`iOnF}* zkLk~Jf8V}n{VzMhzN@{V7SEJ-zQvnxiSow3Xt(b*-V%#v+V>BOm#%qYWM2KbR7Cq; z>m9Us#-E!*%y9jU)V!$vAfmk2c_|jpl=l&f_km?! zUgb@RuisHMxf;`@{Of;yt5zwdXQdqV~x4FJ&g$<2U5}WburB z!^mUG``jh$>l@X{lAiQdB&&-CXR7O%7BMeEP;UF`DSNm${{Z_2N zb_H2mO|{A^7f{wO;P@xbWesEk>(hSUus%(?+56ct?=rH_+l|0U5Zo6U*Z(RmOe5ML z?Hd12lf&8tS-{iq(2=WxiYSY}RTeX844 zwZpAm&pgW8!Q%aPiSn+BC~qlmhE-m9NZm|Wi!GjgCFwTe_aG^6BKt0dIhi-%ZoA*z z=Iyn37ssu|JE!f7Hg4U|Y+h+E;dr<`sVy5=j;eK~P^Q7a*iJ2(3RitG}f4Tg2 zuZhJoez^fW!AO5GXKJJQ<#gR1YF%2!doK@Oy2U%8?Tg0Cj^N$lErnlY-%O$I|CRhhFR z+M}vhDqFl-#6N&!errh^XW~x_9<=u%s(Z~WUNh3RM8lD>ubSpn`Ih%Upsq;v zak%i->BhcV3VlKvM)|8GuZP7moBRc;4^zuL1E|FSk;U9TBDQ{FAi(Uo(!T$FtBbF#k5)Vz_z z+0UC3nb{Ri4kvyiHYcwaCpPClYPag0-hiCkNS+^Xvc$+jYcfT|H|K}oj z^}U@I&#WVBtPI=tqvl0j_eJ!R2fb^~hU@Le7r2fE)@X~jTl01h_cQt(iL>uWXOQEB z)@#%_Q}x%ts}9f1L*{tx+Ew9p{X_Gl7yQHVTE-6AHL0Q3(K62*uO)z!AkBJG3(#)G@nU_QIJ?Lj-a6L4x@*2!S#~;KKHjG^LU|RB&pWwZd?-B18%RbW{ zPms~H$65`H)*c5V+9TDw`h2)OrofqrHd(yQnpb))^@nOBdpoJh6uUi|do?VcY2R1K zW9-|idC}T8HKKhV^P>66khhx9?02yTk6Yg*P6aY2RBo zG<*cN-h@1+K~8C258`^GC~iID7usV$pryCUvTxd0UNuIZ0mzKAt1k0hLEI;85vzrihrUY1qhXGz-y^+m?MXEaYf#uGmoIf>z^zl>fMt2gYl@p3F) z25B?VCS-UoS-evczk!>Q@8j~%BxPUy2wq$7m{neRty&S%7e%I@^s#tViBGwg8#Aj% zHpuZtJY}DUh7`z(ZRZuepzfHKeD%rjF!}%)1Fw~yOoKH4feXvg5Y%xX#~2wjAoFXE zzQ^}kzd_o2jo>x%vpCKRE>8y`{g24-I%=LI`H8yQ$9IFvgf}xw=>~r2N=ebd>j$r+ z{Fm@MX^*4pHimh{)mMIpd7k(_NM0n}{}jhOy}5Y#xN-n1u@|@R&4rg=<#A*kJDc=5 z7LTQwgs9h7W=A-vr@UV*UWrW{L!rl!Deocivl$eJL zchm-U`alvs@BLvFxEg6|p*qMI_^jqNB(516OAp#xB67sRN1?-BK#UtGCjDX%x0HsGG85hvlz3%=sT@))+x z8n_0~MwE?A{dKZ{2Z=w6#xnd{G8V#6cMatWC<$We>8 zNb~%Ut(?{>86F&BpM-+vS%jYvUJq|RymZaGob=NF3h`;|TVe5TAb!`F@Kbga?ZSnI zf6)Pb-s|4>Jb1+|-iCk4TX9zGd&9c`Z=klX44iVPg2mfv@fs1|gaeMjOx4CV`4sy` zoP(Dhc+)GJFYK~p(bj@YZIJ0Or!Amaw3WIhyl9)GI}C1%(9>%IueHkK+`=Br^RT)g zQ-Sm~331(tdzSA9<5JVLw=zc3nUgclW8m^&FRzPbU{5l=jrt*D-~|nok1vVegr=Qh z6^P|>5#ziF1Jk^8%@g0AL)ty)cVu|Fx5qWu#(l1+4?4bp0uNQS82^fTb?X^_67KC~ zSoVEJ+Ue*EWO&(@ef{Wt%lWS5oh(;aJ!G-S%F^})$4kOK-Whmi5wni8o6!Y}_loBA z%;8}}Xa%xQ#+FaBH(THGZixvx$$fjSmxuZn+Rg=ns5vtB-J^IhyND~WgA?MYFAdU~ zqhD!|@;V}711@<`FHA{!$7^Bn za=)fV4r6TI`L#||-X5RV*L&UK<$f1eZeEXnuy0nH*!QmY@&6Gotv9@3fqvdn3s|o$ zSJ!ekS#Jz64Iu@-PS549ei(4p{TeyFW$TWjcG2JSax9)a3Gt8H)r+~zNV9qW@TR)) zeXy@ifA8e~4eqFqd*5?o!`84gVKiMP7>_V|IT;R~h6jgx5%qU3qTl zrMgO`+yCyAIcQ7X(APKcBku&jBn^~j7>>udsZk6(#8O}`-|f0O4DEDK8LEyf2YY4W z!t1J6uHb31uqU9r`f^DIOkQtz=kD0#qwiv1r6FEpcxD+X&v}Z%6TH9Wq8~b%JgXo1 zlZJZj$ZwpTDU-3W3 zSxfvzWIsjXlx|51M@aXUSp}2lcL5$I@R{{7rtc z;oi@deSeWQb|*8yF6ESjSHw@}#J#?UXG)?V$MvVqI8M)-Stk`>Cj3xcijd?VV2to? zy)4|2jd$?$n7usk3W<{wUI)#SkNw04er9&H4p{o@Jx5jEkzQ?hx{jQ9(iTIFk>S0k zdAIz+<6BT~wCWVIMHM<|a=__SS{Y1XCH^mx3Z5| zLUq{uJ=CY-jrMxLGab!;EOkb}xr{v0v!uL1zunZVD0_Q$TgXV2a1+bV0rZ!YkG+B5 z$|@5aY2IBtWaml?cZG#3MtolHQNXn1Gs0UQ9OI3*fF;RL20emId2h6UtBK!*8Zr9o zGpLj1@?+4_+8q@N~z;a|hN8Orv! z#>72_(oom&j^m!?i~KyX86F>wdbQUl-c9*gJ!K7|HvPvB-N=e{I9W{d%Haj`gg=!; zYhE!=f-8%kk08ZP@Tv-Sto-rjQ4pg+jzv;f=`{=p3Bi24Cf@WI4y(MnWJ~0WD(F+v zPemJ%sjcF~6ChBc12N7$s4HvDMjvy+jHXFk%d=$oPSw^#Z>E?rX|R+|yyQ1^ctrLj z<#ojj`u)Ey9bPf{sF0d|=B)-RgF*&wD@mtbf}GV&;gUkYXo$C;igPAEhg@kUfnR=a9iZ0I?2kKn)?Bwoedho60lclqU5wO{_Iegj_@L*5yI8&&CV5}(&agV$h6M!M9_bgzxrl_h_y2)s@D{%9l;yM)(Tz?ktB zaf{G*$Sz+zo|5w%-UvAU_~5VZyrz6J>9!-oNs?r6;ts_)SEB3DL6!zd{qoK5 zPQXd>lk&28(%gp1AXC0R>N~$v4J3XU9wPTi`@Zt9`4JRpS74@>$n!zW)G~|=qtOIp z4Es|9HxRc4?Lq5sJxvmoVS_PD#$PFa%%DN8rYF0}=v20;4{gHg+w@v-o}@}AD4oP8`F$G;N% z4);&>)^7~FI`h1@;Kln{cn=QClfJOtvv@bF?|j~m*sj;4ejk&5CP7X=3ohkrZ<K29^LZ_fh2!vDf{&9Wv%RWRFn`ueo-!8Rut0{l)++BufQF+9$n@W?8W?k!tJBbp z$X@>*)cuzod%}G01UxhFo9+uZw~)RRGX3rjU4Qk7YlHIYca(RucBpN`?P@b zF6oCN!~0a*x0JZ=(HdlTnSzHDSMk2_CSspy-rc1A1^tQ)&pgjgij(gIr$LbYx`Rr( zyC~i=Zw)---e*4=aEg(>I5NC%w0(oO2ApQZKY>!|e&!{wDVnFc)pG9yyhOh)IRq`w zI*s&iTD(J=H-@;0=nGW;2F7s%RnFtOJ=9w6Td!^*=Ic|R(R)hEfrz++OtJ_?W{cwr z=l^T1RFkJnBFCqJ@4U|BPtx{ek#P;$hD`bL%YWz}SNzGN>rhD)&$+eM*Qq1GR9(I? zA4sw+Zyvlv`7h!67kH*8>8l{ab2YCWaXrwxXaRjU^A1(Mj+&>+_r14X%9lM^$~TCl z>1ZS}Zi4 zr_1P(AkIf{`vR-IUhophBSE&^uQ|zOlE{?L<`w%m;FLf%vzxAMR)B;x-gv8=hF9S~ z@cKsZ)_ULk-;{UjbjrItxX#;Um3PY=$9VwTT1Bz1`>=r1o$u`OrbpPf-uo+$^7fCy z%d7q-MesIw?$zObA}@d(2WwIk-lmW9Ia`r^E_0sdDev=xSKH#r#X2)!eHn$9*XD6n z1aG6)310G~nbc-xIMPnPYShi4X-jY)em3%I5hudbgCUh=tFSkV3zzRSjdbShTt+pl?PH6-B{?|KHB znN8${nc_pz$YaXe#qju))mvT{b7gaB#DUrTTI^P@tQ@+Xl0VV{Qr^C>K18Ox4=P^F z81|>85kDK5odvP4KJDQ++q@Q*U2^M+w8J9Oie2|oZ!HzaueTM%7i6KD`zQ;Kot!oo zQ{Ks!<8`rs>&fsV+JnR}0d~;9xYN8y29-vYigRc?T~%C(|EZ%a^&I2v-iH>iGHI)$ z+Q{(Uw+!q|{Hq}#XuPZ<79PG~METu6bk6Fo4lMRH9J8 z>4Bu;DlM^>Sv$R(t_=^2)@Ql=19eBnK66yLiMWFje~t^e?&0aLBb0qPdIMCgQg?aP z;F)ENoJZ-yWKfbkra_8}XV)G1pWb&hPx{GjuO+zTvGPY+pvA0!QySDg$e5St)0~(d zeD@9-gzSFO$?qq7yyq>ma-VH`kY-g@sqytH*J{`Y3Q}zno}`~l`C9Dy$r~ni&67WR z1@8FJaq4i(M2F9VzFiIAF&9dRd7b#dXezSpDl=7naj&=7vg?_8oS2{+b@+noAo%tn zI8}wBtIOTzL@<<9{(kJz3@rIH@UwRWo*Adl!RdlNKvG}AYwF`vIZqOQ4%zce6Wx8) zHG{u+EsBKwoZ%In73SdzB>3YiFJ2$bQ>&tV-UslKkIcu~wSmRE@e|hvomb#VZHRql zC-GI{OntHQ?tM)@)2-g*yFO?Dl5#aC-*B-)+cBH?1;{Q}{?}D^Rd)R9-F97=ci?%) z`Hu8!EZ%I3SAh#-cI4v4NAM1KAHz$|T1dG{_u#lv+|bWtk!BS0^mHJ9I)4zai@HeLo1?tWL9Ynanw-4|`1*ic`B<)0 z&}nS(Shq@uNg}=uYJg02OSh^7&v6cUHQ<E>eq=+Lw2>N zXuFj6`rTV(@owb8fofwpa3YUXjPQmCh;j}mZY;7d6foVLW#p_(O4c{uVebgM6qU#M zjP%pdA|%~Hcw5zXe!cxl{1MbmPjj+m+aLEJ+@nh+;Sp~R@A64fd7QwUpmQ0DM}~Jm zedqI%iLZ}r-n0nbAKoc=rd_x8;mzly?`-k7=0if<*TiL_m8i;%oU<#c?3$y8kMgcZ zz4JU&J;~4FI0s037+p0tY#(R1B>48VB)$zgsFyKP-c=Fy9rIqjA>6)c|KqpWSMEn1 z(;nAbyb;9PZEM=218#BYH#A7fac==UGfZWVT6p6uUNMU|gZM0L%RL<@(sc(d6W$5$ zFN^mi4IN-V@JowV(&EWWQS!1+-1Z)y_or8dD_l)`$mLgZdUKh@>u2$@iO-AoBF`wF zwOs5w>AeWgj1M#0?X-AY0(r4L4n^Tf{iS^?yi?xS@DlwjoDL%Wi5GCu7LOa8F7nEM znfLhcPkaln>1ppTc=n(%&aYhLEhc^yvd7$B-T&11J>zZR^0?%g-vLhx z$gM#qNbj&SVR-Y@Z^gL8-Hgg2+pip?|FJXdUFC*X9c#*Rs{+f@s-!jjZnNU}{Wxbg zt1CTbJAR?Yh4j5zqu71Ql6pJm)yRW)zr|x^DB+U4e%}l4y!Q$`(~rL|$y=fp1)K*h z-Z6{UC07~ExM)DTZuNP8c@yC!syvSLb_7D67cTE_%)vuoO+uz!?Pc^4;!h*n#)7}AcELtMAoLZyL{%o|d;Chl zc|pfRhBsb)7uT4$$51C!ijB4->;g;u6)CS)tE%4xL!)@ns^MM6Z#=Ta>j-_bGLe;%Hy;p?K7xIMwqu-^ZG8} z?Zs$68qD&u?bnKzf0ezuj|&ySnHpZcMM39sR1z8c%sGKKhTnHXXdkP(l5b|9Tx9C%{xKdIh0uZ?>yFw$!R~p z8y2`S)CFLo%H+f@4LSwTHOLgWvj&zYt|n@XI#vdHzcR9;9w2HVdR6Ff@$dxMoU~Hl zR(zTQchfxi=tjKlR7`;xz~eV!UwWWW=q|3~F^>6l()UKAkg@Me&D%oUE_4{lF8-)n zRfp-O?R(O1xWb`P@Jt03D;jXtV_$x@#*KYvE&DpLz{u;Q3asR%n=o*H;OfvifT=2z zb3Gsz)kMa?vbx7ek~zfBNA?P`tM&+0eOGi%=>8Jn2H8W}{pjjtVIIeo68xEMF!7U- z%-}uo3Q~cY`hxcTe!6Qz$KjRrvpCLX(r!aLkSXx&E5f`o%YzX|8Kyz}9{8j5z#^eC zw}dOu@a`s`;pH!IX`bH$vxRqE=xKPSf#t26Z^BBmcu!h9X^_tREh`LTn|$8G;NIZ# zt`B_%FL!xAuz1N=U)nw?@AxfZU(wJmc&5Xc^5$5)q5py>&aHh8f&hDN|k9xH#m*n;G( zP#Yw@NhV&s&k=l)IJ3}moP^NwlHqFqmHkgy;B_aBbc^T7SIg?Q!}+c(2R!B)DbtiE zAK~hU9Dccu8#)HhbPL0K)8ai~@!ld{9?8G=N_EYZ;oZdcqu|oxyinq;bZu;r(4X`l zp^-?2so3|B<_-LgHw~g3)PFqpLY`ytnc+A|u9|o@`4tcf<>LT4QDB5SSS?+dg}un| z)>!scBEBlJ_eeYGiDI?iy^Dn&DHXOag|rRPbI9;=ES~#42k|KLQ-%Y#7f5+iyD5LH z{BUCE{@cR!7vjL@WzzRThDVc2@Vmu0;wK?{;_e%<@VP1U(rsbhY|?&>GLhjm(!7nt z?L_;Ly3+cQbK^&|hd0V`DFp`kNNPD-mi_I^3VHTuJ{z@yPIs`#2|VJ8|dG z9W2CV5?SVU#XF_XZma#LTSD&b;r8u8+TQ3LWOz?$-tDVdIHDG)Z5_5#A5grW9Jz^| z>bk#@p{L;4ZfOMRMkRLq4zAHypkxDA8dn6zYriU$1m55#CJ#8O!vlj zPKp?(cZ3$?!RzxMc=IB7cZLqaGySX<`|uB-W_myV4GR38RquO=zkpIJaln(T`t7{W zmETnT_O8&rJHq3ta|h+?Lrkw|*0;MfY45L`vv5Ar?kL#~lb`;{D7v3G|?-5Ksz6?oq0O@HyIA0+nl z0dTXQ--&yGxJOY3RL0uGTBZGlvZq|A&RyYg{xWG_N4=2YmD9WrFL1gBeS-#H&qfyK z0;GdDoQsvu$45)T|AiiAvm{C7ah_mvsFf4zv_pp1LVf4gS9jujBD1^{PL^&@#Va3L z0gt^EKfFWQ{%9C7Jbhx-=Y9QHK4&uD*-M6O&0`aba8Ic4-I2UGq+e|DdaIxEdFzSK z&c)jw!K)Bz0k5^n<8^Fr4?&^C=xz`X60Gf?t0V_OUTR+PX=OzYc>-xi6Frj?wIgLBoT-d95s5dG(cV zUOVD<-QqY0i#yI(mQ2dH3l|3C#*Yebacq@PAvTAMeKOvjBhyRB)L(lIl<_uz_}t^I z;9&)3dLmQ}RfA{xv)nZ_{NA85lzj5F)L$>nll!sl^@uT!V>v>#P{&ACQZ8sa2Qk9E6t9cByezJ#-Xae)ZeVkXJdMMEYNm;muLs`4x9rzF4Oq zl5u7>67s*H%BeO^l0s$5hx^@lHhGJZz8o^VWft#g;-5#SuHx=}DrenX`m zM#3}gP~{=V8ASTg7VkHUSNg$#Gn?<^SlINv`ntTzz8ax*@JvTpMA~I&i^V&xd7+qC z=QdOcO-f>YeUB<HZ%L3Kd_s+9H=RwjpL8iR+VRbj+dm-Dt_=x(e6{>6T z`jYk<#@PpansL_H?+0olYXb4|p3MmZS^HCWrmrwAGEUHs(*yU1`oS~v;#?NzH8^KD zoqWc=Cp7OUai>v{*jT4l9q#sJ<4%~Rw0#^Z5o(756~gVCawiv~!b>2Jv2TFpN$N-G z{FP`6P6_pa*T~O;xy<_c*&**w9%CTaZTLL-=X2rOIZ-e7(AVW4fj7)*gTfm#*@bakh zPzqZ?wQzY|;FA87`atNmieb-U?wqPa9#h~#>bK<2h+Fiwp2nc2^+V0cZ$`xPn*vTf z@-{`rp1W0k-vf*y{!^54EAA5)Dg|t-?Rlw&Bz!Qm6khVYGr-dVb4Z(k79zvzr+6{H z5_b+=d0DJ~pL9pMsqp$U!mu=SSEX=ITQ-K-hjce1Q?99sz>!;;ijal?rli@ref?qxC^#$}i+d8g^2uUu23&{WI7 z>u+ROZRd%L&5Nl=Ts!mz zk_z025yH#H6?3y?s3{y{*N3DThQ=eqkyO{|secCX^H9#s)LUOQzgE&NM2*lUp#c_e z(jM-XBK?Xey!FIyMsmn+TzX0buW4w7#WRN{+oSOEIy6a*;57?f&eUwmyN>#h=n5Q!fu8y*F8}4R&b7!zJ#d?;xK{xV z)*e6|TRa-t4llpT<1A!PX9)M}-bx-ZP%Hs?t?HKgA#jCBpi#tVJ zp(|pY;;2$G<<%Z|neljulJK$6Gw{l)JkH&uJ-amEROHjx*HeAx+t-fxu1Jm*r!jb? zyvH?9+1Dy`#TjjRn@+skoU!-T$UQ}wax&hc0_!{;l4~qYht9{o z{0Z{Uvv@ySJh@3fuX72sN58khHEkWLFWaIji{pLgIGLbUB2(OB7Va4F=aBuzv4grf z)TLZcgr0$yykFpH7q1DrtU#EDZ;=r7nxKx1Umi;rO0$Y7_xxtj_fMZt<3hTLJ(&N88M2a@qT}lque-w~O{AFOwW8#rV!17TvVpd&{qw z_Mxg4PYzK^kpA{Od4v1GYhOMWuWy7O?GSnvo*8CxW7VbVFDs9w;?>+Qm-e1m-!U}O z;z>7_GD}y^t39Ot^5V&`*x>V?3ax@?`tiSM-^?rXZr}0!#lELQPPH)a-?VRDJZayf z!rK*iCR7oi@uT-q*~zGuZjj-0=;joj5R*pSyJ#>;FR){ zGTCNwT@2|KAsMj3@yCz$pF4=(CmeiA4if*At{YY@e4Y*ESiCun@Fy<>o!`kL4I#Wi z>bHD4#c82A>4K0youQcIP|WgO<_usR{SR(DO;*rLtUwG7~K%j|6EDuK1A)v1k$VY$;2a*{BX~_;3SFHX=JmRP``gL$D>ChXQ^5hGFI;-I236S;ncRP(66by98dk6iMZx&pY@u#Vw+6!TX4-hs>tzputkSS3)n7 z-E@oG3q`4Rm0g+hPYcC8!mHCQGz(s$SVqYG@D{@}6NFU1{k#v;oXpd+hKPCHLr1}x z))Zf9`^((8H(5X0JU%S!Ao`* znWw8CDB-nGJBzn%KhMO2)gcP68}Vv<04N-=4ImJd$26G&cRiZr>BIqAe(vrb~mo5h`3W+`em;aj=Na zkxzKj_~#?37TtZXD#QUQYs9@JB8Tgf_{~AX;SCGC8M+mqY2l|kv)M+b(nty{K);?f zuo?0HkF|4wuetvJ`1fo(qoPzqrSttBNejs(n$UKHoeC*dD=JAPNk~Ph)`*e&buNj8 z=9Wt?Yc4HR3l)tPDux|=L%Z|fCGw7*)A<`d68Q4?<^T#q(g$>_tS z(6ae7(#=5UsXaq{tKh}DyoQ90Mt2~^OK^GP@LPd)p;-)X1zwLaYbCpk1D%1wN$?xK z!|(!$Z((iBVS*k*ZtJneU@+6i_l z+baBvTQ$inXTvObb3G${s{uvesth=x|G&V>(6n!PiGb} z+V=#!z>(QlTf6!r&eXa-QG_D-)Xu@#|F2>1QRP=^DlyW-#`uzmuewWl%=pbjjzP+v z9~?mB1u0$)`NQo!DzX+C#drEMfb-q_Vhw>C?`r`s zTK>ef8_emP%Q;0#95G8WOuapD5q|HZ6>Z6TW+O7xC@1TYyg6iG+yvjl@KpZE@G5&w z8#LY)&Aw}&Wq73{>SPt=$?!iH+}jZoeTnd-zKPokCmWqYD!tn^Uf@cG8`PH5eS;_y zv2TStYyE>UolP9yx0-#g5Oy#cjTG;c#+!rxGL%K;C$m2zysd8eI^{9hcN|_NLF3jE zb_3dl6t9)@Rpg~tvE_ssp&9qG^FNQSX$hUCTOJN?itoB$s67M;dpDYh6tB6<%e|VJ zVReRnbU2l3l>cJZPv;wbf&MnQ6yGLz^_@7zmxTQqU42c6SHbP`#5!^?gjFETqy&-y+T)rHgx1U$r9Xe9PAgo-*(S z_B!7s@@~z*asqaFGA-UprkuME)01|#d7*9KOkY2Mv34A$2Y`M=XEXyVX~1~iY1RiN zjAV2k?i4_RJ4%1sQXp^pX2DYxJoBX-m60(~afJAO+v`JqY&P zR+FZ2e{s#^=j^`M&w^Bp=0nPWN?$@V_IK@N0;NlS4y$j8kCz`xq3xz_-4b_$Rga zz7pbR+wm9rb`%r;FD<@VLj3V7!`;!}c^)=BSUD~JbxwS{o4pkO?hHfHRY+MV$8;f2aKR0F3^chactvQjviwM|PG-uu3T@YF2pf=j}U<-}R3@rJm(kMY}vqZX@Kt7>t;#_jF}#a7yEUFXVFYIvYg1_-CL9GgMawxV&c*gqP|22wr*l6Q??-kBB2q z5_*x{UX92SI;TUKq;rbrBi~POf_5xAbmDJ8`;bbf&*eyvzws|ulR=gVxf*0E9CbQR z=d#TWzH)bm%2V}rR}e?_c9S(;ef*2t#GvyWu|cZGMqd;-mCVKjZ-#EuaEn~rgZTAD zed-!UVvW!MAx#Y2Zoy6QZ1UX!FUn1Bb~-QbCC*@^lKZ{On}pviG#_PY9cZ#!49->C zANxkZvs~V2_9&JT{(Yp9D^Ci?MSh5%JS|EtDN$8KHGg`$QyZ}_Is6mfLe0KUh_e;# zLdw1xa zICIeh?h^mZYWdmEd<)=pkUw$b37dkZBgOmN*GQE|fy--#UrW@gRcN`Z$^+X1BR-`-a>BRx8Uj@P({;3O8ExAU zQ5jgnshxH)cf)_qgGKKoOK~d?^ z8n1`TD<8$42C|Smu(y-t6iDS;oC@PiqQ3M!c5f*E*5!DNc)}+jm4DB>yq@^=MFWuD zC#1XfITd=FZzMcb0XMzHV|)ld7^wn&Lrd>e{PS7=oqI|{3i!}w3OGG%yKg?gC^x}x zz8z+y5@{|{22OB+>+s7$J5XgJ+xM$xpxo!1NBE;i@s_x}DmSpn zgsw&XgP{&}q|0+!$PQn{j-gp?eZoqMYr?1EWxBi`_`QsVq7~PN?8|X`gqC)$edTKa zPi3IIr%R@L^NFJ}@Eez>-qSU>l1lV$<3_RchC6B+t z{~MHlEvtWOq3nWXxh3o*_-o%-cvL3a$&){F34c)Ig2-LZoNupYpS+_m zqAnNXA;nvzl#$AZfG_tkq;#Q{^i?%Z42k@EFf`zNa+k z%k`zgJGbIpbYrOERd#tLRJ`3^Vb^z_{l08C(RNyR${6vhplV3jRo&&Z#;*hFjPxF5 zk=sKxvU4lXce55`!{u3KHsH~8hEqo{znin>#^8drWw!8#4>2VWw*YPJ=IabZ19_M)mt<=dZH zI`786D+)Ge2%qni<5rb#HseQM)%%^1=S`0L5_SN33n`wTWezT~)=gZAg}Nhy2D`M9 z$FMl3m-bAUv4{Z9(0$N%SpxfdnK`7srCgT(E?-S0imJaI!Br{cE^aI<(h=W4%J<~^ zZi5>omf+q3I0xk-W#>(D1`gmm6vw>~?(-+ZejotfW~&Lj^vyBa45AJHge-)C+*<@YT7Z$$37bK9;8$K;zM zzE9z(@>E+i(S%jyc~wOT=WIyTf5gfAA#{xAmgnYum=br?cR=H*4X)cXUQpwew83>X z`)}WYi#g^C?;J93Hg-rm3xX3T-IF|Q0T-#yAtc+y$@p($e)rV`qk40NX{%v=bTK9L z<_mJgn&ZAW4Wl+ZI%t@D7gOBRL9phSV1g%nz1&1yhUN9kIm?_*S{}tvza>%K@Ougs zuo;_6CnM(sr8ZH2?w0)7BW0;l)Dek0ixtm(a zxY(}T1j-oQU*iT{Gx^#`#9uD-Ki5oBeMoTL0^e4#vOo?BtsJJ&?kuB~8@`7W{L^@Hd4JYolmi%X&_3f}ze^58G3sF?3HLVP0O6n)%Ly9o} zwi7RZ7bd=|Mx9&+s-1Wt#d*vd9&-9H=^W%HS2>l_UE_Y>CSH=(2mg^Y^e7N}-SZV28`)0^97G-JvGF(+en_Md=;5QA;Mdh`Q zDIt-`B5|DwbcFe;n0Z9tg=Q`#iYlT{%4lZB&yeyxUh{1?H~A^!#_>GO3h1v$*?C$L z;0{>vjlISbNFD`|a*NY>#$Mx0Xq=1sBFzo(EISG(`w2T2r6I+;ibjZwJb+)hCSIc! zN}I+-5^UT_XIz(oR6d<_movj34ow^`Wir>8@X<&m{6?2|Cw}p$c_;E4>3i(h7Fh5L z3HFvZ>%a@7%RwN(xF-W(4-Izvb!f1L`=Sh1N`p)~B4$=F zzj4hJGt}a9n8wZ4%$$P%aZV%2t)2RuN5z$S=tySFdcbMxOhZl3X*%Y3dAgY;N6XJ=JdFD0DZE%sr&Frd?_ksyl zHXi|_Rt<8~k+jxZHM1JJ7-7l9Oq(ckwK?n<<=*6b0^Sr)6>|u{`Vtx!3#bhmh*a+s ztpV5IzYWPl%{p05S`*x5wQ~yP3Uij0PPy7w&H(;S9MwCu(|E6O6{4K|llrQRlTYee z_8-`n@2P68*X%n3CnB0FQIWDQUgPb?zhYDDqmAUe<}rHg_83uY+6vQaFITFWcRd

+ + + diff --git a/nym-vpn/ui/package.json b/nym-vpn/ui/package.json new file mode 100644 index 0000000000..72a91ff079 --- /dev/null +++ b/nym-vpn/ui/package.json @@ -0,0 +1,38 @@ +{ + "name": "nym-vpn-ui", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "dev:app": "tauri dev", + "dev:browser": "vite --mode dev-browser", + "build": "tsc && vite build", + "preview": "vite preview", + "lint": "eslint --ext .ts,.tsx src/", + "lint:fix": "eslint --ext .js,.ts --fix src/", + "fmt": "prettier --check --ignore-unknown \"**/*\"", + "fmt:fix": "prettier --write --ignore-unknown \"**/*\"", + "typecheck": "tsc --noEmit", + "tauri": "tauri" + }, + "dependencies": { + "@tauri-apps/api": "^1.5.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@tauri-apps/cli": "^1.5.0", + "@types/react": "^18.2.15", + "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.8.0", + "@typescript-eslint/parser": "^6.8.0", + "@vitejs/plugin-react-swc": "^3.3.2", + "eslint": "^8.52.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-react": "^7.33.2", + "prettier": "^3.0.3", + "typescript": "^5.0.2", + "vite": "^4.4.5" + } +} diff --git a/nym-vpn/ui/prettier.config.js b/nym-vpn/ui/prettier.config.js new file mode 100644 index 0000000000..44bcd83526 --- /dev/null +++ b/nym-vpn/ui/prettier.config.js @@ -0,0 +1,9 @@ +/** @type {import("prettier").Config} */ + +const config = { + tabWidth: 2, + semi: true, + singleQuote: true, +}; + +export default config; diff --git a/nym-vpn/ui/public/tauri.svg b/nym-vpn/ui/public/tauri.svg new file mode 100644 index 0000000000..31b62c9280 --- /dev/null +++ b/nym-vpn/ui/public/tauri.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/nym-vpn/ui/public/vite.svg b/nym-vpn/ui/public/vite.svg new file mode 100644 index 0000000000..e7b8dfb1b2 --- /dev/null +++ b/nym-vpn/ui/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/nym-vpn/ui/src-tauri/.gitignore b/nym-vpn/ui/src-tauri/.gitignore new file mode 100644 index 0000000000..f4dfb82b2c --- /dev/null +++ b/nym-vpn/ui/src-tauri/.gitignore @@ -0,0 +1,4 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + diff --git a/nym-vpn/ui/src-tauri/Cargo.lock b/nym-vpn/ui/src-tauri/Cargo.lock new file mode 100644 index 0000000000..6909dda0e5 --- /dev/null +++ b/nym-vpn/ui/src-tauri/Cargo.lock @@ -0,0 +1,3678 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "atk" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c3d816ce6f0e2909a96830d6911c2aff044370b1ef92d7f267b43bae5addedd" +dependencies = [ + "atk-sys", + "bitflags 1.3.2", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58aeb089fb698e06db8089971c7ee317ab9644bade33383f63631437b03aafb6" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps 6.1.2", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "brotli" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da74e2b81409b1b743f8f0c62cc6254afefb8b8e50bbfe3735550f7aeefa3448" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bstr" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "bytemuck" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cairo-rs" +version = "0.15.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c76ee391b03d35510d9fa917357c7f1855bd9a6659c95a1b392e33f49b3369bc" +dependencies = [ + "bitflags 1.3.2", + "cairo-sys-rs", + "glib", + "libc", + "thiserror", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" +dependencies = [ + "glib-sys", + "libc", + "system-deps 6.1.2", +] + +[[package]] +name = "cargo_toml" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "599aa35200ffff8f04c1925aa1acc92fa2e08874379ef42e210a80e527e60838" +dependencies = [ + "serde", + "toml 0.7.8", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfb" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" +dependencies = [ + "byteorder", + "fnv", + "uuid", +] + +[[package]] +name = "cfg-expr" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3431df59f28accaf4cb4eed4a9acc66bea3f3c3753aa6cdc2f024174ef232af7" +dependencies = [ + "smallvec", +] + +[[package]] +name = "cfg-expr" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + +[[package]] +name = "cocoa" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation", + "core-graphics-types", + "libc", + "objc", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "combine" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa 0.4.8", + "matches", + "phf 0.8.0", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.38", +] + +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.38", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbaceec3c6e4211c79e7b1800fb9680527106beb2f9c51904a3210c03a448c74" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + +[[package]] +name = "embed-resource" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f54cc3e827ee1c3812239a9a41dede7b4d7d5d5464faa32d71bd7cba28ce2cb2" +dependencies = [ + "cc", + "rustc_version", + "toml 0.8.2", + "vswhom", + "winreg", +] + +[[package]] +name = "embed_plist" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "fdeflate" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "filetime" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "windows-sys 0.48.0", +] + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-core", + "futures-macro", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "gdk" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6e05c1f572ab0e1f15be94217f0dc29088c248b14f792a5ff0af0d84bcda9e8" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad38dd9cc8b099cceecdf41375bb6d481b1b5a7cd5cd603e10a69a9383f8619a" +dependencies = [ + "bitflags 1.3.2", + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps 6.1.2", +] + +[[package]] +name = "gdk-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e7a08c1e8f06f4177fb7e51a777b8c1689f743a7bc11ea91d44d2226073a88" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps 6.1.2", +] + +[[package]] +name = "gdkwayland-sys" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cca49a59ad8cfdf36ef7330fe7bdfbe1d34323220cc16a0de2679ee773aee2c2" +dependencies = [ + "gdk-sys", + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", + "system-deps 6.1.2", +] + +[[package]] +name = "gdkx11-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b7f8c7a84b407aa9b143877e267e848ff34106578b64d1e0a24bf550716178" +dependencies = [ + "gdk-sys", + "glib-sys", + "libc", + "system-deps 6.1.2", + "x11", +] + +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows 0.48.0", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + +[[package]] +name = "gio" +version = "0.15.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68fdbc90312d462781a395f7a16d96a2b379bb6ef8cd6310a2df272771c4283b" +dependencies = [ + "bitflags 1.3.2", + "futures-channel", + "futures-core", + "futures-io", + "gio-sys", + "glib", + "libc", + "once_cell", + "thiserror", +] + +[[package]] +name = "gio-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps 6.1.2", + "winapi", +] + +[[package]] +name = "glib" +version = "0.15.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb0306fbad0ab5428b0ca674a23893db909a98582969c9b537be4ced78c505d" +dependencies = [ + "bitflags 1.3.2", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "once_cell", + "smallvec", + "thiserror", +] + +[[package]] +name = "glib-macros" +version = "0.15.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10c6ae9f6fa26f4fb2ac16b528d138d971ead56141de489f8111e259b9df3c4a" +dependencies = [ + "anyhow", + "heck 0.4.1", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "glib-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" +dependencies = [ + "libc", + "system-deps 6.1.2", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "globset" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "gobject-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" +dependencies = [ + "glib-sys", + "libc", + "system-deps 6.1.2", +] + +[[package]] +name = "gtk" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e3004a2d5d6d8b5057d2b57b3712c9529b62e82c77f25c1fecde1fd5c23bd0" +dependencies = [ + "atk", + "bitflags 1.3.2", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "once_cell", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5bc2f0587cba247f60246a0ca11fe25fb733eabc3de12d1965fc07efab87c84" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps 6.1.2", +] + +[[package]] +name = "gtk3-macros" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "684c0456c086e8e7e9af73ec5b84e35938df394712054550e81558d21c44ab0d" +dependencies = [ + "anyhow", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "html5ever" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" +dependencies = [ + "log", + "mac", + "markup5ever 0.10.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "html5ever" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +dependencies = [ + "log", + "mac", + "markup5ever 0.11.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.9", +] + +[[package]] +name = "http-range" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" + +[[package]] +name = "iana-time-zone" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ico" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3804960be0bb5e4edb1e1ad67afd321a9ecfd875c3e65c099468fd2717d7cae" +dependencies = [ + "byteorder", + "png", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "ignore" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +dependencies = [ + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + +[[package]] +name = "image" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "num-rational", + "num-traits", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +dependencies = [ + "equivalent", + "hashbrown 0.14.2", + "serde", +] + +[[package]] +name = "infer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a898e4b7951673fce96614ce5751d13c40fc5674bc2d759288e46c3ab62598b3" +dependencies = [ + "cfb", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "javascriptcore-rs" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf053e7843f2812ff03ef5afe34bb9c06ffee120385caad4f6b9967fcd37d41c" +dependencies = [ + "bitflags 1.3.2", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "905fbb87419c5cde6e3269537e4ea7d46431f3008c5d057e915ef3f115e7793c" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps 5.0.0", +] + +[[package]] +name = "jni" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "json-patch" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ff1e1486799e3f64129f8ccad108b38290df9cd7015cd31bed17239f0789d6" +dependencies = [ + "serde", + "serde_json", + "thiserror", + "treediff", +] + +[[package]] +name = "kuchiki" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358" +dependencies = [ + "cssparser", + "html5ever 0.25.2", + "matches", + "selectors", +] + +[[package]] +name = "kuchikiki" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" +dependencies = [ + "cssparser", + "html5ever 0.26.0", + "indexmap 1.9.3", + "matches", + "selectors", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" + +[[package]] +name = "line-wrap" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" +dependencies = [ + "safemem", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "markup5ever" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" +dependencies = [ + "log", + "phf 0.8.0", + "phf_codegen 0.8.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", + "simd-adler32", +] + +[[package]] +name = "ndk" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" +dependencies = [ + "bitflags 1.3.2", + "jni-sys", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "nym-vpn-ui" +version = "0.0.0" +dependencies = [ + "serde", + "serde_json", + "tauri", + "tauri-build", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", + "objc_exception", +] + +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "open" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8" +dependencies = [ + "pathdiff", + "windows-sys 0.42.0", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pango" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f" +dependencies = [ + "bitflags 1.3.2", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps 6.1.2", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "smallvec", + "windows-targets", +] + +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_macros 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_macros 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "phf_macros" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "plist" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a4a0cfc5fb21a09dc6af4bf834cf10d4a32fccd9e2ea468c4b1751a097487aa" +dependencies = [ + "base64 0.21.5", + "indexmap 1.9.3", + "line-wrap", + "quick-xml", + "serde", + "time", +] + +[[package]] +name = "png" +version = "0.17.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-xml" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.10", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom 0.2.10", + "redox_syscall 0.2.16", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "selectors" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" +dependencies = [ + "bitflags 1.3.2", + "cssparser", + "derive_more", + "fxhash", + "log", + "matches", + "phf 0.8.0", + "phf_codegen 0.8.0", + "precomputed-hash", + "servo_arc", + "smallvec", + "thin-slice", +] + +[[package]] +name = "semver" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "serde_json" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +dependencies = [ + "itoa 1.0.9", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_with" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" +dependencies = [ + "base64 0.21.5", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.0.2", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "serialize-to-javascript" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9823f2d3b6a81d98228151fdeaf848206a7855a7a042bbf9bf870449a66cafb" +dependencies = [ + "serde", + "serde_json", + "serialize-to-javascript-impl", +] + +[[package]] +name = "serialize-to-javascript-impl" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "servo_arc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + +[[package]] +name = "soup2" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b4d76501d8ba387cf0fefbe055c3e0a59891d09f0f995ae4e4b16f6b60f3c0" +dependencies = [ + "bitflags 1.3.2", + "gio", + "glib", + "libc", + "once_cell", + "soup2-sys", +] + +[[package]] +name = "soup2-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "009ef427103fcb17f802871647a7fa6c60cbb654b4c4e4c0ac60a31c5f6dc9cf" +dependencies = [ + "bitflags 1.3.2", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps 5.0.0", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "state" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b" +dependencies = [ + "loom", +] + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-deps" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18db855554db7bd0e73e06cf7ba3df39f97812cb11d3f75e71c39bf45171797e" +dependencies = [ + "cfg-expr 0.9.1", + "heck 0.3.3", + "pkg-config", + "toml 0.5.11", + "version-compare 0.0.11", +] + +[[package]] +name = "system-deps" +version = "6.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94af52f9402f94aac4948a2518b43359be8d9ce6cd9efc1c4de3b2f7b7e897d6" +dependencies = [ + "cfg-expr 0.15.5", + "heck 0.4.1", + "pkg-config", + "toml 0.8.2", + "version-compare 0.1.1", +] + +[[package]] +name = "tao" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b768eb5cf657b045d03304b1f60ecb54eac8b520f393c4f4240a94111a1caa17" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "cc", + "cocoa", + "core-foundation", + "core-graphics", + "crossbeam-channel", + "dispatch", + "gdk", + "gdk-pixbuf", + "gdk-sys", + "gdkwayland-sys", + "gdkx11-sys", + "gio", + "glib", + "glib-sys", + "gtk", + "image", + "instant", + "jni", + "lazy_static", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "objc", + "once_cell", + "parking_lot", + "png", + "raw-window-handle", + "scopeguard", + "serde", + "tao-macros", + "unicode-segmentation", + "uuid", + "windows 0.39.0", + "windows-implement", + "x11-dl", +] + +[[package]] +name = "tao-macros" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec114582505d158b669b136e6851f85840c109819d77c42bb7c0709f727d18c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "tar" +version = "0.4.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "target-lexicon" +version = "0.12.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" + +[[package]] +name = "tauri" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bfe673cf125ef364d6f56b15e8ce7537d9ca7e4dae1cf6fbbdeed2e024db3d9" +dependencies = [ + "anyhow", + "cocoa", + "dirs-next", + "embed_plist", + "encoding_rs", + "flate2", + "futures-util", + "glib", + "glob", + "gtk", + "heck 0.4.1", + "http", + "ignore", + "objc", + "once_cell", + "open", + "percent-encoding", + "rand 0.8.5", + "raw-window-handle", + "regex", + "semver", + "serde", + "serde_json", + "serde_repr", + "serialize-to-javascript", + "state", + "tar", + "tauri-macros", + "tauri-runtime", + "tauri-runtime-wry", + "tauri-utils", + "tempfile", + "thiserror", + "tokio", + "url", + "uuid", + "webkit2gtk", + "webview2-com", + "windows 0.39.0", +] + +[[package]] +name = "tauri-build" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defbfc551bd38ab997e5f8e458f87396d2559d05ce32095076ad6c30f7fc5f9c" +dependencies = [ + "anyhow", + "cargo_toml", + "dirs-next", + "heck 0.4.1", + "json-patch", + "semver", + "serde", + "serde_json", + "tauri-utils", + "tauri-winres", + "walkdir", +] + +[[package]] +name = "tauri-codegen" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b3475e55acec0b4a50fb96435f19631fb58cbcd31923e1a213de5c382536bbb" +dependencies = [ + "base64 0.21.5", + "brotli", + "ico", + "json-patch", + "plist", + "png", + "proc-macro2", + "quote", + "regex", + "semver", + "serde", + "serde_json", + "sha2", + "tauri-utils", + "thiserror", + "time", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-macros" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613740228de92d9196b795ac455091d3a5fbdac2654abb8bb07d010b62ab43af" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 1.0.109", + "tauri-codegen", + "tauri-utils", +] + +[[package]] +name = "tauri-runtime" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07f8e9e53e00e9f41212c115749e87d5cd2a9eebccafca77a19722eeecd56d43" +dependencies = [ + "gtk", + "http", + "http-range", + "rand 0.8.5", + "raw-window-handle", + "serde", + "serde_json", + "tauri-utils", + "thiserror", + "url", + "uuid", + "webview2-com", + "windows 0.39.0", +] + +[[package]] +name = "tauri-runtime-wry" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8141d72b6b65f2008911e9ef5b98a68d1e3413b7a1464e8f85eb3673bb19a895" +dependencies = [ + "cocoa", + "gtk", + "percent-encoding", + "rand 0.8.5", + "raw-window-handle", + "tauri-runtime", + "tauri-utils", + "uuid", + "webkit2gtk", + "webview2-com", + "windows 0.39.0", + "wry", +] + +[[package]] +name = "tauri-utils" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34d55e185904a84a419308d523c2c6891d5e2dbcee740c4997eb42e75a7b0f46" +dependencies = [ + "brotli", + "ctor", + "dunce", + "glob", + "heck 0.4.1", + "html5ever 0.26.0", + "infer", + "json-patch", + "kuchikiki", + "log", + "memchr", + "phf 0.10.1", + "proc-macro2", + "quote", + "semver", + "serde", + "serde_json", + "serde_with", + "thiserror", + "url", + "walkdir", + "windows 0.39.0", +] + +[[package]] +name = "tauri-winres" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5993dc129e544393574288923d1ec447c857f3f644187f4fbf7d9a875fbfc4fb" +dependencies = [ + "embed-resource", + "toml 0.7.8", +] + +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall 0.3.5", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "thin-slice" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +dependencies = [ + "deranged", + "itoa 1.0.9", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +dependencies = [ + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +dependencies = [ + "backtrace", + "bytes", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.2", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.0.2", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.0.2", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "treediff" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52984d277bdf2a751072b5df30ec0377febdb02f7696d64c2d7d54630bac4303" +dependencies = [ + "serde_json", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "url" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "uuid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +dependencies = [ + "getrandom 0.2.10", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version-compare" +version = "0.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c18c859eead79d8b95d09e4678566e8d70105c4e7b251f707a03df32442661b" + +[[package]] +name = "version-compare" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" +dependencies = [ + "libc", + "vswhom-sys", +] + +[[package]] +name = "vswhom-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b17ae1f6c8a2b28506cd96d412eebf83b4a0ff2cbefeeb952f2f9dfa44ba18" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.38", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "webkit2gtk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8f859735e4a452aeb28c6c56a852967a8a76c8eb1cc32dbf931ad28a13d6370" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup2", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d76ca6ecc47aeba01ec61e480139dda143796abcae6f83bcddf50d6b5b1dcf3" +dependencies = [ + "atk-sys", + "bitflags 1.3.2", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pango-sys", + "pkg-config", + "soup2-sys", + "system-deps 6.1.2", +] + +[[package]] +name = "webview2-com" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4a769c9f1a64a8734bde70caafac2b96cada12cd4aefa49196b3a386b8b4178" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows 0.39.0", + "windows-implement", +] + +[[package]] +name = "webview2-com-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaebe196c01691db62e9e4ca52c5ef1e4fd837dcae27dae3ada599b5a8fd05ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "webview2-com-sys" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac48ef20ddf657755fdcda8dfed2a7b4fc7e4581acce6fe9b88c3d64f29dee7" +dependencies = [ + "regex", + "serde", + "serde_json", + "thiserror", + "windows 0.39.0", + "windows-bindgen", + "windows-metadata", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" +dependencies = [ + "windows-implement", + "windows_aarch64_msvc 0.39.0", + "windows_i686_gnu 0.39.0", + "windows_i686_msvc 0.39.0", + "windows_x86_64_gnu 0.39.0", + "windows_x86_64_msvc 0.39.0", +] + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-bindgen" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68003dbd0e38abc0fb85b939240f4bce37c43a5981d3df37ccbaaa981b47cb41" +dependencies = [ + "windows-metadata", + "windows-tokens", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-implement" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba01f98f509cb5dc05f4e5fc95e535f78260f15fea8fe1a8abdd08f774f1cee7" +dependencies = [ + "syn 1.0.109", + "windows-tokens", +] + +[[package]] +name = "windows-metadata" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee5e275231f07c6e240d14f34e1b635bf1faa1c76c57cfd59a5cdb9848e4278" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-tokens" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f838de2fe15fe6bac988e74b798f26499a8b21a9d97edec321e79b28d1d7f597" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winnow" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "937f3df7948156640f46aacef17a70db0de5917bda9c92b0f751f3a955b588fc" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wry" +version = "0.24.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ef04bdad49eba2e01f06e53688c8413bd6a87b0bc14b72284465cf96e3578e" +dependencies = [ + "base64 0.13.1", + "block", + "cocoa", + "core-graphics", + "crossbeam-channel", + "dunce", + "gdk", + "gio", + "glib", + "gtk", + "html5ever 0.25.2", + "http", + "kuchiki", + "libc", + "log", + "objc", + "objc_id", + "once_cell", + "serde", + "serde_json", + "sha2", + "soup2", + "tao", + "thiserror", + "url", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows 0.39.0", + "windows-implement", +] + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "xattr" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" +dependencies = [ + "libc", +] diff --git a/nym-vpn/ui/src-tauri/Cargo.toml b/nym-vpn/ui/src-tauri/Cargo.toml new file mode 100644 index 0000000000..e05eaf1144 --- /dev/null +++ b/nym-vpn/ui/src-tauri/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "nym-vpn-ui" +version = "0.0.0" +description = "Application UI for Nym VPN desktop clients" +authors = ["you"] +license = "" +repository = "" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[build-dependencies] +tauri-build = { version = "1.5", features = [] } + +[dependencies] +tauri = { version = "1.5", features = ["shell-open"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" + +[features] +# this feature is used for production builds or when `devPath` points to the filesystem +# DO NOT REMOVE!! +custom-protocol = ["tauri/custom-protocol"] diff --git a/nym-vpn/ui/src-tauri/build.rs b/nym-vpn/ui/src-tauri/build.rs new file mode 100644 index 0000000000..d860e1e6a7 --- /dev/null +++ b/nym-vpn/ui/src-tauri/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_build::build() +} diff --git a/nym-vpn/ui/src-tauri/icons/128x128.png b/nym-vpn/ui/src-tauri/icons/128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..6be5e50e9b9ae84d9e2ee433f32ef446495eaf3b GIT binary patch literal 3512 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 literal 0 HcmV?d00001 diff --git a/nym-vpn/ui/src-tauri/icons/128x128@2x.png b/nym-vpn/ui/src-tauri/icons/128x128@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e81becee571e96f76aa5667f9324c05e5e7a4479 GIT binary patch literal 7012 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 Sh@|Ye~|0>}wMPLT8jm@Y!H33Sz}5aFI6 zM9Lzqz|;A*0sGs=2A1uU!1nk2dGF7knQwr99SAFen)x(eCO;F8y2C~0FD1YxRTPcy zPWVxkUYmeuz}Tv?7&Fe-!UE{)ZW)Mb;H)^#eHDv$`dkZGguJz@^MA!ZNGAUqt{|0H zpZ7Ch9S`q5!>R%}>}62!+(T^evyO+ImSo2wpu)su4^3nw5(%)KD%gbSev^*HZZ&3( z#&c@Z0gH|}Ck)w6fh0&NBJ62ib%R}(3@$VFl*_#l2W$wQ-~4RmZZAt5O*^2Q5}Xr8Hy@c`#pM?kc?hFWxRXr*mUfUCXf4ka5DD~ zat6d85COB05l#(P9*cQZ3EC8fVdS~?&vN#rce(aF9@xp80O2{{FBvU+{X>Hoh;xI` z{$e^Nw1y*VbO8wv`8|-m?NwNaKGTGaF{P^JLB^DbOYWIbn%eT`*!^C1H36=O8Z-M> zkD~88ry`eSo`tEBN4>w7OWZwUzlh{WM1m8R6zepqGcGMaV7vWY9b?K4b6~|HVG)ec wi>I@ws#sZo7or4_*4M>7;p5{nr2pZ?Uu4>Krr0kU)&Kwi07*qoM6N<$f)&@lf&c&j literal 0 HcmV?d00001 diff --git a/nym-vpn/ui/src-tauri/icons/Square107x107Logo.png b/nym-vpn/ui/src-tauri/icons/Square107x107Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0ca4f27198838968bd60ed7d371bfa23496b7fe5 GIT binary patch literal 2863 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 Y2S8W#vM)6=T>t<807*qoM6N<$f*y@n<^TWy literal 0 HcmV?d00001 diff --git a/nym-vpn/ui/src-tauri/icons/Square284x284Logo.png b/nym-vpn/ui/src-tauri/icons/Square284x284Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c021d2ba76619c08969ab688db3b27f29257aa6f GIT binary patch literal 7737 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 literal 0 HcmV?d00001 diff --git a/nym-vpn/ui/src-tauri/icons/Square30x30Logo.png b/nym-vpn/ui/src-tauri/icons/Square30x30Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..621970023096ed9f494ba18ace15421a45cd65fa GIT binary patch literal 903 zcmV;219<$2P)2 z+CUKPMqaqGiH;zb!R4$B-WXS^YzQr=@UH>k4?*L)&R=zYjBrZenKdc9|JlS$SO*RJ zKt8FSTDAdk1g_WPAO!p^V!AuL;Lm;uQyV;zKq)J3i(;q*;k+pD%f3eltU`PYdy9(k0&%` zuWAPcV6|-y?|?7O1W!KSK}pbk8#~!|FA@(VJkt^V@0lio{afoAeo*f&$W2s6${5!1eKvAGD2$GZwSB98L2ZVS- zKn8ENRkZ*sb!@QugOrQNK3(sy1v%J#m|rpB+h|Nkqa3FRT>74xSs{#&saU2Lf!_Iq zKmuKAESh`gs!fneGWn+nf}l?7jE$HW!Af&vE5=G!QU)U2v&HLIBGXKk4nQx{hsHjL zLPMAo5=*uInFbq7(aa`Y2VX5wCmaeqvECOFv)a>0t>ZaEb*cJccER=BB?KFZhV$c^ znL*l8x*UYZv4WK|j?~Jt6~~F%{pk~z5A*>^M`?r5m9@RJ_x|uEtX(6Vk@Y()MVto* z93wr)%3m%|#OZ~srm>zF(JvDuTq*@;d&^>_BJm5hOU`3FjG70L#Vzv9I?`<7$T@

5l#v3A#xI3*z~1~fvo9Q(N^(==!|_FZ z*duZ=+M1~)8E|otX8KNZlr?qels#x_1Xq@9IIw~@9uAREJVH)Xw^}UclF6327}E42 zT)E&?U%TK?(+K7%R!`H5oX0i)4Qn5??Iw3p5J~6_u+aWehY{DSn}3V2p$bgjnAu?o)v@iC254fXeMv50$9YrpU`N?u@QIWs)T?SP|fa}(|9 zqAX+!7`cx=4)cCBg5h~pu(?@9`)aCr#oyz$ld=#RFxYCNZCZls@4v2~*e-t6PEVvV z&bbK3b3wt(Coc!ufAbXXC<**#HQ%J9k`New6iG<5RjtO4XVO?dCvwxD{kJ#tfQr(X zg^NTwF-FwAeS_{V4bfel8l`~NbfrTR2s!G>WduFWxH(t~aK4q=6rEE^$+Uox>gJO2 z{L<;6Q6nHa5#ZEM>H58not!)z(6*_=^~8}jWf*IG$AUKVWOZ4?)GfF z+BM#*wKKmLFD7E~W3U!$IVm$k_k1f&Kz6WV8@55P?r~bcg-Za-!rvW?ns&)KOGT2~ zlkAyqhQj=P$Eg3w#K~}zH@J5bo-BfHjInKSz$@?+Z)NPD4pHj^_Qxmi`UqoTy=`sV zLVxrXGuBr=QRm|}wg75yetQQK4fY3#P_~J}zEfPnb2C4Wo!E(d*(cA;b?7$g2in<( zPn)ghX}nzJPmb6(3Dpeg_GW~Hc}Lt=lgsSZz z!5QXyz7KaR;D`3Ee}d`af{H>WWZ|Io1QI3~4Ll_`g1(cRnhLK73Ro)7zPCd={1W2x zRp%Xlvv4>!<2@}$hz|!V{T}_eHx2xkLl^hQoZTCnsjCl|W_@5Fx2(+j0ogy&Y+;L- z<)G$*CiN7hOm^s!{U>1F7U=iNk{+u~dAC!eDz%=|glFW0jEZU1&o(G_c#wTxUjnG} z#cg3>jEpUi#Mlq@t?Msg_#geK^Lx@DyHWf7=AS5vVyM7YOjvUVCfcpVR<(+5!H?9- zySI6s>o3m&*zr||=wcPGyBkQV`EWJl@bH8qobjOp+sXL*)=&yX)8aAbf~tGv?a2SN zu^Ddo-z?DWk9h9Yz#5p^NU#x~wYSd?H@w@!2Gb4G)6-utEMV~~M85Br5ff(v5O1|T z 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 String { + format!("Hello, {}! You've been greeted from Rust!", name) +} + +fn main() { + tauri::Builder::default() + .invoke_handler(tauri::generate_handler![greet]) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} diff --git a/nym-vpn/ui/src-tauri/tauri.conf.json b/nym-vpn/ui/src-tauri/tauri.conf.json new file mode 100644 index 0000000000..89644f65b7 --- /dev/null +++ b/nym-vpn/ui/src-tauri/tauri.conf.json @@ -0,0 +1,46 @@ +{ + "build": { + "beforeDevCommand": "yarn dev", + "beforeBuildCommand": "yarn build", + "devPath": "http://localhost:1420", + "distDir": "../dist", + "withGlobalTauri": false + }, + "package": { + "productName": "nym-vpn-ui", + "version": "0.0.0" + }, + "tauri": { + "allowlist": { + "all": false, + "shell": { + "all": false, + "open": true + } + }, + "bundle": { + "active": true, + "targets": "all", + "identifier": "com.tauri.dev", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ] + }, + "security": { + "csp": null + }, + "windows": [ + { + "fullscreen": false, + "resizable": true, + "title": "NymVPN", + "width": 800, + "height": 600 + } + ] + } +} diff --git a/nym-vpn/ui/src/App.css b/nym-vpn/ui/src/App.css new file mode 100644 index 0000000000..a89ebd15df --- /dev/null +++ b/nym-vpn/ui/src/App.css @@ -0,0 +1,7 @@ +.logo.vite:hover { + filter: drop-shadow(0 0 2em #747bff); +} + +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafb); +} diff --git a/nym-vpn/ui/src/App.tsx b/nym-vpn/ui/src/App.tsx new file mode 100644 index 0000000000..f354586200 --- /dev/null +++ b/nym-vpn/ui/src/App.tsx @@ -0,0 +1,53 @@ +import { useState } from 'react'; +import reactLogo from './assets/react.svg'; +import { invoke } from '@tauri-apps/api/tauri'; +import './App.css'; + +function App() { + const [greetMsg, setGreetMsg] = useState(''); + const [name, setName] = useState(''); + + async function greet() { + // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command + setGreetMsg(await invoke('greet', { name })); + } + + return ( +

+

Welcome to Tauri!

+ +
+ +

Click on the Tauri, Vite, and React logos to learn more.

+ +
{ + e.preventDefault(); + greet(); + }} + > + setName(e.currentTarget.value)} + placeholder="Enter a name..." + /> + +
+ +

{greetMsg}

+
+ ); +} + +export default App; diff --git a/nym-vpn/ui/src/assets/react.svg b/nym-vpn/ui/src/assets/react.svg new file mode 100644 index 0000000000..6c87de9bb3 --- /dev/null +++ b/nym-vpn/ui/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/nym-vpn/ui/src/dev/setup.ts b/nym-vpn/ui/src/dev/setup.ts new file mode 100644 index 0000000000..de8c1ca081 --- /dev/null +++ b/nym-vpn/ui/src/dev/setup.ts @@ -0,0 +1,11 @@ +import { mockIPC, mockWindows } from '@tauri-apps/api/mocks'; +import { greet } from './tauri-cmd-mocks'; + +mockWindows('main'); + +mockIPC(async (cmd, args) => { + console.log(`IPC call mocked "${cmd}"`); + if (cmd === 'greet') { + return greet(args.name as string) + } +}); diff --git a/nym-vpn/ui/src/dev/tauri-cmd-mocks/greet.ts b/nym-vpn/ui/src/dev/tauri-cmd-mocks/greet.ts new file mode 100644 index 0000000000..30f2b2f5ac --- /dev/null +++ b/nym-vpn/ui/src/dev/tauri-cmd-mocks/greet.ts @@ -0,0 +1,3 @@ +export default function greet(name: string): string { + return `Hello, ${name}!`; +} diff --git a/nym-vpn/ui/src/dev/tauri-cmd-mocks/index.ts b/nym-vpn/ui/src/dev/tauri-cmd-mocks/index.ts new file mode 100644 index 0000000000..0f66f1f84f --- /dev/null +++ b/nym-vpn/ui/src/dev/tauri-cmd-mocks/index.ts @@ -0,0 +1,2 @@ +export {default as greet } from './greet'; + diff --git a/nym-vpn/ui/src/main.tsx b/nym-vpn/ui/src/main.tsx new file mode 100644 index 0000000000..977f2b3fa3 --- /dev/null +++ b/nym-vpn/ui/src/main.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; +import './styles.css'; + +console.log(import.meta.env.MODE); + +if (import.meta.env.MODE === 'dev-browser') { + console.log('Running in dev-browser mode. Mocking tauri window and IPCs'); + import('./dev/setup'); +} + +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + + + , +); diff --git a/nym-vpn/ui/src/styles.css b/nym-vpn/ui/src/styles.css new file mode 100644 index 0000000000..f7de85bf06 --- /dev/null +++ b/nym-vpn/ui/src/styles.css @@ -0,0 +1,109 @@ +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color: #0f0f0f; + background-color: #f6f6f6; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +.container { + margin: 0; + padding-top: 10vh; + display: flex; + flex-direction: column; + justify-content: center; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: 0.75s; +} + +.logo.tauri:hover { + filter: drop-shadow(0 0 2em #24c8db); +} + +.row { + display: flex; + justify-content: center; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} + +a:hover { + color: #535bf2; +} + +h1 { + text-align: center; +} + +input, +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + color: #0f0f0f; + background-color: #ffffff; + transition: border-color 0.25s; + box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); +} + +button { + cursor: pointer; +} + +button:hover { + border-color: #396cd8; +} +button:active { + border-color: #396cd8; + background-color: #e8e8e8; +} + +input, +button { + outline: none; +} + +#greet-input { + margin-right: 5px; +} + +@media (prefers-color-scheme: dark) { + :root { + color: #f6f6f6; + background-color: #2f2f2f; + } + + a:hover { + color: #24c8db; + } + + input, + button { + color: #ffffff; + background-color: #0f0f0f98; + } + button:active { + background-color: #0f0f0f69; + } +} diff --git a/nym-vpn/ui/src/vite-env.d.ts b/nym-vpn/ui/src/vite-env.d.ts new file mode 100644 index 0000000000..11f02fe2a0 --- /dev/null +++ b/nym-vpn/ui/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/nym-vpn/ui/tsconfig.json b/nym-vpn/ui/tsconfig.json new file mode 100644 index 0000000000..a7fc6fbf23 --- /dev/null +++ b/nym-vpn/ui/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/nym-vpn/ui/tsconfig.node.json b/nym-vpn/ui/tsconfig.node.json new file mode 100644 index 0000000000..42872c59f5 --- /dev/null +++ b/nym-vpn/ui/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/nym-vpn/ui/vite.config.ts b/nym-vpn/ui/vite.config.ts new file mode 100644 index 0000000000..8d90eb50cb --- /dev/null +++ b/nym-vpn/ui/vite.config.ts @@ -0,0 +1,20 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react-swc'; + +// https://vitejs.dev/config/ +export default defineConfig(async () => ({ + plugins: [react()], + + // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` + // + // 1. prevent vite from obscuring rust errors + clearScreen: false, + // 2. tauri expects a fixed port, fail if that port is not available + server: { + port: 1420, + strictPort: true, + }, + // 3. to make use of `TAURI_DEBUG` and other env variables + // https://tauri.app/v1/api/config#buildconfig.beforedevcommand + envPrefix: ['VITE_', 'TAURI_'], +})); diff --git a/nym-vpn/ui/yarn.lock b/nym-vpn/ui/yarn.lock new file mode 100644 index 0000000000..2f994347d5 --- /dev/null +++ b/nym-vpn/ui/yarn.lock @@ -0,0 +1,2102 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@esbuild/android-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622" + integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ== + +"@esbuild/android-arm@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682" + integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw== + +"@esbuild/android-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2" + integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg== + +"@esbuild/darwin-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1" + integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA== + +"@esbuild/darwin-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d" + integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ== + +"@esbuild/freebsd-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54" + integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw== + +"@esbuild/freebsd-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e" + integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ== + +"@esbuild/linux-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0" + integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA== + +"@esbuild/linux-arm@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0" + integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg== + +"@esbuild/linux-ia32@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7" + integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA== + +"@esbuild/linux-loong64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d" + integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg== + +"@esbuild/linux-mips64el@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231" + integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ== + +"@esbuild/linux-ppc64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb" + integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA== + +"@esbuild/linux-riscv64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6" + integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A== + +"@esbuild/linux-s390x@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071" + integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ== + +"@esbuild/linux-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338" + integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w== + +"@esbuild/netbsd-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1" + integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A== + +"@esbuild/openbsd-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae" + integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg== + +"@esbuild/sunos-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d" + integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ== + +"@esbuild/win32-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9" + integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg== + +"@esbuild/win32-ia32@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102" + integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g== + +"@esbuild/win32-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d" + integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ== + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4" + integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA== + +"@eslint/eslintrc@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" + integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.52.0": + version "8.52.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.52.0.tgz#78fe5f117840f69dc4a353adf9b9cd926353378c" + integrity sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA== + +"@humanwhocodes/config-array@^0.11.13": + version "0.11.13" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" + integrity sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ== + dependencies: + "@humanwhocodes/object-schema" "^2.0.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" + integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@swc/core-darwin-arm64@1.3.94": + version "1.3.94" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.94.tgz#2fe8e513433cd5d5c987952e38ca06e6226de0f3" + integrity sha512-KNuE6opIy/wAXiGUWLhGWhCG3wA/AdjG6eYkv6dstrAURLaQMAoD8vDfVm8pxS8FA8Kx+0Z4QiDNPqk5aKIsqg== + +"@swc/core-darwin-x64@1.3.94": + version "1.3.94" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.94.tgz#6b626013657e18eaf1e795370eac70e86dc7d300" + integrity sha512-HypemhyehQrLqXwfJv5ronD4BMAXdgMCP4Ei7rt3B6Ftmt9axwGvdwGiXxsYR9h1ncyxoVxN+coGxbNIhKhahw== + +"@swc/core-linux-arm-gnueabihf@1.3.94": + version "1.3.94" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.94.tgz#300483c9e9a3a4084d8264f59daee19102e1084b" + integrity sha512-KzKN54c7Y6X1db+bBVSXG4+bXmAPvXtDWk+TgwNJH4yYliOrnP/RKkHA5QZ9VFSnqJF06/sAO4kYBiL/aVQDBQ== + +"@swc/core-linux-arm64-gnu@1.3.94": + version "1.3.94" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.94.tgz#ac099db32d60e161c11bf01a9496ea0ada347247" + integrity sha512-iAcR8Ho0Uck/SLSrgYfXkpcGOXuN5waMZO7GlL/52QODr7GJtOfZ0H1MCZLbIFkPJp/iXoJpYgym4d/qSd477Q== + +"@swc/core-linux-arm64-musl@1.3.94": + version "1.3.94" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.94.tgz#e555791abf27d74831dc3581327662f65e2b62f2" + integrity sha512-VCHL1Mb9ENHx+sAeubSSg481MUeP9/PYzPPy9tfswunj/w35M+vEWflwK2dzQL9kUTFD3zcFTpAgsKnj6aX24w== + +"@swc/core-linux-x64-gnu@1.3.94": + version "1.3.94" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.94.tgz#8d7d4104ba29ce0d7871472c69a7616db2908850" + integrity sha512-gjq7U6clhJi0Oel2a4gwR4MbSu+THQ2hmBNVCOSA3JjPZWZTkJXaJDpnh/r7PJxKBwUDlo0VPlwiwjepAQR2Rw== + +"@swc/core-linux-x64-musl@1.3.94": + version "1.3.94" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.94.tgz#d7180fcff29339b7a2011670a1e1697a2075d13d" + integrity sha512-rSylruWyeol2ujZDHmwiovupMR5ukMXivlA7DDxmQ1dFUV9HuiPknQrU5rEbI3V2V3V5RkpbEKjnADen7AeMPQ== + +"@swc/core-win32-arm64-msvc@1.3.94": + version "1.3.94" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.94.tgz#1ddab334f90ba40fb2b7768476fb64f4e8f1d759" + integrity sha512-OenDUr5MQkz506ebVQq6ezoZ3GZ26nchgf5mPnwab4gx2TEiyR9zn7MdX5LWskTmOK3+FszPbGK0B5oLK6Y5yw== + +"@swc/core-win32-ia32-msvc@1.3.94": + version "1.3.94" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.94.tgz#e254b4ab6514cf0ebd89781c7bf348484d006b8b" + integrity sha512-mi6NcmtJKnaiHAxLtVz+WzunscsEwPdA0j15DuiYVx06Xo+MdRLJj4eVBgVLwGD1AI3IqKs4MVVx2cD7n0h5mg== + +"@swc/core-win32-x64-msvc@1.3.94": + version "1.3.94" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.94.tgz#dc193537ccd87f40552e099038f543e0756f74de" + integrity sha512-Ba0ZLcGMnqPWWF9Xa+rWhhnkpvE7XoQegMP/VCF2JIHb2ieGBC8jChO6nKRFKZjib/3wghGzxakyDQx3LDhDug== + +"@swc/core@^1.3.85": + version "1.3.94" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.94.tgz#3719cbec7d05e8228fd5b5c7e0dec65ecf2d0422" + integrity sha512-jTHn8UJOGgERKZLy8euEixVAzC/w/rUSuMlM3e7hxgap/TC595hSkuQwtkpL238dsuEPveD44GMy2A5UBtSvjg== + dependencies: + "@swc/counter" "^0.1.1" + "@swc/types" "^0.1.5" + optionalDependencies: + "@swc/core-darwin-arm64" "1.3.94" + "@swc/core-darwin-x64" "1.3.94" + "@swc/core-linux-arm-gnueabihf" "1.3.94" + "@swc/core-linux-arm64-gnu" "1.3.94" + "@swc/core-linux-arm64-musl" "1.3.94" + "@swc/core-linux-x64-gnu" "1.3.94" + "@swc/core-linux-x64-musl" "1.3.94" + "@swc/core-win32-arm64-msvc" "1.3.94" + "@swc/core-win32-ia32-msvc" "1.3.94" + "@swc/core-win32-x64-msvc" "1.3.94" + +"@swc/counter@^0.1.1": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.2.tgz#bf06d0770e47c6f1102270b744e17b934586985e" + integrity sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw== + +"@swc/types@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.5.tgz#043b731d4f56a79b4897a3de1af35e75d56bc63a" + integrity sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw== + +"@tauri-apps/api@^1.5.0": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@tauri-apps/api/-/api-1.5.1.tgz#9074476c4323f71351db624e9711c99277cdfb99" + integrity sha512-6unsZDOdlXTmauU3NhWhn+Cx0rODV+rvNvTdvolE5Kls5ybA6cqndQENDt1+FS0tF7ozCP66jwWoH6a5h90BrA== + +"@tauri-apps/cli-darwin-arm64@1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.5.tgz#394fbc2920bc84524c8adb0021b1f788495a643f" + integrity sha512-CmKc/PjlI1+oD88VtR1Nr0pmrf/cUU1XFRazU+FB9ChWO3ZPp4MeA+eSemiln0F1XJR9fMJw/QS58IPH4GydLw== + +"@tauri-apps/cli-darwin-x64@1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.5.tgz#76f91cdb629d3f2996fe41a9401080baaabd956c" + integrity sha512-d7l/4FB5uWGkMHM08UI6+qk45PAeBYMSC19l0Sz47WrRHQDMIX4V591ydnUg8AffWK/I3r1DJtQmd6C89g7JwQ== + +"@tauri-apps/cli-linux-arm-gnueabihf@1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.5.tgz#94cad5de0ce908271768aae931ed455352516b44" + integrity sha512-avFw/BvW01qhXPbzfVPy/KU/FYJ/SUoCe9DP8oA/eSh49VzE9JvlH62iqjtGtA8XzxfTJRezXdCQbrq7OkQHKQ== + +"@tauri-apps/cli-linux-arm64-gnu@1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.5.tgz#9601a48572080796f30621a3723a2bbab5109e29" + integrity sha512-j7yvbZ/IG+W5QtEqK9nSz33lJtaZEFvNnFs0Bxz8r2TjF80m8SdlfxL38R/OVl7xM7ctJWRyM6ws9mBWT0uHNA== + +"@tauri-apps/cli-linux-arm64-musl@1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.5.tgz#c99c3612ffe65f4cc603baa821f7d8dcc1afd226" + integrity sha512-neLu3FEYE2IixnqtX10+jsvkJx26kxmh5ekktzjolu5HqV73nquCj7VK/V5uyRMyMQeGEPyhbT09A36DUl+zDA== + +"@tauri-apps/cli-linux-x64-gnu@1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.5.tgz#f4d2ad6a46ef53d184ea6f3d27815c0b5bbaccd7" + integrity sha512-zZlfklupFaV6RxPze9kQytp1N/K4q/QuYUsgQ5GB/7/OX4EWTUkOpNCeVEocmHag4+9UCQkb1HxdTkXiEVcXEQ== + +"@tauri-apps/cli-linux-x64-musl@1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.5.tgz#e59cda396e24915a3307077c27f0c1a061624229" + integrity sha512-2VByWblZnSgLZJyhRxggy528ahcYFH8jboZZ2BUaYT/P5WeJ1lOoQwQj9ssEUrGauGPNS3PmmfBCF7u5oaMRJA== + +"@tauri-apps/cli-win32-arm64-msvc@1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.5.tgz#44b6fcf0966a3bb9fc163d19ace83e98ee03cdce" + integrity sha512-4UZFHMIJaqgPGT+PHfDDp63OgJsXwLd+0u8x1+2hFMT25dEYj+KzKOVwktYgN6UT9F7rEyzNTTZe7ZZpAkGT5Q== + +"@tauri-apps/cli-win32-ia32-msvc@1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.5.tgz#04c7c7eba376a82e2f13c6e3c640cf34c988502c" + integrity sha512-t4XbmMyDtX7kW+wQrlWO4tZus+w77w+Hz5/NBQsjRNnO3lbuYMYaF4IZpt0tZG6lQ0uyvH+o2v5dbZhUTpVT0Q== + +"@tauri-apps/cli-win32-x64-msvc@1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.5.tgz#cc4f5336e958e5d754a551e5c5df5e32680b89ec" + integrity sha512-7OiUfBmYjQ9LGTvl0Zs567JQIQuxpTCDraca3cpJFV/6TsRLEZAvXo3sgqEFOJopImrCWTpUT4FyzsGC76KlIg== + +"@tauri-apps/cli@^1.5.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/cli/-/cli-1.5.5.tgz#8bcf5fa7694f7bc359a4d1f3b45fed20f938aca9" + integrity sha512-AUFqiA5vbriMd6xWDLWwxzW2FtEhSmL0KcMktkQQGzM+QKFnFbQsubvvd95YDAIX2Q4L1eygGv7ebNX0QVA7sg== + optionalDependencies: + "@tauri-apps/cli-darwin-arm64" "1.5.5" + "@tauri-apps/cli-darwin-x64" "1.5.5" + "@tauri-apps/cli-linux-arm-gnueabihf" "1.5.5" + "@tauri-apps/cli-linux-arm64-gnu" "1.5.5" + "@tauri-apps/cli-linux-arm64-musl" "1.5.5" + "@tauri-apps/cli-linux-x64-gnu" "1.5.5" + "@tauri-apps/cli-linux-x64-musl" "1.5.5" + "@tauri-apps/cli-win32-arm64-msvc" "1.5.5" + "@tauri-apps/cli-win32-ia32-msvc" "1.5.5" + "@tauri-apps/cli-win32-x64-msvc" "1.5.5" + +"@types/json-schema@^7.0.12": + version "7.0.14" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.14.tgz#74a97a5573980802f32c8e47b663530ab3b6b7d1" + integrity sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw== + +"@types/prop-types@*": + version "15.7.9" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.9.tgz#b6f785caa7ea1fe4414d9df42ee0ab67f23d8a6d" + integrity sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g== + +"@types/react-dom@^18.2.7": + version "18.2.14" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.14.tgz#c01ba40e5bb57fc1dc41569bb3ccdb19eab1c539" + integrity sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^18.2.15": + version "18.2.31" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.31.tgz#74ae2630e4aa9af599584157abd3b95d96fb9b40" + integrity sha512-c2UnPv548q+5DFh03y8lEDeMfDwBn9G3dRwfkrxQMo/dOtRHUUO57k6pHvBIfH/VF4Nh+98mZ5aaSe+2echD5g== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.5" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.5.tgz#4751153abbf8d6199babb345a52e1eb4167d64af" + integrity sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw== + +"@types/semver@^7.5.0": + version "7.5.4" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.4.tgz#0a41252ad431c473158b22f9bfb9a63df7541cff" + integrity sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ== + +"@typescript-eslint/eslint-plugin@^6.8.0": + version "6.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz#06abe4265e7c82f20ade2dcc0e3403c32d4f148b" + integrity sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw== + dependencies: + "@eslint-community/regexpp" "^4.5.1" + "@typescript-eslint/scope-manager" "6.8.0" + "@typescript-eslint/type-utils" "6.8.0" + "@typescript-eslint/utils" "6.8.0" + "@typescript-eslint/visitor-keys" "6.8.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.4" + natural-compare "^1.4.0" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/parser@^6.8.0": + version "6.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.8.0.tgz#bb2a969d583db242f1ee64467542f8b05c2e28cb" + integrity sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg== + dependencies: + "@typescript-eslint/scope-manager" "6.8.0" + "@typescript-eslint/types" "6.8.0" + "@typescript-eslint/typescript-estree" "6.8.0" + "@typescript-eslint/visitor-keys" "6.8.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@6.8.0": + version "6.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz#5cac7977385cde068ab30686889dd59879811efd" + integrity sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g== + dependencies: + "@typescript-eslint/types" "6.8.0" + "@typescript-eslint/visitor-keys" "6.8.0" + +"@typescript-eslint/type-utils@6.8.0": + version "6.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz#50365e44918ca0fd159844b5d6ea96789731e11f" + integrity sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g== + dependencies: + "@typescript-eslint/typescript-estree" "6.8.0" + "@typescript-eslint/utils" "6.8.0" + debug "^4.3.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/types@6.8.0": + version "6.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.8.0.tgz#1ab5d4fe1d613e3f65f6684026ade6b94f7e3ded" + integrity sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ== + +"@typescript-eslint/typescript-estree@6.8.0": + version "6.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz#9565f15e0cd12f55cf5aa0dfb130a6cb0d436ba1" + integrity sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg== + dependencies: + "@typescript-eslint/types" "6.8.0" + "@typescript-eslint/visitor-keys" "6.8.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/utils@6.8.0": + version "6.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.8.0.tgz#d42939c2074c6b59844d0982ce26a51d136c4029" + integrity sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "6.8.0" + "@typescript-eslint/types" "6.8.0" + "@typescript-eslint/typescript-estree" "6.8.0" + semver "^7.5.4" + +"@typescript-eslint/visitor-keys@6.8.0": + version "6.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz#cffebed56ae99c45eba901c378a6447b06be58b8" + integrity sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg== + dependencies: + "@typescript-eslint/types" "6.8.0" + eslint-visitor-keys "^3.4.1" + +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + +"@vitejs/plugin-react-swc@^3.3.2": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react-swc/-/plugin-react-swc-3.4.0.tgz#53ca6a07423abadec92f967e188d5ba49b350830" + integrity sha512-m7UaA4Uvz82N/0EOVpZL4XsFIakRqrFKeSNxa1FBLSXGvWrWRBwmZb4qxk+ZIVAZcW3c3dn5YosomDgx62XWcQ== + dependencies: + "@swc/core" "^1.3.85" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.9.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + +array-includes@^3.1.6: + version "3.1.7" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" + integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.flat@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.tosorted@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz#620eff7442503d66c799d95503f82b475745cefd" + integrity sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + get-intrinsic "^1.2.1" + +arraybuffer.prototype.slice@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" + integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + +asynciterator.prototype@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz#8c5df0514936cdd133604dfcc9d3fb93f09b2b62" + integrity sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg== + dependencies: + has-symbols "^1.0.3" + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" + integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== + dependencies: + function-bind "^1.1.2" + get-intrinsic "^1.2.1" + set-function-length "^1.1.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +csstype@^3.0.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" + integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== + +debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +define-data-property@^1.0.1, define-data-property@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" + integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== + dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +es-abstract@^1.22.1: + version "1.22.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" + integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== + dependencies: + array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.2" + available-typed-arrays "^1.0.5" + call-bind "^1.0.5" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.2" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.12" + is-weakref "^1.0.2" + object-inspect "^1.13.1" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.1" + safe-array-concat "^1.0.1" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.8" + string.prototype.trimend "^1.0.7" + string.prototype.trimstart "^1.0.7" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" + typed-array-byte-offset "^1.0.0" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.13" + +es-iterator-helpers@^1.0.12: + version "1.0.15" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz#bd81d275ac766431d19305923707c3efd9f1ae40" + integrity sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g== + dependencies: + asynciterator.prototype "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.1" + es-abstract "^1.22.1" + es-set-tostringtag "^2.0.1" + function-bind "^1.1.1" + get-intrinsic "^1.2.1" + globalthis "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + iterator.prototype "^1.1.2" + safe-array-concat "^1.0.1" + +es-set-tostringtag@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9" + integrity sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q== + dependencies: + get-intrinsic "^1.2.2" + has-tostringtag "^1.0.0" + hasown "^2.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== + dependencies: + hasown "^2.0.0" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +esbuild@^0.18.10: + version "0.18.20" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.20.tgz#4709f5a34801b43b799ab7d6d82f7284a9b7a7a6" + integrity sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA== + optionalDependencies: + "@esbuild/android-arm" "0.18.20" + "@esbuild/android-arm64" "0.18.20" + "@esbuild/android-x64" "0.18.20" + "@esbuild/darwin-arm64" "0.18.20" + "@esbuild/darwin-x64" "0.18.20" + "@esbuild/freebsd-arm64" "0.18.20" + "@esbuild/freebsd-x64" "0.18.20" + "@esbuild/linux-arm" "0.18.20" + "@esbuild/linux-arm64" "0.18.20" + "@esbuild/linux-ia32" "0.18.20" + "@esbuild/linux-loong64" "0.18.20" + "@esbuild/linux-mips64el" "0.18.20" + "@esbuild/linux-ppc64" "0.18.20" + "@esbuild/linux-riscv64" "0.18.20" + "@esbuild/linux-s390x" "0.18.20" + "@esbuild/linux-x64" "0.18.20" + "@esbuild/netbsd-x64" "0.18.20" + "@esbuild/openbsd-x64" "0.18.20" + "@esbuild/sunos-x64" "0.18.20" + "@esbuild/win32-arm64" "0.18.20" + "@esbuild/win32-ia32" "0.18.20" + "@esbuild/win32-x64" "0.18.20" + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-prettier@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz#eb25485946dd0c66cd216a46232dc05451518d1f" + integrity sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw== + +eslint-plugin-react@^7.33.2: + version "7.33.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz#69ee09443ffc583927eafe86ffebb470ee737608" + integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw== + dependencies: + array-includes "^3.1.6" + array.prototype.flatmap "^1.3.1" + array.prototype.tosorted "^1.1.1" + doctrine "^2.1.0" + es-iterator-helpers "^1.0.12" + estraverse "^5.3.0" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.6" + object.fromentries "^2.0.6" + object.hasown "^1.1.2" + object.values "^1.1.6" + prop-types "^15.8.1" + resolve "^2.0.0-next.4" + semver "^6.3.1" + string.prototype.matchall "^4.0.8" + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8.52.0: + version "8.52.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.52.0.tgz#d0cd4a1fac06427a61ef9242b9353f36ea7062fc" + integrity sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.2" + "@eslint/js" "8.52.0" + "@humanwhocodes/config-array" "^0.11.13" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.1.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.1.tgz#a02a15fdec25a8f844ff7cc658f03dd99eb4609b" + integrity sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + +flatted@^3.2.9: + version "3.2.9" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" + integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.1, function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" + integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== + dependencies: + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^13.19.0: + version "13.23.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.23.0.tgz#ef31673c926a0976e1f61dab4dca57e0c0a8af02" + integrity sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA== + dependencies: + type-fest "^0.20.2" + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" + integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== + dependencies: + get-intrinsic "^1.2.2" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" + +ignore@^5.2.0, ignore@^5.2.4: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" + integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg== + dependencies: + get-intrinsic "^1.2.2" + hasown "^2.0.0" + side-channel "^1.0.4" + +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + +is-async-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" + integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== + dependencies: + has-tostringtag "^1.0.0" + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-date-object@^1.0.1, is-date-object@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finalizationregistry@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" + integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== + dependencies: + call-bind "^1.0.2" + +is-generator-function@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-map@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" + integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-set@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" + integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== + dependencies: + which-typed-array "^1.1.11" + +is-weakmap@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" + integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-weakset@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d" + integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +iterator.prototype@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" + integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== + dependencies: + define-properties "^1.2.1" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + reflect.getprototypeof "^1.0.4" + set-function-name "^2.0.1" + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +"jsx-ast-utils@^2.4.1 || ^3.0.0": + version "3.3.5" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== + dependencies: + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + object.assign "^4.1.4" + object.values "^1.1.6" + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +loose-envify@^1.1.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nanoid@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.13.1, object-inspect@^1.9.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.entries@^1.1.6: + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.7.tgz#2b47760e2a2e3a752f39dd874655c61a7f03c131" + integrity sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.fromentries@^2.0.6: + version "2.0.7" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" + integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.hasown@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.3.tgz#6a5f2897bb4d3668b8e79364f98ccf971bda55ae" + integrity sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA== + dependencies: + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.values@^1.1.6: + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +postcss@^8.4.27: + version "8.4.31" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643" + integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg== + +prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +react-dom@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" + integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.0" + +react-is@^16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== + dependencies: + loose-envify "^1.1.0" + +reflect.getprototypeof@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3" + integrity sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + globalthis "^1.0.3" + which-builtin-type "^1.1.3" + +regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" + integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + set-function-name "^2.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^2.0.0-next.4: + version "2.0.0-next.5" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rollup@^3.27.1: + version "3.29.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" + integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw== + optionalDependencies: + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-array-concat@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" + integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + isarray "^2.0.5" + +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + +scheduler@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" + integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== + dependencies: + loose-envify "^1.1.0" + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +set-function-length@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" + integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== + dependencies: + define-data-property "^1.1.1" + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + +set-function-name@^2.0.0, set-function-name@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" + integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== + dependencies: + define-data-property "^1.0.1" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +string.prototype.matchall@^4.0.8: + version "4.0.10" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz#a1553eb532221d4180c51581d6072cd65d1ee100" + integrity sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + regexp.prototype.flags "^1.5.0" + set-function-name "^2.0.0" + side-channel "^1.0.4" + +string.prototype.trim@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" + integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string.prototype.trimend@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" + integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string.prototype.trimstart@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" + integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-api-utils@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" + integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" + integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +typescript@^5.0.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" + integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +vite@^4.4.5: + version "4.5.0" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.0.tgz#ec406295b4167ac3bc23e26f9c8ff559287cff26" + integrity sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw== + dependencies: + esbuild "^0.18.10" + postcss "^8.4.27" + rollup "^3.27.1" + optionalDependencies: + fsevents "~2.3.2" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-builtin-type@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" + integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== + dependencies: + function.prototype.name "^1.1.5" + has-tostringtag "^1.0.0" + is-async-function "^2.0.0" + is-date-object "^1.0.5" + is-finalizationregistry "^1.0.2" + is-generator-function "^1.0.10" + is-regex "^1.1.4" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.1" + which-typed-array "^1.1.9" + +which-collection@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" + integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== + dependencies: + is-map "^2.0.1" + is-set "^2.0.1" + is-weakmap "^2.0.1" + is-weakset "^2.0.1" + +which-typed-array@^1.1.11, which-typed-array@^1.1.13, which-typed-array@^1.1.9: + version "1.1.13" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" + integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.4" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 735751b0d4f1cad3a2ae8ef015feb6aec7bea631 Mon Sep 17 00:00:00 2001 From: pierre Date: Mon, 23 Oct 2023 19:57:48 +0200 Subject: [PATCH 033/236] setup mui and tailwind --- nym-vpn/ui/.eslintignore | 2 + nym-vpn/ui/index.html | 2 +- nym-vpn/ui/package.json | 9 +- nym-vpn/ui/postcss.config.js | 8 + nym-vpn/ui/public/tauri.svg | 6 - nym-vpn/ui/src/App.css | 7 - nym-vpn/ui/src/App.tsx | 42 +- nym-vpn/ui/src/assets/.gitkeep | 0 nym-vpn/ui/src/assets/react.svg | 1 - nym-vpn/ui/src/dev/setup.ts | 2 +- nym-vpn/ui/src/dev/tauri-cmd-mocks/index.ts | 3 +- nym-vpn/ui/src/main.tsx | 2 - nym-vpn/ui/src/styles.css | 112 +- nym-vpn/ui/tailwind.config.js | 10 + nym-vpn/ui/yarn.lock | 1081 ++++++++++++++----- 15 files changed, 876 insertions(+), 411 deletions(-) create mode 100644 nym-vpn/ui/.eslintignore create mode 100644 nym-vpn/ui/postcss.config.js delete mode 100644 nym-vpn/ui/public/tauri.svg delete mode 100644 nym-vpn/ui/src/App.css create mode 100644 nym-vpn/ui/src/assets/.gitkeep delete mode 100644 nym-vpn/ui/src/assets/react.svg create mode 100644 nym-vpn/ui/tailwind.config.js diff --git a/nym-vpn/ui/.eslintignore b/nym-vpn/ui/.eslintignore new file mode 100644 index 0000000000..a2a9c20b8d --- /dev/null +++ b/nym-vpn/ui/.eslintignore @@ -0,0 +1,2 @@ +*.config.js +*.config.ts diff --git a/nym-vpn/ui/index.html b/nym-vpn/ui/index.html index 03abf55f90..4472026329 100644 --- a/nym-vpn/ui/index.html +++ b/nym-vpn/ui/index.html @@ -8,7 +8,7 @@ -
+
diff --git a/nym-vpn/ui/package.json b/nym-vpn/ui/package.json index 72a91ff079..71c59b7e09 100644 --- a/nym-vpn/ui/package.json +++ b/nym-vpn/ui/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "dev": "vite", - "dev:app": "tauri dev", + "dev:app": "WEBKIT_DISABLE_COMPOSITING_MODE=1 tauri dev", "dev:browser": "vite --mode dev-browser", "build": "tsc && vite build", "preview": "vite preview", @@ -17,7 +17,10 @@ "tauri": "tauri" }, "dependencies": { + "@mui/base": "^5.0.0-beta.20", + "@mui/material": "^5.14.14", "@tauri-apps/api": "^1.5.0", + "clsx": "^2.0.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -28,10 +31,14 @@ "@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/parser": "^6.8.0", "@vitejs/plugin-react-swc": "^3.3.2", + "autoprefixer": "^10.4.16", "eslint": "^8.52.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-react": "^7.33.2", + "postcss": "^8.4.31", + "postcss-import": "^15.1.0", "prettier": "^3.0.3", + "tailwindcss": "^3.3.3", "typescript": "^5.0.2", "vite": "^4.4.5" } diff --git a/nym-vpn/ui/postcss.config.js b/nym-vpn/ui/postcss.config.js new file mode 100644 index 0000000000..feab3515aa --- /dev/null +++ b/nym-vpn/ui/postcss.config.js @@ -0,0 +1,8 @@ +export default { + plugins: { + 'postcss-import': {}, + 'tailwindcss/nesting': {}, + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/nym-vpn/ui/public/tauri.svg b/nym-vpn/ui/public/tauri.svg deleted file mode 100644 index 31b62c9280..0000000000 --- a/nym-vpn/ui/public/tauri.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/nym-vpn/ui/src/App.css b/nym-vpn/ui/src/App.css deleted file mode 100644 index a89ebd15df..0000000000 --- a/nym-vpn/ui/src/App.css +++ /dev/null @@ -1,7 +0,0 @@ -.logo.vite:hover { - filter: drop-shadow(0 0 2em #747bff); -} - -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafb); -} diff --git a/nym-vpn/ui/src/App.tsx b/nym-vpn/ui/src/App.tsx index f354586200..27a4fd3126 100644 --- a/nym-vpn/ui/src/App.tsx +++ b/nym-vpn/ui/src/App.tsx @@ -1,7 +1,24 @@ -import { useState } from 'react'; -import reactLogo from './assets/react.svg'; +import React, { useState } from 'react'; import { invoke } from '@tauri-apps/api/tauri'; -import './App.css'; +import { Button as BaseButton, ButtonProps } from '@mui/base/Button'; +import clsx from 'clsx'; + +// eslint-disable-next-line react/display-name +const Button = React.forwardRef( + (props, ref) => { + const { className, ...other } = props; + return ( + + ); + }, +); function App() { const [greetMsg, setGreetMsg] = useState(''); @@ -13,25 +30,10 @@ function App() { } return ( -
+

Welcome to Tauri!

- - -

Click on the Tauri, Vite, and React logos to learn more.

-
{ e.preventDefault(); greet(); @@ -42,7 +44,7 @@ function App() { onChange={(e) => setName(e.currentTarget.value)} placeholder="Enter a name..." /> - +

{greetMsg}

diff --git a/nym-vpn/ui/src/assets/.gitkeep b/nym-vpn/ui/src/assets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nym-vpn/ui/src/assets/react.svg b/nym-vpn/ui/src/assets/react.svg deleted file mode 100644 index 6c87de9bb3..0000000000 --- a/nym-vpn/ui/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/nym-vpn/ui/src/dev/setup.ts b/nym-vpn/ui/src/dev/setup.ts index de8c1ca081..261a6aede9 100644 --- a/nym-vpn/ui/src/dev/setup.ts +++ b/nym-vpn/ui/src/dev/setup.ts @@ -6,6 +6,6 @@ mockWindows('main'); mockIPC(async (cmd, args) => { console.log(`IPC call mocked "${cmd}"`); if (cmd === 'greet') { - return greet(args.name as string) + return greet(args.name as string); } }); diff --git a/nym-vpn/ui/src/dev/tauri-cmd-mocks/index.ts b/nym-vpn/ui/src/dev/tauri-cmd-mocks/index.ts index 0f66f1f84f..72f4e4c640 100644 --- a/nym-vpn/ui/src/dev/tauri-cmd-mocks/index.ts +++ b/nym-vpn/ui/src/dev/tauri-cmd-mocks/index.ts @@ -1,2 +1 @@ -export {default as greet } from './greet'; - +export { default as greet } from './greet'; diff --git a/nym-vpn/ui/src/main.tsx b/nym-vpn/ui/src/main.tsx index 977f2b3fa3..4d42a8e37b 100644 --- a/nym-vpn/ui/src/main.tsx +++ b/nym-vpn/ui/src/main.tsx @@ -3,8 +3,6 @@ import ReactDOM from 'react-dom/client'; import App from './App'; import './styles.css'; -console.log(import.meta.env.MODE); - if (import.meta.env.MODE === 'dev-browser') { console.log('Running in dev-browser mode. Mocking tauri window and IPCs'); import('./dev/setup'); diff --git a/nym-vpn/ui/src/styles.css b/nym-vpn/ui/src/styles.css index f7de85bf06..b5c61c9567 100644 --- a/nym-vpn/ui/src/styles.css +++ b/nym-vpn/ui/src/styles.css @@ -1,109 +1,3 @@ -:root { - font-family: Inter, Avenir, Helvetica, Arial, sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - - color: #0f0f0f; - background-color: #f6f6f6; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -.container { - margin: 0; - padding-top: 10vh; - display: flex; - flex-direction: column; - justify-content: center; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: 0.75s; -} - -.logo.tauri:hover { - filter: drop-shadow(0 0 2em #24c8db); -} - -.row { - display: flex; - justify-content: center; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -h1 { - text-align: center; -} - -input, -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - color: #0f0f0f; - background-color: #ffffff; - transition: border-color 0.25s; - box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); -} - -button { - cursor: pointer; -} - -button:hover { - border-color: #396cd8; -} -button:active { - border-color: #396cd8; - background-color: #e8e8e8; -} - -input, -button { - outline: none; -} - -#greet-input { - margin-right: 5px; -} - -@media (prefers-color-scheme: dark) { - :root { - color: #f6f6f6; - background-color: #2f2f2f; - } - - a:hover { - color: #24c8db; - } - - input, - button { - color: #ffffff; - background-color: #0f0f0f98; - } - button:active { - background-color: #0f0f0f69; - } -} +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/nym-vpn/ui/tailwind.config.js b/nym-vpn/ui/tailwind.config.js new file mode 100644 index 0000000000..a1f67d7f61 --- /dev/null +++ b/nym-vpn/ui/tailwind.config.js @@ -0,0 +1,10 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], + theme: { + extend: {}, + }, + plugins: [], + // Toggling dark mode manually + darkMode: 'class', +}; diff --git a/nym-vpn/ui/yarn.lock b/nym-vpn/ui/yarn.lock index 2f994347d5..dbfa3880ed 100644 --- a/nym-vpn/ui/yarn.lock +++ b/nym-vpn/ui/yarn.lock @@ -4,9 +4,52 @@ "@aashutoshrathi/word-wrap@^1.2.3": version "1.2.6" - resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + resolved "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== +"@alloc/quick-lru@^5.2.0": + version "5.2.0" + resolved "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz" + integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== + +"@babel/runtime@^7.23.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": + version "7.23.2" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz" + integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg== + dependencies: + regenerator-runtime "^0.14.0" + +"@emotion/cache@^11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff" + integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ== + dependencies: + "@emotion/memoize" "^0.8.1" + "@emotion/sheet" "^1.2.2" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + stylis "4.2.0" + +"@emotion/memoize@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" + integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== + +"@emotion/sheet@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec" + integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA== + +"@emotion/utils@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4" + integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg== + +"@emotion/weak-memoize@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" + integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== + "@esbuild/android-arm64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622" @@ -84,7 +127,7 @@ "@esbuild/linux-x64@0.18.20": version "0.18.20" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338" + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz" integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w== "@esbuild/netbsd-x64@0.18.20": @@ -119,19 +162,19 @@ "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== dependencies: eslint-visitor-keys "^3.3.0" "@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": version "4.9.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4" + resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz" integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA== "@eslint/eslintrc@^2.1.2": version "2.1.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz" integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== dependencies: ajv "^6.12.4" @@ -146,12 +189,39 @@ "@eslint/js@8.52.0": version "8.52.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.52.0.tgz#78fe5f117840f69dc4a353adf9b9cd926353378c" + resolved "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz" integrity sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA== +"@floating-ui/core@^1.4.2": + version "1.5.0" + resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.0.tgz" + integrity sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg== + dependencies: + "@floating-ui/utils" "^0.1.3" + +"@floating-ui/dom@^1.5.1": + version "1.5.3" + resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz" + integrity sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA== + dependencies: + "@floating-ui/core" "^1.4.2" + "@floating-ui/utils" "^0.1.3" + +"@floating-ui/react-dom@^2.0.2": + version "2.0.2" + resolved "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.2.tgz" + integrity sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ== + dependencies: + "@floating-ui/dom" "^1.5.1" + +"@floating-ui/utils@^0.1.3": + version "0.1.6" + resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz" + integrity sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A== + "@humanwhocodes/config-array@^0.11.13": version "0.11.13" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" + resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz" integrity sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ== dependencies: "@humanwhocodes/object-schema" "^2.0.1" @@ -160,17 +230,133 @@ "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== "@humanwhocodes/object-schema@^2.0.1": version "2.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" + resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz" integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.1" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.20" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz" + integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@mui/base@5.0.0-beta.20", "@mui/base@^5.0.0-beta.20": + version "5.0.0-beta.20" + resolved "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.20.tgz" + integrity sha512-CS2pUuqxST7ch9VNDCklRYDbJ3rru20Tx7na92QvVVKfu3RL4z/QLuVIc8jYGsdCnauMaeUSlFNLAJNb0yXe6w== + dependencies: + "@babel/runtime" "^7.23.1" + "@floating-ui/react-dom" "^2.0.2" + "@mui/types" "^7.2.6" + "@mui/utils" "^5.14.13" + "@popperjs/core" "^2.11.8" + clsx "^2.0.0" + prop-types "^15.8.1" + +"@mui/core-downloads-tracker@^5.14.14": + version "5.14.14" + resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.14.tgz#a54894e9b4dc908ab2d59eac543219d9018448e6" + integrity sha512-Rw/xKiTOUgXD8hdKqj60aC6QcGprMipG7ne2giK6Mz7b4PlhL/xog9xLeclY3BxsRLkZQ05egFnIEY1CSibTbw== + +"@mui/material@^5.14.14": + version "5.14.14" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.14.14.tgz#e47f3992b609002cd57a71f70e829dc2d286028c" + integrity sha512-cAmCwAHFQXxb44kWbVFkhKATN8tACgMsFwrXo8ro6WzYW73U/qsR5AcCiJIhCyYYg+gcftfkmNcpRaV3JjhHCg== + dependencies: + "@babel/runtime" "^7.23.1" + "@mui/base" "5.0.0-beta.20" + "@mui/core-downloads-tracker" "^5.14.14" + "@mui/system" "^5.14.14" + "@mui/types" "^7.2.6" + "@mui/utils" "^5.14.13" + "@types/react-transition-group" "^4.4.7" + clsx "^2.0.0" + csstype "^3.1.2" + prop-types "^15.8.1" + react-is "^18.2.0" + react-transition-group "^4.4.5" + +"@mui/private-theming@^5.14.14": + version "5.14.14" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.14.14.tgz#035dde1eb30c896c69a12b7dee1dce3a323c66e9" + integrity sha512-n77au3CQj9uu16hak2Y+rvbGSBaJKxziG/gEbOLVGrAuqZ+ycVSkorCfN6Y/4XgYOpG/xvmuiY3JwhAEOzY3iA== + dependencies: + "@babel/runtime" "^7.23.1" + "@mui/utils" "^5.14.13" + prop-types "^15.8.1" + +"@mui/styled-engine@^5.14.13": + version "5.14.14" + resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.14.14.tgz#b0ededf531fff1ef110f7b263c2d3d95a0b8ec9a" + integrity sha512-sF3DS2PVG+cFWvkVHQQaGFpL1h6gSwOW3L91pdxPLQDHDZ5mZ/X0SlXU5XA+WjypoysG4urdAQC7CH/BRvUiqg== + dependencies: + "@babel/runtime" "^7.23.1" + "@emotion/cache" "^11.11.0" + csstype "^3.1.2" + prop-types "^15.8.1" + +"@mui/system@^5.14.14": + version "5.14.14" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.14.14.tgz#f33327e74230523169107ace960e8bb51cbdbab7" + integrity sha512-y4InFmCgGGWXnz+iK4jRTWVikY0HgYnABjz4wgiUgEa2W1H8M4ow+27BegExUWPkj4TWthQ2qG9FOGSMtI+PKA== + dependencies: + "@babel/runtime" "^7.23.1" + "@mui/private-theming" "^5.14.14" + "@mui/styled-engine" "^5.14.13" + "@mui/types" "^7.2.6" + "@mui/utils" "^5.14.13" + clsx "^2.0.0" + csstype "^3.1.2" + prop-types "^15.8.1" + +"@mui/types@^7.2.6": + version "7.2.6" + resolved "https://registry.npmjs.org/@mui/types/-/types-7.2.6.tgz" + integrity sha512-7sjLQrUmBwufm/M7jw/quNiPK/oor2+pGUQP2CULRcFCArYTq78oJ3D5esTaL0UMkXKJvDqXn6Ike69yAOBQng== + +"@mui/utils@^5.14.13": + version "5.14.14" + resolved "https://registry.npmjs.org/@mui/utils/-/utils-5.14.14.tgz" + integrity sha512-3AKp8uksje5sRfVrtgG9Q/2TBsHWVBUtA0NaXliZqGcXo8J+A+Agp0qUW2rJ+ivgPWTCCubz9FZVT2IQZ3bGsw== + dependencies: + "@babel/runtime" "^7.23.1" + "@types/prop-types" "^15.7.7" + prop-types "^15.8.1" + react-is "^18.2.0" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -178,17 +364,22 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@popperjs/core@^2.11.8": + version "2.11.8" + resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz" + integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== + "@swc/core-darwin-arm64@1.3.94": version "1.3.94" resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.94.tgz#2fe8e513433cd5d5c987952e38ca06e6226de0f3" @@ -216,12 +407,12 @@ "@swc/core-linux-x64-gnu@1.3.94": version "1.3.94" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.94.tgz#8d7d4104ba29ce0d7871472c69a7616db2908850" + resolved "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.94.tgz" integrity sha512-gjq7U6clhJi0Oel2a4gwR4MbSu+THQ2hmBNVCOSA3JjPZWZTkJXaJDpnh/r7PJxKBwUDlo0VPlwiwjepAQR2Rw== "@swc/core-linux-x64-musl@1.3.94": version "1.3.94" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.94.tgz#d7180fcff29339b7a2011670a1e1697a2075d13d" + resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.94.tgz" integrity sha512-rSylruWyeol2ujZDHmwiovupMR5ukMXivlA7DDxmQ1dFUV9HuiPknQrU5rEbI3V2V3V5RkpbEKjnADen7AeMPQ== "@swc/core-win32-arm64-msvc@1.3.94": @@ -241,7 +432,7 @@ "@swc/core@^1.3.85": version "1.3.94" - resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.94.tgz#3719cbec7d05e8228fd5b5c7e0dec65ecf2d0422" + resolved "https://registry.npmjs.org/@swc/core/-/core-1.3.94.tgz" integrity sha512-jTHn8UJOGgERKZLy8euEixVAzC/w/rUSuMlM3e7hxgap/TC595hSkuQwtkpL238dsuEPveD44GMy2A5UBtSvjg== dependencies: "@swc/counter" "^0.1.1" @@ -260,17 +451,17 @@ "@swc/counter@^0.1.1": version "0.1.2" - resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.2.tgz#bf06d0770e47c6f1102270b744e17b934586985e" + resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz" integrity sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw== "@swc/types@^0.1.5": version "0.1.5" - resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.5.tgz#043b731d4f56a79b4897a3de1af35e75d56bc63a" + resolved "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz" integrity sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw== "@tauri-apps/api@^1.5.0": version "1.5.1" - resolved "https://registry.yarnpkg.com/@tauri-apps/api/-/api-1.5.1.tgz#9074476c4323f71351db624e9711c99277cdfb99" + resolved "https://registry.npmjs.org/@tauri-apps/api/-/api-1.5.1.tgz" integrity sha512-6unsZDOdlXTmauU3NhWhn+Cx0rODV+rvNvTdvolE5Kls5ybA6cqndQENDt1+FS0tF7ozCP66jwWoH6a5h90BrA== "@tauri-apps/cli-darwin-arm64@1.5.5": @@ -300,12 +491,12 @@ "@tauri-apps/cli-linux-x64-gnu@1.5.5": version "1.5.5" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.5.tgz#f4d2ad6a46ef53d184ea6f3d27815c0b5bbaccd7" + resolved "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.5.tgz" integrity sha512-zZlfklupFaV6RxPze9kQytp1N/K4q/QuYUsgQ5GB/7/OX4EWTUkOpNCeVEocmHag4+9UCQkb1HxdTkXiEVcXEQ== "@tauri-apps/cli-linux-x64-musl@1.5.5": version "1.5.5" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.5.tgz#e59cda396e24915a3307077c27f0c1a061624229" + resolved "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.5.tgz" integrity sha512-2VByWblZnSgLZJyhRxggy528ahcYFH8jboZZ2BUaYT/P5WeJ1lOoQwQj9ssEUrGauGPNS3PmmfBCF7u5oaMRJA== "@tauri-apps/cli-win32-arm64-msvc@1.5.5": @@ -325,7 +516,7 @@ "@tauri-apps/cli@^1.5.0": version "1.5.5" - resolved "https://registry.yarnpkg.com/@tauri-apps/cli/-/cli-1.5.5.tgz#8bcf5fa7694f7bc359a4d1f3b45fed20f938aca9" + resolved "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.5.tgz" integrity sha512-AUFqiA5vbriMd6xWDLWwxzW2FtEhSmL0KcMktkQQGzM+QKFnFbQsubvvd95YDAIX2Q4L1eygGv7ebNX0QVA7sg== optionalDependencies: "@tauri-apps/cli-darwin-arm64" "1.5.5" @@ -341,24 +532,31 @@ "@types/json-schema@^7.0.12": version "7.0.14" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.14.tgz#74a97a5573980802f32c8e47b663530ab3b6b7d1" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz" integrity sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw== -"@types/prop-types@*": +"@types/prop-types@*", "@types/prop-types@^15.7.7": version "15.7.9" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.9.tgz#b6f785caa7ea1fe4414d9df42ee0ab67f23d8a6d" + resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz" integrity sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g== "@types/react-dom@^18.2.7": version "18.2.14" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.14.tgz#c01ba40e5bb57fc1dc41569bb3ccdb19eab1c539" + resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz" integrity sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ== dependencies: "@types/react" "*" +"@types/react-transition-group@^4.4.7": + version "4.4.8" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.8.tgz#46f87d80512959cac793ecc610a93d80ef241ccf" + integrity sha512-QmQ22q+Pb+HQSn04NL3HtrqHwYMf4h3QKArOy5F8U5nEVMaihBs3SR10WiOM1iwPz5jIo8x/u11al+iEGZZrvg== + dependencies: + "@types/react" "*" + "@types/react@*", "@types/react@^18.2.15": version "18.2.31" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.31.tgz#74ae2630e4aa9af599584157abd3b95d96fb9b40" + resolved "https://registry.npmjs.org/@types/react/-/react-18.2.31.tgz" integrity sha512-c2UnPv548q+5DFh03y8lEDeMfDwBn9G3dRwfkrxQMo/dOtRHUUO57k6pHvBIfH/VF4Nh+98mZ5aaSe+2echD5g== dependencies: "@types/prop-types" "*" @@ -367,17 +565,17 @@ "@types/scheduler@*": version "0.16.5" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.5.tgz#4751153abbf8d6199babb345a52e1eb4167d64af" + resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz" integrity sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw== "@types/semver@^7.5.0": version "7.5.4" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.4.tgz#0a41252ad431c473158b22f9bfb9a63df7541cff" + resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz" integrity sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ== "@typescript-eslint/eslint-plugin@^6.8.0": version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz#06abe4265e7c82f20ade2dcc0e3403c32d4f148b" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz" integrity sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw== dependencies: "@eslint-community/regexpp" "^4.5.1" @@ -394,7 +592,7 @@ "@typescript-eslint/parser@^6.8.0": version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.8.0.tgz#bb2a969d583db242f1ee64467542f8b05c2e28cb" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz" integrity sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg== dependencies: "@typescript-eslint/scope-manager" "6.8.0" @@ -405,7 +603,7 @@ "@typescript-eslint/scope-manager@6.8.0": version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz#5cac7977385cde068ab30686889dd59879811efd" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz" integrity sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g== dependencies: "@typescript-eslint/types" "6.8.0" @@ -413,7 +611,7 @@ "@typescript-eslint/type-utils@6.8.0": version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz#50365e44918ca0fd159844b5d6ea96789731e11f" + resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz" integrity sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g== dependencies: "@typescript-eslint/typescript-estree" "6.8.0" @@ -423,12 +621,12 @@ "@typescript-eslint/types@6.8.0": version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.8.0.tgz#1ab5d4fe1d613e3f65f6684026ade6b94f7e3ded" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz" integrity sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ== "@typescript-eslint/typescript-estree@6.8.0": version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz#9565f15e0cd12f55cf5aa0dfb130a6cb0d436ba1" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz" integrity sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg== dependencies: "@typescript-eslint/types" "6.8.0" @@ -441,7 +639,7 @@ "@typescript-eslint/utils@6.8.0": version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.8.0.tgz#d42939c2074c6b59844d0982ce26a51d136c4029" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz" integrity sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q== dependencies: "@eslint-community/eslint-utils" "^4.4.0" @@ -454,7 +652,7 @@ "@typescript-eslint/visitor-keys@6.8.0": version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz#cffebed56ae99c45eba901c378a6447b06be58b8" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz" integrity sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg== dependencies: "@typescript-eslint/types" "6.8.0" @@ -462,29 +660,29 @@ "@ungap/structured-clone@^1.2.0": version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== "@vitejs/plugin-react-swc@^3.3.2": version "3.4.0" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-react-swc/-/plugin-react-swc-3.4.0.tgz#53ca6a07423abadec92f967e188d5ba49b350830" + resolved "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.4.0.tgz" integrity sha512-m7UaA4Uvz82N/0EOVpZL4XsFIakRqrFKeSNxa1FBLSXGvWrWRBwmZb4qxk+ZIVAZcW3c3dn5YosomDgx62XWcQ== dependencies: "@swc/core" "^1.3.85" acorn-jsx@^5.3.2: version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn@^8.9.0: version "8.10.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== ajv@^6.12.4: version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -494,24 +692,42 @@ ajv@^6.12.4: ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== + argparse@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== array-buffer-byte-length@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + resolved "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz" integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== dependencies: call-bind "^1.0.2" @@ -519,7 +735,7 @@ array-buffer-byte-length@^1.0.0: array-includes@^3.1.6: version "3.1.7" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" + resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz" integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== dependencies: call-bind "^1.0.2" @@ -530,12 +746,12 @@ array-includes@^3.1.6: array-union@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== array.prototype.flat@^1.3.1: version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + resolved "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz" integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== dependencies: call-bind "^1.0.2" @@ -545,7 +761,7 @@ array.prototype.flat@^1.3.1: array.prototype.flatmap@^1.3.1: version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + resolved "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz" integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== dependencies: call-bind "^1.0.2" @@ -555,7 +771,7 @@ array.prototype.flatmap@^1.3.1: array.prototype.tosorted@^1.1.1: version "1.1.2" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz#620eff7442503d66c799d95503f82b475745cefd" + resolved "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz" integrity sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg== dependencies: call-bind "^1.0.2" @@ -566,7 +782,7 @@ array.prototype.tosorted@^1.1.1: arraybuffer.prototype.slice@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" + resolved "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz" integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== dependencies: array-buffer-byte-length "^1.0.0" @@ -579,39 +795,66 @@ arraybuffer.prototype.slice@^1.0.2: asynciterator.prototype@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz#8c5df0514936cdd133604dfcc9d3fb93f09b2b62" + resolved "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz" integrity sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg== dependencies: has-symbols "^1.0.3" +autoprefixer@^10.4.16: + version "10.4.16" + resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz" + integrity sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ== + dependencies: + browserslist "^4.21.10" + caniuse-lite "^1.0.30001538" + fraction.js "^4.3.6" + normalize-range "^0.1.2" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" + available-typed-arrays@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" +browserslist@^4.21.10: + version "4.22.1" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz" + integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ== + dependencies: + caniuse-lite "^1.0.30001541" + electron-to-chromium "^1.4.535" + node-releases "^2.0.13" + update-browserslist-db "^1.0.13" + call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz" integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== dependencies: function-bind "^1.1.2" @@ -620,63 +863,103 @@ call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: callsites@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +caniuse-lite@^1.0.30001538, caniuse-lite@^1.0.30001541: + version "1.0.30001553" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001553.tgz" + integrity sha512-N0ttd6TrFfuqKNi+pMgWJTb9qrdJu4JSpgPFLe/lrD19ugC6fZgF0pUewRowDwzdDnb9V41mFcdlYgl/PyKf4A== + chalk@^4.0.0: version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" +chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +clsx@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b" + integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q== + color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@~1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +commander@^4.0.0: + version "4.1.1" + resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== cross-spawn@^7.0.2: version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" which "^2.0.1" -csstype@^3.0.2: +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +csstype@^3.0.2, csstype@^3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" + resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz" integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" deep-is@^0.1.3: version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== define-data-property@^1.0.1, define-data-property@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" + resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz" integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== dependencies: get-intrinsic "^1.2.1" @@ -685,37 +968,60 @@ define-data-property@^1.0.1, define-data-property@^1.1.1: define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, define-properties@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== dependencies: define-data-property "^1.0.1" has-property-descriptors "^1.0.0" object-keys "^1.1.1" +didyoumean@^1.2.2: + version "1.2.2" + resolved "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz" + integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== + dir-glob@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: path-type "^4.0.0" +dlv@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz" + integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== + doctrine@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz" integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" doctrine@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" +dom-helpers@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + +electron-to-chromium@^1.4.535: + version "1.4.563" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.563.tgz" + integrity sha512-dg5gj5qOgfZNkPNeyKBZQAQitIQ/xwfIDmEQJHCbXaD9ebTZxwJXUsDYcBlAvZGZLi+/354l35J1wkmP6CqYaw== + es-abstract@^1.22.1: version "1.22.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz" integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== dependencies: array-buffer-byte-length "^1.0.0" @@ -760,7 +1066,7 @@ es-abstract@^1.22.1: es-iterator-helpers@^1.0.12: version "1.0.15" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz#bd81d275ac766431d19305923707c3efd9f1ae40" + resolved "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz" integrity sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g== dependencies: asynciterator.prototype "^1.0.0" @@ -780,7 +1086,7 @@ es-iterator-helpers@^1.0.12: es-set-tostringtag@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9" + resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz" integrity sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q== dependencies: get-intrinsic "^1.2.2" @@ -789,14 +1095,14 @@ es-set-tostringtag@^2.0.1: es-shim-unscopables@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + resolved "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz" integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== dependencies: hasown "^2.0.0" es-to-primitive@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" @@ -805,7 +1111,7 @@ es-to-primitive@^1.2.1: esbuild@^0.18.10: version "0.18.20" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.20.tgz#4709f5a34801b43b799ab7d6d82f7284a9b7a7a6" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz" integrity sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA== optionalDependencies: "@esbuild/android-arm" "0.18.20" @@ -831,19 +1137,24 @@ esbuild@^0.18.10: "@esbuild/win32-ia32" "0.18.20" "@esbuild/win32-x64" "0.18.20" +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + escape-string-regexp@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== eslint-config-prettier@^9.0.0: version "9.0.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz#eb25485946dd0c66cd216a46232dc05451518d1f" + resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz" integrity sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw== eslint-plugin-react@^7.33.2: version "7.33.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz#69ee09443ffc583927eafe86ffebb470ee737608" + resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz" integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw== dependencies: array-includes "^3.1.6" @@ -865,7 +1176,7 @@ eslint-plugin-react@^7.33.2: eslint-scope@^7.2.2: version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz" integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: esrecurse "^4.3.0" @@ -873,12 +1184,12 @@ eslint-scope@^7.2.2: eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint@^8.52.0: version "8.52.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.52.0.tgz#d0cd4a1fac06427a61ef9242b9353f36ea7062fc" + resolved "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz" integrity sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg== dependencies: "@eslint-community/eslint-utils" "^4.2.0" @@ -922,7 +1233,7 @@ eslint@^8.52.0: espree@^9.6.0, espree@^9.6.1: version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz" integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: acorn "^8.9.0" @@ -931,36 +1242,36 @@ espree@^9.6.0, espree@^9.6.1: esquery@^1.4.2: version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: estraverse "^5.1.0" esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.9: +fast-glob@^3.2.12, fast-glob@^3.2.9: version "3.3.1" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: "@nodelib/fs.stat" "^2.0.2" @@ -971,38 +1282,38 @@ fast-glob@^3.2.9: fast-json-stable-stringify@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.6.0: version "1.15.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz" integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== dependencies: reusify "^1.0.4" file-entry-cache@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: flat-cache "^3.0.4" fill-range@^7.0.1: version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: to-regex-range "^5.0.1" find-up@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: locate-path "^6.0.0" @@ -1010,7 +1321,7 @@ find-up@^5.0.0: flat-cache@^3.0.4: version "3.1.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.1.tgz#a02a15fdec25a8f844ff7cc658f03dd99eb4609b" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz" integrity sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q== dependencies: flatted "^3.2.9" @@ -1019,19 +1330,24 @@ flat-cache@^3.0.4: flatted@^3.2.9: version "3.2.9" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz" integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== for-each@^0.3.3: version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" +fraction.js@^4.3.6: + version "4.3.7" + resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz" + integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== + fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: @@ -1041,12 +1357,12 @@ fsevents@~2.3.2: function-bind@^1.1.1, function-bind@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz" integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== dependencies: call-bind "^1.0.2" @@ -1056,12 +1372,12 @@ function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: functions-have-names@^1.2.3: version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: version "1.2.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz" integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== dependencies: function-bind "^1.1.2" @@ -1071,29 +1387,41 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@ get-symbol-description@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz" integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== dependencies: call-bind "^1.0.2" get-intrinsic "^1.1.1" -glob-parent@^5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob-parent@^6.0.2: version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== dependencies: is-glob "^4.0.3" +glob@7.1.6: + version "7.1.6" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.1.3: version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -1105,21 +1433,21 @@ glob@^7.1.3: globals@^13.19.0: version "13.23.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.23.0.tgz#ef31673c926a0976e1f61dab4dca57e0c0a8af02" + resolved "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz" integrity sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA== dependencies: type-fest "^0.20.2" globalthis@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz" integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== dependencies: define-properties "^1.1.3" globby@^11.1.0: version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" @@ -1131,65 +1459,65 @@ globby@^11.1.0: gopd@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz" integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== dependencies: get-intrinsic "^1.1.3" graphemer@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-property-descriptors@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz" integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== dependencies: get-intrinsic "^1.2.2" has-proto@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz" integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-tostringtag@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== dependencies: has-symbols "^1.0.2" hasown@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz" integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== dependencies: function-bind "^1.1.2" ignore@^5.2.0, ignore@^5.2.4: version "5.2.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== import-fresh@^3.2.1: version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" @@ -1197,12 +1525,12 @@ import-fresh@^3.2.1: imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -1210,12 +1538,12 @@ inflight@^1.0.4: inherits@2: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== internal-slot@^1.0.5: version "1.0.6" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" + resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz" integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg== dependencies: get-intrinsic "^1.2.2" @@ -1224,7 +1552,7 @@ internal-slot@^1.0.5: is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz" integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== dependencies: call-bind "^1.0.2" @@ -1233,21 +1561,28 @@ is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: is-async-function@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" + resolved "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz" integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== dependencies: has-tostringtag "^1.0.0" is-bigint@^1.0.1: version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== dependencies: has-bigints "^1.0.1" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-boolean-object@^1.1.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz" integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== dependencies: call-bind "^1.0.2" @@ -1255,79 +1590,79 @@ is-boolean-object@^1.1.0: is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== is-core-module@^2.13.0: version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz" integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== dependencies: hasown "^2.0.0" is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== dependencies: has-tostringtag "^1.0.0" is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-finalizationregistry@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" + resolved "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz" integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== dependencies: call-bind "^1.0.2" is-generator-function@^1.0.10: version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz" integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== dependencies: has-tostringtag "^1.0.0" -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-map@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" + resolved "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz" integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== is-negative-zero@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== is-number-object@^1.0.4: version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz" integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== dependencies: has-tostringtag "^1.0.0" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-path-inside@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== is-regex@^1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== dependencies: call-bind "^1.0.2" @@ -1335,52 +1670,52 @@ is-regex@^1.1.4: is-set@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" + resolved "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz" integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== is-shared-array-buffer@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz" integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== dependencies: call-bind "^1.0.2" is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== dependencies: has-tostringtag "^1.0.0" is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz" integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== dependencies: has-symbols "^1.0.2" is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: version "1.1.12" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz" integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== dependencies: which-typed-array "^1.1.11" is-weakmap@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" + resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz" integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== is-weakref@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz" integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== dependencies: call-bind "^1.0.2" is-weakset@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d" + resolved "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz" integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg== dependencies: call-bind "^1.0.2" @@ -1388,17 +1723,17 @@ is-weakset@^2.0.1: isarray@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== isexe@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== iterator.prototype@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" + resolved "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz" integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== dependencies: define-properties "^1.2.1" @@ -1407,36 +1742,41 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" +jiti@^1.18.2: + version "1.20.0" + resolved "https://registry.npmjs.org/jiti/-/jiti-1.20.0.tgz" + integrity sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA== + "js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" json-buffer@3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== "jsx-ast-utils@^2.4.1 || ^3.0.0": version "3.3.5" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz" integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== dependencies: array-includes "^3.1.6" @@ -1446,98 +1786,137 @@ json-stable-stringify-without-jsonify@^1.0.1: keyv@^4.5.3: version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== dependencies: json-buffer "3.0.1" levn@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: prelude-ls "^1.2.1" type-check "~0.4.0" +lilconfig@^2.0.5, lilconfig@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + locate-path@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: p-locate "^5.0.0" lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^4.0.4: +micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: braces "^3.0.2" picomatch "^2.3.1" -minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" ms@2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + nanoid@^3.3.6: version "3.3.6" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz" integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -object-assign@^4.1.1: +node-releases@^2.0.13: + version "2.0.13" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz" + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz" + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== + +object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + object-inspect@^1.13.1, object-inspect@^1.9.0: version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object.assign@^4.1.4: version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz" integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: call-bind "^1.0.2" @@ -1547,7 +1926,7 @@ object.assign@^4.1.4: object.entries@^1.1.6: version "1.1.7" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.7.tgz#2b47760e2a2e3a752f39dd874655c61a7f03c131" + resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz" integrity sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA== dependencies: call-bind "^1.0.2" @@ -1556,7 +1935,7 @@ object.entries@^1.1.6: object.fromentries@^2.0.6: version "2.0.7" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" + resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz" integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== dependencies: call-bind "^1.0.2" @@ -1565,7 +1944,7 @@ object.fromentries@^2.0.6: object.hasown@^1.1.2: version "1.1.3" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.3.tgz#6a5f2897bb4d3668b8e79364f98ccf971bda55ae" + resolved "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz" integrity sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA== dependencies: define-properties "^1.2.0" @@ -1573,7 +1952,7 @@ object.hasown@^1.1.2: object.values@^1.1.6: version "1.1.7" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" + resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz" integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== dependencies: call-bind "^1.0.2" @@ -1582,14 +1961,14 @@ object.values@^1.1.6: once@^1.3.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" optionator@^0.9.3: version "0.9.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz" integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== dependencies: "@aashutoshrathi/word-wrap" "^1.2.3" @@ -1601,63 +1980,117 @@ optionator@^0.9.3: p-limit@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" p-locate@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== dependencies: p-limit "^3.0.2" parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-type@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== picocolors@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -postcss@^8.4.27: +pify@^2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pirates@^4.0.1: + version "4.0.6" + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +postcss-import@^15.1.0: + version "15.1.0" + resolved "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz" + integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew== + dependencies: + postcss-value-parser "^4.0.0" + read-cache "^1.0.0" + resolve "^1.1.7" + +postcss-js@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz" + integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw== + dependencies: + camelcase-css "^2.0.1" + +postcss-load-config@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz" + integrity sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA== + dependencies: + lilconfig "^2.0.5" + yaml "^2.1.1" + +postcss-nested@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz" + integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ== + dependencies: + postcss-selector-parser "^6.0.11" + +postcss-selector-parser@^6.0.11: + version "6.0.13" + resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz" + integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.4.23, postcss@^8.4.27, postcss@^8.4.31: version "8.4.31" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz" integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== dependencies: nanoid "^3.3.6" @@ -1666,17 +2099,17 @@ postcss@^8.4.27: prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prettier@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643" + resolved "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz" integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg== -prop-types@^15.8.1: +prop-types@^15.6.2, prop-types@^15.8.1: version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== dependencies: loose-envify "^1.4.0" @@ -1685,17 +2118,17 @@ prop-types@^15.8.1: punycode@^2.1.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== react-dom@^18.2.0: version "18.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" + resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz" integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== dependencies: loose-envify "^1.1.0" @@ -1703,19 +2136,48 @@ react-dom@^18.2.0: react-is@^16.13.1: version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^18.2.0: + version "18.2.0" + resolved "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +react-transition-group@^4.4.5: + version "4.4.5" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" + integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + react@^18.2.0: version "18.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz" integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== dependencies: loose-envify "^1.1.0" +read-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz" + integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== + dependencies: + pify "^2.3.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + reflect.getprototypeof@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3" + resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz" integrity sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw== dependencies: call-bind "^1.0.2" @@ -1725,9 +2187,14 @@ reflect.getprototypeof@^1.0.4: globalthis "^1.0.3" which-builtin-type "^1.1.3" +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: version "1.5.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" + resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz" integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== dependencies: call-bind "^1.0.2" @@ -1736,12 +2203,21 @@ regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve@^1.1.7, resolve@^1.22.2: + version "1.22.8" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^2.0.0-next.4: version "2.0.0-next.5" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz" integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== dependencies: is-core-module "^2.13.0" @@ -1750,33 +2226,33 @@ resolve@^2.0.0-next.4: reusify@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" rollup@^3.27.1: version "3.29.4" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" + resolved "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz" integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw== optionalDependencies: fsevents "~2.3.2" run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" safe-array-concat@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" + resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz" integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== dependencies: call-bind "^1.0.2" @@ -1786,7 +2262,7 @@ safe-array-concat@^1.0.1: safe-regex-test@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz" integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== dependencies: call-bind "^1.0.2" @@ -1795,26 +2271,26 @@ safe-regex-test@^1.0.0: scheduler@^0.23.0: version "0.23.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" + resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz" integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== dependencies: loose-envify "^1.1.0" semver@^6.3.1: version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.5.4: version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" set-function-length@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" + resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz" integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== dependencies: define-data-property "^1.1.1" @@ -1824,7 +2300,7 @@ set-function-length@^1.1.1: set-function-name@^2.0.0, set-function-name@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" + resolved "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz" integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== dependencies: define-data-property "^1.0.1" @@ -1833,19 +2309,19 @@ set-function-name@^2.0.0, set-function-name@^2.0.1: shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== side-channel@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== dependencies: call-bind "^1.0.0" @@ -1854,17 +2330,17 @@ side-channel@^1.0.4: slash@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== source-map-js@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== string.prototype.matchall@^4.0.8: version "4.0.10" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz#a1553eb532221d4180c51581d6072cd65d1ee100" + resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz" integrity sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ== dependencies: call-bind "^1.0.2" @@ -1879,7 +2355,7 @@ string.prototype.matchall@^4.0.8: string.prototype.trim@^1.2.8: version "1.2.8" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" + resolved "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz" integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== dependencies: call-bind "^1.0.2" @@ -1888,7 +2364,7 @@ string.prototype.trim@^1.2.8: string.prototype.trimend@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz" integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== dependencies: call-bind "^1.0.2" @@ -1897,7 +2373,7 @@ string.prototype.trimend@^1.0.7: string.prototype.trimstart@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz" integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== dependencies: call-bind "^1.0.2" @@ -1906,60 +2382,125 @@ string.prototype.trimstart@^1.0.7: strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" strip-json-comments@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +stylis@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" + integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== + +sucrase@^3.32.0: + version "3.34.0" + resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz" + integrity sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + glob "7.1.6" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + ts-interface-checker "^0.1.9" + supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +tailwindcss@^3.3.3: + version "3.3.3" + resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz" + integrity sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w== + dependencies: + "@alloc/quick-lru" "^5.2.0" + arg "^5.0.2" + chokidar "^3.5.3" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.2.12" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.18.2" + lilconfig "^2.1.0" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.0.0" + postcss "^8.4.23" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.1" + postcss-nested "^6.0.1" + postcss-selector-parser "^6.0.11" + resolve "^1.22.2" + sucrase "^3.32.0" + text-table@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" ts-api-utils@^1.0.1: version "1.0.3" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" + resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz" integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: prelude-ls "^1.2.1" type-fest@^0.20.2: version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== typed-array-buffer@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz" integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== dependencies: call-bind "^1.0.2" @@ -1968,7 +2509,7 @@ typed-array-buffer@^1.0.0: typed-array-byte-length@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + resolved "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz" integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== dependencies: call-bind "^1.0.2" @@ -1978,7 +2519,7 @@ typed-array-byte-length@^1.0.0: typed-array-byte-offset@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" + resolved "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz" integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== dependencies: available-typed-arrays "^1.0.5" @@ -1989,7 +2530,7 @@ typed-array-byte-offset@^1.0.0: typed-array-length@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz" integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== dependencies: call-bind "^1.0.2" @@ -1998,12 +2539,12 @@ typed-array-length@^1.0.4: typescript@^5.0.2: version "5.2.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz" integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== unbox-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz" integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== dependencies: call-bind "^1.0.2" @@ -2011,16 +2552,29 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + vite@^4.4.5: version "4.5.0" - resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.0.tgz#ec406295b4167ac3bc23e26f9c8ff559287cff26" + resolved "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz" integrity sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw== dependencies: esbuild "^0.18.10" @@ -2031,7 +2585,7 @@ vite@^4.4.5: which-boxed-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== dependencies: is-bigint "^1.0.1" @@ -2042,7 +2596,7 @@ which-boxed-primitive@^1.0.2: which-builtin-type@^1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" + resolved "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz" integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== dependencies: function.prototype.name "^1.1.5" @@ -2060,7 +2614,7 @@ which-builtin-type@^1.1.3: which-collection@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" + resolved "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz" integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== dependencies: is-map "^2.0.1" @@ -2070,7 +2624,7 @@ which-collection@^1.0.1: which-typed-array@^1.1.11, which-typed-array@^1.1.13, which-typed-array@^1.1.9: version "1.1.13" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz" integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== dependencies: available-typed-arrays "^1.0.5" @@ -2081,22 +2635,27 @@ which-typed-array@^1.1.11, which-typed-array@^1.1.13, which-typed-array@^1.1.9: which@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== yallist@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^2.1.1: + version "2.3.3" + resolved "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz" + integrity sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ== + yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From a0e39789276196447a12db6ceb5897f8b62923d2 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 08:15:04 +0200 Subject: [PATCH 034/236] add legal forum to faq --- documentation/operators/src/faq/smoosh-faq.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index b9683dc7d3..ae0f763464 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -74,9 +74,7 @@ From an operator standpoint, it shall just be a standard Nym upgrade, a new opti ### Are there any legal concerns for the operators? -So far the general line is running a gateway is not illegal (unless you are in Iran, China, and a few other places) and due to encryption/mixing less risky than running a normal VPN node. For mix nodes, its very safe as they have no idea what packets they are mixing. +So far the general line is running a gateway is not illegal (unless you are in Iran, China, and a few other places) and due to encryption/mixing less risky than running a normal VPN node. For mix nodes, its very safe as they have "no idea" what packets they are mixing. -There are several legal questions regarding to this and we would like to ask you to fill this [short survey](https://nymtech.typeform.com/exitnode). - -We'll have a thorough legal analysis out before hand and various resources from and for the community. +There are several legal questions regarding to this and analysis to be made for different jurisdictions. To be able to share resources and findings between the operators themselves we created a [Community Legal Forum](../legal/exit-gateway.md). From 6bff864444f21925959159e0c27780403426a498 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 08:24:40 +0200 Subject: [PATCH 035/236] add how to make legal PR --- documentation/operators/src/legal/exit-gateway.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index fb73e7f8f0..e011cc01e3 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -202,4 +202,11 @@ git add .md git commit -am "" git push origin operators/legal-forum/ ``` -7. Notify others in the [Node Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) (Matrix chat) +7. Open the git generated link in your browser, fill the description and click on `Create a Pull Request` button +```sh +# The link will look like this + https://github.com/nymtech/nym/pull/new/ +``` +8. Notify others in the [Node Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) (Matrix chat) + + From b5ca5b4417de002f274daf30f76655ae76903464 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 09:11:17 +0200 Subject: [PATCH 036/236] add exit gateway options --- .../operators/src/nodes/gateway-setup.md | 78 ++++++++++++++++++- .../operators/src/nodes/maintenance.md | 10 +-- 2 files changed, 76 insertions(+), 12 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 5a880c4ece..76412d55c4 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -9,6 +9,8 @@ ``` +As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` function which can be turned on or off byt the operator, to set the gateway as an exit node. More info on these changes [below](). + ## Preliminary steps Make sure you do the preparation listed in the [preliminary steps page](../preliminary-steps.md) before setting up your gateway. @@ -56,22 +58,90 @@ To check available configuration options use: ``` ~~~ -The following command returns a gateway on your current IP with the `id` of `supergateway`: +The following command returns a gateway on your current IP with the `` of `supergateway`: ``` -./nym-gateway init --id supergateway --host $(curl ifconfig.me) --wallet-address n1eufxdlgt0puwrwptgjfqne8pj4nhy2u5ft62uq +./nym-gateway init --id supergateway --host $(curl ifconfig.me) ``` ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ The `$(curl ifconfig.me)` command above returns your IP automatically using an external service. Alternatively, you can enter your IP manually if you wish. If you do this, remember to enter your IP **without** any port information. + +#### Initialising gateway with network requester + +As some of the [Project Smoosh](../faq/smoosh-faq.md) changes getting implemented, the gateways now can work also as a network requesters at the same time. Such combination creates an exit gateway node, needed for new more open setup. + +An operator can initialise the gateway and network requester together by running: + +``` +./nym-gateway init --id --host $(curl ifconfig.me) --with-network-requester +``` + +If we follow the previous example with `` chosen `supergateway`, adding the `--with-network-requester` flag, the outcome will be: + + +~~~admonish example collapsible=true title="Console output" +``` + +``` +~~~ + +You can see that the printed information besides identity and sphinx keys also includes a long string called address. This is the addressto be provided to your local [socks5 client](https://nymtech.net/docs/clients/socks5-client.html) as a `--provider` if you wish to connect to your own exit gateway. + +#### Add network requester to existing gateway + +If you already have a gateway and got it [upgraded](./maintenance.md#upgrading-your-node) to the [newest version](./gateway-setup.md#current-version), you can easily add a network requester by stopping your gateway and running a command `setup-network-requester`. + +See the options: + +``` +./nym-gateway setup-network-requester --help +``` + +~~~admonish example collapsible=true title="Console output" +``` + +``` +~~~ + +Run with `--enabled true` flag (using same placeholders like above): + +``` +./nym-gateway setup-network-requester --enabled true --id supergateway --host $(curl ifconfig.me) +``` + +~~~admonish example collapsible=true title="Console output" +``` + +``` +~~~ + +In case there are any problems, you can also change it manually by editing the gateway config stored in `/home/user/.nym/gateways//config/config.toml` where the line under `[network_requester]` needs to be edited from `false` to `true`, it shall look like this: + +``` +[network_requester] +# Specifies whether network requester service is enabled in this process. +enabled = true +``` + +Save, exit and restart your gateway. + +All information about your network requester connected to your gateway is in `/home/user/.nym/gateways/snus/config/network_requester_config.toml`. + +```admonish info +Before you bond and run your gateway, please make sure the [firewall configuration](./maintenance.md#configure-your-firewall) is setup so your gateway can be reached from the outside. +``` + ### Bonding your gateway + #### Via the Desktop wallet + You can bond your gateway via the Desktop wallet. 1. Open your wallet, and head to the `Bonding` page, then select the node type `Gateway` and input your node details (Location format is , ). Press `Next` @@ -81,7 +151,7 @@ You can bond your gateway via the Desktop wallet. 3. You will be asked to run a the `sign` command with your `gateway` - copy and paste the long signature as the value of `--contract-msg` and run it. ``` -./nym-mixnode sign --id --contract-msg +./nym-gatewway sign --id --contract-msg ``` It will look something like this: diff --git a/documentation/operators/src/nodes/maintenance.md b/documentation/operators/src/nodes/maintenance.md index e29b80eb25..03bb33a0f3 100644 --- a/documentation/operators/src/nodes/maintenance.md +++ b/documentation/operators/src/nodes/maintenance.md @@ -152,14 +152,8 @@ sudo ufw status Finally open your `` p2p port, as well as ports for ssh and ports for verloc and measurement pings: ```sh -# for mix node -sudo ufw allow 1789,1790,8000,22/tcp - -# for gateway -sudo ufw allow 1789,22,9000/tcp - -# for network requester -sudo ufw allow 22,9000/tcp +# for mix node, gateway and network requester +sudo ufw allow 1789,1790,8000,9000,22/tcp # for validator sudo ufw allow 1317,26656,26660,22,80,443/tcp From c41872d5a412bb480fb3415e66bf5ccf07dced69 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 09:15:34 +0200 Subject: [PATCH 037/236] finish gateway doc updates --- documentation/operators/src/nodes/gateway-setup.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 76412d55c4..3861af8e7b 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -144,7 +144,7 @@ Before you bond and run your gateway, please make sure the [firewall configurati You can bond your gateway via the Desktop wallet. -1. Open your wallet, and head to the `Bonding` page, then select the node type `Gateway` and input your node details (Location format is , ). Press `Next` +1. Open your wallet, and head to the `Bonding` page, then select the node type `Gateway` and input your node details. Press `Next` 2. Enter the `Amount`, `Operating cost` and press `Next`. @@ -158,7 +158,7 @@ It will look something like this: ~~~admonish example collapsible=true title="Console output" ``` -./nym-gateway sign --id upgrade_test --contract-msg 2Mf8xYytgEeyJke9LA7TjhHoGQWNBEfgHZtTyy2krFJfGHSiqy7FLgTnauSkQepCZTqKN5Yfi34JQCuog9k6FGA2EjsdpNGAWHZiuUGDipyJ6UksNKRxnFKhYW7ri4MRduyZwbR98y5fQMLAwHne1Tjm9cXYCn8McfigNt77WAYwBk5bRRKmC34BJMmWcAxphcLES2v9RdSR68tkHSpy2C8STfdmAQs3tZg8bJS5Qa8pQdqx14TnfQAPLk3QYCynfUJvgcQTrg29aqCasceGRpKdQ3Tbn81MLXAGAs7JLBbiMEAhCezAr2kEN8kET1q54zXtKz6znTPgeTZoSbP8rzf4k2JKHZYWrHYF9JriXepuZTnyxAKAxvGFPBk8Z6KAQi33NRQkwd7MPyttatHna6kG9x7knffV6ebGzgRBf7NV27LurH8x4L1uUXwm1v1UYCA1WSBQ9Pp2JW69k5v5v7G9gBy8RUcZnMbeL26Qqb8WkuGcmuHhaFfoqSfV7PRHPpPT4M8uRqUyR4bjUtSJJM1yh6QSeZk9BEazzoJqPeYeGoiFDZ3LMj2jesbJweQR4caaYuRczK92UGSSqu9zBKmE45a +./nym-gateway sign --id supergateway --contract-msg 2Mf8xYytgEeyJke9LA7TjhHoGQWNBEfgHZtTyy2krFJfGHSiqy7FLgTnauSkQepCZTqKN5Yfi34JQCuog9k6FGA2EjsdpNGAWHZiuUGDipyJ6UksNKRxnFKhYW7ri4MRduyZwbR98y5fQMLAwHne1Tjm9cXYCn8McfigNt77WAYwBk5bRRKmC34BJMmWcAxphcLES2v9RdSR68tkHSpy2C8STfdmAQs3tZg8bJS5Qa8pQdqx14TnfQAPLk3QYCynfUJvgcQTrg29aqCasceGRpKdQ3Tbn81MLXAGAs7JLBbiMEAhCezAr2kEN8kET1q54zXtKz6znTPgeTZoSbP8rzf4k2JKHZYWrHYF9JriXepuZTnyxAKAxvGFPBk8Z6KAQi33NRQkwd7MPyttatHna6kG9x7knffV6ebGzgRBf7NV27LurH8x4L1uUXwm1v1UYCA1WSBQ9Pp2JW69k5v5v7G9gBy8RUcZnMbeL26Qqb8WkuGcmuHhaFfoqSfV7PRHPpPT4M8uRqUyR4bjUtSJJM1yh6QSeZk9BEazzoJqPeYeGoiFDZ3LMj2jesbJweQR4caaYuRczK92UGSSqu9zBKmE45a _ __ _ _ _ __ ___ From c3ffadf53f5fce9e10b9d66950a1c26600d12632 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:22:05 +0200 Subject: [PATCH 038/236] update network requester smooshed setup --- .../operators/src/nodes/gateway-setup.md | 14 +-- .../src/nodes/network-requester-setup.md | 118 ++++-------------- 2 files changed, 28 insertions(+), 104 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 3861af8e7b..34b55f4716 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -9,7 +9,7 @@ ``` -As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` function which can be turned on or off byt the operator, to set the gateway as an exit node. More info on these changes [below](). +As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` function which can be turned on or off byt the operator, to set the gateway as an exit node. More info on these changes [below](./gateway-setup.md#initialising-gateway-with-network-requester). ## Preliminary steps @@ -83,12 +83,12 @@ An operator can initialise the gateway and network requester together by running ./nym-gateway init --id --host $(curl ifconfig.me) --with-network-requester ``` -If we follow the previous example with `` chosen `supergateway`, adding the `--with-network-requester` flag, the outcome will be: +If we follow the previous example with `` chosen `superexitgateway`, adding the `--with-network-requester` flag, the outcome will be: ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ @@ -110,15 +110,15 @@ See the options: ``` ~~~ -Run with `--enabled true` flag (using same placeholders like above): +Run with `--enabled true` flag chosing `` as `supergateway`: ``` -./nym-gateway setup-network-requester --enabled true --id supergateway --host $(curl ifconfig.me) +./nym-gateway setup-network-requester --enabled true --id supergateway ``` ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ @@ -198,7 +198,7 @@ If you want to bond your mix node via the CLI, then check out the [relevant sect The `run` command starts the gateway: ``` -./nym-gateway run --id +./nym-gateway run --id ``` ## Maintenance diff --git a/documentation/operators/src/nodes/network-requester-setup.md b/documentation/operators/src/nodes/network-requester-setup.md index 640f103a65..ff94054657 100644 --- a/documentation/operators/src/nodes/network-requester-setup.md +++ b/documentation/operators/src/nodes/network-requester-setup.md @@ -1,6 +1,10 @@ # Network Requesters -> The Nym gateway was built in the [building nym](../binaries/building-nym.md) section. If you haven't yet built Nym and want to run the code, go there first. +> The Nym network requester was built in the [building nym](../binaries/building-nym.md) section. If you haven't yet built Nym and want to run the code, go there first. + +```admonish info +As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-network-requester` can be ran as a part of [`nym-gateway`](./gateway-setup.md#initialising-gateway-with-network-requester). This combination is a basis of Nym exit gateway node - an essential piece in our new setup. Please read more in our [Project Smoosh FAQ](../faq/smoosh-faq.md) and [Exit Gateways Page](../legal/exit-gateway.md). We recommend operators to start shifting to that model instead of running gateway and network requester as two separated binaries. +``` > Any syntax in `<>` brackets is a user's unique variable. Exchange with a corresponding name without the `<>` brackets. @@ -14,10 +18,13 @@ Make sure you do the preparation listed in the [preliminary steps page](../preliminary-steps.md) before setting up your network requester. ## Network Requester Whitelist + If you have access to a server, you can run the network requester, which allows Nym users to send outbound requests from their local machine through the mixnet to a server, which then makes the request on their behalf, shielding them (and their metadata) from clearnet, untrusted and unknown infrastructure, such as email or message client servers. By default the network requester is **not** an open proxy (although it can be used as one). It uses a file called `allowed.list` (located in `~/.nym/service-providers/network-requester//`) as a whitelist for outbound requests. +**Note:** If you run network requester as a part of the gateway the `allowed.list` will be stored in `~/.nym/gateways/snus/data/network-requester-data/allowed.list`. + Any request to a URL which is not on this list will be blocked. On startup, if this file is not present, the requester will grab the default whitelist from [Nym's default list](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) automatically. @@ -100,12 +107,17 @@ alephium.org ``` ## Network Requester Directory + You can find a list of Network requesters running the default whitelist in the [explorer](https://explorer.nymtech.net/network-components/service-providers). This list comprises of the NRs running as infrastructure for NymConnect. > We are currently working on a smart-contract based solution more in line with how Mix nodes and Gateways announce themselves to the network. ## Viewing command help +```admonish info +If you run your network requester as a part of your gateway according to the suggested setup, please skip the rest of this page and read about [exit gateway setup](./gateway-setup.md#initialising-gateway-with-network-requester). +``` + To begin, move to `/target/release` directory from which you run the node commands: ``` @@ -151,102 +163,11 @@ Now that we have initialized our network-requester, we can start it with the fol ./nym-network-requester run --id ``` -## Maintenance - -For network requester upgrade (including an upgrade from `= v1.1.10`), firewall setup, port configuration, API endpoints, VPS suggestions, automation and more, see the [maintenance page](./maintenance.md). - -### Upgrading to >= v1.1.10 from -KillSignal=SIGINT -Restart=on-failure -RestartSec=30 - -[Install] -WantedBy=multi-user.target -``` - -Now enable and start your requester: - -``` -systemctl enable nym-network-requester.service -systemctl start nym-network-requester.service - -# you can always check your requester has succesfully started with: -systemctl status nym-network-requester.service -``` - -## VPS Setup -### Configure your firewall -Although your requester is now ready to receive traffic, your server may not be - the following commands will allow you to set up a properly configured firewall using `ufw`: - -``` -# check if you have ufw installed -ufw version -# if it is not installed, install with -sudo apt install ufw -y -# enable ufw -sudo ufw enable -# check the status of the firewall -sudo ufw status -``` - -Finally open your requester's ssh port to incoming administration connections: - -``` -sudo ufw allow 22/tcp -# check the status of the firewall -sudo ufw status -``` ->>>>>>> release/v1.1.27:documentation/docs/src/nodes/network-requester-setup.md ->>>>>>> 85ab634d9c1f1f54073c97a133c83e645a0a3f41 - ## Using your network requester The next thing to do is use your requester, share its address with friends (or whoever you want to help privacy-enhance their app traffic). Is this safe to do? If it was an open proxy, this would be unsafe, because any Nym user could make network requests to any system on the internet. -To make things a bit less stressful for administrators, the Network Requester drops all incoming requests by default. In order for it to make requests, you need to add specific domains to the `allowed.list` file at `$HOME/.nym/service-providers/network-requester/allowed.list`. +To make things a bit less stressful for administrators, the Network Requester drops all incoming requests by default. In order for it to make requests, you need to add specific domains to the `allowed.list` file at `$HOME/.nym/service-providers/network-requester/allowed.list` or if network requester is ran from the [gateway binary](./gateway-setup.md#initialising-gateway-with-network-requester), the `allowed.list` will be stored in `~/.nym/gateways//data/network-requester-data/allowed.list` ### Global vs local allow lists Your Network Requester will check for a domain against 2 lists before allowing traffic through for a particular domain or IP. @@ -263,12 +184,16 @@ It is easy to add new domains and services to your network requester - simply fi How to go about this? Have a look in your nym-network-requester config directory: ``` +# network requester binary ls -lt $HOME/.nym/service-providers/network-requester/*/data | grep "list" +# gateway with network requester binary +ls -lt $HOME/.nym/gateways/*/data/network-requester-data | grep "list" + # returns: allowed.list unknown.list ``` -We already know that `allowed.list` is what lets requests go through. All unknown requests are logged to `unknown.list`. If you want to try using a new client type, just start the new application, point it at your local [socks client](https://nymtech.net/docs/clients/socks5-client.html) (configured to use your remote `nym-network-requester`), and keep copying URLs from `unknown.list` into `allowed.list` (it may take multiple tries until you get all of them, depending on the complexity of the application). Make sure to restart your network requester! +We already know that `allowed.list` is what lets requests go through. All unknown requests are logged to `unknown.list`. If you want to try using a new client type, just start the new application, point it at your local [socks client](https://nymtech.net/docs/clients/socks5-client.html) (configured to use your remote `nym-network-requester`), and keep copying URLs from `unknown.list` into `allowed.list` (it may take multiple tries until you get all of them, depending on the complexity of the application). Make sure to delete the copied ones in 'unknown.list' and restart your network requester or gateway with network requester! > If you are adding custom domains, please note that whilst they may appear in the logs of your network-requester as something like `api-0.core.keybaseapi.com:443`, you **only need** to include the main domain name, in this instance `keybaseapi.com` @@ -292,8 +217,7 @@ This command should return the following: { "status": "ok" } ``` +## Maintenance -## Ports -### Requester port reference +For network requester upgrade (including an upgrade from `= v1.1.10`), firewall setup, port configuration, API endpoints, VPS suggestions, automation and more, see the [maintenance page](./maintenance.md). -All network-requester-specific port configuration can be found in `$HOME/.nym/service-providers/network-requester//config/config.toml`. If you do edit any port configs, remember to restart your client and requester processes. From bbb6919bf1798e9b5b2b999b942872efe7103f1a Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:31:11 +0200 Subject: [PATCH 039/236] delete old troubleshooting stuff --- .../operators/src/nodes/troubleshooting.md | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/documentation/operators/src/nodes/troubleshooting.md b/documentation/operators/src/nodes/troubleshooting.md index 20b98970df..a46332094b 100644 --- a/documentation/operators/src/nodes/troubleshooting.md +++ b/documentation/operators/src/nodes/troubleshooting.md @@ -236,7 +236,7 @@ Here is a sample of the `init` command example to create the mix node config. ./nym-mixnode init --id --host 0.0.0.0 --announce-host 85.160.12.13 ``` -- `--host 0.0.0.0` should work every time even if your local machine IPv4 address changes. For example on Monday your router gives your machine an address `192.168.0.13` and on Wednesday, the DHCP lease will end and you will be assigned `192.168.0.14`. Using `0.0.0.0` should avoid this without having to set any static IP in your router`s configuration. +- `--host 0.0.0.0` should work every time even if your local machine IPv4 address changes. For example on Monday your router gives your machine an address `192.168.0.13` and on Wednesday, the DHCP lease will end and you will be assigned `192.168.0.14`. Using `0.0.0.0` should avoid this without having to set any static IP in your router's configuration. - you can get your current IPv4 address by either using `curl ipinfo.io` if you're on MacOS or Linux or visiting [whatsmyip site](https://www.whatsmyip.org/). Simply copy it and use it as `--anounce-host` address. @@ -262,23 +262,6 @@ thread 'tokio-runtime-worker' panicked at 'Failed to create TCP listener: Os { c Then you need to `--announce-host ` and `--host ` on startup. This issue is addressed [above](./troubleshooting.md#missing-`announce-host`-flag) - ### Can I use a port other than 1789 ? Yes! Here is what you will need to do: @@ -312,6 +295,12 @@ Finally, restart your node. You should see if the mix node is using the port you You don't have to do any additional configuration for your node to implement this, it is a passive process that runs in the background of the mixnet from version `0.10.1` onward. +## Gateways & Network requesters + +### My gateway seems to be running but appears offline + +Check if your [firewall status](./maintenance.md#configure-your-firewall) is active and if the needed ports are allowed. + ## Validators ### Common reasons for your validator being jailed From ddd7c7058c86c67952cefd52ac01ddc7c26e9cd8 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:35:42 +0200 Subject: [PATCH 040/236] add gateway troubleshooting --- documentation/operators/src/nodes/gateway-setup.md | 9 +++++++-- documentation/operators/src/nodes/troubleshooting.md | 9 +++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 34b55f4716..2a5c57b563 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -2,6 +2,10 @@ > The Nym gateway was built in the [building nym](../binaries/building-nym.md) section. If you haven't yet built Nym and want to run the code, go there first. + +```admonish info +As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` function which can be turned on or off [by the operator](./gateway-setup.md#initialising-gateway-with-network-requester). This combination is a basis of Nym exit gateway node - an essential piece in our new setup. Please read more in our [Project Smoosh FAQ](../faq/smoosh-faq.md) and [Exit Gateways Page](../legal/exit-gateway.md). We recommend operators to start shifting to that model instead of running gateway and network requester as two separated binaries. +``` > Any syntax in `<>` brackets is a user's unique variable. Exchange with a corresponding name without the `<>` brackets. ## Current version @@ -9,8 +13,6 @@ ``` -As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` function which can be turned on or off byt the operator, to set the gateway as an exit node. More info on these changes [below](./gateway-setup.md#initialising-gateway-with-network-requester). - ## Preliminary steps Make sure you do the preparation listed in the [preliminary steps page](../preliminary-steps.md) before setting up your gateway. @@ -134,6 +136,9 @@ Save, exit and restart your gateway. All information about your network requester connected to your gateway is in `/home/user/.nym/gateways/snus/config/network_requester_config.toml`. +To read more about the configuration like whitelisted outbound requestes in `allowed.list` and other useful information, see the page [*Network Requester Whitelist*](network-requester-setup.md#using-your-network-requester). + + ```admonish info Before you bond and run your gateway, please make sure the [firewall configuration](./maintenance.md#configure-your-firewall) is setup so your gateway can be reached from the outside. ``` diff --git a/documentation/operators/src/nodes/troubleshooting.md b/documentation/operators/src/nodes/troubleshooting.md index a46332094b..fe9ff47966 100644 --- a/documentation/operators/src/nodes/troubleshooting.md +++ b/documentation/operators/src/nodes/troubleshooting.md @@ -301,6 +301,15 @@ You don't have to do any additional configuration for your node to implement thi Check if your [firewall status](./maintenance.md#configure-your-firewall) is active and if the needed ports are allowed. +### My gateway (with network requester) "is still not online..." + +Remember the epoch takes up to 1h. It's important to run your node right after bonding so it responds positively on our API ping tests. Otherwise it may be blacklisted. + +You may want to diconnect the network requester and let it run as a gatewy alone for some time to regain better routing score. + +If it won't help, simply unbond, delete the config and initialize a new one. + + ## Validators ### Common reasons for your validator being jailed From d103cefed2ab117963de439dff2bf025ab7982f6 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:36:53 +0200 Subject: [PATCH 041/236] spellcheck gateway-setup.md --- documentation/operators/src/nodes/gateway-setup.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 2a5c57b563..24f216492d 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -94,7 +94,7 @@ If we follow the previous example with `` chosen `superexitgateway`, adding ``` ~~~ -You can see that the printed information besides identity and sphinx keys also includes a long string called address. This is the addressto be provided to your local [socks5 client](https://nymtech.net/docs/clients/socks5-client.html) as a `--provider` if you wish to connect to your own exit gateway. +You can see that the printed information besides identity and sphinx keys also includes a long string called address. This is the address to be provided to your local [socks5 client](https://nymtech.net/docs/clients/socks5-client.html) as a `--provider` if you wish to connect to your own exit gateway. #### Add network requester to existing gateway @@ -112,7 +112,7 @@ See the options: ``` ~~~ -Run with `--enabled true` flag chosing `` as `supergateway`: +Run with `--enabled true` flag choosing `` as `supergateway`: ``` ./nym-gateway setup-network-requester --enabled true --id supergateway @@ -136,7 +136,7 @@ Save, exit and restart your gateway. All information about your network requester connected to your gateway is in `/home/user/.nym/gateways/snus/config/network_requester_config.toml`. -To read more about the configuration like whitelisted outbound requestes in `allowed.list` and other useful information, see the page [*Network Requester Whitelist*](network-requester-setup.md#using-your-network-requester). +To read more about the configuration like whitelisted outbound requesters in `allowed.list` and other useful information, see the page [*Network Requester Whitelist*](network-requester-setup.md#using-your-network-requester). ```admonish info From 1e13dc542d92968086d2a8ffc4a6f9fd02c38fbf Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:38:19 +0200 Subject: [PATCH 042/236] spellcheck troubleshooting.md --- documentation/operators/src/nodes/troubleshooting.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/operators/src/nodes/troubleshooting.md b/documentation/operators/src/nodes/troubleshooting.md index fe9ff47966..47de3c3a5e 100644 --- a/documentation/operators/src/nodes/troubleshooting.md +++ b/documentation/operators/src/nodes/troubleshooting.md @@ -291,7 +291,7 @@ Finally, restart your node. You should see if the mix node is using the port you ### What is `verloc` and do I have to configure my mix node to implement it? -`verloc` is short for _verifiable location_. Mixnodes and gateways now measure speed-of-light distances to each other, in an attempt to verify how far apart they are. In later releases, this will allow us to algorithmically verify node locations in a non-fakeable and trustworthy manner. +`verloc` is short for _verifiable location_. Mixnodes and gateways now measure speed-of-light distances to each other, in an attempt to verify how far apart they are. In later releases, this will allow us to algorithmically verify node locations in a non-fake-able and trustworthy manner. You don't have to do any additional configuration for your node to implement this, it is a passive process that runs in the background of the mixnet from version `0.10.1` onward. @@ -305,9 +305,9 @@ Check if your [firewall status](./maintenance.md#configure-your-firewall) is act Remember the epoch takes up to 1h. It's important to run your node right after bonding so it responds positively on our API ping tests. Otherwise it may be blacklisted. -You may want to diconnect the network requester and let it run as a gatewy alone for some time to regain better routing score. +You may want to disconnect the network requester and let it run as a gatewy alone for some time to regain better routing score. -If it won't help, simply unbond, delete the config and initialize a new one. +If it won't help, simply un-bond, delete the config and initialize a new one. ## Validators From 4d8d40f288cced7394c11857bad1f246c2485692 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:42:00 +0200 Subject: [PATCH 043/236] spellcheck mixnodes-faq.md --- documentation/operators/src/faq/mixnodes-faq.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/operators/src/faq/mixnodes-faq.md b/documentation/operators/src/faq/mixnodes-faq.md index 870c1960a6..c93b51f739 100644 --- a/documentation/operators/src/faq/mixnodes-faq.md +++ b/documentation/operators/src/faq/mixnodes-faq.md @@ -14,7 +14,7 @@ For more detailed calculation, read our blog post [Nym Token Economics update](h ### Which VPS providers would you recommend? -Consider in which jurisdiction you reside and where do you want to run a mix node. Do you want to pay by crypto or not and what are the other important particularities for your case? We always recommend operators to try to chose smaller and decentralized VPS providers over the most known ones controlling a majority of the internet. We receive some good feedback on these: Hertzner, DigitalOcean, Linode, Ghandi and Exoscale. Do your own research and share with the community. +Consider in which jurisdiction you reside and where do you want to run a mix node. Do you want to pay by crypto or not and what are the other important particularities for your case? We always recommend operators to try to chose smaller and decentralized VPS providers over the most known ones controlling a majority of the internet. We receive some good feedback on these: Hertzner, DigitalOcean, Linode, Ghandi, Flokinet and Exoscale. Do your own research and share with the community. @@ -24,7 +24,7 @@ The sizes are shown in the configs [here](https://github.com/nymtech/nym/blob/1b ### Why a mix node and a gateway cannot be bond to the same wallet? -Becauase of the way the smart contract works we keep it one-node one-address at the moment. +Because of the way the smart contract works we keep it one-node one-address at the moment. ### Which nodes are the most needed to be setup to strengthen Nym infrastructure and which ones bring rewards? From d80333c819160323a379e79cf452c32de899d4a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 24 Oct 2023 10:50:30 +0200 Subject: [PATCH 044/236] wireguard: add packet relayer (#4032) * wip * wip: first step in putting in place forward channels * Setup event loop for packet relayer * tuntaskresponse * wip * tun task response channel * Update comment * done * formatting * nits * Add comment --- common/wireguard/src/lib.rs | 19 ++- common/wireguard/src/packet_relayer.rs | 66 ++++++++++ .../src/platform/linux/tun_device.rs | 120 ++++++++++-------- common/wireguard/src/tun_task_channel.rs | 34 ++++- common/wireguard/src/udp_listener.rs | 11 +- common/wireguard/src/wg_tunnel.rs | 39 +++--- 6 files changed, 208 insertions(+), 81 deletions(-) create mode 100644 common/wireguard/src/packet_relayer.rs diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index 813ba4718f..cd13ba6937 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -7,6 +7,7 @@ mod active_peers; mod error; mod event; mod network_table; +mod packet_relayer; mod platform; mod registered_peers; mod setup; @@ -38,12 +39,26 @@ pub async fn start_wireguard( let peers_by_tag = Arc::new(std::sync::Mutex::new(wg_tunnel::PeersByTag::new())); // Start the tun device that is used to relay traffic outbound - let (tun, tun_task_tx) = tun_device::TunDevice::new(peers_by_ip.clone(), peers_by_tag.clone()); + let (tun, tun_task_tx, tun_task_response_rx) = tun_device::TunDevice::new(peers_by_ip.clone()); tun.start(); + // If we want to have the tun device on a separate host, it's the tun_task and + // tun_task_response channels that needs to be sent over the network to the host where the tun + // device is running. + + // The packet relayer's responsibility is to route packets between the correct tunnel and the + // tun device. The tun device may or may not be on a separate host, which is why we can't do + // this routing in the tun device itself. + let (packet_relayer, packet_tx) = packet_relayer::PacketRelayer::new( + tun_task_tx.clone(), + tun_task_response_rx, + peers_by_tag.clone(), + ); + packet_relayer.start(); + // Start the UDP listener that clients connect to let udp_listener = udp_listener::WgUdpListener::new( - tun_task_tx, + packet_tx, peers_by_ip, peers_by_tag, Arc::clone(&gateway_client_registry), diff --git a/common/wireguard/src/packet_relayer.rs b/common/wireguard/src/packet_relayer.rs new file mode 100644 index 0000000000..8f0a4ce1ac --- /dev/null +++ b/common/wireguard/src/packet_relayer.rs @@ -0,0 +1,66 @@ +use std::{collections::HashMap, sync::Arc}; + +use tap::TapFallible; +use tokio::sync::mpsc::{self}; + +use crate::{ + event::Event, + tun_task_channel::{TunTaskResponseRx, TunTaskTx}, +}; + +// The tunnels send packets to the packet relayer, which then relays it to the tun device. And +// conversely, it's where the tun device send responses to, which are relayed back to the correct +// tunnel. +pub(crate) struct PacketRelayer { + // Receive packets from the various tunnels + packet_rx: mpsc::Receiver<(u64, Vec)>, + + // After receive from tunnels, send to the tun device + tun_task_tx: TunTaskTx, + + // Receive responses from the tun device + tun_task_response_rx: TunTaskResponseRx, + + // After receiving from the tun device, relay back to the correct tunnel + peers_by_tag: Arc>>>, +} + +impl PacketRelayer { + pub(crate) fn new( + tun_task_tx: TunTaskTx, + tun_task_response_rx: TunTaskResponseRx, + peers_by_tag: Arc>>>, + ) -> (Self, mpsc::Sender<(u64, Vec)>) { + let (packet_tx, packet_rx) = mpsc::channel(16); + ( + Self { + packet_rx, + tun_task_tx, + tun_task_response_rx, + peers_by_tag, + }, + packet_tx, + ) + } + + pub(crate) async fn run(mut self) { + loop { + tokio::select! { + Some((tag, packet)) = self.packet_rx.recv() => { + log::info!("Sent packet to tun device with tag: {tag}"); + self.tun_task_tx.send((tag, packet)).unwrap(); + }, + Some((tag, packet)) = self.tun_task_response_rx.recv() => { + log::info!("Received response from tun device with tag: {tag}"); + self.peers_by_tag.lock().unwrap().get(&tag).and_then(|tx| { + tx.send(Event::Ip(packet.into())).tap_err(|e| log::error!("{e}")).ok() + }); + } + } + } + } + + pub(crate) fn start(self) { + tokio::spawn(async move { self.run().await }); + } +} diff --git a/common/wireguard/src/platform/linux/tun_device.rs b/common/wireguard/src/platform/linux/tun_device.rs index c714eb6cdf..cc449112bc 100644 --- a/common/wireguard/src/platform/linux/tun_device.rs +++ b/common/wireguard/src/platform/linux/tun_device.rs @@ -11,9 +11,11 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt}; use crate::{ event::Event, setup::{TUN_BASE_NAME, TUN_DEVICE_ADDRESS, TUN_DEVICE_NETMASK}, - tun_task_channel::{tun_task_channel, TunTaskPayload, TunTaskRx, TunTaskTx}, + tun_task_channel::{ + tun_task_channel, tun_task_response_channel, TunTaskPayload, TunTaskResponseRx, + TunTaskResponseTx, TunTaskRx, TunTaskTx, + }, udp_listener::PeersByIp, - wg_tunnel::PeersByTag, }; fn setup_tokio_tun_device(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> tokio_tun::Tun { @@ -37,19 +39,21 @@ pub struct TunDevice { // Incoming data that we should send tun_task_rx: TunTaskRx, - // The routing table. - // An alternative would be to do NAT by just matching incoming with outgoing. + // And when we get replies, this is where we should send it + tun_task_response_tx: TunTaskResponseTx, + + // The routing table, as how wireguard does it peers_by_ip: Arc>, + // This is an alternative to the routing table, where we just match outgoing source IP with + // incoming destination IP. nat_table: HashMap, - peers_by_tag: Arc>, } impl TunDevice { pub fn new( peers_by_ip: Arc>, - peers_by_tag: Arc>, - ) -> (Self, TunTaskTx) { + ) -> (Self, TunTaskTx, TunTaskResponseRx) { let tun = setup_tokio_tun_device( format!("{TUN_BASE_NAME}%d").as_str(), TUN_DEVICE_ADDRESS.parse().unwrap(), @@ -59,63 +63,20 @@ impl TunDevice { // Channels to communicate with the other tasks let (tun_task_tx, tun_task_rx) = tun_task_channel(); + let (tun_task_response_tx, tun_task_response_rx) = tun_task_response_channel(); let tun_device = TunDevice { tun_task_rx, + tun_task_response_tx, tun, peers_by_ip, nat_table: HashMap::new(), - peers_by_tag, }; - (tun_device, tun_task_tx) - } - - fn handle_tun_read(&self, packet: &[u8]) { - let Some(dst_addr) = boringtun::noise::Tunn::dst_address(packet) else { - log::error!("Unable to parse dst_address in packet that was read from tun device"); - return; - }; - let Some(src_addr) = parse_src_address(packet) else { - log::error!("Unable to parse src_address in packet that was read from tun device"); - return; - }; - log::info!( - "iface: read Packet({src_addr} -> {dst_addr}, {} bytes)", - packet.len(), - ); - - // Route packet to the correct peer. - if false { - let Ok(peers) = self.peers_by_ip.lock() else { - log::error!("Failed to lock peers_by_ip, aborting tun device read"); - return; - }; - if let Some(peer_tx) = peers.longest_match(dst_addr).map(|(_, tx)| tx) { - log::info!("Forward packet to wg tunnel"); - peer_tx - .send(Event::Ip(packet.to_vec().into())) - .tap_err(|err| log::error!("{err}")) - .ok(); - return; - } - } - - { - if let Some(tag) = self.nat_table.get(&dst_addr) { - log::info!("Forward packet to wg tunnel with tag: {tag}"); - self.peers_by_tag.lock().unwrap().get(tag).and_then(|tx| { - tx.send(Event::Ip(packet.to_vec().into())) - .tap_err(|err| log::error!("{err}")) - .ok() - }); - return; - } - } - - log::info!("No peer found, packet dropped"); + (tun_device, tun_task_tx, tun_task_response_rx) } + // Send outbound packets out on the wild internet async fn handle_tun_write(&mut self, data: TunTaskPayload) { let (tag, packet) = data; let Some(dst_addr) = boringtun::noise::Tunn::dst_address(&packet) else { @@ -143,6 +104,55 @@ impl TunDevice { .ok(); } + // Receive reponse packets from the wild internet + async fn handle_tun_read(&self, packet: &[u8]) { + let Some(dst_addr) = boringtun::noise::Tunn::dst_address(packet) else { + log::error!("Unable to parse dst_address in packet that was read from tun device"); + return; + }; + let Some(src_addr) = parse_src_address(packet) else { + log::error!("Unable to parse src_address in packet that was read from tun device"); + return; + }; + log::info!( + "iface: read Packet({src_addr} -> {dst_addr}, {} bytes)", + packet.len(), + ); + + // Route packet to the correct peer. + + // This is how wireguard does it, by consulting the AllowedIPs table. + if false { + let Ok(peers) = self.peers_by_ip.lock() else { + log::error!("Failed to lock peers_by_ip, aborting tun device read"); + return; + }; + if let Some(peer_tx) = peers.longest_match(dst_addr).map(|(_, tx)| tx) { + log::info!("Forward packet to wg tunnel"); + peer_tx + .send(Event::Ip(packet.to_vec().into())) + .tap_err(|err| log::error!("{err}")) + .ok(); + return; + } + } + + // But we do it by consulting the NAT table. + { + if let Some(tag) = self.nat_table.get(&dst_addr) { + log::info!("Forward packet to wg tunnel with tag: {tag}"); + self.tun_task_response_tx + .send((*tag, packet.to_vec())) + .await + .tap_err(|err| log::error!("{err}")) + .ok(); + return; + } + } + + log::info!("No peer found, packet dropped"); + } + pub async fn run(mut self) { let mut buf = [0u8; 1024]; @@ -152,7 +162,7 @@ impl TunDevice { len = self.tun.read(&mut buf) => match len { Ok(len) => { let packet = &buf[..len]; - self.handle_tun_read(packet); + self.handle_tun_read(packet).await; }, Err(err) => { log::info!("iface: read error: {err}"); diff --git a/common/wireguard/src/tun_task_channel.rs b/common/wireguard/src/tun_task_channel.rs index 423243d27e..3ecc6a76b4 100644 --- a/common/wireguard/src/tun_task_channel.rs +++ b/common/wireguard/src/tun_task_channel.rs @@ -1,9 +1,10 @@ +use tokio::sync::mpsc; + pub(crate) type TunTaskPayload = (u64, Vec); #[derive(Clone)] -pub struct TunTaskTx(tokio::sync::mpsc::UnboundedSender); - -pub(crate) struct TunTaskRx(tokio::sync::mpsc::UnboundedReceiver); +pub struct TunTaskTx(mpsc::UnboundedSender); +pub(crate) struct TunTaskRx(mpsc::UnboundedReceiver); impl TunTaskTx { pub(crate) fn send( @@ -24,3 +25,30 @@ pub(crate) fn tun_task_channel() -> (TunTaskTx, TunTaskRx) { let (tun_task_tx, tun_task_rx) = tokio::sync::mpsc::unbounded_channel(); (TunTaskTx(tun_task_tx), TunTaskRx(tun_task_rx)) } + +// Send responses back from the tun device back to the PacketRelayer +pub(crate) struct TunTaskResponseTx(mpsc::Sender); +pub struct TunTaskResponseRx(mpsc::Receiver); + +impl TunTaskResponseTx { + pub(crate) async fn send( + &self, + data: TunTaskPayload, + ) -> Result<(), tokio::sync::mpsc::error::SendError> { + self.0.send(data).await + } +} + +impl TunTaskResponseRx { + pub(crate) async fn recv(&mut self) -> Option { + self.0.recv().await + } +} + +pub(crate) fn tun_task_response_channel() -> (TunTaskResponseTx, TunTaskResponseRx) { + let (tun_task_tx, tun_task_rx) = tokio::sync::mpsc::channel(16); + ( + TunTaskResponseTx(tun_task_tx), + TunTaskResponseRx(tun_task_rx), + ) +} diff --git a/common/wireguard/src/udp_listener.rs b/common/wireguard/src/udp_listener.rs index e06e0feb20..c703468d97 100644 --- a/common/wireguard/src/udp_listener.rs +++ b/common/wireguard/src/udp_listener.rs @@ -24,7 +24,6 @@ use crate::{ network_table::NetworkTable, registered_peers::{RegisteredPeer, RegisteredPeers}, setup::{self, WG_ADDRESS, WG_PORT}, - tun_task_channel::TunTaskTx, wg_tunnel::PeersByTag, }; @@ -65,7 +64,8 @@ pub struct WgUdpListener { udp: Arc, // Send data to the TUN device for sending - tun_task_tx: TunTaskTx, + // tun_task_tx: TunTaskTx, + packet_tx: mpsc::Sender<(u64, Vec)>, // Wireguard rate limiter rate_limiter: RateLimiter, @@ -75,7 +75,7 @@ pub struct WgUdpListener { impl WgUdpListener { pub async fn new( - tun_task_tx: TunTaskTx, + packet_tx: mpsc::Sender<(u64, Vec)>, peers_by_ip: Arc>, peers_by_tag: Arc>, gateway_client_registry: Arc, @@ -101,7 +101,7 @@ impl WgUdpListener { peers_by_ip, peers_by_tag, udp, - tun_task_tx, + packet_tx, rate_limiter, gateway_client_registry, }) @@ -207,7 +207,8 @@ impl WgUdpListener { *registered_peer.public_key, registered_peer.index, registered_peer.allowed_ips, - self.tun_task_tx.clone(), + // self.tun_task_tx.clone(), + self.packet_tx.clone(), ); self.peers_by_ip.lock().unwrap().insert(registered_peer.allowed_ips, peer_tx.clone()); diff --git a/common/wireguard/src/wg_tunnel.rs b/common/wireguard/src/wg_tunnel.rs index f9308fbe2c..32ece1e842 100644 --- a/common/wireguard/src/wg_tunnel.rs +++ b/common/wireguard/src/wg_tunnel.rs @@ -7,6 +7,7 @@ use boringtun::{ }; use bytes::Bytes; use log::{debug, error, info, warn}; +use rand::RngCore; use tap::TapFallible; use tokio::{ net::UdpSocket, @@ -14,10 +15,7 @@ use tokio::{ time::timeout, }; -use crate::{ - error::WgError, event::Event, network_table::NetworkTable, registered_peers::PeerIdx, - tun_task_channel::TunTaskTx, -}; +use crate::{error::WgError, event::Event, network_table::NetworkTable, registered_peers::PeerIdx}; const HANDSHAKE_MAX_RATE: u64 = 10; @@ -47,7 +45,8 @@ pub struct WireGuardTunnel { close_rx: broadcast::Receiver<()>, // Send data to the task that handles sending data through the tun device - tun_task_tx: TunTaskTx, + // tun_task_tx: TunTaskTx, + packet_tx: mpsc::Sender<(u64, Vec)>, tag: u64, } @@ -68,7 +67,7 @@ impl WireGuardTunnel { index: PeerIdx, peer_allowed_ips: ip_network::IpNetwork, // rate_limiter: Option, - tunnel_tx: TunTaskTx, + packet_tx: mpsc::Sender<(u64, Vec)>, ) -> (Self, mpsc::UnboundedSender, u64) { let local_addr = udp.local_addr().unwrap(); let peer_addr = udp.peer_addr(); @@ -92,7 +91,7 @@ impl WireGuardTunnel { index, rate_limiter, ) - .unwrap(), + .expect("failed to create Tunn instance"), )); // Channels with incoming data that is received by the main event loop @@ -104,10 +103,7 @@ impl WireGuardTunnel { let mut allowed_ips = NetworkTable::new(); allowed_ips.insert(peer_allowed_ips, ()); - // random u64 - use rand::RngCore; - let mut rng = rand::rngs::OsRng; - let tag = rng.next_u64(); + let tag = Self::new_tag(); let tunnel = WireGuardTunnel { peer_rx, @@ -117,13 +113,18 @@ impl WireGuardTunnel { wg_tunnel, close_tx, close_rx, - tun_task_tx: tunnel_tx, + packet_tx, tag, }; (tunnel, peer_tx, tag) } + fn new_tag() -> u64 { + // TODO: check for collisions + rand::thread_rng().next_u64() + } + fn close(&self) { let _ = self.close_tx.send(()); } @@ -210,14 +211,20 @@ impl WireGuardTunnel { } TunnResult::WriteToTunnelV4(packet, addr) => { if self.allowed_ips.longest_match(addr).is_some() { - self.tun_task_tx.send((self.tag, packet.to_vec())).unwrap(); + self.packet_tx + .send((self.tag, packet.to_vec())) + .await + .unwrap(); } else { warn!("Packet from {addr} not in allowed_ips"); } } TunnResult::WriteToTunnelV6(packet, addr) => { if self.allowed_ips.longest_match(addr).is_some() { - self.tun_task_tx.send((self.tag, packet.to_vec())).unwrap(); + self.packet_tx + .send((self.tag, packet.to_vec())) + .await + .unwrap(); } else { warn!("Packet (v6) from {addr} not in allowed_ips"); } @@ -319,7 +326,7 @@ pub(crate) fn start_wg_tunnel( peer_static_public: x25519::PublicKey, peer_index: PeerIdx, peer_allowed_ips: ip_network::IpNetwork, - tunnel_tx: TunTaskTx, + packet_tx: mpsc::Sender<(u64, Vec)>, ) -> ( tokio::task::JoinHandle, mpsc::UnboundedSender, @@ -332,7 +339,7 @@ pub(crate) fn start_wg_tunnel( peer_static_public, peer_index, peer_allowed_ips, - tunnel_tx, + packet_tx, ); let join_handle = tokio::spawn(async move { tunnel.spin_off().await; From e2d816defb21d206af0e1cd057fbfc2f3b8b91e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 24 Oct 2023 09:57:53 +0100 Subject: [PATCH 045/236] fixed fmt::Display impl for GatewayNetworkRequesterDetails (#4033) --- common/types/src/gateway.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/types/src/gateway.rs b/common/types/src/gateway.rs index a26fea053f..c57dee8001 100644 --- a/common/types/src/gateway.rs +++ b/common/types/src/gateway.rs @@ -143,6 +143,6 @@ impl fmt::Display for GatewayNetworkRequesterDetails { writeln!(f, "\tsends statistics: {}", self.enabled_statistics)?; writeln!(f, "\tallow list path: {}", self.allow_list_path)?; - writeln!(f, "\tunknown list path: {}", self.allow_list_path) + writeln!(f, "\tunknown list path: {}", self.unknown_list_path) } } From 4b68f8b725e51ad2195c3f4504fdcb9562a1bc12 Mon Sep 17 00:00:00 2001 From: pierre Date: Tue, 24 Oct 2023 11:04:54 +0200 Subject: [PATCH 046/236] setup lib compilation --- nym-vpn/ui/.eslintrc.cjs | 1 + nym-vpn/ui/README.md | 31 +++++++++++++++++++++++++++- nym-vpn/ui/package.json | 6 ++++-- nym-vpn/ui/src-tauri/Cargo.lock | 2 +- nym-vpn/ui/src-tauri/Cargo.toml | 5 +++-- nym-vpn/ui/src-tauri/Cross.toml | 2 ++ nym-vpn/ui/src-tauri/src/lib.rs | 16 ++++++++++++++ nym-vpn/ui/src-tauri/tauri.conf.json | 2 +- nym-vpn/ui/yarn.lock | 11 +++++++--- 9 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 nym-vpn/ui/src-tauri/Cross.toml create mode 100644 nym-vpn/ui/src-tauri/src/lib.rs diff --git a/nym-vpn/ui/.eslintrc.cjs b/nym-vpn/ui/.eslintrc.cjs index a1a2282c97..5c7c3e4c95 100644 --- a/nym-vpn/ui/.eslintrc.cjs +++ b/nym-vpn/ui/.eslintrc.cjs @@ -4,6 +4,7 @@ module.exports = { 'plugin:@typescript-eslint/recommended', 'plugin:react/recommended', 'plugin:react/jsx-runtime', + 'plugin:react-hooks/recommended', 'prettier', ], parser: '@typescript-eslint/parser', diff --git a/nym-vpn/ui/README.md b/nym-vpn/ui/README.md index 5d2ff29980..79fc724759 100644 --- a/nym-vpn/ui/README.md +++ b/nym-vpn/ui/README.md @@ -4,6 +4,17 @@ This is the application UI layer for the next NymVPN clients. ## Install +#### Prerequisites + +- Rust +- Nodejs, latest LTS version recommended +- yarn 1.x + +Some system libraries are required depending on the host platform. +Follow the instructions for your specific OS [here](https://tauri.app/v1/guides/getting-started/prerequisites) + +To install run + ``` yarn ``` @@ -17,7 +28,7 @@ yarn dev:app ## Dev in the browser For convenience and better development experience, we can run the -app in dev mode in the browser +app directly in the browser ``` yarn dev:browser @@ -29,3 +40,21 @@ In browser mode requires all tauri [commands](https://tauri.app/v1/guides/featur When creating new tauri command, be sure to add the corresponding mock definition into `nym-vpn/ui/src/dev/tauri-cmd-mocks/` and update `nym-vpn/ui/src/dev/setup.ts` accordingly. + +## Build + +To build as a **shared library** + +``` +yarn build && cd src-tauri && cargo build --release --lib --features custom-protocol + +#alias +yarn build:app +``` + +You can build for a different platform using [Cross](https://github.com/cross-rs/cross). +For example, to build for Windows on Linux: + +``` +cross build --target x86_64-pc-windows-gnu --release --lib --features custom-protocol +``` diff --git a/nym-vpn/ui/package.json b/nym-vpn/ui/package.json index 71c59b7e09..7d49d0ca36 100644 --- a/nym-vpn/ui/package.json +++ b/nym-vpn/ui/package.json @@ -8,6 +8,7 @@ "dev:app": "WEBKIT_DISABLE_COMPOSITING_MODE=1 tauri dev", "dev:browser": "vite --mode dev-browser", "build": "tsc && vite build", + "build:app": "yarn build && cd src-tauri && cargo build --release --lib --features custom-protocol", "preview": "vite preview", "lint": "eslint --ext .ts,.tsx src/", "lint:fix": "eslint --ext .js,.ts --fix src/", @@ -26,8 +27,8 @@ }, "devDependencies": { "@tauri-apps/cli": "^1.5.0", - "@types/react": "^18.2.15", - "@types/react-dom": "^18.2.7", + "@types/react": "^18.2.31", + "@types/react-dom": "^18.2.14", "@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/parser": "^6.8.0", "@vitejs/plugin-react-swc": "^3.3.2", @@ -35,6 +36,7 @@ "eslint": "^8.52.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", "postcss": "^8.4.31", "postcss-import": "^15.1.0", "prettier": "^3.0.3", diff --git a/nym-vpn/ui/src-tauri/Cargo.lock b/nym-vpn/ui/src-tauri/Cargo.lock index 6909dda0e5..4e4061f1a5 100644 --- a/nym-vpn/ui/src-tauri/Cargo.lock +++ b/nym-vpn/ui/src-tauri/Cargo.lock @@ -1648,7 +1648,7 @@ dependencies = [ ] [[package]] -name = "nym-vpn-ui" +name = "nymvpn-ui" version = "0.0.0" dependencies = [ "serde", diff --git a/nym-vpn/ui/src-tauri/Cargo.toml b/nym-vpn/ui/src-tauri/Cargo.toml index e05eaf1144..93b390a573 100644 --- a/nym-vpn/ui/src-tauri/Cargo.toml +++ b/nym-vpn/ui/src-tauri/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "nym-vpn-ui" +name = "nymvpn-ui" version = "0.0.0" description = "Application UI for Nym VPN desktop clients" authors = ["you"] @@ -7,7 +7,8 @@ license = "" repository = "" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +crate-type = ["cdylib"] [build-dependencies] tauri-build = { version = "1.5", features = [] } diff --git a/nym-vpn/ui/src-tauri/Cross.toml b/nym-vpn/ui/src-tauri/Cross.toml new file mode 100644 index 0000000000..27d16cba1f --- /dev/null +++ b/nym-vpn/ui/src-tauri/Cross.toml @@ -0,0 +1,2 @@ +[build.env] +volumes = ["VOL1_ARG=../dist"] diff --git a/nym-vpn/ui/src-tauri/src/lib.rs b/nym-vpn/ui/src-tauri/src/lib.rs new file mode 100644 index 0000000000..940f438b54 --- /dev/null +++ b/nym-vpn/ui/src-tauri/src/lib.rs @@ -0,0 +1,16 @@ +// Prevents additional console window on Windows in release, DO NOT REMOVE!! +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command +#[tauri::command] +fn greet(name: &str) -> String { + format!("Hello, {}! You've been greeted from Rust!", name) +} + +#[no_mangle] +pub extern "C" fn run_tauri() { + tauri::Builder::default() + .invoke_handler(tauri::generate_handler![greet]) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} diff --git a/nym-vpn/ui/src-tauri/tauri.conf.json b/nym-vpn/ui/src-tauri/tauri.conf.json index 89644f65b7..d3983c24e4 100644 --- a/nym-vpn/ui/src-tauri/tauri.conf.json +++ b/nym-vpn/ui/src-tauri/tauri.conf.json @@ -7,7 +7,7 @@ "withGlobalTauri": false }, "package": { - "productName": "nym-vpn-ui", + "productName": "nymvpn-ui", "version": "0.0.0" }, "tauri": { diff --git a/nym-vpn/ui/yarn.lock b/nym-vpn/ui/yarn.lock index dbfa3880ed..e243243e30 100644 --- a/nym-vpn/ui/yarn.lock +++ b/nym-vpn/ui/yarn.lock @@ -540,9 +540,9 @@ resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz" integrity sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g== -"@types/react-dom@^18.2.7": +"@types/react-dom@^18.2.14": version "18.2.14" - resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.14.tgz#c01ba40e5bb57fc1dc41569bb3ccdb19eab1c539" integrity sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ== dependencies: "@types/react" "*" @@ -554,7 +554,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^18.2.15": +"@types/react@*", "@types/react@^18.2.31": version "18.2.31" resolved "https://registry.npmjs.org/@types/react/-/react-18.2.31.tgz" integrity sha512-c2UnPv548q+5DFh03y8lEDeMfDwBn9G3dRwfkrxQMo/dOtRHUUO57k6pHvBIfH/VF4Nh+98mZ5aaSe+2echD5g== @@ -1152,6 +1152,11 @@ eslint-config-prettier@^9.0.0: resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz" integrity sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw== +eslint-plugin-react-hooks@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" + integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== + eslint-plugin-react@^7.33.2: version "7.33.2" resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz" From 7cafd25036df945d2bc6bf14022b4074ff01f3c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 24 Oct 2023 11:22:59 +0200 Subject: [PATCH 047/236] wg: all channels strongly typed (#4035) * Add PeerEventSender/Receiver * Create strong types * Create PacketRelaySender/Receiver * Strongly typed --- common/wireguard/src/active_peers.rs | 32 ++++++++++++++++++++---- common/wireguard/src/packet_relayer.rs | 22 ++++++++++++----- common/wireguard/src/udp_listener.rs | 18 +++++--------- common/wireguard/src/wg_tunnel.rs | 34 ++++++++++++++------------ 4 files changed, 68 insertions(+), 38 deletions(-) diff --git a/common/wireguard/src/active_peers.rs b/common/wireguard/src/active_peers.rs index 43b4b43366..6973d29be1 100644 --- a/common/wireguard/src/active_peers.rs +++ b/common/wireguard/src/active_peers.rs @@ -9,8 +9,30 @@ use tokio::sync::mpsc::{self}; use crate::event::Event; -pub(crate) type PeersByKey = DashMap>; -pub(crate) type PeersByAddr = DashMap>; +// Channels that are used to communicate with the various tunnels +#[derive(Clone)] +pub struct PeerEventSender(mpsc::UnboundedSender); +pub(crate) struct PeerEventReceiver(mpsc::UnboundedReceiver); + +impl PeerEventSender { + pub(crate) fn send(&self, event: Event) -> Result<(), mpsc::error::SendError> { + self.0.send(event) + } +} + +impl PeerEventReceiver { + pub(crate) async fn recv(&mut self) -> Option { + self.0.recv().await + } +} + +pub(crate) fn peer_event_channel() -> (PeerEventSender, PeerEventReceiver) { + let (tx, rx) = mpsc::unbounded_channel(); + (PeerEventSender(tx), PeerEventReceiver(rx)) +} + +pub(crate) type PeersByKey = DashMap; +pub(crate) type PeersByAddr = DashMap; #[derive(Default)] pub(crate) struct ActivePeers { @@ -30,7 +52,7 @@ impl ActivePeers { &self, public_key: x25519::PublicKey, addr: SocketAddr, - peer_tx: mpsc::UnboundedSender, + peer_tx: PeerEventSender, ) { self.active_peers.insert(public_key, peer_tx.clone()); self.active_peers_by_addr.insert(addr, peer_tx); @@ -39,14 +61,14 @@ impl ActivePeers { pub(crate) fn get_by_key_mut( &self, public_key: &x25519::PublicKey, - ) -> Option>> { + ) -> Option> { self.active_peers.get_mut(public_key) } pub(crate) fn get_by_addr( &self, addr: &SocketAddr, - ) -> Option>> { + ) -> Option> { self.active_peers_by_addr.get(addr) } } diff --git a/common/wireguard/src/packet_relayer.rs b/common/wireguard/src/packet_relayer.rs index 8f0a4ce1ac..40d49d5d37 100644 --- a/common/wireguard/src/packet_relayer.rs +++ b/common/wireguard/src/packet_relayer.rs @@ -4,16 +4,26 @@ use tap::TapFallible; use tokio::sync::mpsc::{self}; use crate::{ + active_peers::PeerEventSender, event::Event, tun_task_channel::{TunTaskResponseRx, TunTaskTx}, }; +#[derive(Clone)] +pub struct PacketRelaySender(pub(crate) mpsc::Sender<(u64, Vec)>); +pub(crate) struct PacketRelayReceiver(pub(crate) mpsc::Receiver<(u64, Vec)>); + +pub(crate) fn packet_relay_channel() -> (PacketRelaySender, PacketRelayReceiver) { + let (tx, rx) = mpsc::channel(16); + (PacketRelaySender(tx), PacketRelayReceiver(rx)) +} + // The tunnels send packets to the packet relayer, which then relays it to the tun device. And // conversely, it's where the tun device send responses to, which are relayed back to the correct // tunnel. pub(crate) struct PacketRelayer { // Receive packets from the various tunnels - packet_rx: mpsc::Receiver<(u64, Vec)>, + packet_rx: PacketRelayReceiver, // After receive from tunnels, send to the tun device tun_task_tx: TunTaskTx, @@ -22,16 +32,16 @@ pub(crate) struct PacketRelayer { tun_task_response_rx: TunTaskResponseRx, // After receiving from the tun device, relay back to the correct tunnel - peers_by_tag: Arc>>>, + peers_by_tag: Arc>>, } impl PacketRelayer { pub(crate) fn new( tun_task_tx: TunTaskTx, tun_task_response_rx: TunTaskResponseRx, - peers_by_tag: Arc>>>, - ) -> (Self, mpsc::Sender<(u64, Vec)>) { - let (packet_tx, packet_rx) = mpsc::channel(16); + peers_by_tag: Arc>>, + ) -> (Self, PacketRelaySender) { + let (packet_tx, packet_rx) = packet_relay_channel(); ( Self { packet_rx, @@ -46,7 +56,7 @@ impl PacketRelayer { pub(crate) async fn run(mut self) { loop { tokio::select! { - Some((tag, packet)) = self.packet_rx.recv() => { + Some((tag, packet)) = self.packet_rx.0.recv() => { log::info!("Sent packet to tun device with tag: {tag}"); self.tun_task_tx.send((tag, packet)).unwrap(); }, diff --git a/common/wireguard/src/udp_listener.rs b/common/wireguard/src/udp_listener.rs index c703468d97..5c04c010a4 100644 --- a/common/wireguard/src/udp_listener.rs +++ b/common/wireguard/src/udp_listener.rs @@ -9,19 +9,14 @@ use log::error; use nym_task::TaskClient; use nym_wireguard_types::{registration::GatewayClientRegistry, PeerPublicKey}; use tap::TapFallible; -use tokio::{ - net::UdpSocket, - sync::{ - mpsc::{self}, - Mutex, - }, -}; +use tokio::{net::UdpSocket, sync::Mutex}; use crate::{ - active_peers::ActivePeers, + active_peers::{ActivePeers, PeerEventSender}, error::WgError, event::Event, network_table::NetworkTable, + packet_relayer::PacketRelaySender, registered_peers::{RegisteredPeer, RegisteredPeers}, setup::{self, WG_ADDRESS, WG_PORT}, wg_tunnel::PeersByTag, @@ -30,7 +25,7 @@ use crate::{ const MAX_PACKET: usize = 65535; // Registered peers -pub(crate) type PeersByIp = NetworkTable>; +pub(crate) type PeersByIp = NetworkTable; async fn add_test_peer(registered_peers: &mut RegisteredPeers) { let peer_static_public = PeerPublicKey::new(setup::peer_static_public_key()); @@ -64,8 +59,7 @@ pub struct WgUdpListener { udp: Arc, // Send data to the TUN device for sending - // tun_task_tx: TunTaskTx, - packet_tx: mpsc::Sender<(u64, Vec)>, + packet_tx: PacketRelaySender, // Wireguard rate limiter rate_limiter: RateLimiter, @@ -75,7 +69,7 @@ pub struct WgUdpListener { impl WgUdpListener { pub async fn new( - packet_tx: mpsc::Sender<(u64, Vec)>, + packet_tx: PacketRelaySender, peers_by_ip: Arc>, peers_by_tag: Arc>, gateway_client_registry: Arc, diff --git a/common/wireguard/src/wg_tunnel.rs b/common/wireguard/src/wg_tunnel.rs index 32ece1e842..f35f51e1bd 100644 --- a/common/wireguard/src/wg_tunnel.rs +++ b/common/wireguard/src/wg_tunnel.rs @@ -9,24 +9,27 @@ use bytes::Bytes; use log::{debug, error, info, warn}; use rand::RngCore; use tap::TapFallible; -use tokio::{ - net::UdpSocket, - sync::{broadcast, mpsc}, - time::timeout, -}; +use tokio::{net::UdpSocket, sync::broadcast, time::timeout}; -use crate::{error::WgError, event::Event, network_table::NetworkTable, registered_peers::PeerIdx}; +use crate::{ + active_peers::{peer_event_channel, PeerEventReceiver, PeerEventSender}, + error::WgError, + event::Event, + network_table::NetworkTable, + packet_relayer::PacketRelaySender, + registered_peers::PeerIdx, +}; const HANDSHAKE_MAX_RATE: u64 = 10; const MAX_PACKET: usize = 65535; // We index the tunnels by tag -pub(crate) type PeersByTag = HashMap>; +pub(crate) type PeersByTag = HashMap; pub struct WireGuardTunnel { // Incoming data from the UDP socket received in the main event loop - peer_rx: mpsc::UnboundedReceiver, + peer_rx: PeerEventReceiver, // UDP socket used for sending data udp: Arc, @@ -45,8 +48,7 @@ pub struct WireGuardTunnel { close_rx: broadcast::Receiver<()>, // Send data to the task that handles sending data through the tun device - // tun_task_tx: TunTaskTx, - packet_tx: mpsc::Sender<(u64, Vec)>, + packet_tx: PacketRelaySender, tag: u64, } @@ -67,8 +69,8 @@ impl WireGuardTunnel { index: PeerIdx, peer_allowed_ips: ip_network::IpNetwork, // rate_limiter: Option, - packet_tx: mpsc::Sender<(u64, Vec)>, - ) -> (Self, mpsc::UnboundedSender, u64) { + packet_tx: PacketRelaySender, + ) -> (Self, PeerEventSender, u64) { let local_addr = udp.local_addr().unwrap(); let peer_addr = udp.peer_addr(); log::info!("New wg tunnel: endpoint: {endpoint}, local_addr: {local_addr}, peer_addr: {peer_addr:?}"); @@ -95,7 +97,7 @@ impl WireGuardTunnel { )); // Channels with incoming data that is received by the main event loop - let (peer_tx, peer_rx) = mpsc::unbounded_channel(); + let (peer_tx, peer_rx) = peer_event_channel(); // Signal close tunnel let (close_tx, close_rx) = broadcast::channel(1); @@ -212,6 +214,7 @@ impl WireGuardTunnel { TunnResult::WriteToTunnelV4(packet, addr) => { if self.allowed_ips.longest_match(addr).is_some() { self.packet_tx + .0 .send((self.tag, packet.to_vec())) .await .unwrap(); @@ -222,6 +225,7 @@ impl WireGuardTunnel { TunnResult::WriteToTunnelV6(packet, addr) => { if self.allowed_ips.longest_match(addr).is_some() { self.packet_tx + .0 .send((self.tag, packet.to_vec())) .await .unwrap(); @@ -326,10 +330,10 @@ pub(crate) fn start_wg_tunnel( peer_static_public: x25519::PublicKey, peer_index: PeerIdx, peer_allowed_ips: ip_network::IpNetwork, - packet_tx: mpsc::Sender<(u64, Vec)>, + packet_tx: PacketRelaySender, ) -> ( tokio::task::JoinHandle, - mpsc::UnboundedSender, + PeerEventSender, u64, ) { let (mut tunnel, peer_tx, tag) = WireGuardTunnel::new( From cd425412cc76bb6f73664311652f5458a0d80c98 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 11:35:43 +0200 Subject: [PATCH 048/236] fix comments mixnodes-faq.md --- documentation/operators/src/faq/mixnodes-faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/faq/mixnodes-faq.md b/documentation/operators/src/faq/mixnodes-faq.md index c93b51f739..38c62154b5 100644 --- a/documentation/operators/src/faq/mixnodes-faq.md +++ b/documentation/operators/src/faq/mixnodes-faq.md @@ -14,7 +14,7 @@ For more detailed calculation, read our blog post [Nym Token Economics update](h ### Which VPS providers would you recommend? -Consider in which jurisdiction you reside and where do you want to run a mix node. Do you want to pay by crypto or not and what are the other important particularities for your case? We always recommend operators to try to chose smaller and decentralized VPS providers over the most known ones controlling a majority of the internet. We receive some good feedback on these: Hertzner, DigitalOcean, Linode, Ghandi, Flokinet and Exoscale. Do your own research and share with the community. +Consider in which jurisdiction you reside and where do you want to run a mix node. Do you want to pay by crypto or not and what are the other important particularities for your case? We always recommend operators to try to choose smaller and decentralised VPS providers over the most known ones controlling a majority of the internet. We receive some good feedback on these: Linode, Ghandi, Flokinet and Exoscale. Do your own research and share with the community. From d5cabb10d6c80daad3665c628cdb40a94589aaa9 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 11:39:21 +0200 Subject: [PATCH 049/236] fix comments smoosh-faq.md --- documentation/operators/src/faq/smoosh-faq.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index ae0f763464..8bcc071e3e 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -74,7 +74,7 @@ From an operator standpoint, it shall just be a standard Nym upgrade, a new opti ### Are there any legal concerns for the operators? -So far the general line is running a gateway is not illegal (unless you are in Iran, China, and a few other places) and due to encryption/mixing less risky than running a normal VPN node. For mix nodes, its very safe as they have "no idea" what packets they are mixing. +So far the general line is that running a gateway is not illegal (unless you are in Iran, China, and a few other places) and due to encryption/mixing less risky than running a normal VPN node. For mix nodes, it's very safe as they have "no idea" what packets they are mixing. -There are several legal questions regarding to this and analysis to be made for different jurisdictions. To be able to share resources and findings between the operators themselves we created a [Community Legal Forum](../legal/exit-gateway.md). +There are several legal questions and analysis to be made for different jurisdictions. To be able to share resources and findings between the operators themselves we created a [Community Legal Forum](../legal/exit-gateway.md). From e7e68dafb542bafd7a7f31f89b51a8c5e203f969 Mon Sep 17 00:00:00 2001 From: pierre Date: Tue, 24 Oct 2023 11:46:34 +0200 Subject: [PATCH 050/236] fix typo --- nym-vpn/ui/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nym-vpn/ui/README.md b/nym-vpn/ui/README.md index 79fc724759..a1fe5876a6 100644 --- a/nym-vpn/ui/README.md +++ b/nym-vpn/ui/README.md @@ -34,9 +34,11 @@ app directly in the browser yarn dev:browser ``` +Then press `o` to open the app in the browser. + #### Tauri commands mock -In browser mode requires all tauri [commands](https://tauri.app/v1/guides/features/command) (IPC calls) in use to be mocked. +Browser mode requires all tauri [commands](https://tauri.app/v1/guides/features/command) (IPC calls) to be mocked. When creating new tauri command, be sure to add the corresponding mock definition into `nym-vpn/ui/src/dev/tauri-cmd-mocks/` and update `nym-vpn/ui/src/dev/setup.ts` accordingly. From 6b674fb53e6f409cbfa71ccaa0a31f351d0d3002 Mon Sep 17 00:00:00 2001 From: Tommy Verrall <60836166+tommyv1987@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:48:39 +0100 Subject: [PATCH 051/236] Update qa.env (#4038) add ephemera placeholder --- envs/qa.env | 1 + 1 file changed, 1 insertion(+) diff --git a/envs/qa.env b/envs/qa.env index 21c8014d1b..97d9838411 100644 --- a/envs/qa.env +++ b/envs/qa.env @@ -16,6 +16,7 @@ COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n1w798gp0zqv3s9hjl3jlnwxtwhykga6rn93p46q2crsd GROUP_CONTRACT_ADDRESS=n1sthrn5ep8ls5vzz8f9gp89khhmedahhdqd244dh9uqzk3hx2pzrsvf7zgk MULTISIG_CONTRACT_ADDRESS=n1sr06m8yqg0wzqqyqvzvp5t07dj4nevx9u8qc7j4qa72qu8e3ct8qledthy COCONUT_DKG_CONTRACT_ADDRESS=n1udfs22xpxle475m2nz7u47jfa3vngncdegmczwwdx00cmetypa3s7uyuqn +EPHEMERA_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0 REWARDING_VALIDATOR_ADDRESS=n1rfvpsynktze6wvn6ldskj8xgwfzzk5v6pnff39 NAME_SERVICE_CONTRACT_ADDRESS=n1qum2tr7hh4y7ruzew68c64myjec0dq2s2njf6waja5t0w879lutqadamme SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS=n13ehuhysn5mqjeaheeuew2gjs785f6k7jm8vfsqg3jhtpkwppcmzq6m2hmz From 7df87a9c22299822908ce4e5182f472c26cf25f3 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 11:51:32 +0200 Subject: [PATCH 052/236] fix comments gateway-setup.md --- .../operators/src/nodes/gateway-setup.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 24f216492d..0c95db8b8a 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -4,7 +4,7 @@ ```admonish info -As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` function which can be turned on or off [by the operator](./gateway-setup.md#initialising-gateway-with-network-requester). This combination is a basis of Nym exit gateway node - an essential piece in our new setup. Please read more in our [Project Smoosh FAQ](../faq/smoosh-faq.md) and [Exit Gateways Page](../legal/exit-gateway.md). We recommend operators to start shifting to that model instead of running gateway and network requester as two separated binaries. +As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` functionality which can be enabled [by the operator](./gateway-setup.md#initialising-gateway-with-network-requester). This combination is a basis of Nym exit gateway node - an essential piece in our new setup. Please read more in our [Project Smoosh FAQ](../faq/smoosh-faq.md) and [Exit Gateways Page](../legal/exit-gateway.md). We recommend operators begin to shift their setups to this new combined node, instead of operating two separate binaries. ``` > Any syntax in `<>` brackets is a user's unique variable. Exchange with a corresponding name without the `<>` brackets. @@ -77,9 +77,9 @@ The `$(curl ifconfig.me)` command above returns your IP automatically using an e #### Initialising gateway with network requester -As some of the [Project Smoosh](../faq/smoosh-faq.md) changes getting implemented, the gateways now can work also as a network requesters at the same time. Such combination creates an exit gateway node, needed for new more open setup. +As some of the [Project Smoosh](../faq/smoosh-faq.md) changes getting implemented, network requester is smooshed with gateways. Such combination creates an exit gateway node, needed for new more open setup. -An operator can initialise the gateway and network requester together by running: +An operator can initialise the exit gateway functionality by: ``` ./nym-gateway init --id --host $(curl ifconfig.me) --with-network-requester @@ -94,11 +94,11 @@ If we follow the previous example with `` chosen `superexitgateway`, adding ``` ~~~ -You can see that the printed information besides identity and sphinx keys also includes a long string called address. This is the address to be provided to your local [socks5 client](https://nymtech.net/docs/clients/socks5-client.html) as a `--provider` if you wish to connect to your own exit gateway. +You can see that the printed information besides *identity* and *sphinx keys* also includes a long string called *address*. This is the address to be provided to your local [socks5 client](https://nymtech.net/docs/clients/socks5-client.html) as a `--provider` if you wish to connect to your own exit gateway. #### Add network requester to existing gateway -If you already have a gateway and got it [upgraded](./maintenance.md#upgrading-your-node) to the [newest version](./gateway-setup.md#current-version), you can easily add a network requester by stopping your gateway and running a command `setup-network-requester`. +If you already run a gateway and got it [upgraded](./maintenance.md#upgrading-your-node) to the [newest version](./gateway-setup.md#current-version), you can easily change its functionality to exit gateway. PAuse the gateway and run a command `setup-network-requester`. See the options: @@ -124,7 +124,7 @@ Run with `--enabled true` flag choosing `` as `supergateway`: ``` ~~~ -In case there are any problems, you can also change it manually by editing the gateway config stored in `/home/user/.nym/gateways//config/config.toml` where the line under `[network_requester]` needs to be edited from `false` to `true`, it shall look like this: +In case there are any problems, you can also change it manually by editing the gateway config stored in `/home/user/.nym/gateways//config/config.toml` where the line under `[network_requester]` needs to be edited from `false` to `true`. ``` [network_requester] @@ -132,9 +132,9 @@ In case there are any problems, you can also change it manually by editing the g enabled = true ``` -Save, exit and restart your gateway. +Save, exit and restart your gateway. Now it is a post-smooshed exit gateway. -All information about your network requester connected to your gateway is in `/home/user/.nym/gateways/snus/config/network_requester_config.toml`. +All information about network requester part of your exit gateway is in `/home/user/.nym/gateways/snus/config/network_requester_config.toml`. To read more about the configuration like whitelisted outbound requesters in `allowed.list` and other useful information, see the page [*Network Requester Whitelist*](network-requester-setup.md#using-your-network-requester). @@ -149,7 +149,7 @@ Before you bond and run your gateway, please make sure the [firewall configurati You can bond your gateway via the Desktop wallet. -1. Open your wallet, and head to the `Bonding` page, then select the node type `Gateway` and input your node details. Press `Next` +1. Open your wallet, and head to the `Bonding` page, then select the node type `Gateway` and input your node details. Press `Next`. 2. Enter the `Amount`, `Operating cost` and press `Next`. From 11e0b085d55bb174bcf8959b2020960f983ca5ff Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 11:56:57 +0200 Subject: [PATCH 053/236] fix comments network-requester-setup.md --- .../operators/src/nodes/network-requester-setup.md | 10 +++++----- documentation/operators/src/nodes/troubleshooting.md | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/documentation/operators/src/nodes/network-requester-setup.md b/documentation/operators/src/nodes/network-requester-setup.md index ff94054657..05b588fa9a 100644 --- a/documentation/operators/src/nodes/network-requester-setup.md +++ b/documentation/operators/src/nodes/network-requester-setup.md @@ -3,9 +3,8 @@ > The Nym network requester was built in the [building nym](../binaries/building-nym.md) section. If you haven't yet built Nym and want to run the code, go there first. ```admonish info -As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-network-requester` can be ran as a part of [`nym-gateway`](./gateway-setup.md#initialising-gateway-with-network-requester). This combination is a basis of Nym exit gateway node - an essential piece in our new setup. Please read more in our [Project Smoosh FAQ](../faq/smoosh-faq.md) and [Exit Gateways Page](../legal/exit-gateway.md). We recommend operators to start shifting to that model instead of running gateway and network requester as two separated binaries. +As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` functionality which can be enabled [by the operator](./gateway-setup.md#initialising-gateway-with-network-requester). This combination is a basis of Nym exit gateway node - an essential piece in our new setup. Please read more in our [Project Smoosh FAQ](../faq/smoosh-faq.md) and [Exit Gateways Page](../legal/exit-gateway.md). We recommend operators begin to shift their setups to this new combined node, instead of operating two separate binaries. ``` - > Any syntax in `<>` brackets is a user's unique variable. Exchange with a corresponding name without the `<>` brackets. ## Current version @@ -104,6 +103,7 @@ matrix.org # alephium alephium.org + ``` ## Network Requester Directory @@ -115,7 +115,7 @@ You can find a list of Network requesters running the default whitelist in the [ ## Viewing command help ```admonish info -If you run your network requester as a part of your gateway according to the suggested setup, please skip the rest of this page and read about [exit gateway setup](./gateway-setup.md#initialising-gateway-with-network-requester). +If you run your network requester as a part of your exit gateway according to the suggested setup, please skip this part of the page and read about [exit gateway setup](./gateway-setup.md#initialising-gateway-with-network-requester) instead. ``` To begin, move to `/target/release` directory from which you run the node commands: @@ -167,7 +167,7 @@ Now that we have initialized our network-requester, we can start it with the fol The next thing to do is use your requester, share its address with friends (or whoever you want to help privacy-enhance their app traffic). Is this safe to do? If it was an open proxy, this would be unsafe, because any Nym user could make network requests to any system on the internet. -To make things a bit less stressful for administrators, the Network Requester drops all incoming requests by default. In order for it to make requests, you need to add specific domains to the `allowed.list` file at `$HOME/.nym/service-providers/network-requester/allowed.list` or if network requester is ran from the [gateway binary](./gateway-setup.md#initialising-gateway-with-network-requester), the `allowed.list` will be stored in `~/.nym/gateways//data/network-requester-data/allowed.list` +To make things a bit less stressful for administrators, the Network Requester drops all incoming requests by default. In order for it to make requests, you need to add specific domains to the `allowed.list` file at `$HOME/.nym/service-providers/network-requester/allowed.list` or if network requester is ran as a part of [exit gateway](./gateway-setup.md#initialising-gateway-with-network-requester), the `allowed.list` will be stored in `~/.nym/gateways//data/network-requester-data/allowed.list` ### Global vs local allow lists Your Network Requester will check for a domain against 2 lists before allowing traffic through for a particular domain or IP. @@ -187,7 +187,7 @@ How to go about this? Have a look in your nym-network-requester config directory # network requester binary ls -lt $HOME/.nym/service-providers/network-requester/*/data | grep "list" -# gateway with network requester binary +# exit gateway binary ls -lt $HOME/.nym/gateways/*/data/network-requester-data | grep "list" # returns: allowed.list unknown.list diff --git a/documentation/operators/src/nodes/troubleshooting.md b/documentation/operators/src/nodes/troubleshooting.md index 47de3c3a5e..ad3151092d 100644 --- a/documentation/operators/src/nodes/troubleshooting.md +++ b/documentation/operators/src/nodes/troubleshooting.md @@ -262,7 +262,7 @@ thread 'tokio-runtime-worker' panicked at 'Failed to create TCP listener: Os { c Then you need to `--announce-host ` and `--host ` on startup. This issue is addressed [above](./troubleshooting.md#missing-`announce-host`-flag) -### Can I use a port other than 1789 ? +### Can I use a port other than 1789? Yes! Here is what you will need to do: From f4a17ac6982dc1ef93faec6a8bcc29fdd29db34e Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 11:58:31 +0200 Subject: [PATCH 054/236] fix comments network-requester-setup.md --- documentation/operators/src/nodes/network-requester-setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/nodes/network-requester-setup.md b/documentation/operators/src/nodes/network-requester-setup.md index 05b588fa9a..aef7c1c3d2 100644 --- a/documentation/operators/src/nodes/network-requester-setup.md +++ b/documentation/operators/src/nodes/network-requester-setup.md @@ -22,7 +22,7 @@ If you have access to a server, you can run the network requester, which allows By default the network requester is **not** an open proxy (although it can be used as one). It uses a file called `allowed.list` (located in `~/.nym/service-providers/network-requester//`) as a whitelist for outbound requests. -**Note:** If you run network requester as a part of the gateway the `allowed.list` will be stored in `~/.nym/gateways/snus/data/network-requester-data/allowed.list`. +**Note:** If you run network requester as a part of the exit gateway (suggested setup) the `allowed.list` will be stored in `~/.nym/gateways//data/network-requester-data/allowed.list`. Any request to a URL which is not on this list will be blocked. From d79eda40a4404b2024176e65bd944a3068445dc0 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 12:03:19 +0200 Subject: [PATCH 055/236] fix comments network-requester-setup.md --- documentation/operators/src/nodes/network-requester-setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/nodes/network-requester-setup.md b/documentation/operators/src/nodes/network-requester-setup.md index aef7c1c3d2..5e7cd7969e 100644 --- a/documentation/operators/src/nodes/network-requester-setup.md +++ b/documentation/operators/src/nodes/network-requester-setup.md @@ -193,7 +193,7 @@ ls -lt $HOME/.nym/gateways/*/data/network-requester-data | grep "list" # returns: allowed.list unknown.list ``` -We already know that `allowed.list` is what lets requests go through. All unknown requests are logged to `unknown.list`. If you want to try using a new client type, just start the new application, point it at your local [socks client](https://nymtech.net/docs/clients/socks5-client.html) (configured to use your remote `nym-network-requester`), and keep copying URLs from `unknown.list` into `allowed.list` (it may take multiple tries until you get all of them, depending on the complexity of the application). Make sure to delete the copied ones in 'unknown.list' and restart your network requester or gateway with network requester! +We already know that `allowed.list` is what lets requests go through. All unknown requests are logged to `unknown.list`. If you want to try using a new client type, just start the new application, point it at your local [socks client](https://nymtech.net/docs/clients/socks5-client.html) (configured to use your remote `nym-network-requester`), and keep copying URLs from `unknown.list` into `allowed.list` (it may take multiple tries until you get all of them, depending on the complexity of the application). Make sure to delete the copied ones in `unknown.list` and restart your exit gateway or standalone network requester. > If you are adding custom domains, please note that whilst they may appear in the logs of your network-requester as something like `api-0.core.keybaseapi.com:443`, you **only need** to include the main domain name, in this instance `keybaseapi.com` From 26217f53ae6afa0c89397eb294cc9af3130334e6 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 12:10:44 +0200 Subject: [PATCH 056/236] fix comments troubleshooting.md --- documentation/operators/src/nodes/troubleshooting.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/documentation/operators/src/nodes/troubleshooting.md b/documentation/operators/src/nodes/troubleshooting.md index ad3151092d..1942dac60a 100644 --- a/documentation/operators/src/nodes/troubleshooting.md +++ b/documentation/operators/src/nodes/troubleshooting.md @@ -299,15 +299,13 @@ You don't have to do any additional configuration for your node to implement thi ### My gateway seems to be running but appears offline -Check if your [firewall status](./maintenance.md#configure-your-firewall) is active and if the needed ports are allowed. +Check your [firewall](./maintenance.md#configure-your-firewall) is active and if the necessary ports are open / allowed. -### My gateway (with network requester) "is still not online..." +### My exit gateway "is still not online..." -Remember the epoch takes up to 1h. It's important to run your node right after bonding so it responds positively on our API ping tests. Otherwise it may be blacklisted. +The Nyx chain epoch takes up to 60 min. To prevent the gateway getting blacklisted, it's important to run it right after the bonding process to return positive response our API testing it's routing score. -You may want to disconnect the network requester and let it run as a gatewy alone for some time to regain better routing score. - -If it won't help, simply un-bond, delete the config and initialize a new one. +You may want to disconnect the network requester and let it run as a gatewy alone for some time to regain better routing score and then areturn to the full [exit gateway finctionality](./gateway-setup.md#initialising-gateway-with-network-requester). ## Validators From 56e4b13e63d3a698cccd45dec3d9181e6edb7f92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 24 Oct 2023 11:15:38 +0100 Subject: [PATCH 057/236] re-exported additional types for tx queries (#4036) * re-exported additional types for tx queries * replaced source of 'query::Query' type from cosmrs to tendermint-rpc for wasm compatibility --- .../src/nyxd/cosmwasm_client/client_traits/query_client.rs | 2 +- common/client-libs/validator-client/src/nyxd/mod.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/client_traits/query_client.rs b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/client_traits/query_client.rs index 69e94b3387..a6ed3afddc 100644 --- a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/client_traits/query_client.rs +++ b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/client_traits/query_client.rs @@ -8,6 +8,7 @@ use crate::nyxd::cosmwasm_client::types::{ Account, CodeDetails, Contract, ContractCodeId, SequenceResponse, SimulateResponse, }; use crate::nyxd::error::NyxdError; +use crate::nyxd::Query; use crate::rpc::TendermintRpcClient; use async_trait::async_trait; use cosmrs::cosmwasm::{CodeInfoResponse, ContractCodeHistoryEntry}; @@ -35,7 +36,6 @@ use std::convert::TryFrom; use std::time::Duration; use tendermint_rpc::{ endpoint::{block::Response as BlockResponse, broadcast, tx::Response as TxResponse}, - query::Query, Order, }; diff --git a/common/client-libs/validator-client/src/nyxd/mod.rs b/common/client-libs/validator-client/src/nyxd/mod.rs index 10cca6de7e..e7d6650052 100644 --- a/common/client-libs/validator-client/src/nyxd/mod.rs +++ b/common/client-libs/validator-client/src/nyxd/mod.rs @@ -18,7 +18,7 @@ use crate::{DirectSigningReqwestRpcNyxdClient, QueryReqwestRpcNyxdClient, Reqwes use async_trait::async_trait; use cosmrs::cosmwasm; use cosmrs::tendermint::{abci, evidence::Evidence, Genesis}; -use cosmrs::tx::{Msg, Raw, SignDoc}; +use cosmrs::tx::{Raw, SignDoc}; use cosmwasm_std::Addr; use nym_network_defaults::{ChainDetails, NymNetworkDetails}; use serde::{de::DeserializeOwned, Serialize}; @@ -39,6 +39,7 @@ pub use cosmrs::tendermint::block::Height; pub use cosmrs::tendermint::hash::{self, Algorithm, Hash}; pub use cosmrs::tendermint::validator::Info as TendermintValidatorInfo; pub use cosmrs::tendermint::Time as TendermintTime; +pub use cosmrs::tx::Msg; pub use cosmrs::tx::{self}; pub use cosmrs::Coin as CosmosCoin; pub use cosmrs::Gas; @@ -47,6 +48,7 @@ pub use cosmwasm_std::Coin as CosmWasmCoin; pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment}; pub use tendermint_rpc::{ endpoint::{tx::Response as TxResponse, validators::Response as ValidatorResponse}, + query::Query, Paging, }; pub use tendermint_rpc::{Request, Response, SimpleRequest}; @@ -57,7 +59,6 @@ use crate::http_client; use crate::{DirectSigningHttpRpcNyxdClient, QueryHttpRpcNyxdClient}; #[cfg(feature = "http-client")] use cosmrs::rpc::{HttpClient, HttpClientUrl}; -use tendermint_rpc::query::Query; pub mod coin; pub mod contract_traits; From 42d3c3eec57cb1fa4ffd81e04d75275f56bb6aa0 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 24 Oct 2023 12:22:11 +0200 Subject: [PATCH 058/236] fix comments troubleshooting.md --- documentation/operators/src/nodes/troubleshooting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/nodes/troubleshooting.md b/documentation/operators/src/nodes/troubleshooting.md index 1942dac60a..7e2f37503d 100644 --- a/documentation/operators/src/nodes/troubleshooting.md +++ b/documentation/operators/src/nodes/troubleshooting.md @@ -236,7 +236,7 @@ Here is a sample of the `init` command example to create the mix node config. ./nym-mixnode init --id --host 0.0.0.0 --announce-host 85.160.12.13 ``` -- `--host 0.0.0.0` should work every time even if your local machine IPv4 address changes. For example on Monday your router gives your machine an address `192.168.0.13` and on Wednesday, the DHCP lease will end and you will be assigned `192.168.0.14`. Using `0.0.0.0` should avoid this without having to set any static IP in your router's configuration. +- `--host 0.0.0.0` should work every time even if your local machine IPv4 address changes. For example on Monday your router gives your machine an address `192.168.0.13` and on Wednesday, the [DHCP](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol) lease will end and you will be assigned `192.168.0.14`. Using `0.0.0.0` should avoid this without having to set any static IP in your router's configuration. - you can get your current IPv4 address by either using `curl ipinfo.io` if you're on MacOS or Linux or visiting [whatsmyip site](https://www.whatsmyip.org/). Simply copy it and use it as `--anounce-host` address. From 4533834177888cb7900709fc7f63bc0558521237 Mon Sep 17 00:00:00 2001 From: fmtabbara Date: Tue, 24 Oct 2023 11:28:33 +0100 Subject: [PATCH 059/236] add loading model on initial load --- nym-wallet/Cargo.lock | 121 +++++++++++++++++++++- nym-wallet/src/pages/delegation/index.tsx | 19 ++-- 2 files changed, 125 insertions(+), 15 deletions(-) diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 7b33510a97..a2922d8391 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -419,6 +419,29 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "845141a4fade3f790628b7daaaa298a25b204fb28907eb54febe5142db6ce653" +[[package]] +name = "boringtun" +version = "0.6.0" +source = "git+https://github.com/cloudflare/boringtun?rev=e1d6360d6ab4529fc942a078e4c54df107abe2ba#e1d6360d6ab4529fc942a078e4c54df107abe2ba" +dependencies = [ + "aead", + "base64 0.13.1", + "blake2 0.10.6", + "chacha20poly1305", + "hex", + "hmac 0.12.1", + "ip_network", + "ip_network_table", + "libc", + "nix", + "parking_lot", + "rand_core 0.6.4", + "ring", + "tracing", + "untrusted 0.9.0", + "x25519-dalek 2.0.0", +] + [[package]] name = "brotli" version = "3.3.4" @@ -593,6 +616,30 @@ dependencies = [ "keystream", ] +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher 0.4.4", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher 0.4.4", + "poly1305", + "zeroize", +] + [[package]] name = "cipher" version = "0.3.0" @@ -610,6 +657,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", + "zeroize", ] [[package]] @@ -2688,6 +2736,28 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "ip_network" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" + +[[package]] +name = "ip_network_table" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4099b7cfc5c5e2fe8c5edf3f6f7adf7a714c9cc697534f63a5a5da30397cb2c0" +dependencies = [ + "ip_network", + "ip_network_table-deps-treebitmap", +] + +[[package]] +name = "ip_network_table-deps-treebitmap" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e537132deb99c0eb4b752f0346b6a836200eaaa3516dd7e5514b63930a09e5d" + [[package]] name = "ipnet" version = "2.8.0" @@ -3098,6 +3168,18 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "libc", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -3428,11 +3510,11 @@ dependencies = [ "base64 0.21.4", "nym-bin-common", "nym-crypto", + "nym-wireguard-types", "schemars", "serde", "serde_json", "thiserror", - "x25519-dalek 2.0.0", ] [[package]] @@ -3484,7 +3566,6 @@ dependencies = [ "base64 0.21.4", "cosmrs", "cosmwasm-std", - "dashmap", "eyre", "hmac 0.12.1", "itertools 0.11.0", @@ -3602,6 +3683,19 @@ dependencies = [ "ts-rs", ] +[[package]] +name = "nym-wireguard-types" +version = "0.1.0" +dependencies = [ + "base64 0.21.4", + "boringtun", + "dashmap", + "nym-crypto", + "serde", + "thiserror", + "x25519-dalek 2.0.0", +] + [[package]] name = "nym_wallet" version = "1.2.9" @@ -4162,6 +4256,17 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash", +] + [[package]] name = "polyval" version = "0.6.1" @@ -4576,7 +4681,7 @@ dependencies = [ "libc", "once_cell", "spin", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] @@ -4723,7 +4828,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -6082,6 +6187,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.4.0" @@ -6343,7 +6454,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] diff --git a/nym-wallet/src/pages/delegation/index.tsx b/nym-wallet/src/pages/delegation/index.tsx index 7bcd6cda06..8f934cb83c 100644 --- a/nym-wallet/src/pages/delegation/index.tsx +++ b/nym-wallet/src/pages/delegation/index.tsx @@ -302,16 +302,15 @@ export const Delegation: FC<{ isStorybook?: boolean }> = ({ isStorybook }) => { }; const delegationsComponent = (delegationItems: TDelegations | undefined) => { - if (delegationItems && Boolean(delegationItems?.length)) { - return ( - - ); - } + return ( + + ); + return ( From 50e03d08bf09657cf4e1346e482a529ce9b990bc Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 24 Oct 2023 13:18:32 +0200 Subject: [PATCH 060/236] added info on post_process.sh --- documentation/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/documentation/README.md b/documentation/README.md index 59c5e32133..3defd29526 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -9,5 +9,4 @@ Each directory contains a readme with more information about running and contrib ## Scripts * `bump_versions.sh` allows you to update the ~~`platform_release_version` and~~ `wallet_release_version` variable~~s~~ in the `book.toml` of each mdbook project at once. You can also optionally update the `minimum_rust_version` as well. Helpful for lazy-updating when cutting a new version of the docs. * `build_all_to_dist.sh` is used by the `ci-dev.yml` and `cd-dev.yml` scripts for building all mdbook projects and moving the rendered html to `../dist/` to be rsynced with various servers. - - +* `post_process.sh` is a script called by the github CI and CD workflows to post process CSS/image/href links for serving several mdbooks from a subdirectory. From 8c54ebb6d1098a2dcb8b6115de4160ca61b6e324 Mon Sep 17 00:00:00 2001 From: Tommy Verrall <60836166+tommyv1987@users.noreply.github.com> Date: Tue, 24 Oct 2023 12:22:45 +0100 Subject: [PATCH 061/236] Update sandbox.env (#4040) --- envs/sandbox.env | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/envs/sandbox.env b/envs/sandbox.env index 2510e3c4f0..2ce9298766 100644 --- a/envs/sandbox.env +++ b/envs/sandbox.env @@ -17,10 +17,11 @@ COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n16a32stm6kknhq5cc8rx77elr66pygf2hfszw7wvpq74 GROUP_CONTRACT_ADDRESS=n1pd7kfgvr5tpcv0xnlv46c4jsq9jg2r799xxrcwqdm4l2jhq2pjwqrmz5ju MULTISIG_CONTRACT_ADDRESS=n14ph4e660eyqz0j36zlkaey4zgzexm5twkmjlqaequxr2cjm9eprqsmad6k COCONUT_DKG_CONTRACT_ADDRESS=n1ahg0erc2fs6xx3j5m8sfx3ryuzdjh6kf6qm9plsf865fltekyrfsesac6a +EPHEMERA_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0 NAME_SERVICE_CONTRACT_ADDRESS=n12ne7qtmdwd0j03t9t5es8md66wq4e5xg9neladrsag8fx3y89rcs36asfp SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS=n1ps5yutd7sufwg058qd7ac7ldnlazsvmhzqwucsfxmm445d70u8asqxpur4 STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0" EXPLORER_API=https://sandbox-explorer.nymtech.net/api NYXD="https://sandbox-validator1.nymtech.net" -NYM_API="https://sandbox-nym-api1.nymtech.net/api" \ No newline at end of file +NYM_API="https://sandbox-nym-api1.nymtech.net/api" From 732720c30654fc9a3e526623627a0413858828a7 Mon Sep 17 00:00:00 2001 From: Fouad Date: Tue, 24 Oct 2023 13:35:17 +0100 Subject: [PATCH 062/236] update frontend type for current vesting period (#4042) --- nym-wallet/src/components/Balance/VestingTimeline.tsx | 2 +- nym-wallet/src/components/Balance/cards/VestingSchedule.tsx | 2 +- ts-packages/types/src/types/rust/Period.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nym-wallet/src/components/Balance/VestingTimeline.tsx b/nym-wallet/src/components/Balance/VestingTimeline.tsx index cfb489056d..52e137f4c8 100644 --- a/nym-wallet/src/components/Balance/VestingTimeline.tsx +++ b/nym-wallet/src/components/Balance/VestingTimeline.tsx @@ -26,7 +26,7 @@ export const VestingTimeline: FCWithChildren<{ percentageComplete: number }> = ( const nextPeriod = typeof currentVestingPeriod === 'object' && !!vestingAccountInfo?.periods - ? Number(vestingAccountInfo?.periods[currentVestingPeriod.In + 1]?.start_time) + ? Number(vestingAccountInfo?.periods[currentVestingPeriod.in + 1]?.start_time) : undefined; return ( diff --git a/nym-wallet/src/components/Balance/cards/VestingSchedule.tsx b/nym-wallet/src/components/Balance/cards/VestingSchedule.tsx index b26b999970..e713565680 100644 --- a/nym-wallet/src/components/Balance/cards/VestingSchedule.tsx +++ b/nym-wallet/src/components/Balance/cards/VestingSchedule.tsx @@ -23,7 +23,7 @@ const columnsHeaders: Array<{ title: string; align: TableCellProps['align'] }> = const vestingPeriod = (current?: Period, original?: number) => { if (current === 'After') return 'Complete'; - if (typeof current === 'object' && typeof original === 'number') return `${current.In + 1}/${original}`; + if (typeof current === 'object' && typeof original === 'number') return `${current.in + 1}/${original}`; return 'N/A'; }; diff --git a/ts-packages/types/src/types/rust/Period.ts b/ts-packages/types/src/types/rust/Period.ts index 76a8876b31..2e0a752ee7 100644 --- a/ts-packages/types/src/types/rust/Period.ts +++ b/ts-packages/types/src/types/rust/Period.ts @@ -1,3 +1,3 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export type Period = 'Before' | { In: number } | 'After'; +export type Period = 'Before' | { in: number } | 'After'; From 2806931ca17198f9f3143f61a35e1eff6053f79c Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 24 Oct 2023 14:50:03 +0200 Subject: [PATCH 063/236] added new pages --- documentation/dev-portal/book.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/dev-portal/book.toml b/documentation/dev-portal/book.toml index d0dfbe0674..1012ec22f9 100644 --- a/documentation/dev-portal/book.toml +++ b/documentation/dev-portal/book.toml @@ -43,7 +43,7 @@ turn-off = true [preprocessor.admonish] command = "mdbook-admonish" -assets_version = "3.0.0" # do not edit: managed by `mdbook-admonish install` +assets_version = "2.0.1" # do not edit: managed by `mdbook-admonish install` # variables preprocessor: import variables into files # https://gitlab.com/tglman/mdbook-variables/ From 0e1548db72f019d076682d45b3a5f3e36e4973d5 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 24 Oct 2023 14:50:24 +0200 Subject: [PATCH 064/236] added new pages to summary --- documentation/dev-portal/src/SUMMARY.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/documentation/dev-portal/src/SUMMARY.md b/documentation/dev-portal/src/SUMMARY.md index 5dcbd3ba70..7c9836c58a 100644 --- a/documentation/dev-portal/src/SUMMARY.md +++ b/documentation/dev-portal/src/SUMMARY.md @@ -22,6 +22,13 @@ - [NymConnect Matrix](tutorials/matrix.md) - [NymConnect Telegram](tutorials/telegram.md) +# Code Examples + +- [Rust](examples/rust.md) +- [Typescript](examples/typescript.md) +- [Nym Demos](examples/demos.md) +- [Community Apps](examples/community-apps.md) + # Integrations - [Integration Options](integrations/integration-options.md) @@ -41,7 +48,7 @@ - [Preparing Your Service pt2](tutorials/cosmos-service/service-src.md) - [Querying the Chain](tutorials/cosmos-service/querying.md) - [Typescript](tutorials/typescript.md) - - [Simple Service Provider](tutorials/simple-service-provider/simple-service-provider.md) + - [[DEPRECATED] Simple Service Provider](tutorials/simple-service-provider/simple-service-provider.md) - [Tutorial Overview](tutorials/simple-service-provider/overview.md) - [Preparing Your User Client Environment](tutorials/simple-service-provider/preparating-env.md) - [Building Your User Client](tutorials/simple-service-provider/user-client.md) From 7b3a8d5bcd34d01aae9a6bc6b27632b448af74a0 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 24 Oct 2023 14:50:40 +0200 Subject: [PATCH 065/236] added new examples pages --- documentation/dev-portal/src/examples/community-apps.md | 1 + documentation/dev-portal/src/examples/demos.md | 1 + documentation/dev-portal/src/examples/rust.md | 1 + documentation/dev-portal/src/examples/typescript.md | 1 + 4 files changed, 4 insertions(+) create mode 100644 documentation/dev-portal/src/examples/community-apps.md create mode 100644 documentation/dev-portal/src/examples/demos.md create mode 100644 documentation/dev-portal/src/examples/rust.md create mode 100644 documentation/dev-portal/src/examples/typescript.md diff --git a/documentation/dev-portal/src/examples/community-apps.md b/documentation/dev-portal/src/examples/community-apps.md new file mode 100644 index 0000000000..b6c3fda9c6 --- /dev/null +++ b/documentation/dev-portal/src/examples/community-apps.md @@ -0,0 +1 @@ +# Community Apps diff --git a/documentation/dev-portal/src/examples/demos.md b/documentation/dev-portal/src/examples/demos.md new file mode 100644 index 0000000000..ddcf4dd8c4 --- /dev/null +++ b/documentation/dev-portal/src/examples/demos.md @@ -0,0 +1 @@ +# Nym Demos diff --git a/documentation/dev-portal/src/examples/rust.md b/documentation/dev-portal/src/examples/rust.md new file mode 100644 index 0000000000..2f1d5efed1 --- /dev/null +++ b/documentation/dev-portal/src/examples/rust.md @@ -0,0 +1 @@ +# Rust diff --git a/documentation/dev-portal/src/examples/typescript.md b/documentation/dev-portal/src/examples/typescript.md new file mode 100644 index 0000000000..42c9775801 --- /dev/null +++ b/documentation/dev-portal/src/examples/typescript.md @@ -0,0 +1 @@ +# Typescript From bd10b17272400e80638dce5946986c1ac3952857 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 24 Oct 2023 14:50:53 +0200 Subject: [PATCH 066/236] update plugin --- documentation/dev-portal/mdbook-admonish.css | 172 ++++++++++--------- 1 file changed, 92 insertions(+), 80 deletions(-) diff --git a/documentation/dev-portal/mdbook-admonish.css b/documentation/dev-portal/mdbook-admonish.css index e0a3365532..244bc9ade7 100644 --- a/documentation/dev-portal/mdbook-admonish.css +++ b/documentation/dev-portal/mdbook-admonish.css @@ -1,18 +1,31 @@ @charset "UTF-8"; :root { - --md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,"); - --md-details-icon: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--note: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--abstract: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--info: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--tip: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--success: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--question: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--warning: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--failure: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--danger: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--bug: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--example: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--quote: + url("data:image/svg+xml;charset=utf-8,"); + --md-details-icon: + url("data:image/svg+xml;charset=utf-8,"); } :is(.admonition) { @@ -62,7 +75,7 @@ a.admonition-anchor-link::before { content: "§"; } -:is(.admonition-title, summary.admonition-title) { +:is(.admonition-title, summary) { position: relative; min-height: 4rem; margin-block: 0; @@ -73,13 +86,13 @@ a.admonition-anchor-link::before { background-color: rgba(68, 138, 255, 0.1); display: flex; } -:is(.admonition-title, summary.admonition-title) p { +:is(.admonition-title, summary) p { margin: 0; } -html :is(.admonition-title, summary.admonition-title):last-child { +html :is(.admonition-title, summary):last-child { margin-bottom: 0; } -:is(.admonition-title, summary.admonition-title)::before { +:is(.admonition-title, summary)::before { position: absolute; top: 0.625em; inset-inline-start: 1.6rem; @@ -94,7 +107,7 @@ html :is(.admonition-title, summary.admonition-title):last-child { -webkit-mask-size: contain; content: ""; } -:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link { +:is(.admonition-title, summary):hover a.admonition-anchor-link { display: initial; } @@ -119,204 +132,204 @@ details[open].admonition > summary.admonition-title::after { transform: rotate(90deg); } -:is(.admonition):is(.admonish-note) { +:is(.admonition):is(.note) { border-color: #448aff; } -:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) { +:is(.note) > :is(.admonition-title, summary) { background-color: rgba(68, 138, 255, 0.1); } -:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before { +:is(.note) > :is(.admonition-title, summary)::before { background-color: #448aff; - mask-image: var(--md-admonition-icon--admonish-note); - -webkit-mask-image: var(--md-admonition-icon--admonish-note); + mask-image: var(--md-admonition-icon--note); + -webkit-mask-image: var(--md-admonition-icon--note); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) { +:is(.admonition):is(.abstract, .summary, .tldr) { border-color: #00b0ff; } -:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) { +:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary) { background-color: rgba(0, 176, 255, 0.1); } -:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before { +:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary)::before { background-color: #00b0ff; - mask-image: var(--md-admonition-icon--admonish-abstract); - -webkit-mask-image: var(--md-admonition-icon--admonish-abstract); + mask-image: var(--md-admonition-icon--abstract); + -webkit-mask-image: var(--md-admonition-icon--abstract); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-info, .admonish-todo) { +:is(.admonition):is(.info, .todo) { border-color: #00b8d4; } -:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) { +:is(.info, .todo) > :is(.admonition-title, summary) { background-color: rgba(0, 184, 212, 0.1); } -:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before { +:is(.info, .todo) > :is(.admonition-title, summary)::before { background-color: #00b8d4; - mask-image: var(--md-admonition-icon--admonish-info); - -webkit-mask-image: var(--md-admonition-icon--admonish-info); + mask-image: var(--md-admonition-icon--info); + -webkit-mask-image: var(--md-admonition-icon--info); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) { +:is(.admonition):is(.tip, .hint, .important) { border-color: #00bfa5; } -:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) { +:is(.tip, .hint, .important) > :is(.admonition-title, summary) { background-color: rgba(0, 191, 165, 0.1); } -:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before { +:is(.tip, .hint, .important) > :is(.admonition-title, summary)::before { background-color: #00bfa5; - mask-image: var(--md-admonition-icon--admonish-tip); - -webkit-mask-image: var(--md-admonition-icon--admonish-tip); + mask-image: var(--md-admonition-icon--tip); + -webkit-mask-image: var(--md-admonition-icon--tip); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) { +:is(.admonition):is(.success, .check, .done) { border-color: #00c853; } -:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) { +:is(.success, .check, .done) > :is(.admonition-title, summary) { background-color: rgba(0, 200, 83, 0.1); } -:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before { +:is(.success, .check, .done) > :is(.admonition-title, summary)::before { background-color: #00c853; - mask-image: var(--md-admonition-icon--admonish-success); - -webkit-mask-image: var(--md-admonition-icon--admonish-success); + mask-image: var(--md-admonition-icon--success); + -webkit-mask-image: var(--md-admonition-icon--success); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) { +:is(.admonition):is(.question, .help, .faq) { border-color: #64dd17; } -:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) { +:is(.question, .help, .faq) > :is(.admonition-title, summary) { background-color: rgba(100, 221, 23, 0.1); } -:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before { +:is(.question, .help, .faq) > :is(.admonition-title, summary)::before { background-color: #64dd17; - mask-image: var(--md-admonition-icon--admonish-question); - -webkit-mask-image: var(--md-admonition-icon--admonish-question); + mask-image: var(--md-admonition-icon--question); + -webkit-mask-image: var(--md-admonition-icon--question); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) { +:is(.admonition):is(.warning, .caution, .attention) { border-color: #ff9100; } -:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) { +:is(.warning, .caution, .attention) > :is(.admonition-title, summary) { background-color: rgba(255, 145, 0, 0.1); } -:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before { +:is(.warning, .caution, .attention) > :is(.admonition-title, summary)::before { background-color: #ff9100; - mask-image: var(--md-admonition-icon--admonish-warning); - -webkit-mask-image: var(--md-admonition-icon--admonish-warning); + mask-image: var(--md-admonition-icon--warning); + -webkit-mask-image: var(--md-admonition-icon--warning); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) { +:is(.admonition):is(.failure, .fail, .missing) { border-color: #ff5252; } -:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) { +:is(.failure, .fail, .missing) > :is(.admonition-title, summary) { background-color: rgba(255, 82, 82, 0.1); } -:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before { +:is(.failure, .fail, .missing) > :is(.admonition-title, summary)::before { background-color: #ff5252; - mask-image: var(--md-admonition-icon--admonish-failure); - -webkit-mask-image: var(--md-admonition-icon--admonish-failure); + mask-image: var(--md-admonition-icon--failure); + -webkit-mask-image: var(--md-admonition-icon--failure); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-danger, .admonish-error) { +:is(.admonition):is(.danger, .error) { border-color: #ff1744; } -:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) { +:is(.danger, .error) > :is(.admonition-title, summary) { background-color: rgba(255, 23, 68, 0.1); } -:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before { +:is(.danger, .error) > :is(.admonition-title, summary)::before { background-color: #ff1744; - mask-image: var(--md-admonition-icon--admonish-danger); - -webkit-mask-image: var(--md-admonition-icon--admonish-danger); + mask-image: var(--md-admonition-icon--danger); + -webkit-mask-image: var(--md-admonition-icon--danger); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-bug) { +:is(.admonition):is(.bug) { border-color: #f50057; } -:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) { +:is(.bug) > :is(.admonition-title, summary) { background-color: rgba(245, 0, 87, 0.1); } -:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before { +:is(.bug) > :is(.admonition-title, summary)::before { background-color: #f50057; - mask-image: var(--md-admonition-icon--admonish-bug); - -webkit-mask-image: var(--md-admonition-icon--admonish-bug); + mask-image: var(--md-admonition-icon--bug); + -webkit-mask-image: var(--md-admonition-icon--bug); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-example) { +:is(.admonition):is(.example) { border-color: #7c4dff; } -:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) { +:is(.example) > :is(.admonition-title, summary) { background-color: rgba(124, 77, 255, 0.1); } -:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before { +:is(.example) > :is(.admonition-title, summary)::before { background-color: #7c4dff; - mask-image: var(--md-admonition-icon--admonish-example); - -webkit-mask-image: var(--md-admonition-icon--admonish-example); + mask-image: var(--md-admonition-icon--example); + -webkit-mask-image: var(--md-admonition-icon--example); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-quote, .admonish-cite) { +:is(.admonition):is(.quote, .cite) { border-color: #9e9e9e; } -:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) { +:is(.quote, .cite) > :is(.admonition-title, summary) { background-color: rgba(158, 158, 158, 0.1); } -:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before { +:is(.quote, .cite) > :is(.admonition-title, summary)::before { background-color: #9e9e9e; - mask-image: var(--md-admonition-icon--admonish-quote); - -webkit-mask-image: var(--md-admonition-icon--admonish-quote); + mask-image: var(--md-admonition-icon--quote); + -webkit-mask-image: var(--md-admonition-icon--quote); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; @@ -327,8 +340,7 @@ details[open].admonition > summary.admonition-title::after { background-color: var(--sidebar-bg); } -.ayu :is(.admonition), -.coal :is(.admonition) { +.ayu :is(.admonition), .coal :is(.admonition) { background-color: var(--theme-hover); } From b26f70eb6a48c708cdf11815693c68ad3a6e5034 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 24 Oct 2023 14:51:05 +0200 Subject: [PATCH 067/236] stripped down + added new links --- .../src/infrastructure/node-types.md | 42 +++---------------- 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/documentation/dev-portal/src/infrastructure/node-types.md b/documentation/dev-portal/src/infrastructure/node-types.md index e864208cd3..c918c0e6d9 100644 --- a/documentation/dev-portal/src/infrastructure/node-types.md +++ b/documentation/dev-portal/src/infrastructure/node-types.md @@ -4,43 +4,11 @@ Discover the workings of Nym's privacy-enhancing mixnet infrastructure through t -### Mixnet Infrastructure - -There are few types of Nym infrastructure nodes: - -#### Mix Nodes -Mix nodes play a critical role in the Nym network by providing enhanced security and privacy to network content and metadata. They are part of the three-layer mixnet that ensures that communication remains anonymous and untraceable. Mix nodes receive `NYM` tokens as compensation for their quality of service, which is measured by the network validators. - -Mix nodes anonymously relay encrypted Sphinx packets between each other, adding an extra layer of protection by reordering and delaying the packets before forwarding them to the intended recipient. Additionally, cover traffic is maintained through mix nodes sending Sphinx packets to other mix nodes, making it appear as if there is a constant flow of user messages and further protecting the privacy of legitimate data packets. - -With the ability to hide, reorder and add a delay to network traffic, mix nodes make it difficult for attackers to perform time-based correlation attacks and deanonymize users. By consistently delivering high-quality service, mix nodes are rewarded with NYM tokens, reinforcing the integrity of the Nym network. - -#### Gateways -Gateways serve as the point of entry for user data into the mixnet, verifying that users have acquired sufficient NYM-based bandwidth credentials before allowing encrypted packets to be forwarded to mixnodes. They are also responsible for safeguarding against denial of service attacks and act as a message storage for users who may go offline. - -Gateways receive bandwidth credentials from users, which are periodically redeemed for `NYM` tokens as payment for their services. Users have the flexibility to choose a single gateway, split traffic across multiple gateways, run their own gateways, or a combination of these options. - -In addition, gateways also cache messages, functioning as an inbox for users who are offline. By providing secure, reliable access to the mixnet and ensuring that data remains protected, gateways play a crucial role in maintaining the integrity of the Nym network. - -#### Validators -Validators are essential to the security and integrity of the Nym network, tasked with several key responsibilities. They utilize proof-of-stake Sybil defense measures to secure the network and determine which nodes are included within it. Through their collaborative efforts, validators create Coconut threshold credentials which provide anonymous access to network data and resources. - -Validators also play a critical role in maintaining the Nym Cosmos blockchain, a secure, public ledger that records network-wide information such as node public information and keys, network configuration parameters, CosmWasm smart contracts, and `NYM` and credential transactions. - -#### Service Providers -Service Providers are a crucial aspect of the Nym infrastructure that support the application layer of the Nym network. Any application built with Nym will require a Service Provider, which can be created by anyone. Service Providers run a piece of binary code that enables them to handle requests from Nym users or other services, and then make requests to external servers on behalf of the users. - -For example, a Service Provider could receive a request to check a mail server and then forward the response to the user. The presence of Service Providers in the Nym network enhances its security and privacy, making it a reliable and robust platform for anonymous communication and data exchange. - ### Where do I go from here? 💭 -Maybe you would like to concentrate on building a application that uses the mixnet: +For more in-depth information on the network architecture, head to the [Network Overview page](https://nymtech.net/docs/architecture/network-overview.html). -* Explore the Tutorials section of the Developer Portal. Our in-depth tutorial on [Building a Simple Service Provider](../tutorials/simple-service-provider/simple-service-provider.md) give a good understanding of building User Clients and Service Providers in TypeScript, and how to configure Nym Websocket Clients for seamless communication with the mixnet. - -* Get started with using the Nym Mixnet quickly and easily by exploring the [Quickstart](../quickstart/overview.md) options, such a NymConnect, proxying traffic through the Nym Socks5 client, or dive into integrating Nym into your existing application with the [Integrations](../integrations/integration-options.md) section. - -Or perhaps you a developer that would like to run a infrastructure node such as a Gateway, Mix node or Network Requestor: -* Check out the [Network Overview](https://nymtech.net/docs/architecture/network-overview.html) docs page. - -* Take a look at our [Node Setup Guide](https://nymtech.net/operators/nodes/setup-guides.html) with our Nym Docs, containing setup guides for setting up you own infrastructure node. +If you would like to concentrate on building an application that uses the mixnet: +* Get started with using the Nym Mixnet quickly and easily by exploring the [Quickstart](../quickstart/overview.md) options. +* Go the [Tutorials](../tutorials) section . +* Check out examples of [Community Apps](../community-resources/community-applications-and-guides.md). From 0347a2bd892524fb07cfa8ab8cec8fb977f4e121 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 24 Oct 2023 14:51:15 +0200 Subject: [PATCH 068/236] added deprecation warning --- .../simple-service-provider/simple-service-provider.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/documentation/dev-portal/src/tutorials/simple-service-provider/simple-service-provider.md b/documentation/dev-portal/src/tutorials/simple-service-provider/simple-service-provider.md index b08d988de2..ece2427041 100644 --- a/documentation/dev-portal/src/tutorials/simple-service-provider/simple-service-provider.md +++ b/documentation/dev-portal/src/tutorials/simple-service-provider/simple-service-provider.md @@ -1,5 +1,12 @@ # Building a Simple Service Provider +```admonish warning +This tutorial was written before the creation of the [Typescript SDK](https://sdk.nymtech.net), and involves running a Nym Client alongside your application processes, instead of relying on the SDK to integrate the Client process into your application logic. + +As such, although this tutorial is still a valid way of approaching building on Nym, it is a little less streamlined than it could be. + +A more streamlined rewrite of this tutorial will be coming soon. +``` This tutorial is the best place to start for developers new to Nym. You will learn how to build a minimum viable privacy-enabled application (PEApp) able to send and receive traffic via the mixnet. This tutorial is less about building an immediately useful application, and more about beginning to understand: From 15af5511399fd1cb1c2abca908e8a7d4686b4e9e Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 24 Oct 2023 15:03:58 +0200 Subject: [PATCH 069/236] smol reword --- documentation/dev-portal/src/infrastructure/node-types.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/dev-portal/src/infrastructure/node-types.md b/documentation/dev-portal/src/infrastructure/node-types.md index c918c0e6d9..ba1a127d37 100644 --- a/documentation/dev-portal/src/infrastructure/node-types.md +++ b/documentation/dev-portal/src/infrastructure/node-types.md @@ -6,9 +6,9 @@ Discover the workings of Nym's privacy-enhancing mixnet infrastructure through t ### Where do I go from here? 💭 -For more in-depth information on the network architecture, head to the [Network Overview page](https://nymtech.net/docs/architecture/network-overview.html). +For more in-depth information on the network architecture, head to the [Network Overview page](https://nymtech.net/docs/architecture/network-overview.html), and check out the [Operators book](https://nymtech.net/operators) if you want to run a node yourself. If you would like to concentrate on building an application that uses the mixnet: -* Get started with using the Nym Mixnet quickly and easily by exploring the [Quickstart](../quickstart/overview.md) options. -* Go the [Tutorials](../tutorials) section . +* Explore the [Quickstart](../quickstart/overview.md) options. * Check out examples of [Community Apps](../community-resources/community-applications-and-guides.md). +* Run through one of the [tutorials](../tutorials). From d94a0454ae11acee525916d7243088658fbb898b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 24 Oct 2023 16:04:27 +0200 Subject: [PATCH 070/236] wg: bounded channels (#4037) * Make peer event channel bounded * Make tun task channel bounded --- common/wireguard/src/active_peers.rs | 10 +++++----- common/wireguard/src/lib.rs | 4 ++-- common/wireguard/src/packet_relayer.rs | 12 ++++++------ common/wireguard/src/platform/linux/tun_device.rs | 10 ++++------ common/wireguard/src/tun_task_channel.rs | 10 +++++----- common/wireguard/src/udp_listener.rs | 15 +++++++++------ 6 files changed, 31 insertions(+), 30 deletions(-) diff --git a/common/wireguard/src/active_peers.rs b/common/wireguard/src/active_peers.rs index 6973d29be1..a22453c861 100644 --- a/common/wireguard/src/active_peers.rs +++ b/common/wireguard/src/active_peers.rs @@ -11,12 +11,12 @@ use crate::event::Event; // Channels that are used to communicate with the various tunnels #[derive(Clone)] -pub struct PeerEventSender(mpsc::UnboundedSender); -pub(crate) struct PeerEventReceiver(mpsc::UnboundedReceiver); +pub struct PeerEventSender(mpsc::Sender); +pub(crate) struct PeerEventReceiver(mpsc::Receiver); impl PeerEventSender { - pub(crate) fn send(&self, event: Event) -> Result<(), mpsc::error::SendError> { - self.0.send(event) + pub(crate) async fn send(&self, event: Event) -> Result<(), mpsc::error::SendError> { + self.0.send(event).await } } @@ -27,7 +27,7 @@ impl PeerEventReceiver { } pub(crate) fn peer_event_channel() -> (PeerEventSender, PeerEventReceiver) { - let (tx, rx) = mpsc::unbounded_channel(); + let (tx, rx) = mpsc::channel(16); (PeerEventSender(tx), PeerEventReceiver(rx)) } diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index cd13ba6937..dc226c56fd 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -33,10 +33,10 @@ pub async fn start_wireguard( gateway_client_registry: Arc, ) -> Result<(), Box> { // We can either index peers by their IP like standard wireguard - let peers_by_ip = Arc::new(std::sync::Mutex::new(network_table::NetworkTable::new())); + let peers_by_ip = Arc::new(tokio::sync::Mutex::new(network_table::NetworkTable::new())); // ... or by their tunnel tag, which is a random number assigned to them - let peers_by_tag = Arc::new(std::sync::Mutex::new(wg_tunnel::PeersByTag::new())); + let peers_by_tag = Arc::new(tokio::sync::Mutex::new(wg_tunnel::PeersByTag::new())); // Start the tun device that is used to relay traffic outbound let (tun, tun_task_tx, tun_task_response_rx) = tun_device::TunDevice::new(peers_by_ip.clone()); diff --git a/common/wireguard/src/packet_relayer.rs b/common/wireguard/src/packet_relayer.rs index 40d49d5d37..c37af0648e 100644 --- a/common/wireguard/src/packet_relayer.rs +++ b/common/wireguard/src/packet_relayer.rs @@ -32,14 +32,14 @@ pub(crate) struct PacketRelayer { tun_task_response_rx: TunTaskResponseRx, // After receiving from the tun device, relay back to the correct tunnel - peers_by_tag: Arc>>, + peers_by_tag: Arc>>, } impl PacketRelayer { pub(crate) fn new( tun_task_tx: TunTaskTx, tun_task_response_rx: TunTaskResponseRx, - peers_by_tag: Arc>>, + peers_by_tag: Arc>>, ) -> (Self, PacketRelaySender) { let (packet_tx, packet_rx) = packet_relay_channel(); ( @@ -58,13 +58,13 @@ impl PacketRelayer { tokio::select! { Some((tag, packet)) = self.packet_rx.0.recv() => { log::info!("Sent packet to tun device with tag: {tag}"); - self.tun_task_tx.send((tag, packet)).unwrap(); + self.tun_task_tx.send((tag, packet)).await.tap_err(|e| log::error!("{e}")).ok(); }, Some((tag, packet)) = self.tun_task_response_rx.recv() => { log::info!("Received response from tun device with tag: {tag}"); - self.peers_by_tag.lock().unwrap().get(&tag).and_then(|tx| { - tx.send(Event::Ip(packet.into())).tap_err(|e| log::error!("{e}")).ok() - }); + if let Some(tx) = self.peers_by_tag.lock().await.get(&tag) { + tx.send(Event::Ip(packet.into())).await.tap_err(|e| log::error!("{e}")).ok(); + } } } } diff --git a/common/wireguard/src/platform/linux/tun_device.rs b/common/wireguard/src/platform/linux/tun_device.rs index cc449112bc..348abdb609 100644 --- a/common/wireguard/src/platform/linux/tun_device.rs +++ b/common/wireguard/src/platform/linux/tun_device.rs @@ -43,7 +43,7 @@ pub struct TunDevice { tun_task_response_tx: TunTaskResponseTx, // The routing table, as how wireguard does it - peers_by_ip: Arc>, + peers_by_ip: Arc>, // This is an alternative to the routing table, where we just match outgoing source IP with // incoming destination IP. @@ -52,7 +52,7 @@ pub struct TunDevice { impl TunDevice { pub fn new( - peers_by_ip: Arc>, + peers_by_ip: Arc>, ) -> (Self, TunTaskTx, TunTaskResponseRx) { let tun = setup_tokio_tun_device( format!("{TUN_BASE_NAME}%d").as_str(), @@ -123,14 +123,12 @@ impl TunDevice { // This is how wireguard does it, by consulting the AllowedIPs table. if false { - let Ok(peers) = self.peers_by_ip.lock() else { - log::error!("Failed to lock peers_by_ip, aborting tun device read"); - return; - }; + let peers = self.peers_by_ip.lock().await; if let Some(peer_tx) = peers.longest_match(dst_addr).map(|(_, tx)| tx) { log::info!("Forward packet to wg tunnel"); peer_tx .send(Event::Ip(packet.to_vec().into())) + .await .tap_err(|err| log::error!("{err}")) .ok(); return; diff --git a/common/wireguard/src/tun_task_channel.rs b/common/wireguard/src/tun_task_channel.rs index 3ecc6a76b4..1cbd6985da 100644 --- a/common/wireguard/src/tun_task_channel.rs +++ b/common/wireguard/src/tun_task_channel.rs @@ -3,15 +3,15 @@ use tokio::sync::mpsc; pub(crate) type TunTaskPayload = (u64, Vec); #[derive(Clone)] -pub struct TunTaskTx(mpsc::UnboundedSender); -pub(crate) struct TunTaskRx(mpsc::UnboundedReceiver); +pub struct TunTaskTx(mpsc::Sender); +pub(crate) struct TunTaskRx(mpsc::Receiver); impl TunTaskTx { - pub(crate) fn send( + pub(crate) async fn send( &self, data: TunTaskPayload, ) -> Result<(), tokio::sync::mpsc::error::SendError> { - self.0.send(data) + self.0.send(data).await } } @@ -22,7 +22,7 @@ impl TunTaskRx { } pub(crate) fn tun_task_channel() -> (TunTaskTx, TunTaskRx) { - let (tun_task_tx, tun_task_rx) = tokio::sync::mpsc::unbounded_channel(); + let (tun_task_tx, tun_task_rx) = tokio::sync::mpsc::channel(16); (TunTaskTx(tun_task_tx), TunTaskRx(tun_task_rx)) } diff --git a/common/wireguard/src/udp_listener.rs b/common/wireguard/src/udp_listener.rs index 5c04c010a4..8e32325c36 100644 --- a/common/wireguard/src/udp_listener.rs +++ b/common/wireguard/src/udp_listener.rs @@ -50,10 +50,10 @@ pub struct WgUdpListener { registered_peers: RegisteredPeers, // The routing table, as defined by wireguard - peers_by_ip: Arc>, + peers_by_ip: Arc>, // ... or alternatively we can map peers by their tag - peers_by_tag: Arc>, + peers_by_tag: Arc>, // The UDP socket to the peer udp: Arc, @@ -70,8 +70,8 @@ pub struct WgUdpListener { impl WgUdpListener { pub async fn new( packet_tx: PacketRelaySender, - peers_by_ip: Arc>, - peers_by_tag: Arc>, + peers_by_ip: Arc>, + peers_by_tag: Arc>, gateway_client_registry: Arc, ) -> Result> { let wg_address = SocketAddr::new(WG_ADDRESS.parse().unwrap(), WG_PORT); @@ -143,6 +143,7 @@ impl WgUdpListener { log::info!("udp: received {len} bytes from {addr} from known peer"); peer_tx .send(Event::Wg(buf[..len].to_vec().into())) + .await .tap_err(|e| log::error!("{e}")) .ok(); continue; @@ -186,6 +187,7 @@ impl WgUdpListener { // We found the peer as connected, even though the addr was not known log::info!("udp: received {len} bytes from {addr} which is a known peer with unknown addr"); peer_tx.send(Event::WgVerified(buf[..len].to_vec().into())) + .await .tap_err(|err| log::error!("{err}")) .ok(); } else { @@ -205,10 +207,11 @@ impl WgUdpListener { self.packet_tx.clone(), ); - self.peers_by_ip.lock().unwrap().insert(registered_peer.allowed_ips, peer_tx.clone()); - self.peers_by_tag.lock().unwrap().insert(tag, peer_tx.clone()); + self.peers_by_ip.lock().await.insert(registered_peer.allowed_ips, peer_tx.clone()); + self.peers_by_tag.lock().await.insert(tag, peer_tx.clone()); peer_tx.send(Event::Wg(buf[..len].to_vec().into())) + .await .tap_err(|e| log::error!("{e}")) .ok(); From af892619922caf79592dba95c2874d45a23bf651 Mon Sep 17 00:00:00 2001 From: pierre Date: Tue, 24 Oct 2023 16:08:12 +0200 Subject: [PATCH 071/236] add gh ci workflows --- .github/workflows/ci-nym-vpn-ui-js.yml | 43 +++++++++++++++++ .github/workflows/ci-nym-vpn-ui-rust.yml | 60 ++++++++++++++++++++++++ nym-vpn/ui/package.json | 4 +- 3 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/ci-nym-vpn-ui-js.yml create mode 100644 .github/workflows/ci-nym-vpn-ui-rust.yml diff --git a/.github/workflows/ci-nym-vpn-ui-js.yml b/.github/workflows/ci-nym-vpn-ui-js.yml new file mode 100644 index 0000000000..12e18760d4 --- /dev/null +++ b/.github/workflows/ci-nym-vpn-ui-js.yml @@ -0,0 +1,43 @@ +name: ci-nym-vpn-ui-js + +on: + push: + paths: + - 'nym-vpn/ui/src/**' + - 'nym-vpn/ui/package.json' + - 'nym-vpn/ui/index.html' + pull_request: + paths: + - 'nym-vpn/ui/src/**' + - 'nym-vpn/ui/package.json' + - 'nym-vpn/ui/index.html' + +jobs: + check: + runs-on: [ self-hosted, custom-linux ] + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Node + uses: actions/setup-node@v3 + with: + node-version: 18 + - name: Install Yarn + run: npm install -g yarn + - name: Install dependencies + run: yarn + - name: Type-check + working-directory: nym-vpn/ui + run: yarn typecheck + - name: Check lint + working-directory: nym-vpn/ui + run: yarn lint + - name: Check formatting + working-directory: nym-vpn/ui + run: yarn fmt:check +# - name: Run tests +# working-directory: nym-vpn/ui +# run: yarn test + - name: Check build + working-directory: nym-vpn/ui + run: yarn build diff --git a/.github/workflows/ci-nym-vpn-ui-rust.yml b/.github/workflows/ci-nym-vpn-ui-rust.yml new file mode 100644 index 0000000000..8217e3fae8 --- /dev/null +++ b/.github/workflows/ci-nym-vpn-ui-rust.yml @@ -0,0 +1,60 @@ +name: ci-nym-vpn-ui-rust + +on: + push: + paths: + - 'nym-vpn/ui/src-tauri/**' + pull_request: + paths: + - 'nym-vpn/ui/src-tauri/**' + +jobs: + build: + runs-on: [self-hosted, custom-linux] + env: + CARGO_TERM_COLOR: always + CARGOTOML_PATH: nym-vpn/ui/src-tauri/Cargo.toml + steps: + - name: Install Dependencies (Linux) + run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libayatana-appindicator3-dev + continue-on-error: true + + - name: Checkout + uses: actions/checkout@v4 + + - name: Install rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + components: rustfmt, clippy + + - name: Check build + working-directory: nym-vpn/ui/src-tauri + run: cargo build --release --lib --features custom-protocol + +# - name: Run all tests +# uses: actions-rs/cargo@v1 +# with: +# command: test +# args: --manifest-path nym-connect/desktop/Cargo.toml --workspace + + - name: Check formatting + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --manifest-path $CARGOTOML_PATH --all -- --check + + - uses: actions-rs/clippy-check@v1 + name: Clippy checks + continue-on-error: true + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --manifest-path $CARGOTOML_PATH --workspace --all-features + + - name: Run clippy + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --manifest-path $CARGOTOML_PATH --workspace --all-features -- -D warnings diff --git a/nym-vpn/ui/package.json b/nym-vpn/ui/package.json index 7d49d0ca36..2570661bcc 100644 --- a/nym-vpn/ui/package.json +++ b/nym-vpn/ui/package.json @@ -12,8 +12,8 @@ "preview": "vite preview", "lint": "eslint --ext .ts,.tsx src/", "lint:fix": "eslint --ext .js,.ts --fix src/", - "fmt": "prettier --check --ignore-unknown \"**/*\"", - "fmt:fix": "prettier --write --ignore-unknown \"**/*\"", + "fmt": "prettier --write --ignore-unknown \"**/*\"", + "fmt:check": "prettier --check --ignore-unknown \"**/*\"", "typecheck": "tsc --noEmit", "tauri": "tauri" }, From 67f13be3f79a321826464bd7811b6600fd1e7f3f Mon Sep 17 00:00:00 2001 From: pierre Date: Tue, 24 Oct 2023 16:11:57 +0200 Subject: [PATCH 072/236] fix ci wip --- .github/workflows/ci-nym-vpn-ui-js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-nym-vpn-ui-js.yml b/.github/workflows/ci-nym-vpn-ui-js.yml index 12e18760d4..acf62a8907 100644 --- a/.github/workflows/ci-nym-vpn-ui-js.yml +++ b/.github/workflows/ci-nym-vpn-ui-js.yml @@ -23,7 +23,7 @@ jobs: with: node-version: 18 - name: Install Yarn - run: npm install -g yarn + run: npm install -g yarn typescript - name: Install dependencies run: yarn - name: Type-check From 71e9fa178d2a7c0229d9a019300ee35625054184 Mon Sep 17 00:00:00 2001 From: pierre Date: Tue, 24 Oct 2023 16:15:30 +0200 Subject: [PATCH 073/236] fix ci wip --- .github/workflows/ci-nym-vpn-ui-js.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-nym-vpn-ui-js.yml b/.github/workflows/ci-nym-vpn-ui-js.yml index acf62a8907..5c3d286244 100644 --- a/.github/workflows/ci-nym-vpn-ui-js.yml +++ b/.github/workflows/ci-nym-vpn-ui-js.yml @@ -23,8 +23,9 @@ jobs: with: node-version: 18 - name: Install Yarn - run: npm install -g yarn typescript + run: npm install -g yarn - name: Install dependencies + working-directory: nym-vpn/ui run: yarn - name: Type-check working-directory: nym-vpn/ui From a618668b63f2d16eb40312778575849b04308a5f Mon Sep 17 00:00:00 2001 From: pierre Date: Tue, 24 Oct 2023 16:37:05 +0200 Subject: [PATCH 074/236] fix ci wip --- .github/workflows/ci-nym-vpn-ui-rust.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci-nym-vpn-ui-rust.yml b/.github/workflows/ci-nym-vpn-ui-rust.yml index 8217e3fae8..8db77ad812 100644 --- a/.github/workflows/ci-nym-vpn-ui-rust.yml +++ b/.github/workflows/ci-nym-vpn-ui-rust.yml @@ -30,6 +30,10 @@ jobs: override: true components: rustfmt, clippy + - name: Prepare build + working-directory: nym-vpn/ui/ + run: mkdir dist + - name: Check build working-directory: nym-vpn/ui/src-tauri run: cargo build --release --lib --features custom-protocol From b131de3beadc98b1b52253ae107c80fdd15b24a4 Mon Sep 17 00:00:00 2001 From: pierre Date: Tue, 24 Oct 2023 16:44:36 +0200 Subject: [PATCH 075/236] fix ci wip --- .github/workflows/ci-nym-vpn-ui-rust.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-nym-vpn-ui-rust.yml b/.github/workflows/ci-nym-vpn-ui-rust.yml index 8db77ad812..9f21147c30 100644 --- a/.github/workflows/ci-nym-vpn-ui-rust.yml +++ b/.github/workflows/ci-nym-vpn-ui-rust.yml @@ -13,7 +13,7 @@ jobs: runs-on: [self-hosted, custom-linux] env: CARGO_TERM_COLOR: always - CARGOTOML_PATH: nym-vpn/ui/src-tauri/Cargo.toml + CARGOTOML_PATH: ./nym-vpn/ui/src-tauri/Cargo.toml steps: - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libayatana-appindicator3-dev @@ -42,23 +42,23 @@ jobs: # uses: actions-rs/cargo@v1 # with: # command: test -# args: --manifest-path nym-connect/desktop/Cargo.toml --workspace +# args: --manifest-path ${{ env.CARGOTOML_PATH }} --workspace - name: Check formatting uses: actions-rs/cargo@v1 with: command: fmt - args: --manifest-path $CARGOTOML_PATH --all -- --check + args: --manifest-path ${{ env.CARGOTOML_PATH }} --all -- --check - uses: actions-rs/clippy-check@v1 name: Clippy checks continue-on-error: true with: token: ${{ secrets.GITHUB_TOKEN }} - args: --manifest-path $CARGOTOML_PATH --workspace --all-features + args: --manifest-path ${{ env.CARGOTOML_PATH }} --workspace --all-features - name: Run clippy uses: actions-rs/cargo@v1 with: command: clippy - args: --manifest-path $CARGOTOML_PATH --workspace --all-features -- -D warnings + args: --manifest-path ${{ env.CARGOTOML_PATH }} --workspace --all-features -- -D warnings From 6eac899167374a715827b357d8972daca84778f3 Mon Sep 17 00:00:00 2001 From: fmtabbara Date: Tue, 24 Oct 2023 16:14:25 +0100 Subject: [PATCH 076/236] update bond page link --- nym-wallet/Cargo.lock | 121 ++++++++++++++++++++- nym-wallet/src/components/Bonding/Bond.tsx | 2 +- 2 files changed, 117 insertions(+), 6 deletions(-) diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 7b33510a97..a2922d8391 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -419,6 +419,29 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "845141a4fade3f790628b7daaaa298a25b204fb28907eb54febe5142db6ce653" +[[package]] +name = "boringtun" +version = "0.6.0" +source = "git+https://github.com/cloudflare/boringtun?rev=e1d6360d6ab4529fc942a078e4c54df107abe2ba#e1d6360d6ab4529fc942a078e4c54df107abe2ba" +dependencies = [ + "aead", + "base64 0.13.1", + "blake2 0.10.6", + "chacha20poly1305", + "hex", + "hmac 0.12.1", + "ip_network", + "ip_network_table", + "libc", + "nix", + "parking_lot", + "rand_core 0.6.4", + "ring", + "tracing", + "untrusted 0.9.0", + "x25519-dalek 2.0.0", +] + [[package]] name = "brotli" version = "3.3.4" @@ -593,6 +616,30 @@ dependencies = [ "keystream", ] +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher 0.4.4", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher 0.4.4", + "poly1305", + "zeroize", +] + [[package]] name = "cipher" version = "0.3.0" @@ -610,6 +657,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", + "zeroize", ] [[package]] @@ -2688,6 +2736,28 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "ip_network" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" + +[[package]] +name = "ip_network_table" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4099b7cfc5c5e2fe8c5edf3f6f7adf7a714c9cc697534f63a5a5da30397cb2c0" +dependencies = [ + "ip_network", + "ip_network_table-deps-treebitmap", +] + +[[package]] +name = "ip_network_table-deps-treebitmap" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e537132deb99c0eb4b752f0346b6a836200eaaa3516dd7e5514b63930a09e5d" + [[package]] name = "ipnet" version = "2.8.0" @@ -3098,6 +3168,18 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "libc", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -3428,11 +3510,11 @@ dependencies = [ "base64 0.21.4", "nym-bin-common", "nym-crypto", + "nym-wireguard-types", "schemars", "serde", "serde_json", "thiserror", - "x25519-dalek 2.0.0", ] [[package]] @@ -3484,7 +3566,6 @@ dependencies = [ "base64 0.21.4", "cosmrs", "cosmwasm-std", - "dashmap", "eyre", "hmac 0.12.1", "itertools 0.11.0", @@ -3602,6 +3683,19 @@ dependencies = [ "ts-rs", ] +[[package]] +name = "nym-wireguard-types" +version = "0.1.0" +dependencies = [ + "base64 0.21.4", + "boringtun", + "dashmap", + "nym-crypto", + "serde", + "thiserror", + "x25519-dalek 2.0.0", +] + [[package]] name = "nym_wallet" version = "1.2.9" @@ -4162,6 +4256,17 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash", +] + [[package]] name = "polyval" version = "0.6.1" @@ -4576,7 +4681,7 @@ dependencies = [ "libc", "once_cell", "spin", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] @@ -4723,7 +4828,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -6082,6 +6187,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.4.0" @@ -6343,7 +6454,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] diff --git a/nym-wallet/src/components/Bonding/Bond.tsx b/nym-wallet/src/components/Bonding/Bond.tsx index 304543cd51..d240b31035 100644 --- a/nym-wallet/src/components/Bonding/Bond.tsx +++ b/nym-wallet/src/components/Bonding/Bond.tsx @@ -21,7 +21,7 @@ export const Bond = ({ > Bond a mix node or a gateway. Learn how to set up and run a node{' '} - + here From caff2aa9d2ae2c86a4ce19df6b1fbcf477dc1ba4 Mon Sep 17 00:00:00 2001 From: fmtabbara Date: Wed, 25 Oct 2023 10:02:08 +0100 Subject: [PATCH 077/236] format delegations summary --- .../src/components/Rewards/RewardsSummary.tsx | 77 +++++++++++++------ 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/nym-wallet/src/components/Rewards/RewardsSummary.tsx b/nym-wallet/src/components/Rewards/RewardsSummary.tsx index c6e48b395c..75f7da4a7b 100644 --- a/nym-wallet/src/components/Rewards/RewardsSummary.tsx +++ b/nym-wallet/src/components/Rewards/RewardsSummary.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { CircularProgress, Stack, Typography } from '@mui/material'; +import { CircularProgress, Stack, StackProps, Typography, useMediaQuery } from '@mui/material'; import { useTheme } from '@mui/material/styles'; import { useDelegationContext } from 'src/context/delegations'; import { InfoTooltip } from '../InfoToolTip'; @@ -9,34 +9,63 @@ export const RewardsSummary: FCWithChildren<{ totalDelegation?: string; totalRewards?: string; }> = ({ isLoading, totalDelegation, totalRewards }) => { - const theme = useTheme(); - const { totalDelegationsAndRewards } = useDelegationContext(); return ( - - - Total delegations: - - {isLoading ? : totalDelegationsAndRewards || '-'} - - - - - Original delegations: - - {isLoading ? : totalDelegation || '-'} - - - - - Total rewards: - - {isLoading ? : totalRewards || '-'} - - + + } + /> + } + /> + + } + /> ); }; + +const RewardSummaryField = ({ + title, + value, + Tooltip, + isLoading, +}: { + title: string; + value: string; + Tooltip?: React.ReactNode; + isLoading?: boolean; +}) => { + const breakpoint = useMediaQuery(useTheme().breakpoints.down('xl')); + const alignProps: { gap: number; direction: StackProps['direction'] } = { + gap: breakpoint ? 0 : 1, + direction: breakpoint ? 'column' : 'row', + }; + + return ( + + + {Tooltip} + {title}: + + + {isLoading ? : value} + + + ); +}; From e9449b9135f11f48de9fee4a95cc1260726a6305 Mon Sep 17 00:00:00 2001 From: fmtabbara Date: Wed, 25 Oct 2023 10:02:21 +0100 Subject: [PATCH 078/236] fix delegations loading page --- nym-wallet/src/pages/delegation/index.tsx | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/nym-wallet/src/pages/delegation/index.tsx b/nym-wallet/src/pages/delegation/index.tsx index 8f934cb83c..c6ef1c26d6 100644 --- a/nym-wallet/src/pages/delegation/index.tsx +++ b/nym-wallet/src/pages/delegation/index.tsx @@ -19,6 +19,7 @@ import { DelegationListItemActions } from '../../components/Delegation/Delegatio import { RedeemModal } from '../../components/Rewards/RedeemModal'; import { DelegationModal, DelegationModalProps } from '../../components/Delegation/DelegationModal'; import { backDropStyles, modalStyles } from '../../../.storybook/storiesStyles'; +import { LoadingModal } from 'src/components/Modals/LoadingModal'; const storybookStyles = (theme: Theme, isStorybook?: boolean, backdropProps?: object) => isStorybook @@ -302,14 +303,16 @@ export const Delegation: FC<{ isStorybook?: boolean }> = ({ isStorybook }) => { }; const delegationsComponent = (delegationItems: TDelegations | undefined) => { - return ( - - ); + if (delegationItems && Boolean(delegationItems?.length)) { + return ( + + ); + } return ( @@ -342,6 +345,10 @@ export const Delegation: FC<{ isStorybook?: boolean }> = ({ isStorybook }) => { ); }; + if (isLoading) { + return ; + } + return ( <> From b72649e2967958c7731bce38d03a248afc3471b0 Mon Sep 17 00:00:00 2001 From: fmtabbara Date: Wed, 25 Oct 2023 10:26:04 +0100 Subject: [PATCH 079/236] fix linting --- nym-wallet/src/pages/delegation/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nym-wallet/src/pages/delegation/index.tsx b/nym-wallet/src/pages/delegation/index.tsx index c6ef1c26d6..64a24b41db 100644 --- a/nym-wallet/src/pages/delegation/index.tsx +++ b/nym-wallet/src/pages/delegation/index.tsx @@ -9,6 +9,7 @@ import { TPoolOption } from 'src/components'; import { Console } from 'src/utils/console'; import { OverSaturatedBlockerModal } from 'src/components/Delegation/DelegateBlocker'; import { getSpendableCoins, userBalance } from 'src/requests'; +import { LoadingModal } from 'src/components/Modals/LoadingModal'; import { getIntervalAsDate, toPercentIntegerString } from 'src/utils'; import { RewardsSummary } from '../../components/Rewards/RewardsSummary'; import { DelegationContextProvider, TDelegations, useDelegationContext } from '../../context/delegations'; @@ -19,7 +20,6 @@ import { DelegationListItemActions } from '../../components/Delegation/Delegatio import { RedeemModal } from '../../components/Rewards/RedeemModal'; import { DelegationModal, DelegationModalProps } from '../../components/Delegation/DelegationModal'; import { backDropStyles, modalStyles } from '../../../.storybook/storiesStyles'; -import { LoadingModal } from 'src/components/Modals/LoadingModal'; const storybookStyles = (theme: Theme, isStorybook?: boolean, backdropProps?: object) => isStorybook From 700cd16641ac238798f3f621d007df7edf390f9e Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Wed, 25 Oct 2023 12:54:22 +0200 Subject: [PATCH 080/236] suppress error output - we can run the api and set the logging level differently on launch - same offending characters are spamming the logs --- explorer-api/src/geo_ip/location.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/explorer-api/src/geo_ip/location.rs b/explorer-api/src/geo_ip/location.rs index fdb8584938..f416f7c6df 100644 --- a/explorer-api/src/geo_ip/location.rs +++ b/explorer-api/src/geo_ip/location.rs @@ -86,7 +86,7 @@ impl GeoIp { })? .next() .ok_or_else(|| { - error!("Fail to resolve IP address from {}:{}", &address, p); + debug!("Fail to resolve IP address from {}:{}", &address, p); GeoIpError::NoValidIP })?; let ip = socket_addr.ip(); From 89746e7dfe6cf52e5ceeff32f564b4b52ffd5d34 Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Wed, 25 Oct 2023 14:09:08 +0200 Subject: [PATCH 081/236] - validate entries don't spam the logs --- explorer-api/src/geo_ip/location.rs | 37 ++++++++++++++++++----------- explorer-api/src/helpers.rs | 26 ++++++++++++++++++++ 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/explorer-api/src/geo_ip/location.rs b/explorer-api/src/geo_ip/location.rs index f416f7c6df..4896cb3eee 100644 --- a/explorer-api/src/geo_ip/location.rs +++ b/explorer-api/src/geo_ip/location.rs @@ -1,6 +1,7 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::helpers::{append_ip_to_file, ip_exists_in_file}; use isocountry::CountryCode; use log::warn; use maxminddb::{geoip2::City, MaxMindDBError, Reader}; @@ -78,20 +79,28 @@ impl GeoIp { &address ); let p = port.unwrap_or(FAKE_PORT); - let socket_addr = (address, p) - .to_socket_addrs() - .map_err(|e| { - error!("Fail to resolve IP address from {}:{}: {}", &address, p, e); - GeoIpError::NoValidIP - })? - .next() - .ok_or_else(|| { - debug!("Fail to resolve IP address from {}:{}", &address, p); - GeoIpError::NoValidIP - })?; - let ip = socket_addr.ip(); - debug!("Internal lookup succeed, resolved ip: {}", ip); - Ok(ip) + match (address, p).to_socket_addrs() { + Ok(mut addrs) => { + if let Some(socket_addr) = addrs.next() { + let ip = socket_addr.ip(); + debug!("Internal lookup succeeded, resolved ip: {}", ip); + Ok(ip) + } else { + debug!("Fail to resolve IP address from {}:{}", &address, p); + if !ip_exists_in_file(address) { + append_ip_to_file(address); + } + Err(GeoIpError::NoValidIP) + } + } + Err(_) => { + debug!("Fail to resolve IP address from {}:{}.", &address, p); + if !ip_exists_in_file(address) { + append_ip_to_file(address); + } + Err(GeoIpError::NoValidIP) + } + } })?; let result = self .db diff --git a/explorer-api/src/helpers.rs b/explorer-api/src/helpers.rs index cd271e838c..93477369c1 100644 --- a/explorer-api/src/helpers.rs +++ b/explorer-api/src/helpers.rs @@ -2,9 +2,35 @@ // SPDX-License-Identifier: Apache-2.0 use nym_mixnet_contract_common::{Decimal, Fraction}; +use std::env; +use std::fs; +use std::fs::OpenOptions; +use std::io::Write; pub(crate) fn best_effort_small_dec_to_f64(dec: Decimal) -> f64 { let num = dec.numerator().u128() as f64; let den = dec.denominator().u128() as f64; num / den } + +pub fn failed_ips_filepath() -> String { + let home_dir = env::var("HOME").unwrap_or_else(|_| "/tmp".to_string()); + format!("{}/failed_ips.txt", home_dir) +} + +pub fn ip_exists_in_file(address: &str) -> bool { + if let Ok(content) = fs::read_to_string(failed_ips_filepath()) { + return content.contains(address); + } + false +} + +pub fn append_ip_to_file(address: &str) { + if let Ok(mut file) = OpenOptions::new() + .append(true) + .create(true) + .open(failed_ips_filepath()) + { + writeln!(file, "{}", address).expect("Failed to write to file"); + } +} From 86fe4d1c1bb312bc25026ec030ca70fd8c97a7d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 25 Oct 2023 15:23:11 +0100 Subject: [PATCH 082/236] linked to swagger api from the landing page (#4058) --- nym-node/src/http/router/landing_page.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nym-node/src/http/router/landing_page.rs b/nym-node/src/http/router/landing_page.rs index 6ac6a66b80..425d59c4de 100644 --- a/nym-node/src/http/router/landing_page.rs +++ b/nym-node/src/http/router/landing_page.rs @@ -26,6 +26,8 @@ pub(super) async fn default() -> Html<&'static str> {

Nym Node

default page of the nym node - you can customize it by setting the 'assets' path under '[http]' section of your config.

+ + You can explore the REST API at /api/v1/swagger/
"#, ) From 8139fcfe74e6ac458d531719b8bd11a0181b617d Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Wed, 25 Oct 2023 16:44:03 +0200 Subject: [PATCH 083/236] keep list of ips in memory before deciding what to do.. --- explorer-api/src/geo_ip/location.rs | 30 +++++++++++++++++++++++++---- explorer-api/src/helpers.rs | 8 -------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/explorer-api/src/geo_ip/location.rs b/explorer-api/src/geo_ip/location.rs index 4896cb3eee..272200f6d2 100644 --- a/explorer-api/src/geo_ip/location.rs +++ b/explorer-api/src/geo_ip/location.rs @@ -1,10 +1,12 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::helpers::{append_ip_to_file, ip_exists_in_file}; +use crate::helpers::append_ip_to_file; use isocountry::CountryCode; use log::warn; use maxminddb::{geoip2::City, MaxMindDBError, Reader}; +use std::collections::HashSet; +use std::sync::Mutex; use std::{ net::{IpAddr, ToSocketAddrs}, str::FromStr, @@ -27,6 +29,7 @@ pub enum GeoIpError { // and an error will be logged. pub(crate) struct GeoIp { pub(crate) db: Option>>, + failed_addresses: FailedIpAddresses, } #[derive(Clone)] @@ -43,6 +46,17 @@ pub(crate) struct Location { pub(crate) longitude: Option, } +pub(crate) struct FailedIpAddresses { + failed_ips: Arc>>, +} + +impl FailedIpAddresses { + pub fn new() -> Self { + FailedIpAddresses { + failed_ips: Arc::new(Mutex::new(HashSet::new())), + } + } +} impl From for nym_explorer_api_requests::Location { fn from(location: Location) -> Self { nym_explorer_api_requests::Location { @@ -69,7 +83,13 @@ impl GeoIp { error!("Fail to open GeoLite2 database file {}: {}", db_path, e); }) .ok(); - GeoIp { db: reader } + + let failed_addresses = FailedIpAddresses::new(); + + GeoIp { + db: reader, + failed_addresses, + } } pub fn query(&self, address: &str, port: Option) -> Result, GeoIpError> { @@ -87,7 +107,8 @@ impl GeoIp { Ok(ip) } else { debug!("Fail to resolve IP address from {}:{}", &address, p); - if !ip_exists_in_file(address) { + let mut failed_ips_guard = self.failed_addresses.failed_ips.lock().unwrap(); + if failed_ips_guard.insert(address.to_string()) { append_ip_to_file(address); } Err(GeoIpError::NoValidIP) @@ -95,7 +116,8 @@ impl GeoIp { } Err(_) => { debug!("Fail to resolve IP address from {}:{}.", &address, p); - if !ip_exists_in_file(address) { + let mut failed_ips_guard = self.failed_addresses.failed_ips.lock().unwrap(); + if failed_ips_guard.insert(address.to_string()) { append_ip_to_file(address); } Err(GeoIpError::NoValidIP) diff --git a/explorer-api/src/helpers.rs b/explorer-api/src/helpers.rs index 93477369c1..dbe4a219e7 100644 --- a/explorer-api/src/helpers.rs +++ b/explorer-api/src/helpers.rs @@ -3,7 +3,6 @@ use nym_mixnet_contract_common::{Decimal, Fraction}; use std::env; -use std::fs; use std::fs::OpenOptions; use std::io::Write; @@ -18,13 +17,6 @@ pub fn failed_ips_filepath() -> String { format!("{}/failed_ips.txt", home_dir) } -pub fn ip_exists_in_file(address: &str) -> bool { - if let Ok(content) = fs::read_to_string(failed_ips_filepath()) { - return content.contains(address); - } - false -} - pub fn append_ip_to_file(address: &str) { if let Ok(mut file) = OpenOptions::new() .append(true) From e3fd26ca4ef4f23a247824b80f6bc097a2f57352 Mon Sep 17 00:00:00 2001 From: Tommy Verrall <60836166+tommyv1987@users.noreply.github.com> Date: Thu, 26 Oct 2023 10:29:04 +0200 Subject: [PATCH 084/236] Update README.md fix denom --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e1a976f529..e46c02478d 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Node, node operator and delegator rewards are determined according to the princi ||A Sybil attack resistance parameter - the higher this parameter is set, the stronger the reduction in competitiveness for a Sybil attacker. ||declared profit margin of operator `i`, defaults to 10%. ||uptime of node `i`, scaled to 0 - 1, for the rewarding epoch -||cost of operating node `i` for the duration of the rewarding epoch, set to 40 NYMTs. +||cost of operating node `i` for the duration of the rewarding epoch, set to 40 NYMs. Node reward for node `i` is determined as: From 0d21f2f39de6cf23a9bc8bd5f79a7c8096e3833d Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 10:39:11 +0200 Subject: [PATCH 085/236] initialise operators update branch --- documentation/operators/src/faq/smoosh-faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index 8bcc071e3e..ceb356ff7b 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -2,8 +2,8 @@ > We aim on purpose to make minimal changes to reward scheme and software. We're just 'smooshing' together stuff we already debugged and know works. > -- Harry Halpin, Nym CEO -

+
This page refer to the changes which are planned to take place over Q3 and Q4 2023. As this is a transition period in the beginning (Q3 2023) the [Mix Nodes FAQ page](./mixnodes-faq.md) holds more answers to the current setup as project Smoosh refers to the eventual setup. As project Smoosh gets progressively implemented the answers on this page will become to be more relevant to the current state and eventually this FAQ page will be merged with the still relevant parts of the main Mix Nodes FAQ page. If any questions are not answered or it's not clear for you in which stage project Smoosh is right now, please reach out in Node Operators [Matrix room](https://matrix.to/#/#operators:nymtech.chat). From 76d4036883f15db9f9004c9c813eed5e2bcff411 Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Thu, 26 Oct 2023 10:46:09 +0200 Subject: [PATCH 086/236] address pr feedback --- explorer-api/src/geo_ip/location.rs | 18 ++++++++++++------ explorer-api/src/helpers.rs | 11 +++++++++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/explorer-api/src/geo_ip/location.rs b/explorer-api/src/geo_ip/location.rs index 272200f6d2..d1c15dac9d 100644 --- a/explorer-api/src/geo_ip/location.rs +++ b/explorer-api/src/geo_ip/location.rs @@ -107,18 +107,24 @@ impl GeoIp { Ok(ip) } else { debug!("Fail to resolve IP address from {}:{}", &address, p); - let mut failed_ips_guard = self.failed_addresses.failed_ips.lock().unwrap(); - if failed_ips_guard.insert(address.to_string()) { - append_ip_to_file(address); + if let Ok(mut failed_ips_guard) = self.failed_addresses.failed_ips.lock() { + if failed_ips_guard.insert(address.to_string()) { + append_ip_to_file(address); + } + } else { + error!("Failed to acquire lock on failed_ips"); } Err(GeoIpError::NoValidIP) } } Err(_) => { debug!("Fail to resolve IP address from {}:{}.", &address, p); - let mut failed_ips_guard = self.failed_addresses.failed_ips.lock().unwrap(); - if failed_ips_guard.insert(address.to_string()) { - append_ip_to_file(address); + if let Ok(mut failed_ips_guard) = self.failed_addresses.failed_ips.lock() { + if failed_ips_guard.insert(address.to_string()) { + append_ip_to_file(address); + } + } else { + error!("Failed to acquire lock on failed_ips"); } Err(GeoIpError::NoValidIP) } diff --git a/explorer-api/src/helpers.rs b/explorer-api/src/helpers.rs index dbe4a219e7..2f65fc3dba 100644 --- a/explorer-api/src/helpers.rs +++ b/explorer-api/src/helpers.rs @@ -18,11 +18,18 @@ pub fn failed_ips_filepath() -> String { } pub fn append_ip_to_file(address: &str) { - if let Ok(mut file) = OpenOptions::new() + match OpenOptions::new() .append(true) .create(true) .open(failed_ips_filepath()) { - writeln!(file, "{}", address).expect("Failed to write to file"); + Ok(mut file) => { + if let Err(e) = writeln!(file, "{}", address) { + error!("Failed to write to file: {}", e); + } + } + Err(e) => { + error!("Failed to open or create the file: {}", e); + } } } From 515054f1c695e9b128443ad08297349658c77b00 Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Thu, 26 Oct 2023 11:10:02 +0200 Subject: [PATCH 087/236] addressing more pr feedback --- explorer-api/src/geo_ip/location.rs | 45 +++++++++++++++++++---------- explorer-api/src/helpers.rs | 5 +++- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/explorer-api/src/geo_ip/location.rs b/explorer-api/src/geo_ip/location.rs index d1c15dac9d..9be80105a9 100644 --- a/explorer-api/src/geo_ip/location.rs +++ b/explorer-api/src/geo_ip/location.rs @@ -1,11 +1,14 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::helpers::append_ip_to_file; +use crate::helpers::{append_ip_to_file, failed_ips_filepath}; use isocountry::CountryCode; use log::warn; use maxminddb::{geoip2::City, MaxMindDBError, Reader}; use std::collections::HashSet; +use std::fs::File; +use std::io::{self, BufRead}; +use std::path::Path; use std::sync::Mutex; use std::{ net::{IpAddr, ToSocketAddrs}, @@ -52,8 +55,20 @@ pub(crate) struct FailedIpAddresses { impl FailedIpAddresses { pub fn new() -> Self { + let mut failed_ips = HashSet::new(); + let file_path = failed_ips_filepath(); + + if Path::new(&file_path).exists() { + if let Ok(file) = File::open(&file_path) { + let lines = io::BufReader::new(file).lines(); + for ip in lines.flatten() { + failed_ips.insert(ip); + } + } + } + FailedIpAddresses { - failed_ips: Arc::new(Mutex::new(HashSet::new())), + failed_ips: Arc::new(Mutex::new(failed_ips)), } } } @@ -92,6 +107,16 @@ impl GeoIp { } } + fn handle_failed_ip(&self, address: &str) { + if let Ok(mut failed_ips_guard) = self.failed_addresses.failed_ips.lock() { + if failed_ips_guard.insert(address.to_string()) { + append_ip_to_file(address); + } + } else { + error!("Failed to acquire lock on failed_ips"); + } + } + pub fn query(&self, address: &str, port: Option) -> Result, GeoIpError> { let ip: IpAddr = FromStr::from_str(address).or_else(|_| { debug!( @@ -107,25 +132,13 @@ impl GeoIp { Ok(ip) } else { debug!("Fail to resolve IP address from {}:{}", &address, p); - if let Ok(mut failed_ips_guard) = self.failed_addresses.failed_ips.lock() { - if failed_ips_guard.insert(address.to_string()) { - append_ip_to_file(address); - } - } else { - error!("Failed to acquire lock on failed_ips"); - } + self.handle_failed_ip(address); Err(GeoIpError::NoValidIP) } } Err(_) => { debug!("Fail to resolve IP address from {}:{}.", &address, p); - if let Ok(mut failed_ips_guard) = self.failed_addresses.failed_ips.lock() { - if failed_ips_guard.insert(address.to_string()) { - append_ip_to_file(address); - } - } else { - error!("Failed to acquire lock on failed_ips"); - } + self.handle_failed_ip(address); Err(GeoIpError::NoValidIP) } } diff --git a/explorer-api/src/helpers.rs b/explorer-api/src/helpers.rs index 2f65fc3dba..16b02d95d4 100644 --- a/explorer-api/src/helpers.rs +++ b/explorer-api/src/helpers.rs @@ -5,6 +5,7 @@ use nym_mixnet_contract_common::{Decimal, Fraction}; use std::env; use std::fs::OpenOptions; use std::io::Write; +use std::path::PathBuf; pub(crate) fn best_effort_small_dec_to_f64(dec: Decimal) -> f64 { let num = dec.numerator().u128() as f64; @@ -14,7 +15,9 @@ pub(crate) fn best_effort_small_dec_to_f64(dec: Decimal) -> f64 { pub fn failed_ips_filepath() -> String { let home_dir = env::var("HOME").unwrap_or_else(|_| "/tmp".to_string()); - format!("{}/failed_ips.txt", home_dir) + let mut path = PathBuf::from(home_dir); + path.push("failed_ips.txt"); + path.to_string_lossy().into_owned() } pub fn append_ip_to_file(address: &str) { From 1f66670cc3e891fbee2235e2ecd749163c920ade Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Thu, 26 Oct 2023 11:14:14 +0200 Subject: [PATCH 088/236] hopefully no more comments :) --- explorer-api/src/geo_ip/location.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/explorer-api/src/geo_ip/location.rs b/explorer-api/src/geo_ip/location.rs index 9be80105a9..52f88069f3 100644 --- a/explorer-api/src/geo_ip/location.rs +++ b/explorer-api/src/geo_ip/location.rs @@ -50,7 +50,7 @@ pub(crate) struct Location { } pub(crate) struct FailedIpAddresses { - failed_ips: Arc>>, + failed_ips: Mutex>, } impl FailedIpAddresses { @@ -68,7 +68,7 @@ impl FailedIpAddresses { } FailedIpAddresses { - failed_ips: Arc::new(Mutex::new(failed_ips)), + failed_ips: Mutex::new(failed_ips), } } } From d47f7afbf6ea23d9822c682f0428060f5ed6638b Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 11:17:13 +0200 Subject: [PATCH 089/236] update smoosh faq - two options --- documentation/operators/src/faq/smoosh-faq.md | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index ceb356ff7b..1169992001 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -16,26 +16,39 @@ As we shared in our blog post article [*What does it take to build the wolds mos > A nick-name by CTO Dave Hrycyszyn and Chief Scientist Claudia Diaz for the work they are currently doing to “smoosh” Nym nodes so that the same operator can serve alternately as mix node, gateway or VPN node. This requires careful calibration of the Nym token economics, for example, only nodes with the highest reputation for good quality service will be in the VPN set and have the chance to earn higher rewards. > By simplifying the components, adding VPN features and supporting new node operators, the aim is to widen the geographical coverage of nodes and have significant redundancy, meaning plenty of operators to be able to meet demand. This requires strong token economic incentives as well as training and support for new node operators. + ## Technical Questions ### What are the changes? Project smoosh will have three steps: -1. Combine the `gateway` and `network-requester`. -2. Combine all the nodes in the Nym Mixnet into one binary, that is `mixnode`, `gateway` (entry and exit) and `network-requester`. -3. Make a selection button (command/argument/flag) for operators to choose whether they want their node to provide all or just some of the functions nodes have in the Nym Mixnet. Not everyone will be able/want to run an exit `gateway` for example. +1. Combine the `gateway` and `network-requester` into one binary ✅ +2. Create [exit gateway](../legal/exit-gateway.md): Take the gateway binary including network requester combined in \#1 and switch from *allowed.list* to a new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) ✅ +3. Combine all the nodes in the Nym Mixnet into one binary, that is `mixnode`, `gateway` (entry and exit) and `network-requester`. These three steps will be staggered over time - period of several months, and will be implemented one by one with enough time to take in feedback and fix bugs in between. Generally, the software will be the same, just instead of multiple binaries, there will be one Nym Mixnet node binary. Delegations will remain on as they are now, per our token economics (staking, saturation etc) +### What does it mean for Nym nodes operators? + +We are looking into two possible ways how such binary will work in practice and will inform in advance. These are the options: + +1. Make a selection button (command/argument/flag) for operators to choose whether they want their node to provide all or just some of the functions nodes have in the Nym Mixnet. Those nodes functioning as exit gateway (in that epoch) will then have bigger rewards due to their larger risk exposure and overhead work with the setup. + +2. All nodes will be required to have the exit gateway functionality. All nodes are rewarded the same as now, and the difference is that a node sometimes (some epochs) may be performing as exit gateway sometimes as mix node or entry gateway of mix functions. + +### Where can I read more about the exit gateway setup? + +We created an [entire page](../legal/exit-gateway.md) about the technical and legal questions around exit gateway. + ### What is the change from allow list to deny list? -The operators running `gateways` would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short allow list to a more permissive setup. An exit policy will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients. +The operators running `gateways` would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short allow list to a more permissive setup. An [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients. ### Can I run a mix node only? -Yes, to run a mix node only is an option. However it will be less rewarded as nodes providing option for `gateway` - meaning the *new smooshed gateway* (previously `gateway` and `network requester`) - due to the work and risk the operators have in comparison to running a `mixnode` only. +Depends which [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators) will be the final one. In case of the first one - yes. In case of the second option, all the nodes will be setup with gateway functionality turned on. ## Token Economics & Rewards @@ -45,22 +58,21 @@ In the original setup there were no incentives to run a `network-requester`. Aft ### How does this change the token economics? -The token economics will stay the same as they are, same goes for the reward algorithm. In practice the distribution of rewards will benefit more the operators who run open gateways. +The token economics will stay the same as they are, same goes for the reward algorithm. ### How are the rewards distributed? +This depends on [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators) chosen. In case of \#1, it will look like this: + As each operator can choose what roles their nodes provide, the nodes which work as open gateways will have higher rewards because they are the most important to keep up and stable. Besides that the operators of gateways may be exposed to more complication and possible legal risks. The nodes which are initialized to run as mix nodes and gateways will be chosen to be on top of the active set before the ones working only as a mix node. -We are considering to turn off the rewards for non-open gateways to incentivize operators to run the open ones. Mix nodes on 'standby' will not be rewarded (as they are not being used). - -The more roles an operator will allow their node to provide the bigger reward ratio which will have huge performance benefits for the end-users. - +I case we go with \#2, all nodes active in the epoch will be rewarded proportionally according their work. ### How will be the staking and inflation after project Smoosh? -We must run tests to see how many users pay. We may need to keep inflation on if not enough people pay to keep high quality gateways on in the early stage of the transition. That would mean keeping staking on for gateways. Staking will always be on for mix nodes. +We must run tests to see how many users pay. We may need to keep inflation on if not enough people pay to keep high quality gateways on in the early stage of the transition. ### When project smooth will be launched, it would be the mixmining pool that will pay for the gateway rewards based on amount of traffic routed ? From 0ff512f3736c0773f7a3361d74095c092e60c684 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 11:22:23 +0200 Subject: [PATCH 090/236] update smoosh faq - two options --- documentation/operators/src/faq/smoosh-faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index 1169992001..4d369d8d12 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -36,7 +36,7 @@ We are looking into two possible ways how such binary will work in practice and 1. Make a selection button (command/argument/flag) for operators to choose whether they want their node to provide all or just some of the functions nodes have in the Nym Mixnet. Those nodes functioning as exit gateway (in that epoch) will then have bigger rewards due to their larger risk exposure and overhead work with the setup. -2. All nodes will be required to have the exit gateway functionality. All nodes are rewarded the same as now, and the difference is that a node sometimes (some epochs) may be performing as exit gateway sometimes as mix node or entry gateway of mix functions. +2. All nodes will be required to have the exit gateway functionality. All nodes are rewarded the same as now, and the difference is that a node sometimes (some epochs) may be performing as exit gateway sometimes as mix node or entry gateway adjusted according the network demand by an algorithm. ### Where can I read more about the exit gateway setup? From 0801b3c6f8e9a6e5cfaf9ca6ec4add2a38364454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Thu, 26 Oct 2023 10:35:14 +0100 Subject: [PATCH 091/236] Feature/exit policy (#4030) * exit policy types * simple client for grabbing the policy * moved allowed_hosts to a submodule * started integrating exit policy into a NR * ability to construct ExitPolicyRequestFilter * fixed policy parsing to look for comment char from the left * conditionally setting up request filter * [wip] setting up correct url for exit policy upstream * clap flags for running with exit policy * fixed NR template * updated NR config template * making sure to perform request filtering in separate task * initial, placeholder, exit policy API endpoint * serving exit policy from an embedded NR * double slash sanitization * socks5 query for exit policy * adjusted address policy logging * cargo fmt * Updated exit policy url to point to the correct mainnet file * removed unecessary mutability in filter tests * fixed the code block showing example policy being interpreted as doc test --- Cargo.lock | 15 + Cargo.toml | 1 + common/config/src/lib.rs | 1 + common/config/src/serde_helpers.rs | 47 ++ common/exit-policy/Cargo.toml | 33 + common/exit-policy/src/client.rs | 10 + common/exit-policy/src/lib.rs | 233 ++++++ .../exit-policy/src/policy/address_policy.rs | 726 ++++++++++++++++++ common/exit-policy/src/policy/error.rs | 71 ++ common/exit-policy/src/policy/mod.rs | 14 + common/http-api-client/src/lib.rs | 4 + common/network-defaults/src/mainnet.rs | 6 + common/network-defaults/src/var_names.rs | 1 + common/socks5/requests/Cargo.toml | 1 + common/socks5/requests/src/request.rs | 2 + common/socks5/requests/src/response.rs | 52 ++ gateway/src/commands/helpers.rs | 6 + gateway/src/commands/init.rs | 8 + gateway/src/commands/run.rs | 7 + .../src/commands/setup_network_requester.rs | 25 +- gateway/src/http/mod.rs | 179 ++++- .../embedded_network_requester/mod.rs | 5 +- gateway/src/node/mod.rs | 54 +- nym-connect/desktop/Cargo.lock | 11 + nym-node/nym-node-requests/Cargo.toml | 3 +- .../v1/network_requester/exit_policy/mod.rs | 4 + .../network_requester/exit_policy/models.rs | 44 ++ .../src/api/v1/network_requester/mod.rs | 1 + .../src/api/v1/network_requester/models.rs | 13 - nym-node/nym-node-requests/src/lib.rs | 10 +- .../api/v1/network_requester/exit_policy.rs | 30 + .../router/api/v1/network_requester/mod.rs | 27 +- nym-node/src/http/router/api/v1/openapi.rs | 7 + nym-node/src/http/router/mod.rs | 7 + .../network-requester/Cargo.toml | 5 +- .../network-requester/src/cli/init.rs | 29 +- .../network-requester/src/cli/mod.rs | 5 + .../network-requester/src/cli/run.rs | 7 + .../network-requester/src/config/mod.rs | 29 +- .../src/config/persistence.rs | 2 + .../network-requester/src/config/template.rs | 8 + .../network-requester/src/core.rs | 125 +-- .../network-requester/src/error.rs | 33 +- .../network-requester/src/lib.rs | 3 +- .../network-requester/src/main.rs | 2 +- .../allowed_hosts/filter.rs | 67 +- .../allowed_hosts/group.rs | 2 +- .../allowed_hosts/host.rs | 0 .../allowed_hosts/hosts.rs | 2 +- .../{ => request_filter}/allowed_hosts/mod.rs | 0 .../allowed_hosts/standard_list.rs | 4 +- .../allowed_hosts/stored_allowed_hosts.rs | 2 +- .../src/request_filter/exit_policy/mod.rs | 82 ++ .../src/request_filter/mod.rs | 142 ++++ tools/nym-nr-query/Cargo.toml | 2 +- tools/nym-nr-query/src/main.rs | 75 +- 56 files changed, 2073 insertions(+), 211 deletions(-) create mode 100644 common/config/src/serde_helpers.rs create mode 100644 common/exit-policy/Cargo.toml create mode 100644 common/exit-policy/src/client.rs create mode 100644 common/exit-policy/src/lib.rs create mode 100644 common/exit-policy/src/policy/address_policy.rs create mode 100644 common/exit-policy/src/policy/error.rs create mode 100644 common/exit-policy/src/policy/mod.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/network_requester/exit_policy/mod.rs create mode 100644 nym-node/nym-node-requests/src/api/v1/network_requester/exit_policy/models.rs create mode 100644 nym-node/src/http/router/api/v1/network_requester/exit_policy.rs rename service-providers/network-requester/src/{ => request_filter}/allowed_hosts/filter.rs (88%) rename service-providers/network-requester/src/{ => request_filter}/allowed_hosts/group.rs (96%) rename service-providers/network-requester/src/{ => request_filter}/allowed_hosts/host.rs (100%) rename service-providers/network-requester/src/{ => request_filter}/allowed_hosts/hosts.rs (99%) rename service-providers/network-requester/src/{ => request_filter}/allowed_hosts/mod.rs (100%) rename service-providers/network-requester/src/{ => request_filter}/allowed_hosts/standard_list.rs (96%) rename service-providers/network-requester/src/{ => request_filter}/allowed_hosts/stored_allowed_hosts.rs (98%) create mode 100644 service-providers/network-requester/src/request_filter/exit_policy/mod.rs create mode 100644 service-providers/network-requester/src/request_filter/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 5c80148210..eb1e5cd900 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6477,6 +6477,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "nym-exit-policy" +version = "0.1.0" +dependencies = [ + "reqwest", + "serde", + "serde_json", + "thiserror", + "tracing", + "utoipa", +] + [[package]] name = "nym-explorer-api-requests" version = "0.1.0" @@ -6803,6 +6815,7 @@ dependencies = [ "nym-config", "nym-credential-storage", "nym-crypto", + "nym-exit-policy", "nym-network-defaults", "nym-ordered-buffer", "nym-sdk", @@ -6887,6 +6900,7 @@ dependencies = [ "http-api-client", "nym-bin-common", "nym-crypto", + "nym-exit-policy", "nym-wireguard-types", "schemars", "serde", @@ -7178,6 +7192,7 @@ version = "0.1.0" dependencies = [ "bincode", "log", + "nym-exit-policy", "nym-service-providers-common", "nym-sphinx-addressing", "serde", diff --git a/Cargo.toml b/Cargo.toml index 93b62803db..e4d6645927 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ members = [ "common/crypto", "common/dkg", "common/execute", + "common/exit-policy", "common/http-api-client", "common/inclusion-probability", "common/ledger", diff --git a/common/config/src/lib.rs b/common/config/src/lib.rs index d3e4dbf6b5..3a9104eeb6 100644 --- a/common/config/src/lib.rs +++ b/common/config/src/lib.rs @@ -15,6 +15,7 @@ pub use toml::de::Error as TomlDeError; pub mod defaults; pub mod helpers; pub mod legacy_helpers; +pub mod serde_helpers; pub const NYM_DIR: &str = ".nym"; pub const DEFAULT_NYM_APIS_DIR: &str = "nym-api"; diff --git a/common/config/src/serde_helpers.rs b/common/config/src/serde_helpers.rs new file mode 100644 index 0000000000..27c11f21be --- /dev/null +++ b/common/config/src/serde_helpers.rs @@ -0,0 +1,47 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use serde::{Deserialize, Deserializer}; +use std::fmt::Display; +use std::path::PathBuf; +use std::str::FromStr; + +pub fn de_maybe_stringified<'de, D, T, E>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, + T: FromStr, + E: Display, +{ + let raw = String::deserialize(deserializer)?; + if raw.is_empty() { + Ok(None) + } else { + Ok(Some(raw.parse().map_err(serde::de::Error::custom)?)) + } +} + +pub fn de_maybe_string<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + de_maybe_stringified(deserializer) +} + +pub fn de_maybe_path<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + de_maybe_stringified(deserializer) +} + +pub fn de_maybe_port<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let port = u16::deserialize(deserializer)?; + if port == 0 { + Ok(None) + } else { + Ok(Some(port)) + } +} diff --git a/common/exit-policy/Cargo.toml b/common/exit-policy/Cargo.toml new file mode 100644 index 0000000000..a5e8f26974 --- /dev/null +++ b/common/exit-policy/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "nym-exit-policy" +version = "0.1.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde = { workspace = true, features = ["derive"] } +thiserror = { workspace = true } +tracing = { workspace = true } + +# feature-specific dependencies: + +## client feature +reqwest = { workspace = true, optional = true } + +## openapi feature +serde_json = { workspace = true, optional = true } +utoipa = { workspace = true, optional = true } + +[dev-dependencies] +serde_json = { workspace = true } + +[features] +default = [] +client = ["reqwest"] +openapi = ["utoipa", "serde_json"] diff --git a/common/exit-policy/src/client.rs b/common/exit-policy/src/client.rs new file mode 100644 index 0000000000..c6dfbe3f3b --- /dev/null +++ b/common/exit-policy/src/client.rs @@ -0,0 +1,10 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::policy::PolicyError; +use crate::ExitPolicy; +use reqwest::IntoUrl; + +pub async fn get_exit_policy(url: impl IntoUrl) -> Result { + ExitPolicy::parse_from_torrc(reqwest::get(url).await?.text().await?) +} diff --git a/common/exit-policy/src/lib.rs b/common/exit-policy/src/lib.rs new file mode 100644 index 0000000000..f1b41274bc --- /dev/null +++ b/common/exit-policy/src/lib.rs @@ -0,0 +1,233 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod policy; + +#[cfg(feature = "client")] +pub mod client; + +pub use crate::policy::{ + AddressPolicy, AddressPolicyAction, AddressPolicyRule, AddressPortPattern, PolicyError, + PortRange, +}; + +pub(crate) const EXIT_POLICY_FIELD_NAME: &str = "ExitPolicy"; +const COMMENT_CHAR: char = '#'; + +pub type ExitPolicy = AddressPolicy; + +pub fn parse_exit_policy>(exit_policy: S) -> Result { + let rules = exit_policy + .as_ref() + .lines() + .map(|maybe_rule| { + if let Some(comment_start) = maybe_rule.find(COMMENT_CHAR) { + &maybe_rule[..comment_start] + } else { + maybe_rule + } + .trim() + }) + .filter(|maybe_rule| !maybe_rule.is_empty()) + .map(parse_address_policy_rule) + .collect::, _>>()?; + + Ok(AddressPolicy { rules }) +} + +pub fn format_exit_policy(policy: &ExitPolicy) -> String { + policy + .rules + .iter() + .map(|rule| format!("{EXIT_POLICY_FIELD_NAME} {rule}")) + .fold(String::new(), |accumulator, rule| { + accumulator + &rule + "\n" + }) + .trim_end() + .to_string() +} + +fn parse_address_policy_rule(rule: &str) -> Result { + // each exit policy rule must begin with 'ExitPolicy' followed by the actual rule + rule.strip_prefix(EXIT_POLICY_FIELD_NAME) + .ok_or(PolicyError::NoExitPolicyPrefix { + entry: rule.to_string(), + })? + .trim() + .parse() +} + +// for each line, ignore everything after the comment + +#[cfg(test)] +mod tests { + use super::*; + use crate::policy::AddressPolicyAction::{Accept, Accept6, Reject, Reject6}; + use crate::policy::{AddressPortPattern, IpPattern, PortRange}; + + #[test] + fn parsing_policy() { + let sample = r#" +ExitPolicy reject 1.2.3.4/32:*#comment +ExitPolicy reject 1.2.3.5:* #comment +ExitPolicy reject 1.2.3.6/16:* +ExitPolicy reject 1.2.3.6/16:123-456 # comment + +ExitPolicy accept *:53 # DNS + +# random comment + +ExitPolicy accept6 *6:119 +ExitPolicy accept *4:120 +ExitPolicy reject6 [FC00::]/7:* + +#ExitPolicy accept *:8080 #and another comment here + +ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8329:* +ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8328:1234 +ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8328/64:1235 + +#another comment +#ExitPolicy accept *:8080 + +ExitPolicy reject *:* + "#; + + let res = parse_exit_policy(sample).unwrap(); + + let mut expected = AddressPolicy::new(); + + // ExitPolicy reject 1.2.3.4/32:*#comment + expected.push( + Reject, + AddressPortPattern { + ip_pattern: IpPattern::V4 { + addr_prefix: "1.2.3.4".parse().unwrap(), + mask: 32, + }, + ports: PortRange::new_all(), + }, + ); + + // ExitPolicy reject 1.2.3.5:* #comment + expected.push( + Reject, + AddressPortPattern { + ip_pattern: IpPattern::V4 { + addr_prefix: "1.2.3.5".parse().unwrap(), + mask: 32, + }, + ports: PortRange::new_all(), + }, + ); + + // ExitPolicy reject 1.2.3.6/16:* + expected.push( + Reject, + AddressPortPattern { + ip_pattern: IpPattern::V4 { + addr_prefix: "1.2.3.6".parse().unwrap(), + mask: 16, + }, + ports: PortRange::new_all(), + }, + ); + + // ExitPolicy reject 1.2.3.6/16:123-456 + expected.push( + Reject, + AddressPortPattern { + ip_pattern: IpPattern::V4 { + addr_prefix: "1.2.3.6".parse().unwrap(), + mask: 16, + }, + ports: PortRange::new(123, 456).unwrap(), + }, + ); + + // ExitPolicy accept *:53 + expected.push( + Accept, + AddressPortPattern { + ip_pattern: IpPattern::Star, + ports: PortRange::new_singleton(53), + }, + ); + + // ExitPolicy accept6 *6:119 + expected.push( + Accept6, + AddressPortPattern { + ip_pattern: IpPattern::V6Star, + ports: PortRange::new_singleton(119), + }, + ); + + // ExitPolicy accept *4:120 + expected.push( + Accept, + AddressPortPattern { + ip_pattern: IpPattern::V4Star, + ports: PortRange::new_singleton(120), + }, + ); + + // ExitPolicy reject6 [FC00::]/7:* + expected.push( + Reject6, + AddressPortPattern { + ip_pattern: IpPattern::V6 { + addr_prefix: "FC00::".parse().unwrap(), + mask: 7, + }, + ports: PortRange::new_all(), + }, + ); + + // ExitPolicy FE80:0000:0000:0000:0202:B3FF:FE1E:8329:* + expected.push( + Reject, + AddressPortPattern { + ip_pattern: IpPattern::V6 { + addr_prefix: "FE80:0000:0000:0000:0202:B3FF:FE1E:8329".parse().unwrap(), + mask: 128, + }, + ports: PortRange::new_all(), + }, + ); + + // ExitPolicy FE80:0000:0000:0000:0202:B3FF:FE1E:8328:1234 + expected.push( + Reject, + AddressPortPattern { + ip_pattern: IpPattern::V6 { + addr_prefix: "FE80:0000:0000:0000:0202:B3FF:FE1E:8328".parse().unwrap(), + mask: 128, + }, + ports: PortRange::new_singleton(1234), + }, + ); + + // ExitPolicy FE80:0000:0000:0000:0202:B3FF:FE1E:8328/64:1235 + expected.push( + Reject, + AddressPortPattern { + ip_pattern: IpPattern::V6 { + addr_prefix: "FE80:0000:0000:0000:0202:B3FF:FE1E:8328".parse().unwrap(), + mask: 64, + }, + ports: PortRange::new_singleton(1235), + }, + ); + + expected.push( + Reject, + AddressPortPattern { + ip_pattern: IpPattern::Star, + ports: PortRange::new_all(), + }, + ); + + assert_eq!(res, expected) + } +} diff --git a/common/exit-policy/src/policy/address_policy.rs b/common/exit-policy/src/policy/address_policy.rs new file mode 100644 index 0000000000..09162a6e9b --- /dev/null +++ b/common/exit-policy/src/policy/address_policy.rs @@ -0,0 +1,726 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +//! Implements address policies, based on a series of accept/reject +//! rules. + +use crate::policy::error::PolicyError; +use serde::{Deserialize, Serialize}; +use std::fmt::{Display, Formatter}; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; +use std::str::FromStr; +use tracing::trace; + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +#[serde(rename_all = "lowercase")] +pub enum AddressPolicyAction { + /// A rule that accepts matching address:port combinations on IPv4 and IPv6. + Accept, + + /// A rule that rejects matching address:port combinations on IPv4 and IPv6. + Reject, + + /// A rule that accepts matching address:port combinations on IPv6 only. + Accept6, + + /// A rule that rejects matching address:port combinations on IPv6 only. + Reject6, +} + +impl AddressPolicyAction { + pub fn is_accept(&self) -> bool { + matches!( + self, + AddressPolicyAction::Accept | AddressPolicyAction::Accept6 + ) + } +} + +impl FromStr for AddressPolicyAction { + type Err = PolicyError; + + fn from_str(s: &str) -> Result { + match s { + "accept" => Ok(AddressPolicyAction::Accept), + "reject" => Ok(AddressPolicyAction::Reject), + "accept6" => Ok(AddressPolicyAction::Accept6), + "reject6" => Ok(AddressPolicyAction::Reject6), + other => Err(PolicyError::InvalidPolicyAction { + action: other.to_string(), + }), + } + } +} + +impl Display for AddressPolicyAction { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + AddressPolicyAction::Accept => write!(f, "accept"), + AddressPolicyAction::Reject => write!(f, "reject"), + AddressPolicyAction::Accept6 => write!(f, "accept6"), + AddressPolicyAction::Reject6 => write!(f, "reject6"), + } + } +} + +/// A sequence of rules that are applied to an address:port until one +/// matches. +/// +/// Each rule is of the form "accept(6) PATTERN" or "reject(6) PATTERN", +/// where every pattern describes a set of addresses and ports. +/// Address sets are given as a prefix of 0-128 bits that the address +/// must have; port sets are given as a low-bound and high-bound that +/// the target port might lie between. +/// +/// An example IPv4 policy might be: +/// +/// ```text +/// reject *:25 +/// reject 127.0.0.0/8:* +/// reject 192.168.0.0/16:* +/// accept *:80 +/// accept *:443 +/// accept *:9000-65535 +/// reject *:* +/// ``` +#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +#[cfg_attr(feature = "openapi", aliases(ExitPolicy))] +pub struct AddressPolicy { + /// A list of rules to apply to find out whether an address is + /// contained by this policy. + /// + /// The rules apply in order; the first one to match determines + /// whether the address is accepted or rejected. + pub(crate) rules: Vec, +} + +impl AddressPolicy { + /// Create a new AddressPolicy that matches nothing. + pub const fn new() -> Self { + AddressPolicy { rules: Vec::new() } + } + + /// Create a new AddressPolicy that matches everything. + pub fn new_open() -> Self { + AddressPolicy { + rules: vec![AddressPolicyRule::new( + AddressPolicyAction::Accept, + AddressPortPattern { + ip_pattern: IpPattern::Star, + ports: PortRange::new_all(), + }, + )], + } + } + + /// Check whether this AddressPolicy matches all patterns. + pub fn is_open(&self) -> bool { + if self.rules.len() != 1 { + return false; + } + + let rule = &self.rules[0]; + + rule.action == AddressPolicyAction::Accept + && rule.pattern.ip_pattern == IpPattern::Star + && rule.pattern.ports.is_all() + } + + /// Attempts to parse the AddressPolicy out of raw torrc representation. + pub fn parse_from_torrc>(raw: S) -> Result { + crate::parse_exit_policy(raw) + } + + /// Formats the AddressPolicy with torrc representation + pub fn format_as_torrc(&self) -> String { + crate::format_exit_policy(self) + } + + /// Apply this policy to an address:port combination + /// + /// We do this by applying each rule in sequence, until one + /// matches. + /// + /// Returns None if no rule matches. + pub fn allows(&self, addr: &IpAddr, port: u16) -> Option { + self.rules + .iter() + .find(|rule| rule.pattern.matches(addr, port)) + .map(|rule| { + trace!("'{addr}:{port}' is covered by rule '{rule}'"); + rule.action.is_accept() + }) + } + + /// As allows, but accept a SocketAddr. + pub fn allows_sockaddr(&self, addr: &SocketAddr) -> Option { + self.allows(&addr.ip(), addr.port()) + } + + /// Add a new rule to this policy. + /// + /// The newly added rule is applied _after_ all previous rules. + /// It matches all addresses and ports covered by AddressPortPattern. + /// + /// If accept is true, the rule is to accept addresses that match; + /// if accept is false, the rule rejects such addresses. + pub fn push(&mut self, action: AddressPolicyAction, pattern: AddressPortPattern) { + self.rules.push(AddressPolicyRule { action, pattern }) + } + + /// As push, but accepts a AddressPolicyRule. + pub fn push_rule(&mut self, rule: AddressPolicyRule) { + self.rules.push(rule) + } +} + +/// A single rule in an address policy. +/// +/// Contains a pattern, what to do with things that match it. +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct AddressPolicyRule { + /// What do we do with items that match the pattern? + action: AddressPolicyAction, + + /// What pattern are we trying to match? + pattern: AddressPortPattern, +} + +impl FromStr for AddressPolicyRule { + type Err = PolicyError; + + fn from_str(s: &str) -> Result { + // split on the first space, i.e. separation between the action and the pattern + let Some((action, pattern)) = s.split_once(' ') else { + return Err(PolicyError::MalformedAddressPolicy { raw: s.to_string() }); + }; + + Ok(AddressPolicyRule { + action: action.parse()?, + pattern: pattern.parse()?, + }) + } +} + +impl AddressPolicyRule { + pub fn new(action: AddressPolicyAction, pattern: AddressPortPattern) -> Self { + AddressPolicyRule { action, pattern } + } +} +impl Display for AddressPolicyRule { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{} {}", self.action, self.pattern) + } +} + +/// A pattern that may or may not match an address and port. +/// +/// Each AddrPortPattern has an IP pattern, which matches a set of +/// addresses by prefix, and a port pattern, which matches a range of +/// ports. +/// +/// # Example +/// +/// ``` +/// use nym_exit_policy::policy::AddressPortPattern; +/// use std::net::{IpAddr,Ipv4Addr}; +/// let localhost = IpAddr::V4(Ipv4Addr::new(127,3,4,5)); +/// let not_localhost = IpAddr::V4(Ipv4Addr::new(192,0,2,16)); +/// let pat: AddressPortPattern = "127.0.0.0/8:*".parse().unwrap(); +/// +/// assert!(pat.matches(&localhost, 22)); +/// assert!(!pat.matches(¬_localhost, 22)); +/// ``` +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct AddressPortPattern { + /// A pattern to match somewhere between zero and all IP addresses. + #[serde(with = "stringified_ip_pattern")] + #[cfg_attr(feature = "openapi", schema(example = "1.2.3.6/16", value_type = String))] + pub(crate) ip_pattern: IpPattern, + + /// A pattern to match a range of ports. + pub(crate) ports: PortRange, +} + +mod stringified_ip_pattern { + use super::IpPattern; + use serde::{Deserialize, Deserializer, Serializer}; + use std::str::FromStr; + + pub fn serialize(pattern: &IpPattern, serializer: S) -> Result { + serializer.serialize_str(&pattern.to_string()) + } + + pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result { + let s = ::deserialize(deserializer)?; + IpPattern::from_str(&s).map_err(serde::de::Error::custom) + } +} + +impl AddressPortPattern { + /// Return true iff this pattern matches a given address and port. + pub fn matches(&self, addr: &IpAddr, port: u16) -> bool { + self.ip_pattern.matches(addr) && self.ports.contains(port) + } + + /// As matches, but accept a SocketAddr. + pub fn matches_sockaddr(&self, addr: &SocketAddr) -> bool { + self.matches(&addr.ip(), addr.port()) + } +} + +impl Display for AddressPortPattern { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}:{}", self.ip_pattern, self.ports) + } +} + +impl FromStr for AddressPortPattern { + type Err = PolicyError; + + fn from_str(s: &str) -> Result { + let last_colon = s + .rfind(':') + .ok_or(PolicyError::MalformedAddressPortPattern { raw: s.to_string() })?; + + // doesn't have enough chars to cover the port, even if its a wildcard + if s.len() < last_colon + 2 { + return Err(PolicyError::MalformedAddressPortPattern { raw: s.to_string() }); + } + + let ip_pattern = s[..last_colon].parse()?; + let ports = s[last_colon + 1..].parse()?; + + Ok(AddressPortPattern { ip_pattern, ports }) + } +} + +/// A pattern that matches one or more IP addresses. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum IpPattern { + /// Match all addresses. + Star, + + /// Match all IPv4 addresses. + V4Star, + + /// Match all IPv6 addresses. + V6Star, + + /// Match all IPv4 addresses beginning with a given prefix and mask. + V4 { addr_prefix: Ipv4Addr, mask: u8 }, + + /// Match all IPv6 addresses beginning with a given prefix and mask. + V6 { addr_prefix: Ipv6Addr, mask: u8 }, +} + +impl IpPattern { + /// Construct an IpPattern that matches the first `mask` bits of `addr`. + fn from_addr_and_mask(address: IpAddr, target_mask: u8) -> Result { + match (address, target_mask) { + (IpAddr::V4(_), 0) => Ok(IpPattern::V4Star), + (IpAddr::V6(_), 0) => Ok(IpPattern::V6Star), + (IpAddr::V4(addr_prefix), mask) if mask <= 32 => { + Ok(IpPattern::V4 { addr_prefix, mask }) + } + (IpAddr::V6(addr_prefix), mask) if mask <= 128 => { + Ok(IpPattern::V6 { addr_prefix, mask }) + } + (addr, mask) => { + if addr.is_ipv4() { + Err(PolicyError::InvalidIpV4Mask { mask }) + } else { + Err(PolicyError::InvalidIpV6Mask { mask }) + } + } + } + } + + /// Return true iff `addr` is matched by this pattern. + fn matches(&self, addr: &IpAddr) -> bool { + match (self, addr) { + (IpPattern::Star, _) => true, + (IpPattern::V4Star, IpAddr::V4(_)) => true, + (IpPattern::V6Star, IpAddr::V6(_)) => true, + (IpPattern::V4 { addr_prefix, mask }, IpAddr::V4(addr)) => { + let p1 = u32::from_be_bytes(addr_prefix.octets()); + let p2 = u32::from_be_bytes(addr.octets()); + + let shift = 32 - mask; + (p1 >> shift) == (p2 >> shift) + } + (IpPattern::V6 { addr_prefix, mask }, IpAddr::V6(addr)) => { + let p1 = u128::from_be_bytes(addr_prefix.octets()); + let p2 = u128::from_be_bytes(addr.octets()); + + let shift = 128 - mask; + (p1 >> shift) == (p2 >> shift) + } + (_, _) => false, + } + } +} + +impl Display for IpPattern { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + IpPattern::Star => write!(f, "*"), + IpPattern::V4Star => write!(f, "*4"), + IpPattern::V6Star => write!(f, "*6"), + IpPattern::V4 { addr_prefix, mask } => { + write!(f, "{addr_prefix}/{mask}") + } + IpPattern::V6 { addr_prefix, mask } => { + write!(f, "{addr_prefix}/{mask}") + } + } + } +} + +/// Helper: try to parse a plain ipv4 address, or an IPv6 address +/// wrapped in brackets. +fn parse_addr(s: &str) -> Result { + if s.starts_with('[') && s.ends_with(']') { + Ipv6Addr::from_str(&s[1..s.len() - 1]).map(IpAddr::V6) + } else { + IpAddr::from_str(s) + } + .map_err(|source| PolicyError::MalformedIpAddress { + addr: s.to_string(), + source, + }) +} + +/// Helper: try to parse a port making sure it's non-zero +fn parse_port(s: &str) -> Result { + let port = s + .parse::() + .map_err(|_| PolicyError::InvalidPort { raw: s.to_string() })?; + + if port == 0 { + Err(PolicyError::InvalidPort { + raw: port.to_string(), + }) + } else { + Ok(port) + } +} + +impl FromStr for IpPattern { + type Err = PolicyError; + fn from_str(s: &str) -> Result { + let (ip_s, mask_s) = match s.find('/') { + Some(slash_idx) => (&s[..slash_idx], Some(&s[slash_idx + 1..])), + None => (s, None), + }; + + match (ip_s, mask_s) { + // '*' patterns + ("*", Some(m)) => Err(PolicyError::MaskWithStar { + mask: m.to_string(), + }), + ("*", None) => Ok(IpPattern::Star), + + // '*4' patterns + ("*4", Some(m)) => Err(PolicyError::MaskWithV4Star { + mask: m.to_string(), + }), + ("*4", None) => Ok(IpPattern::V4Star), + + // '*6' patterns + ("*6", Some(m)) => Err(PolicyError::MaskWithV6Star { + mask: m.to_string(), + }), + ("*6", None) => Ok(IpPattern::V6Star), + + (s, Some(m)) => { + let a: IpAddr = parse_addr(s)?; + let m: u8 = m.parse().map_err(|_| PolicyError::InvalidMask { + mask: m.to_string(), + })?; + IpPattern::from_addr_and_mask(a, m) + } + (s, None) => { + let a: IpAddr = parse_addr(s)?; + let m = if a.is_ipv4() { 32 } else { 128 }; + IpPattern::from_addr_and_mask(a, m) + } + } + } +} + +/// A PortRange is a set of consecutively numbered TCP or UDP ports. +/// +/// # Example +/// ``` +/// use nym_exit_policy::policy::PortRange; +/// +/// let r: PortRange = "22-8000".parse().unwrap(); +/// assert!(r.contains(128)); +/// assert!(r.contains(22)); +/// assert!(r.contains(8000)); +/// +/// assert!(! r.contains(21)); +/// assert!(! r.contains(8001)); +/// ``` +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct PortRange { + /// The first port in this range. + #[cfg_attr(feature = "openapi", schema(example = 80))] + pub start: u16, + + /// The last port in this range. + #[cfg_attr(feature = "openapi", schema(example = 81))] + pub end: u16, +} + +impl PortRange { + /// Create a new port range spanning from start to end, asserting that + /// the correct invariants hold. + fn new_unchecked(start: u16, end: u16) -> Self { + assert_ne!(start, 0); + assert!(start <= end); + + PortRange { start, end } + } + + /// Create a port range containing all ports. + pub fn new_all() -> Self { + PortRange::new_unchecked(1, 65535) + } + + /// Create a new PortRange. + /// + /// The Portrange contains all ports between `start` and `end` inclusive. + /// + /// Returns None if lo is greater than end, or if either is zero. + pub const fn new(start: u16, end: u16) -> Option { + if start != 0 && start <= end { + Some(PortRange { start, end }) + } else { + None + } + } + + /// Create a new singleton PortRange. + pub const fn new_singleton(value: u16) -> Self { + PortRange { + start: value, + end: value, + } + } + + /// Return true if a port is in this range. + pub fn contains(&self, port: u16) -> bool { + self.start <= port && port <= self.end + } + + /// Return true if this range contains all ports. + pub fn is_all(&self) -> bool { + self.start == 1 && self.end == 65535 + } +} + +/// A PortRange is displayed as a number if it contains a single port, +/// and as a start point and end point separated by a dash if it contains +/// more than one port. +impl Display for PortRange { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.is_all() { + write!(f, "*") + } else if self.start == self.end { + write!(f, "{}", self.start) + } else { + write!(f, "{}-{}", self.start, self.end) + } + } +} + +impl FromStr for PortRange { + type Err = PolicyError; + fn from_str(s: &str) -> Result { + // check is if it's a star range + if s == "*" { + return Ok(PortRange::new_all()); + } + + if let Some(pos) = s.find('-') { + // This is a range; parse each part + let start = parse_port(&s[..pos])?; + let end = parse_port(&s[pos + 1..])?; + PortRange::new(start, end).ok_or(PolicyError::InvalidRange { start, end }) + } else { + // There was no hyphen, so try to parse this range as a singleton. + let value = parse_port(s)?; + Ok(PortRange::new_singleton(value)) + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_bad_rules() { + fn check(s: &str) { + assert!(s.parse::().is_err()); + } + + check("marzipan:80"); + check("1.2.3.4:90-80"); + check("1.2.3.4/100:8888"); + check("[1.2.3.4]/16:80"); + check("[::1]/130:8888"); + } + + #[test] + fn test_rule_matches() { + fn check(address: &str, yes: &[&str], no: &[&str]) { + use std::net::SocketAddr; + let policy = address.parse::().unwrap(); + for s in yes { + let sa = s.parse::().unwrap(); + assert!(policy.matches_sockaddr(&sa)); + } + for s in no { + let sa = s.parse::().unwrap(); + assert!(!policy.matches_sockaddr(&sa)); + } + } + + check( + "1.2.3.4/16:80", + &["1.2.3.4:80", "1.2.44.55:80"], + &["9.9.9.9:80", "1.3.3.4:80", "1.2.3.4:81"], + ); + check( + "*:443-8000", + &["1.2.3.4:443", "[::1]:500"], + &["9.0.0.0:80", "[::1]:80"], + ); + check( + "[face::]/8:80", + &["[fab0::7]:80"], + &["[dd00::]:80", "[face::7]:443"], + ); + + check("0.0.0.0/0:*", &["127.0.0.1:80"], &["[f00b::]:80"]); + check("[::]/0:*", &["[f00b::]:80"], &["127.0.0.1:80"]); + } + + #[test] + fn test_policy_matches() -> Result<(), PolicyError> { + let mut policy = AddressPolicy::default(); + policy.push(AddressPolicyAction::Accept, "*:443".parse()?); + policy.push(AddressPolicyAction::Accept, "[::1]:80".parse()?); + policy.push(AddressPolicyAction::Reject, "*:80".parse()?); + + let policy = policy; // drop mut + assert!(policy + .allows_sockaddr(&"[::6]:443".parse().unwrap()) + .unwrap()); + assert!(policy + .allows_sockaddr(&"127.0.0.1:443".parse().unwrap()) + .unwrap()); + assert!(policy + .allows_sockaddr(&"[::1]:80".parse().unwrap()) + .unwrap()); + assert!(!policy + .allows_sockaddr(&"[::2]:80".parse().unwrap()) + .unwrap()); + assert!(!policy + .allows_sockaddr(&"127.0.0.1:80".parse().unwrap()) + .unwrap()); + assert!(policy + .allows_sockaddr(&"127.0.0.1:66".parse().unwrap()) + .is_none()); + Ok(()) + } + + #[test] + fn parse_portrange() { + assert_eq!( + "1-100".parse::().unwrap(), + PortRange::new(1, 100).unwrap() + ); + assert_eq!( + "01-100".parse::().unwrap(), + PortRange::new(1, 100).unwrap() + ); + assert_eq!( + "1-65535".parse::().unwrap(), + PortRange::new_all() + ); + assert_eq!( + "10-30".parse::().unwrap(), + PortRange::new(10, 30).unwrap() + ); + assert_eq!( + "9001".parse::().unwrap(), + PortRange::new(9001, 9001).unwrap() + ); + assert_eq!( + "9001-9001".parse::().unwrap(), + PortRange::new(9001, 9001).unwrap() + ); + assert_eq!("*".parse::().unwrap(), PortRange::new_all()); + + assert!("hello".parse::().is_err()); + assert!("0".parse::().is_err()); + assert!("65536".parse::().is_err()); + assert!("65537".parse::().is_err()); + assert!("1-2-3".parse::().is_err()); + assert!("10-5".parse::().is_err()); + assert!("1-".parse::().is_err()); + assert!("-2".parse::().is_err()); + assert!("-".parse::().is_err()); + } + + #[test] + fn test_portrange() { + assert!(PortRange::new_all().is_all()); + assert!(!PortRange::new(2, 65535).unwrap().is_all()); + + assert!(PortRange::new_all().contains(1)); + assert!(PortRange::new_all().contains(65535)); + assert!(PortRange::new_all().contains(7777)); + + assert!(PortRange::new(20, 30).unwrap().contains(20)); + assert!(PortRange::new(20, 30).unwrap().contains(25)); + assert!(PortRange::new(20, 30).unwrap().contains(30)); + assert!(!PortRange::new(20, 30).unwrap().contains(19)); + assert!(!PortRange::new(20, 30).unwrap().contains(31)); + } + + // this test exists due to manually implemented 'stringified_ip_pattern' on 'AddressPortPattern' + #[test] + fn policy_serde_json_roundtrip() { + let policy = AddressPolicy::parse_from_torrc( + r#" +ExitPolicy reject 1.2.3.4/32:* +ExitPolicy reject 1.2.3.5:* +ExitPolicy reject 1.2.3.6/16:* +ExitPolicy reject 1.2.3.6/16:123-456 +ExitPolicy accept *:53 +ExitPolicy accept6 *6:119 +ExitPolicy accept *4:120 +ExitPolicy reject6 [FC00::]/7:* +ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8329:* +ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8328:1234 +ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8328/64:1235 +ExitPolicy reject *:*"#, + ) + .unwrap(); + + let json = serde_json::to_string(&policy).unwrap(); + let recovered: AddressPolicy = serde_json::from_str(&json).unwrap(); + + assert_eq!(recovered, policy); + } +} diff --git a/common/exit-policy/src/policy/error.rs b/common/exit-policy/src/policy/error.rs new file mode 100644 index 0000000000..5a39e096e5 --- /dev/null +++ b/common/exit-policy/src/policy/error.rs @@ -0,0 +1,71 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::EXIT_POLICY_FIELD_NAME; +use std::net::AddrParseError; +use thiserror::Error; + +/// Error from an unparsable or invalid policy. +#[derive(Debug, Error)] +#[non_exhaustive] +pub enum PolicyError { + #[cfg(feature = "client")] + #[error("failed to fetch the remote policy: {source}")] + ClientError { + #[from] + source: reqwest::Error, + }, + + #[error("/{mask} is not a valid mask for an IpV4 address")] + InvalidIpV4Mask { mask: u8 }, + + #[error("/{mask} is not a valid mask for an IpV6 address")] + InvalidIpV6Mask { mask: u8 }, + + #[error("'{action}' is not a valid policy action")] + InvalidPolicyAction { action: String }, + + #[error("'{addr}' is not a valid Ip address: {source}")] + MalformedIpAddress { + addr: String, + #[source] + source: AddrParseError, + }, + + /// Attempted to use a bitmask with the address "*". + #[error("attempted to use a bitmask ('/{mask}') with the address '*'")] + MaskWithStar { mask: String }, + + /// Attempted to use a bitmask with the address "*4". + #[error("attempted to use a bitmask ('/{mask}') with the address '*4'")] + MaskWithV4Star { mask: String }, + + /// Attempted to use a bitmask with the address "*6". + #[error("attempted to use a bitmask ('/{mask}') with the address '*6'")] + MaskWithV6Star { mask: String }, + + #[error("'/{mask}' is not a valid mask")] + InvalidMask { mask: String }, + + /// A port was not a number in the range 1..65535 + #[error( + "the provided port '{raw}' was either malformed or was not in the valid 1..65535 range" + )] + InvalidPort { raw: String }, + + /// A port range had its starting-point higher than its ending point. + #[error("the provided port range ({start}-{end}) was invalid. either the start was 0 or it was greater than the end.")] + InvalidRange { start: u16, end: u16 }, + + #[error("could not parse '{raw}' into a valid policy address:port pattern")] + MalformedAddressPortPattern { raw: String }, + + #[error("could not parse '{raw}' into a valid address policy")] + MalformedAddressPolicy { raw: String }, + + #[error( + "the provided exit policy entry does not start with the expected '{}' prefix: '{entry}'", + EXIT_POLICY_FIELD_NAME + )] + NoExitPolicyPrefix { entry: String }, +} diff --git a/common/exit-policy/src/policy/mod.rs b/common/exit-policy/src/policy/mod.rs new file mode 100644 index 0000000000..2100ad311d --- /dev/null +++ b/common/exit-policy/src/policy/mod.rs @@ -0,0 +1,14 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +// adapted from: https://github.com/dgoulet-tor/arti/tree/781dc4bd64f515f0c13ae9907c473c2bad8fbf71 +// and https://github.com/torproject/tor/blob/3cb6a690be60fcdab60130402ff88dcfc0657596/contrib/or-tools/exitlist +// + https://github.com/torproject/tor/blob/3cb6a690be60fcdab60130402ff88dcfc0657596/src/feature/dirparse/policy_parse.c + +mod address_policy; +mod error; + +pub use address_policy::{ + AddressPolicy, AddressPolicyAction, AddressPolicyRule, AddressPortPattern, IpPattern, PortRange, +}; +pub use error::PolicyError; diff --git a/common/http-api-client/src/lib.rs b/common/http-api-client/src/lib.rs index 2d816cc142..c3c4f98f09 100644 --- a/common/http-api-client/src/lib.rs +++ b/common/http-api-client/src/lib.rs @@ -386,12 +386,16 @@ pub fn sanitize_url, V: AsRef>( let mut path_segments = url .path_segments_mut() .expect("provided validator url does not have a base!"); + + path_segments.pop_if_empty(); + for segment in segments { let segment = segment.strip_prefix('/').unwrap_or(segment); let segment = segment.strip_suffix('/').unwrap_or(segment); path_segments.push(segment); } + // I don't understand why compiler couldn't figure out that it's no longer used // and can be dropped drop(path_segments); diff --git a/common/network-defaults/src/mainnet.rs b/common/network-defaults/src/mainnet.rs index fd002d4db7..236c9d9f1f 100644 --- a/common/network-defaults/src/mainnet.rs +++ b/common/network-defaults/src/mainnet.rs @@ -27,6 +27,10 @@ pub const NYXD_URL: &str = "https://rpc.nymtech.net"; pub const NYM_API: &str = "https://validator.nymtech.net/api/"; pub const EXPLORER_API: &str = "https://explorer.nymtech.net/api/"; +// I'm making clippy mad on purpose, because that url HAS TO be updated and deployed before merging +pub const EXIT_POLICY_URL: &str = + "https://nymtech.net/.wellknown/network-requester/exit-policy.txt"; + pub(crate) fn validators() -> Vec { vec![ValidatorDetails::new(NYXD_URL, Some(NYM_API))] } @@ -101,6 +105,7 @@ pub fn export_to_env() { set_var_to_default(var_names::NYXD, NYXD_URL); set_var_to_default(var_names::NYM_API, NYM_API); set_var_to_default(var_names::EXPLORER_API, EXPLORER_API); + set_var_to_default(var_names::EXIT_POLICY_URL, EXIT_POLICY_URL); } pub fn export_to_env_if_not_set() { @@ -148,4 +153,5 @@ pub fn export_to_env_if_not_set() { set_var_conditionally_to_default(var_names::NYXD, NYXD_URL); set_var_conditionally_to_default(var_names::NYM_API, NYM_API); set_var_conditionally_to_default(var_names::EXPLORER_API, EXPLORER_API); + set_var_conditionally_to_default(var_names::EXIT_POLICY_URL, EXIT_POLICY_URL); } diff --git a/common/network-defaults/src/var_names.rs b/common/network-defaults/src/var_names.rs index d082045a03..c74117630e 100644 --- a/common/network-defaults/src/var_names.rs +++ b/common/network-defaults/src/var_names.rs @@ -27,6 +27,7 @@ pub const NAME_SERVICE_CONTRACT_ADDRESS: &str = "NAME_SERVICE_CONTRACT_ADDRESS"; pub const NYXD: &str = "NYXD"; pub const NYM_API: &str = "NYM_API"; pub const EXPLORER_API: &str = "EXPLORER_API"; +pub const EXIT_POLICY_URL: &str = "EXIT_POLICY"; pub const DKG_TIME_CONFIGURATION: &str = "DKG_TIME_CONFIGURATION"; diff --git a/common/socks5/requests/Cargo.toml b/common/socks5/requests/Cargo.toml index acb08b31a6..a5b60ee08f 100644 --- a/common/socks5/requests/Cargo.toml +++ b/common/socks5/requests/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" [dependencies] bincode = "1.3.3" log = { workspace = true } +nym-exit-policy = { path = "../../../common/exit-policy"} nym-service-providers-common = { path = "../../../service-providers/common" } nym-sphinx-addressing = { path = "../../../common/nymsphinx/addressing" } serde = { workspace = true, features = ["derive"] } diff --git a/common/socks5/requests/src/request.rs b/common/socks5/requests/src/request.rs index bca0bc25a5..72241f7ef2 100644 --- a/common/socks5/requests/src/request.rs +++ b/common/socks5/requests/src/request.rs @@ -103,9 +103,11 @@ pub struct SendRequest { } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[non_exhaustive] pub enum QueryRequest { OpenProxy, Description, + ExitPolicy, } #[derive(Debug, Clone)] diff --git a/common/socks5/requests/src/response.rs b/common/socks5/requests/src/response.rs index e7ea358479..584f39df5b 100644 --- a/common/socks5/requests/src/response.rs +++ b/common/socks5/requests/src/response.rs @@ -5,6 +5,7 @@ use crate::{ make_bincode_serializer, ConnectionId, InsufficientSocketDataError, SocketData, Socks5ProtocolVersion, Socks5RequestError, }; +use nym_exit_policy::ExitPolicy; use nym_service_providers_common::interface::{Serializable, ServiceProviderResponse}; use serde::{Deserialize, Serialize}; use tap::TapFallible; @@ -155,6 +156,18 @@ impl Socks5Response { content: Socks5ResponseContent::Query(query_response), } } + + pub fn new_query_error>( + protocol_version: Socks5ProtocolVersion, + message: S, + ) -> Socks5Response { + Socks5Response { + protocol_version, + content: Socks5ResponseContent::Query(QueryResponse::Error { + message: message.into(), + }), + } + } } #[derive(Clone, Debug, PartialEq, Eq)] @@ -296,9 +309,18 @@ impl ConnectionError { } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[non_exhaustive] pub enum QueryResponse { OpenProxy(bool), Description(String), + ExitPolicy { + enabled: bool, + upstream: String, + policy: Option, + }, + Error { + message: String, + }, } #[cfg(test)] @@ -364,11 +386,41 @@ mod tests { let bytes_description = description.clone().into_bytes(); assert_eq!(bytes_description, vec![3, 1, 3, 102, 111, 111]); + let error = Socks5ResponseContent::Query(QueryResponse::Error { + message: "this is an error".to_string(), + }); + let bytes_error = error.clone().into_bytes(); + assert_eq!( + bytes_error, + vec![ + 3, 3, 16, 116, 104, 105, 115, 32, 105, 115, 32, 97, 110, 32, 101, 114, 114, + 111, 114 + ] + ); + + let exit_policy = Socks5ResponseContent::Query(QueryResponse::ExitPolicy { + enabled: false, + upstream: "http://foo.bar".to_string(), + policy: Some(ExitPolicy::new_open()), + }); + let bytes_exit_policy = exit_policy.clone().into_bytes(); + assert_eq!( + bytes_exit_policy, + vec![ + 3, 2, 0, 14, 104, 116, 116, 112, 58, 47, 47, 102, 111, 111, 46, 98, 97, 114, 1, + 1, 0, 1, 42, 1, 251, 255, 255 + ] + ); + let open_proxy2 = Socks5ResponseContent::try_from_bytes(&bytes_open_proxy).unwrap(); let description2 = Socks5ResponseContent::try_from_bytes(&bytes_description).unwrap(); + let error2 = Socks5ResponseContent::try_from_bytes(&bytes_error).unwrap(); + let exit_policy2 = Socks5ResponseContent::try_from_bytes(&bytes_exit_policy).unwrap(); assert_eq!(open_proxy, open_proxy2); assert_eq!(description, description2); + assert_eq!(error, error2); + assert_eq!(exit_policy, exit_policy2); } } } diff --git a/gateway/src/commands/helpers.rs b/gateway/src/commands/helpers.rs index c58020ca3c..9029c14a7a 100644 --- a/gateway/src/commands/helpers.rs +++ b/gateway/src/commands/helpers.rs @@ -95,6 +95,8 @@ pub(crate) struct OverrideNetworkRequesterConfig { pub(crate) medium_toggle: bool, pub(crate) open_proxy: Option, + pub(crate) enable_exit_policy: Option, + pub(crate) enable_statistics: Option, pub(crate) statistics_recipient: Option, } @@ -204,6 +206,10 @@ pub(crate) fn override_network_requester_config( nym_network_requester::Config::with_open_proxy, opts.open_proxy, ) + .with_optional( + nym_network_requester::Config::with_old_allow_list, + opts.enable_exit_policy.map(|e| !e), + ) .with_optional( nym_network_requester::Config::with_enabled_statistics, opts.enable_statistics, diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index 645fbd7ab3..e5e14068a8 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -126,6 +126,12 @@ pub struct Init { )] medium_toggle: bool, + /// Specifies whether this network requester will run using the default ExitPolicy + /// as opposed to the allow list. + /// Note: this setting will become the default in the future releases. + #[clap(long)] + with_exit_policy: Option, + #[clap(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, } @@ -159,6 +165,7 @@ impl<'a> From<&'a Init> for OverrideNetworkRequesterConfig { no_cover: value.no_cover, medium_toggle: value.medium_toggle, open_proxy: value.open_proxy, + enable_exit_policy: value.with_exit_policy, enable_statistics: value.enable_statistics, statistics_recipient: value.statistics_recipient.clone(), } @@ -275,6 +282,7 @@ mod tests { fastmode: false, no_cover: false, medium_toggle: false, + with_exit_policy: None, }; std::env::set_var(BECH32_PREFIX, "n"); diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index 95dd0c5707..185bf75a53 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -126,6 +126,12 @@ pub struct Run { #[clap(long, group = "network", hide = true)] custom_mixnet: Option, + /// Specifies whether this network requester will run using the default ExitPolicy + /// as opposed to the allow list. + /// Note: this setting will become the default in the future releases. + #[clap(long)] + with_exit_policy: Option, + #[clap(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, @@ -162,6 +168,7 @@ impl<'a> From<&'a Run> for OverrideNetworkRequesterConfig { no_cover: value.no_cover, medium_toggle: value.medium_toggle, open_proxy: value.open_proxy, + enable_exit_policy: value.with_exit_policy, enable_statistics: value.enable_statistics, statistics_recipient: value.statistics_recipient.clone(), } diff --git a/gateway/src/commands/setup_network_requester.rs b/gateway/src/commands/setup_network_requester.rs index f59f37dbd5..6c45c05d19 100644 --- a/gateway/src/commands/setup_network_requester.rs +++ b/gateway/src/commands/setup_network_requester.rs @@ -12,46 +12,46 @@ use std::path::PathBuf; #[derive(Args, Clone)] pub struct CmdArgs { /// The id of the gateway you want to initialise local network requester for. - #[arg(long)] + #[clap(long)] id: String, /// Path to custom location for network requester's config. - #[arg(long)] + #[clap(long)] custom_config_path: Option, /// Specify whether the network requester should be enabled. // (you might want to create all the configs, generate keys, etc. but not actually run the NR just yet) - #[arg(long)] + #[clap(long)] enabled: Option, // note: those flags are set as bools as we want to explicitly override any settings values // so say `open_proxy` was set to true in the config.toml. youd have to explicitly state `open-proxy=false` // as an argument here to override it as opposed to not providing the value at all. /// Specifies whether this network requester should run in 'open-proxy' mode - #[arg(long)] + #[clap(long)] open_proxy: Option, /// Enable service anonymized statistics that get sent to a statistics aggregator server - #[arg(long)] + #[clap(long)] enable_statistics: Option, /// Mixnet client address where a statistics aggregator is running. The default value is a Nym /// aggregator client - #[arg(long)] + #[clap(long)] statistics_recipient: Option, /// Mostly debug-related option to increase default traffic rate so that you would not need to /// modify config post init - #[arg(long, hide = true, conflicts_with = "medium_toggle")] + #[clap(long, hide = true, conflicts_with = "medium_toggle")] fastmode: bool, /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) - #[arg(long, hide = true, conflicts_with = "medium_toggle")] + #[clap(long, hide = true, conflicts_with = "medium_toggle")] no_cover: bool, /// Enable medium mixnet traffic, for experiments only. /// This includes things like disabling cover traffic, no per hop delays, etc. - #[arg( + #[clap( long, hide = true, conflicts_with = "no_cover", @@ -59,6 +59,12 @@ pub struct CmdArgs { )] medium_toggle: bool, + /// Specifies whether this network requester will run using the default ExitPolicy + /// as opposed to the allow list. + /// Note: this setting will become the default in the future releases. + #[clap(long)] + with_exit_policy: Option, + #[clap(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, } @@ -70,6 +76,7 @@ impl<'a> From<&'a CmdArgs> for OverrideNetworkRequesterConfig { no_cover: value.no_cover, medium_toggle: value.medium_toggle, open_proxy: value.open_proxy, + enable_exit_policy: value.with_exit_policy, enable_statistics: value.enable_statistics, statistics_recipient: value.statistics_recipient.clone(), } diff --git a/gateway/src/http/mod.rs b/gateway/src/http/mod.rs index eabb377456..a53a966584 100644 --- a/gateway/src/http/mod.rs +++ b/gateway/src/http/mod.rs @@ -4,10 +4,13 @@ use crate::config::Config; use crate::error::GatewayError; use crate::node::helpers::load_public_key; +use log::warn; use nym_bin_common::bin_info_owned; use nym_crypto::asymmetric::{encryption, identity}; +use nym_network_requester::RequestFilter; use nym_node::error::NymNodeError; use nym_node::http::api::api_requests; +use nym_node::http::api::api_requests::v1::network_requester::exit_policy::models::UsedExitPolicy; use nym_node::http::api::api_requests::SignedHostInformation; use nym_node::http::router::WireguardAppState; use nym_node::wireguard::types::GatewayClientRegistry; @@ -98,44 +101,154 @@ fn load_network_requester_details( ) } -pub(crate) fn start_http_api( - gateway_config: &Config, - network_requester_config: Option<&nym_network_requester::Config>, - client_registry: Arc, - identity_keypair: &identity::KeyPair, +pub(crate) struct HttpApiBuilder<'a> { + gateway_config: &'a Config, + network_requester_config: Option<&'a nym_network_requester::Config>, + exit_policy: Option, + + identity_keypair: &'a identity::KeyPair, // TODO: this should be a wg specific key and not re-used sphinx sphinx_keypair: Arc, - task_client: TaskClient, -) -> Result<(), GatewayError> { - // is it suboptimal to load all the keys, etc for the second time after they've already been - // retrieved during startup of the rest of the components? - // yes, a bit. - // but in the grand scheme of things performance penalty is negligible since it's only happening on startup - // and makes the code a bit nicer to manage. on top of it, all of it will refactored anyway at some point - // (famous last words, eh? - 22.09.23) - let mut config = nym_node::http::Config::new( - bin_info_owned!(), - load_host_details( - gateway_config, - sphinx_keypair.public_key(), - identity_keypair, - )?, - ) - .with_gateway(load_gateway_details(gateway_config)?) - .with_landing_page_assets(gateway_config.http.landing_page_assets_path.as_ref()); + client_registry: Option>, +} - if let Some(nr_config) = network_requester_config { - config = config - .with_network_requester(load_network_requester_details(gateway_config, nr_config)?) +impl<'a> HttpApiBuilder<'a> { + pub(crate) fn new( + gateway_config: &'a Config, + identity_keypair: &'a identity::KeyPair, + sphinx_keypair: Arc, + ) -> Self { + HttpApiBuilder { + gateway_config, + network_requester_config: None, + exit_policy: None, + identity_keypair, + sphinx_keypair, + client_registry: None, + } } - let wg_state = WireguardAppState::new(sphinx_keypair, client_registry, Default::default()); - let router = nym_node::http::NymNodeRouter::new(config, Some(wg_state)); + #[must_use] + pub(crate) fn with_maybe_network_requester( + mut self, + network_requester_config: Option<&'a nym_network_requester::Config>, + ) -> Self { + self.network_requester_config = network_requester_config; + self + } - let server = router - .build_server(&gateway_config.http.bind_address)? - .with_task_client(task_client); - tokio::spawn(async move { server.run().await }); - Ok(()) + #[must_use] + pub(crate) fn with_maybe_network_request_filter( + mut self, + request_filter: Option, + ) -> Self { + let Some(request_filter) = request_filter else { + warn!("no valid request filter has been passed. no changes will be made"); + return self; + }; + + // we can cheat here a bit since we're not refreshing the exit policy + // thus: + // - we can ignore the Arc pointer and clone the inner value + // - we can set the last refresh time to the current time + // + // once we start refreshing it, we'll have to change it, but at that point + // the allow list will be probably be completely removed and thus the pointer management + // will be much easier + let Some(exit_policy) = request_filter.current_exit_policy_filter() else { + warn!("this node does not use an exit policy. no changes will be made"); + return self; + }; + + // if there's no upstream (i.e. open proxy), we couldn't have possibly updated it : ) + let last_updated = if exit_policy.upstream().is_some() { + #[allow(clippy::expect_used)] + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .expect("system clock is set to before the unix epoch") + .as_secs() + } else { + 0 + }; + + self.exit_policy = Some(UsedExitPolicy { + enabled: true, + upstream_source: exit_policy + .upstream() + .map(|u| u.to_string()) + .unwrap_or_default(), + last_updated, + policy: Some(exit_policy.policy().clone()), + }); + + self + } + + #[must_use] + pub(crate) fn with_wireguard_client_registry( + mut self, + client_registry: Arc, + ) -> Self { + self.client_registry = Some(client_registry); + self + } + + pub(crate) fn start(self, task_client: TaskClient) -> Result<(), GatewayError> { + // is it suboptimal to load all the keys, etc for the second time after they've already been + // retrieved during startup of the rest of the components? + // yes, a bit. + // but in the grand scheme of things performance penalty is negligible since it's only happening on startup + // and makes the code a bit nicer to manage. on top of it, all of it will refactored anyway at some point + // (famous last words, eh? - 22.09.23) + let mut config = nym_node::http::Config::new( + bin_info_owned!(), + load_host_details( + self.gateway_config, + self.sphinx_keypair.public_key(), + self.identity_keypair, + )?, + ) + .with_gateway(load_gateway_details(self.gateway_config)?) + .with_landing_page_assets(self.gateway_config.http.landing_page_assets_path.as_ref()); + + if let Some(nr_config) = self.network_requester_config { + config = config.with_network_requester(load_network_requester_details( + self.gateway_config, + nr_config, + )?); + + if let Some(exit_policy) = self.exit_policy { + config = config.with_used_exit_policy(exit_policy) + } + } + + let wg_state = self.client_registry.map(|client_registry| { + WireguardAppState::new(self.sphinx_keypair, client_registry, Default::default()) + }); + + let router = nym_node::http::NymNodeRouter::new(config, wg_state); + + let server = router + .build_server(&self.gateway_config.http.bind_address)? + .with_task_client(task_client); + tokio::spawn(async move { server.run().await }); + Ok(()) + } } + +// pub(crate) fn start_http_api( +// gateway_config: &Config, +// network_requester_config: Option<&nym_network_requester::Config>, +// client_registry: Arc, +// identity_keypair: &identity::KeyPair, +// // TODO: this should be a wg specific key and not re-used sphinx +// sphinx_keypair: Arc, +// +// task_client: TaskClient, +// ) -> Result<(), GatewayError> { +// HttpApiBuilder::new(gateway_config, identity_keypair, sphinx_keypair) +// .with_wireguard_client_registry(client_registry) +// .with_network_requester(network_requester_config) +// .start(task_client) +// } diff --git a/gateway/src/node/client_handling/embedded_network_requester/mod.rs b/gateway/src/node/client_handling/embedded_network_requester/mod.rs index 7d2d612aa0..e088535cd9 100644 --- a/gateway/src/node/client_handling/embedded_network_requester/mod.rs +++ b/gateway/src/node/client_handling/embedded_network_requester/mod.rs @@ -6,7 +6,6 @@ use crate::node::client_handling::websocket::message_receiver::{ }; use futures::StreamExt; use log::{debug, error}; -use nym_network_requester::core::OnStartData; use nym_network_requester::{GatewayPacketRouter, PacketRouter}; use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::DestinationAddressBytes; @@ -22,9 +21,9 @@ pub(crate) struct LocalNetworkRequesterHandle { } impl LocalNetworkRequesterHandle { - pub(crate) fn new(start_data: OnStartData, mix_message_sender: MixMessageSender) -> Self { + pub(crate) fn new(address: Recipient, mix_message_sender: MixMessageSender) -> Self { Self { - address: start_data.address, + address, mix_message_sender, } } diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index f902bb66d7..a51180ba35 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -5,7 +5,7 @@ use self::storage::PersistentStorage; use crate::commands::helpers::{override_network_requester_config, OverrideNetworkRequesterConfig}; use crate::config::Config; use crate::error::GatewayError; -use crate::http::start_http_api; +use crate::http::HttpApiBuilder; use crate::node::client_handling::active_clients::ActiveClientsStore; use crate::node::client_handling::embedded_network_requester::{ LocalNetworkRequesterHandle, MessageRouter, @@ -23,7 +23,7 @@ use log::*; use nym_crypto::asymmetric::{encryption, identity}; use nym_mixnet_client::forwarder::{MixForwardingSender, PacketForwarder}; use nym_network_defaults::NymNetworkDetails; -use nym_network_requester::{LocalGateway, NRServiceProviderBuilder}; +use nym_network_requester::{LocalGateway, NRServiceProviderBuilder, RequestFilter}; use nym_node::wireguard::types::GatewayClientRegistry; use nym_statistics_common::collector::StatisticsSender; use nym_task::{TaskClient, TaskManager}; @@ -41,6 +41,15 @@ pub(crate) mod mixnet_handling; pub(crate) mod statistics; pub(crate) mod storage; +// TODO: should this struct live here? +struct StartedNetworkRequester { + /// Request filter, either an exit policy or the allow list, used by the network requester. + used_request_filter: RequestFilter, + + /// Handle to interact with the local network requester + handle: LocalNetworkRequesterHandle, +} + /// Wire up and create Gateway instance pub(crate) async fn create_gateway( config: Config, @@ -215,7 +224,7 @@ impl Gateway { &self, forwarding_channel: MixForwardingSender, shutdown: TaskClient, - ) -> Result { + ) -> Result { info!("Starting network requester..."); // if network requester is enabled, configuration file must be provided! @@ -235,7 +244,6 @@ impl Gateway { router_tx, ); - // TODO: well, wire it up internally to gateway traffic, shutdowns, etc. let (on_start_tx, on_start_rx) = oneshot::channel(); let mut nr_builder = NRServiceProviderBuilder::new(nr_opts.config.clone()) .with_shutdown(shutdown) @@ -266,12 +274,13 @@ impl Gateway { }; MessageRouter::new(nr_mix_receiver, packet_router).start_with_shutdown(router_shutdown); - info!( - "the local network requester is running on {}", - start_data.address - ); + let address = start_data.address; - Ok(LocalNetworkRequesterHandle::new(start_data, nr_mix_sender)) + info!("the local network requester is running on {address}",); + Ok(StartedNetworkRequester { + used_request_filter: start_data.request_filter, + handle: LocalNetworkRequesterHandle::new(address, nr_mix_sender), + }) } async fn wait_for_interrupt(shutdown: TaskManager) -> Result<(), Box> { @@ -340,15 +349,6 @@ impl Gateway { CoconutVerifier::new(nyxd_client) }; - start_http_api( - &self.config, - self.network_requester_opts.as_ref().map(|o| &o.config), - self.client_registry.clone(), - self.identity_keypair.as_ref(), - self.sphinx_keypair.clone(), - shutdown.subscribe().named("http-api"), - )?; - let mix_forwarding_channel = self.start_packet_forwarder(shutdown.subscribe().named("PacketForwarder")); @@ -372,7 +372,7 @@ impl Gateway { }); } - if self.config.network_requester.enabled { + let nr_request_filter = if self.config.network_requester.enabled { let embedded_nr = self .start_network_requester( mix_forwarding_channel.clone(), @@ -380,10 +380,22 @@ impl Gateway { ) .await?; // insert information about embedded NR to the active clients store - active_clients_store.insert_embedded(embedded_nr) + active_clients_store.insert_embedded(embedded_nr.handle); + Some(embedded_nr.used_request_filter) } else { info!("embedded network requester is disabled"); - } + None + }; + + HttpApiBuilder::new( + &self.config, + self.identity_keypair.as_ref(), + self.sphinx_keypair.clone(), + ) + .with_wireguard_client_registry(self.client_registry.clone()) + .with_maybe_network_requester(self.network_requester_opts.as_ref().map(|o| &o.config)) + .with_maybe_network_request_filter(nr_request_filter) + .start(shutdown.subscribe().named("http-api"))?; self.start_client_websocket_listener( mix_forwarding_channel, diff --git a/nym-connect/desktop/Cargo.lock b/nym-connect/desktop/Cargo.lock index 83a2c97fe9..6dbf35cc44 100644 --- a/nym-connect/desktop/Cargo.lock +++ b/nym-connect/desktop/Cargo.lock @@ -4278,6 +4278,15 @@ dependencies = [ "nym-contracts-common", ] +[[package]] +name = "nym-exit-policy" +version = "0.1.0" +dependencies = [ + "serde", + "thiserror", + "tracing", +] + [[package]] name = "nym-explorer-api-requests" version = "0.1.0" @@ -4432,6 +4441,7 @@ dependencies = [ "base64 0.21.4", "nym-bin-common", "nym-crypto", + "nym-exit-policy", "nym-wireguard-types", "schemars", "serde", @@ -4558,6 +4568,7 @@ version = "0.1.0" dependencies = [ "bincode", "log", + "nym-exit-policy", "nym-service-providers-common", "nym-sphinx-addressing", "serde", diff --git a/nym-node/nym-node-requests/Cargo.toml b/nym-node/nym-node-requests/Cargo.toml index ff7cb13336..bea55fbffb 100644 --- a/nym-node/nym-node-requests/Cargo.toml +++ b/nym-node/nym-node-requests/Cargo.toml @@ -18,6 +18,7 @@ serde_json = { workspace = true } thiserror = { workspace = true } nym-crypto = { path = "../../common/crypto", features = ["asymmetric"] } +nym-exit-policy = { path = "../../common/exit-policy" } nym-wireguard-types = { path = "../../common/wireguard-types", default-features = false } # feature-specific dependencies: @@ -36,4 +37,4 @@ tokio = { workspace = true, features = ["full"] } [features] default = ["client"] client = ["http-api-client", "async-trait"] -openapi = ["utoipa", "nym-bin-common/openapi", "nym-wireguard-types/openapi"] +openapi = ["utoipa", "nym-bin-common/openapi", "nym-wireguard-types/openapi", "nym-exit-policy/openapi"] diff --git a/nym-node/nym-node-requests/src/api/v1/network_requester/exit_policy/mod.rs b/nym-node/nym-node-requests/src/api/v1/network_requester/exit_policy/mod.rs new file mode 100644 index 0000000000..c57081432b --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/network_requester/exit_policy/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod models; diff --git a/nym-node/nym-node-requests/src/api/v1/network_requester/exit_policy/models.rs b/nym-node/nym-node-requests/src/api/v1/network_requester/exit_policy/models.rs new file mode 100644 index 0000000000..bd54d9ec3e --- /dev/null +++ b/nym-node/nym-node-requests/src/api/v1/network_requester/exit_policy/models.rs @@ -0,0 +1,44 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub use nym_exit_policy::{ + AddressPolicy, AddressPolicyAction, AddressPolicyRule, AddressPortPattern, ExitPolicy, + PortRange, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] +pub struct UsedExitPolicy { + /// Flag indicating whether this node uses the below exit policy or + /// whether it still relies on the legacy allow lists. + pub enabled: bool, + + /// Source URL from which the exit policy was obtained + #[cfg_attr( + feature = "openapi", + schema(example = "https://nymtech.net/.wellknown/network-requester/exit-policy.txt") + )] + pub upstream_source: String, + + /// Unix timestamp indicating when the exit policy was last updated from the upstream. + #[cfg_attr(feature = "openapi", schema(example = 1697731611))] + pub last_updated: u64, + + /// The actual policy used by this node. + // `ExitPolicy` is a type alias for `AddressPolicy`, + // but it seems utoipa is too stupid to realise it by itself + #[cfg_attr(feature = "openapi", schema(value_type = Option))] + pub policy: Option, +} + +impl Default for UsedExitPolicy { + fn default() -> Self { + UsedExitPolicy { + enabled: false, + upstream_source: "".to_string(), + last_updated: 0, + policy: None, + } + } +} diff --git a/nym-node/nym-node-requests/src/api/v1/network_requester/mod.rs b/nym-node/nym-node-requests/src/api/v1/network_requester/mod.rs index c57081432b..6309de6974 100644 --- a/nym-node/nym-node-requests/src/api/v1/network_requester/mod.rs +++ b/nym-node/nym-node-requests/src/api/v1/network_requester/mod.rs @@ -1,4 +1,5 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +pub mod exit_policy; pub mod models; diff --git a/nym-node/nym-node-requests/src/api/v1/network_requester/models.rs b/nym-node/nym-node-requests/src/api/v1/network_requester/models.rs index b8aa29236b..08bb332356 100644 --- a/nym-node/nym-node-requests/src/api/v1/network_requester/models.rs +++ b/nym-node/nym-node-requests/src/api/v1/network_requester/models.rs @@ -16,16 +16,3 @@ pub struct NetworkRequester { /// Nym address of this network requester. pub address: String, } - -// #[derive(Serialize, Debug, Clone, ToSchema)] -// pub struct ExitPolicy { -// // pub allowed_ports: -// // pub deny_list: DenyList, -// } -// -// #[derive(Serialize, Debug, Clone, ToSchema)] -// pub struct DenyListEntry { -// // pub ports: -// // pub ips: -// pub description: String, -// } diff --git a/nym-node/nym-node-requests/src/lib.rs b/nym-node/nym-node-requests/src/lib.rs index e1922f5d3b..cb7942f861 100644 --- a/nym-node/nym-node-requests/src/lib.rs +++ b/nym-node/nym-node-requests/src/lib.rs @@ -86,7 +86,15 @@ pub mod routes { } pub mod network_requester { - // use super::*; + use super::*; + + pub const EXIT_POLICY: &str = "/exit-policy"; + + absolute_route!( + exit_policy_absolute, + network_requester_absolute(), + EXIT_POLICY + ); } } } diff --git a/nym-node/src/http/router/api/v1/network_requester/exit_policy.rs b/nym-node/src/http/router/api/v1/network_requester/exit_policy.rs new file mode 100644 index 0000000000..a743f20514 --- /dev/null +++ b/nym-node/src/http/router/api/v1/network_requester/exit_policy.rs @@ -0,0 +1,30 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::http::api::{FormattedResponse, OutputParams}; +use axum::extract::Query; +use nym_node_requests::api::v1::network_requester::exit_policy::models::UsedExitPolicy; + +/// Returns information about the exit policy used by this node. +#[utoipa::path( + get, + path = "/exit-policy", + context_path = "/api/v1/network-requester", + tag = "Network Requester", + responses( + (status = 200, content( + ("application/json" = UsedExitPolicy), + ("application/yaml" = UsedExitPolicy) + )) + ), + params(OutputParams) +)] +pub(crate) async fn node_exit_policy( + policy: UsedExitPolicy, + Query(output): Query, +) -> ExitPolicyResponse { + let output = output.output.unwrap_or_default(); + output.to_response(policy) +} + +pub type ExitPolicyResponse = FormattedResponse; diff --git a/nym-node/src/http/router/api/v1/network_requester/mod.rs b/nym-node/src/http/router/api/v1/network_requester/mod.rs index aced86bad3..7b2ebabf34 100644 --- a/nym-node/src/http/router/api/v1/network_requester/mod.rs +++ b/nym-node/src/http/router/api/v1/network_requester/mod.rs @@ -1,23 +1,36 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::http::api::v1::network_requester::exit_policy::node_exit_policy; use axum::routing::get; use axum::Router; +use nym_node_requests::api::v1::network_requester::exit_policy::models::UsedExitPolicy; use nym_node_requests::api::v1::network_requester::models; +use nym_node_requests::routes::api::v1::network_requester; +pub mod exit_policy; pub mod root; #[derive(Debug, Clone, Default)] pub struct Config { pub details: Option, + pub exit_policy: Option, } pub(crate) fn routes(config: Config) -> Router { - Router::new().route( - "/", - get({ - let network_requester_details = config.details; - move |query| root::root_network_requester(network_requester_details, query) - }), - ) + Router::new() + .route( + "/", + get({ + let network_requester_details = config.details; + move |query| root::root_network_requester(network_requester_details, query) + }), + ) + .route( + network_requester::EXIT_POLICY, + get({ + let policy = config.exit_policy.unwrap_or_default(); + move |query| node_exit_policy(policy, query) + }), + ) } diff --git a/nym-node/src/http/router/api/v1/openapi.rs b/nym-node/src/http/router/api/v1/openapi.rs index 8678c613d7..6302429f73 100644 --- a/nym-node/src/http/router/api/v1/openapi.rs +++ b/nym-node/src/http/router/api/v1/openapi.rs @@ -26,6 +26,7 @@ use utoipa_swagger_ui::SwaggerUi; api::v1::gateway::client_interfaces::wireguard::client_registry::get_client, api::v1::mixnode::root::root_mixnode, api::v1::network_requester::root::root_network_requester, + api::v1::network_requester::exit_policy::node_exit_policy, ), components( schemas( @@ -49,6 +50,12 @@ use utoipa_swagger_ui::SwaggerUi; api_requests::v1::gateway::client_interfaces::wireguard::models::ClientRegistrationResponse, api_requests::v1::mixnode::models::Mixnode, api_requests::v1::network_requester::models::NetworkRequester, + api_requests::v1::network_requester::exit_policy::models::AddressPolicy, + api_requests::v1::network_requester::exit_policy::models::AddressPolicyRule, + api_requests::v1::network_requester::exit_policy::models::AddressPolicyAction, + api_requests::v1::network_requester::exit_policy::models::AddressPortPattern, + api_requests::v1::network_requester::exit_policy::models::PortRange, + api_requests::v1::network_requester::exit_policy::models::UsedExitPolicy, ), responses(RequestError) ) diff --git a/nym-node/src/http/router/mod.rs b/nym-node/src/http/router/mod.rs index a25c6427f8..3548266373 100644 --- a/nym-node/src/http/router/mod.rs +++ b/nym-node/src/http/router/mod.rs @@ -9,6 +9,7 @@ use crate::http::NymNodeHTTPServer; use axum::Router; use nym_node_requests::api::v1::gateway::models::{Gateway, Wireguard}; use nym_node_requests::api::v1::mixnode::models::Mixnode; +use nym_node_requests::api::v1::network_requester::exit_policy::models::UsedExitPolicy; use nym_node_requests::api::v1::network_requester::models::NetworkRequester; use nym_node_requests::api::v1::node::models; use nym_node_requests::api::SignedHostInformation; @@ -87,6 +88,12 @@ impl Config { self.api.v1_config.network_requester.details = Some(network_requester); self } + + #[must_use] + pub fn with_used_exit_policy(mut self, exit_policy: UsedExitPolicy) -> Self { + self.api.v1_config.network_requester.exit_policy = Some(exit_policy); + self + } } pub struct NymNodeRouter { diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index c34975a3f3..42c54bc0b2 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -47,7 +47,7 @@ nym-config = { path = "../../common/config" } nym-credential-storage = { path = "../../common/credential-storage" } nym-crypto = { path = "../../common/crypto" } nym-network-defaults = { path = "../../common/network-defaults" } -nym-ordered-buffer = {path = "../../common/socks5/ordered-buffer"} +nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" } nym-sdk = { path = "../../sdk/rust/nym-sdk" } nym-service-providers-common = { path = "../common" } nym-socks5-proxy-helpers = { path = "../../common/socks5/proxy-helpers" } @@ -56,7 +56,8 @@ nym-sphinx = { path = "../../common/nymsphinx" } nym-statistics-common = { path = "../../common/statistics" } nym-task = { path = "../../common/task" } nym-types = { path = "../../common/types" } +nym-exit-policy = { path = "../../common/exit-policy", features = ["client"] } [dev-dependencies] tempfile = "3.5.0" -anyhow = "1.0.68" +anyhow = { workspace = true } diff --git a/service-providers/network-requester/src/cli/init.rs b/service-providers/network-requester/src/cli/init.rs index d4321846e7..d6c1960da6 100644 --- a/service-providers/network-requester/src/cli/init.rs +++ b/service-providers/network-requester/src/cli/init.rs @@ -29,42 +29,42 @@ use tap::TapFallible; #[derive(Args, Clone)] pub(crate) struct Init { /// Id of the nym-mixnet-client we want to create config for. - #[arg(long)] + #[clap(long)] id: String, /// Specifies whether this network requester should run in 'open-proxy' mode - #[arg(long)] + #[clap(long)] open_proxy: Option, /// Enable service anonymized statistics that get sent to a statistics aggregator server - #[arg(long)] + #[clap(long)] enable_statistics: Option, /// Mixnet client address where a statistics aggregator is running. The default value is a Nym /// aggregator client - #[arg(long)] + #[clap(long)] statistics_recipient: Option, /// Id of the gateway we are going to connect to. - #[arg(long)] + #[clap(long)] gateway: Option, /// Specifies whether the new gateway should be determined based by latency as opposed to being chosen /// uniformly. - #[arg(long, conflicts_with = "gateway")] + #[clap(long, conflicts_with = "gateway")] latency_based_selection: bool, /// Force register gateway. WARNING: this will overwrite any existing keys for the given id, /// potentially causing loss of access. - #[arg(long)] + #[clap(long)] force_register_gateway: bool, /// Comma separated list of rest endpoints of the nyxd validators - #[arg(long, alias = "nymd_validators", value_delimiter = ',')] + #[clap(long, alias = "nymd_validators", value_delimiter = ',')] nyxd_urls: Option>, /// Comma separated list of rest endpoints of the API validators - #[arg( + #[clap( long, alias = "api_validators", value_delimiter = ',', @@ -79,10 +79,16 @@ pub(crate) struct Init { /// Set this client to work in a enabled credentials mode that would attempt to use gateway /// with bandwidth credential requirement. - #[arg(long)] + #[clap(long)] enabled_credentials_mode: Option, - #[arg(short, long, default_value_t = OutputFormat::default())] + /// Specifies whether this network requester will run using the default ExitPolicy + /// as opposed to the allow list. + /// Note: this setting will become the default in the future releases. + #[clap(long)] + with_exit_policy: Option, + + #[clap(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, } @@ -95,6 +101,7 @@ impl From for OverrideConfig { medium_toggle: false, nyxd_urls: init_config.nyxd_urls, enabled_credentials_mode: init_config.enabled_credentials_mode, + enable_exit_policy: init_config.with_exit_policy, open_proxy: init_config.open_proxy, enable_statistics: init_config.enabled_credentials_mode, statistics_recipient: init_config.statistics_recipient, diff --git a/service-providers/network-requester/src/cli/mod.rs b/service-providers/network-requester/src/cli/mod.rs index 5566de0e93..c090912743 100644 --- a/service-providers/network-requester/src/cli/mod.rs +++ b/service-providers/network-requester/src/cli/mod.rs @@ -81,6 +81,7 @@ pub(crate) struct OverrideConfig { medium_toggle: bool, nyxd_urls: Option>, enabled_credentials_mode: Option, + enable_exit_policy: Option, open_proxy: Option, enable_statistics: Option, @@ -141,6 +142,10 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi args.enabled_credentials_mode.map(|b| !b), ) .with_optional(Config::with_open_proxy, args.open_proxy) + .with_optional( + Config::with_old_allow_list, + args.enable_exit_policy.map(|e| !e), + ) .with_optional(Config::with_enabled_statistics, args.enable_statistics) .with_optional(Config::with_statistics_recipient, args.statistics_recipient) } diff --git a/service-providers/network-requester/src/cli/run.rs b/service-providers/network-requester/src/cli/run.rs index 0973e473b7..c55e37ca48 100644 --- a/service-providers/network-requester/src/cli/run.rs +++ b/service-providers/network-requester/src/cli/run.rs @@ -59,6 +59,12 @@ pub(crate) struct Run { conflicts_with = "fastmode" )] medium_toggle: bool, + + /// Specifies whether this network requester will run using the default ExitPolicy + /// as opposed to the allow list. + /// Note: this setting will become the default in the future releases. + #[clap(long)] + with_exit_policy: Option, } impl From for OverrideConfig { @@ -70,6 +76,7 @@ impl From for OverrideConfig { medium_toggle: run_config.medium_toggle, nyxd_urls: None, enabled_credentials_mode: run_config.enabled_credentials_mode, + enable_exit_policy: run_config.with_exit_policy, open_proxy: run_config.open_proxy, enable_statistics: run_config.enabled_credentials_mode, statistics_recipient: run_config.statistics_recipient, diff --git a/service-providers/network-requester/src/config/mod.rs b/service-providers/network-requester/src/config/mod.rs index b26ec1ff20..81ace42e36 100644 --- a/service-providers/network-requester/src/config/mod.rs +++ b/service-providers/network-requester/src/config/mod.rs @@ -5,8 +5,9 @@ use crate::config::persistence::NetworkRequesterPaths; use crate::config::template::CONFIG_TEMPLATE; use nym_bin_common::logging::LoggingSettings; use nym_config::{ - must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate, - OptionalSet, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, + must_get_home, read_config_from_toml_file, save_formatted_config_to_file, + serde_helpers::de_maybe_stringified, NymConfigTemplate, OptionalSet, DEFAULT_CONFIG_DIR, + DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, }; use nym_service_providers_common::DEFAULT_SERVICE_PROVIDERS_DIR; use serde::{Deserialize, Serialize}; @@ -14,9 +15,11 @@ use std::io; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::time::Duration; +use url::Url; pub use nym_client_core::config::Config as BaseClientConfig; pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig}; +use nym_network_defaults::mainnet; use nym_sphinx::params::PacketSize; pub mod old_config_v1_1_13; @@ -141,6 +144,12 @@ impl Config { self } + #[must_use] + pub fn with_old_allow_list(mut self, use_old_allow_list: bool) -> Self { + self.network_requester.use_deprecated_allow_list = use_old_allow_list; + self + } + #[must_use] pub fn with_enabled_statistics(mut self, enabled_statistics: bool) -> Self { self.network_requester.enabled_statistics = enabled_statistics; @@ -216,6 +225,15 @@ pub struct NetworkRequester { /// 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. + /// Note: this field will be removed in a near future. + 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 NetworkRequester { @@ -225,6 +243,12 @@ 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() + .expect("invalid default exit policy URL"), + ), } } } @@ -233,6 +257,7 @@ impl Default for NetworkRequester { #[serde(default, deny_unknown_fields)] pub struct Debug { /// Defines how often the standard allow list should get updated + /// Deprecated #[serde(with = "humantime_serde")] pub standard_list_update_interval: Duration, } diff --git a/service-providers/network-requester/src/config/persistence.rs b/service-providers/network-requester/src/config/persistence.rs index 563116933d..d62ffcea9a 100644 --- a/service-providers/network-requester/src/config/persistence.rs +++ b/service-providers/network-requester/src/config/persistence.rs @@ -14,9 +14,11 @@ pub struct NetworkRequesterPaths { #[serde(flatten)] pub common_paths: CommonClientPaths, + /// Deprecated /// Location of the file containing our allow.list pub allowed_list_location: PathBuf, + /// Deprecated /// Location of the file containing our unknown.list pub unknown_list_location: PathBuf, diff --git a/service-providers/network-requester/src/config/template.rs b/service-providers/network-requester/src/config/template.rs index a6aebee454..ae039f5da4 100644 --- a/service-providers/network-requester/src/config/template.rs +++ b/service-providers/network-requester/src/config/template.rs @@ -95,6 +95,14 @@ statistics_recipient = '{{ network_requester.statistics_recipient }}' # This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true, disable_poisson_rate = {{ network_requester.disable_poisson_rate }} +# 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. +use_deprecated_allow_list = {{ network_requester.use_deprecated_allow_list }} + +# Specifies the url for an upstream source of the exit policy used by this node. +upstream_exit_policy_url = '{{ network_requester.upstream_exit_policy_url }}' + ##### logging configuration options ##### [logging] diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index 39b35708fd..8751b2265c 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -1,14 +1,12 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::allowed_hosts::standard_list::StandardListUpdater; -use crate::allowed_hosts::stored_allowed_hosts::{start_allowed_list_reloader, StoredAllowedHosts}; -use crate::allowed_hosts::{OutboundRequestFilter, StandardList}; use crate::config::{BaseClientConfig, Config}; use crate::error::NetworkRequesterError; use crate::reply::MixnetMessage; +use crate::request_filter::RequestFilter; use crate::statistics::ServiceStatisticsCollector; -use crate::{allowed_hosts, reply, socks5}; +use crate::{reply, socks5}; use async_trait::async_trait; use futures::channel::{mpsc, oneshot}; use futures::stream::StreamExt; @@ -56,11 +54,16 @@ pub(crate) fn new_legacy_request_version() -> RequestVersion { pub struct OnStartData { // to add more fields as required pub address: Recipient, + + pub request_filter: RequestFilter, } impl OnStartData { - fn new(address: Recipient) -> Self { - Self { address } + fn new(address: Recipient, request_filter: RequestFilter) -> Self { + Self { + address, + request_filter, + } } } @@ -68,7 +71,6 @@ impl OnStartData { // ... something ... pub struct NRServiceProviderBuilder { config: Config, - outbound_request_filter: OutboundRequestFilter, wait_for_gateway: bool, custom_topology_provider: Option>, @@ -79,7 +81,7 @@ pub struct NRServiceProviderBuilder { pub struct NRServiceProvider { config: Config, - outbound_request_filter: OutboundRequestFilter, + request_filter: RequestFilter, mixnet_client: nym_sdk::mixnet::MixnetClient, controller_sender: ControllerSender, @@ -179,18 +181,8 @@ impl ServiceProvider for NRServiceProvider { impl NRServiceProviderBuilder { pub fn new(config: Config) -> NRServiceProviderBuilder { - let standard_list = StandardList::new(); - - let allowed_hosts = StoredAllowedHosts::new(&config.storage_paths.allowed_list_location); - let unknown_hosts = - allowed_hosts::HostsStore::new(&config.storage_paths.unknown_list_location); - - let outbound_request_filter = - OutboundRequestFilter::new(allowed_hosts, standard_list, unknown_hosts); - NRServiceProviderBuilder { config, - outbound_request_filter, wait_for_gateway: false, custom_topology_provider: None, custom_gateway_transceiver: None, @@ -334,26 +326,14 @@ impl NRServiceProviderBuilder { .await; }); - // start the standard list updater - StandardListUpdater::new( - self.config - .network_requester_debug - .standard_list_update_interval, - self.outbound_request_filter.standard_list(), - shutdown.get_handle().named("StandardListUpdater"), - ) - .start(); - - // start the allowed.list watcher and updater - start_allowed_list_reloader( - self.outbound_request_filter.allowed_hosts(), - shutdown.get_handle().named("stored_allowed_hosts_reloader"), - ) - .await; + let request_filter = RequestFilter::new(&self.config).await?; + request_filter + .start_update_tasks(&self.config.network_requester_debug, &shutdown) + .await; let mut service_provider = NRServiceProvider { config: self.config, - outbound_request_filter: self.outbound_request_filter, + request_filter: request_filter.clone(), mixnet_client, controller_sender, mix_input_sender, @@ -365,7 +345,10 @@ impl NRServiceProviderBuilder { log::info!("All systems go. Press CTRL-C to stop the server."); if let Some(on_start) = self.on_start { - if on_start.send(OnStartData::new(self_address)).is_err() { + if on_start + .send(OnStartData::new(self_address, request_filter)) + .is_err() + { // the parent has dropped the channel before receiving the response return Err(NetworkRequesterError::DisconnectedParent); } @@ -533,7 +516,7 @@ impl NRServiceProvider { } async fn handle_proxy_connect( - &mut self, + &self, remote_version: RequestVersion, sender_tag: Option, connect_req: Box, @@ -549,24 +532,6 @@ impl NRServiceProvider { let remote_addr = connect_req.remote_addr; let conn_id = connect_req.conn_id; - - let open_proxy = self.config.network_requester.open_proxy; - if !open_proxy && !self.outbound_request_filter.check(&remote_addr).await { - let log_msg = format!("Domain {remote_addr:?} failed filter check"); - log::info!("{log_msg}"); - let msg = MixnetMessage::new_connection_error( - return_address, - remote_version, - conn_id, - log_msg, - ); - self.mix_input_sender - .send(msg) - .await - .expect("InputMessageReceiver has stopped receiving!"); - return; - } - let traffic_config = self.config.base.debug.traffic; let packet_size = traffic_config .secondary_packet_size @@ -575,10 +540,34 @@ impl NRServiceProvider { let controller_sender_clone = self.controller_sender.clone(); let mix_input_sender_clone = self.mix_input_sender.clone(); let lane_queue_lengths_clone = self.mixnet_client.shared_lane_queue_lengths(); - let shutdown = self.shutdown.get_handle(); + let mut shutdown = self.shutdown.get_handle(); - // and start the proxy for this connection + // we're just cloning the underlying pointer, nothing expensive is happening here + let request_filter = self.request_filter.clone(); + + // at this point move it into the separate task + // because we might have to resolve the underlying address and it can take some time + // during which we don't want to block other incoming requests tokio::spawn(async move { + if !request_filter.check_address(&remote_addr).await { + let log_msg = format!("Domain {remote_addr:?} failed filter check"); + log::info!("{log_msg}"); + let error_msg = MixnetMessage::new_connection_error( + return_address, + remote_version, + conn_id, + log_msg, + ); + + mix_input_sender_clone + .send(error_msg) + .await + .expect("InputMessageReceiver has stopped receiving!"); + shutdown.mark_as_success(); + return; + } + + // if all is good, start the proxy for this connection Self::start_proxy( remote_version, conn_id, @@ -615,6 +604,28 @@ impl NRServiceProvider { protocol_version, QueryResponse::Description("Description (placeholder)".to_string()), ), + QueryRequest::ExitPolicy => { + let response = match self.request_filter.current_exit_policy_filter() { + Some(exit_policy_filter) => QueryResponse::ExitPolicy { + enabled: true, + upstream: exit_policy_filter + .upstream() + .map(|u| u.to_string()) + .unwrap_or_default(), + policy: Some(exit_policy_filter.policy().clone()), + }, + None => QueryResponse::ExitPolicy { + enabled: false, + upstream: "".to_string(), + policy: None, + }, + }; + + Socks5Response::new_query(protocol_version, response) + } + _ => { + Socks5Response::new_query_error(protocol_version, "received unknown query variant") + } }; Ok(Some(response)) } diff --git a/service-providers/network-requester/src/error.rs b/service-providers/network-requester/src/error.rs index cb71cd715a..fb05dc976f 100644 --- a/service-providers/network-requester/src/error.rs +++ b/service-providers/network-requester/src/error.rs @@ -1,5 +1,7 @@ pub use nym_client_core::error::ClientCoreError; -use nym_socks5_requests::Socks5RequestError; +use nym_exit_policy::policy::PolicyError; +use nym_socks5_requests::{RemoteAddress, Socks5RequestError}; +use std::net::SocketAddr; #[derive(thiserror::Error, Debug)] pub enum NetworkRequesterError { @@ -33,4 +35,33 @@ pub enum NetworkRequesterError { #[error("the entity wrapping the network requester has disconnected")] DisconnectedParent, + + #[error("the provided socket address, '{addr}' is not covered by the exit policy!")] + AddressNotCoveredByExitPolicy { addr: SocketAddr }, + + #[error( + "could not resolve socket address for the provided remote address '{remote}': {source}" + )] + CouldNotResolveHost { + remote: RemoteAddress, + source: std::io::Error, + }, + + #[error("the provided address: '{remote}' was somehow resolved to an empty list of socket addresses")] + EmptyResolvedAddresses { remote: RemoteAddress }, + + #[error("failed to apply the exit policy: {source}")] + ExitPolicyFailure { + #[from] + source: PolicyError, + }, + + #[error("the url provided for the upstream exit policy source is malformed: {source}")] + MalformedExitPolicyUpstreamUrl { + #[source] + source: reqwest::Error, + }, + + #[error("can't setup an exit policy without any upstream urls")] + NoUpstreamExitPolicy, } diff --git a/service-providers/network-requester/src/lib.rs b/service-providers/network-requester/src/lib.rs index cc3915c481..1b730aacd1 100644 --- a/service-providers/network-requester/src/lib.rs +++ b/service-providers/network-requester/src/lib.rs @@ -1,11 +1,11 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -pub mod allowed_hosts; pub mod config; pub mod core; pub mod error; mod reply; +pub mod request_filter; mod socks5; mod statistics; @@ -25,3 +25,4 @@ pub use nym_client_core::{ }, }, }; +pub use request_filter::RequestFilter; diff --git a/service-providers/network-requester/src/main.rs b/service-providers/network-requester/src/main.rs index 76e9349a7e..a8efdf0f76 100644 --- a/service-providers/network-requester/src/main.rs +++ b/service-providers/network-requester/src/main.rs @@ -6,12 +6,12 @@ use error::NetworkRequesterError; use nym_bin_common::logging::{maybe_print_banner, setup_logging}; use nym_network_defaults::setup_env; -mod allowed_hosts; mod cli; mod config; mod core; mod error; mod reply; +mod request_filter; mod socks5; mod statistics; diff --git a/service-providers/network-requester/src/allowed_hosts/filter.rs b/service-providers/network-requester/src/request_filter/allowed_hosts/filter.rs similarity index 88% rename from service-providers/network-requester/src/allowed_hosts/filter.rs rename to service-providers/network-requester/src/request_filter/allowed_hosts/filter.rs index bb33bb931d..5b46f85c41 100644 --- a/service-providers/network-requester/src/allowed_hosts/filter.rs +++ b/service-providers/network-requester/src/request_filter/allowed_hosts/filter.rs @@ -2,10 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 use super::HostsStore; -use crate::allowed_hosts::group::HostsGroup; -use crate::allowed_hosts::standard_list::StandardList; -use crate::allowed_hosts::stored_allowed_hosts::StoredAllowedHosts; +use crate::request_filter::allowed_hosts::group::HostsGroup; +use crate::request_filter::allowed_hosts::standard_list::StandardList; +use crate::request_filter::allowed_hosts::stored_allowed_hosts::StoredAllowedHosts; use std::net::{IpAddr, SocketAddr}; +use tokio::sync::Mutex; #[derive(Debug)] enum RequestHost { @@ -31,7 +32,7 @@ pub(crate) struct OutboundRequestFilter { pub(super) allowed_hosts: StoredAllowedHosts, pub(super) standard_list: StandardList, root_domain_list: publicsuffix::List, - unknown_hosts: HostsStore, + unknown_hosts: Mutex, } impl OutboundRequestFilter { @@ -56,7 +57,7 @@ impl OutboundRequestFilter { allowed_hosts, standard_list, root_domain_list: domain_list, - unknown_hosts, + unknown_hosts: Mutex::new(unknown_hosts), } } @@ -86,11 +87,12 @@ impl OutboundRequestFilter { } } - fn add_to_unknown_hosts(&mut self, host: RequestHost) { + async fn add_to_unknown_hosts(&self, host: RequestHost) { + let mut guard = self.unknown_hosts.lock().await; match host { - RequestHost::IpAddr(ip_addr) => self.unknown_hosts.add_ip(ip_addr), - RequestHost::SocketAddr(socket_addr) => self.unknown_hosts.add_ip(socket_addr.ip()), - RequestHost::RootDomain(domain) => self.unknown_hosts.add_domain(&domain), + RequestHost::IpAddr(ip_addr) => guard.add_ip(ip_addr), + RequestHost::SocketAddr(socket_addr) => guard.add_ip(socket_addr.ip()), + RequestHost::RootDomain(domain) => guard.add_domain(&domain), } } @@ -112,7 +114,7 @@ impl OutboundRequestFilter { } } - async fn check_request_host(&mut self, request_host: &RequestHost) -> bool { + async fn check_request_host(&self, request_host: &RequestHost) -> bool { // first check our own allow list let local_allowed = self.check_allowed_hosts(request_host).await; @@ -128,12 +130,12 @@ impl OutboundRequestFilter { /// Returns `true` if a host's root domain is in the `allowed_hosts` list. /// /// If it's not in the list, return `false` and write it to the `unknown_hosts` storefile. - pub(crate) async fn check(&mut self, host: &str) -> bool { + pub(crate) async fn check(&self, host: &str) -> bool { let allowed = match self.parse_request_host(host) { Some(request_host) => { let res = self.check_request_host(&request_host).await; if !res { - self.add_to_unknown_hosts(request_host) + self.add_to_unknown_hosts(request_host).await } res } @@ -352,20 +354,32 @@ mod tests { #[tokio::test] async fn are_not_allowed() { let host = "unknown.com"; - let mut filter = setup_empty(); + let filter = setup_empty(); assert!(!filter.check(host).await); } #[tokio::test] async fn get_appended_once_to_the_unknown_hosts_list() { let host = "unknown.com"; - let mut filter = setup_empty(); + let filter = setup_empty(); filter.check(host).await; - assert_eq!(1, filter.unknown_hosts.data.domains.len()); - assert!(filter.unknown_hosts.data.domains.contains("unknown.com")); + assert_eq!(1, filter.unknown_hosts.lock().await.data.domains.len()); + assert!(filter + .unknown_hosts + .lock() + .await + .data + .domains + .contains("unknown.com")); filter.check(host).await; - assert_eq!(1, filter.unknown_hosts.data.domains.len()); - assert!(filter.unknown_hosts.data.domains.contains("unknown.com")); + assert_eq!(1, filter.unknown_hosts.lock().await.data.domains.len()); + assert!(filter + .unknown_hosts + .lock() + .await + .data + .domains + .contains("unknown.com")); } } @@ -377,7 +391,7 @@ mod tests { async fn are_allowed() { let host = "nymtech.net"; - let mut filter = setup_with_allowed(&["nymtech.net"]); + let filter = setup_with_allowed(&["nymtech.net"]); assert!(filter.check(host).await); } @@ -385,13 +399,13 @@ mod tests { async fn are_allowed_for_subdomains() { let host = "foomp.nymtech.net"; - let mut filter = setup_with_allowed(&["nymtech.net"]); + let filter = setup_with_allowed(&["nymtech.net"]); assert!(filter.check(host).await); } #[tokio::test] async fn are_not_appended_to_file() { - let mut filter = setup_with_allowed(&["nymtech.net"]); + let filter = setup_with_allowed(&["nymtech.net"]); // test initial state let lines = @@ -414,7 +428,7 @@ mod tests { let address_good_port = "1.1.1.1:1234"; let address_bad = "1.1.1.2"; - let mut filter = setup_with_allowed(&["1.1.1.1"]); + let filter = setup_with_allowed(&["1.1.1.1"]); assert!(filter.check(address_good).await); assert!(filter.check(address_good_port).await); assert!(!filter.check(address_bad).await); @@ -431,9 +445,8 @@ mod tests { let ip_v6_loopback_port = "[::1]:1234"; - let mut filter1 = setup_with_allowed(&[ip_v6_full, ip_v6_semi, "::1"]); - let mut filter2 = - setup_with_allowed(&[ip_v6_full_rendered, ip_v6_semi_rendered, "::1"]); + let filter1 = setup_with_allowed(&[ip_v6_full, ip_v6_semi, "::1"]); + let filter2 = setup_with_allowed(&[ip_v6_full_rendered, ip_v6_semi_rendered, "::1"]); assert!(filter1.check(ip_v6_full).await); assert!(filter1.check(ip_v6_full_rendered).await); @@ -460,7 +473,7 @@ mod tests { let outside_range2 = "1.2.2.4"; - let mut filter = setup_with_allowed(&[range1, range2]); + let filter = setup_with_allowed(&[range1, range2]); assert!(filter.check("127.0.0.1").await); assert!(filter.check("127.0.0.1:1234").await); assert!(filter.check(bottom_range2).await); @@ -478,7 +491,7 @@ mod tests { let top = "2620:0:ffff:ffff:ffff:ffff:ffff:ffff"; let mid = "2620:0:42::42"; - let mut filter = setup_with_allowed(&[range]); + let filter = setup_with_allowed(&[range]); assert!(filter.check(bottom1).await); assert!(filter.check(bottom2).await); assert!(filter.check(top).await); diff --git a/service-providers/network-requester/src/allowed_hosts/group.rs b/service-providers/network-requester/src/request_filter/allowed_hosts/group.rs similarity index 96% rename from service-providers/network-requester/src/allowed_hosts/group.rs rename to service-providers/network-requester/src/request_filter/allowed_hosts/group.rs index 5b398e1ff0..5b5ba4c75a 100644 --- a/service-providers/network-requester/src/allowed_hosts/group.rs +++ b/service-providers/network-requester/src/request_filter/allowed_hosts/group.rs @@ -1,7 +1,7 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::allowed_hosts::host::Host; +use crate::request_filter::allowed_hosts::host::Host; use ipnetwork::IpNetwork; use std::collections::HashSet; use std::net::IpAddr; diff --git a/service-providers/network-requester/src/allowed_hosts/host.rs b/service-providers/network-requester/src/request_filter/allowed_hosts/host.rs similarity index 100% rename from service-providers/network-requester/src/allowed_hosts/host.rs rename to service-providers/network-requester/src/request_filter/allowed_hosts/host.rs diff --git a/service-providers/network-requester/src/allowed_hosts/hosts.rs b/service-providers/network-requester/src/request_filter/allowed_hosts/hosts.rs similarity index 99% rename from service-providers/network-requester/src/allowed_hosts/hosts.rs rename to service-providers/network-requester/src/request_filter/allowed_hosts/hosts.rs index b9d534fe89..58ac73b669 100644 --- a/service-providers/network-requester/src/allowed_hosts/hosts.rs +++ b/service-providers/network-requester/src/request_filter/allowed_hosts/hosts.rs @@ -1,5 +1,5 @@ use super::host::Host; -use crate::allowed_hosts::group::HostsGroup; +use crate::request_filter::allowed_hosts::group::HostsGroup; use ipnetwork::IpNetwork; use std::{ fs::{self, File, OpenOptions}, diff --git a/service-providers/network-requester/src/allowed_hosts/mod.rs b/service-providers/network-requester/src/request_filter/allowed_hosts/mod.rs similarity index 100% rename from service-providers/network-requester/src/allowed_hosts/mod.rs rename to service-providers/network-requester/src/request_filter/allowed_hosts/mod.rs diff --git a/service-providers/network-requester/src/allowed_hosts/standard_list.rs b/service-providers/network-requester/src/request_filter/allowed_hosts/standard_list.rs similarity index 96% rename from service-providers/network-requester/src/allowed_hosts/standard_list.rs rename to service-providers/network-requester/src/request_filter/allowed_hosts/standard_list.rs index 3b873827e3..76cc3289a0 100644 --- a/service-providers/network-requester/src/allowed_hosts/standard_list.rs +++ b/service-providers/network-requester/src/request_filter/allowed_hosts/standard_list.rs @@ -1,8 +1,8 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::allowed_hosts::group::HostsGroup; -use crate::allowed_hosts::host::Host; +use crate::request_filter::allowed_hosts::group::HostsGroup; +use crate::request_filter::allowed_hosts::host::Host; use nym_task::TaskClient; use regex::Regex; use std::sync::Arc; diff --git a/service-providers/network-requester/src/allowed_hosts/stored_allowed_hosts.rs b/service-providers/network-requester/src/request_filter/allowed_hosts/stored_allowed_hosts.rs similarity index 98% rename from service-providers/network-requester/src/allowed_hosts/stored_allowed_hosts.rs rename to service-providers/network-requester/src/request_filter/allowed_hosts/stored_allowed_hosts.rs index 20dc0499b9..a7d87d803e 100644 --- a/service-providers/network-requester/src/allowed_hosts/stored_allowed_hosts.rs +++ b/service-providers/network-requester/src/request_filter/allowed_hosts/stored_allowed_hosts.rs @@ -1,7 +1,7 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::allowed_hosts::HostsStore; +use crate::request_filter::allowed_hosts::HostsStore; use async_file_watcher::{AsyncFileWatcher, FileWatcherEventReceiver}; use futures::channel::mpsc; use futures::StreamExt; diff --git a/service-providers/network-requester/src/request_filter/exit_policy/mod.rs b/service-providers/network-requester/src/request_filter/exit_policy/mod.rs new file mode 100644 index 0000000000..beab727a2b --- /dev/null +++ b/service-providers/network-requester/src/request_filter/exit_policy/mod.rs @@ -0,0 +1,82 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::error::NetworkRequesterError; +use log::trace; +use nym_exit_policy::client::get_exit_policy; +use nym_exit_policy::ExitPolicy; +use nym_socks5_requests::RemoteAddress; +use reqwest::IntoUrl; +use tokio::net::lookup_host; +use url::Url; + +pub struct ExitPolicyRequestFilter { + upstream: Option, + policy: ExitPolicy, +} + +impl ExitPolicyRequestFilter { + pub(crate) async fn new_upstream(url: impl IntoUrl) -> Result { + let url = url + .into_url() + .map_err(|source| NetworkRequesterError::MalformedExitPolicyUpstreamUrl { source })?; + + Ok(ExitPolicyRequestFilter { + upstream: Some(url.clone()), + policy: get_exit_policy(url).await?, + }) + } + + pub(crate) fn new(policy: ExitPolicy) -> Self { + ExitPolicyRequestFilter { + upstream: None, + policy, + } + } + + pub fn policy(&self) -> &ExitPolicy { + &self.policy + } + + pub fn upstream(&self) -> Option<&Url> { + self.upstream.as_ref() + } + + pub(crate) async fn check( + &self, + remote: &RemoteAddress, + ) -> Result { + // try to convert the remote to a proper socket address + let addrs = lookup_host(remote) + .await + .map_err(|source| NetworkRequesterError::CouldNotResolveHost { + remote: remote.to_string(), + source, + })? + .collect::>(); + + // I'm honestly not sure if it's possible to return an Ok with an empty iterator, + // but might as well guard against that + if addrs.is_empty() { + return Err(NetworkRequesterError::EmptyResolvedAddresses { + remote: remote.to_string(), + }); + } + + trace!("{remote} has been resolved to {addrs:?}"); + + // if the remote decided to give us an address that can resolve to multiple socket addresses, + // they'd better make sure all of them are allowed by the exit policy. + for addr in addrs { + if !self + .policy + .allows_sockaddr(&addr) + .ok_or(NetworkRequesterError::AddressNotCoveredByExitPolicy { addr })? + { + return Ok(false); + } + } + + Ok(true) + } +} diff --git a/service-providers/network-requester/src/request_filter/mod.rs b/service-providers/network-requester/src/request_filter/mod.rs new file mode 100644 index 0000000000..c3a3697ec0 --- /dev/null +++ b/service-providers/network-requester/src/request_filter/mod.rs @@ -0,0 +1,142 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::{self, Config}; +use crate::error::NetworkRequesterError; +use crate::request_filter::allowed_hosts::standard_list::StandardListUpdater; +use crate::request_filter::allowed_hosts::stored_allowed_hosts::{ + start_allowed_list_reloader, StoredAllowedHosts, +}; +use crate::request_filter::allowed_hosts::{OutboundRequestFilter, StandardList}; +use crate::request_filter::exit_policy::ExitPolicyRequestFilter; +use log::{info, warn}; +use nym_exit_policy::ExitPolicy; +use nym_socks5_requests::RemoteAddress; +use nym_task::TaskHandle; +use std::sync::Arc; + +/// Old request filtering based on the allowed.list files. +pub mod allowed_hosts; +pub mod exit_policy; + +enum RequestFilterInner { + AllowList { + open_proxy: bool, + filter: OutboundRequestFilter, + }, + ExitPolicy { + policy_filter: ExitPolicyRequestFilter, + }, +} + +#[derive(Clone)] +pub struct RequestFilter { + inner: Arc, +} + +impl RequestFilter { + pub(crate) async fn new(config: &Config) -> Result { + if config.network_requester.use_deprecated_allow_list { + info!("setting up allow-list based 'OutboundRequestFilter'..."); + Ok(Self::new_allow_list_request_filter(config)) + } else { + info!("setting up ExitPolicy based request filter..."); + Self::new_exit_policy_filter(config).await + } + } + + pub fn current_exit_policy_filter(&self) -> Option<&ExitPolicyRequestFilter> { + match &*self.inner { + RequestFilterInner::AllowList { .. } => None, + RequestFilterInner::ExitPolicy { policy_filter } => Some(policy_filter), + } + } + + pub(crate) async fn start_update_tasks( + &self, + config: &config::Debug, + task_handle: &TaskHandle, + ) { + match &*self.inner { + RequestFilterInner::AllowList { open_proxy, filter } => { + // if we're running in open proxy, we don't have to spawn any refreshers, + // after all, we're going to be accepting all requests regardless + // of the local allow list or the standard list + if *open_proxy { + return; + } + + // start the standard list updater + StandardListUpdater::new( + config.standard_list_update_interval, + filter.standard_list(), + task_handle.get_handle().named("StandardListUpdater"), + ) + .start(); + + // start the allowed.list watcher and updater + start_allowed_list_reloader( + filter.allowed_hosts(), + task_handle + .get_handle() + .named("stored_allowed_hosts_reloader"), + ) + .await; + } + RequestFilterInner::ExitPolicy { .. } => { + // nothing to do for the exit policy (yet; we might add a refresher at some point) + } + } + } + + fn new_allow_list_request_filter(config: &Config) -> Self { + let standard_list = StandardList::new(); + let allowed_hosts = StoredAllowedHosts::new(&config.storage_paths.allowed_list_location); + let unknown_hosts = + allowed_hosts::HostsStore::new(&config.storage_paths.unknown_list_location); + + // TODO: technically if we're running open proxy, we don't have to be loading anything here + RequestFilter { + inner: Arc::new(RequestFilterInner::AllowList { + open_proxy: config.network_requester.open_proxy, + filter: OutboundRequestFilter::new(allowed_hosts, standard_list, unknown_hosts), + }), + } + } + + async fn new_exit_policy_filter(config: &Config) -> Result { + let policy_filter = if config.network_requester.open_proxy { + ExitPolicyRequestFilter::new(ExitPolicy::new_open()) + } else { + let upstream_url = config + .network_requester + .upstream_exit_policy_url + .as_ref() + .ok_or(NetworkRequesterError::NoUpstreamExitPolicy)?; + ExitPolicyRequestFilter::new_upstream(upstream_url.clone()).await? + }; + Ok(RequestFilter { + inner: Arc::new(RequestFilterInner::ExitPolicy { policy_filter }), + }) + } + + pub(crate) async fn check_address(&self, address: &RemoteAddress) -> bool { + match &*self.inner { + RequestFilterInner::AllowList { open_proxy, filter } => { + if *open_proxy { + return true; + } + filter.check(address).await + } + RequestFilterInner::ExitPolicy { policy_filter } => { + match policy_filter.check(address).await { + Err(err) => { + warn!("failed to validate '{address}' against the exit policy: {err}"); + false + } + Ok(res) => res, + } + } + } + } +} diff --git a/tools/nym-nr-query/Cargo.toml b/tools/nym-nr-query/Cargo.toml index 9e3dfbb727..9034b536db 100644 --- a/tools/nym-nr-query/Cargo.toml +++ b/tools/nym-nr-query/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow = "1.0.68" +anyhow = { workspace = true } clap = {version = "4.0", features = ["cargo", "derive"]} log = { workspace = true } nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] } diff --git a/tools/nym-nr-query/src/main.rs b/tools/nym-nr-query/src/main.rs index 362e1312ff..477d3937c9 100644 --- a/tools/nym-nr-query/src/main.rs +++ b/tools/nym-nr-query/src/main.rs @@ -1,5 +1,7 @@ +use anyhow::Result; use clap::{Parser, ValueEnum}; use nym_bin_common::output_format::OutputFormat; +use nym_network_defaults::NymNetworkDetails; use nym_sdk::mixnet::{self, IncludedSurbs, MixnetMessageSender}; use nym_service_providers_common::interface::{ ControlRequest, ControlResponse, ProviderInterfaceVersion, Request, Response, ResponseContent, @@ -51,6 +53,9 @@ enum Commands { /// Check if the network requester is acting a an open proxy OpenProxy, + /// Get the exit policy of this network requester + ExitPolicy, + /// Ping the network requester Ping, } @@ -103,17 +108,26 @@ async fn wait_for_socks5_response(client: &mut mixnet::MixnetClient) -> Socks5Re } } -async fn connect_to_mixnet(gateway: Option) -> mixnet::MixnetClient { - match gateway { - Some(gateway) => mixnet::MixnetClientBuilder::new_ephemeral() - .request_gateway(gateway.to_base58_string()) - .build() - .expect("Failed to create mixnet client") - .connect_to_mixnet() - .await - .expect("Failed to connect to the mixnet"), - None => mixnet::MixnetClient::connect_new().await.unwrap(), - } +async fn connect_to_mixnet(gateway: Option) -> Result { + let network = NymNetworkDetails::new_from_env(); + + Ok(match gateway { + Some(gateway) => { + mixnet::MixnetClientBuilder::new_ephemeral() + .network_details(network) + .request_gateway(gateway.to_base58_string()) + .build()? + .connect_to_mixnet() + .await? + } + None => { + mixnet::MixnetClientBuilder::new_ephemeral() + .network_details(network) + .build()? + .connect_to_mixnet() + .await? + } + }) } fn new_bin_info_request() -> Request { @@ -134,6 +148,14 @@ fn new_open_proxy_request() -> Request { Request::new_provider_data(ProviderInterfaceVersion::new_current(), request_open_proxy) } +fn new_exit_policy_request() -> Request { + let request_exit_policy = Socks5Request::new_query( + Socks5ProtocolVersion::new_current(), + QueryRequest::ExitPolicy, + ); + Request::new_provider_data(ProviderInterfaceVersion::new_current(), request_exit_policy) +} + fn new_ping_request() -> Request { let request_ping = ControlRequest::Health; Request::new_control(ProviderInterfaceVersion::new_current(), request_ping) @@ -145,9 +167,12 @@ struct QueryClient { } impl QueryClient { - async fn new(provider: mixnet::Recipient, gateway: Option) -> Self { - let client = connect_to_mixnet(gateway).await; - Self { client, provider } + async fn new( + provider: mixnet::Recipient, + gateway: Option, + ) -> Result { + let client = connect_to_mixnet(gateway).await?; + Ok(Self { client, provider }) } async fn query_bin_info(&mut self) -> ControlResponse { @@ -191,6 +216,24 @@ impl QueryClient { .clone() } + async fn query_exit_policy(&mut self) -> QueryResponse { + self.client + .send_message( + self.provider, + new_exit_policy_request().into_bytes(), + IncludedSurbs::Amount(10), + ) + .await + .unwrap(); + + let response = wait_for_socks5_response(&mut self.client).await; + response + .content + .as_query() + .expect("Unexpected response type!") + .clone() + } + async fn ping(&mut self) -> PingResponse { let now = std::time::Instant::now(); self.client @@ -275,7 +318,7 @@ async fn main() -> anyhow::Result<()> { nym_network_defaults::setup_env(args.config_env_file.as_ref()); text_println("Registering with gateway...", &args.output); - let mut client = QueryClient::new(args.provider, args.gateway).await; + let mut client = QueryClient::new(args.provider, args.gateway).await?; let our_gateway = client.client.nym_address().gateway(); text_println(&format!(" gateway: {our_gateway}"), &args.output); @@ -310,7 +353,9 @@ async fn main() -> anyhow::Result<()> { Commands::BinaryInfo => client.query_bin_info().await.into(), Commands::SupportedRequestVersions => client.query_supported_versions().await.into(), Commands::OpenProxy => client.query_open_proxy().await.into(), + Commands::ExitPolicy => client.query_exit_policy().await.into(), Commands::Ping => unreachable!(), + // _ => unimplemented!(), }; println!("{}", args.output.format(&resp)); } From e61281e25eb4b4dc64a933b280b8305289c93597 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 11:54:51 +0200 Subject: [PATCH 092/236] correction based on feedback --- documentation/operators/src/faq/smoosh-faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index 4d369d8d12..30180eba09 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -32,7 +32,7 @@ Generally, the software will be the same, just instead of multiple binaries, the ### What does it mean for Nym nodes operators? -We are looking into two possible ways how such binary will work in practice and will inform in advance. These are the options: +We are exploring two potential methods for implementing binary functionality in practice and will provide information in advance. The options are: 1. Make a selection button (command/argument/flag) for operators to choose whether they want their node to provide all or just some of the functions nodes have in the Nym Mixnet. Those nodes functioning as exit gateway (in that epoch) will then have bigger rewards due to their larger risk exposure and overhead work with the setup. From a65da367a30ef3824b5bd5108e44bf39d8decc72 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 11:55:59 +0200 Subject: [PATCH 093/236] correction based on feedback --- documentation/operators/src/faq/smoosh-faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index 30180eba09..4c1342c326 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -34,7 +34,7 @@ Generally, the software will be the same, just instead of multiple binaries, the We are exploring two potential methods for implementing binary functionality in practice and will provide information in advance. The options are: -1. Make a selection button (command/argument/flag) for operators to choose whether they want their node to provide all or just some of the functions nodes have in the Nym Mixnet. Those nodes functioning as exit gateway (in that epoch) will then have bigger rewards due to their larger risk exposure and overhead work with the setup. +1. Make a selection button (command/argument/flag) for operators to choose whether they want their node to provide all or just some of the functions nodes have in the Nym Mixnet. Nodes functioning as exit gateways (in that epoch) will then have bigger rewards due to their larger risk exposure and overhead work with the setup. 2. All nodes will be required to have the exit gateway functionality. All nodes are rewarded the same as now, and the difference is that a node sometimes (some epochs) may be performing as exit gateway sometimes as mix node or entry gateway adjusted according the network demand by an algorithm. From 1c8685681ef51618afac364fb350658fe5587dec Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Thu, 26 Oct 2023 12:25:31 +0200 Subject: [PATCH 094/236] =?UTF-8?q?i=20hope=20for=20no=20more=20comments?= =?UTF-8?q?=20hold=20my=20=F0=9F=8D=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- explorer-api/src/geo_ip/location.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/explorer-api/src/geo_ip/location.rs b/explorer-api/src/geo_ip/location.rs index 52f88069f3..a507056828 100644 --- a/explorer-api/src/geo_ip/location.rs +++ b/explorer-api/src/geo_ip/location.rs @@ -118,12 +118,12 @@ impl GeoIp { } pub fn query(&self, address: &str, port: Option) -> Result, GeoIpError> { - let ip: IpAddr = FromStr::from_str(address).or_else(|_| { + let p = port.unwrap_or(FAKE_PORT); + let ip_result: Result = FromStr::from_str(address).or_else(|_| { debug!( "Fail to create IpAddr from {}. Trying using internal lookup...", &address ); - let p = port.unwrap_or(FAKE_PORT); match (address, p).to_socket_addrs() { Ok(mut addrs) => { if let Some(socket_addr) = addrs.next() { @@ -142,7 +142,10 @@ impl GeoIp { Err(GeoIpError::NoValidIP) } } - })?; + }); + + let ip = ip_result?; + let result = self .db .as_ref() From 4e994f2b9266da2144d6f753135f4664b3734fa1 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 12:32:53 +0200 Subject: [PATCH 095/236] update exit policy info --- .../operators/src/legal/exit-gateway.md | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index e011cc01e3..2c73435c9b 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -6,7 +6,7 @@ The entire content of this page is under [Creative Commons Attribution 4.0 Inter This page is a part of Nym Community Legal Forum and its content is composed by shared advices in [Node Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) (Matrix chat) as well as though pull requests done by the node operators directly to our [repository](https://github.com/nymtech/nym/tree/develop/documentation/operators/src), reviewed by Nym DevRels. -This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating gateways and opening these to any online service with the safeguards of the [Tor Null ‘deny’ list](https://tornull.org/). +This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating gateways and opening these to any online service. Such setup needs a **clear policy**, one which will remain the **same for all operators** running Nym nodes. The [proposed **Exit policy**](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) is a combination of two existing safeguards: [Tor Null ‘deny’ list](https://tornull.org/) and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). ```admonish warning @@ -22,7 +22,7 @@ Nym core team cannot provide comprehensive legal advice across all jurisdictions * Currently, Nym Gateway nodes only enable access to apps and services that are on an ‘allow’ list that is maintained by the core team. -* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list (based on the [Tor Null advisory BL](https://tornull.org/)). +* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list - [Exit policy]((https://nymtech.net/.wellknown/network-requester/exit-policy.txt). Based on two existing safeguards: [Tor Null ‘deny’ list](https://tornull.org/) and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). * This will enhance the usage and appeal of Nym products for end users. As a result, increased usage will ultimately lead to higher revenues for Nym operators. @@ -39,7 +39,7 @@ Nym core team cannot provide comprehensive legal advice across all jurisdictions To offer a better and more private everyday experience for its users, Nym would like them to use any online services they please, without limiting its access to a few messaging apps or crypto wallets. -To achieve this, operators running “gateways” would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. +To achieve this, operators running exit gateways would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays following this [Exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). ## Pros and cons of the initiative @@ -63,21 +63,17 @@ The new setup: Running nodes supporting traffic of any online service (with safe | Operational | | - Higher operational overhead, such as dealing with DMCA / abuse complaints, managing the VPS provider questions, or helping the community to maintain the denylist
- Administrative overhead if running nodes as a company or an entity | | Legal | | - Ideally requires to check legal environment with local privacy association or lawyer | Financial | - Higher revenue potential for operators due to the increase in network usage | - If not running VPS with an unlimited bandwidth plan, higher costs due to higher network usage | -## New gateway setup +## Exit gateways: New setup In our previous technical setup, network requesters acted as a proxy, and only made requests that match an allow list. That was a default IP based list of allowed domains stored at Nym page in a centralised fashion possibly re-defined by any Network requester operator. This restricts the hosts that the NymConnect app can connect to and has the effect of selectively supporting messaging services (e.g. Telegram, Matrix) or crypto wallets (e.g. Electrum or Monero). Operators of network requesters can have confidence that the infrastructure they run only connects to a limited set of public internet hosts. -In the new setup, the main change is to expand this short allow list to a more permissive setup. An exit policy will constrain the hosts that the users of the Nym Mixnet and Nym VPN can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym Mixnet VPN and VPN clients (both wrapped in the same app). +In the new setup, the main change is to expand this short allow list to a more permissive setup. An [Exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym Mixnet and Nym VPN can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym Mixnet VPN and VPN clients (both wrapped in the same app). -As of now we the gateways will be defaulted to Tornull’s (note: Not affiliated with Tor) deny list - reproduction permitted under Creative Commons Attribution 3.0 United States License which is IP-based, e.g., `ExitPolicy reject 5.188.10.0/23:*`. Whether we will stick with this list, do modifications (likely) or compile another one is still a subject of discussion. +As of now we the gateways will be defaulted to a combination of [Tor Null ‘deny’ list](https://tornull.org/) (note: Not affiliated with Tor) - reproduction permitted under Creative Commons Attribution 3.0 United States License which is IP-based, e.g., `ExitPolicy reject 5.188.10.0/23:*` and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). Whether we will stick with this list, do modifications or compile another one is still a subject of discussion. In all cases, this policy will remain the same for all the nodes, without any option to modify it by Nym node operators to secure stable and reliable service for the end users. -<:-- -These policies will be either reused without modification from Tor / Tornull (license permitting), or customized and updated in a Nym crowd-sourced community effort. ---> - -The Gateways will display an HTML page similar to that suggested by [Tor](https://gitlab.torproject.org/tpo/core/tor/-/raw/HEAD/contrib/operator-tools/tor-exit-notice.html) for exit relays on port 80 and port 443. This will allow the operator to provide information about their Gateway, possibly including the currently configured exit policy, without having to actively communicate with law enforcement or regulatory authorities. It also makes the behaviour of the Gateway transparent and even computable (a possible feature would be to offer a machine readable form of the notice in JSON or YAML). +The Gateways will display an HTML page similar to that suggested by [Tor](https://gitlab.torproject.org/tpo/core/tor/-/raw/HEAD/contrib/operator-tools/tor-exit-notice.html) for exit relays on port 80 and port 443. This will allow the operator to provide information about their Gateway, possibly including the currently configured exit policy, without having to actively communicate with law enforcement or regulatory authorities. It also makes the behaviour of exit gateways transparent and even computable (a possible feature would be to offer a machine readable form of the notice in JSON or YAML). We also recommend operators to check the technical advice from [Tor](https://community.torproject.org/relay/setup/exit/). @@ -133,14 +129,14 @@ Useful links: ## Legal environment - Findings from our legal team ```admonish warning -Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the operator channels ([Element](https://matrix.to/#/#operators:nymtech.chat), [Discord](https://discord.com/invite/nym), [Telegram](https://t.me/nymchan_help_chat)) to share best practices and experiences. +The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators LEgal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. ``` The Swiss legal counsel and US legal counsel have so far provided the following advice: ### Switzerland -TBD soon. + ### United States From f9e5a1159d3d03ecd076ab673e3f82aa47218376 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 12:37:15 +0200 Subject: [PATCH 096/236] create legal region pages - us, swiss --- documentation/operators/src/legal/swiss.md | 0 .../operators/src/legal/united-states.md | 25 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 documentation/operators/src/legal/swiss.md create mode 100644 documentation/operators/src/legal/united-states.md diff --git a/documentation/operators/src/legal/swiss.md b/documentation/operators/src/legal/swiss.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/documentation/operators/src/legal/united-states.md b/documentation/operators/src/legal/united-states.md new file mode 100644 index 0000000000..54a215c6fc --- /dev/null +++ b/documentation/operators/src/legal/united-states.md @@ -0,0 +1,25 @@ +## Legal environment: United States + +```admonish warning +The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators LEgal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. +``` + + + +## Findings from our legal team + +```admonish warning +The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators LEgal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. +``` + +The US legal counsel have so far provided the following advice: + +The legal risk faced by VPN operators subject to United States jurisdiction depends on various statutes and regulations related to privacy, anonymity, and electronic communications. The key areas to consider are: intermediary liability and exceptions, data protection, copyright infringement, export controls, criminal law, government requests for data and assistance, and third party liability. + +As outlined in Part A, the United States treats VPNs as telecommunications networks subject to intermediary liability protection from wrongful conduct that occurs on its network. However, such protections do have exceptions including criminal law and copyright claims that are worth considering. In the United States, I am not aware of an individual ever being prosecuted or convicted for running a node for a dVPN or a Privacy Enhancing Network. + +However, as discussed in Part B-C, VPN operators are subject to law enforcement requests for access or assistance in obtaining access to data relevant to an investigation into allegedly unlawful conduct that was facilitated by the network as an intermediary. As shown in Part C, governments may also request assistance from node operators for certain high-level and national security targets. + +Finally, as outlined in Parts D-G, VPN operators may also be subject to non-criminal liability including (Part D) failing to respond to notices under the DMCA, (Part E) privacy and data protection law, (Part F) third party lawsuits stemming from wrongful acts committed using the network, and (G) export control violations. + + From 96d18619559e1a5dc5530dfc24788bdab6245538 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 12:51:30 +0200 Subject: [PATCH 097/236] add legal findings switzerland --- .../operators/src/legal/exit-gateway.md | 26 ++----- documentation/operators/src/legal/swiss.md | 73 +++++++++++++++++++ .../operators/src/legal/united-states.md | 8 +- 3 files changed, 80 insertions(+), 27 deletions(-) diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index 2c73435c9b..2b55bc3223 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -128,30 +128,14 @@ Useful links: ## Legal environment - Findings from our legal team -```admonish warning -The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators LEgal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. -``` +The Node Operators Legal Forum are divided into pages according the regions: -The Swiss legal counsel and US legal counsel have so far provided the following advice: +- [Switzerland](./swiss.md) +- [United States](./united-states.md) -### Switzerland +See the next chapter to learn how to edit or add the Legal Forum pages. - - -### United States - -A US counsel shared the following advice: - -The legal risk faced by VPN operators subject to United States jurisdiction depends on various statutes and regulations related to privacy, anonymity, and electronic communications. The key areas to consider are: intermediary liability and exceptions, data protection, copyright infringement, export controls, criminal law, government requests for data and assistance, and third party liability. - -As outlined in Part A, the United States treats VPNs as telecommunications networks subject to intermediary liability protection from wrongful conduct that occurs on its network. However, such protections do have exceptions including criminal law and copyright claims that are worth considering. In the United States, I am not aware of an individual ever being prosecuted or convicted for running a node for a dVPN or a Privacy Enhancing Network. - -However, as discussed in Part B-C, VPN operators are subject to law enforcement requests for access or assistance in obtaining access to data relevant to an investigation into allegedly unlawful conduct that was facilitated by the network as an intermediary. As shown in Part C, governments may also request assistance from node operators for certain high-level and national security targets. - -Finally, as outlined in Parts D-G, VPN operators may also be subject to non-criminal liability including (Part D) failing to respond to notices under the DMCA, (Part E) privacy and data protection law, (Part F) third party lawsuits stemming from wrongful acts committed using the network, and (G) export control violations. - - -## How to add legal information +## How to edit or add legal information Our aim is to establish a strong community network, sharing legal findings with each other. We would like to encourage all the current and future operators to do research about the situation in the jurisdiction they operate and update this page. diff --git a/documentation/operators/src/legal/swiss.md b/documentation/operators/src/legal/swiss.md index e69de29bb2..1f03ce9f7b 100644 --- a/documentation/operators/src/legal/swiss.md +++ b/documentation/operators/src/legal/swiss.md @@ -0,0 +1,73 @@ +# Legal environment: Switzerland + +```admonish warning +The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators LEgal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. +``` + +## Findings from our legal team + +**Note:** The information shared below is in the stage of conclusions upon final confirmation. The text is a not edited exert from a legal counsel. Nym core team is asking for more clarifications. + +### Operators of Exit Nodes + +#### Telecoms Law + +As well as operators of normal mixnet nodes, operators of exit nodes might be considered telecommunications providers according to the broad term of the telecommunications act (TCA). +The regulatory consequences have already been laid out in section 5.1.2.2.1 above. + +####Telecoms Surveillance Law + +Unlike normal mixnet nodes, exit nodes might have information about the communication party which uses the respective exit node (in particular its IP address). They might therefore be a target for surveillance authorities, at least at first glance. + +However, as the IP address of the communications party is disguised on the other side of the communications through the Nym encryption infrastructure, the usual situation, where an IP address or another trace of an Internet user is found in the connection with a criminal activity (e.g., in a web server protocol), and then used in cooperation with the user’s provider to identify the user, is not going to take place. + +The same is true for the opposite side: The node operator does not see the communication party of his user. + +Experience has shown that Swiss investigative authorities are aware of these limitations and do not conduct investigations against individuals who operate TOR nodes, for example. In one specific case that I know of, the investigation was stopped by the police as soon as it was clear that a TOR node was being operated. + +I therefore consider the risk for an exit node operator to become involved in a SPTA proceeding as low. + +Nevertheless, in such a situation, exit node operators providers would have to provide the authorities with the information already available to them (Art. 22 Para. 3 SPTA), and they would have to tolerate monitoring by the authorities or by the persons commissioned by the service of the data which the monitored person transmits or stores using derived communications services (Art. 27 Para. 1 SPTA; see above, 5.1.1.2). There is no duty of data retention for providers of derived communication services, though. + +The the risk for exit node operators of being upgraded according to Art. 22 Para. 4 SPTA is low to non existent for the reasons mentioned above. + +#### Intelligence Service Law + +Operators of exit nodes do not provide wire-based telecommunications services either and therefore do not fall under the IntelSA. + +### Nym as VPN provider + +#### Telecoms Law + +Nym as a VPN operator might be considered a telecommunication provider under the newly revised TCA, as the term now also covers operators of Over-the-Top services which are carried out over the internet. + +However I consider possible administrative burdens arising from this qualification as negligible (see above, 5.1.2.1). + +#### Telecoms Surveillance Law + +VPN providers have information about the communication party which uses the respective exit node (in particular its IP address). They might therefore be a target for surveillance authorities, at least at first glance. + +However, for the same reason I see a risk low for exit node operators to become involved in a SPTA proceeding (the IP address is not visible to the communication partner, which is exactly the reason the Nym VPN is being used at all), I also see a low risk for Nym itself to become involved in such a proceeding (see above, 5.1.3.2). + +#### Intelligence Service Law + +VPN operators do not provide wire-based telecommunications services and therefore do not fall under the IntelSA. + +### EU chat control regulation in particular + +According to a EU commission proposal for a regulation laying down rules to prevent and combat child sexual abuse (https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX: 52022PC0209) hosting providers and providers of so-called interpersonal communication services should be obliged to perform an assessment of risks of online child sexual abuse. Additionally an obligation for certain providers should be established to detect such abuse, to report it via the EU Centre, to remove or disable access to, or to block online child sexual abuse material when so ordered. + +'Interpersonal communications service’ means a service normally provided for remuneration that enables direct interpersonal and interactive exchange of information via electronic communications networks between a finite number of persons, whereby the persons initiating or participating in the communication determine its recipient(s) and does not include services which enable interpersonal and interactive communication merely as a minor ancillary feature that is intrinsically linked to another service (Art. 2 Point 5 Directive (EU) 2018/1972, which is also relevant for the mentioned proposal). + +Interpersonal communications services are services that enable interpersonal and interactive exchange of information. Interactive communication entails that the service allows the recipient of the information to respond. The proposal therefore only covers services like traditional voice calls between two individuals but also all types of emails, messaging services, or group chats. Examples for services which do not meet those requirements are linear broadcasting, video on demand, websites, social networks, blogs, or exchange of information between machines (Directive (EU) 2018/1972, Consideration 17). + +Neither the Nym encryption infrastructure nor the NYM VPN are used as means for an interactive exchange of information in the aforementioned sense (of e-mail, messaging, chats or similar). + +I therefore consider the risk arising from the mentioned proposal for Nym as low, be it as software developer or VPN operator. + +However, an application provider which uses the Nym encryption infrastructure to provide encrypted chat services or similar could still fall under the proposal. This might pose a commercial risk for Nym as the provider of the basic infrastructure for such services, because such services might lose their commercial value for end customers. + +Currently the EU decision on chat control has been postponed because there is a blocking minority which can prevent the adoption of the respective parts of the law. In addition, even EU internal lawyers held that the proposal was clearly in violation of the EU charter of fundamental rights and would therefore be nullified by the EU courts in case it would still be enacted by the parliament. + +I therefore consider the risk that the mentioned proposal is enacted by the EU authorities and finally upheld by the courts in its planned form as low. + diff --git a/documentation/operators/src/legal/united-states.md b/documentation/operators/src/legal/united-states.md index 54a215c6fc..6988a9bc5a 100644 --- a/documentation/operators/src/legal/united-states.md +++ b/documentation/operators/src/legal/united-states.md @@ -1,16 +1,12 @@ -## Legal environment: United States +# Legal environment: United States ```admonish warning The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators LEgal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. ``` - - ## Findings from our legal team -```admonish warning -The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators LEgal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. -``` +**Note:** The information shared below is in the stage of conclusions upon final confirmation. The US legal counsel have so far provided the following advice: From 722486ca689562b5020b88df7b968447eabdedbf Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 12:57:31 +0200 Subject: [PATCH 098/236] add regions to SUMMARY.md --- documentation/operators/src/legal/exit-gateway.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index 2b55bc3223..75f67956c7 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -1,4 +1,4 @@ -# Nym operators - Running Exit Gateway +# Nym Operators Legal Forum: Running Exit Gateway ```admonish info The entire content of this page is under [Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/). From 3d5a3ad9587d55e24fad6893854aeb95e4386620 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 12:58:29 +0200 Subject: [PATCH 099/236] add regions to SUMMARY.md --- documentation/operators/src/SUMMARY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/documentation/operators/src/SUMMARY.md b/documentation/operators/src/SUMMARY.md index 0e2cdb2323..b349782408 100644 --- a/documentation/operators/src/SUMMARY.md +++ b/documentation/operators/src/SUMMARY.md @@ -27,6 +27,8 @@ # Legal Forum - [Exit Gateway](./legal/exit-gateway.md) + - [Switzerland](./legal/swiss.md) + - [United States](./legal/united-states.md) --- # Misc. From fa3277e18b3304f869b71a6ba9952a32a42420de Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 12:59:40 +0200 Subject: [PATCH 100/236] syntax fix --- documentation/operators/src/legal/exit-gateway.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index 75f67956c7..a513a4d74f 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -22,7 +22,7 @@ Nym core team cannot provide comprehensive legal advice across all jurisdictions * Currently, Nym Gateway nodes only enable access to apps and services that are on an ‘allow’ list that is maintained by the core team. -* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list - [Exit policy]((https://nymtech.net/.wellknown/network-requester/exit-policy.txt). Based on two existing safeguards: [Tor Null ‘deny’ list](https://tornull.org/) and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). +* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list - [Exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). Based on two existing safeguards: [Tor Null ‘deny’ list](https://tornull.org/) and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). * This will enhance the usage and appeal of Nym products for end users. As a result, increased usage will ultimately lead to higher revenues for Nym operators. From 1aad2a3a7a605b5396f007e08dfb0f5050f5ffd0 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 13:04:56 +0200 Subject: [PATCH 101/236] syntax fix --- documentation/operators/src/legal/exit-gateway.md | 4 ++-- documentation/operators/src/legal/swiss.md | 6 +++--- documentation/operators/src/legal/united-states.md | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index a513a4d74f..69e1ec4099 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -128,12 +128,12 @@ Useful links: ## Legal environment - Findings from our legal team -The Node Operators Legal Forum are divided into pages according the regions: +The Node Operators Legal Forum pages are divided into pages according the region: - [Switzerland](./swiss.md) - [United States](./united-states.md) -See the next chapter to learn how to edit or add the Legal Forum pages. +See the next chapter to learn how to edit information or add findings about your jurisdiction. ## How to edit or add legal information diff --git a/documentation/operators/src/legal/swiss.md b/documentation/operators/src/legal/swiss.md index 1f03ce9f7b..07d21553b7 100644 --- a/documentation/operators/src/legal/swiss.md +++ b/documentation/operators/src/legal/swiss.md @@ -1,12 +1,12 @@ # Legal environment: Switzerland ```admonish warning -The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators LEgal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. +The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. ``` ## Findings from our legal team -**Note:** The information shared below is in the stage of conclusions upon final confirmation. The text is a not edited exert from a legal counsel. Nym core team is asking for more clarifications. +> **Note:** The information shared below is in the stage of conclusions upon final confirmation. The text is a not edited exert from a legal counsel. Nym core team is asking for more clarifications. ### Operators of Exit Nodes @@ -15,7 +15,7 @@ The following part is for informational purposes only. Nym core team cannot prov As well as operators of normal mixnet nodes, operators of exit nodes might be considered telecommunications providers according to the broad term of the telecommunications act (TCA). The regulatory consequences have already been laid out in section 5.1.2.2.1 above. -####Telecoms Surveillance Law +#### Telecoms Surveillance Law Unlike normal mixnet nodes, exit nodes might have information about the communication party which uses the respective exit node (in particular its IP address). They might therefore be a target for surveillance authorities, at least at first glance. diff --git a/documentation/operators/src/legal/united-states.md b/documentation/operators/src/legal/united-states.md index 6988a9bc5a..c0e66054dc 100644 --- a/documentation/operators/src/legal/united-states.md +++ b/documentation/operators/src/legal/united-states.md @@ -1,12 +1,12 @@ # Legal environment: United States ```admonish warning -The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators LEgal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. +The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. ``` ## Findings from our legal team -**Note:** The information shared below is in the stage of conclusions upon final confirmation. +> **Note:** The information shared below is in the stage of conclusions upon final confirmation. The text is a not edited exert from a legal counsel. Nym core team is asking for more clarifications. The US legal counsel have so far provided the following advice: From 3fdd89035b3bdb72b98eb16ba1fa79e33135bd2c Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 13:07:07 +0200 Subject: [PATCH 102/236] add page license --- documentation/operators/src/legal/swiss.md | 4 ++++ documentation/operators/src/legal/united-states.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/documentation/operators/src/legal/swiss.md b/documentation/operators/src/legal/swiss.md index 07d21553b7..b879123d85 100644 --- a/documentation/operators/src/legal/swiss.md +++ b/documentation/operators/src/legal/swiss.md @@ -1,5 +1,9 @@ # Legal environment: Switzerland +```admonish info +The entire content of this page is under [Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/). +``` + ```admonish warning The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. ``` diff --git a/documentation/operators/src/legal/united-states.md b/documentation/operators/src/legal/united-states.md index c0e66054dc..ce541b3028 100644 --- a/documentation/operators/src/legal/united-states.md +++ b/documentation/operators/src/legal/united-states.md @@ -1,5 +1,9 @@ # Legal environment: United States +```admonish info +The entire content of this page is under [Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/). +``` + ```admonish warning The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. ``` From 361532830c05a73c358f7549dd0fdf516889b63e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Walther?= Date: Thu, 26 Oct 2023 14:15:05 +0200 Subject: [PATCH 103/236] update security disclosure info --- SECURITY.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index a7c38e5e01..dac44ded6c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,10 +1,8 @@ Critical bug or security issue 💥 -If you're here because you're trying to figure out how to notify us of a security issue, go to Discord, and alert the core engineers: +If you're here because you're trying to figure out how to notify us of a security issue, go to Discord or Matrix, and alert the core engineers: - Dave Hrycyszyn futurechimp#5430 - Jedrzej Stuczynski "Jedrzej | Nym#5666" - Fran Arbanas | franarbanas#0995 - Mark Sinclair | marknym#8088 + Jedrzej Stuczynski, discord: "Jedrzej | Nym#5666" , matrix: @jstuczyn:nymtech.chat + Mark Sinclair | discord: marknym#8088 , matrix: @mark:nymtech.chat Please avoid opening public issues on GitHub that contain information about a potential security vulnerability as this makes it difficult to reduce the impact and harm of valid security issues. From 49dcc7e89473e08f937918bac80802b708a1fbb6 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 14:37:30 +0200 Subject: [PATCH 104/236] syntax fix --- documentation/operators/src/nodes/gateway-setup.md | 3 ++- documentation/operators/src/nodes/network-requester-setup.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 0c95db8b8a..d23e0ab02e 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -6,6 +6,7 @@ ```admonish info As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` functionality which can be enabled [by the operator](./gateway-setup.md#initialising-gateway-with-network-requester). This combination is a basis of Nym exit gateway node - an essential piece in our new setup. Please read more in our [Project Smoosh FAQ](../faq/smoosh-faq.md) and [Exit Gateways Page](../legal/exit-gateway.md). We recommend operators begin to shift their setups to this new combined node, instead of operating two separate binaries. ``` + > Any syntax in `<>` brackets is a user's unique variable. Exchange with a corresponding name without the `<>` brackets. ## Current version @@ -156,7 +157,7 @@ You can bond your gateway via the Desktop wallet. 3. You will be asked to run a the `sign` command with your `gateway` - copy and paste the long signature as the value of `--contract-msg` and run it. ``` -./nym-gatewway sign --id --contract-msg +./nym-gateway sign --id --contract-msg ``` It will look something like this: diff --git a/documentation/operators/src/nodes/network-requester-setup.md b/documentation/operators/src/nodes/network-requester-setup.md index 5e7cd7969e..9945bf0d0f 100644 --- a/documentation/operators/src/nodes/network-requester-setup.md +++ b/documentation/operators/src/nodes/network-requester-setup.md @@ -5,6 +5,7 @@ ```admonish info As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` functionality which can be enabled [by the operator](./gateway-setup.md#initialising-gateway-with-network-requester). This combination is a basis of Nym exit gateway node - an essential piece in our new setup. Please read more in our [Project Smoosh FAQ](../faq/smoosh-faq.md) and [Exit Gateways Page](../legal/exit-gateway.md). We recommend operators begin to shift their setups to this new combined node, instead of operating two separate binaries. ``` + > Any syntax in `<>` brackets is a user's unique variable. Exchange with a corresponding name without the `<>` brackets. ## Current version From 84f64595985980be457875b51a9edd5917fa2f0d Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Thu, 26 Oct 2023 15:19:10 +0200 Subject: [PATCH 105/236] remove any whitespace from input field when bonding host --- nym-wallet/src/utils/common.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nym-wallet/src/utils/common.ts b/nym-wallet/src/utils/common.ts index f4ddba7275..1f113ff37a 100644 --- a/nym-wallet/src/utils/common.ts +++ b/nym-wallet/src/utils/common.ts @@ -47,11 +47,13 @@ export const validateAmount = async ( }; export const isValidHostname = (value: string) => { - // regex for ipv4 and ipv6 and hhostname- source http://jsfiddle.net/DanielD/8S4nq/ + // regex for ipv4 and ipv6 and hostname- source http://jsfiddle.net/DanielD/8S4nq/ + const trimmedValue = value.replace(/\s+/g, ''); + const hostnameRegex = /((^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))|(^\s*((?=.{1,255}$)(?=.*[A-Za-z].*)[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?)*)\s*$)/; - return hostnameRegex.test(value); + return hostnameRegex.test(trimmedValue); }; export const validateVersion = (version: string): boolean => { From c3d62b2a6a7734e5e4dc981bbd3a52097b33bf12 Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Thu, 26 Oct 2023 15:47:05 +0200 Subject: [PATCH 106/236] be quiet linter --- .../src/components/Rewards/RewardsSummary.tsx | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/nym-wallet/src/components/Rewards/RewardsSummary.tsx b/nym-wallet/src/components/Rewards/RewardsSummary.tsx index 75f7da4a7b..2ecd236c5b 100644 --- a/nym-wallet/src/components/Rewards/RewardsSummary.tsx +++ b/nym-wallet/src/components/Rewards/RewardsSummary.tsx @@ -4,6 +4,36 @@ import { useTheme } from '@mui/material/styles'; import { useDelegationContext } from 'src/context/delegations'; import { InfoTooltip } from '../InfoToolTip'; +const RewardSummaryField = ({ + title, + value, + Tooltip, + isLoading, +}: { + title: string; + value: string; + Tooltip?: React.ReactNode; + isLoading?: boolean; +}) => { + const breakpoint = useMediaQuery(useTheme().breakpoints.down('xl')); + const alignProps: { gap: number; direction: StackProps['direction'] } = { + gap: breakpoint ? 0 : 1, + direction: breakpoint ? 'column' : 'row', + }; + + return ( + + + {Tooltip} + {title}: + + + {isLoading ? : value} + + + ); +}; + export const RewardsSummary: FCWithChildren<{ isLoading?: boolean; totalDelegation?: string; @@ -39,33 +69,3 @@ export const RewardsSummary: FCWithChildren<{ ); }; - -const RewardSummaryField = ({ - title, - value, - Tooltip, - isLoading, -}: { - title: string; - value: string; - Tooltip?: React.ReactNode; - isLoading?: boolean; -}) => { - const breakpoint = useMediaQuery(useTheme().breakpoints.down('xl')); - const alignProps: { gap: number; direction: StackProps['direction'] } = { - gap: breakpoint ? 0 : 1, - direction: breakpoint ? 'column' : 'row', - }; - - return ( - - - {Tooltip} - {title}: - - - {isLoading ? : value} - - - ); -}; From 31740f70e382edd01e1af22d6fb0b67063a083fd Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Thu, 26 Oct 2023 16:54:14 +0200 Subject: [PATCH 107/236] update validation . use joi to validate ipv4 / ipv6 and hostname addresses . check for empty characters on both version and host field and prevent submission otherwise --- nym-wallet/package.json | 5 ++- .../Bonding/forms/gatewayValidationSchema.ts | 11 +++-- .../Bonding/forms/mixnodeValidationSchema.ts | 4 ++ nym-wallet/src/utils/common.ts | 13 +++--- yarn.lock | 40 +++++++++++++++++++ 5 files changed, 62 insertions(+), 11 deletions(-) diff --git a/nym-wallet/package.json b/nym-wallet/package.json index a1a302bf9a..c930554e2b 100644 --- a/nym-wallet/package.json +++ b/nym-wallet/package.json @@ -29,9 +29,9 @@ "@mui/styles": "^5.2.2", "@mui/utils": "^5.7.0", "@nymproject/mui-theme": "^1.0.0", + "@nymproject/node-tester": "^1.0.0", "@nymproject/react": "^1.0.0", "@nymproject/types": "^1.0.0", - "@nymproject/node-tester": "^1.0.0", "@storybook/react": "^6.5.15", "@tauri-apps/api": "^1.2.0", "@tauri-apps/tauri-forage": "^1.0.0-beta.2", @@ -39,6 +39,7 @@ "bs58": "^4.0.1", "clsx": "^1.1.1", "date-fns": "^2.28.0", + "joi": "^17.11.0", "lodash": "^4.17.21", "notistack": "^2.0.3", "npm-run-all": "^4.1.5", @@ -123,4 +124,4 @@ "webpack-favicons": "^1.3.8", "webpack-merge": "^5.8.0" } -} \ No newline at end of file +} diff --git a/nym-wallet/src/components/Bonding/forms/gatewayValidationSchema.ts b/nym-wallet/src/components/Bonding/forms/gatewayValidationSchema.ts index 6935b6e623..9de1e6a1f7 100644 --- a/nym-wallet/src/components/Bonding/forms/gatewayValidationSchema.ts +++ b/nym-wallet/src/components/Bonding/forms/gatewayValidationSchema.ts @@ -11,7 +11,7 @@ import { export const gatewayValidationSchema = Yup.object().shape({ identityKey: Yup.string() - .required('An indentity key is required') + .required('An identity key is required') .test('valid-id-key', 'A valid identity key is required', (value) => validateKey(value || '', 32)), sphinxKey: Yup.string() @@ -20,10 +20,12 @@ export const gatewayValidationSchema = Yup.object().shape({ host: Yup.string() .required('A host is required') + .test('no-whitespace', 'Host cannot contain whitespace', (value) => !/\s/.test(value || '')) .test('valid-host', 'A valid host is required', (value) => (value ? isValidHostname(value) : false)), version: Yup.string() .required('A version is required') + .test('no-whitespace', 'A version cannot contain whitespace', (value) => !/\s/.test(value || '')) .test('valid-version', 'A valid version is required', (value) => (value ? validateVersion(value) : false)), location: Yup.string() @@ -70,6 +72,7 @@ export const amountSchema = Yup.object().shape({ export const updateGatewayValidationSchema = Yup.object().shape({ host: Yup.string() .required('A host is required') + .test('no-whitespace', 'Host cannot contain whitespace', (value) => !/\s/.test(value || '')) .test('valid-host', 'A valid host is required', (value) => (value ? isValidHostname(value) : false)), mixPort: Yup.number() @@ -82,7 +85,7 @@ export const updateGatewayValidationSchema = Yup.object().shape({ location: Yup.string().test('valid-location', 'A valid location is required', (value) => value ? validateLocation(value) : false, ), - version: Yup.string().test('valid-version', 'A valid version is required', (value) => - value ? validateVersion(value) : false, - ), + version: Yup.string() + .test('no-whitespace', 'A version cannot contain whitespace', (value) => !/\s/.test(value || '')) + .test('valid-version', 'A valid version is required', (value) => (value ? validateVersion(value) : false)), }); diff --git a/nym-wallet/src/components/Bonding/forms/mixnodeValidationSchema.ts b/nym-wallet/src/components/Bonding/forms/mixnodeValidationSchema.ts index 601731bd3e..3230fc0714 100644 --- a/nym-wallet/src/components/Bonding/forms/mixnodeValidationSchema.ts +++ b/nym-wallet/src/components/Bonding/forms/mixnodeValidationSchema.ts @@ -12,10 +12,12 @@ export const mixnodeValidationSchema = Yup.object().shape({ host: Yup.string() .required('A host is required') + .test('no-whitespace', 'Host cannot contain whitespace', (value) => !/\s/.test(value || '')) .test('valid-host', 'A valid host is required', (value) => (value ? isValidHostname(value) : false)), version: Yup.string() .required('A version is required') + .test('no-whitespace', 'A version cannot contain whitespace', (value) => !/\s/.test(value || '')) .test('valid-version', 'A valid version is required', (value) => (value ? validateVersion(value) : false)), mixPort: Yup.number() @@ -65,10 +67,12 @@ export const amountSchema = Yup.object().shape({ export const bondedInfoParametersValidationSchema = Yup.object().shape({ host: Yup.string() .required('A host is required') + .test('no-whitespace', 'Host cannot contain whitespace', (value) => !/\s/.test(value || '')) .test('valid-host', 'A valid host is required', (value) => (value ? isValidHostname(value) : false)), version: Yup.string() .required('A version is required') + .test('no-whitespace', 'A version cannot contain whitespace', (value) => !/\s/.test(value || '')) .test('valid-version', 'A valid version is required', (value) => (value ? validateVersion(value) : false)), mixPort: Yup.number() diff --git a/nym-wallet/src/utils/common.ts b/nym-wallet/src/utils/common.ts index 1f113ff37a..6d953db072 100644 --- a/nym-wallet/src/utils/common.ts +++ b/nym-wallet/src/utils/common.ts @@ -5,6 +5,7 @@ import { valid } from 'semver'; import { add, format, fromUnixTime } from 'date-fns'; import { DecCoin, isValidRawCoin, MixNodeCostParams } from '@nymproject/types'; import { TPoolOption } from 'src/components'; +import Joi from 'joi'; import { getCurrentInterval, getDefaultMixnodeCostParams, @@ -47,13 +48,15 @@ export const validateAmount = async ( }; export const isValidHostname = (value: string) => { - // regex for ipv4 and ipv6 and hostname- source http://jsfiddle.net/DanielD/8S4nq/ - const trimmedValue = value.replace(/\s+/g, ''); + const trimmedValue = value.trim(); - const hostnameRegex = - /((^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))|(^\s*((?=.{1,255}$)(?=.*[A-Za-z].*)[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?)*)\s*$)/; + const hostnameSchema = Joi.alternatives().try( + Joi.string().hostname(), + Joi.string().ip({ version: ['ipv4', 'ipv6'] }), + ); - return hostnameRegex.test(trimmedValue); + const result = hostnameSchema.validate(trimmedValue); + return !result.error; }; export const validateVersion = (version: string): boolean => { diff --git a/yarn.lock b/yarn.lock index e5fc44427d..d982958fcf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1830,6 +1830,18 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== +"@hapi/hoek@^9.0.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.0.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hookform/resolvers@^2.8.0": version "2.9.11" resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.9.11.tgz#9ce96e7746625a89239f68ca57c4f654264c17ef" @@ -3035,6 +3047,23 @@ "@sentry/types" "7.73.0" tslib "^2.4.1 || ^1.9.3" +"@sideway/address@^4.1.3": + version "4.1.4" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" + integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "@sigstore/bundle@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@sigstore/bundle/-/bundle-1.1.0.tgz#17f8d813b09348b16eeed66a8cf1c3d6bd3d04f1" @@ -12417,6 +12446,17 @@ jest@^27.1.0: import-local "^3.0.2" jest-cli "^27.5.1" +joi@^17.11.0: + version "17.11.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.11.0.tgz#aa9da753578ec7720e6f0ca2c7046996ed04fc1a" + integrity sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.3" + "@sideway/formula" "^3.0.1" + "@sideway/pinpoint" "^2.0.0" + js-sha3@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" From 9d1adf9884ded83a3247deb20cebc8a044c2f05f Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 26 Oct 2023 16:56:43 +0200 Subject: [PATCH 108/236] fix based on feedback --- documentation/operators/src/legal/exit-gateway.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index 69e1ec4099..2cd3f03daa 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -22,7 +22,7 @@ Nym core team cannot provide comprehensive legal advice across all jurisdictions * Currently, Nym Gateway nodes only enable access to apps and services that are on an ‘allow’ list that is maintained by the core team. -* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list - [Exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). Based on two existing safeguards: [Tor Null ‘deny’ list](https://tornull.org/) and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). +* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list - [Exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). In accordance with the [Tor Null 'deny' list](https://tornull.org/) and [Tor reduced policy] (https://tornull.org/tor-reduced-reduced-exit-policy.php), which are two established safeguards. * This will enhance the usage and appeal of Nym products for end users. As a result, increased usage will ultimately lead to higher revenues for Nym operators. @@ -69,11 +69,11 @@ In our previous technical setup, network requesters acted as a proxy, and only m This restricts the hosts that the NymConnect app can connect to and has the effect of selectively supporting messaging services (e.g. Telegram, Matrix) or crypto wallets (e.g. Electrum or Monero). Operators of network requesters can have confidence that the infrastructure they run only connects to a limited set of public internet hosts. -In the new setup, the main change is to expand this short allow list to a more permissive setup. An [Exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym Mixnet and Nym VPN can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym Mixnet VPN and VPN clients (both wrapped in the same app). +The principal change in the new configuration is to make this short allow list more permissive. Nym's [Exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will restrict the hosts to which Nym Mixnet and Nym VPN users are permitted to connect. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym Mixnet VPN and VPN clients (both wrapped in the same app). As of now we the gateways will be defaulted to a combination of [Tor Null ‘deny’ list](https://tornull.org/) (note: Not affiliated with Tor) - reproduction permitted under Creative Commons Attribution 3.0 United States License which is IP-based, e.g., `ExitPolicy reject 5.188.10.0/23:*` and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). Whether we will stick with this list, do modifications or compile another one is still a subject of discussion. In all cases, this policy will remain the same for all the nodes, without any option to modify it by Nym node operators to secure stable and reliable service for the end users. -The Gateways will display an HTML page similar to that suggested by [Tor](https://gitlab.torproject.org/tpo/core/tor/-/raw/HEAD/contrib/operator-tools/tor-exit-notice.html) for exit relays on port 80 and port 443. This will allow the operator to provide information about their Gateway, possibly including the currently configured exit policy, without having to actively communicate with law enforcement or regulatory authorities. It also makes the behaviour of exit gateways transparent and even computable (a possible feature would be to offer a machine readable form of the notice in JSON or YAML). +For exit relays on ports 80 and 443, the gateways will exhibit an HTML page resembling the one proposed by [Tor](https://gitlab.torproject.org/tpo/core/tor/-/raw/HEAD/contrib/operator-tools/tor-exit-notice.html). By doing so, the operator will be able to disclose details regarding their gateway, including the currently configured exit policy, all without the need for direct correspondence with regulatory or law enforcement agencies. It also makes the behaviour of exit gateways transparent and even computable (a possible feature would be to offer a machine readable form of the notice in JSON or YAML). We also recommend operators to check the technical advice from [Tor](https://community.torproject.org/relay/setup/exit/). From d95f0e6f545eb2200e83b39f3e436eb3bc0e9b08 Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Thu, 26 Oct 2023 17:00:52 +0200 Subject: [PATCH 109/236] remove overhang from previous round :) --- nym-wallet/src/utils/common.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nym-wallet/src/utils/common.ts b/nym-wallet/src/utils/common.ts index 6d953db072..973e766c33 100644 --- a/nym-wallet/src/utils/common.ts +++ b/nym-wallet/src/utils/common.ts @@ -48,14 +48,12 @@ export const validateAmount = async ( }; export const isValidHostname = (value: string) => { - const trimmedValue = value.trim(); - const hostnameSchema = Joi.alternatives().try( Joi.string().hostname(), Joi.string().ip({ version: ['ipv4', 'ipv6'] }), ); - const result = hostnameSchema.validate(trimmedValue); + const result = hostnameSchema.validate(value); return !result.error; }; From bef4a92e9908ff863297615226d1f514f88ed159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 26 Oct 2023 18:13:36 +0200 Subject: [PATCH 110/236] Create beginning of nym-ip-forwarder crate (#4063) --- Cargo.lock | 16 ++ Cargo.toml | 1 + service-providers/ip-forwarder/Cargo.toml | 21 +++ .../ip-forwarder/src/config/mod.rs | 23 +++ .../ip-forwarder/src/config/persistence.rs | 28 +++ service-providers/ip-forwarder/src/error.rs | 29 +++ service-providers/ip-forwarder/src/lib.rs | 169 ++++++++++++++++++ 7 files changed, 287 insertions(+) create mode 100644 service-providers/ip-forwarder/Cargo.toml create mode 100644 service-providers/ip-forwarder/src/config/mod.rs create mode 100644 service-providers/ip-forwarder/src/config/persistence.rs create mode 100644 service-providers/ip-forwarder/src/error.rs create mode 100644 service-providers/ip-forwarder/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index eb1e5cd900..614ed8738a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6643,6 +6643,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "nym-ip-forwarder" +version = "0.1.0" +dependencies = [ + "futures", + "log", + "nym-client-core", + "nym-config", + "nym-sdk", + "nym-sphinx", + "nym-task", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "nym-mixnet-client" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index e4d6645927..802b81f89e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,6 +90,7 @@ members = [ "sdk/lib/socks5-listener", "sdk/rust/nym-sdk", "service-providers/common", + "service-providers/ip-forwarder", "service-providers/network-requester", "service-providers/network-statistics", "nym-api", diff --git a/service-providers/ip-forwarder/Cargo.toml b/service-providers/ip-forwarder/Cargo.toml new file mode 100644 index 0000000000..777de65c28 --- /dev/null +++ b/service-providers/ip-forwarder/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "nym-ip-forwarder" +version = "0.1.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] +futures = { workspace = true } +log = { workspace = true } +nym-client-core = { path = "../../common/client-core" } +nym-config = { path = "../../common/config" } +nym-sdk = { path = "../../sdk/rust/nym-sdk" } +nym-sphinx = { path = "../../common/nymsphinx" } +nym-task = { path = "../../common/task" } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +thiserror = { workspace = true } diff --git a/service-providers/ip-forwarder/src/config/mod.rs b/service-providers/ip-forwarder/src/config/mod.rs new file mode 100644 index 0000000000..1792793107 --- /dev/null +++ b/service-providers/ip-forwarder/src/config/mod.rs @@ -0,0 +1,23 @@ +use std::{io, path::Path}; + +pub use nym_client_core::config::Config as BaseClientConfig; +use serde::{Deserialize, Serialize}; + +use crate::config::persistence::IpForwarderPaths; + +mod persistence; + +#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct Config { + #[serde(flatten)] + pub base: BaseClientConfig, + + pub storage_paths: IpForwarderPaths, +} + +impl Config { + pub fn read_from_toml_file>(path: P) -> io::Result { + nym_config::read_config_from_toml_file(path) + } +} diff --git a/service-providers/ip-forwarder/src/config/persistence.rs b/service-providers/ip-forwarder/src/config/persistence.rs new file mode 100644 index 0000000000..17276d36b3 --- /dev/null +++ b/service-providers/ip-forwarder/src/config/persistence.rs @@ -0,0 +1,28 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use nym_client_core::config::disk_persistence::CommonClientPaths; +use serde::{Deserialize, Serialize}; +use std::path::{Path, PathBuf}; + +pub const DEFAULT_DESCRIPTION_FILENAME: &str = "description.toml"; + +#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)] +pub struct IpForwarderPaths { + #[serde(flatten)] + pub common_paths: CommonClientPaths, + + /// Location of the file containing our description + pub ip_forwarder_description: PathBuf, +} + +impl IpForwarderPaths { + pub fn new_base>(base_data_directory: P) -> Self { + let base_dir = base_data_directory.as_ref(); + + Self { + common_paths: CommonClientPaths::new_base(base_dir), + ip_forwarder_description: base_dir.join(DEFAULT_DESCRIPTION_FILENAME), + } + } +} diff --git a/service-providers/ip-forwarder/src/error.rs b/service-providers/ip-forwarder/src/error.rs new file mode 100644 index 0000000000..7a0268fb61 --- /dev/null +++ b/service-providers/ip-forwarder/src/error.rs @@ -0,0 +1,29 @@ +pub use nym_client_core::error::ClientCoreError; + +#[derive(thiserror::Error, Debug)] +pub enum IpForwarderError { + #[error("I/O error: {0}")] + IoError(#[from] std::io::Error), + + #[error("client-core error: {0}")] + ClientCoreError(#[from] ClientCoreError), + + #[error("failed to load configuration file: {0}")] + FailedToLoadConfig(String), + + // TODO: add more details here + #[error("Failed to validate the loaded config")] + ConfigValidationFailure, + + #[error("failed local version check, client and config mismatch")] + FailedLocalVersionCheck, + + #[error("failed to setup mixnet client: {source}")] + FailedToSetupMixnetClient { source: nym_sdk::Error }, + + #[error("failed to connect to mixnet: {source}")] + FailedToConnectToMixnet { source: nym_sdk::Error }, + + #[error("the entity wrapping the network requester has disconnected")] + DisconnectedParent, +} diff --git a/service-providers/ip-forwarder/src/lib.rs b/service-providers/ip-forwarder/src/lib.rs new file mode 100644 index 0000000000..9aadf5f50a --- /dev/null +++ b/service-providers/ip-forwarder/src/lib.rs @@ -0,0 +1,169 @@ +use std::path::Path; + +use error::IpForwarderError; +use futures::channel::oneshot; +use nym_client_core::{ + client::mix_traffic::transceiver::GatewayTransceiver, + config::disk_persistence::CommonClientPaths, HardcodedTopologyProvider, TopologyProvider, +}; +use nym_sdk::{mixnet::Recipient, NymNetworkDetails}; +use nym_task::{TaskClient, TaskHandle}; + +use crate::config::BaseClientConfig; + +pub use crate::config::Config; + +pub mod config; +pub mod error; + +pub struct OnStartData { + // to add more fields as required + pub address: Recipient, +} + +impl OnStartData { + pub fn new(address: Recipient) -> Self { + Self { address } + } +} + +pub struct IpForwarderBuilder { + config: Config, + wait_for_gateway: bool, + custom_topology_provider: Option>, + custom_gateway_transceiver: Option>, + shutdown: Option, + on_start: Option>, +} + +impl IpForwarderBuilder { + pub fn new(config: Config) -> Self { + Self { + config, + wait_for_gateway: false, + custom_topology_provider: None, + custom_gateway_transceiver: None, + shutdown: None, + on_start: None, + } + } + + #[must_use] + pub fn with_shutdown(mut self, shutdown: TaskClient) -> Self { + self.shutdown = Some(shutdown); + self + } + + #[must_use] + pub fn with_custom_gateway_transceiver( + mut self, + gateway_transceiver: Box, + ) -> Self { + self.custom_gateway_transceiver = Some(gateway_transceiver); + self + } + + #[must_use] + pub fn with_wait_for_gateway(mut self, wait_for_gateway: bool) -> Self { + self.wait_for_gateway = wait_for_gateway; + self + } + + #[must_use] + pub fn with_on_start(mut self, on_start: oneshot::Sender) -> Self { + self.on_start = Some(on_start); + self + } + + #[must_use] + pub fn with_custom_topology_provider( + mut self, + topology_provider: Box, + ) -> Self { + self.custom_topology_provider = Some(topology_provider); + self + } + + pub fn with_stored_topology>( + mut self, + file: P, + ) -> Result { + self.custom_topology_provider = + Some(Box::new(HardcodedTopologyProvider::new_from_file(file)?)); + Ok(self) + } + + pub async fn run_service_provider(self) -> Result<(), IpForwarderError> { + // Used to notify tasks to shutdown. Not all tasks fully supports this (yet). + let shutdown: TaskHandle = self.shutdown.map(Into::into).unwrap_or_default(); + + // Connect to the mixnet + let mixnet_client = create_mixnet_client( + &self.config.base, + shutdown.get_handle().named("nym_sdk::MixnetClient"), + self.custom_gateway_transceiver, + self.custom_topology_provider, + self.wait_for_gateway, + &self.config.storage_paths.common_paths, + ) + .await?; + + let self_address = *mixnet_client.nym_address(); + + log::info!("The address of this client is: {self_address}"); + log::info!("All systems go. Press CTRL-C to stop the server."); + + if let Some(on_start) = self.on_start { + if on_start.send(OnStartData::new(self_address)).is_err() { + // the parent has dropped the channel before receiving the response + return Err(IpForwarderError::DisconnectedParent); + } + } + + todo!(); + } +} + +// Helper function to create the mixnet client. +// This is NOT in the SDK since we don't want to expose any of the client-core config types. +// We could however consider moving it to a crate in common in the future. +// TODO: refactor this function and its arguments +async fn create_mixnet_client( + config: &BaseClientConfig, + shutdown: TaskClient, + custom_transceiver: Option>, + custom_topology_provider: Option>, + wait_for_gateway: bool, + paths: &CommonClientPaths, +) -> Result { + let debug_config = config.debug; + + let storage_paths = nym_sdk::mixnet::StoragePaths::from(paths.clone()); + + let mut client_builder = + nym_sdk::mixnet::MixnetClientBuilder::new_with_default_storage(storage_paths) + .await + .map_err(|err| IpForwarderError::FailedToSetupMixnetClient { source: err })? + .network_details(NymNetworkDetails::new_from_env()) + .debug_config(debug_config) + .custom_shutdown(shutdown) + .with_wait_for_gateway(wait_for_gateway); + if !config.get_disabled_credentials_mode() { + client_builder = client_builder.enable_credentials_mode(); + } + if let Some(gateway_transceiver) = custom_transceiver { + client_builder = client_builder.custom_gateway_transceiver(gateway_transceiver); + } + if let Some(topology_provider) = custom_topology_provider { + client_builder = client_builder.custom_topology_provider(topology_provider); + } + + let mixnet_client = client_builder + .build() + .map_err(|err| IpForwarderError::FailedToSetupMixnetClient { source: err })?; + + mixnet_client + .connect_to_mixnet() + .await + .map_err(|err| IpForwarderError::FailedToConnectToMixnet { source: err }) +} From acbfdd7bbfa9d8ee2a51c985216df2c825b687ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Oct 2023 09:49:17 +0100 Subject: [PATCH 111/236] Bump browserify-sign from 4.2.1 to 4.2.2 (#4066) Bumps [browserify-sign](https://github.com/crypto-browserify/browserify-sign) from 4.2.1 to 4.2.2. - [Changelog](https://github.com/browserify/browserify-sign/blob/main/CHANGELOG.md) - [Commits](https://github.com/crypto-browserify/browserify-sign/compare/v4.2.1...v4.2.2) --- updated-dependencies: - dependency-name: browserify-sign dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/yarn.lock b/yarn.lock index d982958fcf..1d5fec6aef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6459,7 +6459,7 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.8, bn.js@^4.11.9: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.2.0: +bn.js@^5.0.0, bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== @@ -6607,7 +6607,7 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: +browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== @@ -6616,19 +6616,19 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + version "4.2.2" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e" + integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg== dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" + bn.js "^5.2.1" + browserify-rsa "^4.1.0" create-hash "^1.2.0" create-hmac "^1.1.7" - elliptic "^6.5.3" + elliptic "^6.5.4" inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + parse-asn1 "^5.1.6" + readable-stream "^3.6.2" + safe-buffer "^5.2.1" browserify-zlib@^0.2.0: version "0.2.0" @@ -15137,7 +15137,7 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0, parse-asn1@^5.1.5: +parse-asn1@^5.0.0, parse-asn1@^5.1.6: version "5.1.6" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== @@ -16508,7 +16508,7 @@ read@^2.0.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: +readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0, readable-stream@^3.6.2: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -17051,7 +17051,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== From 6c436024f767d516a1da723e32a3cd94576f7b69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Oct 2023 09:49:40 +0100 Subject: [PATCH 112/236] Bump browserify-sign from 4.2.1 to 4.2.2 in /testnet-faucet (#4067) Bumps [browserify-sign](https://github.com/crypto-browserify/browserify-sign) from 4.2.1 to 4.2.2. - [Changelog](https://github.com/browserify/browserify-sign/blob/main/CHANGELOG.md) - [Commits](https://github.com/crypto-browserify/browserify-sign/compare/v4.2.1...v4.2.2) --- updated-dependencies: - dependency-name: browserify-sign dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testnet-faucet/yarn.lock | 71 +++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/testnet-faucet/yarn.lock b/testnet-faucet/yarn.lock index 4c313acb5f..be27983742 100644 --- a/testnet-faucet/yarn.lock +++ b/testnet-faucet/yarn.lock @@ -1488,11 +1488,16 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.8, bn.js@^4.11.9: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1: +bn.js@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -1549,7 +1554,7 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: +browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== @@ -1558,19 +1563,19 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + version "4.2.2" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e" + integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg== dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" + bn.js "^5.2.1" + browserify-rsa "^4.1.0" create-hash "^1.2.0" create-hmac "^1.1.7" - elliptic "^6.5.3" + elliptic "^6.5.4" inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + parse-asn1 "^5.1.6" + readable-stream "^3.6.2" + safe-buffer "^5.2.1" browserslist@^4.6.6: version "4.18.1" @@ -1935,7 +1940,7 @@ electron-to-chromium@^1.3.896: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.903.tgz#e2d3c3809f4ef05fdbe5cc88969dfc94b1bd15b9" integrity sha512-+PnYAyniRRTkNq56cqYDLq9LyklZYk0hqoDy9GpcU11H5QjRmFZVDbxtgHUMK/YzdNTcn1XWP5gb+hFlSCr20g== -elliptic@^6.5.3: +elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -2967,7 +2972,7 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0, parse-asn1@^5.1.5: +parse-asn1@^5.0.0, parse-asn1@^5.1.6: version "5.1.6" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== @@ -3160,14 +3165,13 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -react-dom@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" - integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== +react-dom@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" + integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler "^0.20.2" + scheduler "^0.23.0" react-hook-form@^7.20.1: version "7.20.1" @@ -3199,13 +3203,12 @@ react-transition-group@^4.4.2: loose-envify "^1.4.0" prop-types "^15.6.2" -react@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" - integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== +react@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.0" @@ -3216,6 +3219,15 @@ readable-stream@^3.5.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readonly-date@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/readonly-date/-/readonly-date-1.0.0.tgz#5af785464d8c7d7c40b9d738cbde8c646f97dcd9" @@ -3287,7 +3299,7 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -3302,13 +3314,12 @@ safer-buffer@^2.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -scheduler@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" - integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== +scheduler@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" + integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" semver@^5.7.0, semver@^5.7.1: version "5.7.1" From ffb4457427e7db3d87364b0e613b33d86b9bd7e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Fri, 27 Oct 2023 13:40:42 +0300 Subject: [PATCH 113/236] Feature/wg gateway data on handshake init (#4057) * Return wg gateway data on handshake init * Add wg register to gateway api client * Remove socket addr and return just wg port --- common/wireguard-types/src/registration.rs | 35 ++++++------------- gateway/src/http/mod.rs | 7 +++- nym-node/nym-node-requests/src/api/client.rs | 12 +++++++ .../wireguard/client_registry.rs | 11 +++++- .../client_interfaces/wireguard/mod.rs | 19 ++++++---- 5 files changed, 51 insertions(+), 33 deletions(-) diff --git a/common/wireguard-types/src/registration.rs b/common/wireguard-types/src/registration.rs index c899be5d02..1da614aaa0 100644 --- a/common/wireguard-types/src/registration.rs +++ b/common/wireguard-types/src/registration.rs @@ -6,7 +6,6 @@ use crate::PeerPublicKey; use base64::{engine::general_purpose, Engine}; use dashmap::DashMap; use serde::{Deserialize, Serialize}; -use std::net::SocketAddr; use std::{fmt, ops::Deref, str::FromStr}; #[cfg(feature = "verify")] @@ -54,11 +53,17 @@ impl InitMessage { #[serde(tag = "type", rename_all = "camelCase")] #[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] pub enum ClientRegistrationResponse { - PendingRegistration { nonce: u64 }, - Registered { success: bool }, + PendingRegistration { + nonce: u64, + gateway_data: GatewayClient, + wg_port: u16, + }, + Registered { + success: bool, + }, } -/// Client that wants to register sends its PublicKey and SocketAddr bytes mac digest encrypted with a DH shared secret. +/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret. /// Gateway/Nym node can then verify pub_key payload using the same process #[derive(Serialize, Deserialize, Debug, Clone)] #[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] @@ -67,10 +72,6 @@ pub struct GatewayClient { #[cfg_attr(feature = "openapi", schema(value_type = String, format = Byte))] pub pub_key: PeerPublicKey, - /// Client's socket address - #[cfg_attr(feature = "openapi", schema(example = "1.2.3.4:51820", value_type = String))] - pub socket: SocketAddr, - /// Sha256 hmac on the data (alongside the prior nonce) #[cfg_attr(feature = "openapi", schema(value_type = String, format = Byte))] pub mac: ClientMac, @@ -78,12 +79,7 @@ pub struct GatewayClient { impl GatewayClient { #[cfg(feature = "verify")] - pub fn new( - local_secret: &PrivateKey, - remote_public: PublicKey, - socket_address: SocketAddr, - nonce: u64, - ) -> Self { + pub fn new(local_secret: &PrivateKey, remote_public: PublicKey, nonce: u64) -> Self { // convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek #[allow(clippy::expect_used)] let static_secret = boringtun::x25519::StaticSecret::try_from(local_secret.to_bytes()) @@ -100,13 +96,10 @@ impl GatewayClient { .expect("x25519 shared secret is always 32 bytes long"); mac.update(local_public.as_bytes()); - mac.update(socket_address.ip().to_string().as_bytes()); - mac.update(socket_address.port().to_string().as_bytes()); mac.update(&nonce.to_le_bytes()); GatewayClient { pub_key: PeerPublicKey::new(local_public), - socket: socket_address, mac: ClientMac(mac.finalize().into_bytes().to_vec()), } } @@ -128,8 +121,6 @@ impl GatewayClient { .expect("x25519 shared secret is always 32 bytes long"); mac.update(self.pub_key.as_bytes()); - mac.update(self.socket.ip().to_string().as_bytes()); - mac.update(self.socket.port().to_string().as_bytes()); mac.update(&nonce.to_le_bytes()); mac.verify_slice(&self.mac) @@ -142,10 +133,6 @@ impl GatewayClient { pub fn pub_key(&self) -> PeerPublicKey { self.pub_key } - - pub fn socket(&self) -> SocketAddr { - self.socket - } } // TODO: change the inner type into generic array of size HmacSha256::OutputSize @@ -217,13 +204,11 @@ mod tests { let gateway_key_pair = encryption::KeyPair::new(&mut rng); let client_key_pair = encryption::KeyPair::new(&mut rng); - let socket: SocketAddr = "1.2.3.4:5678".parse().unwrap(); let nonce = 1234567890; let client = GatewayClient::new( client_key_pair.private_key(), *gateway_key_pair.public_key(), - socket, nonce, ); assert!(client.verify(gateway_key_pair.private_key(), nonce).is_ok()) diff --git a/gateway/src/http/mod.rs b/gateway/src/http/mod.rs index a53a966584..d27b7873c6 100644 --- a/gateway/src/http/mod.rs +++ b/gateway/src/http/mod.rs @@ -224,7 +224,12 @@ impl<'a> HttpApiBuilder<'a> { } let wg_state = self.client_registry.map(|client_registry| { - WireguardAppState::new(self.sphinx_keypair, client_registry, Default::default()) + WireguardAppState::new( + self.sphinx_keypair, + client_registry, + Default::default(), + self.gateway_config.wireguard.bind_address.port(), + ) }); let router = nym_node::http::NymNodeRouter::new(config, wg_state); diff --git a/nym-node/nym-node-requests/src/api/client.rs b/nym-node/nym-node-requests/src/api/client.rs index 1967b6963e..6815b1a023 100644 --- a/nym-node/nym-node-requests/src/api/client.rs +++ b/nym-node/nym-node-requests/src/api/client.rs @@ -8,6 +8,7 @@ use crate::routes; use async_trait::async_trait; use http_api_client::{ApiClient, HttpClientError}; use nym_bin_common::build_information::BinaryBuildInformationOwned; +use nym_wireguard_types::{ClientMessage, ClientRegistrationResponse}; use crate::api::v1::health::models::NodeHealth; pub use http_api_client::Client; @@ -40,6 +41,17 @@ pub trait NymNodeApiClientExt: ApiClient { ) .await } + + async fn post_gateway_register_client( + &self, + client_message: &ClientMessage, + ) -> Result { + self.post_json_data_to( + routes::api::v1::gateway::client_interfaces::wireguard::client_absolute(), + client_message, + ) + .await + } } #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] diff --git a/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/client_registry.rs b/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/client_registry.rs index f21a1e719f..850443e325 100644 --- a/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/client_registry.rs +++ b/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/client_registry.rs @@ -10,6 +10,7 @@ use crate::wireguard::error::WireguardError; use axum::extract::{Path, Query, State}; use axum::http::StatusCode; use axum::Json; +use nym_crypto::asymmetric::encryption::PublicKey; use nym_node_requests::api::v1::gateway::client_interfaces::wireguard::models::{ ClientMessage, ClientRegistrationResponse, GatewayClient, InitMessage, Nonce, PeerPublicKey, }; @@ -87,8 +88,16 @@ pub(crate) async fn register_client( match payload { ClientMessage::Initial(init) => { + let remote_public = PublicKey::from_bytes(init.pub_key().as_bytes()) + .map_err(|_| RequestError::new_status(StatusCode::BAD_REQUEST))?; let nonce = process_init_message(init, state).await; - let response = ClientRegistrationResponse::PendingRegistration { nonce }; + let gateway_data = + GatewayClient::new(state.dh_keypair.private_key(), remote_public, nonce); + let response = ClientRegistrationResponse::PendingRegistration { + nonce, + gateway_data, + wg_port: state.binding_port, + }; Ok(output.to_response(response)) } ClientMessage::Final(finalize) => { diff --git a/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/mod.rs b/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/mod.rs index 8e29d8c0fb..37348be94e 100644 --- a/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/mod.rs +++ b/nym-node/src/http/router/api/v1/gateway/client_interfaces/wireguard/mod.rs @@ -25,12 +25,14 @@ impl WireguardAppState { dh_keypair: Arc, client_registry: Arc, registration_in_progress: Arc, + binding_port: u16, ) -> Self { WireguardAppState { inner: Some(WireguardAppStateInner { dh_keypair, client_registry, registration_in_progress, + binding_port, }), } } @@ -74,6 +76,7 @@ pub(crate) struct WireguardAppStateInner { dh_keypair: Arc, client_registry: Arc, registration_in_progress: Arc, + binding_port: u16, } pub(crate) fn routes(initial_state: WireguardAppState) -> Router { @@ -139,6 +142,7 @@ mod test { client_registry: Arc::clone(&client_registry), dh_keypair: Arc::new(gateway_key_pair), registration_in_progress: Arc::clone(®istration_in_progress), + binding_port: 8080, }), }; @@ -167,23 +171,26 @@ mod test { assert_eq!(response.status(), StatusCode::OK); assert!(!registration_in_progress.is_empty()); - let ClientRegistrationResponse::PendingRegistration { nonce } = - serde_json::from_slice(&hyper::body::to_bytes(response.into_body()).await.unwrap()) - .unwrap() + let ClientRegistrationResponse::PendingRegistration { + nonce, + gateway_data, + wg_port: 8080, + } = serde_json::from_slice(&hyper::body::to_bytes(response.into_body()).await.unwrap()) + .unwrap() else { panic!("invalid response") }; + assert!(gateway_data + .verify(client_key_pair.private_key(), nonce) + .is_ok()); let mut mac = HmacSha256::new_from_slice(client_dh.as_bytes()).unwrap(); mac.update(client_static_public.as_bytes()); - mac.update("127.0.0.1".as_bytes()); - mac.update("8080".as_bytes()); mac.update(&nonce.to_le_bytes()); let mac = mac.finalize().into_bytes(); let finalized_message = ClientMessage::Final(GatewayClient { pub_key: PeerPublicKey::new(client_static_public), - socket: "127.0.0.1:8080".parse().unwrap(), mac: ClientMac::new(mac.as_slice().to_vec()), }); From a209b87a4160d86f52304bbea544d598b3e76dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Fri, 27 Oct 2023 14:29:57 +0300 Subject: [PATCH 114/236] Use the same hardcoded value for wg port --- common/wireguard-types/src/lib.rs | 2 ++ common/wireguard/src/setup.rs | 1 - common/wireguard/src/udp_listener.rs | 4 ++-- nym-node/src/config/mod.rs | 5 +++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/common/wireguard-types/src/lib.rs b/common/wireguard-types/src/lib.rs index acb3366f86..6467dfa6e9 100644 --- a/common/wireguard-types/src/lib.rs +++ b/common/wireguard-types/src/lib.rs @@ -13,3 +13,5 @@ pub use registration::{ #[cfg(feature = "verify")] pub use registration::HmacSha256; + +pub const WG_PORT: u16 = 51822; diff --git a/common/wireguard/src/setup.rs b/common/wireguard/src/setup.rs index b01442258a..94331d2e79 100644 --- a/common/wireguard/src/setup.rs +++ b/common/wireguard/src/setup.rs @@ -6,7 +6,6 @@ use log::info; // The wireguard UDP listener pub const WG_ADDRESS: &str = "0.0.0.0"; -pub const WG_PORT: u16 = 51822; // The interface used to route traffic pub const TUN_BASE_NAME: &str = "nymtun"; diff --git a/common/wireguard/src/udp_listener.rs b/common/wireguard/src/udp_listener.rs index 8e32325c36..49aade2330 100644 --- a/common/wireguard/src/udp_listener.rs +++ b/common/wireguard/src/udp_listener.rs @@ -7,7 +7,7 @@ use boringtun::{ use futures::StreamExt; use log::error; use nym_task::TaskClient; -use nym_wireguard_types::{registration::GatewayClientRegistry, PeerPublicKey}; +use nym_wireguard_types::{registration::GatewayClientRegistry, PeerPublicKey, WG_PORT}; use tap::TapFallible; use tokio::{net::UdpSocket, sync::Mutex}; @@ -18,7 +18,7 @@ use crate::{ network_table::NetworkTable, packet_relayer::PacketRelaySender, registered_peers::{RegisteredPeer, RegisteredPeers}, - setup::{self, WG_ADDRESS, WG_PORT}, + setup::{self, WG_ADDRESS}, wg_tunnel::PeersByTag, }; diff --git a/nym-node/src/config/mod.rs b/nym-node/src/config/mod.rs index 87b464c48e..958b912c7b 100644 --- a/nym-node/src/config/mod.rs +++ b/nym-node/src/config/mod.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use nym_config::defaults::DEFAULT_NYM_NODE_HTTP_PORT; +use nym_wireguard_types::WG_PORT; use serde::{Deserialize, Serialize}; use serde_helpers::*; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; @@ -10,7 +11,7 @@ use std::path::PathBuf; pub mod persistence; mod serde_helpers; -pub const DEFAULT_WIREGUARD_PORT: u16 = 51820; +pub const DEFAULT_WIREGUARD_PORT: u16 = WG_PORT; pub const DEFAULT_HTTP_PORT: u16 = DEFAULT_NYM_NODE_HTTP_PORT; // TODO: this is very much a WIP. we need proper ssl certificate support here @@ -66,7 +67,7 @@ pub struct Wireguard { pub enabled: bool, /// Socket address this node will use for binding its wireguard interface. - /// default: `0.0.0.0:51820` + /// default: `0.0.0.0:51822` pub bind_address: SocketAddr, /// Port announced to external clients wishing to connect to the wireguard interface. From 8270204c7e2553f8c726edb4ce8db703decabcc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 26 Oct 2023 17:01:43 +0200 Subject: [PATCH 115/236] Run embedded ip-forwarder in gateway --- Cargo.lock | 1 + gateway/Cargo.toml | 1 + gateway/src/commands/helpers.rs | 12 ++ gateway/src/commands/run.rs | 16 ++- gateway/src/config/mod.rs | 17 +++ gateway/src/config/old_config_v1_1_29.rs | 4 + gateway/src/config/persistence/paths.rs | 5 + gateway/src/error.rs | 24 ++++ .../embedded_network_requester/mod.rs | 11 ++ gateway/src/node/helpers.rs | 14 ++ gateway/src/node/mod.rs | 125 +++++++++++++++++- 11 files changed, 223 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 614ed8738a..369423472d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6540,6 +6540,7 @@ dependencies = [ "nym-credentials", "nym-crypto", "nym-gateway-requests", + "nym-ip-forwarder", "nym-mixnet-client", "nym-mixnode-common", "nym-network-defaults", diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index b968ee7b7e..b5881ef080 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -76,6 +76,7 @@ nym-task = { path = "../common/task" } nym-types = { path = "../common/types" } nym-validator-client = { path = "../common/client-libs/validator-client" } nym-wireguard = { path = "../common/wireguard", optional = true } +nym-ip-forwarder = { path = "../service-providers/ip-forwarder" } [dev-dependencies] tower = "0.4.13" diff --git a/gateway/src/commands/helpers.rs b/gateway/src/commands/helpers.rs index 9029c14a7a..94947890c4 100644 --- a/gateway/src/commands/helpers.rs +++ b/gateway/src/commands/helpers.rs @@ -101,6 +101,11 @@ pub(crate) struct OverrideNetworkRequesterConfig { pub(crate) statistics_recipient: Option, } +#[derive(Default)] +pub(crate) struct OverrideIpForwarderConfig { + // TODO +} + /// Ensures that a given bech32 address is valid pub(crate) fn ensure_correct_bech32_prefix(address: &AccountId) -> Result<(), GatewayError> { let expected_prefix = @@ -220,6 +225,13 @@ pub(crate) fn override_network_requester_config( ) } +pub(crate) fn override_ip_forwarder_config( + cfg: nym_ip_forwarder::Config, + _opts: Option, +) -> nym_ip_forwarder::Config { + cfg +} + pub(crate) async fn initialise_local_network_requester( gateway_config: &Config, opts: OverrideNetworkRequesterConfig, diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index 185bf75a53..4f390db406 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -15,6 +15,8 @@ use nym_node::error::NymNodeError; use std::net::IpAddr; use std::path::PathBuf; +use super::helpers::OverrideIpForwarderConfig; + #[derive(Args, Clone)] pub struct Run { /// Id of the gateway we want to run @@ -88,6 +90,10 @@ pub struct Run { #[clap(long)] with_network_requester: Option, + /// Allows this gateway to run an embedded network requester for minimal network overhead + #[clap(long)] + with_ip_forwarder: Option, + // ##### NETWORK REQUESTER FLAGS ##### /// Specifies whether this network requester should run in 'open-proxy' mode #[arg(long)] @@ -175,6 +181,12 @@ impl<'a> From<&'a Run> for OverrideNetworkRequesterConfig { } } +impl From<&Run> for OverrideIpForwarderConfig { + fn from(_value: &Run) -> Self { + OverrideIpForwarderConfig {} + } +} + fn show_binding_warning(address: IpAddr) { eprintln!("\n##### NOTE #####"); eprintln!( @@ -217,6 +229,7 @@ pub async fn execute(args: Run) -> anyhow::Result<()> { let output = args.output; let custom_mixnet = args.custom_mixnet.clone(); let nr_opts = (&args).into(); + let ip_opts = (&args).into(); let config = build_config(id, args)?; ensure_config_version_compatibility(&config)?; @@ -235,7 +248,8 @@ pub async fn execute(args: Run) -> anyhow::Result<()> { } let node_details = node_details(&config)?; - let gateway = crate::node::create_gateway(config, Some(nr_opts), custom_mixnet).await?; + let gateway = + crate::node::create_gateway(config, Some(nr_opts), Some(ip_opts), custom_mixnet).await?; eprintln!( "\nTo bond your gateway you will need to install the Nym wallet, go to https://nymtech.net/get-involved and select the Download button.\n\ Select the correct version and install it to your machine. You will need to provide some of the following: \n "); diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index 134964fe94..caef4cd68d 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -100,6 +100,8 @@ pub struct Config { pub network_requester: NetworkRequester, + pub ip_forwarder: IpForwarder, + #[serde(default)] pub logging: LoggingSettings, @@ -128,6 +130,7 @@ impl Config { wireguard: Default::default(), storage_paths: GatewayPaths::new_default(id.as_ref()), network_requester: Default::default(), + ip_forwarder: Default::default(), logging: Default::default(), debug: Default::default(), } @@ -360,6 +363,20 @@ impl Default for NetworkRequester { } } +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(default)] +pub struct IpForwarder { + /// Specifies whether ip forwarder service is enabled in this process. + pub enabled: bool, +} + +#[allow(clippy::derivable_impls)] +impl Default for IpForwarder { + fn default() -> Self { + Self { enabled: false } + } +} + #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(default)] pub struct Debug { diff --git a/gateway/src/config/old_config_v1_1_29.rs b/gateway/src/config/old_config_v1_1_29.rs index e38ff2a57c..467b82709f 100644 --- a/gateway/src/config/old_config_v1_1_29.rs +++ b/gateway/src/config/old_config_v1_1_29.rs @@ -150,10 +150,14 @@ impl From for Config { }, clients_storage: value.storage_paths.clients_storage, network_requester_config: value.storage_paths.network_requester_config, + // WIP: make proper conversion + ip_forwarder_config: Default::default(), }, network_requester: NetworkRequester { enabled: value.network_requester.enabled, }, + // WIP: make proper conversion + ip_forwarder: Default::default(), logging: LoggingSettings {}, debug: Debug { packet_forwarding_initial_backoff: value.debug.packet_forwarding_initial_backoff, diff --git a/gateway/src/config/persistence/paths.rs b/gateway/src/config/persistence/paths.rs index 8d3be49335..4430e65921 100644 --- a/gateway/src/config/persistence/paths.rs +++ b/gateway/src/config/persistence/paths.rs @@ -50,6 +50,10 @@ pub struct GatewayPaths { // pub node_description: PathBuf, // pub cosmos_bip39_mnemonic: PathBuf, + + /// Path to the configuration of the embedded ip forwarder. + #[serde(deserialize_with = "de_maybe_path")] + pub ip_forwarder_config: Option, } impl GatewayPaths { @@ -59,6 +63,7 @@ impl GatewayPaths { clients_storage: default_data_directory(id).join(DEFAULT_CLIENTS_STORAGE_FILENAME), // node_description: default_config_filepath(id).join(DEFAULT_DESCRIPTION_FILENAME), network_requester_config: None, + ip_forwarder_config: None, } } diff --git a/gateway/src/error.rs b/gateway/src/error.rs index 438b684981..681131d8b9 100644 --- a/gateway/src/error.rs +++ b/gateway/src/error.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::node::storage::error::StorageError; +use nym_ip_forwarder::error::IpForwarderError; use nym_network_requester::error::{ClientCoreError, NetworkRequesterError}; use nym_validator_client::nyxd::error::NyxdError; use nym_validator_client::nyxd::AccountId; @@ -48,6 +49,17 @@ pub(crate) enum GatewayError { source: io::Error, }, + #[error( + "failed to load config file for ip forwarder (gateway-id: '{id}') using path '{}'. detailed message: {source}", + path.display() + )] + IpForwarderConfigLoadFailure { + id: String, + path: PathBuf, + #[source] + source: io::Error, + }, + #[error( "failed to save config file for id {id} using path '{}'. detailed message: {source}", path.display() )] @@ -86,15 +98,27 @@ pub(crate) enum GatewayError { #[error("Path to network requester configuration file hasn't been specified. Perhaps try to run `setup-network-requester`?")] UnspecifiedNetworkRequesterConfig, + #[error("Path to ip forwarder configuration file hasn't been specified. Perhaps try to run `setup-ip-forwarder`?")] + UnspecifiedIpForwarderConfig, + #[error("there was an issue with the local network requester: {source}")] NetworkRequesterFailure { #[from] source: NetworkRequesterError, }, + #[error("there was an issue with the local ip forwarder: {source}")] + IpForwarederFailure { + #[from] + source: IpForwarderError, + }, + #[error("failed to startup local network requester")] NetworkRequesterStartupFailure, + #[error("failed to startup local ip forwarder")] + IpForwarderStartupFailure, + #[error("there are no nym API endpoints available")] NoNymApisAvailable, diff --git a/gateway/src/node/client_handling/embedded_network_requester/mod.rs b/gateway/src/node/client_handling/embedded_network_requester/mod.rs index e088535cd9..0256592ea6 100644 --- a/gateway/src/node/client_handling/embedded_network_requester/mod.rs +++ b/gateway/src/node/client_handling/embedded_network_requester/mod.rs @@ -28,6 +28,17 @@ impl LocalNetworkRequesterHandle { } } + // TODO: generalize this whole thing to be general. And change the name(s). + pub(crate) fn new_ip( + start_data: nym_ip_forwarder::OnStartData, + mix_message_sender: MixMessageSender, + ) -> Self { + Self { + address: start_data.address, + mix_message_sender, + } + } + pub(crate) fn client_destination(&self) -> DestinationAddressBytes { self.address.identity().derive_destination_address() } diff --git a/gateway/src/node/helpers.rs b/gateway/src/node/helpers.rs index 9535519fce..54953e133e 100644 --- a/gateway/src/node/helpers.rs +++ b/gateway/src/node/helpers.rs @@ -96,6 +96,20 @@ pub(crate) fn load_network_requester_config>( }) } +pub(crate) fn load_ip_forwarder_config>( + id: &str, + path: P, +) -> Result { + let path = path.as_ref(); + nym_ip_forwarder::Config::read_from_toml_file(path).map_err(|err| { + GatewayError::IpForwarderConfigLoadFailure { + id: id.to_string(), + path: path.to_path_buf(), + source: err, + } + }) +} + pub(crate) async fn initialise_main_storage( config: &Config, ) -> Result { diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index a51180ba35..6dc8bf3076 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -1,8 +1,12 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use self::helpers::load_ip_forwarder_config; use self::storage::PersistentStorage; -use crate::commands::helpers::{override_network_requester_config, OverrideNetworkRequesterConfig}; +use crate::commands::helpers::{ + override_ip_forwarder_config, override_network_requester_config, OverrideIpForwarderConfig, + OverrideNetworkRequesterConfig, +}; use crate::config::Config; use crate::error::GatewayError; use crate::http::HttpApiBuilder; @@ -54,7 +58,8 @@ struct StartedNetworkRequester { pub(crate) async fn create_gateway( config: Config, nr_config_override: Option, - custom_nr_mixnet: Option, + ip_config_override: Option, + custom_mixnet: Option, ) -> Result { // don't attempt to read config if NR is disabled let network_requester_config = if config.network_requester.enabled { @@ -69,14 +74,32 @@ pub(crate) async fn create_gateway( None }; + // don't attempt to read config if NR is disabled + let ip_forwarder_config = if config.ip_forwarder.enabled { + if let Some(path) = &config.storage_paths.ip_forwarder_config { + let cfg = load_ip_forwarder_config(&config.gateway.id, path)?; + Some(override_ip_forwarder_config(cfg, ip_config_override)) + } else { + // if NR is enabled, the config path must be specified + return Err(GatewayError::UnspecifiedIpForwarderConfig); + } + } else { + None + }; + let storage = initialise_main_storage(&config).await?; let nr_opts = network_requester_config.map(|config| LocalNetworkRequesterOpts { - config, - custom_mixnet_path: custom_nr_mixnet, + config: config.clone(), + custom_mixnet_path: custom_mixnet.clone(), }); - Gateway::new(config, nr_opts, storage) + let ip_opts = ip_forwarder_config.map(|config| LocalIpForwarderOpts { + config, + custom_mixnet_path: custom_mixnet, + }); + + Gateway::new(config, nr_opts, ip_opts, storage) } #[derive(Debug, Clone)] @@ -86,11 +109,20 @@ pub struct LocalNetworkRequesterOpts { custom_mixnet_path: Option, } +#[derive(Debug, Clone)] +pub struct LocalIpForwarderOpts { + config: nym_ip_forwarder::Config, + + custom_mixnet_path: Option, +} + pub(crate) struct Gateway { config: Config, network_requester_opts: Option, + ip_forwarder_opts: Option, + /// ed25519 keypair used to assert one's identity. identity_keypair: Arc, @@ -106,6 +138,7 @@ impl Gateway { pub fn new( config: Config, network_requester_opts: Option, + ip_forwarder_opts: Option, storage: St, ) -> Result { Ok(Gateway { @@ -114,6 +147,7 @@ impl Gateway { sphinx_keypair: Arc::new(helpers::load_sphinx_keys(&config)?), config, network_requester_opts, + ip_forwarder_opts, client_registry: Arc::new(DashMap::new()), }) } @@ -219,6 +253,73 @@ impl Gateway { packet_sender } + async fn start_ip_service_provider( + &self, + forwarding_channel: MixForwardingSender, + shutdown: TaskClient, + ) -> Result { + info!("Starting IP service provider..."); + + // if network requester is enabled, configuration file must be provided! + let Some(ip_opts) = &self.ip_forwarder_opts else { + return Err(GatewayError::UnspecifiedIpForwarderConfig); + }; + + // this gateway, whenever it has anything to send to its local NR will use fake_client_tx + let (nr_mix_sender, nr_mix_receiver) = mpsc::unbounded(); + let router_shutdown = shutdown.fork("message_router"); + + let (router_tx, mut router_rx) = oneshot::channel(); + + let transceiver = LocalGateway::new( + *self.identity_keypair.public_key(), + forwarding_channel, + router_tx, + ); + + // TODO: well, wire it up internally to gateway traffic, shutdowns, etc. + let (on_start_tx, on_start_rx) = oneshot::channel(); + // let mut nr_builder = nym_ip_forwarder::IpForwarderBuilder::new(nr_opts.config.clone()) + let mut ip_builder = nym_ip_forwarder::IpForwarderBuilder::new(ip_opts.config.clone()) + .with_shutdown(shutdown) + .with_custom_gateway_transceiver(Box::new(transceiver)) + .with_wait_for_gateway(true) + .with_on_start(on_start_tx); + + if let Some(custom_mixnet) = &ip_opts.custom_mixnet_path { + ip_builder = ip_builder.with_stored_topology(custom_mixnet)? + } + + tokio::spawn(async move { + if let Err(err) = ip_builder.run_service_provider().await { + // no need to panic as we have passed a task client to the ip forwarder so we're + // most likely already in the process of shutting down + error!("ip forwarder has failed: {err}") + } + }); + + let start_data = on_start_rx + .await + .map_err(|_| GatewayError::IpForwarderStartupFailure)?; + + // this should be instantaneous since the data is sent on this channel before the on start is called; + // the failure should be impossible + let Ok(Some(packet_router)) = router_rx.try_recv() else { + return Err(GatewayError::IpForwarderStartupFailure); + }; + + MessageRouter::new(nr_mix_receiver, packet_router).start_with_shutdown(router_shutdown); + info!( + "the local ip forwarder is running on {}", + start_data.address + ); + + Ok(LocalNetworkRequesterHandle::new_ip( + start_data, + nr_mix_sender, + )) + } + // TODO: rethink the logic in this function... async fn start_network_requester( &self, @@ -372,7 +473,9 @@ impl Gateway { }); } - let nr_request_filter = if self.config.network_requester.enabled { + // WIP(JON) + // let nr_request_filter = if self.config.network_requester.enabled { + let nr_request_filter = if false { let embedded_nr = self .start_network_requester( mix_forwarding_channel.clone(), @@ -397,6 +500,16 @@ impl Gateway { .with_maybe_network_request_filter(nr_request_filter) .start(shutdown.subscribe().named("http-api"))?; + if true { + let embedded_ip_sp = self + .start_ip_service_provider( + mix_forwarding_channel.clone(), + shutdown.subscribe().named("ip_service_provider"), + ) + .await?; + active_clients_store.insert_embedded(embedded_ip_sp); + } + self.start_client_websocket_listener( mix_forwarding_channel, active_clients_store, From cfef1f8325d52dd8f03cc2303e18b48f735cec1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 26 Oct 2023 23:14:05 +0200 Subject: [PATCH 116/236] config handling --- Cargo.lock | 2 + common/types/src/gateway.rs | 25 +++ gateway/src/commands/helpers.rs | 77 ++++++++- gateway/src/commands/init.rs | 21 ++- gateway/src/commands/mod.rs | 6 + gateway/src/commands/run.rs | 39 ++--- gateway/src/commands/setup_ip_forwarder.rs | 67 ++++++++ gateway/src/config/mod.rs | 13 ++ gateway/src/config/persistence/paths.rs | 24 +++ gateway/src/config/template.rs | 7 + gateway/src/node/mod.rs | 155 +++++++++--------- service-providers/ip-forwarder/Cargo.toml | 2 + .../ip-forwarder/src/config/mod.rs | 85 +++++++++- .../ip-forwarder/src/config/template.rs | 105 ++++++++++++ 14 files changed, 525 insertions(+), 103 deletions(-) create mode 100644 gateway/src/commands/setup_ip_forwarder.rs create mode 100644 service-providers/ip-forwarder/src/config/template.rs diff --git a/Cargo.lock b/Cargo.lock index 369423472d..938ab2606d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6650,9 +6650,11 @@ version = "0.1.0" dependencies = [ "futures", "log", + "nym-bin-common", "nym-client-core", "nym-config", "nym-sdk", + "nym-service-providers-common", "nym-sphinx", "nym-task", "serde", diff --git a/common/types/src/gateway.rs b/common/types/src/gateway.rs index c57dee8001..9c0dc8541a 100644 --- a/common/types/src/gateway.rs +++ b/common/types/src/gateway.rs @@ -146,3 +146,28 @@ impl fmt::Display for GatewayNetworkRequesterDetails { writeln!(f, "\tunknown list path: {}", self.unknown_list_path) } } + +#[derive(Serialize, Deserialize)] +pub struct GatewayIpForwarderDetails { + pub enabled: bool, + + pub identity_key: String, + pub encryption_key: String, + + // just a convenience wrapper around all the keys + pub address: String, + + pub config_path: String, +} + +impl fmt::Display for GatewayIpForwarderDetails { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "IP forwarder:")?; + writeln!(f, "\tenabled: {}", self.enabled)?; + writeln!(f, "\tconfig path: {}", self.config_path)?; + + writeln!(f, "\tidentity key: {}", self.identity_key)?; + writeln!(f, "\tencryption key: {}", self.encryption_key)?; + writeln!(f, "\taddress: {}", self.address) + } +} diff --git a/gateway/src/commands/helpers.rs b/gateway/src/commands/helpers.rs index 94947890c4..56c9d74292 100644 --- a/gateway/src/commands/helpers.rs +++ b/gateway/src/commands/helpers.rs @@ -3,7 +3,9 @@ use crate::commands::upgrade_helpers; use crate::config::default_config_filepath; -use crate::config::persistence::paths::default_network_requester_data_dir; +use crate::config::persistence::paths::{ + default_ip_forwarder_data_dir, default_network_requester_data_dir, +}; use crate::config::Config; use crate::error::GatewayError; use log::{error, info}; @@ -17,7 +19,7 @@ use nym_network_requester::config::BaseClientConfig; use nym_network_requester::{ setup_gateway, GatewaySelectionSpecification, GatewaySetup, OnDiskGatewayDetails, OnDiskKeys, }; -use nym_types::gateway::GatewayNetworkRequesterDetails; +use nym_types::gateway::{GatewayIpForwarderDetails, GatewayNetworkRequesterDetails}; use nym_validator_client::nyxd::AccountId; use std::net::IpAddr; use std::path::PathBuf; @@ -39,6 +41,7 @@ pub(crate) struct OverrideConfig { pub(crate) nyxd_urls: Option>, pub(crate) only_coconut_credentials: Option, pub(crate) with_network_requester: Option, + pub(crate) with_ip_forwarder: Option, } impl OverrideConfig { @@ -76,12 +79,16 @@ impl OverrideConfig { .with_optional( Config::with_enabled_network_requester, self.with_network_requester, - ); + ) + .with_optional(Config::with_enabled_ip_forwarder, self.with_ip_forwarder); if config.network_requester.enabled && config.storage_paths.network_requester_config.is_none() { Ok(config.with_default_network_requester_config_path()) + } else if config.ip_forwarder.enabled && config.storage_paths.ip_forwarder_config.is_none() + { + Ok(config.with_default_ip_forwarder_config_path()) } else { Ok(config) } @@ -166,6 +173,10 @@ fn make_nr_id(gateway_id: &str) -> String { format!("{gateway_id}-network-requester") } +fn make_ip_id(gateway_id: &str) -> String { + format!("{gateway_id}-ip-forwarder") +} + // NOTE: make sure this is in sync with service-providers/network-requester/src/cli/mod.rs::override_config pub(crate) fn override_network_requester_config( mut cfg: nym_network_requester::Config, @@ -303,3 +314,63 @@ pub(crate) async fn initialise_local_network_requester( .to_string(), }) } + +pub(crate) async fn initialise_local_ip_forwarder( + gateway_config: &Config, + opts: OverrideIpForwarderConfig, + identity: identity::PublicKey, +) -> Result { + info!("initialising ip forwarder..."); + let Some(ip_cfg_path) = gateway_config.storage_paths.ip_forwarder_config() else { + return Err(GatewayError::UnspecifiedIpForwarderConfig); + }; + + let id = &gateway_config.gateway.id; + let ip_id = make_ip_id(id); + let ip_data_dir = default_ip_forwarder_data_dir(id); + let mut ip_cfg = nym_ip_forwarder::Config::new(&ip_id).with_data_directory(ip_data_dir); + ip_cfg = override_ip_forwarder_config(ip_cfg, Some(opts)); + + let key_store = OnDiskKeys::new(ip_cfg.storage_paths.common_paths.keys.clone()); + let details_store = + OnDiskGatewayDetails::new(&ip_cfg.storage_paths.common_paths.gateway_details); + + // gateway setup here is way simpler as we're 'connecting' to ourselves + let init_res = setup_gateway( + GatewaySetup::New { + specification: GatewaySelectionSpecification::Custom { + gateway_identity: identity.to_base58_string(), + additional_data: Default::default(), + }, + available_gateways: vec![], + overwrite_data: false, + }, + &key_store, + &details_store, + ) + .await?; + + let address = init_res.client_address()?; + + if let Err(err) = save_formatted_config_to_file(&ip_cfg, ip_cfg_path) { + log::error!("Failed to save the ip forwarder config file: {err}"); + return Err(GatewayError::ConfigSaveFailure { + id: ip_id, + path: ip_cfg_path.to_path_buf(), + source: err, + }); + } else { + eprintln!( + "Saved ip forwarder configuration file to {}", + ip_cfg_path.display() + ) + } + + Ok(GatewayIpForwarderDetails { + enabled: gateway_config.ip_forwarder.enabled, + identity_key: address.identity().to_string(), + encryption_key: address.encryption_key().to_string(), + address: address.to_string(), + config_path: ip_cfg_path.display().to_string(), + }) +} diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index e5e14068a8..8823524791 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -2,7 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use crate::commands::helpers::{ - initialise_local_network_requester, OverrideNetworkRequesterConfig, + initialise_local_ip_forwarder, initialise_local_network_requester, + OverrideNetworkRequesterConfig, }; use crate::config::{default_config_directory, default_config_filepath, default_data_directory}; use crate::node::helpers::node_details; @@ -14,6 +15,8 @@ use std::net::IpAddr; use std::path::PathBuf; use std::{fs, io}; +use super::helpers::OverrideIpForwarderConfig; + #[derive(Args, Clone)] pub struct Init { /// Id of the gateway we want to create config for @@ -79,9 +82,13 @@ pub struct Init { statistics_service_url: Option, /// Allows this gateway to run an embedded network requester for minimal network overhead - #[clap(long)] + #[clap(long, conflicts_with = "with_ip_forwarder")] with_network_requester: bool, + /// Allows this gateway to run an embedded network requester for minimal network overhead + #[clap(long, conflicts_with = "with_network_requester")] + with_ip_forwarder: bool, + // ##### NETWORK REQUESTER FLAGS ##### /// Specifies whether this network requester should run in 'open-proxy' mode #[clap(long, requires = "with_network_requester")] @@ -154,6 +161,7 @@ impl From for OverrideConfig { nyxd_urls: init_config.nyxd_urls, only_coconut_credentials: init_config.only_coconut_credentials, with_network_requester: Some(init_config.with_network_requester), + with_ip_forwarder: Some(init_config.with_ip_forwarder), } } } @@ -172,6 +180,12 @@ impl<'a> From<&'a Init> for OverrideNetworkRequesterConfig { } } +impl From<&Init> for OverrideIpForwarderConfig { + fn from(_value: &Init) -> Self { + OverrideIpForwarderConfig {} + } +} + fn init_paths(id: &str) -> io::Result<()> { fs::create_dir_all(default_data_directory(id))?; fs::create_dir_all(default_config_directory(id)) @@ -196,6 +210,7 @@ pub async fn execute(args: Init) -> anyhow::Result<()> { // Initialising the config structure is just overriding a default constructed one let fresh_config = Config::new(&args.id); let nr_opts = (&args).into(); + let ip_opts = (&args).into(); let mut config = OverrideConfig::from(args).do_override(fresh_config)?; // if gateway was already initialised, don't generate new keys, et al. @@ -228,6 +243,8 @@ pub async fn execute(args: Init) -> anyhow::Result<()> { if config.network_requester.enabled { initialise_local_network_requester(&config, nr_opts, *identity_keys.public_key()) .await?; + } else if config.ip_forwarder.enabled { + initialise_local_ip_forwarder(&config, ip_opts, *identity_keys.public_key()).await?; } eprintln!("Saved identity and mixnet sphinx keypairs"); diff --git a/gateway/src/commands/mod.rs b/gateway/src/commands/mod.rs index 0df249edb1..f51fd011d2 100644 --- a/gateway/src/commands/mod.rs +++ b/gateway/src/commands/mod.rs @@ -12,6 +12,7 @@ pub(crate) mod helpers; pub(crate) mod init; pub(crate) mod node_details; pub(crate) mod run; +pub(crate) mod setup_ip_forwarder; pub(crate) mod setup_network_requester; pub(crate) mod sign; mod upgrade_helpers; @@ -31,6 +32,10 @@ pub(crate) enum Commands { // essentially an option to include NR without having to setup fresh gateway SetupNetworkRequester(setup_network_requester::CmdArgs), + /// Add ip forwarder support to this gateway + // essentially an option to include ip forwarder without having to setup fresh gateway + SetupIpForwarder(setup_ip_forwarder::CmdArgs), + /// Sign text to prove ownership of this mixnode Sign(sign::Sign), @@ -52,6 +57,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box node_details::execute(m).await?, Commands::Run(m) => run::execute(m).await?, Commands::SetupNetworkRequester(m) => setup_network_requester::execute(m).await?, + Commands::SetupIpForwarder(m) => setup_ip_forwarder::execute(m).await?, Commands::Sign(m) => sign::execute(m)?, Commands::BuildInfo(m) => build_info::execute(m), Commands::Completions(s) => s.generate(&mut crate::Cli::command(), bin_name), diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index 4f390db406..ad6a4495c6 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -20,36 +20,36 @@ use super::helpers::OverrideIpForwarderConfig; #[derive(Args, Clone)] pub struct Run { /// Id of the gateway we want to run - #[clap(long)] + #[arg(long)] id: String, /// The custom listening address on which the gateway will be running for receiving sphinx packets - #[clap(long, alias = "host")] + #[arg(long, alias = "host")] listening_address: Option, /// Comma separated list of public ip addresses that will announced to the nym-api and subsequently to the clients. /// In nearly all circumstances, it's going to be identical to the address you're going to use for bonding. - #[clap(long, value_delimiter = ',')] + #[arg(long, value_delimiter = ',')] public_ips: Option>, /// Optional hostname associated with this gateway that will announced to the nym-api and subsequently to the clients - #[clap(long)] + #[arg(long)] hostname: Option, /// The port on which the gateway will be listening for sphinx packets - #[clap(long)] + #[arg(long)] mix_port: Option, /// The port on which the gateway will be listening for clients gateway-requests - #[clap(long)] + #[arg(long)] clients_port: Option, /// Path to sqlite database containing all gateway persistent data - #[clap(long)] + #[arg(long)] datastore: Option, /// Comma separated list of endpoints of nym APIs - #[clap( + #[arg( long, alias = "validator_apis", value_delimiter = ',', @@ -59,7 +59,7 @@ pub struct Run { nym_apis: Option>, /// Comma separated list of endpoints of the validator - #[clap( + #[arg( long, alias = "validators", alias = "nyxd_validators", @@ -70,28 +70,28 @@ pub struct Run { nyxd_urls: Option>, /// Cosmos wallet mnemonic - #[clap(long)] + #[arg(long)] mnemonic: Option, /// Set this gateway to work only with coconut credentials; that would disallow clients to /// bypass bandwidth credential requirement - #[clap(long, hide = true)] + #[arg(long, hide = true)] only_coconut_credentials: Option, /// Enable/disable gateway anonymized statistics that get sent to a statistics aggregator server - #[clap(long)] + #[arg(long)] enabled_statistics: Option, /// URL where a statistics aggregator is running. The default value is a Nym aggregator server - #[clap(long)] + #[arg(long)] statistics_service_url: Option, /// Allows this gateway to run an embedded network requester for minimal network overhead - #[clap(long)] + #[arg(long, conflicts_with = "with_ip_forwarder")] with_network_requester: Option, /// Allows this gateway to run an embedded network requester for minimal network overhead - #[clap(long)] + #[arg(long, conflicts_with = "with_network_requester")] with_ip_forwarder: Option, // ##### NETWORK REQUESTER FLAGS ##### @@ -129,20 +129,20 @@ pub struct Run { /// Path to .json file containing custom network specification. /// Only usable when local network requester is enabled. - #[clap(long, group = "network", hide = true)] + #[arg(long, group = "network", hide = true)] custom_mixnet: Option, /// Specifies whether this network requester will run using the default ExitPolicy /// as opposed to the allow list. /// Note: this setting will become the default in the future releases. - #[clap(long)] + #[arg(long)] with_exit_policy: Option, - #[clap(short, long, default_value_t = OutputFormat::default())] + #[arg(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, /// Flag specifying this node will be running in a local setting. - #[clap(long)] + #[arg(long)] local: bool, } @@ -163,6 +163,7 @@ impl From for OverrideConfig { nyxd_urls: run_config.nyxd_urls, only_coconut_credentials: run_config.only_coconut_credentials, with_network_requester: run_config.with_network_requester, + with_ip_forwarder: run_config.with_ip_forwarder, } } } diff --git a/gateway/src/commands/setup_ip_forwarder.rs b/gateway/src/commands/setup_ip_forwarder.rs new file mode 100644 index 0000000000..6b8678f3ab --- /dev/null +++ b/gateway/src/commands/setup_ip_forwarder.rs @@ -0,0 +1,67 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::commands::helpers::{ + initialise_local_ip_forwarder, try_load_current_config, OverrideIpForwarderConfig, +}; +use crate::node::helpers::load_public_key; +use clap::Args; +use nym_bin_common::output_format::OutputFormat; +use std::path::PathBuf; + +#[derive(Args, Clone)] +pub struct CmdArgs { + /// The id of the gateway you want to initialise local ip forwarder for. + #[arg(long)] + id: String, + + /// Path to custom location for ip forward's config. + #[arg(long)] + custom_config_path: Option, + + /// Specify whether the ip forwarder should be enabled. + // (you might want to create all the configs, generate keys, etc. but not actually run the NR just yet) + #[arg(long)] + enabled: Option, + + #[arg(short, long, default_value_t = OutputFormat::default())] + output: OutputFormat, +} + +impl From<&CmdArgs> for OverrideIpForwarderConfig { + fn from(_value: &CmdArgs) -> Self { + OverrideIpForwarderConfig {} + } +} + +pub async fn execute(args: CmdArgs) -> anyhow::Result<()> { + let mut config = try_load_current_config(&args.id)?; + let opts = (&args).into(); + + // if somebody provided config file of a custom NR, that's fine + // but in 90% cases, I'd assume, it won't work due to invalid gateway configuration + // but it might be nice to be able to move files around. + if let Some(custom_config_path) = args.custom_config_path { + // if you specified anything as the argument, overwrite whatever was already in the config file + config.storage_paths.ip_forwarder_config = Some(custom_config_path); + } + + if let Some(override_enabled) = args.enabled { + config.ip_forwarder.enabled = override_enabled; + } + + if config.storage_paths.ip_forwarder_config.is_none() { + config = config.with_default_ip_forwarder_config_path() + } + + let identity_public_key = load_public_key( + &config.storage_paths.keys.public_identity_key_file, + "gateway identity", + )?; + let details = initialise_local_ip_forwarder(&config, opts, identity_public_key).await?; + config.try_save()?; + + args.output.to_stdout(&details); + + Ok(()) +} diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index caef4cd68d..88c438e29c 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -100,6 +100,7 @@ pub struct Config { pub network_requester: NetworkRequester, + #[serde(default)] pub ip_forwarder: IpForwarder, #[serde(default)] @@ -198,6 +199,18 @@ impl Config { self } + pub fn with_enabled_ip_forwarder(mut self, enabled_ip_forwarder: bool) -> Self { + self.ip_forwarder.enabled = enabled_ip_forwarder; + self + } + + pub fn with_default_ip_forwarder_config_path(mut self) -> Self { + self.storage_paths = self + .storage_paths + .with_default_ip_forwarder_config(&self.gateway.id); + self + } + pub fn with_only_coconut_credentials(mut self, only_coconut_credentials: bool) -> Self { self.gateway.only_coconut_credentials = only_coconut_credentials; self diff --git a/gateway/src/config/persistence/paths.rs b/gateway/src/config/persistence/paths.rs index 4430e65921..0e0ec8d836 100644 --- a/gateway/src/config/persistence/paths.rs +++ b/gateway/src/config/persistence/paths.rs @@ -15,12 +15,19 @@ pub const DEFAULT_CLIENTS_STORAGE_FILENAME: &str = "db.sqlite"; pub const DEFAULT_NETWORK_REQUESTER_CONFIG_FILENAME: &str = "network_requester_config.toml"; pub const DEFAULT_NETWORK_REQUESTER_DATA_DIR: &str = "network-requester-data"; +pub const DEFAULT_IP_FORWARDER_CONFIG_FILENAME: &str = "ip_forwarder_config.toml"; +pub const DEFAULT_IP_FORWARDER_DATA_DIR: &str = "ip-forwarder-data"; + // pub const DEFAULT_DESCRIPTION_FILENAME: &str = "description.toml"; pub fn default_network_requester_data_dir>(id: P) -> PathBuf { default_data_directory(id).join(DEFAULT_NETWORK_REQUESTER_DATA_DIR) } +pub fn default_ip_forwarder_data_dir>(id: P) -> PathBuf { + default_data_directory(id).join(DEFAULT_IP_FORWARDER_DATA_DIR) +} + /// makes sure that an empty path is converted into a `None` as opposed to `Some("")` fn de_maybe_path<'de, D>(deserializer: D) -> Result, D::Error> where @@ -80,10 +87,27 @@ impl GatewayPaths { ) } + #[must_use] + pub fn with_ip_forwarder_config>(mut self, path: P) -> Self { + self.ip_forwarder_config = Some(path.as_ref().into()); + self + } + + #[must_use] + pub fn with_default_ip_forwarder_config>(self, id: P) -> Self { + self.with_ip_forwarder_config( + default_config_directory(id).join(DEFAULT_IP_FORWARDER_CONFIG_FILENAME), + ) + } + pub fn network_requester_config(&self) -> &Option { &self.network_requester_config } + pub fn ip_forwarder_config(&self) -> &Option { + &self.ip_forwarder_config + } + pub fn private_identity_key(&self) -> &Path { self.keys.private_identity_key() } diff --git a/gateway/src/config/template.rs b/gateway/src/config/template.rs index 0f77d499fc..24867e10c4 100644 --- a/gateway/src/config/template.rs +++ b/gateway/src/config/template.rs @@ -82,6 +82,10 @@ landing_page_assets_path = '{{ http.landing_page_assets_path }}' # Specifies whether network requester service is enabled in this process. enabled = {{ network_requester.enabled }} +[ip_forwarder] +# Specifies whether ip forwarder service is enabled in this process. +enabled = {{ ip_forwarder.enabled }} + [storage_paths] # Path to file containing private identity key. @@ -103,6 +107,9 @@ clients_storage = '{{ storage_paths.clients_storage }}' # Path to the configuration of the embedded network requester. network_requester_config = '{{ storage_paths.network_requester_config }}' +# Path to the configuration of the embedded ip forwarder. +ip_forwarder_config = '{{ storage_paths.ip_forwarder_config }}' + ##### logging configuration options ##### [logging] diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 6dc8bf3076..2a8bf0b088 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -253,73 +253,6 @@ impl Gateway { packet_sender } - async fn start_ip_service_provider( - &self, - forwarding_channel: MixForwardingSender, - shutdown: TaskClient, - ) -> Result { - info!("Starting IP service provider..."); - - // if network requester is enabled, configuration file must be provided! - let Some(ip_opts) = &self.ip_forwarder_opts else { - return Err(GatewayError::UnspecifiedIpForwarderConfig); - }; - - // this gateway, whenever it has anything to send to its local NR will use fake_client_tx - let (nr_mix_sender, nr_mix_receiver) = mpsc::unbounded(); - let router_shutdown = shutdown.fork("message_router"); - - let (router_tx, mut router_rx) = oneshot::channel(); - - let transceiver = LocalGateway::new( - *self.identity_keypair.public_key(), - forwarding_channel, - router_tx, - ); - - // TODO: well, wire it up internally to gateway traffic, shutdowns, etc. - let (on_start_tx, on_start_rx) = oneshot::channel(); - // let mut nr_builder = nym_ip_forwarder::IpForwarderBuilder::new(nr_opts.config.clone()) - let mut ip_builder = nym_ip_forwarder::IpForwarderBuilder::new(ip_opts.config.clone()) - .with_shutdown(shutdown) - .with_custom_gateway_transceiver(Box::new(transceiver)) - .with_wait_for_gateway(true) - .with_on_start(on_start_tx); - - if let Some(custom_mixnet) = &ip_opts.custom_mixnet_path { - ip_builder = ip_builder.with_stored_topology(custom_mixnet)? - } - - tokio::spawn(async move { - if let Err(err) = ip_builder.run_service_provider().await { - // no need to panic as we have passed a task client to the ip forwarder so we're - // most likely already in the process of shutting down - error!("ip forwarder has failed: {err}") - } - }); - - let start_data = on_start_rx - .await - .map_err(|_| GatewayError::IpForwarderStartupFailure)?; - - // this should be instantaneous since the data is sent on this channel before the on start is called; - // the failure should be impossible - let Ok(Some(packet_router)) = router_rx.try_recv() else { - return Err(GatewayError::IpForwarderStartupFailure); - }; - - MessageRouter::new(nr_mix_receiver, packet_router).start_with_shutdown(router_shutdown); - info!( - "the local ip forwarder is running on {}", - start_data.address - ); - - Ok(LocalNetworkRequesterHandle::new_ip( - start_data, - nr_mix_sender, - )) - } - // TODO: rethink the logic in this function... async fn start_network_requester( &self, @@ -384,6 +317,74 @@ impl Gateway { }) } + async fn start_ip_service_provider( + &self, + forwarding_channel: MixForwardingSender, + shutdown: TaskClient, + ) -> Result { + info!("Starting IP service provider..."); + + // if network requester is enabled, configuration file must be provided! + let Some(ip_opts) = &self.ip_forwarder_opts else { + log::error!("IP service provider is enabled but no configuration file was provided!"); + return Err(GatewayError::UnspecifiedIpForwarderConfig); + }; + + // this gateway, whenever it has anything to send to its local NR will use fake_client_tx + let (nr_mix_sender, nr_mix_receiver) = mpsc::unbounded(); + let router_shutdown = shutdown.fork("message_router"); + + let (router_tx, mut router_rx) = oneshot::channel(); + + let transceiver = LocalGateway::new( + *self.identity_keypair.public_key(), + forwarding_channel, + router_tx, + ); + + // TODO: well, wire it up internally to gateway traffic, shutdowns, etc. + let (on_start_tx, on_start_rx) = oneshot::channel(); + // let mut nr_builder = nym_ip_forwarder::IpForwarderBuilder::new(nr_opts.config.clone()) + let mut ip_builder = nym_ip_forwarder::IpForwarderBuilder::new(ip_opts.config.clone()) + .with_shutdown(shutdown) + .with_custom_gateway_transceiver(Box::new(transceiver)) + .with_wait_for_gateway(true) + .with_on_start(on_start_tx); + + if let Some(custom_mixnet) = &ip_opts.custom_mixnet_path { + ip_builder = ip_builder.with_stored_topology(custom_mixnet)? + } + + tokio::spawn(async move { + if let Err(err) = ip_builder.run_service_provider().await { + // no need to panic as we have passed a task client to the ip forwarder so we're + // most likely already in the process of shutting down + error!("ip forwarder has failed: {err}") + } + }); + + let start_data = on_start_rx + .await + .map_err(|_| GatewayError::IpForwarderStartupFailure)?; + + // this should be instantaneous since the data is sent on this channel before the on start is called; + // the failure should be impossible + let Ok(Some(packet_router)) = router_rx.try_recv() else { + return Err(GatewayError::IpForwarderStartupFailure); + }; + + MessageRouter::new(nr_mix_receiver, packet_router).start_with_shutdown(router_shutdown); + info!( + "the local ip forwarder is running on {}", + start_data.address + ); + + Ok(LocalNetworkRequesterHandle::new_ip( + start_data, + nr_mix_sender, + )) + } + async fn wait_for_interrupt(shutdown: TaskManager) -> Result<(), Box> { let res = shutdown.catch_interrupt().await; log::info!("Stopping nym gateway"); @@ -490,16 +491,6 @@ impl Gateway { None }; - HttpApiBuilder::new( - &self.config, - self.identity_keypair.as_ref(), - self.sphinx_keypair.clone(), - ) - .with_wireguard_client_registry(self.client_registry.clone()) - .with_maybe_network_requester(self.network_requester_opts.as_ref().map(|o| &o.config)) - .with_maybe_network_request_filter(nr_request_filter) - .start(shutdown.subscribe().named("http-api"))?; - if true { let embedded_ip_sp = self .start_ip_service_provider( @@ -510,6 +501,16 @@ impl Gateway { active_clients_store.insert_embedded(embedded_ip_sp); } + HttpApiBuilder::new( + &self.config, + self.identity_keypair.as_ref(), + self.sphinx_keypair.clone(), + ) + .with_wireguard_client_registry(self.client_registry.clone()) + .with_maybe_network_requester(self.network_requester_opts.as_ref().map(|o| &o.config)) + .with_maybe_network_request_filter(nr_request_filter) + .start(shutdown.subscribe().named("http-api"))?; + self.start_client_websocket_listener( mix_forwarding_channel, active_clients_store, diff --git a/service-providers/ip-forwarder/Cargo.toml b/service-providers/ip-forwarder/Cargo.toml index 777de65c28..bb88978f18 100644 --- a/service-providers/ip-forwarder/Cargo.toml +++ b/service-providers/ip-forwarder/Cargo.toml @@ -11,9 +11,11 @@ license.workspace = true [dependencies] futures = { workspace = true } log = { workspace = true } +nym-bin-common = { path = "../../common/bin-common" } nym-client-core = { path = "../../common/client-core" } nym-config = { path = "../../common/config" } nym-sdk = { path = "../../sdk/rust/nym-sdk" } +nym-service-providers-common = { path = "../common" } nym-sphinx = { path = "../../common/nymsphinx" } nym-task = { path = "../../common/task" } serde = { workspace = true, features = ["derive"] } diff --git a/service-providers/ip-forwarder/src/config/mod.rs b/service-providers/ip-forwarder/src/config/mod.rs index 1792793107..19bcaedc49 100644 --- a/service-providers/ip-forwarder/src/config/mod.rs +++ b/service-providers/ip-forwarder/src/config/mod.rs @@ -1,11 +1,53 @@ -use std::{io, path::Path}; - pub use nym_client_core::config::Config as BaseClientConfig; + +use nym_bin_common::logging::LoggingSettings; +use nym_config::{ + must_get_home, save_formatted_config_to_file, NymConfigTemplate, DEFAULT_CONFIG_DIR, + DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, +}; +use nym_service_providers_common::DEFAULT_SERVICE_PROVIDERS_DIR; use serde::{Deserialize, Serialize}; +use std::{ + io, + path::{Path, PathBuf}, +}; use crate::config::persistence::IpForwarderPaths; +use self::template::CONFIG_TEMPLATE; + mod persistence; +mod template; + +const DEFAULT_IP_FORWARDERS_DIR: &str = "ip-forwarder"; + +/// Derive default path to ip forwarder's config directory. +/// It should get resolved to `$HOME/.nym/service-providers/ip-forwareder//config` +pub fn default_config_directory>(id: P) -> PathBuf { + must_get_home() + .join(NYM_DIR) + .join(DEFAULT_SERVICE_PROVIDERS_DIR) + .join(DEFAULT_IP_FORWARDERS_DIR) + .join(id) + .join(DEFAULT_CONFIG_DIR) +} + +/// Derive default path to ip forwarder's config file. +/// It should get resolved to `$HOME/.nym/service-providers/ip-forwarder//config/config.toml` +pub fn default_config_filepath>(id: P) -> PathBuf { + default_config_directory(id).join(DEFAULT_CONFIG_FILENAME) +} + +/// Derive default path to network requester's data directory where files, such as keys, are stored. +/// It should get resolved to `$HOME/.nym/service-providers/network-requester//data` +pub fn default_data_directory>(id: P) -> PathBuf { + must_get_home() + .join(NYM_DIR) + .join(DEFAULT_SERVICE_PROVIDERS_DIR) + .join(DEFAULT_IP_FORWARDERS_DIR) + .join(id) + .join(DEFAULT_DATA_DIR) +} #[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] @@ -14,10 +56,49 @@ pub struct Config { pub base: BaseClientConfig, pub storage_paths: IpForwarderPaths, + + pub logging: LoggingSettings, +} + +impl NymConfigTemplate for Config { + fn template(&self) -> &'static str { + CONFIG_TEMPLATE + } } impl Config { + pub fn new>(id: S) -> Self { + Config { + base: BaseClientConfig::new(id.as_ref(), env!("CARGO_PKG_VERSION")), + storage_paths: IpForwarderPaths::new_base(default_data_directory(id.as_ref())), + logging: Default::default(), + } + } + + pub fn with_data_directory>(mut self, data_directory: P) -> Self { + self.storage_paths = IpForwarderPaths::new_base(data_directory); + self + } + pub fn read_from_toml_file>(path: P) -> io::Result { nym_config::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 default_location(&self) -> PathBuf { + default_config_filepath(&self.base.client.id) + } + + pub fn save_to_default_location(&self) -> io::Result<()> { + let config_save_location: PathBuf = self.default_location(); + save_formatted_config_to_file(self, config_save_location) + } + + pub fn validate(&self) -> bool { + // no other sections have explicit requirements (yet) + self.base.validate() + } } diff --git a/service-providers/ip-forwarder/src/config/template.rs b/service-providers/ip-forwarder/src/config/template.rs new file mode 100644 index 0000000000..2da118a580 --- /dev/null +++ b/service-providers/ip-forwarder/src/config/template.rs @@ -0,0 +1,105 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub(crate) const CONFIG_TEMPLATE: &str = + // While using normal toml marshalling would have been way simpler with less overhead, + // I think it's useful to have comments attached to the saved config file to explain behaviour of + // particular fields. + // Note: any changes to the template must be reflected in the appropriate structs. + r#" +# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +##### main base client config options ##### + +[client] +# Version of the client for which this configuration was created. +version = '{{ client.version }}' + +# Human readable ID of this particular client. +id = '{{ client.id }}' + +# Indicates whether this client is running in a disabled credentials mode, thus attempting +# to claim bandwidth without presenting bandwidth credentials. +disabled_credentials_mode = {{ client.disabled_credentials_mode }} + +# Addresses to nyxd validators via which the client can communicate with the chain. +nyxd_urls = [ + {{#each client.nyxd_urls }} + '{{this}}', + {{/each}} +] + +# Addresses to APIs running on validator from which the client gets the view of the network. +nym_api_urls = [ + {{#each client.nym_api_urls }} + '{{this}}', + {{/each}} +] + +[storage_paths] + +# Path to file containing private identity key. +keys.private_identity_key_file = '{{ storage_paths.keys.private_identity_key_file }}' + +# Path to file containing public identity key. +keys.public_identity_key_file = '{{ storage_paths.keys.public_identity_key_file }}' + +# Path to file containing private encryption key. +keys.private_encryption_key_file = '{{ storage_paths.keys.private_encryption_key_file }}' + +# Path to file containing public encryption key. +keys.public_encryption_key_file = '{{ storage_paths.keys.public_encryption_key_file }}' + +# A gateway specific, optional, base58 stringified shared key used for +# communication with particular gateway. +keys.gateway_shared_key_file = '{{ storage_paths.keys.gateway_shared_key_file }}' + +# Path to file containing key used for encrypting and decrypting the content of an +# acknowledgement so that nobody besides the client knows which packet it refers to. +keys.ack_key_file = '{{ storage_paths.keys.ack_key_file }}' + +# Path to the database containing bandwidth credentials +credentials_database = '{{ storage_paths.credentials_database }}' + +# Path to the file containing information about gateway used by this client, +# i.e. details such as its public key, owner address or the network information. +gateway_details = '{{ storage_paths.gateway_details }}' + +# Path to the persistent store for received reply surbs, unused encryption keys and used sender tags. +reply_surb_database = '{{ storage_paths.reply_surb_database }}' + +# Location of the file containing our allow.list +allowed_list_location = '{{ storage_paths.allowed_list_location }}' + +# Location of the file containing our unknown.list +unknown_list_location = '{{ storage_paths.unknown_list_location }}' + +# Path to file containing description of this network-requester. +ip_forwarder_description = '{{ storage_paths.ip_forwarder_description }}' + + +##### logging configuration options ##### + +[logging] + +# TODO + + +##### debug configuration options ##### +# The following options should not be modified unless you know EXACTLY what you are doing +# as if set incorrectly, they may impact your anonymity. + +[debug] + +[debug.traffic] +average_packet_delay = '{{ debug.traffic.average_packet_delay }}' +message_sending_average_delay = '{{ debug.traffic.message_sending_average_delay }}' + +[debug.acknowledgements] +average_ack_delay = '{{ debug.acknowledgements.average_ack_delay }}' + +[debug.cover_traffic] +loop_cover_traffic_average_delay = '{{ debug.cover_traffic.loop_cover_traffic_average_delay }}' + +"#; From d33967f60c6e97fbce08cab3bf5da3b9320549e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 26 Oct 2023 23:39:56 +0200 Subject: [PATCH 117/236] rustfmt --- gateway/src/config/persistence/paths.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/gateway/src/config/persistence/paths.rs b/gateway/src/config/persistence/paths.rs index 0e0ec8d836..14e35f4613 100644 --- a/gateway/src/config/persistence/paths.rs +++ b/gateway/src/config/persistence/paths.rs @@ -57,7 +57,6 @@ pub struct GatewayPaths { // pub node_description: PathBuf, // pub cosmos_bip39_mnemonic: PathBuf, - /// Path to the configuration of the embedded ip forwarder. #[serde(deserialize_with = "de_maybe_path")] pub ip_forwarder_config: Option, From a17d36fd894599521bd0968b1b28c0c2814ed3a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 27 Oct 2023 10:40:03 +0200 Subject: [PATCH 118/236] Fix test compilation --- gateway/src/commands/init.rs | 2 ++ gateway/src/node/mod.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index 8823524791..296e7c8017 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -293,6 +293,7 @@ mod tests { only_coconut_credentials: None, output: Default::default(), with_network_requester: false, + with_ip_forwarder: false, open_proxy: None, enable_statistics: None, statistics_recipient: None, @@ -320,6 +321,7 @@ mod tests { let _gateway = Gateway::new_from_keys_and_storage( config, None, + None, identity_keys, sphinx_keys, InMemStorage, diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 2a8bf0b088..7bbdd1233c 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -156,6 +156,7 @@ impl Gateway { pub async fn new_from_keys_and_storage( config: Config, network_requester_opts: Option, + ip_forwarder_opts: Option, identity_keypair: identity::KeyPair, sphinx_keypair: encryption::KeyPair, storage: St, @@ -163,6 +164,7 @@ impl Gateway { Gateway { config, network_requester_opts, + ip_forwarder_opts, identity_keypair: Arc::new(identity_keypair), sphinx_keypair: Arc::new(sphinx_keypair), storage, From 65d93b2b1803b2454fd07f17e05e699d7cbfd844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 27 Oct 2023 10:54:53 +0200 Subject: [PATCH 119/236] Remove hack --- gateway/src/commands/init.rs | 2 +- gateway/src/commands/run.rs | 2 +- gateway/src/node/mod.rs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index 296e7c8017..286a24f21a 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -86,7 +86,7 @@ pub struct Init { with_network_requester: bool, /// Allows this gateway to run an embedded network requester for minimal network overhead - #[clap(long, conflicts_with = "with_network_requester")] + #[clap(long, hide = true, conflicts_with = "with_network_requester")] with_ip_forwarder: bool, // ##### NETWORK REQUESTER FLAGS ##### diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index ad6a4495c6..a0f807a99d 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -91,7 +91,7 @@ pub struct Run { with_network_requester: Option, /// Allows this gateway to run an embedded network requester for minimal network overhead - #[arg(long, conflicts_with = "with_network_requester")] + #[arg(long, hide = true, conflicts_with = "with_network_requester")] with_ip_forwarder: Option, // ##### NETWORK REQUESTER FLAGS ##### diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 7bbdd1233c..0be8be5eaf 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -476,9 +476,7 @@ impl Gateway { }); } - // WIP(JON) - // let nr_request_filter = if self.config.network_requester.enabled { - let nr_request_filter = if false { + let nr_request_filter = if self.config.network_requester.enabled { let embedded_nr = self .start_network_requester( mix_forwarding_channel.clone(), @@ -493,7 +491,9 @@ impl Gateway { None }; - if true { + // NOTE: this is mutually exclusive with the network requester (for now). This is reflected + // in the command line arguments as well. + if self.config.ip_forwarder.enabled { let embedded_ip_sp = self .start_ip_service_provider( mix_forwarding_channel.clone(), From 49cf33f6d7d7d7aeae792df646536d853f0fb660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 30 Oct 2023 11:09:50 +0100 Subject: [PATCH 120/236] Proper config backwards compatibility --- gateway/src/commands/upgrade_helpers.rs | 33 ++- gateway/src/config/mod.rs | 1 + gateway/src/config/old_config_v1_1_29.rs | 28 +- gateway/src/config/old_config_v1_1_30.rs | 362 +++++++++++++++++++++++ 4 files changed, 407 insertions(+), 17 deletions(-) create mode 100644 gateway/src/config/old_config_v1_1_30.rs diff --git a/gateway/src/commands/upgrade_helpers.rs b/gateway/src/commands/upgrade_helpers.rs index 7b13cc3f53..f5c9b14953 100644 --- a/gateway/src/commands/upgrade_helpers.rs +++ b/gateway/src/commands/upgrade_helpers.rs @@ -4,6 +4,7 @@ use crate::config::old_config_v1_1_20::ConfigV1_1_20; use crate::config::old_config_v1_1_28::ConfigV1_1_28; use crate::config::old_config_v1_1_29::ConfigV1_1_29; +use crate::config::old_config_v1_1_30::ConfigV1_1_30; use crate::config::{default_config_filepath, Config}; use crate::error::GatewayError; use log::info; @@ -22,7 +23,8 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result { let updated_step1: ConfigV1_1_28 = old_config.into(); let updated_step2: ConfigV1_1_29 = updated_step1.into(); - let updated: Config = updated_step2.into(); + let updated_step3: ConfigV1_1_30 = updated_step2.into(); + let updated: Config = updated_step3.into(); updated .save_to_default_location() .map_err(|err| GatewayError::ConfigSaveFailure { @@ -45,7 +47,8 @@ fn try_upgrade_v1_1_28_config(id: &str) -> Result { info!("It is going to get updated to the current specification."); let updated_step1: ConfigV1_1_29 = old_config.into(); - let updated: Config = updated_step1.into(); + let updated_step2: ConfigV1_1_30 = updated_step1.into(); + let updated: Config = updated_step2.into(); updated .save_to_default_location() .map_err(|err| GatewayError::ConfigSaveFailure { @@ -67,6 +70,29 @@ fn try_upgrade_v1_1_29_config(id: &str) -> Result { info!("It seems the gateway is using <= v1.1.29 config template."); info!("It is going to get updated to the current specification."); + let updated_step1: ConfigV1_1_30 = old_config.into(); + let updated: Config = updated_step1.into(); + updated + .save_to_default_location() + .map_err(|err| GatewayError::ConfigSaveFailure { + path: default_config_filepath(id), + id: id.to_string(), + source: err, + })?; + + Ok(true) +} + +fn try_upgrade_v1_1_30_config(id: &str) -> Result { + // explicitly load it as v1.1.30 (which is incompatible with the current, i.e. 1.1.31+) + let Ok(old_config) = ConfigV1_1_30::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 gateway is using <= v1.1.30 config template."); + info!("It is going to get updated to the current specification."); + let updated: Config = old_config.into(); updated .save_to_default_location() @@ -89,6 +115,9 @@ pub(crate) fn try_upgrade_config(id: &str) -> Result<(), GatewayError> { if try_upgrade_v1_1_29_config(id)? { return Ok(()); } + if try_upgrade_v1_1_30_config(id)? { + return Ok(()); + } Ok(()) } diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index 88c438e29c..a1adbf86bf 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -24,6 +24,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop}; pub(crate) mod old_config_v1_1_20; pub(crate) mod old_config_v1_1_28; pub(crate) mod old_config_v1_1_29; +pub(crate) mod old_config_v1_1_30; pub mod persistence; mod template; diff --git a/gateway/src/config/old_config_v1_1_29.rs b/gateway/src/config/old_config_v1_1_29.rs index 467b82709f..842e0a8275 100644 --- a/gateway/src/config/old_config_v1_1_29.rs +++ b/gateway/src/config/old_config_v1_1_29.rs @@ -1,9 +1,6 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::persistence::paths::{GatewayPaths, KeysPaths}; -use crate::config::{Config, Debug, Gateway, NetworkRequester}; -use nym_bin_common::logging::LoggingSettings; use nym_config::{ must_get_home, read_config_from_toml_file, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, NYM_DIR, }; @@ -14,6 +11,11 @@ use std::path::{Path, PathBuf}; use std::time::Duration; use url::Url; +use super::old_config_v1_1_30::{ + ConfigV1_1_30, DebugV1_1_30, GatewayPathsV1_1_30, GatewayV1_1_30, KeysPathsV1_1_30, + LoggingSettingsV1_1_30, NetworkRequesterV1_1_30, +}; + const DEFAULT_GATEWAYS_DIR: &str = "gateways"; // 'DEBUG' @@ -105,9 +107,9 @@ impl ConfigV1_1_29 { } } -impl From for Config { +impl From for ConfigV1_1_30 { fn from(value: ConfigV1_1_29) -> Self { - Config { + ConfigV1_1_30 { save_path: value.save_path, // \/ ADDED @@ -121,7 +123,7 @@ impl From for Config { // \/ ADDED http: Default::default(), // /\ ADDED - gateway: Gateway { + gateway: GatewayV1_1_30 { version: value.gateway.version, id: value.gateway.id, only_coconut_credentials: value.gateway.only_coconut_credentials, @@ -141,8 +143,8 @@ impl From for Config { // \/ ADDED wireguard: Default::default(), // /\ ADDED - storage_paths: GatewayPaths { - keys: KeysPaths { + storage_paths: GatewayPathsV1_1_30 { + keys: KeysPathsV1_1_30 { private_identity_key_file: value.storage_paths.keys.private_identity_key_file, public_identity_key_file: value.storage_paths.keys.public_identity_key_file, private_sphinx_key_file: value.storage_paths.keys.private_sphinx_key_file, @@ -150,16 +152,12 @@ impl From for Config { }, clients_storage: value.storage_paths.clients_storage, network_requester_config: value.storage_paths.network_requester_config, - // WIP: make proper conversion - ip_forwarder_config: Default::default(), }, - network_requester: NetworkRequester { + network_requester: NetworkRequesterV1_1_30 { enabled: value.network_requester.enabled, }, - // WIP: make proper conversion - ip_forwarder: Default::default(), - logging: LoggingSettings {}, - debug: Debug { + logging: LoggingSettingsV1_1_30 {}, + debug: DebugV1_1_30 { packet_forwarding_initial_backoff: value.debug.packet_forwarding_initial_backoff, packet_forwarding_maximum_backoff: value.debug.packet_forwarding_maximum_backoff, initial_connection_timeout: value.debug.initial_connection_timeout, diff --git a/gateway/src/config/old_config_v1_1_30.rs b/gateway/src/config/old_config_v1_1_30.rs new file mode 100644 index 0000000000..66dcbdea60 --- /dev/null +++ b/gateway/src/config/old_config_v1_1_30.rs @@ -0,0 +1,362 @@ +// Copyright 2020-2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::persistence::paths::GatewayPaths; +use nym_bin_common::logging::LoggingSettings; +use nym_config::{ + must_get_home, read_config_from_toml_file, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, NYM_DIR, +}; +use serde::{Deserialize, Deserializer, Serialize}; +use std::io; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use std::path::{Path, PathBuf}; +use std::time::Duration; +use url::Url; + +use super::persistence::paths::KeysPaths; +use super::{Config, Debug, Gateway, NetworkRequester}; + +const DEFAULT_GATEWAYS_DIR: &str = "gateways"; + +// 'DEBUG' +// where applicable, the below are defined in milliseconds +const DEFAULT_PRESENCE_SENDING_DELAY: Duration = Duration::from_millis(10_000); +const DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF: Duration = Duration::from_millis(10_000); +const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: Duration = Duration::from_millis(300_000); +const DEFAULT_INITIAL_CONNECTION_TIMEOUT: Duration = Duration::from_millis(1_500); +const DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE: usize = 2000; + +const DEFAULT_STORED_MESSAGE_FILENAME_LENGTH: u16 = 16; +const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100; + +fn de_maybe_port<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let port = u16::deserialize(deserializer)?; + if port == 0 { + Ok(None) + } else { + Ok(Some(port)) + } +} + +fn de_maybe_path<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let path = PathBuf::deserialize(deserializer)?; + if path.as_os_str().is_empty() { + Ok(None) + } else { + Ok(Some(path)) + } +} + +/// Derive default path to gateway's config directory. +/// It should get resolved to `$HOME/.nym/gateways//config` +pub fn default_config_directory>(id: P) -> PathBuf { + must_get_home() + .join(NYM_DIR) + .join(DEFAULT_GATEWAYS_DIR) + .join(id) + .join(DEFAULT_CONFIG_DIR) +} + +/// Derive default path to gateways's config file. +/// It should get resolved to `$HOME/.nym/gateways//config/config.toml` +pub fn default_config_filepath>(id: P) -> PathBuf { + default_config_directory(id).join(DEFAULT_CONFIG_FILENAME) +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct ConfigV1_1_30 { + // additional metadata holding on-disk location of this config file + #[serde(skip)] + pub(crate) save_path: Option, + + pub host: nym_node::config::Host, + + #[serde(default)] + pub http: nym_node::config::Http, + + pub gateway: GatewayV1_1_30, + + #[serde(default)] + // currently not really used for anything useful + pub wireguard: WireguardV1_1_30, + + pub storage_paths: GatewayPathsV1_1_30, + + pub network_requester: NetworkRequesterV1_1_30, + + #[serde(default)] + pub logging: LoggingSettingsV1_1_30, + + #[serde(default)] + pub debug: DebugV1_1_30, +} + +impl ConfigV1_1_30 { + pub fn read_from_default_path>(id: P) -> io::Result { + read_config_from_toml_file(default_config_filepath(id)) + } +} + +impl From for Config { + fn from(value: ConfigV1_1_30) -> Self { + Self { + save_path: value.save_path, + host: value.host, + http: value.http, + gateway: Gateway { + version: value.gateway.version, + id: value.gateway.id, + only_coconut_credentials: value.gateway.only_coconut_credentials, + listening_address: value.gateway.listening_address, + mix_port: value.gateway.mix_port, + clients_port: value.gateway.clients_port, + clients_wss_port: value.gateway.clients_wss_port, + enabled_statistics: value.gateway.enabled_statistics, + statistics_service_url: value.gateway.statistics_service_url, + nym_api_urls: value.gateway.nym_api_urls, + nyxd_urls: value.gateway.nyxd_urls, + cosmos_mnemonic: value.gateway.cosmos_mnemonic, + }, + wireguard: nym_node::config::Wireguard { + enabled: value.wireguard.enabled, + bind_address: value.wireguard.bind_address, + announced_port: value.wireguard.announced_port, + storage_paths: nym_node::config::persistence::WireguardPaths { + // no fields (yet) + }, + }, + storage_paths: GatewayPaths { + keys: KeysPaths { + private_identity_key_file: value.storage_paths.keys.private_identity_key_file, + public_identity_key_file: value.storage_paths.keys.public_identity_key_file, + private_sphinx_key_file: value.storage_paths.keys.private_sphinx_key_file, + public_sphinx_key_file: value.storage_paths.keys.public_sphinx_key_file, + }, + clients_storage: value.storage_paths.clients_storage, + network_requester_config: value.storage_paths.network_requester_config, + // \/ ADDED + ip_forwarder_config: Default::default(), + // /\ ADDED + }, + network_requester: NetworkRequester { + enabled: value.network_requester.enabled, + }, + // \/ ADDED + ip_forwarder: Default::default(), + // /\ ADDED + logging: LoggingSettings { + // no fields (yet) + }, + debug: Debug { + packet_forwarding_initial_backoff: value.debug.packet_forwarding_initial_backoff, + packet_forwarding_maximum_backoff: value.debug.packet_forwarding_maximum_backoff, + initial_connection_timeout: value.debug.initial_connection_timeout, + maximum_connection_buffer_size: value.debug.maximum_connection_buffer_size, + presence_sending_delay: value.debug.presence_sending_delay, + stored_messages_filename_length: value.debug.stored_messages_filename_length, + message_retrieval_limit: value.debug.message_retrieval_limit, + use_legacy_framed_packet_version: value.debug.use_legacy_framed_packet_version, + }, + } + } +} + +#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)] +pub struct GatewayV1_1_30 { + /// Version of the gateway for which this configuration was created. + pub version: String, + + /// ID specifies the human readable ID of this particular gateway. + pub id: String, + + /// Indicates whether this gateway is accepting only coconut credentials for accessing the + /// the mixnet, or if it also accepts non-paying clients + #[serde(default)] + pub only_coconut_credentials: bool, + + /// Address to which this mixnode will bind to and will be listening for packets. + pub listening_address: IpAddr, + + /// Port used for listening for all mixnet traffic. + /// (default: 1789) + pub mix_port: u16, + + /// Port used for listening for all client-related traffic. + /// (default: 9000) + pub clients_port: u16, + + /// If applicable, announced port for listening for secure websocket client traffic. + /// (default: None) + #[serde(deserialize_with = "de_maybe_port")] + pub clients_wss_port: Option, + + /// Whether gateway collects and sends anonymized statistics + pub enabled_statistics: bool, + + /// Domain address of the statistics service + pub statistics_service_url: Url, + + /// Addresses to APIs from which the node gets the view of the network. + #[serde(alias = "validator_api_urls")] + pub nym_api_urls: Vec, + + /// Addresses to validators which the node uses to check for double spending of ERC20 tokens. + #[serde(alias = "validator_nymd_urls")] + pub nyxd_urls: Vec, + + /// Mnemonic of a cosmos wallet used in checking for double spending. + // #[deprecated(note = "move to storage")] + // TODO: I don't think this should be stored directly in the config... + pub cosmos_mnemonic: bip39::Mnemonic, +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(default)] +#[serde(deny_unknown_fields)] +pub struct WireguardV1_1_30 { + /// Specifies whether the wireguard service is enabled on this node. + pub enabled: bool, + + /// Socket address this node will use for binding its wireguard interface. + /// default: `0.0.0.0:51820` + pub bind_address: SocketAddr, + + /// Port announced to external clients wishing to connect to the wireguard interface. + /// Useful in the instances where the node is behind a proxy. + pub announced_port: u16, + + /// Paths for wireguard keys, client registries, etc. + pub storage_paths: WireguardPathsV1_1_30, +} + +impl Default for WireguardV1_1_30 { + fn default() -> Self { + Self { + enabled: false, + bind_address: SocketAddr::new( + IpAddr::V4(Ipv4Addr::UNSPECIFIED), + nym_node::config::DEFAULT_WIREGUARD_PORT, + ), + announced_port: nym_node::config::DEFAULT_WIREGUARD_PORT, + storage_paths: WireguardPathsV1_1_30 {}, + } + } +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct WireguardPathsV1_1_30 { + // pub keys: +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct GatewayPathsV1_1_30 { + pub keys: KeysPathsV1_1_30, + + /// Path to sqlite database containing all persistent data: messages for offline clients, + /// derived shared keys and available client bandwidths. + #[serde(alias = "persistent_storage")] + pub clients_storage: PathBuf, + + /// Path to the configuration of the embedded network requester. + #[serde(deserialize_with = "de_maybe_path")] + pub network_requester_config: Option, + // pub node_description: PathBuf, + + // pub cosmos_bip39_mnemonic: PathBuf, +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] +pub struct KeysPathsV1_1_30 { + /// Path to file containing private identity key. + pub private_identity_key_file: PathBuf, + + /// Path to file containing public identity key. + pub public_identity_key_file: PathBuf, + + /// Path to file containing private sphinx key. + pub private_sphinx_key_file: PathBuf, + + /// Path to file containing public sphinx key. + pub public_sphinx_key_file: PathBuf, +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(default)] +pub struct NetworkRequesterV1_1_30 { + /// Specifies whether network requester service is enabled in this process. + pub enabled: bool, +} + +#[allow(clippy::derivable_impls)] +impl Default for NetworkRequesterV1_1_30 { + fn default() -> Self { + Self { enabled: false } + } +} + +#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct LoggingSettingsV1_1_30 { + // well, we need to implement something here at some point... +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(default)] +pub struct DebugV1_1_30 { + /// Initial value of an exponential backoff to reconnect to dropped TCP connection when + /// forwarding sphinx packets. + #[serde(with = "humantime_serde")] + pub packet_forwarding_initial_backoff: Duration, + + /// Maximum value of an exponential backoff to reconnect to dropped TCP connection when + /// forwarding sphinx packets. + #[serde(with = "humantime_serde")] + pub packet_forwarding_maximum_backoff: Duration, + + /// Timeout for establishing initial connection when trying to forward a sphinx packet. + #[serde(with = "humantime_serde")] + pub initial_connection_timeout: Duration, + + /// Maximum number of packets that can be stored waiting to get sent to a particular connection. + pub maximum_connection_buffer_size: usize, + + /// Delay between each subsequent presence data being sent. + #[serde(with = "humantime_serde")] + pub presence_sending_delay: Duration, + + /// Length of filenames for new client messages. + pub stored_messages_filename_length: u16, + + /// Number of messages from offline client that can be pulled at once from the storage. + pub message_retrieval_limit: i64, + + /// Specifies whether the mixnode should be using the legacy framing for the sphinx packets. + // it's set to true by default. The reason for that decision is to preserve compatibility with the + // existing nodes whilst everyone else is upgrading and getting the code for handling the new field. + // It shall be disabled in the subsequent releases. + pub use_legacy_framed_packet_version: bool, +} + +impl Default for DebugV1_1_30 { + fn default() -> Self { + Self { + packet_forwarding_initial_backoff: DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF, + packet_forwarding_maximum_backoff: DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF, + initial_connection_timeout: DEFAULT_INITIAL_CONNECTION_TIMEOUT, + presence_sending_delay: DEFAULT_PRESENCE_SENDING_DELAY, + maximum_connection_buffer_size: DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE, + stored_messages_filename_length: DEFAULT_STORED_MESSAGE_FILENAME_LENGTH, + message_retrieval_limit: DEFAULT_MESSAGE_RETRIEVAL_LIMIT, + use_legacy_framed_packet_version: false, + } + } +} From 5ef48b92fae7b29cdb0f230c93eb831c7ef584c7 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Mon, 30 Oct 2023 13:14:48 +0100 Subject: [PATCH 121/236] Edit the copy in wallet for no password flow --- nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx b/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx index 04b50f3785..05ddc018ad 100644 --- a/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx +++ b/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx @@ -21,7 +21,7 @@ export const MultiAccountHowTo = ({ show, handleClose }: { show: boolean; handle } /> - If you don’t have a password set for your account, go to the Settings, under Security tab create a password + If you don’t have a password set for your account, log out, click on login with password and follow the forgot my password flow If you already have a password, log in to the wallet using your password then try create/import accounts From da9d743f39378f9c95b16f76cce689abcedfb1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 30 Oct 2023 12:55:42 +0000 Subject: [PATCH 122/236] [mixnode] replace rocket with axum (#4071) * axum-equivalent mixnode http api routes * replaced all rocket routes with axum equivalents * removed '_axum' suffix from the routes --- Cargo.lock | 4 +- .../mixnode-common/src/verloc/measurement.rs | 8 +-- common/mixnode-common/src/verloc/mod.rs | 2 +- gateway/Cargo.toml | 2 +- mixnode/Cargo.toml | 9 ++- mixnode/src/commands/mod.rs | 1 + mixnode/src/commands/run.rs | 2 +- mixnode/src/commands/sign.rs | 4 +- mixnode/src/error.rs | 11 ++++ mixnode/src/main.rs | 5 +- mixnode/src/node/http/description.rs | 15 +++-- mixnode/src/node/http/hardware.rs | 16 ++--- mixnode/src/node/http/mod.rs | 12 ++-- mixnode/src/node/http/state.rs | 25 ++++++++ mixnode/src/node/http/stats.rs | 41 ++++++++----- mixnode/src/node/http/verloc.rs | 17 ++++-- .../node/listener/connection_handler/mod.rs | 5 +- mixnode/src/node/listener/mod.rs | 3 +- mixnode/src/node/mod.rs | 61 +++++++++++-------- mixnode/src/node/node_statistics.rs | 8 +-- 20 files changed, 159 insertions(+), 92 deletions(-) create mode 100644 mixnode/src/error.rs create mode 100644 mixnode/src/node/http/state.rs diff --git a/Cargo.lock b/Cargo.lock index 614ed8738a..388c0697fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6697,6 +6697,7 @@ name = "nym-mixnode" version = "1.1.31" dependencies = [ "anyhow", + "axum", "bs58 0.4.0", "cfg-if", "clap 4.4.6", @@ -6714,6 +6715,7 @@ dependencies = [ "nym-crypto", "nym-mixnet-client", "nym-mixnode-common", + "nym-node", "nym-nonexhaustive-delayqueue", "nym-pemstore", "nym-sphinx", @@ -6726,10 +6728,10 @@ dependencies = [ "opentelemetry", "pretty_env_logger", "rand 0.7.3", - "rocket", "serde", "serde_json", "sysinfo", + "thiserror", "tokio", "tokio-util", "toml 0.5.11", diff --git a/common/mixnode-common/src/verloc/measurement.rs b/common/mixnode-common/src/verloc/measurement.rs index 6f3d93bb65..a1584dee99 100644 --- a/common/mixnode-common/src/verloc/measurement.rs +++ b/common/mixnode-common/src/verloc/measurement.rs @@ -9,6 +9,7 @@ use std::sync::Arc; use std::time::Duration; use tokio::sync::RwLock; +#[derive(Clone)] pub struct AtomicVerlocResult { inner: Arc>, } @@ -35,13 +36,6 @@ impl AtomicVerlocResult { } } - // this could have also been achieved with a normal #[derive(Clone)] but I prefer to be explicit about it - pub(crate) fn clone_data_pointer(&self) -> Self { - AtomicVerlocResult { - inner: Arc::clone(&self.inner), - } - } - pub(crate) async fn reset_results(&self, new_tested: usize) { let mut write_permit = self.inner.write().await; write_permit.total_tested = new_tested; diff --git a/common/mixnode-common/src/verloc/mod.rs b/common/mixnode-common/src/verloc/mod.rs index 3872f8002e..8fa66e3445 100644 --- a/common/mixnode-common/src/verloc/mod.rs +++ b/common/mixnode-common/src/verloc/mod.rs @@ -226,7 +226,7 @@ impl VerlocMeasurer { } pub fn get_verloc_results_pointer(&self) -> AtomicVerlocResult { - self.results.clone_data_pointer() + self.results.clone() } fn start_listening(&self) -> JoinHandle<()> { diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index b968ee7b7e..c1d6503199 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -52,7 +52,7 @@ tokio = { workspace = true, features = [ tokio-stream = { version = "0.1.11", features = ["fs"] } tokio-tungstenite = { version = "0.20.1" } tokio-util = { version = "0.7.4", features = ["codec"] } -url = { version = "2.2", features = ["serde"] } +url = { workspace = true, features = ["serde"] } zeroize = { workspace = true } # internal diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index 37268c654d..39061c4ca4 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -16,6 +16,7 @@ rust-version = "1.58.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +axum = { workspace = true } anyhow = "1.0.40" bs58 = "0.4.0" clap = { version = "4.0", features = ["cargo", "derive"] } @@ -28,22 +29,24 @@ lazy_static = "1.4.0" log = { workspace = true } pretty_env_logger = "0.4.0" rand = "0.7.3" -rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } sysinfo = "0.27.7" tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] } tokio-util = { version = "0.7.3", features = ["codec"] } toml = "0.5.8" -url = { version = "2.2", features = ["serde"] } +url = { workspace = true, features = ["serde"] } cfg-if = "1.0.0" +thiserror = { workspace = true } ## tracing tracing = { version = "0.1.37", optional = true } opentelemetry = { version = "0.19.0", optional = true } -## internal +# internal +nym-node = { path = "../nym-node" } + nym-config = { path = "../common/config" } nym-crypto = { path = "../common/crypto" } nym-contracts-common = { path = "../common/cosmwasm-smart-contracts/contracts-common" } diff --git a/mixnode/src/commands/mod.rs b/mixnode/src/commands/mod.rs index e79df8e2ab..17a2bd3a59 100644 --- a/mixnode/src/commands/mod.rs +++ b/mixnode/src/commands/mod.rs @@ -7,6 +7,7 @@ use anyhow::anyhow; use clap::CommandFactory; use clap::Subcommand; use colored::Colorize; +use log::{error, info, warn}; use nym_bin_common::completions::{fig_generate, ArgShell}; use nym_bin_common::version_checker; use nym_config::defaults::var_names::{BECH32_PREFIX, NYM_API}; diff --git a/mixnode/src/commands/run.rs b/mixnode/src/commands/run.rs index f617494aad..0fded783b8 100644 --- a/mixnode/src/commands/run.rs +++ b/mixnode/src/commands/run.rs @@ -6,11 +6,11 @@ use crate::commands::{override_config, try_load_current_config, version_check}; use crate::node::MixNode; use anyhow::bail; use clap::Args; +use log::error; use nym_bin_common::output_format::OutputFormat; use nym_config::helpers::SPECIAL_ADDRESSES; use nym_validator_client::nyxd; use std::net::IpAddr; - #[derive(Args, Clone)] pub(crate) struct Run { /// Id of the nym-mixnode we want to run diff --git a/mixnode/src/commands/sign.rs b/mixnode/src/commands/sign.rs index 8c10bdb995..9650f53273 100644 --- a/mixnode/src/commands/sign.rs +++ b/mixnode/src/commands/sign.rs @@ -5,15 +5,13 @@ use crate::commands::{try_load_current_config, validate_bech32_address_or_exit}; use crate::node::MixNode; use anyhow::{bail, Result}; use clap::{ArgGroup, Args}; +use log::error; use nym_bin_common::output_format::OutputFormat; use nym_crypto::asymmetric::identity; use nym_types::helpers::ConsoleSigningOutput; use nym_validator_client::nyxd; use std::convert::TryFrom; -#[cfg(feature = "cpucycles")] -use tracing::error; - use super::version_check; #[derive(Args, Clone)] diff --git a/mixnode/src/error.rs b/mixnode/src/error.rs new file mode 100644 index 0000000000..a0ee647852 --- /dev/null +++ b/mixnode/src/error.rs @@ -0,0 +1,11 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use thiserror::Error; + +#[derive(Debug, Error)] +pub(crate) enum MixnodeError { + // TODO: in the future this should work the other way, i.e. NymNode depending on Gateway errors + #[error(transparent)] + NymNodeError(#[from] nym_node::error::NymNodeError), +} diff --git a/mixnode/src/main.rs b/mixnode/src/main.rs index bdda653edf..34ca2d613f 100644 --- a/mixnode/src/main.rs +++ b/mixnode/src/main.rs @@ -1,12 +1,10 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -#[macro_use] -extern crate rocket; - use ::nym_config::defaults::setup_env; use clap::{crate_name, crate_version, Parser}; use lazy_static::lazy_static; +use log::info; use nym_bin_common::bin_info; #[allow(unused_imports)] @@ -20,6 +18,7 @@ use tracing::instrument; mod commands; mod config; +pub(crate) mod error; mod node; lazy_static! { diff --git a/mixnode/src/node/http/description.rs b/mixnode/src/node/http/description.rs index 3c37014645..7c6ec2b580 100644 --- a/mixnode/src/node/http/description.rs +++ b/mixnode/src/node/http/description.rs @@ -1,9 +1,14 @@ use crate::node::node_description::NodeDescription; -use rocket::serde::json::Json; -use rocket::State; +use axum::extract::Query; +use nym_node::http::api::{FormattedResponse, OutputParams}; /// Returns a description of the node and why someone might want to delegate stake to it. -#[get("/description")] -pub(crate) fn description(description: &State) -> Json { - Json(description.inner().clone()) +pub(crate) async fn description( + description: NodeDescription, + Query(output): Query, +) -> MixnodeDescriptionResponse { + let output = output.output.unwrap_or_default(); + output.to_response(description) } + +pub type MixnodeDescriptionResponse = FormattedResponse; diff --git a/mixnode/src/node/http/hardware.rs b/mixnode/src/node/http/hardware.rs index 57e2e68bbf..c4e24b4911 100644 --- a/mixnode/src/node/http/hardware.rs +++ b/mixnode/src/node/http/hardware.rs @@ -1,10 +1,11 @@ +use axum::extract::Query; use cupid::TopologyType; -use rocket::serde::{json::Json, Serialize}; +use nym_node::http::api::{FormattedResponse, OutputParams}; +use serde::Serialize; use sysinfo::{System, SystemExt}; #[derive(Serialize, Debug)] -#[serde(crate = "rocket::serde")] -pub(crate) struct Hardware { +pub struct Hardware { ram: String, num_cores: usize, crypto_hardware: Option, @@ -12,7 +13,6 @@ pub(crate) struct Hardware { #[allow(clippy::struct_excessive_bools)] #[derive(Serialize, Debug)] -#[serde(crate = "rocket::serde")] pub(crate) struct CryptoHardware { aesni: bool, avx2: bool, @@ -24,11 +24,13 @@ pub(crate) struct CryptoHardware { } /// Provides hardware information which Nym can use to optimize mixnet speed over time (memory, crypto hardware, CPU, cores, etc). -#[get("/hardware")] -pub(crate) fn hardware() -> Json> { - Json(hardware_info()) +pub(crate) async fn hardware(Query(output): Query) -> MixnodeHardwareResponse { + let output = output.output.unwrap_or_default(); + output.to_response(hardware_info()) } +pub type MixnodeHardwareResponse = FormattedResponse>; + /// Gives back a summary report of whatever system hardware info we can get for this platform. fn hardware_info() -> Option { let crypto_hardware = hardware_info_from_cupid(); diff --git a/mixnode/src/node/http/mod.rs b/mixnode/src/node/http/mod.rs index f92212b9aa..ddedce8215 100644 --- a/mixnode/src/node/http/mod.rs +++ b/mixnode/src/node/http/mod.rs @@ -1,11 +1,15 @@ pub(crate) mod description; pub(crate) mod hardware; +pub(crate) mod state; pub(crate) mod stats; pub(crate) mod verloc; -use rocket::Request; +use axum::http::{StatusCode, Uri}; +use axum::response::IntoResponse; -#[catch(404)] -pub(crate) fn not_found(req: &Request<'_>) -> String { - format!("I couldn't find '{}'. Try something else?", req.uri()) +pub(crate) async fn not_found(uri: Uri) -> impl IntoResponse { + ( + StatusCode::NOT_FOUND, + format!("I couldn't find '{uri}'. Try something else?"), + ) } diff --git a/mixnode/src/node/http/state.rs b/mixnode/src/node/http/state.rs new file mode 100644 index 0000000000..4cc3e7b8d6 --- /dev/null +++ b/mixnode/src/node/http/state.rs @@ -0,0 +1,25 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::node::http::verloc::VerlocState; +use crate::node::node_statistics::SharedNodeStats; +use axum::extract::FromRef; + +// this is a temporary thing for the transition period +#[derive(Clone)] +pub(crate) struct MixnodeAppState { + pub(crate) verloc: VerlocState, + pub(crate) stats: SharedNodeStats, +} + +impl FromRef for VerlocState { + fn from_ref(app_state: &MixnodeAppState) -> Self { + app_state.verloc.clone() + } +} + +impl FromRef for SharedNodeStats { + fn from_ref(app_state: &MixnodeAppState) -> Self { + app_state.stats.clone() + } +} diff --git a/mixnode/src/node/http/stats.rs b/mixnode/src/node/http/stats.rs index c285954cb9..093932288a 100644 --- a/mixnode/src/node/http/stats.rs +++ b/mixnode/src/node/http/stats.rs @@ -1,29 +1,38 @@ use crate::node::node_statistics::{NodeStats, NodeStatsSimple, SharedNodeStats}; -use rocket::serde::json::Json; -use rocket::State; -use serde::Serialize; +use axum::extract::{Query, State}; +use nym_node::http::api::{FormattedResponse, Output}; +use serde::{Deserialize, Serialize}; #[derive(Serialize)] #[serde(untagged)] -pub(crate) enum NodeStatsResponse { +pub enum NodeStatsResponse { Full(NodeStats), Simple(NodeStatsSimple), } -/// Returns a running stats of the node. -#[get("/stats?")] pub(crate) async fn stats( - stats: &State, - debug: Option, -) -> Json { + Query(params): Query, + State(stats): State, +) -> MixnodeStatsResponse { + let output = params.output.unwrap_or_default(); + let snapshot_data = stats.clone_data().await; // there's no point in returning the entire hashmap of sending destinations in regular mode - if let Some(debug) = debug { - if debug { - return Json(NodeStatsResponse::Full(snapshot_data)); - } - } - - Json(NodeStatsResponse::Simple(snapshot_data.simplify())) + let response = if params.debug { + NodeStatsResponse::Full(snapshot_data) + } else { + NodeStatsResponse::Simple(snapshot_data.simplify()) + }; + output.to_response(response) +} + +pub type MixnodeStatsResponse = FormattedResponse; + +#[derive(Default, Debug, Serialize, Deserialize, Copy, Clone)] +// #[derive(Default, Debug, Serialize, Deserialize, Copy, Clone, IntoParams, ToSchema)] +#[serde(default)] +pub(crate) struct StatsQueryParams { + debug: bool, + pub output: Option, } diff --git a/mixnode/src/node/http/verloc.rs b/mixnode/src/node/http/verloc.rs index ff26a1b52d..1848f48f6c 100644 --- a/mixnode/src/node/http/verloc.rs +++ b/mixnode/src/node/http/verloc.rs @@ -1,7 +1,8 @@ +use axum::extract::{Query, State}; use nym_mixnode_common::verloc::{AtomicVerlocResult, VerlocResult}; -use rocket::serde::json::Json; -use rocket::State; +use nym_node::http::api::{FormattedResponse, OutputParams}; +#[derive(Clone)] pub(crate) struct VerlocState { shared: AtomicVerlocResult, } @@ -16,8 +17,12 @@ impl VerlocState { /// Provides verifiable location (verloc) measurements for this mixnode - a list of the /// round-trip times, in milliseconds, for all other mixnodes that this node knows about. -#[get("/verloc")] -pub(crate) async fn verloc(state: &State) -> Json { - // since it's impossible to get a mutable reference to the state, we can't cache any results outside the lock : ( - Json(state.shared.clone_data().await) +pub(crate) async fn verloc( + State(verloc): State, + Query(output): Query, +) -> MixnodeVerlocResponse { + let output = output.output.unwrap_or_default(); + output.to_response(verloc.shared.clone_data().await) } + +pub type MixnodeVerlocResponse = FormattedResponse; diff --git a/mixnode/src/node/listener/connection_handler/mod.rs b/mixnode/src/node/listener/connection_handler/mod.rs index 733d2660f8..8d0895cbea 100644 --- a/mixnode/src/node/listener/connection_handler/mod.rs +++ b/mixnode/src/node/listener/connection_handler/mod.rs @@ -7,6 +7,8 @@ use crate::node::listener::connection_handler::packet_processing::{ use crate::node::packet_delayforwarder::PacketDelayForwardSender; use crate::node::TaskClient; use futures::StreamExt; +use log::debug; +use log::{error, info, warn}; use nym_mixnode_common::measure; use nym_sphinx::forwarding::packet::MixPacket; use nym_sphinx::framing::codec::NymCodec; @@ -16,8 +18,9 @@ use std::net::SocketAddr; use tokio::net::TcpStream; use tokio::time::Instant; use tokio_util::codec::Framed; + #[cfg(feature = "cpucycles")] -use tracing::{error, info, instrument}; +use tracing::instrument; pub(crate) mod packet_processing; diff --git a/mixnode/src/node/listener/mod.rs b/mixnode/src/node/listener/mod.rs index f8fad07b23..fc553b41ed 100644 --- a/mixnode/src/node/listener/mod.rs +++ b/mixnode/src/node/listener/mod.rs @@ -2,12 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 use crate::node::listener::connection_handler::ConnectionHandler; +use log::{error, info, warn}; use std::net::SocketAddr; use std::process; use tokio::net::TcpListener; use tokio::task::JoinHandle; -#[cfg(feature = "cpucycles")] -use tracing::error; use super::TaskClient; diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index 98b0c769dc..a73c5a10a4 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -2,23 +2,26 @@ // SPDX-License-Identifier: Apache-2.0 use crate::config::Config; -use crate::node::http::{ - description::description, - hardware::hardware, - not_found, - stats::stats, - verloc::{verloc as verloc_route, VerlocState}, -}; +use crate::node::http::description::description; +use crate::node::http::hardware::hardware; +use crate::node::http::not_found; +use crate::node::http::state::MixnodeAppState; +use crate::node::http::stats::stats; +use crate::node::http::verloc::{verloc, VerlocState}; use crate::node::listener::connection_handler::packet_processing::PacketProcessor; use crate::node::listener::connection_handler::ConnectionHandler; use crate::node::listener::Listener; use crate::node::node_description::NodeDescription; use crate::node::node_statistics::SharedNodeStats; use crate::node::packet_delayforwarder::{DelayForwarder, PacketDelayForwardSender}; +use axum::routing::get; +use axum::Router; +use log::{error, info, warn}; use nym_bin_common::output_format::OutputFormat; use nym_bin_common::version_checker::parse_version; use nym_crypto::asymmetric::{encryption, identity}; use nym_mixnode_common::verloc::{self, AtomicVerlocResult, VerlocMeasurer}; +use nym_node::http::middleware::logging; use nym_task::{TaskClient, TaskManager}; use rand::seq::SliceRandom; use rand::thread_rng; @@ -26,9 +29,6 @@ use std::net::SocketAddr; use std::process; use std::sync::Arc; -#[cfg(feature = "cpucycles")] -use tracing::{error, info, warn}; - mod http; mod listener; pub(crate) mod node_description; @@ -99,29 +99,36 @@ impl MixNode { atomic_verloc_result: AtomicVerlocResult, node_stats_pointer: SharedNodeStats, ) { - info!( - "Starting HTTP API on http://{}:{}", - self.config.mixnode.listening_address, self.config.mixnode.http_api_port + let bind_address = SocketAddr::new( + self.config.mixnode.listening_address, + self.config.mixnode.http_api_port, ); - let mut config = rocket::config::Config::release_default(); + info!("Starting HTTP API on http://{bind_address}",); - // bind to the same address as we are using for mixnodes - config.address = self.config.mixnode.listening_address; - config.port = self.config.mixnode.http_api_port; + let state = MixnodeAppState { + verloc: VerlocState::new(atomic_verloc_result), + stats: node_stats_pointer, + }; - let verloc_state = VerlocState::new(atomic_verloc_result); - let descriptor = self.descriptor.clone(); + let router = Router::new() + .route("/verloc", get(verloc)) + .route( + "/description", + get({ + let descriptor = self.descriptor.clone(); + move |query| description(descriptor, query) + }), + ) + .route("/stats", get(stats)) + .route("/hardware", get(hardware)) + .fallback(not_found) + .layer(axum::middleware::from_fn(logging::logger)) + .with_state(state); tokio::spawn(async move { - rocket::build() - .configure(config) - .mount("/", routes![verloc_route, description, stats, hardware]) - .register("/", catchers![not_found]) - .manage(verloc_state) - .manage(descriptor) - .manage(node_stats_pointer) - .launch() + axum::Server::bind(&bind_address) + .serve(router.into_make_service_with_connect_info::()) .await }); } diff --git a/mixnode/src/node/node_statistics.rs b/mixnode/src/node/node_statistics.rs index 2187d77a91..72f85c6001 100644 --- a/mixnode/src/node/node_statistics.rs +++ b/mixnode/src/node/node_statistics.rs @@ -1,6 +1,8 @@ +use super::TaskClient; use futures::channel::mpsc; use futures::lock::Mutex; use futures::StreamExt; +use log::{debug, info, trace}; use serde::Serialize; use std::collections::HashMap; use std::ops::DerefMut; @@ -9,8 +11,6 @@ use std::sync::Arc; use std::time::{Duration, SystemTime}; use tokio::sync::{RwLock, RwLockReadGuard}; -use super::TaskClient; - // convenience aliases type PacketsMap = HashMap; type PacketDataReceiver = mpsc::UnboundedReceiver; @@ -80,7 +80,7 @@ impl SharedNodeStats { } #[derive(Serialize, Clone)] -pub(crate) struct NodeStats { +pub struct NodeStats { #[serde(serialize_with = "humantime_serde::serialize")] update_time: SystemTime, @@ -126,7 +126,7 @@ impl NodeStats { } #[derive(Serialize, Clone)] -pub(crate) struct NodeStatsSimple { +pub struct NodeStatsSimple { #[serde(serialize_with = "humantime_serde::serialize")] update_time: SystemTime, From aa02f33addb6c2bee4e32b75dc47074a7c6fca04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 30 Oct 2023 15:01:47 +0100 Subject: [PATCH 123/236] No need to show setup-ip-forwarder just yet --- gateway/src/commands/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/gateway/src/commands/mod.rs b/gateway/src/commands/mod.rs index f51fd011d2..83cde5302b 100644 --- a/gateway/src/commands/mod.rs +++ b/gateway/src/commands/mod.rs @@ -34,6 +34,7 @@ pub(crate) enum Commands { /// Add ip forwarder support to this gateway // essentially an option to include ip forwarder without having to setup fresh gateway + #[command(hide = true)] SetupIpForwarder(setup_ip_forwarder::CmdArgs), /// Sign text to prove ownership of this mixnode From 2084095773c264159321213046c4f8e4139c8c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Walther?= Date: Mon, 30 Oct 2023 16:42:40 +0100 Subject: [PATCH 124/236] Update security disclosure process --- SECURITY.md | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index dac44ded6c..c3b9bb9748 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,8 +1,90 @@ Critical bug or security issue 💥 -If you're here because you're trying to figure out how to notify us of a security issue, go to Discord or Matrix, and alert the core engineers: +If you're here because you're trying to figure out how to notify us of a security issue, send us a PGP encrypted email to: - Jedrzej Stuczynski, discord: "Jedrzej | Nym#5666" , matrix: @jstuczyn:nymtech.chat - Mark Sinclair | discord: marknym#8088 , matrix: @mark:nymtech.chat +``` +security@nymte.ch +``` + +Encrypted with our public key which is available below in plain text and also on keyservers: + +``` +pub rsa4096 2023-10-30 [SC] [expire : 2026-10-29] + 24B2592E801A5AAA8666C8BA7C3C727F05090550 +uid [ ultime ] Security Nym Technologies +sub rsa4096 2023-10-30 [E] [expire : 2026-10-29] + +``` + +The fingerprint of the key is on the second line above. + +If you need to chat __urgently__ to our team for a __critical__ security issue: + +go to Matrix, and alert the core engineers with a private direct message: + + Jedrzej Stuczynski @jstuczyn:nymtech.chat + Mark Sinclair @mark:nymtech.chat + Raphaël Walther @raphael:nymtech.chat Please avoid opening public issues on GitHub that contain information about a potential security vulnerability as this makes it difficult to reduce the impact and harm of valid security issues. + +If you don't know what Matrix is, you can follow this documentation to create an account on this federation of instant messaging servers: + +[Matrix for Instant Messaging](https://matrix.org/docs/chat_basics/matrix-for-im/) + + + +``` +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +iC2pMbWdE0ZTQaFq6tPIg058pjqi +=nqgX +-----END PGP PUBLIC KEY BLOCK----- +``` From f6f2cd7e170634d5f72d7b792a4c6b3fccf29d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 30 Oct 2023 16:13:05 +0000 Subject: [PATCH 125/236] unified native, socks5, NR client inits --- Cargo.lock | 53 ++--- Cargo.toml | 1 + clients/native/Cargo.toml | 4 +- clients/native/src/client/config/mod.rs | 20 ++ clients/native/src/commands/init.rs | 202 +++++------------ clients/socks5/Cargo.toml | 4 +- clients/socks5/src/commands/init.rs | 205 +++++------------ clients/socks5/src/config/mod.rs | 20 ++ common/bin-common/Cargo.toml | 2 +- common/client-core/Cargo.toml | 2 + common/client-core/src/error.rs | 21 ++ common/client-core/src/init/client_init.rs | 201 +++++++++++++++++ common/client-core/src/init/mod.rs | 1 + common/client-core/src/init/types.rs | 16 +- common/commands/Cargo.toml | 2 +- ephemera/Cargo.toml | 2 +- explorer-api/Cargo.toml | 2 +- gateway/Cargo.toml | 2 +- mixnode/Cargo.toml | 2 +- nym-api/Cargo.toml | 2 +- nym-connect/desktop/Cargo.lock | 26 +-- nym-wallet/Cargo.lock | 36 +-- .../network-requester/Cargo.toml | 4 +- .../network-requester/src/cli/init.rs | 209 +++++------------- .../network-requester/src/cli/mod.rs | 2 +- .../network-requester/src/config/mod.rs | 20 ++ tools/internal/sdk-version-bump/Cargo.toml | 2 +- tools/nym-cli/Cargo.toml | 2 +- tools/nym-nr-query/Cargo.toml | 2 +- 29 files changed, 534 insertions(+), 533 deletions(-) create mode 100644 common/client-core/src/init/client_init.rs diff --git a/Cargo.lock b/Cargo.lock index 388c0697fa..63ef8aef35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1158,7 +1158,7 @@ checksum = "f769ab9e8c1652d78dd0b3ec59cdaa1e2bcb3b6b39f6681b256abcdbe101cc14" dependencies = [ "anyhow", "cargo_metadata", - "clap 4.4.6", + "clap 4.4.7", "concolor-control", "crates-index", "dirs-next", @@ -1393,9 +1393,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", @@ -1403,13 +1403,13 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", - "clap_lex 0.5.1", + "clap_lex 0.6.0", "strsim", "terminal_size", ] @@ -1420,7 +1420,7 @@ version = "4.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7" dependencies = [ - "clap 4.4.6", + "clap 4.4.7", ] [[package]] @@ -1429,15 +1429,15 @@ version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29bdbe21a263b628f83fcbeac86a4416a1d588c7669dd41473bc4149e4e7d2f1" dependencies = [ - "clap 4.4.6", + "clap 4.4.7", "clap_complete", ] [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -1456,9 +1456,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "cloudabi" @@ -2871,7 +2871,7 @@ dependencies = [ "bytes", "cfg-if", "chrono", - "clap 4.4.6", + "clap 4.4.7", "config", "digest 0.10.7", "dirs 5.0.1", @@ -2941,7 +2941,7 @@ name = "explorer-api" version = "1.1.30" dependencies = [ "chrono", - "clap 4.4.6", + "clap 4.4.7", "dotenvy", "humantime-serde", "isocountry", @@ -5961,7 +5961,7 @@ dependencies = [ "bs58 0.4.0", "cfg-if", "chrono", - "clap 4.4.6", + "clap 4.4.7", "console-subscriber", "cosmwasm-std", "cw-utils", @@ -6066,7 +6066,7 @@ name = "nym-bin-common" version = "0.6.0" dependencies = [ "atty", - "clap 4.4.6", + "clap 4.4.7", "clap_complete", "clap_complete_fig", "log", @@ -6107,7 +6107,7 @@ dependencies = [ "base64 0.13.1", "bip39", "bs58 0.4.0", - "clap 4.4.6", + "clap 4.4.7", "clap_complete", "clap_complete_fig", "dotenvy", @@ -6132,7 +6132,7 @@ dependencies = [ "bip39", "bs58 0.4.0", "cfg-if", - "clap 4.4.6", + "clap 4.4.7", "comfy-table", "cosmrs", "cosmwasm-std", @@ -6176,7 +6176,7 @@ dependencies = [ name = "nym-client" version = "1.1.30" dependencies = [ - "clap 4.4.6", + "clap 4.4.7", "dirs 4.0.0", "futures", "lazy_static", @@ -6215,6 +6215,7 @@ dependencies = [ "async-trait", "base64 0.21.4", "cfg-if", + "clap 4.4.7", "dashmap", "dirs 4.0.0", "futures", @@ -6523,7 +6524,7 @@ dependencies = [ "atty", "bip39", "bs58 0.4.0", - "clap 4.4.6", + "clap 4.4.7", "colored", "dashmap", "dirs 4.0.0", @@ -6700,7 +6701,7 @@ dependencies = [ "axum", "bs58 0.4.0", "cfg-if", - "clap 4.4.6", + "clap 4.4.7", "colored", "cpu-cycles", "cupid", @@ -6820,7 +6821,7 @@ dependencies = [ "async-file-watcher", "async-trait", "bs58 0.4.0", - "clap 4.4.6", + "clap 4.4.7", "dirs 4.0.0", "futures", "humantime-serde", @@ -6982,7 +6983,7 @@ name = "nym-nr-query" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.6", + "clap 4.4.7", "log", "nym-bin-common", "nym-network-defaults", @@ -7107,7 +7108,7 @@ dependencies = [ name = "nym-socks5-client" version = "1.1.30" dependencies = [ - "clap 4.4.6", + "clap 4.4.7", "lazy_static", "log", "nym-bin-common", @@ -9534,7 +9535,7 @@ version = "0.1.0" dependencies = [ "anyhow", "cargo-edit", - "clap 4.4.6", + "clap 4.4.7", "semver 1.0.20", "serde", "serde_json", @@ -10296,7 +10297,7 @@ name = "ssl-inject" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.6", + "clap 4.4.7", "hex", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 802b81f89e..d7771a2d17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -138,6 +138,7 @@ axum = "0.6.20" base64 = "0.21.4" bip39 = { version = "2.0.0", features = ["zeroize"] } boringtun = { git = "https://github.com/cloudflare/boringtun", rev = "e1d6360d6ab4529fc942a078e4c54df107abe2ba" } +clap = "4.4.7" cfg-if = "1.0.0" cosmwasm-derive = "=1.3.0" cosmwasm-schema = "=1.3.0" diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 57df3570b3..4f714aeaef 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -20,7 +20,7 @@ futures = { workspace = true } # bunch of futures stuff, however, now that I thi # and the single instance of abortable we have should really be refactored anyway url = { workspace = true } -clap = { version = "4.0", features = ["cargo", "derive"] } +clap = { workspace = true, features = ["cargo", "derive"] } dirs = "4.0" lazy_static = "1.4.0" log = { workspace = true } # self explanatory @@ -36,7 +36,7 @@ tokio-tungstenite = { workspace = true } ## internal nym-bandwidth-controller = { path = "../../common/bandwidth-controller" } nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] } -nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage"] } +nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "cli"] } nym-coconut-interface = { path = "../../common/coconut-interface" } nym-config = { path = "../../common/config" } nym-credential-storage = { path = "../../common/credential-storage" } diff --git a/clients/native/src/client/config/mod.rs b/clients/native/src/client/config/mod.rs index 4f57387ceb..65185e579e 100644 --- a/clients/native/src/client/config/mod.rs +++ b/clients/native/src/client/config/mod.rs @@ -16,8 +16,10 @@ use std::net::{IpAddr, Ipv4Addr}; use std::path::{Path, PathBuf}; use std::str::FromStr; +use nym_client_core::config::disk_persistence::CommonClientPaths; pub use nym_client_core::config::Config as BaseClientConfig; pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig}; +use nym_client_core::init::client_init::ClientConfig; pub mod old_config_v1_1_13; pub mod old_config_v1_1_20; @@ -72,6 +74,24 @@ impl NymConfigTemplate for Config { } } +impl ClientConfig for Config { + fn common_paths(&self) -> &CommonClientPaths { + &self.storage_paths.common_paths + } + + fn core_config(&self) -> &BaseClientConfig { + &self.base + } + + fn default_store_location(&self) -> PathBuf { + self.default_location() + } + + fn save_to>(&self, path: P) -> io::Result<()> { + save_formatted_config_to_file(self, path) + } +} + impl Config { pub fn new>(id: S) -> Self { Config { diff --git a/clients/native/src/commands/init.rs b/clients/native/src/commands/init.rs index 0fc27590dd..8c9edeec2a 100644 --- a/clients/native/src/commands/init.rs +++ b/clients/native/src/commands/init.rs @@ -12,55 +12,49 @@ use crate::{ }; use clap::Args; use nym_bin_common::output_format::OutputFormat; -use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails; -use nym_client_core::client::key_manager::persistence::OnDiskKeys; -use nym_client_core::config::GatewayEndpointConfig; -use nym_client_core::error::ClientCoreError; -use nym_client_core::init::helpers::current_gateways; -use nym_client_core::init::types::{GatewayDetails, GatewaySelectionSpecification, GatewaySetup}; -use nym_crypto::asymmetric::identity; -use nym_sphinx::addressing::clients::Recipient; -use nym_topology::NymTopology; +use nym_client_core::init::client_init::{ + initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient, +}; use serde::Serialize; use std::fmt::Display; +use std::fs; use std::net::IpAddr; use std::path::PathBuf; -use std::{fs, io}; -use tap::TapFallible; + +struct NativeClientInit; + +impl InitialisableClient for NativeClientInit { + const NAME: &'static str = "native"; + type Error = ClientError; + type InitArgs = Init; + type Config = Config; + + fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> { + try_upgrade_config(id) + } + + fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> { + fs::create_dir_all(default_data_directory(id))?; + fs::create_dir_all(default_config_directory(id))?; + Ok(()) + } + + fn default_config_path(id: &str) -> PathBuf { + default_config_filepath(id) + } + + fn construct_config(init_args: &Self::InitArgs) -> Self::Config { + override_config( + Config::new(&init_args.common_args.id), + OverrideConfig::from(init_args.clone()), + ) + } +} #[derive(Args, Clone)] pub(crate) struct Init { - /// Id of the nym-mixnet-client we want to create config for. - #[clap(long)] - id: String, - - /// Id of the gateway we are going to connect to. - #[clap(long)] - gateway: Option, - - /// Specifies whether the new gateway should be determined based by latency as opposed to being chosen - /// uniformly. - #[clap(long, conflicts_with = "gateway")] - latency_based_selection: bool, - - /// Force register gateway. WARNING: this will overwrite any existing keys for the given id, - /// potentially causing loss of access. - #[clap(long)] - force_register_gateway: bool, - - /// Comma separated list of rest endpoints of the nyxd validators - #[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)] - nyxd_urls: Option>, - - /// Comma separated list of rest endpoints of the API validators - #[clap( - long, - alias = "api_validators", - value_delimiter = ',', - group = "network" - )] - // the alias here is included for backwards compatibility (1.1.4 and before) - nym_apis: Option>, + #[command(flatten)] + common_args: CommonClientInitArgs, /// Whether to not start the websocket #[clap(long)] @@ -74,10 +68,6 @@ pub(crate) struct Init { #[clap(long)] host: Option, - /// Path to .json file containing custom network specification. - #[clap(long, group = "network", hide = true)] - custom_mixnet: Option, - /// Mostly debug-related option to increase default traffic rate so that you would not need to /// modify config post init #[clap(long, hide = true)] @@ -87,27 +77,28 @@ pub(crate) struct Init { #[clap(long, hide = true)] no_cover: bool, - /// Set this client to work in a enabled credentials mode that would attempt to use gateway - /// with bandwidth credential requirement. - #[clap(long, hide = true)] - enabled_credentials_mode: Option, - #[clap(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, } +impl AsRef for Init { + fn as_ref(&self) -> &CommonClientInitArgs { + &self.common_args + } +} + impl From for OverrideConfig { fn from(init_config: Init) -> Self { OverrideConfig { - nym_apis: init_config.nym_apis, + nym_apis: init_config.common_args.nym_apis, disable_socket: init_config.disable_socket, port: init_config.port, host: init_config.host, fastmode: init_config.fastmode, no_cover: init_config.no_cover, - nyxd_urls: init_config.nyxd_urls, - enabled_credentials_mode: init_config.enabled_credentials_mode, + nyxd_urls: init_config.common_args.nyxd_urls, + enabled_credentials_mode: init_config.common_args.enabled_credentials_mode, } } } @@ -121,15 +112,11 @@ pub struct InitResults { } impl InitResults { - fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self { + fn new(res: InitResultsWithConfig) -> Self { Self { - client_core: nym_client_core::init::types::InitResults::new( - &config.base, - address, - gateway, - ), - client_listening_port: config.socket.listening_port, - client_address: address.to_string(), + client_address: res.init_results.address.to_string(), + client_core: res.init_results, + client_listening_port: res.config.socket.listening_port, } } } @@ -142,97 +129,14 @@ impl Display for InitResults { } } -fn init_paths(id: &str) -> io::Result<()> { - fs::create_dir_all(default_data_directory(id))?; - fs::create_dir_all(default_config_directory(id)) -} - pub(crate) async fn execute(args: Init) -> Result<(), ClientError> { eprintln!("Initialising client..."); - let id = &args.id; + let output = args.output; + let res = initialise_client::(args).await?; - let already_init = if default_config_filepath(id).exists() { - // in case we're using old config, try to upgrade it - // (if we're using the current version, it's a no-op) - try_upgrade_config(id)?; - eprintln!("Client \"{id}\" was already initialised before"); - true - } else { - init_paths(id)?; - false - }; - - // Usually you only register with the gateway on the first init, however you can force - // re-registering if wanted. - let user_wants_force_register = args.force_register_gateway; - if user_wants_force_register { - eprintln!("Instructed to force registering gateway. This will overwrite keys!"); - } - - // If the client was already initialized, don't generate new keys and don't re-register with - // the gateway (because this would create a new shared key). - // Unless the user really wants to. - let register_gateway = !already_init || user_wants_force_register; - - // Attempt to use a user-provided gateway, if possible - let user_chosen_gateway_id = args.gateway; - let selection_spec = GatewaySelectionSpecification::new( - user_chosen_gateway_id.map(|id| id.to_base58_string()), - Some(args.latency_based_selection), - false, - ); - - // Load and potentially override config - let config = override_config(Config::new(id), OverrideConfig::from(args.clone())); - - // 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 key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone()); - let details_store = - OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details); - - let available_gateways = if let Some(hardcoded_topology) = args - .custom_mixnet - .map(NymTopology::new_from_file) - .transpose()? - { - // hardcoded_topology - hardcoded_topology.get_gateways() - } else { - let mut rng = rand::thread_rng(); - current_gateways(&mut rng, &config.base.client.nym_api_urls).await? - }; - - let gateway_setup = GatewaySetup::New { - specification: selection_spec, - available_gateways, - overwrite_data: register_gateway, - }; - - let init_details = - nym_client_core::init::setup_gateway(gateway_setup, &key_store, &details_store) - .await - .tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?; - - let config_save_location = config.default_location(); - config.save_to_default_location().tap_err(|_| { - log::error!("Failed to save the config file"); - })?; - eprintln!( - "Saved configuration file to {}", - config_save_location.display() - ); - - let address = init_details.client_address()?; - - eprintln!("Client configuration completed.\n"); - - let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else { - return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?; - }; - let init_results = InitResults::new(&config, &address, &gateway_details); - println!("{}", args.output.format(&init_results)); + let init_results = InitResults::new(res); + println!("{}", output.format(&init_results)); Ok(()) } diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index 7ea0469c74..a3fa47e4a0 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" rust-version = "1.56" [dependencies] -clap = { version = "4.0", features = ["cargo", "derive"] } +clap = { workspace = true, features = ["cargo", "derive"] } lazy_static = "1.4.0" log = { workspace = true } pretty_env_logger = "0.4" @@ -21,7 +21,7 @@ url = { workspace = true } # internal nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] } -nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage"] } +nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "cli"] } nym-coconut-interface = { path = "../../common/coconut-interface" } nym-config = { path = "../../common/config" } nym-credentials = { path = "../../common/credentials" } diff --git a/clients/socks5/src/commands/init.rs b/clients/socks5/src/commands/init.rs index 3c6a2a943f..d0c7e5e842 100644 --- a/clients/socks5/src/commands/init.rs +++ b/clients/socks5/src/commands/init.rs @@ -11,27 +11,50 @@ use crate::{ }; use clap::Args; use nym_bin_common::output_format::OutputFormat; -use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails; -use nym_client_core::client::key_manager::persistence::OnDiskKeys; -use nym_client_core::config::GatewayEndpointConfig; -use nym_client_core::error::ClientCoreError; -use nym_client_core::init::helpers::current_gateways; -use nym_client_core::init::types::{GatewayDetails, GatewaySelectionSpecification, GatewaySetup}; -use nym_crypto::asymmetric::identity; +use nym_client_core::init::client_init::{ + initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient, +}; use nym_sphinx::addressing::clients::Recipient; -use nym_topology::NymTopology; use serde::Serialize; use std::fmt::Display; +use std::fs; use std::net::{IpAddr, SocketAddr}; use std::path::PathBuf; -use std::{fs, io}; -use tap::TapFallible; + +struct Socks5ClientInit; + +impl InitialisableClient for Socks5ClientInit { + const NAME: &'static str = "socks5"; + type Error = Socks5ClientError; + type InitArgs = Init; + type Config = Config; + + fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> { + try_upgrade_config(id) + } + + fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> { + fs::create_dir_all(default_data_directory(id))?; + fs::create_dir_all(default_config_directory(id))?; + Ok(()) + } + + fn default_config_path(id: &str) -> PathBuf { + default_config_filepath(id) + } + + fn construct_config(init_args: &Self::InitArgs) -> Self::Config { + override_config( + Config::new(&init_args.common_args.id, &init_args.provider.to_string()), + OverrideConfig::from(init_args.clone()), + ) + } +} #[derive(Args, Clone)] pub(crate) struct Init { - /// Id of the nym-mixnet-client we want to create config for. - #[clap(long)] - id: String, + #[command(flatten)] + common_args: CommonClientInitArgs, /// Address of the socks5 provider to send messages to. #[clap(long)] @@ -46,34 +69,6 @@ pub(crate) struct Init { #[clap(long, alias = "use_anonymous_sender_tag")] use_reply_surbs: Option, - /// Id of the gateway we are going to connect to. - #[clap(long)] - gateway: Option, - - /// Specifies whether the new gateway should be determined based by latency as opposed to being chosen - /// uniformly. - #[clap(long, conflicts_with = "gateway")] - latency_based_selection: bool, - - /// Force register gateway. WARNING: this will overwrite any existing keys for the given id, - /// potentially causing loss of access. - #[clap(long)] - force_register_gateway: bool, - - /// Comma separated list of rest endpoints of the nyxd validators - #[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)] - nyxd_urls: Option>, - - /// Comma separated list of rest endpoints of the API validators - #[clap( - long, - alias = "api_validators", - value_delimiter = ',', - group = "network" - )] - // the alias here is included for backwards compatibility (1.1.4 and before) - nym_apis: Option>, - /// Port for the socket to listen on in all subsequent runs #[clap(short, long)] port: Option, @@ -82,10 +77,6 @@ pub(crate) struct Init { #[clap(long)] host: Option, - /// Path to .json file containing custom network specification. - #[clap(long, group = "network", hide = true)] - custom_mixnet: Option, - /// Mostly debug-related option to increase default traffic rate so that you would not need to /// modify config post init #[clap(long, hide = true)] @@ -95,19 +86,20 @@ pub(crate) struct Init { #[clap(long, hide = true)] no_cover: bool, - /// Set this client to work in a enabled credentials mode that would attempt to use gateway - /// with bandwidth credential requirement. - #[clap(long, hide = true)] - enabled_credentials_mode: Option, - #[clap(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, } +impl AsRef for Init { + fn as_ref(&self) -> &CommonClientInitArgs { + &self.common_args + } +} + impl From for OverrideConfig { fn from(init_config: Init) -> Self { OverrideConfig { - nym_apis: init_config.nym_apis, + nym_apis: init_config.common_args.nym_apis, ip: init_config.host, port: init_config.port, use_anonymous_replies: init_config.use_reply_surbs, @@ -115,8 +107,8 @@ impl From for OverrideConfig { no_cover: init_config.no_cover, geo_routing: None, medium_toggle: false, - nyxd_urls: init_config.nyxd_urls, - enabled_credentials_mode: init_config.enabled_credentials_mode, + nyxd_urls: init_config.common_args.nyxd_urls, + enabled_credentials_mode: init_config.common_args.enabled_credentials_mode, outfox: false, } } @@ -131,15 +123,11 @@ pub struct InitResults { } impl InitResults { - fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self { + fn new(res: InitResultsWithConfig) -> Self { Self { - client_core: nym_client_core::init::types::InitResults::new( - &config.core.base, - address, - gateway, - ), - socks5_listening_address: config.core.socks5.bind_adddress, - client_address: address.to_string(), + client_address: res.init_results.address.to_string(), + client_core: res.init_results, + socks5_listening_address: res.config.core.socks5.bind_adddress, } } } @@ -156,101 +144,14 @@ impl Display for InitResults { } } -fn init_paths(id: &str) -> io::Result<()> { - fs::create_dir_all(default_data_directory(id))?; - fs::create_dir_all(default_config_directory(id)) -} - pub(crate) async fn execute(args: Init) -> Result<(), Socks5ClientError> { eprintln!("Initialising client..."); - let id = &args.id; - let provider_address = &args.provider; + let output = args.output; + let res = initialise_client::(args).await?; - let already_init = if default_config_filepath(id).exists() { - // in case we're using old config, try to upgrade it - // (if we're using the current version, it's a no-op) - try_upgrade_config(id)?; - eprintln!("SOCKS5 client \"{id}\" was already initialised before"); - true - } else { - init_paths(id)?; - false - }; - - // Usually you only register with the gateway on the first init, however you can force - // re-registering if wanted. - let user_wants_force_register = args.force_register_gateway; - if user_wants_force_register { - eprintln!("Instructed to force registering gateway. This might overwrite keys!"); - } - - // If the client was already initialized, don't generate new keys and don't re-register with - // the gateway (because this would create a new shared key). - // Unless the user really wants to. - let register_gateway = !already_init || user_wants_force_register; - - // Attempt to use a user-provided gateway, if possible - let user_chosen_gateway_id = args.gateway; - let selection_spec = GatewaySelectionSpecification::new( - user_chosen_gateway_id.map(|id| id.to_base58_string()), - Some(args.latency_based_selection), - false, - ); - - // Load and potentially override config - let config = override_config( - Config::new(id, &provider_address.to_string()), - OverrideConfig::from(args.clone()), - ); - - // 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 key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone()); - let details_store = - OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details); - - let available_gateways = if let Some(hardcoded_topology) = args - .custom_mixnet - .map(NymTopology::new_from_file) - .transpose()? - { - // hardcoded_topology - hardcoded_topology.get_gateways() - } else { - let mut rng = rand::thread_rng(); - current_gateways(&mut rng, &config.core.base.client.nym_api_urls).await? - }; - - let gateway_setup = GatewaySetup::New { - specification: selection_spec, - available_gateways, - overwrite_data: register_gateway, - }; - - let init_details = - nym_client_core::init::setup_gateway(gateway_setup, &key_store, &details_store) - .await - .tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?; - - // TODO: ask the service provider we specified for its interface version and set it in the config - - let config_save_location = config.default_location(); - config.save_to_default_location().tap_err(|_| { - log::error!("Failed to save the config file"); - })?; - eprintln!( - "Saved configuration file to {}", - config_save_location.display() - ); - - let address = init_details.client_address()?; - - let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else { - return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?; - }; - let init_results = InitResults::new(&config, &address, &gateway_details); - println!("{}", args.output.format(&init_results)); + let init_results = InitResults::new(res); + println!("{}", output.format(&init_results)); Ok(()) } diff --git a/clients/socks5/src/config/mod.rs b/clients/socks5/src/config/mod.rs index 8a8681c50f..9f4c23720f 100644 --- a/clients/socks5/src/config/mod.rs +++ b/clients/socks5/src/config/mod.rs @@ -15,7 +15,9 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; pub use crate::config::persistence::SocksClientPaths; +use nym_client_core::config::disk_persistence::CommonClientPaths; pub use nym_client_core::config::Config as BaseClientConfig; +use nym_client_core::init::client_init::ClientConfig; pub use nym_socks5_client_core::config::Config as CoreConfig; pub mod old_config_v1_1_13; @@ -69,6 +71,24 @@ impl NymConfigTemplate for Config { } } +impl ClientConfig for Config { + fn common_paths(&self) -> &CommonClientPaths { + &self.storage_paths.common_paths + } + + fn core_config(&self) -> &BaseClientConfig { + &self.core.base + } + + fn default_store_location(&self) -> PathBuf { + self.default_location() + } + + fn save_to>(&self, path: P) -> io::Result<()> { + save_formatted_config_to_file(self, path) + } +} + impl Config { pub fn new>(id: S, provider_mix_address: S) -> Self { Config { diff --git a/common/bin-common/Cargo.toml b/common/bin-common/Cargo.toml index 7f9ae7fe89..9ed9958a07 100644 --- a/common/bin-common/Cargo.toml +++ b/common/bin-common/Cargo.toml @@ -9,7 +9,7 @@ repository = { workspace = true } [dependencies] atty = "0.2" -clap = { version = "4.0", features = ["derive"] } +clap = { workspace = true, features = ["derive"] } clap_complete = "4.0" clap_complete_fig = "4.0" log = { workspace = true } diff --git a/common/client-core/Cargo.toml b/common/client-core/Cargo.toml index cd17b7e979..ccd2113a28 100644 --- a/common/client-core/Cargo.toml +++ b/common/client-core/Cargo.toml @@ -11,6 +11,7 @@ rust-version = "1.66" async-trait = { workspace = true } base64 = "0.21.2" cfg-if = "1.0.0" +clap = { workspace = true, optional = true } dashmap = { workspace = true } dirs = "4.0" futures = { workspace = true } @@ -92,6 +93,7 @@ sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macro [features] default = [] +cli = ["clap"] fs-surb-storage = ["sqlx"] wasm = ["nym-gateway-client/wasm"] diff --git a/common/client-core/src/error.rs b/common/client-core/src/error.rs index 8118936730..8a193d8a75 100644 --- a/common/client-core/src/error.rs +++ b/common/client-core/src/error.rs @@ -8,6 +8,7 @@ use nym_topology::gateway::GatewayConversionError; use nym_topology::NymTopologyError; use nym_validator_client::ValidatorClientError; use std::error::Error; +use std::path::PathBuf; #[derive(thiserror::Error, Debug)] pub enum ClientCoreError { @@ -132,6 +133,26 @@ pub enum ClientCoreError { #[error("the specified gateway '{gateway}' does not support the wss protocol")] UnsupportedWssProtocol { gateway: String }, + + #[error( + "failed to load custom topology using path '{}'. detailed message: {source}", file_path.display() + )] + CustomTopologyLoadFailure { + file_path: PathBuf, + #[source] + source: std::io::Error, + }, + + #[error( + "failed to save config file for client-{typ} id {id} using path '{}'. detailed message: {source}", path.display() + )] + ConfigSaveFailure { + typ: String, + id: String, + path: PathBuf, + #[source] + source: std::io::Error, + }, } /// Set of messages that the client can send to listeners via the task manager diff --git a/common/client-core/src/init/client_init.rs b/common/client-core/src/init/client_init.rs new file mode 100644 index 0000000000..42f9987f44 --- /dev/null +++ b/common/client-core/src/init/client_init.rs @@ -0,0 +1,201 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::disk_persistence::CommonClientPaths; +use crate::error::ClientCoreError; +use crate::{ + client::{ + base_client::storage::gateway_details::OnDiskGatewayDetails, + key_manager::persistence::OnDiskKeys, + }, + init::types::{GatewayDetails, GatewaySelectionSpecification, GatewaySetup, InitResults}, +}; +use log::info; +use nym_crypto::asymmetric::identity; +use nym_topology::NymTopology; +use std::path::{Path, PathBuf}; + +pub trait InitialisableClient { + const NAME: &'static str; + type Error: From; + type InitArgs: AsRef; + type Config: ClientConfig; + + fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error>; + + fn initialise_storage_paths(id: &str) -> Result<(), Self::Error>; + + fn default_config_path(id: &str) -> PathBuf; + + fn construct_config(init_args: &Self::InitArgs) -> Self::Config; +} + +pub trait ClientConfig { + fn common_paths(&self) -> &CommonClientPaths; + + fn core_config(&self) -> &crate::config::Config; + + fn default_store_location(&self) -> PathBuf; + + fn save_to>(&self, path: P) -> std::io::Result<()>; +} + +#[cfg_attr(feature = "cli", derive(clap::Args))] +#[derive(Debug, Clone)] +pub struct CommonClientInitArgs { + /// Id of client we want to create config for. + #[cfg_attr(feature = "cli", clap(long))] + pub id: String, + + /// Id of the gateway we are going to connect to. + #[cfg_attr(feature = "cli", clap(long))] + pub gateway: Option, + + /// Specifies whether the new gateway should be determined based by latency as opposed to being chosen + /// uniformly. + #[cfg_attr(feature = "cli", clap(long, conflicts_with = "gateway"))] + pub latency_based_selection: bool, + + /// Force register gateway. WARNING: this will overwrite any existing keys for the given id, + /// potentially causing loss of access. + #[cfg_attr(feature = "cli", clap(long))] + pub force_register_gateway: bool, + + /// Comma separated list of rest endpoints of the nyxd validators + #[cfg_attr( + feature = "cli", + clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true) + )] + pub nyxd_urls: Option>, + + /// Comma separated list of rest endpoints of the API validators + #[cfg_attr( + feature = "cli", + clap( + long, + alias = "api_validators", + value_delimiter = ',', + group = "network" + ) + )] + pub nym_apis: Option>, + + /// Path to .json file containing custom network specification. + #[cfg_attr(feature = "cli", clap(long, group = "network", hide = true))] + pub custom_mixnet: Option, + + /// Set this client to work in a enabled credentials mode that would attempt to use gateway + /// with bandwidth credential requirement. + #[cfg_attr(feature = "cli", clap(long, hide = true))] + pub enabled_credentials_mode: Option, +} + +pub struct InitResultsWithConfig { + pub config: T, + pub init_results: InitResults, +} + +pub async fn initialise_client( + init_args: C::InitArgs, +) -> Result, C::Error> +where + C: InitialisableClient, +{ + info!("initialising {} client", C::NAME); + + let common_args = init_args.as_ref(); + let id = &common_args.id; + + let already_init = if C::default_config_path(id).exists() { + // in case we're using old config, try to upgrade it + // (if we're using the current version, it's a no-op) + C::try_upgrade_outdated_config(id)?; + eprintln!("{} client \"{id}\" was already initialised before", C::NAME); + true + } else { + C::initialise_storage_paths(id)?; + false + }; + + // Usually you only register with the gateway on the first init, however you can force + // re-registering if wanted. + let user_wants_force_register = common_args.force_register_gateway; + if user_wants_force_register { + eprintln!("Instructed to force registering gateway. This might overwrite keys!"); + } + + // If the client was already initialized, don't generate new keys and don't re-register with + // the gateway (because this would create a new shared key). + // Unless the user really wants to. + let register_gateway = !already_init || user_wants_force_register; + + // Attempt to use a user-provided gateway, if possible + let user_chosen_gateway_id = common_args.gateway; + let selection_spec = GatewaySelectionSpecification::new( + user_chosen_gateway_id.map(|id| id.to_base58_string()), + Some(common_args.latency_based_selection), + false, + ); + + // Load and potentially override config + let config = C::construct_config(&init_args); + let paths = config.common_paths(); + let core = config.core_config(); + + // 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 key_store = OnDiskKeys::new(paths.keys.clone()); + let details_store = OnDiskGatewayDetails::new(&paths.gateway_details); + + let available_gateways = if let Some(custom_mixnet) = common_args.custom_mixnet.as_ref() { + let hardcoded_topology = NymTopology::new_from_file(custom_mixnet).map_err(|source| { + ClientCoreError::CustomTopologyLoadFailure { + file_path: custom_mixnet.clone(), + source, + } + })?; + hardcoded_topology.get_gateways() + } else { + let mut rng = rand::thread_rng(); + crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls).await? + }; + + let gateway_setup = GatewaySetup::New { + specification: selection_spec, + available_gateways, + overwrite_data: register_gateway, + }; + + let init_details = + crate::init::setup_gateway(gateway_setup, &key_store, &details_store).await?; + + // TODO: ask the service provider we specified for its interface version and set it in the config + + let config_save_location = config.default_store_location(); + if let Err(err) = config.save_to(&config_save_location) { + return Err(ClientCoreError::ConfigSaveFailure { + typ: C::NAME.to_string(), + id: id.to_string(), + path: config_save_location, + source: err, + } + .into()); + } + + eprintln!( + "Saved configuration file to {}", + config_save_location.display() + ); + + let address = init_details.client_address()?; + + let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else { + return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?; + }; + let init_results = InitResults::new(config.core_config(), address, &gateway_details); + + Ok(InitResultsWithConfig { + config, + init_results, + }) +} diff --git a/common/client-core/src/init/mod.rs b/common/client-core/src/init/mod.rs index 395fdd45c2..ab153378c2 100644 --- a/common/client-core/src/init/mod.rs +++ b/common/client-core/src/init/mod.rs @@ -24,6 +24,7 @@ use serde::de::DeserializeOwned; use serde::Serialize; use std::sync::Arc; +pub mod client_init; pub mod helpers; pub mod types; diff --git a/common/client-core/src/init/types.rs b/common/client-core/src/init/types.rs index 3e8a88d133..bf9df9edb2 100644 --- a/common/client-core/src/init/types.rs +++ b/common/client-core/src/init/types.rs @@ -296,16 +296,17 @@ impl GatewaySetup { /// Struct describing the results of the client initialization procedure. #[derive(Debug, Serialize)] pub struct InitResults { - version: String, - id: String, - identity_key: String, - encryption_key: String, - gateway_id: String, - gateway_listener: String, + pub version: String, + pub id: String, + pub identity_key: String, + pub encryption_key: String, + pub gateway_id: String, + pub gateway_listener: String, + pub address: Recipient, } impl InitResults { - pub fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self { + pub fn new(config: &Config, address: Recipient, gateway: &GatewayEndpointConfig) -> Self { Self { version: config.client.version.clone(), id: config.client.id.clone(), @@ -313,6 +314,7 @@ impl InitResults { encryption_key: address.encryption_key().to_base58_string(), gateway_id: gateway.gateway_id.clone(), gateway_listener: gateway.gateway_listener.clone(), + address, } } } diff --git a/common/commands/Cargo.toml b/common/commands/Cargo.toml index df6860641e..e538a7ed31 100644 --- a/common/commands/Cargo.toml +++ b/common/commands/Cargo.toml @@ -11,7 +11,7 @@ bip39 = { workspace = true } bs58 = "0.4" comfy-table = "6.0.0" cfg-if = "1.0.0" -clap = { version = "4.0", features = ["derive"] } +clap = { workspace = true, features = ["derive"] } cw-utils = { workspace = true } handlebars = "3.0.1" humantime-serde = "1.0" diff --git a/ephemera/Cargo.toml b/ephemera/Cargo.toml index 63ccaa9ab7..f0af6af3a9 100644 --- a/ephemera/Cargo.toml +++ b/ephemera/Cargo.toml @@ -21,7 +21,7 @@ bs58 = "0.4.0" bytes = "1.3.0" cfg-if = "1.0.0" chrono = { version = "0.4.24", default-features = false, features = ["clock"] } -clap = { version = "4.0.32", features = ["derive"] } +clap = { workspace = true, features = ["derive"] } config = { version = "0.13", default-features = false, features = ["toml"] } digest = "0.10.6" dirs = "5.0.0" diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index 935a76cb52..16c55da6c5 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] chrono = { version = "0.4.31", features = ["serde"] } -clap = { version = "4.0", features = ["cargo", "derive"] } +clap = { workspace = true, features = ["cargo", "derive"] } dotenvy = "0.15.6" humantime-serde = "1.0" isocountry = "0.3.2" diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index c1d6503199..777032d128 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -20,7 +20,7 @@ async-trait = { workspace = true } atty = "0.2" bip39 = { workspace = true } bs58 = "0.4.0" -clap = { version = "4.0", features = ["cargo", "derive"] } +clap = { workspace = true, features = ["cargo", "derive"] } colored = "2.0" dashmap = { workspace = true } dirs = "4.0" diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index 39061c4ca4..751aa06e04 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -19,7 +19,7 @@ rust-version = "1.58.1" axum = { workspace = true } anyhow = "1.0.40" bs58 = "0.4.0" -clap = { version = "4.0", features = ["cargo", "derive"] } +clap = { workspace = true, features = ["cargo", "derive"] } colored = "2.0" cupid = "0.6.1" dirs = "4.0" diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 4691bf250f..85c20d6e59 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -19,7 +19,7 @@ async-trait = { workspace = true } bs58 = { version = "0.4.0" } bip39 = { workspace = true } cfg-if = "1.0" -clap = { version = "4.0", features = ["cargo", "derive"] } +clap = { workspace = true, features = ["cargo", "derive"] } console-subscriber = { version = "0.1.1", optional = true } # validator-api needs to be built with RUSTFLAGS="--cfg tokio_unstable" dirs = "4.0" futures = { workspace = true } diff --git a/nym-connect/desktop/Cargo.lock b/nym-connect/desktop/Cargo.lock index 6dbf35cc44..e3a9fce4c2 100644 --- a/nym-connect/desktop/Cargo.lock +++ b/nym-connect/desktop/Cargo.lock @@ -126,16 +126,15 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] @@ -165,9 +164,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.2" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -868,20 +867,19 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.21" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.21" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", @@ -910,9 +908,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.12" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -922,9 +920,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "cocoa" diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index a2922d8391..ec32ea6a33 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -108,16 +108,15 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] @@ -147,9 +146,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.2" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -662,20 +661,19 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.21" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.21" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", @@ -704,9 +702,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.12" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -716,9 +714,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "cocoa" @@ -3431,6 +3429,15 @@ dependencies = [ "nym-contracts-common", ] +[[package]] +name = "nym-exit-policy" +version = "0.1.0" +dependencies = [ + "serde", + "thiserror", + "tracing", +] + [[package]] name = "nym-group-contract-common" version = "0.1.0" @@ -3510,6 +3517,7 @@ dependencies = [ "base64 0.21.4", "nym-bin-common", "nym-crypto", + "nym-exit-policy", "nym-wireguard-types", "schemars", "serde", diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 42c54bc0b2..a13ee1fed4 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -17,7 +17,7 @@ path = "src/lib.rs" [dependencies] async-trait = { workspace = true } bs58 = "0.4.0" -clap = {version = "4.0", features = ["cargo", "derive"]} +clap = { workspace = true, features = ["cargo", "derive"]} dirs = "4.0" futures = { workspace = true } humantime-serde = "1.1.1" @@ -41,7 +41,7 @@ url = { workspace = true } # internal async-file-watcher = { path = "../../common/async-file-watcher" } nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] } -nym-client-core = { path = "../../common/client-core" } +nym-client-core = { path = "../../common/client-core", features = ["cli"] } nym-client-websocket-requests = { path = "../../clients/native/websocket-requests" } nym-config = { path = "../../common/config" } nym-credential-storage = { path = "../../common/credential-storage" } diff --git a/service-providers/network-requester/src/cli/init.rs b/service-providers/network-requester/src/cli/init.rs index d6c1960da6..35ddedc279 100644 --- a/service-providers/network-requester/src/cli/init.rs +++ b/service-providers/network-requester/src/cli/init.rs @@ -10,27 +10,48 @@ use crate::{ }; use clap::Args; use nym_bin_common::output_format::OutputFormat; -use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails; -use nym_client_core::client::key_manager::persistence::OnDiskKeys; -use nym_client_core::config::GatewayEndpointConfig; -use nym_client_core::error::ClientCoreError; -use nym_client_core::init::helpers::current_gateways; -use nym_client_core::init::types::GatewaySetup; -use nym_client_core::init::types::{GatewayDetails, GatewaySelectionSpecification}; -use nym_crypto::asymmetric::identity; -use nym_sdk::mixnet::NymTopology; -use nym_sphinx::addressing::clients::Recipient; +use nym_client_core::init::client_init::{ + initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient, +}; use serde::Serialize; use std::fmt::Display; +use std::fs; use std::path::PathBuf; -use std::{fs, io}; -use tap::TapFallible; + +struct NetworkRequesterInit; + +impl InitialisableClient for NetworkRequesterInit { + const NAME: &'static str = "network requester"; + type Error = NetworkRequesterError; + type InitArgs = Init; + type Config = Config; + + fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> { + try_upgrade_config(id) + } + + fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> { + fs::create_dir_all(default_data_directory(id))?; + fs::create_dir_all(default_config_directory(id))?; + Ok(()) + } + + fn default_config_path(id: &str) -> PathBuf { + default_config_filepath(id) + } + + fn construct_config(init_args: &Self::InitArgs) -> Self::Config { + override_config( + Config::new(&init_args.common_args.id), + OverrideConfig::from(init_args.clone()), + ) + } +} #[derive(Args, Clone)] pub(crate) struct Init { - /// Id of the nym-mixnet-client we want to create config for. - #[clap(long)] - id: String, + #[command(flatten)] + common_args: CommonClientInitArgs, /// Specifies whether this network requester should run in 'open-proxy' mode #[clap(long)] @@ -45,43 +66,6 @@ pub(crate) struct Init { #[clap(long)] statistics_recipient: Option, - /// Id of the gateway we are going to connect to. - #[clap(long)] - gateway: Option, - - /// Specifies whether the new gateway should be determined based by latency as opposed to being chosen - /// uniformly. - #[clap(long, conflicts_with = "gateway")] - latency_based_selection: bool, - - /// Force register gateway. WARNING: this will overwrite any existing keys for the given id, - /// potentially causing loss of access. - #[clap(long)] - force_register_gateway: bool, - - /// Comma separated list of rest endpoints of the nyxd validators - #[clap(long, alias = "nymd_validators", value_delimiter = ',')] - nyxd_urls: Option>, - - /// Comma separated list of rest endpoints of the API validators - #[clap( - long, - alias = "api_validators", - value_delimiter = ',', - group = "network" - )] - // the alias here is included for backwards compatibility (1.1.4 and before) - nym_apis: Option>, - - /// Path to .json file containing custom network specification. - #[clap(long, group = "network", hide = true)] - custom_mixnet: Option, - - /// Set this client to work in a enabled credentials mode that would attempt to use gateway - /// with bandwidth credential requirement. - #[clap(long)] - enabled_credentials_mode: Option, - /// Specifies whether this network requester will run using the default ExitPolicy /// as opposed to the allow list. /// Note: this setting will become the default in the future releases. @@ -95,20 +79,26 @@ pub(crate) struct Init { impl From for OverrideConfig { fn from(init_config: Init) -> Self { OverrideConfig { - nym_apis: init_config.nym_apis, + nym_apis: init_config.common_args.nym_apis, fastmode: false, no_cover: false, medium_toggle: false, - nyxd_urls: init_config.nyxd_urls, - enabled_credentials_mode: init_config.enabled_credentials_mode, + nyxd_urls: init_config.common_args.nyxd_urls, + enabled_credentials_mode: init_config.common_args.enabled_credentials_mode, enable_exit_policy: init_config.with_exit_policy, open_proxy: init_config.open_proxy, - enable_statistics: init_config.enabled_credentials_mode, + enable_statistics: init_config.enable_statistics, statistics_recipient: init_config.statistics_recipient, } } } +impl AsRef for Init { + fn as_ref(&self) -> &CommonClientInitArgs { + &self.common_args + } +} + #[derive(Debug, Serialize)] pub struct InitResults { #[serde(flatten)] @@ -117,14 +107,10 @@ pub struct InitResults { } impl InitResults { - fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self { + fn new(res: InitResultsWithConfig) -> Self { Self { - client_core: nym_client_core::init::types::InitResults::new( - &config.base, - address, - gateway, - ), - client_address: address.to_string(), + client_address: res.init_results.address.to_string(), + client_core: res.init_results, } } } @@ -140,99 +126,14 @@ impl Display for InitResults { } } -fn init_paths(id: &str) -> io::Result<()> { - fs::create_dir_all(default_data_directory(id))?; - fs::create_dir_all(default_config_directory(id)) -} +pub(crate) async fn execute(args: Init) -> Result<(), NetworkRequesterError> { + eprintln!("Initialising client..."); -pub(crate) async fn execute(args: &Init) -> Result<(), NetworkRequesterError> { - log::info!("Initialising client..."); + let output = args.output; + let res = initialise_client::(args).await?; - let id = &args.id; - - let already_init = if default_config_filepath(id).exists() { - // in case we're using old config, try to upgrade it - // (if we're using the current version, it's a no-op) - try_upgrade_config(id)?; - log::info!("Client \"{id}\" was already initialised before"); - true - } else { - init_paths(&args.id)?; - false - }; - - // Usually you only register with the gateway on the first init, however you can force - // re-registering if wanted. - let user_wants_force_register = args.force_register_gateway; - if user_wants_force_register { - log::warn!("Instructed to force registering gateway. This might overwrite keys!"); - } - - // If the client was already initialized, don't generate new keys and don't re-register with - // the gateway (because this would create a new shared key). - // Unless the user really wants to. - let register_gateway = !already_init || user_wants_force_register; - - // Attempt to use a user-provided gateway, if possible - let user_chosen_gateway_id = args.gateway; - let selection_spec = GatewaySelectionSpecification::new( - user_chosen_gateway_id.map(|id| id.to_base58_string()), - Some(args.latency_based_selection), - false, - ); - - // Load and potentially override config - let config = override_config(Config::new(id), OverrideConfig::from(args.clone())); - log::debug!("Using config: {:#?}", config); - - // 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 key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone()); - let details_store = - OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details); - - let available_gateways = if let Some(hardcoded_topology) = args - .custom_mixnet - .as_ref() - .map(NymTopology::new_from_file) - .transpose()? - { - // hardcoded_topology - hardcoded_topology.get_gateways() - } else { - let mut rng = rand::thread_rng(); - current_gateways(&mut rng, &config.base.client.nym_api_urls).await? - }; - - let gateway_setup = GatewaySetup::New { - specification: selection_spec, - available_gateways, - overwrite_data: register_gateway, - }; - - let init_details = - nym_client_core::init::setup_gateway(gateway_setup, &key_store, &details_store) - .await - .tap_err(|err| log::error!("Failed to setup gateway\nError: {err}"))?; - - let config_save_location = config.default_location(); - config.save_to_default_location().tap_err(|_| { - log::error!("Failed to save the config file"); - })?; - log::info!( - "Saved configuration file to {}", - config_save_location.display() - ); - - let address = init_details.client_address()?; - - log::info!("Client configuration completed.\n"); - - let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else { - return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?; - }; - let init_results = InitResults::new(&config, &address, &gateway_details); - println!("{}", args.output.format(&init_results)); + let init_results = InitResults::new(res); + println!("{}", output.format(&init_results)); Ok(()) } diff --git a/service-providers/network-requester/src/cli/mod.rs b/service-providers/network-requester/src/cli/mod.rs index c090912743..fcc2fe6750 100644 --- a/service-providers/network-requester/src/cli/mod.rs +++ b/service-providers/network-requester/src/cli/mod.rs @@ -154,7 +154,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), NetworkRequesterError> { let bin_name = "nym-network-requester"; match args.command { - Commands::Init(m) => init::execute(&m).await?, + Commands::Init(m) => init::execute(m).await?, Commands::Run(m) => run::execute(&m).await?, Commands::Sign(m) => sign::execute(&m).await?, Commands::BuildInfo(m) => build_info::execute(m), diff --git a/service-providers/network-requester/src/config/mod.rs b/service-providers/network-requester/src/config/mod.rs index 81ace42e36..8fee1c6725 100644 --- a/service-providers/network-requester/src/config/mod.rs +++ b/service-providers/network-requester/src/config/mod.rs @@ -17,8 +17,10 @@ use std::str::FromStr; use std::time::Duration; use url::Url; +use nym_client_core::config::disk_persistence::CommonClientPaths; pub use nym_client_core::config::Config as BaseClientConfig; pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig}; +use nym_client_core::init::client_init::ClientConfig; use nym_network_defaults::mainnet; use nym_sphinx::params::PacketSize; @@ -83,6 +85,24 @@ impl NymConfigTemplate for Config { } } +impl ClientConfig for Config { + fn common_paths(&self) -> &CommonClientPaths { + &self.storage_paths.common_paths + } + + fn core_config(&self) -> &BaseClientConfig { + &self.base + } + + fn default_store_location(&self) -> PathBuf { + self.default_location() + } + + fn save_to>(&self, path: P) -> io::Result<()> { + save_formatted_config_to_file(self, path) + } +} + impl Config { pub fn new>(id: S) -> Self { Config { diff --git a/tools/internal/sdk-version-bump/Cargo.toml b/tools/internal/sdk-version-bump/Cargo.toml index 07bb45a875..b4ab71b34f 100644 --- a/tools/internal/sdk-version-bump/Cargo.toml +++ b/tools/internal/sdk-version-bump/Cargo.toml @@ -13,7 +13,7 @@ license.workspace = true [dependencies] anyhow = { workspace = true } cargo-edit = "0.11.0" -clap = { version = "4.3.19", features = ["derive", "string"] } +clap = { workspace = true, features = ["derive", "string"] } semver = "1.0.18" serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index def3dc32eb..5640b96840 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] base64 = "0.13.0" bs58 = "0.4" -clap = { version = "4.0", features = ["derive"] } +clap = { workspace = true, features = ["derive"] } clap_complete = "4.0" clap_complete_fig = "4.0" dotenvy = "0.15.6" diff --git a/tools/nym-nr-query/Cargo.toml b/tools/nym-nr-query/Cargo.toml index 9034b536db..804577e583 100644 --- a/tools/nym-nr-query/Cargo.toml +++ b/tools/nym-nr-query/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] anyhow = { workspace = true } -clap = {version = "4.0", features = ["cargo", "derive"]} +clap = { workspace = true, features = ["cargo", "derive"]} log = { workspace = true } nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] } nym-network-defaults = { path = "../../common/network-defaults" } From 4716d278ce0f9fa474e3a0b0a13d764494b6b58e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 30 Oct 2023 16:26:37 +0000 Subject: [PATCH 126/236] combine client run args --- clients/native/src/commands/run.rs | 61 ++++--------------- clients/socks5/src/commands/run.rs | 55 ++++------------- common/client-core/src/init/client_run.rs | 55 +++++++++++++++++ common/client-core/src/init/mod.rs | 1 + .../network-requester/src/cli/run.rs | 39 +++--------- 5 files changed, 88 insertions(+), 123 deletions(-) create mode 100644 common/client-core/src/init/client_run.rs diff --git a/clients/native/src/commands/run.rs b/clients/native/src/commands/run.rs index 8a61f8147c..7365b0773b 100644 --- a/clients/native/src/commands/run.rs +++ b/clients/native/src/commands/run.rs @@ -10,35 +10,14 @@ use crate::{ use clap::Args; use log::*; use nym_bin_common::version_checker::is_minor_version_compatible; -use nym_crypto::asymmetric::identity; +use nym_client_core::init::client_run::CommonClientRunArgs; use std::error::Error; use std::net::IpAddr; -use std::path::PathBuf; #[derive(Args, Clone)] pub(crate) struct Run { - /// Id of the nym-mixnet-client we want to run. - #[clap(long)] - id: String, - - /// Comma separated list of rest endpoints of the nyxd validators - #[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)] - nyxd_urls: Option>, - - /// Comma separated list of rest endpoints of the API validators - #[clap( - long, - alias = "api_validators", - value_delimiter = ',', - group = "network" - )] - // the alias here is included for backwards compatibility (1.1.4 and before) - nym_apis: Option>, - - /// Id of the gateway we want to connect to. If overridden, it is user's responsibility to - /// ensure prior registration happened - #[clap(long)] - gateway: Option, + #[command(flatten)] + common_args: CommonClientRunArgs, /// Whether to not start the websocket #[clap(long)] @@ -51,37 +30,19 @@ pub(crate) struct Run { /// Ip for the socket (if applicable) to listen for requests. #[clap(long)] host: Option, - - /// Path to .json file containing custom network specification. - #[clap(long, group = "network", hide = true)] - custom_mixnet: Option, - - /// Mostly debug-related option to increase default traffic rate so that you would not need to - /// modify config post init - #[clap(long, hide = true)] - fastmode: bool, - - /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) - #[clap(long, hide = true)] - no_cover: bool, - - /// Set this client to work in a enabled credentials mode that would attempt to use gateway - /// with bandwidth credential requirement. - #[clap(long, hide = true)] - enabled_credentials_mode: Option, } impl From for OverrideConfig { fn from(run_config: Run) -> Self { OverrideConfig { - nym_apis: run_config.nym_apis, + nym_apis: run_config.common_args.nym_apis, disable_socket: run_config.disable_socket, port: run_config.port, host: run_config.host, - fastmode: run_config.fastmode, - no_cover: run_config.no_cover, - nyxd_urls: run_config.nyxd_urls, - enabled_credentials_mode: run_config.enabled_credentials_mode, + fastmode: run_config.common_args.fastmode, + no_cover: run_config.common_args.no_cover, + nyxd_urls: run_config.common_args.nyxd_urls, + enabled_credentials_mode: run_config.common_args.enabled_credentials_mode, } } } @@ -106,9 +67,9 @@ fn version_check(cfg: &Config) -> bool { } pub(crate) async fn execute(args: Run) -> Result<(), Box> { - eprintln!("Starting client {}...", args.id); + eprintln!("Starting client {}...", args.common_args.id); - let mut config = try_load_current_config(&args.id)?; + let mut config = try_load_current_config(&args.common_args.id)?; config = override_config(config, OverrideConfig::from(args.clone())); if !version_check(&config) { @@ -116,7 +77,7 @@ pub(crate) async fn execute(args: Run) -> Result<(), Box, - /// Id of the gateway we want to connect to. If overridden, it is user's responsibility to - /// ensure prior registration happened - #[clap(long)] - gateway: Option, - - /// Comma separated list of rest endpoints of the nyxd validators - #[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)] - nyxd_urls: Option>, - - /// Comma separated list of rest endpoints of the Nym APIs - #[clap(long, value_delimiter = ',', group = "network")] - nym_apis: Option>, - /// Port for the socket to listen on #[clap(short, long)] port: Option, @@ -58,19 +43,6 @@ pub(crate) struct Run { #[clap(long)] host: Option, - /// Path to .json file containing custom network specification. - #[clap(long, group = "network", group = "routing", hide = true)] - custom_mixnet: Option, - - /// Mostly debug-related option to increase default traffic rate so that you would not need to - /// modify config post init - #[clap(long, hide = true)] - fastmode: bool, - - /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) - #[clap(long, hide = true)] - no_cover: bool, - /// Set geo-aware mixnode selection when sending mixnet traffic, for experiments only. #[clap(long, hide = true, value_parser = validate_country_group, group="routing")] geo_routing: Option, @@ -80,11 +52,6 @@ pub(crate) struct Run { #[clap(long, hide = true)] medium_toggle: bool, - /// Set this client to work in a enabled credentials mode that would attempt to use gateway - /// with bandwidth credential requirement. - #[clap(long, hide = true)] - enabled_credentials_mode: Option, - #[clap(long, hide = true, action)] outfox: bool, } @@ -92,16 +59,16 @@ pub(crate) struct Run { impl From for OverrideConfig { fn from(run_config: Run) -> Self { OverrideConfig { - nym_apis: run_config.nym_apis, + nym_apis: run_config.common_args.nym_apis, ip: run_config.host, port: run_config.port, use_anonymous_replies: run_config.use_anonymous_replies, - fastmode: run_config.fastmode, - no_cover: run_config.no_cover, + fastmode: run_config.common_args.fastmode, + no_cover: run_config.common_args.no_cover, geo_routing: run_config.geo_routing, medium_toggle: run_config.medium_toggle, - nyxd_urls: run_config.nyxd_urls, - enabled_credentials_mode: run_config.enabled_credentials_mode, + nyxd_urls: run_config.common_args.nyxd_urls, + enabled_credentials_mode: run_config.common_args.enabled_credentials_mode, outfox: run_config.outfox, } } @@ -136,9 +103,9 @@ fn version_check(cfg: &Config) -> bool { } pub(crate) async fn execute(args: Run) -> Result<(), Box> { - eprintln!("Starting client {}...", args.id); + eprintln!("Starting client {}...", args.common_args.id); - let mut config = try_load_current_config(&args.id)?; + let mut config = try_load_current_config(&args.common_args.id)?; config = override_config(config, OverrideConfig::from(args.clone())); if !version_check(&config) { @@ -149,7 +116,7 @@ pub(crate) async fn execute(args: Run) -> Result<(), Box +// SPDX-License-Identifier: Apache-2.0 + +use nym_crypto::asymmetric::identity; +use std::path::PathBuf; + +#[cfg_attr(feature = "cli", derive(clap::Args))] +#[derive(Debug, Clone)] +pub struct CommonClientRunArgs { + /// Id of client we want to create config for. + #[cfg_attr(feature = "cli", clap(long))] + pub id: String, + + /// Id of the gateway we want to connect to. If overridden, it is user's responsibility to + /// ensure prior registration happened + #[cfg_attr(feature = "cli", clap(long))] + pub gateway: Option, + + /// Comma separated list of rest endpoints of the nyxd validators + #[cfg_attr( + feature = "cli", + clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true) + )] + pub nyxd_urls: Option>, + + /// Comma separated list of rest endpoints of the API validators + #[cfg_attr( + feature = "cli", + clap( + long, + alias = "api_validators", + value_delimiter = ',', + group = "network" + ) + )] + pub nym_apis: Option>, + + /// Path to .json file containing custom network specification. + #[cfg_attr(feature = "cli", clap(long, group = "network", hide = true))] + pub custom_mixnet: Option, + + /// Set this client to work in a enabled credentials mode that would attempt to use gateway + /// with bandwidth credential requirement. + #[cfg_attr(feature = "cli", clap(long, hide = true))] + pub enabled_credentials_mode: Option, + + /// Mostly debug-related option to increase default traffic rate so that you would not need to + /// modify config post init + #[arg(long, hide = true, conflicts_with = "medium_toggle")] + pub fastmode: bool, + + /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) + #[arg(long, hide = true, conflicts_with = "medium_toggle")] + pub no_cover: bool, +} diff --git a/common/client-core/src/init/mod.rs b/common/client-core/src/init/mod.rs index ab153378c2..c8acabd838 100644 --- a/common/client-core/src/init/mod.rs +++ b/common/client-core/src/init/mod.rs @@ -25,6 +25,7 @@ use serde::Serialize; use std::sync::Arc; pub mod client_init; +pub mod client_run; pub mod helpers; pub mod types; diff --git a/service-providers/network-requester/src/cli/run.rs b/service-providers/network-requester/src/cli/run.rs index c55e37ca48..7ab10102b1 100644 --- a/service-providers/network-requester/src/cli/run.rs +++ b/service-providers/network-requester/src/cli/run.rs @@ -8,16 +8,15 @@ use crate::{ }; use clap::Args; use log::error; -use std::path::PathBuf; +use nym_client_core::init::client_run::CommonClientRunArgs; const ENABLE_STATISTICS: &str = "enable-statistics"; #[allow(clippy::struct_excessive_bools)] #[derive(Args, Clone)] pub(crate) struct Run { - /// Id of the nym-mixnet-client we want to run. - #[arg(long)] - id: String, + #[command(flatten)] + common_args: CommonClientRunArgs, /// Specifies whether this network requester should run in 'open-proxy' mode #[arg(long)] @@ -32,24 +31,6 @@ pub(crate) struct Run { #[arg(long)] statistics_recipient: Option, - /// Set this client to work in a enabled credentials mode that would attempt to use gateway - /// with bandwidth credential requirement. - #[arg(long)] - enabled_credentials_mode: Option, - - /// Path to .json file containing custom network specification. - #[clap(long, group = "network", hide = true)] - custom_mixnet: Option, - - /// Mostly debug-related option to increase default traffic rate so that you would not need to - /// modify config post init - #[arg(long, hide = true, conflicts_with = "medium_toggle")] - fastmode: bool, - - /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) - #[arg(long, hide = true, conflicts_with = "medium_toggle")] - no_cover: bool, - /// Enable medium mixnet traffic, for experiments only. /// This includes things like disabling cover traffic, no per hop delays, etc. #[arg( @@ -71,21 +52,21 @@ impl From for OverrideConfig { fn from(run_config: Run) -> Self { OverrideConfig { nym_apis: None, - fastmode: run_config.fastmode, - no_cover: run_config.no_cover, + fastmode: run_config.common_args.fastmode, + no_cover: run_config.common_args.no_cover, medium_toggle: run_config.medium_toggle, - nyxd_urls: None, - enabled_credentials_mode: run_config.enabled_credentials_mode, + nyxd_urls: run_config.common_args.nyxd_urls, + enabled_credentials_mode: run_config.common_args.enabled_credentials_mode, enable_exit_policy: run_config.with_exit_policy, open_proxy: run_config.open_proxy, - enable_statistics: run_config.enabled_credentials_mode, + enable_statistics: run_config.enable_statistics, statistics_recipient: run_config.statistics_recipient, } } } pub(crate) async fn execute(args: &Run) -> Result<(), NetworkRequesterError> { - let mut config = try_load_current_config(&args.id)?; + let mut config = try_load_current_config(&args.common_args.id)?; config = override_config(config, OverrideConfig::from(args.clone())); log::debug!("Using config: {:#?}", config); @@ -112,7 +93,7 @@ pub(crate) async fn execute(args: &Run) -> Result<(), NetworkRequesterError> { log::info!("Starting socks5 service provider"); let mut server = crate::core::NRServiceProviderBuilder::new(config); - if let Some(custom_mixnet) = &args.custom_mixnet { + if let Some(custom_mixnet) = &args.common_args.custom_mixnet { server = server.with_stored_topology(custom_mixnet)? } From b3c7801f73c12a4bff9ab2d3025c9a3a8cb6fa31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 30 Oct 2023 16:30:12 +0000 Subject: [PATCH 127/236] moved to different submodule --- clients/native/src/client/config/mod.rs | 4 ++-- clients/native/src/commands/init.rs | 2 +- clients/native/src/commands/run.rs | 2 +- clients/socks5/src/commands/init.rs | 2 +- clients/socks5/src/commands/run.rs | 2 +- clients/socks5/src/config/mod.rs | 4 ++-- .../client-core/src/{init => cli_helpers}/client_init.rs | 0 .../client-core/src/{init => cli_helpers}/client_run.rs | 0 common/client-core/src/cli_helpers/mod.rs | 5 +++++ common/client-core/src/init/mod.rs | 2 -- common/client-core/src/lib.rs | 1 + service-providers/network-requester/src/cli/init.rs | 2 +- service-providers/network-requester/src/cli/run.rs | 2 +- service-providers/network-requester/src/config/mod.rs | 8 ++++---- 14 files changed, 20 insertions(+), 16 deletions(-) rename common/client-core/src/{init => cli_helpers}/client_init.rs (100%) rename common/client-core/src/{init => cli_helpers}/client_run.rs (100%) create mode 100644 common/client-core/src/cli_helpers/mod.rs diff --git a/clients/native/src/client/config/mod.rs b/clients/native/src/client/config/mod.rs index 65185e579e..7fa28c8ab4 100644 --- a/clients/native/src/client/config/mod.rs +++ b/clients/native/src/client/config/mod.rs @@ -4,6 +4,8 @@ use crate::client::config::persistence::ClientPaths; use crate::client::config::template::CONFIG_TEMPLATE; use nym_bin_common::logging::LoggingSettings; +use nym_client_core::cli_helpers::client_init::ClientConfig; +use nym_client_core::config::disk_persistence::CommonClientPaths; use nym_config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT; use nym_config::{ must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate, @@ -16,10 +18,8 @@ use std::net::{IpAddr, Ipv4Addr}; use std::path::{Path, PathBuf}; use std::str::FromStr; -use nym_client_core::config::disk_persistence::CommonClientPaths; pub use nym_client_core::config::Config as BaseClientConfig; pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig}; -use nym_client_core::init::client_init::ClientConfig; pub mod old_config_v1_1_13; pub mod old_config_v1_1_20; diff --git a/clients/native/src/commands/init.rs b/clients/native/src/commands/init.rs index 8c9edeec2a..0be76ab332 100644 --- a/clients/native/src/commands/init.rs +++ b/clients/native/src/commands/init.rs @@ -12,7 +12,7 @@ use crate::{ }; use clap::Args; use nym_bin_common::output_format::OutputFormat; -use nym_client_core::init::client_init::{ +use nym_client_core::cli_helpers::client_init::{ initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient, }; use serde::Serialize; diff --git a/clients/native/src/commands/run.rs b/clients/native/src/commands/run.rs index 7365b0773b..b836fe6d20 100644 --- a/clients/native/src/commands/run.rs +++ b/clients/native/src/commands/run.rs @@ -10,7 +10,7 @@ use crate::{ use clap::Args; use log::*; use nym_bin_common::version_checker::is_minor_version_compatible; -use nym_client_core::init::client_run::CommonClientRunArgs; +use nym_client_core::cli_helpers::client_run::CommonClientRunArgs; use std::error::Error; use std::net::IpAddr; diff --git a/clients/socks5/src/commands/init.rs b/clients/socks5/src/commands/init.rs index d0c7e5e842..98e2393bf2 100644 --- a/clients/socks5/src/commands/init.rs +++ b/clients/socks5/src/commands/init.rs @@ -11,7 +11,7 @@ use crate::{ }; use clap::Args; use nym_bin_common::output_format::OutputFormat; -use nym_client_core::init::client_init::{ +use nym_client_core::cli_helpers::client_init::{ initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient, }; use nym_sphinx::addressing::clients::Recipient; diff --git a/clients/socks5/src/commands/run.rs b/clients/socks5/src/commands/run.rs index cc0500b894..5638c80d9b 100644 --- a/clients/socks5/src/commands/run.rs +++ b/clients/socks5/src/commands/run.rs @@ -10,9 +10,9 @@ use crate::{ use clap::Args; use log::*; use nym_bin_common::version_checker::is_minor_version_compatible; +use nym_client_core::cli_helpers::client_run::CommonClientRunArgs; use nym_client_core::client::base_client::storage::OnDiskPersistent; use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup; -use nym_client_core::init::client_run::CommonClientRunArgs; use nym_socks5_client_core::NymClient; use nym_sphinx::addressing::clients::Recipient; use std::net::IpAddr; diff --git a/clients/socks5/src/config/mod.rs b/clients/socks5/src/config/mod.rs index 9f4c23720f..9df903e64b 100644 --- a/clients/socks5/src/config/mod.rs +++ b/clients/socks5/src/config/mod.rs @@ -3,6 +3,8 @@ use crate::config::template::CONFIG_TEMPLATE; use nym_bin_common::logging::LoggingSettings; +use nym_client_core::cli_helpers::client_init::ClientConfig; +use nym_client_core::config::disk_persistence::CommonClientPaths; use nym_config::{ must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, @@ -15,9 +17,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; pub use crate::config::persistence::SocksClientPaths; -use nym_client_core::config::disk_persistence::CommonClientPaths; pub use nym_client_core::config::Config as BaseClientConfig; -use nym_client_core::init::client_init::ClientConfig; pub use nym_socks5_client_core::config::Config as CoreConfig; pub mod old_config_v1_1_13; diff --git a/common/client-core/src/init/client_init.rs b/common/client-core/src/cli_helpers/client_init.rs similarity index 100% rename from common/client-core/src/init/client_init.rs rename to common/client-core/src/cli_helpers/client_init.rs diff --git a/common/client-core/src/init/client_run.rs b/common/client-core/src/cli_helpers/client_run.rs similarity index 100% rename from common/client-core/src/init/client_run.rs rename to common/client-core/src/cli_helpers/client_run.rs diff --git a/common/client-core/src/cli_helpers/mod.rs b/common/client-core/src/cli_helpers/mod.rs new file mode 100644 index 0000000000..874663b75e --- /dev/null +++ b/common/client-core/src/cli_helpers/mod.rs @@ -0,0 +1,5 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod client_init; +pub mod client_run; diff --git a/common/client-core/src/init/mod.rs b/common/client-core/src/init/mod.rs index c8acabd838..395fdd45c2 100644 --- a/common/client-core/src/init/mod.rs +++ b/common/client-core/src/init/mod.rs @@ -24,8 +24,6 @@ use serde::de::DeserializeOwned; use serde::Serialize; use std::sync::Arc; -pub mod client_init; -pub mod client_run; pub mod helpers; pub mod types; diff --git a/common/client-core/src/lib.rs b/common/client-core/src/lib.rs index 386e498e53..83b3c0f393 100644 --- a/common/client-core/src/lib.rs +++ b/common/client-core/src/lib.rs @@ -1,5 +1,6 @@ use std::future::Future; +pub mod cli_helpers; pub mod client; pub mod config; pub mod error; diff --git a/service-providers/network-requester/src/cli/init.rs b/service-providers/network-requester/src/cli/init.rs index 35ddedc279..101b976172 100644 --- a/service-providers/network-requester/src/cli/init.rs +++ b/service-providers/network-requester/src/cli/init.rs @@ -10,7 +10,7 @@ use crate::{ }; use clap::Args; use nym_bin_common::output_format::OutputFormat; -use nym_client_core::init::client_init::{ +use nym_client_core::cli_helpers::client_init::{ initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient, }; use serde::Serialize; diff --git a/service-providers/network-requester/src/cli/run.rs b/service-providers/network-requester/src/cli/run.rs index 7ab10102b1..929ba57661 100644 --- a/service-providers/network-requester/src/cli/run.rs +++ b/service-providers/network-requester/src/cli/run.rs @@ -8,7 +8,7 @@ use crate::{ }; use clap::Args; use log::error; -use nym_client_core::init::client_run::CommonClientRunArgs; +use nym_client_core::cli_helpers::client_run::CommonClientRunArgs; const ENABLE_STATISTICS: &str = "enable-statistics"; diff --git a/service-providers/network-requester/src/config/mod.rs b/service-providers/network-requester/src/config/mod.rs index 8fee1c6725..faaf3487ee 100644 --- a/service-providers/network-requester/src/config/mod.rs +++ b/service-providers/network-requester/src/config/mod.rs @@ -4,12 +4,16 @@ use crate::config::persistence::NetworkRequesterPaths; use crate::config::template::CONFIG_TEMPLATE; use nym_bin_common::logging::LoggingSettings; +use nym_client_core::cli_helpers::client_init::ClientConfig; +use nym_client_core::config::disk_persistence::CommonClientPaths; use nym_config::{ must_get_home, read_config_from_toml_file, save_formatted_config_to_file, serde_helpers::de_maybe_stringified, NymConfigTemplate, OptionalSet, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, }; +use nym_network_defaults::mainnet; use nym_service_providers_common::DEFAULT_SERVICE_PROVIDERS_DIR; +use nym_sphinx::params::PacketSize; use serde::{Deserialize, Serialize}; use std::io; use std::path::{Path, PathBuf}; @@ -17,12 +21,8 @@ use std::str::FromStr; use std::time::Duration; use url::Url; -use nym_client_core::config::disk_persistence::CommonClientPaths; pub use nym_client_core::config::Config as BaseClientConfig; pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig}; -use nym_client_core::init::client_init::ClientConfig; -use nym_network_defaults::mainnet; -use nym_sphinx::params::PacketSize; pub mod old_config_v1_1_13; pub mod old_config_v1_1_20; From 4a4b0ab7e0311054c9baa76086df6d17f30683f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 30 Oct 2023 16:32:13 +0000 Subject: [PATCH 128/236] putting no cover and fastmode to common args --- clients/native/src/commands/init.rs | 13 ++----------- clients/socks5/src/commands/init.rs | 13 ++----------- common/client-core/src/cli_helpers/client_init.rs | 9 +++++++++ common/client-core/src/cli_helpers/client_run.rs | 10 ++++++++-- service-providers/network-requester/src/cli/init.rs | 4 ++-- 5 files changed, 23 insertions(+), 26 deletions(-) diff --git a/clients/native/src/commands/init.rs b/clients/native/src/commands/init.rs index 0be76ab332..27f62bd05b 100644 --- a/clients/native/src/commands/init.rs +++ b/clients/native/src/commands/init.rs @@ -68,15 +68,6 @@ pub(crate) struct Init { #[clap(long)] host: Option, - /// Mostly debug-related option to increase default traffic rate so that you would not need to - /// modify config post init - #[clap(long, hide = true)] - fastmode: bool, - - /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) - #[clap(long, hide = true)] - no_cover: bool, - #[clap(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, } @@ -94,8 +85,8 @@ impl From for OverrideConfig { disable_socket: init_config.disable_socket, port: init_config.port, host: init_config.host, - fastmode: init_config.fastmode, - no_cover: init_config.no_cover, + fastmode: init_config.common_args.fastmode, + no_cover: init_config.common_args.no_cover, nyxd_urls: init_config.common_args.nyxd_urls, enabled_credentials_mode: init_config.common_args.enabled_credentials_mode, diff --git a/clients/socks5/src/commands/init.rs b/clients/socks5/src/commands/init.rs index 98e2393bf2..44a247316e 100644 --- a/clients/socks5/src/commands/init.rs +++ b/clients/socks5/src/commands/init.rs @@ -77,15 +77,6 @@ pub(crate) struct Init { #[clap(long)] host: Option, - /// Mostly debug-related option to increase default traffic rate so that you would not need to - /// modify config post init - #[clap(long, hide = true)] - fastmode: bool, - - /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) - #[clap(long, hide = true)] - no_cover: bool, - #[clap(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, } @@ -103,8 +94,8 @@ impl From for OverrideConfig { ip: init_config.host, port: init_config.port, use_anonymous_replies: init_config.use_reply_surbs, - fastmode: init_config.fastmode, - no_cover: init_config.no_cover, + fastmode: init_config.common_args.fastmode, + no_cover: init_config.common_args.no_cover, geo_routing: None, medium_toggle: false, nyxd_urls: init_config.common_args.nyxd_urls, diff --git a/common/client-core/src/cli_helpers/client_init.rs b/common/client-core/src/cli_helpers/client_init.rs index 42f9987f44..c43ebf4545 100644 --- a/common/client-core/src/cli_helpers/client_init.rs +++ b/common/client-core/src/cli_helpers/client_init.rs @@ -88,6 +88,15 @@ pub struct CommonClientInitArgs { /// with bandwidth credential requirement. #[cfg_attr(feature = "cli", clap(long, hide = true))] pub enabled_credentials_mode: Option, + + /// Mostly debug-related option to increase default traffic rate so that you would not need to + /// modify config post init + #[cfg_attr(feature = "cli", clap(long, hide = true))] + pub fastmode: bool, + + /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) + #[cfg_attr(feature = "cli", clap(long, hide = true))] + pub no_cover: bool, } pub struct InitResultsWithConfig { diff --git a/common/client-core/src/cli_helpers/client_run.rs b/common/client-core/src/cli_helpers/client_run.rs index 8db3d49c38..594a3a34cb 100644 --- a/common/client-core/src/cli_helpers/client_run.rs +++ b/common/client-core/src/cli_helpers/client_run.rs @@ -46,10 +46,16 @@ pub struct CommonClientRunArgs { /// Mostly debug-related option to increase default traffic rate so that you would not need to /// modify config post init - #[arg(long, hide = true, conflicts_with = "medium_toggle")] + #[cfg_attr( + feature = "cli", + clap(long, hide = true, conflicts_with = "medium_toggle") + )] pub fastmode: bool, /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) - #[arg(long, hide = true, conflicts_with = "medium_toggle")] + #[cfg_attr( + feature = "cli", + clap(long, hide = true, conflicts_with = "medium_toggle") + )] pub no_cover: bool, } diff --git a/service-providers/network-requester/src/cli/init.rs b/service-providers/network-requester/src/cli/init.rs index 101b976172..d8439247b5 100644 --- a/service-providers/network-requester/src/cli/init.rs +++ b/service-providers/network-requester/src/cli/init.rs @@ -80,8 +80,8 @@ impl From for OverrideConfig { fn from(init_config: Init) -> Self { OverrideConfig { nym_apis: init_config.common_args.nym_apis, - fastmode: false, - no_cover: false, + fastmode: init_config.common_args.fastmode, + no_cover: init_config.common_args.no_cover, medium_toggle: false, nyxd_urls: init_config.common_args.nyxd_urls, enabled_credentials_mode: init_config.common_args.enabled_credentials_mode, From 00179d563bca8c7933122649f55bba8bd0eceb76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 30 Oct 2023 17:06:36 +0000 Subject: [PATCH 129/236] removed the contracicting flag --- common/client-core/src/cli_helpers/client_run.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/common/client-core/src/cli_helpers/client_run.rs b/common/client-core/src/cli_helpers/client_run.rs index 594a3a34cb..7864e4059f 100644 --- a/common/client-core/src/cli_helpers/client_run.rs +++ b/common/client-core/src/cli_helpers/client_run.rs @@ -46,16 +46,14 @@ pub struct CommonClientRunArgs { /// Mostly debug-related option to increase default traffic rate so that you would not need to /// modify config post init - #[cfg_attr( - feature = "cli", - clap(long, hide = true, conflicts_with = "medium_toggle") - )] + // note: we removed the 'conflicts_with = medium_toggle', but that's fine since NR + // has defined the conflict on that field itself + #[cfg_attr(feature = "cli", clap(long, hide = true))] pub fastmode: bool, /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) - #[cfg_attr( - feature = "cli", - clap(long, hide = true, conflicts_with = "medium_toggle") - )] + // note: we removed the 'conflicts_with = medium_toggle', but that's fine since NR + // has defined the conflict on that field itself + #[cfg_attr(feature = "cli", clap(long, hide = true))] pub no_cover: bool, } From 30000126d1e016b497d61179e4d0f3981af2c07d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 30 Oct 2023 17:12:13 +0000 Subject: [PATCH 130/236] Incorporate basic nym-node HTTP API (with swagger) to mixnodes (#4075) * basic nym-node router * loading legacy routes * dead code * config migrations --- .../mixnode-common/src/verloc/measurement.rs | 4 +- mixnode/src/commands/init.rs | 5 +- mixnode/src/commands/mod.rs | 41 +-- mixnode/src/commands/node_details.rs | 2 +- mixnode/src/commands/run.rs | 4 +- mixnode/src/commands/sign.rs | 4 +- mixnode/src/commands/upgrade_helpers.rs | 66 +++++ mixnode/src/config/mod.rs | 72 ++++- mixnode/src/config/old_config_v1_1_21.rs | 18 +- mixnode/src/config/old_config_v1_1_32.rs | 263 ++++++++++++++++++ mixnode/src/config/template.rs | 25 +- mixnode/src/error.rs | 41 ++- mixnode/src/node/helpers.rs | 52 ++++ .../src/node/http/{ => legacy}/description.rs | 0 .../src/node/http/{ => legacy}/hardware.rs | 0 mixnode/src/node/http/legacy/mod.rs | 49 ++++ mixnode/src/node/http/{ => legacy}/state.rs | 4 +- mixnode/src/node/http/{ => legacy}/stats.rs | 0 mixnode/src/node/http/{ => legacy}/verloc.rs | 2 +- mixnode/src/node/http/mod.rs | 114 +++++++- mixnode/src/node/mod.rs | 99 ++----- mixnode/src/node/node_statistics.rs | 17 +- nym-node/src/config/mod.rs | 1 + nym-node/src/http/router/mod.rs | 6 + nym-wallet/Cargo.lock | 10 + 25 files changed, 751 insertions(+), 148 deletions(-) create mode 100644 mixnode/src/commands/upgrade_helpers.rs create mode 100644 mixnode/src/config/old_config_v1_1_32.rs create mode 100644 mixnode/src/node/helpers.rs rename mixnode/src/node/http/{ => legacy}/description.rs (100%) rename mixnode/src/node/http/{ => legacy}/hardware.rs (100%) create mode 100644 mixnode/src/node/http/legacy/mod.rs rename mixnode/src/node/http/{ => legacy}/state.rs (89%) rename mixnode/src/node/http/{ => legacy}/stats.rs (100%) rename mixnode/src/node/http/{ => legacy}/verloc.rs (97%) diff --git a/common/mixnode-common/src/verloc/measurement.rs b/common/mixnode-common/src/verloc/measurement.rs index a1584dee99..0e7d312f84 100644 --- a/common/mixnode-common/src/verloc/measurement.rs +++ b/common/mixnode-common/src/verloc/measurement.rs @@ -9,12 +9,12 @@ use std::sync::Arc; use std::time::Duration; use tokio::sync::RwLock; -#[derive(Clone)] +#[derive(Clone, Default)] pub struct AtomicVerlocResult { inner: Arc>, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Default)] pub struct VerlocResult { total_tested: usize, #[serde(with = "humantime_serde")] diff --git a/mixnode/src/commands/init.rs b/mixnode/src/commands/init.rs index c0834686ee..31a45dfe96 100644 --- a/mixnode/src/commands/init.rs +++ b/mixnode/src/commands/init.rs @@ -62,7 +62,7 @@ fn init_paths(id: &str) -> io::Result<()> { fs::create_dir_all(default_config_directory(id)) } -pub(crate) fn execute(args: &Init) { +pub(crate) fn execute(args: &Init) -> anyhow::Result<()> { let override_config_fields = OverrideConfig::from(args.clone()); let id = override_config_fields.id.clone(); eprintln!("Initialising mixnode {id}..."); @@ -118,5 +118,6 @@ pub(crate) fn execute(args: &Init) { ); eprintln!("Mixnode configuration completed.\n\n\n"); - MixNode::new(config).print_node_details(args.output) + MixNode::new(config)?.print_node_details(args.output); + Ok(()) } diff --git a/mixnode/src/commands/mod.rs b/mixnode/src/commands/mod.rs index 17a2bd3a59..068089f9d9 100644 --- a/mixnode/src/commands/mod.rs +++ b/mixnode/src/commands/mod.rs @@ -1,9 +1,9 @@ // Copyright 2020 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::old_config_v1_1_21::ConfigV1_1_21; +use crate::config::default_config_filepath; +use crate::error::MixnodeError; use crate::{config::Config, Cli}; -use anyhow::anyhow; use clap::CommandFactory; use clap::Subcommand; use colored::Colorize; @@ -22,6 +22,7 @@ mod init; mod node_details; mod run; mod sign; +mod upgrade_helpers; #[derive(Subcommand)] pub(crate) enum Commands { @@ -65,7 +66,7 @@ pub(crate) async fn execute(args: Cli) -> anyhow::Result<()> { match args.command { Commands::Describe(m) => describe::execute(m)?, - Commands::Init(m) => init::execute(&m), + Commands::Init(m) => init::execute(&m)?, Commands::Run(m) => run::execute(&m).await?, Commands::Sign(m) => sign::execute(&m)?, Commands::NodeDetails(m) => node_details::execute(&m)?, @@ -131,32 +132,18 @@ pub(crate) fn version_check(cfg: &Config) -> bool { } } -fn try_upgrade_v1_1_21_config(id: &str) -> std::io::Result<()> { - use nym_config::legacy_helpers::nym_config::MigrationNymConfig; - - // explicitly load it as v1.1.21 (which is incompatible with the current, i.e. 1.1.22+) - let Ok(old_config) = ConfigV1_1_21::load_from_file(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(()); - }; - info!("It seems the mixnode is using <= v1.1.21 config template."); - info!("It is going to get updated to the current specification."); - - let updated: Config = old_config.into(); - updated.save_to_default_location() -} - -fn try_load_current_config(id: &str) -> anyhow::Result { - try_upgrade_v1_1_21_config(id)?; +fn try_load_current_config(id: &str) -> Result { + upgrade_helpers::try_upgrade_config(id)?; Config::read_from_default_path(id).map_err(|err| { - let error_msg = - format!( - "Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})", - ); - error!("{error_msg}"); - anyhow!(error_msg) + error!( + "Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})", + ); + MixnodeError::ConfigLoadFailure { + path: default_config_filepath(id), + id: id.to_string(), + source: err, + } }) } diff --git a/mixnode/src/commands/node_details.rs b/mixnode/src/commands/node_details.rs index c26bad8cab..c4b17c645f 100644 --- a/mixnode/src/commands/node_details.rs +++ b/mixnode/src/commands/node_details.rs @@ -19,6 +19,6 @@ pub(crate) struct NodeDetails { pub(crate) fn execute(args: &NodeDetails) -> anyhow::Result<()> { let config = try_load_current_config(&args.id)?; - MixNode::new(config).print_node_details(args.output); + MixNode::new(config)?.print_node_details(args.output); Ok(()) } diff --git a/mixnode/src/commands/run.rs b/mixnode/src/commands/run.rs index 0fded783b8..0ca0550679 100644 --- a/mixnode/src/commands/run.rs +++ b/mixnode/src/commands/run.rs @@ -84,13 +84,13 @@ pub(crate) async fn execute(args: &Run) -> anyhow::Result<()> { show_binding_warning(&config.mixnode.listening_address.to_string()); } - let mut mixnode = MixNode::new(config); + let mut mixnode = MixNode::new(config)?; eprintln!( "\nTo bond your mixnode you will need to install the Nym wallet, go to https://nymtech.net/get-involved and select the Download button.\n\ Select the correct version and install it to your machine. You will need to provide the following: \n "); mixnode.print_node_details(args.output); - mixnode.run().await; + mixnode.run().await?; Ok(()) } diff --git a/mixnode/src/commands/sign.rs b/mixnode/src/commands/sign.rs index 9650f53273..7864ef5504 100644 --- a/mixnode/src/commands/sign.rs +++ b/mixnode/src/commands/sign.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::commands::{try_load_current_config, validate_bech32_address_or_exit}; -use crate::node::MixNode; +use crate::node::helpers::load_identity_keys; use anyhow::{bail, Result}; use clap::{ArgGroup, Args}; use log::error; @@ -127,7 +127,7 @@ pub(crate) fn execute(args: &Sign) -> anyhow::Result<()> { bail!(err); } }; - let identity_keypair = MixNode::load_identity_keys(&config); + let identity_keypair = load_identity_keys(&config)?; match signed_target { SignedTarget::Text(text) => { diff --git a/mixnode/src/commands/upgrade_helpers.rs b/mixnode/src/commands/upgrade_helpers.rs new file mode 100644 index 0000000000..cf64c27158 --- /dev/null +++ b/mixnode/src/commands/upgrade_helpers.rs @@ -0,0 +1,66 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::old_config_v1_1_21::ConfigV1_1_21; +use crate::config::old_config_v1_1_32::ConfigV1_1_32; +use crate::config::{default_config_filepath, Config}; +use crate::error::MixnodeError; +use log::info; + +fn try_upgrade_v1_1_21_config(id: &str) -> Result { + use nym_config::legacy_helpers::nym_config::MigrationNymConfig; + + // explicitly load it as v1.1.21 (which is incompatible with the current, i.e. 1.1.22+) + let Ok(old_config) = ConfigV1_1_21::load_from_file(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 mixnode is using <= v1.1.21 config template."); + info!("It is going to get updated to the current specification."); + + let updated_step1: ConfigV1_1_32 = old_config.into(); + + let updated: Config = updated_step1.into(); + updated + .save_to_default_location() + .map_err(|err| MixnodeError::ConfigSaveFailure { + path: default_config_filepath(id), + id: id.to_string(), + source: err, + })?; + + Ok(true) +} + +fn try_upgrade_v1_1_32_config(id: &str) -> Result { + // explicitly load it as v1.1.32 (which is incompatible with the current, i.e. 1.1.22+) + let Ok(old_config) = ConfigV1_1_32::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 mixnode is using <= v1.1.32 config template."); + info!("It is going to get updated to the current specification."); + + let updated: Config = old_config.into(); + updated + .save_to_default_location() + .map_err(|err| MixnodeError::ConfigSaveFailure { + path: default_config_filepath(id), + id: id.to_string(), + source: err, + })?; + + Ok(true) +} + +pub(crate) fn try_upgrade_config(id: &str) -> Result<(), MixnodeError> { + if try_upgrade_v1_1_21_config(id)? { + return Ok(()); + } + if try_upgrade_v1_1_32_config(id)? { + return Ok(()); + } + Ok(()) +} diff --git a/mixnode/src/config/mod.rs b/mixnode/src/config/mod.rs index 7a6a73e06a..97ad26d699 100644 --- a/mixnode/src/config/mod.rs +++ b/mixnode/src/config/mod.rs @@ -3,6 +3,7 @@ use crate::config::persistence::paths::MixNodePaths; use crate::config::template::CONFIG_TEMPLATE; +use log::{debug, warn}; use nym_bin_common::logging::LoggingSettings; use nym_config::defaults::{ mainnet, DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, @@ -13,15 +14,17 @@ use nym_config::{ must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, }; +use nym_node::config; use serde::{Deserialize, Serialize}; use std::io; -use std::net::IpAddr; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::time::Duration; use url::Url; pub(crate) mod old_config_v1_1_21; +pub(crate) mod old_config_v1_1_32; pub mod persistence; mod template; @@ -70,9 +73,28 @@ pub fn default_data_directory>(id: P) -> PathBuf { .join(DEFAULT_DATA_DIR) } +fn default_mixnode_http_config() -> config::Http { + config::Http { + bind_address: SocketAddr::new( + IpAddr::V4(Ipv4Addr::UNSPECIFIED), + DEFAULT_HTTP_API_LISTENING_PORT, + ), + landing_page_assets_path: None, + } +} + #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] pub struct Config { + // additional metadata holding on-disk location of this config file + #[serde(skip)] + pub(crate) save_path: Option, + + pub host: config::Host, + + #[serde(default = "default_mixnode_http_config")] + pub http: config::Http, + pub mixnode: MixNode, pub storage_paths: MixNodePaths, @@ -95,8 +117,17 @@ impl NymConfigTemplate for Config { impl Config { pub fn new>(id: S) -> Self { + let default_mixnode = MixNode::new_default(id.as_ref()); + Config { - mixnode: MixNode::new_default(id.as_ref()), + save_path: None, + host: config::Host { + // this is a very bad default! + public_ips: vec![default_mixnode.listening_address], + hostname: None, + }, + http: default_mixnode_http_config(), + mixnode: default_mixnode, storage_paths: MixNodePaths::new_default(id.as_ref()), verloc: Default::default(), logging: Default::default(), @@ -104,12 +135,24 @@ impl Config { } } + // simple wrapper that reads config file and assigns path location + fn read_from_path>(path: P) -> io::Result { + let path = path.as_ref(); + let mut loaded: Config = read_config_from_toml_file(path)?; + loaded.save_path = Some(path.to_path_buf()); + debug!("loaded config file from {}", path.display()); + Ok(loaded) + } + + // currently this is dead code, but once we allow loading configs from custom paths + // well, we will have to be using it + #[allow(dead_code)] pub fn read_from_toml_file>(path: P) -> io::Result { - read_config_from_toml_file(path) + Self::read_from_path(path) } pub fn read_from_default_path>(id: P) -> io::Result { - Self::read_from_toml_file(default_config_filepath(id)) + Self::read_from_path(default_config_filepath(id)) } pub fn default_location(&self) -> PathBuf { @@ -121,6 +164,15 @@ impl Config { save_formatted_config_to_file(self, config_save_location) } + pub fn try_save(&self) -> io::Result<()> { + if let Some(save_location) = &self.save_path { + save_formatted_config_to_file(self, save_location) + } else { + warn!("config file save location is unknown. falling back to the default"); + self.save_to_default_location() + } + } + // builder methods pub fn with_custom_nym_apis(mut self, nym_api_urls: Vec) -> Self { self.mixnode.nym_api_urls = nym_api_urls; @@ -129,6 +181,10 @@ impl Config { pub fn with_listening_address(mut self, listening_address: IpAddr) -> Self { self.mixnode.listening_address = listening_address; + + let http_port = self.http.bind_address.port(); + self.http.bind_address = SocketAddr::new(listening_address, http_port); + self } @@ -143,7 +199,8 @@ impl Config { } pub fn with_http_api_port(mut self, port: u16) -> Self { - self.mixnode.http_api_port = port; + let http_ip = self.http.bind_address.ip(); + self.http.bind_address = SocketAddr::new(http_ip, port); self } @@ -171,10 +228,6 @@ pub struct MixNode { /// (default: 1790) pub verloc_port: u16, - /// Port used for listening for http requests. - /// (default: 8000) - pub http_api_port: u16, - /// Addresses to nym APIs from which the node gets the view of the network. pub nym_api_urls: Vec, } @@ -187,7 +240,6 @@ impl MixNode { listening_address: inaddr_any(), mix_port: DEFAULT_MIX_LISTENING_PORT, verloc_port: DEFAULT_VERLOC_LISTENING_PORT, - http_api_port: DEFAULT_HTTP_API_LISTENING_PORT, nym_api_urls: vec![Url::from_str(mainnet::NYM_API).expect("Invalid default API URL")], } } diff --git a/mixnode/src/config/old_config_v1_1_21.rs b/mixnode/src/config/old_config_v1_1_21.rs index 5baa6307df..fc4ae148a0 100644 --- a/mixnode/src/config/old_config_v1_1_21.rs +++ b/mixnode/src/config/old_config_v1_1_21.rs @@ -1,8 +1,10 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::config::old_config_v1_1_32::{ + ConfigV1_1_32, DebugV1_1_32, MixNodeV1_1_32, VerlocV1_1_32, +}; use crate::config::persistence::paths::{KeysPaths, MixNodePaths}; -use crate::config::{Config, Debug, MixNode, Verloc}; use nym_bin_common::logging::LoggingSettings; use nym_config::legacy_helpers::nym_config::MigrationNymConfig; use nym_validator_client::nyxd; @@ -67,13 +69,13 @@ pub struct ConfigV1_1_21 { debug: DebugV1_1_21, } -impl From for Config { +impl From for ConfigV1_1_32 { fn from(value: ConfigV1_1_21) -> Self { let node_description = ConfigV1_1_21::default_config_directory(&value.mixnode.id).join(DESCRIPTION_FILE); - Config { - mixnode: MixNode { + ConfigV1_1_32 { + mixnode: MixNodeV1_1_32 { version: value.mixnode.version, id: value.mixnode.id, listening_address: value.mixnode.listening_address, @@ -169,9 +171,9 @@ struct VerlocV1_1_21 { retry_timeout: Duration, } -impl From for Verloc { +impl From for VerlocV1_1_32 { fn from(value: VerlocV1_1_21) -> Self { - Verloc { + VerlocV1_1_32 { packets_per_node: value.packets_per_node, connection_timeout: value.connection_timeout, packet_timeout: value.packet_timeout, @@ -220,9 +222,9 @@ struct DebugV1_1_21 { use_legacy_framed_packet_version: bool, } -impl From for Debug { +impl From for DebugV1_1_32 { fn from(value: DebugV1_1_21) -> Self { - Debug { + DebugV1_1_32 { node_stats_logging_delay: value.node_stats_logging_delay, node_stats_updating_delay: value.node_stats_updating_delay, packet_forwarding_initial_backoff: value.packet_forwarding_initial_backoff, diff --git a/mixnode/src/config/old_config_v1_1_32.rs b/mixnode/src/config/old_config_v1_1_32.rs new file mode 100644 index 0000000000..92947a3234 --- /dev/null +++ b/mixnode/src/config/old_config_v1_1_32.rs @@ -0,0 +1,263 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::persistence::paths::MixNodePaths; +use crate::config::{Config, Debug, MixNode, Verloc}; +use nym_bin_common::logging::LoggingSettings; +use nym_config::{ + must_get_home, read_config_from_toml_file, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, NYM_DIR, +}; +use serde::{Deserialize, Serialize}; +use std::io; +use std::net::{IpAddr, SocketAddr}; +use std::path::{Path, PathBuf}; +use std::time::Duration; +use url::Url; + +const DEFAULT_MIXNODES_DIR: &str = "mixnodes"; + +// 'RTT MEASUREMENT' +const DEFAULT_PACKETS_PER_NODE: usize = 100; +const DEFAULT_CONNECTION_TIMEOUT: Duration = Duration::from_millis(5000); +const DEFAULT_PACKET_TIMEOUT: Duration = Duration::from_millis(1500); +const DEFAULT_DELAY_BETWEEN_PACKETS: Duration = Duration::from_millis(50); +const DEFAULT_BATCH_SIZE: usize = 50; +const DEFAULT_TESTING_INTERVAL: Duration = Duration::from_secs(60 * 60 * 12); +const DEFAULT_RETRY_TIMEOUT: Duration = Duration::from_secs(60 * 30); + +// 'DEBUG' +const DEFAULT_NODE_STATS_LOGGING_DELAY: Duration = Duration::from_millis(60_000); +const DEFAULT_NODE_STATS_UPDATING_DELAY: Duration = Duration::from_millis(30_000); +const DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF: Duration = Duration::from_millis(10_000); +const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: Duration = Duration::from_millis(300_000); +const DEFAULT_INITIAL_CONNECTION_TIMEOUT: Duration = Duration::from_millis(1_500); +const DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE: usize = 2000; + +/// Derive default path to mixnodes's config directory. +/// It should get resolved to `$HOME/.nym/mixnodes//config` +fn default_config_directory>(id: P) -> PathBuf { + must_get_home() + .join(NYM_DIR) + .join(DEFAULT_MIXNODES_DIR) + .join(id) + .join(DEFAULT_CONFIG_DIR) +} + +/// Derive default path to mixnodes's config file. +/// It should get resolved to `$HOME/.nym/mixnodes//config/config.toml` +fn default_config_filepath>(id: P) -> PathBuf { + default_config_directory(id).join(DEFAULT_CONFIG_FILENAME) +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct ConfigV1_1_32 { + pub mixnode: MixNodeV1_1_32, + + // i hope this laziness is not going to backfire... + pub storage_paths: MixNodePaths, + + #[serde(default)] + pub verloc: VerlocV1_1_32, + + #[serde(default)] + pub logging: LoggingSettings, + + #[serde(default)] + pub debug: DebugV1_1_32, +} + +impl ConfigV1_1_32 { + pub fn read_from_default_path>(id: P) -> io::Result { + read_config_from_toml_file(default_config_filepath(id)) + } +} + +impl From for Config { + fn from(value: ConfigV1_1_32) -> Self { + Config { + // \/ ADDED + save_path: None, + // /\ ADDED + + // \/ ADDED + host: nym_node::config::Host { + // this is a very bad default! + public_ips: vec![value.mixnode.listening_address], + hostname: None, + }, + // /\ ADDED + + // \/ ADDED + http: nym_node::config::Http { + bind_address: SocketAddr::new( + value.mixnode.listening_address, + value.mixnode.http_api_port, + ), + landing_page_assets_path: None, + }, + // /\ ADDED + mixnode: MixNode { + version: value.mixnode.version, + id: value.mixnode.id, + listening_address: value.mixnode.listening_address, + mix_port: value.mixnode.mix_port, + verloc_port: value.mixnode.verloc_port, + nym_api_urls: value.mixnode.nym_api_urls, + }, + storage_paths: value.storage_paths, + verloc: value.verloc.into(), + logging: value.logging, + debug: value.debug.into(), + } + } +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +pub struct MixNodeV1_1_32 { + /// Version of the mixnode for which this configuration was created. + pub version: String, + + /// ID specifies the human readable ID of this particular mixnode. + pub id: String, + + /// Address to which this mixnode will bind to and will be listening for packets. + pub listening_address: IpAddr, + + /// Port used for listening for all mixnet traffic. + /// (default: 1789) + pub mix_port: u16, + + /// Port used for listening for verloc traffic. + /// (default: 1790) + pub verloc_port: u16, + + /// Port used for listening for http requests. + /// (default: 8000) + pub http_api_port: u16, + + /// Addresses to nym APIs from which the node gets the view of the network. + pub nym_api_urls: Vec, +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct VerlocV1_1_32 { + /// Specifies number of echo packets sent to each node during a measurement run. + pub packets_per_node: usize, + + /// Specifies maximum amount of time to wait for the connection to get established. + #[serde(with = "humantime_serde")] + pub connection_timeout: Duration, + + /// Specifies maximum amount of time to wait for the reply packet to arrive before abandoning the test. + #[serde(with = "humantime_serde")] + pub packet_timeout: Duration, + + /// Specifies delay between subsequent test packets being sent (after receiving a reply). + #[serde(with = "humantime_serde")] + pub delay_between_packets: Duration, + + /// Specifies number of nodes being tested at once. + pub tested_nodes_batch_size: usize, + + /// Specifies delay between subsequent test runs. + #[serde(with = "humantime_serde")] + pub testing_interval: Duration, + + /// Specifies delay between attempting to run the measurement again if the previous run failed + /// due to being unable to get the list of nodes. + #[serde(with = "humantime_serde")] + pub retry_timeout: Duration, +} + +impl From for Verloc { + fn from(value: VerlocV1_1_32) -> Self { + Verloc { + packets_per_node: value.packets_per_node, + connection_timeout: value.connection_timeout, + packet_timeout: value.packet_timeout, + delay_between_packets: value.delay_between_packets, + tested_nodes_batch_size: value.tested_nodes_batch_size, + testing_interval: value.testing_interval, + retry_timeout: value.retry_timeout, + } + } +} + +impl Default for VerlocV1_1_32 { + fn default() -> Self { + VerlocV1_1_32 { + packets_per_node: DEFAULT_PACKETS_PER_NODE, + connection_timeout: DEFAULT_CONNECTION_TIMEOUT, + packet_timeout: DEFAULT_PACKET_TIMEOUT, + delay_between_packets: DEFAULT_DELAY_BETWEEN_PACKETS, + tested_nodes_batch_size: DEFAULT_BATCH_SIZE, + testing_interval: DEFAULT_TESTING_INTERVAL, + retry_timeout: DEFAULT_RETRY_TIMEOUT, + } + } +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(default)] +pub struct DebugV1_1_32 { + /// Delay between each subsequent node statistics being logged to the console + #[serde(with = "humantime_serde")] + pub node_stats_logging_delay: Duration, + + /// Delay between each subsequent node statistics being updated + #[serde(with = "humantime_serde")] + pub node_stats_updating_delay: Duration, + + /// Initial value of an exponential backoff to reconnect to dropped TCP connection when + /// forwarding sphinx packets. + #[serde(with = "humantime_serde")] + pub packet_forwarding_initial_backoff: Duration, + + /// Maximum value of an exponential backoff to reconnect to dropped TCP connection when + /// forwarding sphinx packets. + #[serde(with = "humantime_serde")] + pub packet_forwarding_maximum_backoff: Duration, + + /// Timeout for establishing initial connection when trying to forward a sphinx packet. + #[serde(with = "humantime_serde")] + pub initial_connection_timeout: Duration, + + /// Maximum number of packets that can be stored waiting to get sent to a particular connection. + pub maximum_connection_buffer_size: usize, + + /// Specifies whether the mixnode should be using the legacy framing for the sphinx packets. + // it's set to true by default. The reason for that decision is to preserve compatibility with the + // existing nodes whilst everyone else is upgrading and getting the code for handling the new field. + // It shall be disabled in the subsequent releases. + pub use_legacy_framed_packet_version: bool, +} + +impl From for Debug { + fn from(value: DebugV1_1_32) -> Self { + Debug { + node_stats_logging_delay: value.node_stats_logging_delay, + node_stats_updating_delay: value.node_stats_updating_delay, + packet_forwarding_initial_backoff: value.packet_forwarding_initial_backoff, + packet_forwarding_maximum_backoff: value.packet_forwarding_maximum_backoff, + initial_connection_timeout: value.initial_connection_timeout, + maximum_connection_buffer_size: value.maximum_connection_buffer_size, + use_legacy_framed_packet_version: value.use_legacy_framed_packet_version, + } + } +} + +impl Default for DebugV1_1_32 { + fn default() -> Self { + DebugV1_1_32 { + node_stats_logging_delay: DEFAULT_NODE_STATS_LOGGING_DELAY, + node_stats_updating_delay: DEFAULT_NODE_STATS_UPDATING_DELAY, + packet_forwarding_initial_backoff: DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF, + packet_forwarding_maximum_backoff: DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF, + initial_connection_timeout: DEFAULT_INITIAL_CONNECTION_TIMEOUT, + maximum_connection_buffer_size: DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE, + use_legacy_framed_packet_version: false, + } + } +} diff --git a/mixnode/src/config/template.rs b/mixnode/src/config/template.rs index a885a1ecbb..b7f9433ae5 100644 --- a/mixnode/src/config/template.rs +++ b/mixnode/src/config/template.rs @@ -11,6 +11,19 @@ pub(crate) const CONFIG_TEMPLATE: &str = r#" ##### main base mixnode config options ##### +[host] +# Ip address(es) of this host, such as 1.1.1.1 that external clients will use for connections. +# currently not in active use for mixnodes +public_ips = [ + {{#each host.public_ips }} + '{{this}}', + {{/each}} +] + +# (temporary) Optional hostname of this node, for example nymtech.net. +# currently not in active use for mixnodes +hostname = '{{ host.hostname }}' + [mixnode] # Version of the mixnode for which this configuration was created. version = '{{ mixnode.version }}' @@ -29,10 +42,6 @@ mix_port = {{ mixnode.mix_port }} # (default: 1790) verloc_port = {{ mixnode.verloc_port }} -# Port used for listening for http requests. -# (default: 8000) -http_api_port = {{ mixnode.http_api_port }} - # Addresses to APIs running on validator from which the node gets the view of the network. nym_api_urls = [ {{#each mixnode.nym_api_urls }} @@ -40,6 +49,14 @@ nym_api_urls = [ {{/each}} ] +[http] +# Socket address this node will use for binding its http API. +# default: `0.0.0.0:8000` +bind_address = '{{ http.bind_address }}' + +# Path to assets directory of custom landing page of this node +landing_page_assets_path = '{{ http.landing_page_assets_path }}' + [storage_paths] # Path to file containing private identity key. diff --git a/mixnode/src/error.rs b/mixnode/src/error.rs index a0ee647852..a5f80b10d4 100644 --- a/mixnode/src/error.rs +++ b/mixnode/src/error.rs @@ -1,10 +1,49 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use std::io; +use std::path::PathBuf; use thiserror::Error; #[derive(Debug, Error)] -pub(crate) enum MixnodeError { +pub enum MixnodeError { + #[error("failed to load {keys} keys from '{}' (private key) and '{}' (public key): {err}", .paths.private_key_path.display(), .paths.public_key_path.display())] + KeyPairLoadFailure { + keys: String, + paths: nym_pemstore::KeyPairPath, + #[source] + err: io::Error, + }, + + #[allow(dead_code)] + #[error("failed to load {key} public key from '{}': {err}", .path.display())] + PublicKeyLoadFailure { + key: String, + path: PathBuf, + #[source] + err: io::Error, + }, + + #[error( + "failed to load config file for id {id} using path '{}'. detailed message: {source}", path.display() + )] + ConfigLoadFailure { + id: String, + path: PathBuf, + #[source] + source: io::Error, + }, + + #[error( + "failed to save config file for id {id} using path '{}'. detailed message: {source}", path.display() + )] + ConfigSaveFailure { + id: String, + path: PathBuf, + #[source] + source: io::Error, + }, + // TODO: in the future this should work the other way, i.e. NymNode depending on Gateway errors #[error(transparent)] NymNodeError(#[from] nym_node::error::NymNodeError), diff --git a/mixnode/src/node/helpers.rs b/mixnode/src/node/helpers.rs new file mode 100644 index 0000000000..955f4f98fe --- /dev/null +++ b/mixnode/src/node/helpers.rs @@ -0,0 +1,52 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::Config; +use crate::error::MixnodeError; +use nym_crypto::asymmetric::{encryption, identity}; +use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair}; +use nym_pemstore::KeyPairPath; +use std::path::Path; + +pub(crate) fn load_keypair( + paths: KeyPairPath, + name: impl Into, +) -> Result { + nym_pemstore::load_keypair(&paths).map_err(|err| MixnodeError::KeyPairLoadFailure { + keys: name.into(), + paths, + err, + }) +} + +#[allow(unused)] +pub(crate) fn load_public_key(path: P, name: S) -> Result +where + T: PemStorableKey, + P: AsRef, + S: Into, +{ + nym_pemstore::load_key(path.as_ref()).map_err(|err| MixnodeError::PublicKeyLoadFailure { + key: name.into(), + path: path.as_ref().to_path_buf(), + err, + }) +} + +/// Loads identity keys stored on disk +pub(crate) fn load_identity_keys(config: &Config) -> Result { + let identity_paths = KeyPairPath::new( + config.storage_paths.keys.private_identity_key(), + config.storage_paths.keys.public_identity_key(), + ); + load_keypair(identity_paths, "mixnode identity") +} + +/// Loads Sphinx keys stored on disk +pub(crate) fn load_sphinx_keys(config: &Config) -> Result { + let sphinx_paths = KeyPairPath::new( + config.storage_paths.keys.private_encryption_key(), + config.storage_paths.keys.public_encryption_key(), + ); + load_keypair(sphinx_paths, "mixnode sphinx") +} diff --git a/mixnode/src/node/http/description.rs b/mixnode/src/node/http/legacy/description.rs similarity index 100% rename from mixnode/src/node/http/description.rs rename to mixnode/src/node/http/legacy/description.rs diff --git a/mixnode/src/node/http/hardware.rs b/mixnode/src/node/http/legacy/hardware.rs similarity index 100% rename from mixnode/src/node/http/hardware.rs rename to mixnode/src/node/http/legacy/hardware.rs diff --git a/mixnode/src/node/http/legacy/mod.rs b/mixnode/src/node/http/legacy/mod.rs new file mode 100644 index 0000000000..49230ebbec --- /dev/null +++ b/mixnode/src/node/http/legacy/mod.rs @@ -0,0 +1,49 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::node::http::legacy::description::description; +use crate::node::http::legacy::hardware::hardware; +use crate::node::http::legacy::state::MixnodeAppState; +use crate::node::http::legacy::stats::stats; +use crate::node::http::legacy::verloc::verloc; +use crate::node::node_description::NodeDescription; +use axum::http::{StatusCode, Uri}; +use axum::response::IntoResponse; +use axum::routing::get; +use axum::Router; + +pub(crate) mod description; +pub(crate) mod hardware; +pub(crate) mod state; +pub(crate) mod stats; +pub(crate) mod verloc; + +pub(crate) async fn not_found(uri: Uri) -> impl IntoResponse { + ( + StatusCode::NOT_FOUND, + format!("I couldn't find '{uri}'. Try something else?"), + ) +} + +pub(crate) mod api_routes { + pub(crate) const VERLOC: &str = "/verloc"; + pub(crate) const DESCRIPTION: &str = "/description"; + pub(crate) const STATS: &str = "/stats"; + pub(crate) const HARDWARE: &str = "/hardware"; +} + +pub(crate) fn routes( + state: MixnodeAppState, + descriptor: NodeDescription, +) -> Router { + Router::new() + .route(api_routes::VERLOC, get(verloc)) + .route( + api_routes::DESCRIPTION, + get(move |query| description(descriptor, query)), + ) + .route(api_routes::STATS, get(stats)) + .route(api_routes::HARDWARE, get(hardware)) + .fallback(not_found) + .with_state(state) +} diff --git a/mixnode/src/node/http/state.rs b/mixnode/src/node/http/legacy/state.rs similarity index 89% rename from mixnode/src/node/http/state.rs rename to mixnode/src/node/http/legacy/state.rs index 4cc3e7b8d6..2b3016185c 100644 --- a/mixnode/src/node/http/state.rs +++ b/mixnode/src/node/http/legacy/state.rs @@ -1,12 +1,12 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::node::http::verloc::VerlocState; +use crate::node::http::legacy::verloc::VerlocState; use crate::node::node_statistics::SharedNodeStats; use axum::extract::FromRef; // this is a temporary thing for the transition period -#[derive(Clone)] +#[derive(Clone, Default)] pub(crate) struct MixnodeAppState { pub(crate) verloc: VerlocState, pub(crate) stats: SharedNodeStats, diff --git a/mixnode/src/node/http/stats.rs b/mixnode/src/node/http/legacy/stats.rs similarity index 100% rename from mixnode/src/node/http/stats.rs rename to mixnode/src/node/http/legacy/stats.rs diff --git a/mixnode/src/node/http/verloc.rs b/mixnode/src/node/http/legacy/verloc.rs similarity index 97% rename from mixnode/src/node/http/verloc.rs rename to mixnode/src/node/http/legacy/verloc.rs index 1848f48f6c..18a263e713 100644 --- a/mixnode/src/node/http/verloc.rs +++ b/mixnode/src/node/http/legacy/verloc.rs @@ -2,7 +2,7 @@ use axum::extract::{Query, State}; use nym_mixnode_common::verloc::{AtomicVerlocResult, VerlocResult}; use nym_node::http::api::{FormattedResponse, OutputParams}; -#[derive(Clone)] +#[derive(Clone, Default)] pub(crate) struct VerlocState { shared: AtomicVerlocResult, } diff --git a/mixnode/src/node/http/mod.rs b/mixnode/src/node/http/mod.rs index ddedce8215..a3a0d49ce2 100644 --- a/mixnode/src/node/http/mod.rs +++ b/mixnode/src/node/http/mod.rs @@ -1,15 +1,105 @@ -pub(crate) mod description; -pub(crate) mod hardware; -pub(crate) mod state; -pub(crate) mod stats; -pub(crate) mod verloc; +use crate::config::Config; +use crate::error::MixnodeError; +use crate::node::http::legacy::verloc::VerlocState; +use crate::node::node_description::NodeDescription; +use crate::node::node_statistics::SharedNodeStats; +use log::info; +use nym_bin_common::bin_info_owned; +use nym_crypto::asymmetric::{encryption, identity}; +use nym_node::error::NymNodeError; +use nym_node::http::api::api_requests; +use nym_node::http::api::api_requests::SignedHostInformation; +use nym_task::TaskClient; -use axum::http::{StatusCode, Uri}; -use axum::response::IntoResponse; +pub(crate) mod legacy; -pub(crate) async fn not_found(uri: Uri) -> impl IntoResponse { - ( - StatusCode::NOT_FOUND, - format!("I couldn't find '{uri}'. Try something else?"), - ) +fn load_host_details( + config: &Config, + sphinx_key: &encryption::PublicKey, + identity_keypair: &identity::KeyPair, +) -> Result { + let host_info = api_requests::v1::node::models::HostInformation { + ip_address: config.host.public_ips.clone(), + hostname: config.host.hostname.clone(), + keys: api_requests::v1::node::models::HostKeys { + ed25519: identity_keypair.public_key().to_base58_string(), + x25519: sphinx_key.to_base58_string(), + }, + }; + + let signed_info = SignedHostInformation::new(host_info, identity_keypair.private_key()) + .map_err(NymNodeError::from)?; + Ok(signed_info) +} + +fn load_mixnode_details( + _config: &Config, +) -> Result { + Ok(api_requests::v1::mixnode::models::Mixnode {}) +} + +pub(crate) struct HttpApiBuilder<'a> { + mixnode_config: &'a Config, + identity_keypair: &'a identity::KeyPair, + sphinx_keypair: &'a encryption::KeyPair, + legacy_mixnode: legacy::state::MixnodeAppState, + legacy_descriptor: NodeDescription, +} + +impl<'a> HttpApiBuilder<'a> { + pub(crate) fn new( + mixnode_config: &'a Config, + identity_keypair: &'a identity::KeyPair, + sphinx_keypair: &'a encryption::KeyPair, + ) -> Self { + HttpApiBuilder { + mixnode_config, + identity_keypair, + sphinx_keypair, + legacy_mixnode: legacy::state::MixnodeAppState::default(), + legacy_descriptor: Default::default(), + } + } + + #[must_use] + pub(crate) fn with_verloc(mut self, verloc: VerlocState) -> Self { + self.legacy_mixnode.verloc = verloc; + self + } + + #[must_use] + pub(crate) fn with_mixing_stats(mut self, stats: SharedNodeStats) -> Self { + self.legacy_mixnode.stats = stats; + self + } + + #[must_use] + pub(crate) fn with_descriptor(mut self, descriptor: NodeDescription) -> Self { + self.legacy_descriptor = descriptor; + self + } + + pub(crate) fn start(self, task_client: TaskClient) -> Result<(), MixnodeError> { + let bind_address = self.mixnode_config.http.bind_address; + info!("Starting HTTP API on http://{bind_address}",); + + let config = nym_node::http::Config::new( + bin_info_owned!(), + load_host_details( + self.mixnode_config, + self.sphinx_keypair.public_key(), + self.identity_keypair, + )?, + ) + .with_mixnode(load_mixnode_details(self.mixnode_config)?) + .with_landing_page_assets(self.mixnode_config.http.landing_page_assets_path.as_ref()); + + let router = nym_node::http::NymNodeRouter::new(config, None); + let server = router + .with_merged(legacy::routes(self.legacy_mixnode, self.legacy_descriptor)) + .build_server(&bind_address)? + .with_task_client(task_client); + tokio::spawn(async move { server.run().await }); + Ok(()) + } } diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index a73c5a10a4..f1b330e69a 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -2,26 +2,21 @@ // SPDX-License-Identifier: Apache-2.0 use crate::config::Config; -use crate::node::http::description::description; -use crate::node::http::hardware::hardware; -use crate::node::http::not_found; -use crate::node::http::state::MixnodeAppState; -use crate::node::http::stats::stats; -use crate::node::http::verloc::{verloc, VerlocState}; +use crate::error::MixnodeError; +use crate::node::helpers::{load_identity_keys, load_sphinx_keys}; +use crate::node::http::legacy::verloc::VerlocState; +use crate::node::http::HttpApiBuilder; use crate::node::listener::connection_handler::packet_processing::PacketProcessor; use crate::node::listener::connection_handler::ConnectionHandler; use crate::node::listener::Listener; use crate::node::node_description::NodeDescription; use crate::node::node_statistics::SharedNodeStats; use crate::node::packet_delayforwarder::{DelayForwarder, PacketDelayForwardSender}; -use axum::routing::get; -use axum::Router; use log::{error, info, warn}; use nym_bin_common::output_format::OutputFormat; use nym_bin_common::version_checker::parse_version; use nym_crypto::asymmetric::{encryption, identity}; use nym_mixnode_common::verloc::{self, AtomicVerlocResult, VerlocMeasurer}; -use nym_node::http::middleware::logging; use nym_task::{TaskClient, TaskManager}; use rand::seq::SliceRandom; use rand::thread_rng; @@ -29,6 +24,7 @@ use std::net::SocketAddr; use std::process; use std::sync::Arc; +pub(crate) mod helpers; mod http; mod listener; pub(crate) mod node_description; @@ -44,41 +40,19 @@ pub struct MixNode { } impl MixNode { - pub fn new(config: Config) -> Self { - MixNode { + pub fn new(config: Config) -> Result { + Ok(MixNode { descriptor: Self::load_node_description(&config), - identity_keypair: Arc::new(Self::load_identity_keys(&config)), - sphinx_keypair: Arc::new(Self::load_sphinx_keys(&config)), + identity_keypair: Arc::new(load_identity_keys(&config)?), + sphinx_keypair: Arc::new(load_sphinx_keys(&config)?), config, - } + }) } fn load_node_description(config: &Config) -> NodeDescription { NodeDescription::load_from_file(&config.storage_paths.node_description).unwrap_or_default() } - /// Loads identity keys stored on disk - pub(crate) fn load_identity_keys(config: &Config) -> identity::KeyPair { - let identity_keypair: identity::KeyPair = - nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new( - config.storage_paths.keys.private_identity_key(), - config.storage_paths.keys.public_identity_key(), - )) - .expect("Failed to read stored identity key files"); - identity_keypair - } - - /// Loads Sphinx keys stored on disk - fn load_sphinx_keys(config: &Config) -> encryption::KeyPair { - let sphinx_keypair: encryption::KeyPair = - nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new( - config.storage_paths.keys.private_encryption_key(), - config.storage_paths.keys.public_encryption_key(), - )) - .expect("Failed to read stored sphinx key files"); - sphinx_keypair - } - /// Prints relevant node details to the console pub(crate) fn print_node_details(&self, output: OutputFormat) { let node_details = nym_types::mixnode::MixnodeNodeDetailsResponse { @@ -87,7 +61,7 @@ impl MixNode { bind_address: self.config.mixnode.listening_address, version: self.config.mixnode.version.clone(), mix_port: self.config.mixnode.mix_port, - http_api_port: self.config.mixnode.http_api_port, + http_api_port: self.config.http.bind_address.port(), verloc_port: self.config.mixnode.verloc_port, }; @@ -98,39 +72,13 @@ impl MixNode { &self, atomic_verloc_result: AtomicVerlocResult, node_stats_pointer: SharedNodeStats, - ) { - let bind_address = SocketAddr::new( - self.config.mixnode.listening_address, - self.config.mixnode.http_api_port, - ); - - info!("Starting HTTP API on http://{bind_address}",); - - let state = MixnodeAppState { - verloc: VerlocState::new(atomic_verloc_result), - stats: node_stats_pointer, - }; - - let router = Router::new() - .route("/verloc", get(verloc)) - .route( - "/description", - get({ - let descriptor = self.descriptor.clone(); - move |query| description(descriptor, query) - }), - ) - .route("/stats", get(stats)) - .route("/hardware", get(hardware)) - .fallback(not_found) - .layer(axum::middleware::from_fn(logging::logger)) - .with_state(state); - - tokio::spawn(async move { - axum::Server::bind(&bind_address) - .serve(router.into_make_service_with_connect_info::()) - .await - }); + task_client: TaskClient, + ) -> Result<(), MixnodeError> { + HttpApiBuilder::new(&self.config, &self.identity_keypair, &self.sphinx_keypair) + .with_verloc(VerlocState::new(atomic_verloc_result)) + .with_mixing_stats(node_stats_pointer) + .with_descriptor(self.descriptor.clone()) + .start(task_client) } fn start_node_stats_controller( @@ -272,7 +220,7 @@ impl MixNode { log::info!("Stopping nym mixnode"); } - pub async fn run(&mut self) { + pub async fn run(&mut self) -> Result<(), MixnodeError> { info!("Starting nym mixnode"); if self.check_if_bonded().await { @@ -298,9 +246,14 @@ impl MixNode { // Rocket handles shutdown on it's own, but its shutdown handling should be incorporated // with that of the rest of the tasks. // Currently it's runtime is forcefully terminated once the mixnode exits. - self.start_http_api(atomic_verloc_results, node_stats_pointer); + self.start_http_api( + atomic_verloc_results, + node_stats_pointer, + shutdown.subscribe().named("http-api"), + )?; info!("Finished nym mixnode startup procedure - it should now be able to receive mix traffic!"); - self.wait_for_interrupt(shutdown).await + self.wait_for_interrupt(shutdown).await; + Ok(()) } } diff --git a/mixnode/src/node/node_statistics.rs b/mixnode/src/node/node_statistics.rs index 72f85c6001..78895b85ce 100644 --- a/mixnode/src/node/node_statistics.rs +++ b/mixnode/src/node/node_statistics.rs @@ -16,7 +16,7 @@ type PacketsMap = HashMap; type PacketDataReceiver = mpsc::UnboundedReceiver; type PacketDataSender = mpsc::UnboundedSender; -#[derive(Clone)] +#[derive(Clone, Default)] pub(crate) struct SharedNodeStats { inner: Arc>, } @@ -104,6 +104,21 @@ pub struct NodeStats { packets_explicitly_dropped_since_last_update: PacketsMap, } +impl Default for NodeStats { + fn default() -> Self { + NodeStats { + update_time: SystemTime::UNIX_EPOCH, + previous_update_time: SystemTime::UNIX_EPOCH, + packets_received_since_startup: 0, + packets_sent_since_startup: Default::default(), + packets_explicitly_dropped_since_startup: Default::default(), + packets_received_since_last_update: 0, + packets_sent_since_last_update: Default::default(), + packets_explicitly_dropped_since_last_update: Default::default(), + } + } +} + impl NodeStats { pub(crate) fn simplify(&self) -> NodeStatsSimple { NodeStatsSimple { diff --git a/nym-node/src/config/mod.rs b/nym-node/src/config/mod.rs index 958b912c7b..ad4a9a8823 100644 --- a/nym-node/src/config/mod.rs +++ b/nym-node/src/config/mod.rs @@ -43,6 +43,7 @@ impl Host { pub struct Http { /// Socket address this node will use for binding its http API. /// default: `0.0.0.0:8080` + /// note: for legacy reasons, it defaults to port `8000` for mixnodes. pub bind_address: SocketAddr, /// Path to assets directory of custom landing page of this node. diff --git a/nym-node/src/http/router/mod.rs b/nym-node/src/http/router/mod.rs index 3548266373..d24033f1bc 100644 --- a/nym-node/src/http/router/mod.rs +++ b/nym-node/src/http/router/mod.rs @@ -124,6 +124,12 @@ impl NymNodeRouter { self } + #[must_use] + pub fn with_merged(mut self, router: Router) -> Self { + self.inner = self.inner.merge(router); + self + } + pub fn build_server( self, bind_address: &SocketAddr, diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index a2922d8391..8696afe916 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -3431,6 +3431,15 @@ dependencies = [ "nym-contracts-common", ] +[[package]] +name = "nym-exit-policy" +version = "0.1.0" +dependencies = [ + "serde", + "thiserror", + "tracing", +] + [[package]] name = "nym-group-contract-common" version = "0.1.0" @@ -3510,6 +3519,7 @@ dependencies = [ "base64 0.21.4", "nym-bin-common", "nym-crypto", + "nym-exit-policy", "nym-wireguard-types", "schemars", "serde", From 5fcaacc39af378a152976b398a689c3863a6705d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 30 Oct 2023 17:16:08 +0000 Subject: [PATCH 131/236] wasm lock --- common/client-core/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/common/client-core/src/lib.rs b/common/client-core/src/lib.rs index 83b3c0f393..0b401f4e02 100644 --- a/common/client-core/src/lib.rs +++ b/common/client-core/src/lib.rs @@ -1,5 +1,6 @@ use std::future::Future; +#[cfg(not(target_arch = "wasm32"))] pub mod cli_helpers; pub mod client; pub mod config; From b48dc0b38ab1e863629d25a5dc045da7bc35436f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 09:53:28 +0100 Subject: [PATCH 132/236] Rename to old_config_v1_1_31.rs --- .../src/config/{old_config_v1_1_30.rs => old_config_v1_1_31.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename gateway/src/config/{old_config_v1_1_30.rs => old_config_v1_1_31.rs} (100%) diff --git a/gateway/src/config/old_config_v1_1_30.rs b/gateway/src/config/old_config_v1_1_31.rs similarity index 100% rename from gateway/src/config/old_config_v1_1_30.rs rename to gateway/src/config/old_config_v1_1_31.rs From cf234ecf8237507121d44dc9cb54257fb3d217c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 09:58:08 +0100 Subject: [PATCH 133/236] Update files to reflect new filename --- gateway/src/commands/upgrade_helpers.rs | 14 +++---- gateway/src/config/mod.rs | 2 +- gateway/src/config/old_config_v1_1_29.rs | 22 +++++------ gateway/src/config/old_config_v1_1_31.rs | 48 ++++++++++++------------ 4 files changed, 43 insertions(+), 43 deletions(-) diff --git a/gateway/src/commands/upgrade_helpers.rs b/gateway/src/commands/upgrade_helpers.rs index f5c9b14953..e09e6f827d 100644 --- a/gateway/src/commands/upgrade_helpers.rs +++ b/gateway/src/commands/upgrade_helpers.rs @@ -4,7 +4,7 @@ use crate::config::old_config_v1_1_20::ConfigV1_1_20; use crate::config::old_config_v1_1_28::ConfigV1_1_28; use crate::config::old_config_v1_1_29::ConfigV1_1_29; -use crate::config::old_config_v1_1_30::ConfigV1_1_30; +use crate::config::old_config_v1_1_31::ConfigV1_1_31; use crate::config::{default_config_filepath, Config}; use crate::error::GatewayError; use log::info; @@ -23,7 +23,7 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result { let updated_step1: ConfigV1_1_28 = old_config.into(); let updated_step2: ConfigV1_1_29 = updated_step1.into(); - let updated_step3: ConfigV1_1_30 = updated_step2.into(); + let updated_step3: ConfigV1_1_31 = updated_step2.into(); let updated: Config = updated_step3.into(); updated .save_to_default_location() @@ -47,7 +47,7 @@ fn try_upgrade_v1_1_28_config(id: &str) -> Result { info!("It is going to get updated to the current specification."); let updated_step1: ConfigV1_1_29 = old_config.into(); - let updated_step2: ConfigV1_1_30 = updated_step1.into(); + let updated_step2: ConfigV1_1_31 = updated_step1.into(); let updated: Config = updated_step2.into(); updated .save_to_default_location() @@ -70,7 +70,7 @@ fn try_upgrade_v1_1_29_config(id: &str) -> Result { info!("It seems the gateway is using <= v1.1.29 config template."); info!("It is going to get updated to the current specification."); - let updated_step1: ConfigV1_1_30 = old_config.into(); + let updated_step1: ConfigV1_1_31 = old_config.into(); let updated: Config = updated_step1.into(); updated .save_to_default_location() @@ -83,9 +83,9 @@ fn try_upgrade_v1_1_29_config(id: &str) -> Result { Ok(true) } -fn try_upgrade_v1_1_30_config(id: &str) -> Result { +fn try_upgrade_v1_1_31_config(id: &str) -> Result { // explicitly load it as v1.1.30 (which is incompatible with the current, i.e. 1.1.31+) - let Ok(old_config) = ConfigV1_1_30::read_from_default_path(id) else { + let Ok(old_config) = ConfigV1_1_31::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); @@ -115,7 +115,7 @@ pub(crate) fn try_upgrade_config(id: &str) -> Result<(), GatewayError> { if try_upgrade_v1_1_29_config(id)? { return Ok(()); } - if try_upgrade_v1_1_30_config(id)? { + if try_upgrade_v1_1_31_config(id)? { return Ok(()); } diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index a1adbf86bf..6705d7a737 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -24,7 +24,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop}; pub(crate) mod old_config_v1_1_20; pub(crate) mod old_config_v1_1_28; pub(crate) mod old_config_v1_1_29; -pub(crate) mod old_config_v1_1_30; +pub(crate) mod old_config_v1_1_31; pub mod persistence; mod template; diff --git a/gateway/src/config/old_config_v1_1_29.rs b/gateway/src/config/old_config_v1_1_29.rs index 842e0a8275..bbd939b16a 100644 --- a/gateway/src/config/old_config_v1_1_29.rs +++ b/gateway/src/config/old_config_v1_1_29.rs @@ -11,9 +11,9 @@ use std::path::{Path, PathBuf}; use std::time::Duration; use url::Url; -use super::old_config_v1_1_30::{ - ConfigV1_1_30, DebugV1_1_30, GatewayPathsV1_1_30, GatewayV1_1_30, KeysPathsV1_1_30, - LoggingSettingsV1_1_30, NetworkRequesterV1_1_30, +use super::old_config_v1_1_31::{ + ConfigV1_1_31, DebugV1_1_31, GatewayPathsV1_1_31, GatewayV1_1_31, KeysPathsV1_1_31, + LoggingSettingsV1_1_31, NetworkRequesterV1_1_31, }; const DEFAULT_GATEWAYS_DIR: &str = "gateways"; @@ -107,9 +107,9 @@ impl ConfigV1_1_29 { } } -impl From for ConfigV1_1_30 { +impl From for ConfigV1_1_31 { fn from(value: ConfigV1_1_29) -> Self { - ConfigV1_1_30 { + ConfigV1_1_31 { save_path: value.save_path, // \/ ADDED @@ -123,7 +123,7 @@ impl From for ConfigV1_1_30 { // \/ ADDED http: Default::default(), // /\ ADDED - gateway: GatewayV1_1_30 { + gateway: GatewayV1_1_31 { version: value.gateway.version, id: value.gateway.id, only_coconut_credentials: value.gateway.only_coconut_credentials, @@ -143,8 +143,8 @@ impl From for ConfigV1_1_30 { // \/ ADDED wireguard: Default::default(), // /\ ADDED - storage_paths: GatewayPathsV1_1_30 { - keys: KeysPathsV1_1_30 { + storage_paths: GatewayPathsV1_1_31 { + keys: KeysPathsV1_1_31 { private_identity_key_file: value.storage_paths.keys.private_identity_key_file, public_identity_key_file: value.storage_paths.keys.public_identity_key_file, private_sphinx_key_file: value.storage_paths.keys.private_sphinx_key_file, @@ -153,11 +153,11 @@ impl From for ConfigV1_1_30 { clients_storage: value.storage_paths.clients_storage, network_requester_config: value.storage_paths.network_requester_config, }, - network_requester: NetworkRequesterV1_1_30 { + network_requester: NetworkRequesterV1_1_31 { enabled: value.network_requester.enabled, }, - logging: LoggingSettingsV1_1_30 {}, - debug: DebugV1_1_30 { + logging: LoggingSettingsV1_1_31 {}, + debug: DebugV1_1_31 { packet_forwarding_initial_backoff: value.debug.packet_forwarding_initial_backoff, packet_forwarding_maximum_backoff: value.debug.packet_forwarding_maximum_backoff, initial_connection_timeout: value.debug.initial_connection_timeout, diff --git a/gateway/src/config/old_config_v1_1_31.rs b/gateway/src/config/old_config_v1_1_31.rs index 66dcbdea60..122772f5ef 100644 --- a/gateway/src/config/old_config_v1_1_31.rs +++ b/gateway/src/config/old_config_v1_1_31.rs @@ -71,7 +71,7 @@ pub fn default_config_filepath>(id: P) -> PathBuf { #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] -pub struct ConfigV1_1_30 { +pub struct ConfigV1_1_31 { // additional metadata holding on-disk location of this config file #[serde(skip)] pub(crate) save_path: Option, @@ -81,31 +81,31 @@ pub struct ConfigV1_1_30 { #[serde(default)] pub http: nym_node::config::Http, - pub gateway: GatewayV1_1_30, + pub gateway: GatewayV1_1_31, #[serde(default)] // currently not really used for anything useful - pub wireguard: WireguardV1_1_30, + pub wireguard: WireguardV1_1_31, - pub storage_paths: GatewayPathsV1_1_30, + pub storage_paths: GatewayPathsV1_1_31, - pub network_requester: NetworkRequesterV1_1_30, + pub network_requester: NetworkRequesterV1_1_31, #[serde(default)] - pub logging: LoggingSettingsV1_1_30, + pub logging: LoggingSettingsV1_1_31, #[serde(default)] - pub debug: DebugV1_1_30, + pub debug: DebugV1_1_31, } -impl ConfigV1_1_30 { +impl ConfigV1_1_31 { pub fn read_from_default_path>(id: P) -> io::Result { read_config_from_toml_file(default_config_filepath(id)) } } -impl From for Config { - fn from(value: ConfigV1_1_30) -> Self { +impl From for Config { + fn from(value: ConfigV1_1_31) -> Self { Self { save_path: value.save_path, host: value.host, @@ -169,7 +169,7 @@ impl From for Config { } #[derive(Debug, Deserialize, PartialEq, Eq, Serialize)] -pub struct GatewayV1_1_30 { +pub struct GatewayV1_1_31 { /// Version of the gateway for which this configuration was created. pub version: String, @@ -220,7 +220,7 @@ pub struct GatewayV1_1_30 { #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(default)] #[serde(deny_unknown_fields)] -pub struct WireguardV1_1_30 { +pub struct WireguardV1_1_31 { /// Specifies whether the wireguard service is enabled on this node. pub enabled: bool, @@ -233,10 +233,10 @@ pub struct WireguardV1_1_30 { pub announced_port: u16, /// Paths for wireguard keys, client registries, etc. - pub storage_paths: WireguardPathsV1_1_30, + pub storage_paths: WireguardPathsV1_1_31, } -impl Default for WireguardV1_1_30 { +impl Default for WireguardV1_1_31 { fn default() -> Self { Self { enabled: false, @@ -245,21 +245,21 @@ impl Default for WireguardV1_1_30 { nym_node::config::DEFAULT_WIREGUARD_PORT, ), announced_port: nym_node::config::DEFAULT_WIREGUARD_PORT, - storage_paths: WireguardPathsV1_1_30 {}, + storage_paths: WireguardPathsV1_1_31 {}, } } } #[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] -pub struct WireguardPathsV1_1_30 { +pub struct WireguardPathsV1_1_31 { // pub keys: } #[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] -pub struct GatewayPathsV1_1_30 { - pub keys: KeysPathsV1_1_30, +pub struct GatewayPathsV1_1_31 { + pub keys: KeysPathsV1_1_31, /// Path to sqlite database containing all persistent data: messages for offline clients, /// derived shared keys and available client bandwidths. @@ -275,7 +275,7 @@ pub struct GatewayPathsV1_1_30 { } #[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] -pub struct KeysPathsV1_1_30 { +pub struct KeysPathsV1_1_31 { /// Path to file containing private identity key. pub private_identity_key_file: PathBuf, @@ -291,13 +291,13 @@ pub struct KeysPathsV1_1_30 { #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(default)] -pub struct NetworkRequesterV1_1_30 { +pub struct NetworkRequesterV1_1_31 { /// Specifies whether network requester service is enabled in this process. pub enabled: bool, } #[allow(clippy::derivable_impls)] -impl Default for NetworkRequesterV1_1_30 { +impl Default for NetworkRequesterV1_1_31 { fn default() -> Self { Self { enabled: false } } @@ -305,13 +305,13 @@ impl Default for NetworkRequesterV1_1_30 { #[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] -pub struct LoggingSettingsV1_1_30 { +pub struct LoggingSettingsV1_1_31 { // well, we need to implement something here at some point... } #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(default)] -pub struct DebugV1_1_30 { +pub struct DebugV1_1_31 { /// Initial value of an exponential backoff to reconnect to dropped TCP connection when /// forwarding sphinx packets. #[serde(with = "humantime_serde")] @@ -346,7 +346,7 @@ pub struct DebugV1_1_30 { pub use_legacy_framed_packet_version: bool, } -impl Default for DebugV1_1_30 { +impl Default for DebugV1_1_31 { fn default() -> Self { Self { packet_forwarding_initial_backoff: DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF, From 00ca4d2afa3d1e1109bf5af912cf6d3ecfb8e6c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 10:13:10 +0100 Subject: [PATCH 134/236] Rename to nym-ip-packet-router --- Cargo.lock | 4 +-- gateway/Cargo.toml | 2 +- gateway/src/commands/helpers.rs | 28 +++++++-------- gateway/src/commands/init.rs | 14 ++++---- gateway/src/commands/mod.rs | 6 ++-- gateway/src/commands/run.rs | 6 ++-- ...forwarder.rs => setup_ip_packet_router.rs} | 12 +++---- gateway/src/config/mod.rs | 16 ++++----- gateway/src/config/old_config_v1_1_31.rs | 4 +-- gateway/src/config/persistence/paths.rs | 26 +++++++------- gateway/src/config/template.rs | 6 ++-- gateway/src/error.rs | 2 +- .../embedded_network_requester/mod.rs | 2 +- gateway/src/node/helpers.rs | 6 ++-- gateway/src/node/mod.rs | 34 +++++++++---------- service-providers/ip-forwarder/Cargo.toml | 2 +- 16 files changed, 85 insertions(+), 85 deletions(-) rename gateway/src/commands/{setup_ip_forwarder.rs => setup_ip_packet_router.rs} (79%) diff --git a/Cargo.lock b/Cargo.lock index 938ab2606d..e7f8983425 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6540,7 +6540,7 @@ dependencies = [ "nym-credentials", "nym-crypto", "nym-gateway-requests", - "nym-ip-forwarder", + "nym-ip-packet-router", "nym-mixnet-client", "nym-mixnode-common", "nym-network-defaults", @@ -6645,7 +6645,7 @@ dependencies = [ ] [[package]] -name = "nym-ip-forwarder" +name = "nym-ip-packet-router" version = "0.1.0" dependencies = [ "futures", diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index b5881ef080..aa595f0584 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -76,7 +76,7 @@ nym-task = { path = "../common/task" } nym-types = { path = "../common/types" } nym-validator-client = { path = "../common/client-libs/validator-client" } nym-wireguard = { path = "../common/wireguard", optional = true } -nym-ip-forwarder = { path = "../service-providers/ip-forwarder" } +nym-ip-packet-router = { path = "../service-providers/ip-forwarder" } [dev-dependencies] tower = "0.4.13" diff --git a/gateway/src/commands/helpers.rs b/gateway/src/commands/helpers.rs index 56c9d74292..99289b8b16 100644 --- a/gateway/src/commands/helpers.rs +++ b/gateway/src/commands/helpers.rs @@ -4,7 +4,7 @@ use crate::commands::upgrade_helpers; use crate::config::default_config_filepath; use crate::config::persistence::paths::{ - default_ip_forwarder_data_dir, default_network_requester_data_dir, + default_ip_packet_router_data_dir, default_network_requester_data_dir, }; use crate::config::Config; use crate::error::GatewayError; @@ -41,7 +41,7 @@ pub(crate) struct OverrideConfig { pub(crate) nyxd_urls: Option>, pub(crate) only_coconut_credentials: Option, pub(crate) with_network_requester: Option, - pub(crate) with_ip_forwarder: Option, + pub(crate) with_ip_packet_router: Option, } impl OverrideConfig { @@ -80,15 +80,15 @@ impl OverrideConfig { Config::with_enabled_network_requester, self.with_network_requester, ) - .with_optional(Config::with_enabled_ip_forwarder, self.with_ip_forwarder); + .with_optional(Config::with_enabled_ip_packet_router, self.with_ip_packet_router); if config.network_requester.enabled && config.storage_paths.network_requester_config.is_none() { Ok(config.with_default_network_requester_config_path()) - } else if config.ip_forwarder.enabled && config.storage_paths.ip_forwarder_config.is_none() + } else if config.ip_packet_router.enabled && config.storage_paths.ip_packet_router_config.is_none() { - Ok(config.with_default_ip_forwarder_config_path()) + Ok(config.with_default_ip_packet_router_config_path()) } else { Ok(config) } @@ -236,10 +236,10 @@ pub(crate) fn override_network_requester_config( ) } -pub(crate) fn override_ip_forwarder_config( - cfg: nym_ip_forwarder::Config, +pub(crate) fn override_ip_packet_router_config( + cfg: nym_ip_packet_router::Config, _opts: Option, -) -> nym_ip_forwarder::Config { +) -> nym_ip_packet_router::Config { cfg } @@ -315,21 +315,21 @@ pub(crate) async fn initialise_local_network_requester( }) } -pub(crate) async fn initialise_local_ip_forwarder( +pub(crate) async fn initialise_local_ip_packet_router( gateway_config: &Config, opts: OverrideIpForwarderConfig, identity: identity::PublicKey, ) -> Result { info!("initialising ip forwarder..."); - let Some(ip_cfg_path) = gateway_config.storage_paths.ip_forwarder_config() else { + let Some(ip_cfg_path) = gateway_config.storage_paths.ip_packet_router_config() else { return Err(GatewayError::UnspecifiedIpForwarderConfig); }; let id = &gateway_config.gateway.id; let ip_id = make_ip_id(id); - let ip_data_dir = default_ip_forwarder_data_dir(id); - let mut ip_cfg = nym_ip_forwarder::Config::new(&ip_id).with_data_directory(ip_data_dir); - ip_cfg = override_ip_forwarder_config(ip_cfg, Some(opts)); + let ip_data_dir = default_ip_packet_router_data_dir(id); + let mut ip_cfg = nym_ip_packet_router::Config::new(&ip_id).with_data_directory(ip_data_dir); + ip_cfg = override_ip_packet_router_config(ip_cfg, Some(opts)); let key_store = OnDiskKeys::new(ip_cfg.storage_paths.common_paths.keys.clone()); let details_store = @@ -367,7 +367,7 @@ pub(crate) async fn initialise_local_ip_forwarder( } Ok(GatewayIpForwarderDetails { - enabled: gateway_config.ip_forwarder.enabled, + enabled: gateway_config.ip_packet_router.enabled, identity_key: address.identity().to_string(), encryption_key: address.encryption_key().to_string(), address: address.to_string(), diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index 286a24f21a..6fda8fa01c 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::commands::helpers::{ - initialise_local_ip_forwarder, initialise_local_network_requester, + initialise_local_ip_packet_router, initialise_local_network_requester, OverrideNetworkRequesterConfig, }; use crate::config::{default_config_directory, default_config_filepath, default_data_directory}; @@ -82,12 +82,12 @@ pub struct Init { statistics_service_url: Option, /// Allows this gateway to run an embedded network requester for minimal network overhead - #[clap(long, conflicts_with = "with_ip_forwarder")] + #[clap(long, conflicts_with = "with_ip_packet_router")] with_network_requester: bool, /// Allows this gateway to run an embedded network requester for minimal network overhead #[clap(long, hide = true, conflicts_with = "with_network_requester")] - with_ip_forwarder: bool, + with_ip_packet_router: bool, // ##### NETWORK REQUESTER FLAGS ##### /// Specifies whether this network requester should run in 'open-proxy' mode @@ -161,7 +161,7 @@ impl From for OverrideConfig { nyxd_urls: init_config.nyxd_urls, only_coconut_credentials: init_config.only_coconut_credentials, with_network_requester: Some(init_config.with_network_requester), - with_ip_forwarder: Some(init_config.with_ip_forwarder), + with_ip_packet_router: Some(init_config.with_ip_packet_router), } } } @@ -243,8 +243,8 @@ pub async fn execute(args: Init) -> anyhow::Result<()> { if config.network_requester.enabled { initialise_local_network_requester(&config, nr_opts, *identity_keys.public_key()) .await?; - } else if config.ip_forwarder.enabled { - initialise_local_ip_forwarder(&config, ip_opts, *identity_keys.public_key()).await?; + } else if config.ip_packet_router.enabled { + initialise_local_ip_packet_router(&config, ip_opts, *identity_keys.public_key()).await?; } eprintln!("Saved identity and mixnet sphinx keypairs"); @@ -293,7 +293,7 @@ mod tests { only_coconut_credentials: None, output: Default::default(), with_network_requester: false, - with_ip_forwarder: false, + with_ip_packet_router: false, open_proxy: None, enable_statistics: None, statistics_recipient: None, diff --git a/gateway/src/commands/mod.rs b/gateway/src/commands/mod.rs index 83cde5302b..41690d4af3 100644 --- a/gateway/src/commands/mod.rs +++ b/gateway/src/commands/mod.rs @@ -12,7 +12,7 @@ pub(crate) mod helpers; pub(crate) mod init; pub(crate) mod node_details; pub(crate) mod run; -pub(crate) mod setup_ip_forwarder; +pub(crate) mod setup_ip_packet_router; pub(crate) mod setup_network_requester; pub(crate) mod sign; mod upgrade_helpers; @@ -35,7 +35,7 @@ pub(crate) enum Commands { /// Add ip forwarder support to this gateway // essentially an option to include ip forwarder without having to setup fresh gateway #[command(hide = true)] - SetupIpForwarder(setup_ip_forwarder::CmdArgs), + SetupIpForwarder(setup_ip_packet_router::CmdArgs), /// Sign text to prove ownership of this mixnode Sign(sign::Sign), @@ -58,7 +58,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box node_details::execute(m).await?, Commands::Run(m) => run::execute(m).await?, Commands::SetupNetworkRequester(m) => setup_network_requester::execute(m).await?, - Commands::SetupIpForwarder(m) => setup_ip_forwarder::execute(m).await?, + Commands::SetupIpForwarder(m) => setup_ip_packet_router::execute(m).await?, Commands::Sign(m) => sign::execute(m)?, Commands::BuildInfo(m) => build_info::execute(m), Commands::Completions(s) => s.generate(&mut crate::Cli::command(), bin_name), diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index a0f807a99d..e9c1802118 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -87,12 +87,12 @@ pub struct Run { statistics_service_url: Option, /// Allows this gateway to run an embedded network requester for minimal network overhead - #[arg(long, conflicts_with = "with_ip_forwarder")] + #[arg(long, conflicts_with = "with_ip_packet_router")] with_network_requester: Option, /// Allows this gateway to run an embedded network requester for minimal network overhead #[arg(long, hide = true, conflicts_with = "with_network_requester")] - with_ip_forwarder: Option, + with_ip_packet_router: Option, // ##### NETWORK REQUESTER FLAGS ##### /// Specifies whether this network requester should run in 'open-proxy' mode @@ -163,7 +163,7 @@ impl From for OverrideConfig { nyxd_urls: run_config.nyxd_urls, only_coconut_credentials: run_config.only_coconut_credentials, with_network_requester: run_config.with_network_requester, - with_ip_forwarder: run_config.with_ip_forwarder, + with_ip_packet_router: run_config.with_ip_packet_router, } } } diff --git a/gateway/src/commands/setup_ip_forwarder.rs b/gateway/src/commands/setup_ip_packet_router.rs similarity index 79% rename from gateway/src/commands/setup_ip_forwarder.rs rename to gateway/src/commands/setup_ip_packet_router.rs index 6b8678f3ab..abe28fc350 100644 --- a/gateway/src/commands/setup_ip_forwarder.rs +++ b/gateway/src/commands/setup_ip_packet_router.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::commands::helpers::{ - initialise_local_ip_forwarder, try_load_current_config, OverrideIpForwarderConfig, + initialise_local_ip_packet_router, try_load_current_config, OverrideIpForwarderConfig, }; use crate::node::helpers::load_public_key; use clap::Args; @@ -43,22 +43,22 @@ pub async fn execute(args: CmdArgs) -> anyhow::Result<()> { // but it might be nice to be able to move files around. if let Some(custom_config_path) = args.custom_config_path { // if you specified anything as the argument, overwrite whatever was already in the config file - config.storage_paths.ip_forwarder_config = Some(custom_config_path); + config.storage_paths.ip_packet_router_config = Some(custom_config_path); } if let Some(override_enabled) = args.enabled { - config.ip_forwarder.enabled = override_enabled; + config.ip_packet_router.enabled = override_enabled; } - if config.storage_paths.ip_forwarder_config.is_none() { - config = config.with_default_ip_forwarder_config_path() + if config.storage_paths.ip_packet_router_config.is_none() { + config = config.with_default_ip_packet_router_config_path() } let identity_public_key = load_public_key( &config.storage_paths.keys.public_identity_key_file, "gateway identity", )?; - let details = initialise_local_ip_forwarder(&config, opts, identity_public_key).await?; + let details = initialise_local_ip_packet_router(&config, opts, identity_public_key).await?; config.try_save()?; args.output.to_stdout(&details); diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index 6705d7a737..b2d8cf90e2 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -102,7 +102,7 @@ pub struct Config { pub network_requester: NetworkRequester, #[serde(default)] - pub ip_forwarder: IpForwarder, + pub ip_packet_router: IpPacketRouter, #[serde(default)] pub logging: LoggingSettings, @@ -132,7 +132,7 @@ impl Config { wireguard: Default::default(), storage_paths: GatewayPaths::new_default(id.as_ref()), network_requester: Default::default(), - ip_forwarder: Default::default(), + ip_packet_router: Default::default(), logging: Default::default(), debug: Default::default(), } @@ -200,15 +200,15 @@ impl Config { self } - pub fn with_enabled_ip_forwarder(mut self, enabled_ip_forwarder: bool) -> Self { - self.ip_forwarder.enabled = enabled_ip_forwarder; + pub fn with_enabled_ip_packet_router(mut self, enabled_ip_packet_router: bool) -> Self { + self.ip_packet_router.enabled = enabled_ip_packet_router; self } - pub fn with_default_ip_forwarder_config_path(mut self) -> Self { + pub fn with_default_ip_packet_router_config_path(mut self) -> Self { self.storage_paths = self .storage_paths - .with_default_ip_forwarder_config(&self.gateway.id); + .with_default_ip_packet_router_config(&self.gateway.id); self } @@ -379,13 +379,13 @@ impl Default for NetworkRequester { #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(default)] -pub struct IpForwarder { +pub struct IpPacketRouter { /// Specifies whether ip forwarder service is enabled in this process. pub enabled: bool, } #[allow(clippy::derivable_impls)] -impl Default for IpForwarder { +impl Default for IpPacketRouter { fn default() -> Self { Self { enabled: false } } diff --git a/gateway/src/config/old_config_v1_1_31.rs b/gateway/src/config/old_config_v1_1_31.rs index 122772f5ef..6391b18115 100644 --- a/gateway/src/config/old_config_v1_1_31.rs +++ b/gateway/src/config/old_config_v1_1_31.rs @@ -142,14 +142,14 @@ impl From for Config { clients_storage: value.storage_paths.clients_storage, network_requester_config: value.storage_paths.network_requester_config, // \/ ADDED - ip_forwarder_config: Default::default(), + ip_packet_router_config: Default::default(), // /\ ADDED }, network_requester: NetworkRequester { enabled: value.network_requester.enabled, }, // \/ ADDED - ip_forwarder: Default::default(), + ip_packet_router: Default::default(), // /\ ADDED logging: LoggingSettings { // no fields (yet) diff --git a/gateway/src/config/persistence/paths.rs b/gateway/src/config/persistence/paths.rs index 14e35f4613..7c6f2f7fc2 100644 --- a/gateway/src/config/persistence/paths.rs +++ b/gateway/src/config/persistence/paths.rs @@ -15,8 +15,8 @@ pub const DEFAULT_CLIENTS_STORAGE_FILENAME: &str = "db.sqlite"; pub const DEFAULT_NETWORK_REQUESTER_CONFIG_FILENAME: &str = "network_requester_config.toml"; pub const DEFAULT_NETWORK_REQUESTER_DATA_DIR: &str = "network-requester-data"; -pub const DEFAULT_IP_FORWARDER_CONFIG_FILENAME: &str = "ip_forwarder_config.toml"; -pub const DEFAULT_IP_FORWARDER_DATA_DIR: &str = "ip-forwarder-data"; +pub const DEFAULT_IP_PACKET_ROUTER_CONFIG_FILENAME: &str = "ip_packet_router_config.toml"; +pub const DEFAULT_IP_PACKET_ROUTER_DATA_DIR: &str = "ip-packet-router-data"; // pub const DEFAULT_DESCRIPTION_FILENAME: &str = "description.toml"; @@ -24,8 +24,8 @@ pub fn default_network_requester_data_dir>(id: P) -> PathBuf { default_data_directory(id).join(DEFAULT_NETWORK_REQUESTER_DATA_DIR) } -pub fn default_ip_forwarder_data_dir>(id: P) -> PathBuf { - default_data_directory(id).join(DEFAULT_IP_FORWARDER_DATA_DIR) +pub fn default_ip_packet_router_data_dir>(id: P) -> PathBuf { + default_data_directory(id).join(DEFAULT_IP_PACKET_ROUTER_DATA_DIR) } /// makes sure that an empty path is converted into a `None` as opposed to `Some("")` @@ -59,7 +59,7 @@ pub struct GatewayPaths { // pub cosmos_bip39_mnemonic: PathBuf, /// Path to the configuration of the embedded ip forwarder. #[serde(deserialize_with = "de_maybe_path")] - pub ip_forwarder_config: Option, + pub ip_packet_router_config: Option, } impl GatewayPaths { @@ -69,7 +69,7 @@ impl GatewayPaths { clients_storage: default_data_directory(id).join(DEFAULT_CLIENTS_STORAGE_FILENAME), // node_description: default_config_filepath(id).join(DEFAULT_DESCRIPTION_FILENAME), network_requester_config: None, - ip_forwarder_config: None, + ip_packet_router_config: None, } } @@ -87,15 +87,15 @@ impl GatewayPaths { } #[must_use] - pub fn with_ip_forwarder_config>(mut self, path: P) -> Self { - self.ip_forwarder_config = Some(path.as_ref().into()); + pub fn with_ip_packet_router_config>(mut self, path: P) -> Self { + self.ip_packet_router_config = Some(path.as_ref().into()); self } #[must_use] - pub fn with_default_ip_forwarder_config>(self, id: P) -> Self { - self.with_ip_forwarder_config( - default_config_directory(id).join(DEFAULT_IP_FORWARDER_CONFIG_FILENAME), + pub fn with_default_ip_packet_router_config>(self, id: P) -> Self { + self.with_ip_packet_router_config( + default_config_directory(id).join(DEFAULT_IP_PACKET_ROUTER_CONFIG_FILENAME), ) } @@ -103,8 +103,8 @@ impl GatewayPaths { &self.network_requester_config } - pub fn ip_forwarder_config(&self) -> &Option { - &self.ip_forwarder_config + pub fn ip_packet_router_config(&self) -> &Option { + &self.ip_packet_router_config } pub fn private_identity_key(&self) -> &Path { diff --git a/gateway/src/config/template.rs b/gateway/src/config/template.rs index 24867e10c4..c64b14aa1a 100644 --- a/gateway/src/config/template.rs +++ b/gateway/src/config/template.rs @@ -82,9 +82,9 @@ landing_page_assets_path = '{{ http.landing_page_assets_path }}' # Specifies whether network requester service is enabled in this process. enabled = {{ network_requester.enabled }} -[ip_forwarder] -# Specifies whether ip forwarder service is enabled in this process. -enabled = {{ ip_forwarder.enabled }} +[ip_packet_router] +# Specifies whether ip packet router service is enabled in this process. +enabled = {{ ip_packet_router.enabled }} [storage_paths] diff --git a/gateway/src/error.rs b/gateway/src/error.rs index 681131d8b9..7e193e4f19 100644 --- a/gateway/src/error.rs +++ b/gateway/src/error.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::node::storage::error::StorageError; -use nym_ip_forwarder::error::IpForwarderError; +use nym_ip_packet_router::error::IpForwarderError; use nym_network_requester::error::{ClientCoreError, NetworkRequesterError}; use nym_validator_client::nyxd::error::NyxdError; use nym_validator_client::nyxd::AccountId; diff --git a/gateway/src/node/client_handling/embedded_network_requester/mod.rs b/gateway/src/node/client_handling/embedded_network_requester/mod.rs index 0256592ea6..8ed7e2f978 100644 --- a/gateway/src/node/client_handling/embedded_network_requester/mod.rs +++ b/gateway/src/node/client_handling/embedded_network_requester/mod.rs @@ -30,7 +30,7 @@ impl LocalNetworkRequesterHandle { // TODO: generalize this whole thing to be general. And change the name(s). pub(crate) fn new_ip( - start_data: nym_ip_forwarder::OnStartData, + start_data: nym_ip_packet_router::OnStartData, mix_message_sender: MixMessageSender, ) -> Self { Self { diff --git a/gateway/src/node/helpers.rs b/gateway/src/node/helpers.rs index 54953e133e..50a52cd109 100644 --- a/gateway/src/node/helpers.rs +++ b/gateway/src/node/helpers.rs @@ -96,12 +96,12 @@ pub(crate) fn load_network_requester_config>( }) } -pub(crate) fn load_ip_forwarder_config>( +pub(crate) fn load_ip_packet_router_config>( id: &str, path: P, -) -> Result { +) -> Result { let path = path.as_ref(); - nym_ip_forwarder::Config::read_from_toml_file(path).map_err(|err| { + nym_ip_packet_router::Config::read_from_toml_file(path).map_err(|err| { GatewayError::IpForwarderConfigLoadFailure { id: id.to_string(), path: path.to_path_buf(), diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 0be8be5eaf..85ce12fc62 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -1,10 +1,10 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use self::helpers::load_ip_forwarder_config; +use self::helpers::load_ip_packet_router_config; use self::storage::PersistentStorage; use crate::commands::helpers::{ - override_ip_forwarder_config, override_network_requester_config, OverrideIpForwarderConfig, + override_ip_packet_router_config, override_network_requester_config, OverrideIpForwarderConfig, OverrideNetworkRequesterConfig, }; use crate::config::Config; @@ -75,10 +75,10 @@ pub(crate) async fn create_gateway( }; // don't attempt to read config if NR is disabled - let ip_forwarder_config = if config.ip_forwarder.enabled { - if let Some(path) = &config.storage_paths.ip_forwarder_config { - let cfg = load_ip_forwarder_config(&config.gateway.id, path)?; - Some(override_ip_forwarder_config(cfg, ip_config_override)) + let ip_packet_router_config = if config.ip_packet_router.enabled { + if let Some(path) = &config.storage_paths.ip_packet_router_config { + let cfg = load_ip_packet_router_config(&config.gateway.id, path)?; + Some(override_ip_packet_router_config(cfg, ip_config_override)) } else { // if NR is enabled, the config path must be specified return Err(GatewayError::UnspecifiedIpForwarderConfig); @@ -94,7 +94,7 @@ pub(crate) async fn create_gateway( custom_mixnet_path: custom_mixnet.clone(), }); - let ip_opts = ip_forwarder_config.map(|config| LocalIpForwarderOpts { + let ip_opts = ip_packet_router_config.map(|config| LocalIpForwarderOpts { config, custom_mixnet_path: custom_mixnet, }); @@ -111,7 +111,7 @@ pub struct LocalNetworkRequesterOpts { #[derive(Debug, Clone)] pub struct LocalIpForwarderOpts { - config: nym_ip_forwarder::Config, + config: nym_ip_packet_router::Config, custom_mixnet_path: Option, } @@ -121,7 +121,7 @@ pub(crate) struct Gateway { network_requester_opts: Option, - ip_forwarder_opts: Option, + ip_packet_router_opts: Option, /// ed25519 keypair used to assert one's identity. identity_keypair: Arc, @@ -138,7 +138,7 @@ impl Gateway { pub fn new( config: Config, network_requester_opts: Option, - ip_forwarder_opts: Option, + ip_packet_router_opts: Option, storage: St, ) -> Result { Ok(Gateway { @@ -147,7 +147,7 @@ impl Gateway { sphinx_keypair: Arc::new(helpers::load_sphinx_keys(&config)?), config, network_requester_opts, - ip_forwarder_opts, + ip_packet_router_opts, client_registry: Arc::new(DashMap::new()), }) } @@ -156,7 +156,7 @@ impl Gateway { pub async fn new_from_keys_and_storage( config: Config, network_requester_opts: Option, - ip_forwarder_opts: Option, + ip_packet_router_opts: Option, identity_keypair: identity::KeyPair, sphinx_keypair: encryption::KeyPair, storage: St, @@ -164,7 +164,7 @@ impl Gateway { Gateway { config, network_requester_opts, - ip_forwarder_opts, + ip_packet_router_opts, identity_keypair: Arc::new(identity_keypair), sphinx_keypair: Arc::new(sphinx_keypair), storage, @@ -327,7 +327,7 @@ impl Gateway { info!("Starting IP service provider..."); // if network requester is enabled, configuration file must be provided! - let Some(ip_opts) = &self.ip_forwarder_opts else { + let Some(ip_opts) = &self.ip_packet_router_opts else { log::error!("IP service provider is enabled but no configuration file was provided!"); return Err(GatewayError::UnspecifiedIpForwarderConfig); }; @@ -346,8 +346,8 @@ impl Gateway { // TODO: well, wire it up internally to gateway traffic, shutdowns, etc. let (on_start_tx, on_start_rx) = oneshot::channel(); - // let mut nr_builder = nym_ip_forwarder::IpForwarderBuilder::new(nr_opts.config.clone()) - let mut ip_builder = nym_ip_forwarder::IpForwarderBuilder::new(ip_opts.config.clone()) + // let mut nr_builder = nym_ip_packet_router::IpForwarderBuilder::new(nr_opts.config.clone()) + let mut ip_builder = nym_ip_packet_router::IpForwarderBuilder::new(ip_opts.config.clone()) .with_shutdown(shutdown) .with_custom_gateway_transceiver(Box::new(transceiver)) .with_wait_for_gateway(true) @@ -493,7 +493,7 @@ impl Gateway { // NOTE: this is mutually exclusive with the network requester (for now). This is reflected // in the command line arguments as well. - if self.config.ip_forwarder.enabled { + if self.config.ip_packet_router.enabled { let embedded_ip_sp = self .start_ip_service_provider( mix_forwarding_channel.clone(), diff --git a/service-providers/ip-forwarder/Cargo.toml b/service-providers/ip-forwarder/Cargo.toml index bb88978f18..c01c13cfb4 100644 --- a/service-providers/ip-forwarder/Cargo.toml +++ b/service-providers/ip-forwarder/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "nym-ip-forwarder" +name = "nym-ip-packet-router" version = "0.1.0" authors.workspace = true repository.workspace = true From 7c5183700eaf73ffcdaad402e17f9471549f53f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 10:14:01 +0100 Subject: [PATCH 135/236] Rename to ip-packet-router directory --- Cargo.toml | 2 +- gateway/Cargo.toml | 2 +- service-providers/{ip-forwarder => ip-packet-router}/Cargo.toml | 0 .../{ip-forwarder => ip-packet-router}/src/config/mod.rs | 0 .../src/config/persistence.rs | 0 .../{ip-forwarder => ip-packet-router}/src/config/template.rs | 0 .../{ip-forwarder => ip-packet-router}/src/error.rs | 0 service-providers/{ip-forwarder => ip-packet-router}/src/lib.rs | 0 8 files changed, 2 insertions(+), 2 deletions(-) rename service-providers/{ip-forwarder => ip-packet-router}/Cargo.toml (100%) rename service-providers/{ip-forwarder => ip-packet-router}/src/config/mod.rs (100%) rename service-providers/{ip-forwarder => ip-packet-router}/src/config/persistence.rs (100%) rename service-providers/{ip-forwarder => ip-packet-router}/src/config/template.rs (100%) rename service-providers/{ip-forwarder => ip-packet-router}/src/error.rs (100%) rename service-providers/{ip-forwarder => ip-packet-router}/src/lib.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 802b81f89e..3d114f689a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,7 +90,7 @@ members = [ "sdk/lib/socks5-listener", "sdk/rust/nym-sdk", "service-providers/common", - "service-providers/ip-forwarder", + "service-providers/ip-packet-router", "service-providers/network-requester", "service-providers/network-statistics", "nym-api", diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index aa595f0584..7efe36f517 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -76,7 +76,7 @@ nym-task = { path = "../common/task" } nym-types = { path = "../common/types" } nym-validator-client = { path = "../common/client-libs/validator-client" } nym-wireguard = { path = "../common/wireguard", optional = true } -nym-ip-packet-router = { path = "../service-providers/ip-forwarder" } +nym-ip-packet-router = { path = "../service-providers/ip-packet-router" } [dev-dependencies] tower = "0.4.13" diff --git a/service-providers/ip-forwarder/Cargo.toml b/service-providers/ip-packet-router/Cargo.toml similarity index 100% rename from service-providers/ip-forwarder/Cargo.toml rename to service-providers/ip-packet-router/Cargo.toml diff --git a/service-providers/ip-forwarder/src/config/mod.rs b/service-providers/ip-packet-router/src/config/mod.rs similarity index 100% rename from service-providers/ip-forwarder/src/config/mod.rs rename to service-providers/ip-packet-router/src/config/mod.rs diff --git a/service-providers/ip-forwarder/src/config/persistence.rs b/service-providers/ip-packet-router/src/config/persistence.rs similarity index 100% rename from service-providers/ip-forwarder/src/config/persistence.rs rename to service-providers/ip-packet-router/src/config/persistence.rs diff --git a/service-providers/ip-forwarder/src/config/template.rs b/service-providers/ip-packet-router/src/config/template.rs similarity index 100% rename from service-providers/ip-forwarder/src/config/template.rs rename to service-providers/ip-packet-router/src/config/template.rs diff --git a/service-providers/ip-forwarder/src/error.rs b/service-providers/ip-packet-router/src/error.rs similarity index 100% rename from service-providers/ip-forwarder/src/error.rs rename to service-providers/ip-packet-router/src/error.rs diff --git a/service-providers/ip-forwarder/src/lib.rs b/service-providers/ip-packet-router/src/lib.rs similarity index 100% rename from service-providers/ip-forwarder/src/lib.rs rename to service-providers/ip-packet-router/src/lib.rs From a088d64d57d3f68dc163317ba08a0d606f4e219a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 10:21:01 +0100 Subject: [PATCH 136/236] Fix missed rename in template --- gateway/src/config/template.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gateway/src/config/template.rs b/gateway/src/config/template.rs index c64b14aa1a..d48be52009 100644 --- a/gateway/src/config/template.rs +++ b/gateway/src/config/template.rs @@ -108,7 +108,7 @@ clients_storage = '{{ storage_paths.clients_storage }}' network_requester_config = '{{ storage_paths.network_requester_config }}' # Path to the configuration of the embedded ip forwarder. -ip_forwarder_config = '{{ storage_paths.ip_forwarder_config }}' +ip_packet_router_config = '{{ storage_paths.ip_packet_router_config }}' ##### logging configuration options ##### From b056a97c8b745a9903735a12fdf59afb2d2315cb Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Tue, 31 Oct 2023 10:25:19 +0100 Subject: [PATCH 137/236] Update changelog and bump binaries --- CHANGELOG.md | 25 ++++++++++++++++--- Cargo.lock | 18 ++++++------- clients/native/Cargo.toml | 2 +- clients/socks5/Cargo.toml | 2 +- explorer-api/Cargo.toml | 2 +- gateway/Cargo.toml | 2 +- mixnode/Cargo.toml | 2 +- nym-api/Cargo.toml | 2 +- nym-wallet/CHANGELOG.md | 8 ++++++ nym-wallet/package.json | 4 +-- nym-wallet/src-tauri/Cargo.toml | 2 +- nym-wallet/src-tauri/tauri.conf.json | 2 +- .../network-requester/Cargo.toml | 2 +- .../network-statistics/Cargo.toml | 2 +- tools/nym-cli/Cargo.toml | 2 +- 15 files changed, 52 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0db3dfaf1f..04209d93f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,28 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] -- add client registry to Gateway ([#3955]) -- add HTTP API to Gateway ([#3955]) -- add `/client/`, `clients` and `register` routes to the gateway ([#3955]) + +## [2023.3-kinder] (2023-10-31) + +- suppress error output ([#4056]) +- Update frontend type for current vesting period ([#4042]) +- re-exported additional types for tx queries ([#4036]) +- fixed fmt::Display impl for GatewayNetworkRequesterDetails ([#4033]) +- Add exit node policy from TorNull and Tor Exit Node Policy ([#4024]) +- basic self-described api for gateways to dynamically announce its details + nym-api aggregation ([#4017]) +- use saturating sub in case outfox is not enabled ([#3986]) +- Fix sorting for mixnodes and gateways ([#3985]) +- Gateway client registry and api routes ([#3955]) + +[#4056]: https://github.com/nymtech/nym/pull/4056 +[#4042]: https://github.com/nymtech/nym/pull/4042 +[#4036]: https://github.com/nymtech/nym/pull/4036 +[#4033]: https://github.com/nymtech/nym/pull/4033 +[#4024]: https://github.com/nymtech/nym/issues/4024 +[#4017]: https://github.com/nymtech/nym/issues/4017 +[#3986]: https://github.com/nymtech/nym/pull/3986 +[#3985]: https://github.com/nymtech/nym/pull/3985 +[#3955]: https://github.com/nymtech/nym/pull/3955 ## [2023.1-milka] (2023-09-24) diff --git a/Cargo.lock b/Cargo.lock index 614ed8738a..8fe828d128 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2938,7 +2938,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "explorer-api" -version = "1.1.30" +version = "1.1.31" dependencies = [ "chrono", "clap 4.4.6", @@ -5951,7 +5951,7 @@ dependencies = [ [[package]] name = "nym-api" -version = "1.1.31" +version = "1.1.32" dependencies = [ "actix-web", "anyhow", @@ -6101,7 +6101,7 @@ dependencies = [ [[package]] name = "nym-cli" -version = "1.1.30" +version = "1.1.31" dependencies = [ "anyhow", "base64 0.13.1", @@ -6174,7 +6174,7 @@ dependencies = [ [[package]] name = "nym-client" -version = "1.1.30" +version = "1.1.31" dependencies = [ "clap 4.4.6", "dirs 4.0.0", @@ -6516,7 +6516,7 @@ dependencies = [ [[package]] name = "nym-gateway" -version = "1.1.30" +version = "1.1.31" dependencies = [ "anyhow", "async-trait", @@ -6694,7 +6694,7 @@ dependencies = [ [[package]] name = "nym-mixnode" -version = "1.1.31" +version = "1.1.32" dependencies = [ "anyhow", "bs58 0.4.0", @@ -6812,7 +6812,7 @@ dependencies = [ [[package]] name = "nym-network-requester" -version = "1.1.30" +version = "1.1.31" dependencies = [ "anyhow", "async-file-watcher", @@ -6860,7 +6860,7 @@ dependencies = [ [[package]] name = "nym-network-statistics" -version = "1.1.30" +version = "1.1.31" dependencies = [ "dirs 4.0.0", "log", @@ -7103,7 +7103,7 @@ dependencies = [ [[package]] name = "nym-socks5-client" -version = "1.1.30" +version = "1.1.31" dependencies = [ "clap 4.4.6", "lazy_static", diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 57df3570b3..ee2579c611 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-client" -version = "1.1.30" +version = "1.1.31" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] description = "Implementation of the Nym Client" edition = "2021" diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index 7ea0469c74..56e384621e 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-socks5-client" -version = "1.1.30" +version = "1.1.31" authors = ["Dave Hrycyszyn "] description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" edition = "2021" diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index 935a76cb52..a222daeef4 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "explorer-api" -version = "1.1.30" +version = "1.1.31" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index b968ee7b7e..5cba6ced36 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-gateway" -version = "1.1.30" +version = "1.1.31" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index 37268c654d..e749808652 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-mixnode" -version = "1.1.31" +version = "1.1.32" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 4691bf250f..32725e1a40 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-api" -version = "1.1.31" +version = "1.1.32" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/nym-wallet/CHANGELOG.md b/nym-wallet/CHANGELOG.md index e14caee027..1d29030497 100644 --- a/nym-wallet/CHANGELOG.md +++ b/nym-wallet/CHANGELOG.md @@ -2,6 +2,14 @@ ## [Unreleased] +## [v1.2.10] (2023-10-31) + +- Add loading model on initial load of delegations ([#4039]) +- remove any whitespace from input field when bonding host ([#4062]) + +[#4039]: https://github.com/nymtech/nym/pull/4039 +[#4062]: https://github.com/nymtech/nym/pull/4062 + ## [v1.2.9] (2023-10-10) - Wallet: Introduce edit account name ([#3895]) diff --git a/nym-wallet/package.json b/nym-wallet/package.json index c930554e2b..93b1793711 100644 --- a/nym-wallet/package.json +++ b/nym-wallet/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/nym-wallet-app", - "version": "1.2.9", + "version": "1.2.10", "main": "index.js", "license": "MIT", "scripts": { @@ -124,4 +124,4 @@ "webpack-favicons": "^1.3.8", "webpack-merge": "^5.8.0" } -} +} \ No newline at end of file diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index 24c79219b7..eaced888a4 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym_wallet" -version = "1.2.9" +version = "1.2.10" description = "Nym Native Wallet" authors = ["Nym Technologies SA"] license = "" diff --git a/nym-wallet/src-tauri/tauri.conf.json b/nym-wallet/src-tauri/tauri.conf.json index 9b87728fd4..43330b2587 100644 --- a/nym-wallet/src-tauri/tauri.conf.json +++ b/nym-wallet/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "package": { "productName": "nym-wallet", - "version": "1.2.9" + "version": "1.2.10" }, "build": { "distDir": "../dist", diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 42c54bc0b2..0035d67cc3 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-network-requester" -version = "1.1.30" +version = "1.1.31" authors.workspace = true edition.workspace = true rust-version = "1.65" diff --git a/service-providers/network-statistics/Cargo.toml b/service-providers/network-statistics/Cargo.toml index 280a231309..e2f5d56ae1 100644 --- a/service-providers/network-statistics/Cargo.toml +++ b/service-providers/network-statistics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-network-statistics" -version = "1.1.30" +version = "1.1.31" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index def3dc32eb..6cf8da9d8c 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-cli" -version = "1.1.30" +version = "1.1.31" authors.workspace = true edition = "2021" From 9e33454dc2e06fd1d776dd45bdc869e4d1cb9562 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 31 Oct 2023 10:34:31 +0100 Subject: [PATCH 138/236] add exit policy implementation steps --- documentation/operators/src/faq/smoosh-faq.md | 10 +++++++++- documentation/operators/src/legal/exit-gateway.md | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index 4c1342c326..5f312f8267 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -24,7 +24,7 @@ As we shared in our blog post article [*What does it take to build the wolds mos Project smoosh will have three steps: 1. Combine the `gateway` and `network-requester` into one binary ✅ -2. Create [exit gateway](../legal/exit-gateway.md): Take the gateway binary including network requester combined in \#1 and switch from *allowed.list* to a new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) ✅ +2. Create [exit gateway](../legal/exit-gateway.md): Take the gateway binary including network requester combined in \#1 and switch from [*allowed.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) ✅ 3. Combine all the nodes in the Nym Mixnet into one binary, that is `mixnode`, `gateway` (entry and exit) and `network-requester`. These three steps will be staggered over time - period of several months, and will be implemented one by one with enough time to take in feedback and fix bugs in between. @@ -38,6 +38,14 @@ We are exploring two potential methods for implementing binary functionality in 2. All nodes will be required to have the exit gateway functionality. All nodes are rewarded the same as now, and the difference is that a node sometimes (some epochs) may be performing as exit gateway sometimes as mix node or entry gateway adjusted according the network demand by an algorithm. +### How will the design be implemented? + +The progression will have three steps: + +1. By default the [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) filtering will be disabled and the current [*allow.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) filtering is going to continue be used. This is to prevent operators getting surprised by upgrading their gateways/network requesters and suddenly be widely open to the internet. To enable the new exit policy, operators must use `--with-exit-policy` flag or modify the *config.toml* file. ✅ +2. Relatively soon the exit policy will become the default. +3. Further down the line, it will be the only option. Then the *allowed.list* will be completely removed. + ### Where can I read more about the exit gateway setup? We created an [entire page](../legal/exit-gateway.md) about the technical and legal questions around exit gateway. diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index 2cd3f03daa..328633faf2 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -22,7 +22,7 @@ Nym core team cannot provide comprehensive legal advice across all jurisdictions * Currently, Nym Gateway nodes only enable access to apps and services that are on an ‘allow’ list that is maintained by the core team. -* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list - [Exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). In accordance with the [Tor Null 'deny' list](https://tornull.org/) and [Tor reduced policy] (https://tornull.org/tor-reduced-reduced-exit-policy.php), which are two established safeguards. +* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list - [Exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). In accordance with the [Tor Null 'deny' list](https://tornull.org/) and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php), which are two established safeguards. * This will enhance the usage and appeal of Nym products for end users. As a result, increased usage will ultimately lead to higher revenues for Nym operators. From b10aa52eca25742f23528a48eb3ee8783555549d Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 31 Oct 2023 10:35:30 +0100 Subject: [PATCH 139/236] add exit policy implementation steps --- documentation/operators/src/faq/smoosh-faq.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index 5f312f8267..a5d16d5092 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -38,14 +38,6 @@ We are exploring two potential methods for implementing binary functionality in 2. All nodes will be required to have the exit gateway functionality. All nodes are rewarded the same as now, and the difference is that a node sometimes (some epochs) may be performing as exit gateway sometimes as mix node or entry gateway adjusted according the network demand by an algorithm. -### How will the design be implemented? - -The progression will have three steps: - -1. By default the [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) filtering will be disabled and the current [*allow.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) filtering is going to continue be used. This is to prevent operators getting surprised by upgrading their gateways/network requesters and suddenly be widely open to the internet. To enable the new exit policy, operators must use `--with-exit-policy` flag or modify the *config.toml* file. ✅ -2. Relatively soon the exit policy will become the default. -3. Further down the line, it will be the only option. Then the *allowed.list* will be completely removed. - ### Where can I read more about the exit gateway setup? We created an [entire page](../legal/exit-gateway.md) about the technical and legal questions around exit gateway. @@ -54,8 +46,17 @@ We created an [entire page](../legal/exit-gateway.md) about the technical and le The operators running `gateways` would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short allow list to a more permissive setup. An [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients. +### How will the design be implemented? + +The progression will have three steps: + +1. By default the [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) filtering will be disabled and the current [*allow.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) filtering is going to continue be used. This is to prevent operators getting surprised by upgrading their gateways/network requesters and suddenly be widely open to the internet. To enable the new exit policy, operators must use `--with-exit-policy` flag or modify the *config.toml* file. ✅ +2. Relatively soon the exit policy will become the default. +3. Further down the line, it will be the only option. Then the *allowed.list* will be completely removed. + ### Can I run a mix node only? + Depends which [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators) will be the final one. In case of the first one - yes. In case of the second option, all the nodes will be setup with gateway functionality turned on. ## Token Economics & Rewards From b83e756650333fc542a1875951fb05407f1d8721 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 31 Oct 2023 10:37:41 +0100 Subject: [PATCH 140/236] syntax fix --- documentation/operators/src/faq/smoosh-faq.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index a5d16d5092..2a90841283 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -44,13 +44,13 @@ We created an [entire page](../legal/exit-gateway.md) about the technical and le ### What is the change from allow list to deny list? -The operators running `gateways` would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short allow list to a more permissive setup. An [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients. +The operators running Gateways would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short [*allowed.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a more permissive setup. An [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients. ### How will the design be implemented? The progression will have three steps: -1. By default the [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) filtering will be disabled and the current [*allow.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) filtering is going to continue be used. This is to prevent operators getting surprised by upgrading their gateways/network requesters and suddenly be widely open to the internet. To enable the new exit policy, operators must use `--with-exit-policy` flag or modify the *config.toml* file. ✅ +1. By default the [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) filtering will be disabled and the current [*allowed.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) filtering is going to continue be used. This is to prevent operators getting surprised by upgrading their gateways/network requesters and suddenly be widely open to the internet. To enable the new exit policy, operators must use `--with-exit-policy` flag or modify the *config.toml* file. ✅ 2. Relatively soon the exit policy will become the default. 3. Further down the line, it will be the only option. Then the *allowed.list* will be completely removed. From 70d0aabbc13917896e3a4f747984ff26f39a5c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 10:37:46 +0100 Subject: [PATCH 141/236] Big chunk of search replace to the new name --- common/types/src/gateway.rs | 6 +-- gateway/src/commands/helpers.rs | 22 +++++------ gateway/src/commands/init.rs | 6 +-- gateway/src/commands/mod.rs | 8 ++-- gateway/src/commands/run.rs | 6 +-- .../src/commands/setup_ip_packet_router.rs | 12 +++--- gateway/src/config/mod.rs | 2 +- gateway/src/config/persistence/paths.rs | 2 +- gateway/src/config/template.rs | 2 +- gateway/src/error.rs | 16 ++++---- gateway/src/node/helpers.rs | 2 +- gateway/src/node/mod.rs | 39 +++++++++---------- 12 files changed, 61 insertions(+), 62 deletions(-) diff --git a/common/types/src/gateway.rs b/common/types/src/gateway.rs index 9c0dc8541a..3b546320b6 100644 --- a/common/types/src/gateway.rs +++ b/common/types/src/gateway.rs @@ -148,7 +148,7 @@ impl fmt::Display for GatewayNetworkRequesterDetails { } #[derive(Serialize, Deserialize)] -pub struct GatewayIpForwarderDetails { +pub struct GatewayIpPacketRouterDetails { pub enabled: bool, pub identity_key: String, @@ -160,9 +160,9 @@ pub struct GatewayIpForwarderDetails { pub config_path: String, } -impl fmt::Display for GatewayIpForwarderDetails { +impl fmt::Display for GatewayIpPacketRouterDetails { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "IP forwarder:")?; + writeln!(f, "IP packet router:")?; writeln!(f, "\tenabled: {}", self.enabled)?; writeln!(f, "\tconfig path: {}", self.config_path)?; diff --git a/gateway/src/commands/helpers.rs b/gateway/src/commands/helpers.rs index 99289b8b16..984465ecc7 100644 --- a/gateway/src/commands/helpers.rs +++ b/gateway/src/commands/helpers.rs @@ -19,7 +19,7 @@ use nym_network_requester::config::BaseClientConfig; use nym_network_requester::{ setup_gateway, GatewaySelectionSpecification, GatewaySetup, OnDiskGatewayDetails, OnDiskKeys, }; -use nym_types::gateway::{GatewayIpForwarderDetails, GatewayNetworkRequesterDetails}; +use nym_types::gateway::{GatewayIpPacketRouterDetails, GatewayNetworkRequesterDetails}; use nym_validator_client::nyxd::AccountId; use std::net::IpAddr; use std::path::PathBuf; @@ -109,7 +109,7 @@ pub(crate) struct OverrideNetworkRequesterConfig { } #[derive(Default)] -pub(crate) struct OverrideIpForwarderConfig { +pub(crate) struct OverrideIpPacketRouterConfig { // TODO } @@ -174,7 +174,7 @@ fn make_nr_id(gateway_id: &str) -> String { } fn make_ip_id(gateway_id: &str) -> String { - format!("{gateway_id}-ip-forwarder") + format!("{gateway_id}-ip-packet-router") } // NOTE: make sure this is in sync with service-providers/network-requester/src/cli/mod.rs::override_config @@ -238,7 +238,7 @@ pub(crate) fn override_network_requester_config( pub(crate) fn override_ip_packet_router_config( cfg: nym_ip_packet_router::Config, - _opts: Option, + _opts: Option, ) -> nym_ip_packet_router::Config { cfg } @@ -317,12 +317,12 @@ pub(crate) async fn initialise_local_network_requester( pub(crate) async fn initialise_local_ip_packet_router( gateway_config: &Config, - opts: OverrideIpForwarderConfig, + opts: OverrideIpPacketRouterConfig, identity: identity::PublicKey, -) -> Result { - info!("initialising ip forwarder..."); +) -> Result { + info!("initialising ip packet router..."); let Some(ip_cfg_path) = gateway_config.storage_paths.ip_packet_router_config() else { - return Err(GatewayError::UnspecifiedIpForwarderConfig); + return Err(GatewayError::UnspecifiedIpPacketRouterConfig); }; let id = &gateway_config.gateway.id; @@ -353,7 +353,7 @@ pub(crate) async fn initialise_local_ip_packet_router( let address = init_res.client_address()?; if let Err(err) = save_formatted_config_to_file(&ip_cfg, ip_cfg_path) { - log::error!("Failed to save the ip forwarder config file: {err}"); + log::error!("Failed to save the ip packet router config file: {err}"); return Err(GatewayError::ConfigSaveFailure { id: ip_id, path: ip_cfg_path.to_path_buf(), @@ -361,12 +361,12 @@ pub(crate) async fn initialise_local_ip_packet_router( }); } else { eprintln!( - "Saved ip forwarder configuration file to {}", + "Saved ip packet router configuration file to {}", ip_cfg_path.display() ) } - Ok(GatewayIpForwarderDetails { + Ok(GatewayIpPacketRouterDetails { enabled: gateway_config.ip_packet_router.enabled, identity_key: address.identity().to_string(), encryption_key: address.encryption_key().to_string(), diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index 6fda8fa01c..22a142228c 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -15,7 +15,7 @@ use std::net::IpAddr; use std::path::PathBuf; use std::{fs, io}; -use super::helpers::OverrideIpForwarderConfig; +use super::helpers::OverrideIpPacketRouterConfig; #[derive(Args, Clone)] pub struct Init { @@ -180,9 +180,9 @@ impl<'a> From<&'a Init> for OverrideNetworkRequesterConfig { } } -impl From<&Init> for OverrideIpForwarderConfig { +impl From<&Init> for OverrideIpPacketRouterConfig { fn from(_value: &Init) -> Self { - OverrideIpForwarderConfig {} + OverrideIpPacketRouterConfig {} } } diff --git a/gateway/src/commands/mod.rs b/gateway/src/commands/mod.rs index 41690d4af3..99c10869a5 100644 --- a/gateway/src/commands/mod.rs +++ b/gateway/src/commands/mod.rs @@ -32,10 +32,10 @@ pub(crate) enum Commands { // essentially an option to include NR without having to setup fresh gateway SetupNetworkRequester(setup_network_requester::CmdArgs), - /// Add ip forwarder support to this gateway - // essentially an option to include ip forwarder without having to setup fresh gateway + /// Add ip packet router support to this gateway + // essentially an option to include ip packet router without having to setup fresh gateway #[command(hide = true)] - SetupIpForwarder(setup_ip_packet_router::CmdArgs), + SetupIpPacketRouter(setup_ip_packet_router::CmdArgs), /// Sign text to prove ownership of this mixnode Sign(sign::Sign), @@ -58,7 +58,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box node_details::execute(m).await?, Commands::Run(m) => run::execute(m).await?, Commands::SetupNetworkRequester(m) => setup_network_requester::execute(m).await?, - Commands::SetupIpForwarder(m) => setup_ip_packet_router::execute(m).await?, + Commands::SetupIpPacketRouter(m) => setup_ip_packet_router::execute(m).await?, Commands::Sign(m) => sign::execute(m)?, Commands::BuildInfo(m) => build_info::execute(m), Commands::Completions(s) => s.generate(&mut crate::Cli::command(), bin_name), diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index e9c1802118..8e57b7b998 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -15,7 +15,7 @@ use nym_node::error::NymNodeError; use std::net::IpAddr; use std::path::PathBuf; -use super::helpers::OverrideIpForwarderConfig; +use super::helpers::OverrideIpPacketRouterConfig; #[derive(Args, Clone)] pub struct Run { @@ -182,9 +182,9 @@ impl<'a> From<&'a Run> for OverrideNetworkRequesterConfig { } } -impl From<&Run> for OverrideIpForwarderConfig { +impl From<&Run> for OverrideIpPacketRouterConfig { fn from(_value: &Run) -> Self { - OverrideIpForwarderConfig {} + OverrideIpPacketRouterConfig {} } } diff --git a/gateway/src/commands/setup_ip_packet_router.rs b/gateway/src/commands/setup_ip_packet_router.rs index abe28fc350..633c2a4bab 100644 --- a/gateway/src/commands/setup_ip_packet_router.rs +++ b/gateway/src/commands/setup_ip_packet_router.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::commands::helpers::{ - initialise_local_ip_packet_router, try_load_current_config, OverrideIpForwarderConfig, + initialise_local_ip_packet_router, try_load_current_config, OverrideIpPacketRouterConfig, }; use crate::node::helpers::load_public_key; use clap::Args; @@ -11,15 +11,15 @@ use std::path::PathBuf; #[derive(Args, Clone)] pub struct CmdArgs { - /// The id of the gateway you want to initialise local ip forwarder for. + /// The id of the gateway you want to initialise local ip packet router for. #[arg(long)] id: String, - /// Path to custom location for ip forward's config. + /// Path to custom location for ip packet routers' config. #[arg(long)] custom_config_path: Option, - /// Specify whether the ip forwarder should be enabled. + /// Specify whether the ip packet router should be enabled. // (you might want to create all the configs, generate keys, etc. but not actually run the NR just yet) #[arg(long)] enabled: Option, @@ -28,9 +28,9 @@ pub struct CmdArgs { output: OutputFormat, } -impl From<&CmdArgs> for OverrideIpForwarderConfig { +impl From<&CmdArgs> for OverrideIpPacketRouterConfig { fn from(_value: &CmdArgs) -> Self { - OverrideIpForwarderConfig {} + OverrideIpPacketRouterConfig {} } } diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index b2d8cf90e2..4737f38c58 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -380,7 +380,7 @@ impl Default for NetworkRequester { #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(default)] pub struct IpPacketRouter { - /// Specifies whether ip forwarder service is enabled in this process. + /// Specifies whether ip packet router service is enabled in this process. pub enabled: bool, } diff --git a/gateway/src/config/persistence/paths.rs b/gateway/src/config/persistence/paths.rs index 7c6f2f7fc2..340b4a6495 100644 --- a/gateway/src/config/persistence/paths.rs +++ b/gateway/src/config/persistence/paths.rs @@ -57,7 +57,7 @@ pub struct GatewayPaths { // pub node_description: PathBuf, // pub cosmos_bip39_mnemonic: PathBuf, - /// Path to the configuration of the embedded ip forwarder. + /// Path to the configuration of the embedded ip packet router. #[serde(deserialize_with = "de_maybe_path")] pub ip_packet_router_config: Option, } diff --git a/gateway/src/config/template.rs b/gateway/src/config/template.rs index d48be52009..040a92bddd 100644 --- a/gateway/src/config/template.rs +++ b/gateway/src/config/template.rs @@ -107,7 +107,7 @@ clients_storage = '{{ storage_paths.clients_storage }}' # Path to the configuration of the embedded network requester. network_requester_config = '{{ storage_paths.network_requester_config }}' -# Path to the configuration of the embedded ip forwarder. +# Path to the configuration of the embedded ip packet router. ip_packet_router_config = '{{ storage_paths.ip_packet_router_config }}' ##### logging configuration options ##### diff --git a/gateway/src/error.rs b/gateway/src/error.rs index 7e193e4f19..d69b8eb480 100644 --- a/gateway/src/error.rs +++ b/gateway/src/error.rs @@ -50,10 +50,10 @@ pub(crate) enum GatewayError { }, #[error( - "failed to load config file for ip forwarder (gateway-id: '{id}') using path '{}'. detailed message: {source}", + "failed to load config file for ip packet router (gateway-id: '{id}') using path '{}'. detailed message: {source}", path.display() )] - IpForwarderConfigLoadFailure { + IpPacketRouterConfigLoadFailure { id: String, path: PathBuf, #[source] @@ -98,8 +98,8 @@ pub(crate) enum GatewayError { #[error("Path to network requester configuration file hasn't been specified. Perhaps try to run `setup-network-requester`?")] UnspecifiedNetworkRequesterConfig, - #[error("Path to ip forwarder configuration file hasn't been specified. Perhaps try to run `setup-ip-forwarder`?")] - UnspecifiedIpForwarderConfig, + #[error("Path to ip packet router configuration file hasn't been specified. Perhaps try to run `setup-ip-packet-router`?")] + UnspecifiedIpPacketRouterConfig, #[error("there was an issue with the local network requester: {source}")] NetworkRequesterFailure { @@ -107,8 +107,8 @@ pub(crate) enum GatewayError { source: NetworkRequesterError, }, - #[error("there was an issue with the local ip forwarder: {source}")] - IpForwarederFailure { + #[error("there was an issue with the local ip packet router: {source}")] + IpPacketRouterFailure { #[from] source: IpForwarderError, }, @@ -116,8 +116,8 @@ pub(crate) enum GatewayError { #[error("failed to startup local network requester")] NetworkRequesterStartupFailure, - #[error("failed to startup local ip forwarder")] - IpForwarderStartupFailure, + #[error("failed to startup local ip packet router")] + IpPacketRouterStartupFailure, #[error("there are no nym API endpoints available")] NoNymApisAvailable, diff --git a/gateway/src/node/helpers.rs b/gateway/src/node/helpers.rs index 50a52cd109..0b8fc9c994 100644 --- a/gateway/src/node/helpers.rs +++ b/gateway/src/node/helpers.rs @@ -102,7 +102,7 @@ pub(crate) fn load_ip_packet_router_config>( ) -> Result { let path = path.as_ref(); nym_ip_packet_router::Config::read_from_toml_file(path).map_err(|err| { - GatewayError::IpForwarderConfigLoadFailure { + GatewayError::IpPacketRouterConfigLoadFailure { id: id.to_string(), path: path.to_path_buf(), source: err, diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 85ce12fc62..f39f19f932 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -4,7 +4,7 @@ use self::helpers::load_ip_packet_router_config; use self::storage::PersistentStorage; use crate::commands::helpers::{ - override_ip_packet_router_config, override_network_requester_config, OverrideIpForwarderConfig, + override_ip_packet_router_config, override_network_requester_config, OverrideIpPacketRouterConfig, OverrideNetworkRequesterConfig, }; use crate::config::Config; @@ -58,7 +58,7 @@ struct StartedNetworkRequester { pub(crate) async fn create_gateway( config: Config, nr_config_override: Option, - ip_config_override: Option, + ip_config_override: Option, custom_mixnet: Option, ) -> Result { // don't attempt to read config if NR is disabled @@ -81,7 +81,7 @@ pub(crate) async fn create_gateway( Some(override_ip_packet_router_config(cfg, ip_config_override)) } else { // if NR is enabled, the config path must be specified - return Err(GatewayError::UnspecifiedIpForwarderConfig); + return Err(GatewayError::UnspecifiedIpPacketRouterConfig); } } else { None @@ -94,7 +94,7 @@ pub(crate) async fn create_gateway( custom_mixnet_path: custom_mixnet.clone(), }); - let ip_opts = ip_packet_router_config.map(|config| LocalIpForwarderOpts { + let ip_opts = ip_packet_router_config.map(|config| LocalIpPacketRouterOpts { config, custom_mixnet_path: custom_mixnet, }); @@ -110,7 +110,7 @@ pub struct LocalNetworkRequesterOpts { } #[derive(Debug, Clone)] -pub struct LocalIpForwarderOpts { +pub struct LocalIpPacketRouterOpts { config: nym_ip_packet_router::Config, custom_mixnet_path: Option, @@ -121,7 +121,7 @@ pub(crate) struct Gateway { network_requester_opts: Option, - ip_packet_router_opts: Option, + ip_packet_router_opts: Option, /// ed25519 keypair used to assert one's identity. identity_keypair: Arc, @@ -138,7 +138,7 @@ impl Gateway { pub fn new( config: Config, network_requester_opts: Option, - ip_packet_router_opts: Option, + ip_packet_router_opts: Option, storage: St, ) -> Result { Ok(Gateway { @@ -156,7 +156,7 @@ impl Gateway { pub async fn new_from_keys_and_storage( config: Config, network_requester_opts: Option, - ip_packet_router_opts: Option, + ip_packet_router_opts: Option, identity_keypair: identity::KeyPair, sphinx_keypair: encryption::KeyPair, storage: St, @@ -319,17 +319,17 @@ impl Gateway { }) } - async fn start_ip_service_provider( + async fn start_ip_packet_router( &self, forwarding_channel: MixForwardingSender, shutdown: TaskClient, ) -> Result { - info!("Starting IP service provider..."); + info!("Starting IP packet provider..."); // if network requester is enabled, configuration file must be provided! let Some(ip_opts) = &self.ip_packet_router_opts else { - log::error!("IP service provider is enabled but no configuration file was provided!"); - return Err(GatewayError::UnspecifiedIpForwarderConfig); + log::error!("IP packet router is enabled but no configuration file was provided!"); + return Err(GatewayError::UnspecifiedIpPacketRouterConfig); }; // this gateway, whenever it has anything to send to its local NR will use fake_client_tx @@ -346,7 +346,6 @@ impl Gateway { // TODO: well, wire it up internally to gateway traffic, shutdowns, etc. let (on_start_tx, on_start_rx) = oneshot::channel(); - // let mut nr_builder = nym_ip_packet_router::IpForwarderBuilder::new(nr_opts.config.clone()) let mut ip_builder = nym_ip_packet_router::IpForwarderBuilder::new(ip_opts.config.clone()) .with_shutdown(shutdown) .with_custom_gateway_transceiver(Box::new(transceiver)) @@ -359,25 +358,25 @@ impl Gateway { tokio::spawn(async move { if let Err(err) = ip_builder.run_service_provider().await { - // no need to panic as we have passed a task client to the ip forwarder so we're - // most likely already in the process of shutting down - error!("ip forwarder has failed: {err}") + // no need to panic as we have passed a task client to the ip packet router so + // we're most likely already in the process of shutting down + error!("ip packet router has failed: {err}") } }); let start_data = on_start_rx .await - .map_err(|_| GatewayError::IpForwarderStartupFailure)?; + .map_err(|_| GatewayError::IpPacketRouterStartupFailure)?; // this should be instantaneous since the data is sent on this channel before the on start is called; // the failure should be impossible let Ok(Some(packet_router)) = router_rx.try_recv() else { - return Err(GatewayError::IpForwarderStartupFailure); + return Err(GatewayError::IpPacketRouterStartupFailure); }; MessageRouter::new(nr_mix_receiver, packet_router).start_with_shutdown(router_shutdown); info!( - "the local ip forwarder is running on {}", + "the local ip packet router is running on {}", start_data.address ); @@ -495,7 +494,7 @@ impl Gateway { // in the command line arguments as well. if self.config.ip_packet_router.enabled { let embedded_ip_sp = self - .start_ip_service_provider( + .start_ip_packet_router( mix_forwarding_channel.clone(), shutdown.subscribe().named("ip_service_provider"), ) From 3307e7e0fc9a177a2f8be259bae382fd7ac87c4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 10:38:30 +0100 Subject: [PATCH 142/236] rustfmt --- gateway/src/commands/helpers.rs | 8 ++++++-- gateway/src/commands/init.rs | 3 ++- gateway/src/node/mod.rs | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/gateway/src/commands/helpers.rs b/gateway/src/commands/helpers.rs index 984465ecc7..f4ef8640e9 100644 --- a/gateway/src/commands/helpers.rs +++ b/gateway/src/commands/helpers.rs @@ -80,13 +80,17 @@ impl OverrideConfig { Config::with_enabled_network_requester, self.with_network_requester, ) - .with_optional(Config::with_enabled_ip_packet_router, self.with_ip_packet_router); + .with_optional( + Config::with_enabled_ip_packet_router, + self.with_ip_packet_router, + ); if config.network_requester.enabled && config.storage_paths.network_requester_config.is_none() { Ok(config.with_default_network_requester_config_path()) - } else if config.ip_packet_router.enabled && config.storage_paths.ip_packet_router_config.is_none() + } else if config.ip_packet_router.enabled + && config.storage_paths.ip_packet_router_config.is_none() { Ok(config.with_default_ip_packet_router_config_path()) } else { diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index 22a142228c..8bcfca93b7 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -244,7 +244,8 @@ pub async fn execute(args: Init) -> anyhow::Result<()> { initialise_local_network_requester(&config, nr_opts, *identity_keys.public_key()) .await?; } else if config.ip_packet_router.enabled { - initialise_local_ip_packet_router(&config, ip_opts, *identity_keys.public_key()).await?; + initialise_local_ip_packet_router(&config, ip_opts, *identity_keys.public_key()) + .await?; } eprintln!("Saved identity and mixnet sphinx keypairs"); diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index f39f19f932..d3851a671c 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -4,8 +4,8 @@ use self::helpers::load_ip_packet_router_config; use self::storage::PersistentStorage; use crate::commands::helpers::{ - override_ip_packet_router_config, override_network_requester_config, OverrideIpPacketRouterConfig, - OverrideNetworkRequesterConfig, + override_ip_packet_router_config, override_network_requester_config, + OverrideIpPacketRouterConfig, OverrideNetworkRequesterConfig, }; use crate::config::Config; use crate::error::GatewayError; From 47d0c0ffa22d76828887e725688a2ea4ff2ce9eb Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 31 Oct 2023 11:37:57 +0100 Subject: [PATCH 143/236] add exit policy implementation steps --- documentation/operators/src/faq/smoosh-faq.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index 2a90841283..c14a562534 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -51,11 +51,12 @@ The operators running Gateways would have to “open” their nodes to a wider r The progression will have three steps: 1. By default the [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) filtering will be disabled and the current [*allowed.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) filtering is going to continue be used. This is to prevent operators getting surprised by upgrading their gateways/network requesters and suddenly be widely open to the internet. To enable the new exit policy, operators must use `--with-exit-policy` flag or modify the *config.toml* file. ✅ -2. Relatively soon the exit policy will become the default. +2. Relatively soon the exit policy will become the default. To disable this exit policy, operators must use `--disable-network-requester` flag. 3. Further down the line, it will be the only option. Then the *allowed.list* will be completely removed. -### Can I run a mix node only? +Keep in mind this only relates to changes happening on Gateway and Network Requester side. Whether this will be optional or mandatory depends on the chosen [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators). +### Can I run a mix node only? Depends which [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators) will be the final one. In case of the first one - yes. In case of the second option, all the nodes will be setup with gateway functionality turned on. From b169b6b43847eedb52ed3ea0c5739dbcf5a6053f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 11:48:20 +0100 Subject: [PATCH 144/236] ci: add workflow_dispatch to ci-nym-vpn-ui-rust --- .github/workflows/ci-nym-vpn-ui-rust.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-nym-vpn-ui-rust.yml b/.github/workflows/ci-nym-vpn-ui-rust.yml index 9f21147c30..57f257e1bc 100644 --- a/.github/workflows/ci-nym-vpn-ui-rust.yml +++ b/.github/workflows/ci-nym-vpn-ui-rust.yml @@ -1,6 +1,7 @@ name: ci-nym-vpn-ui-rust on: + workflow_dispatch: push: paths: - 'nym-vpn/ui/src-tauri/**' From 99c972e88031acff32f1a0ebf8257aca5ed8aaab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 11:41:04 +0100 Subject: [PATCH 145/236] Set name to ci-nym-api-tests --- .github/workflows/ci-nym-api-tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-nym-api-tests.yml b/.github/workflows/ci-nym-api-tests.yml index fbc3d63eea..bef6e7bc06 100644 --- a/.github/workflows/ci-nym-api-tests.yml +++ b/.github/workflows/ci-nym-api-tests.yml @@ -1,4 +1,4 @@ -name: CI for Nym API Tests +name: ci-nym-api-tests on: workflow_dispatch: @@ -16,10 +16,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - + - name: Install npm run: npm install - + - name: Node v18 uses: actions/setup-node@v3 with: From f2383b5cb00efb9d94fc52092b1f6328202a411e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 31 Oct 2023 12:39:25 +0000 Subject: [PATCH 146/236] replaced '--disable-sign-ext' with '--signext-lowering' when running wasm-opt (#3896) * replaced '--disable-sign-ext' with '--signext-lowering' when running wasm-opt + updated wasm-opt * updated wasm-opt used in CI --- .github/workflows/ci-contracts-upload-binaries.yml | 4 ++-- .github/workflows/publish-nym-contracts.yml | 4 ++-- Makefile | 6 +----- contracts/mixnet/Makefile | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci-contracts-upload-binaries.yml b/.github/workflows/ci-contracts-upload-binaries.yml index c5466d7506..620012763e 100644 --- a/.github/workflows/ci-contracts-upload-binaries.yml +++ b/.github/workflows/ci-contracts-upload-binaries.yml @@ -35,14 +35,14 @@ jobs: - name: Install Rust stable uses: actions-rs/toolchain@v1 with: - toolchain: 1.69.0 + toolchain: stable target: wasm32-unknown-unknown override: true - name: Install wasm-opt uses: ./.github/actions/install-wasm-opt with: - version: '112' + version: '114' - name: Build release contracts run: make contracts diff --git a/.github/workflows/publish-nym-contracts.yml b/.github/workflows/publish-nym-contracts.yml index f1cd855e02..03c4eddb63 100644 --- a/.github/workflows/publish-nym-contracts.yml +++ b/.github/workflows/publish-nym-contracts.yml @@ -14,13 +14,13 @@ jobs: - name: Install Rust stable uses: actions-rs/toolchain@v1 with: - toolchain: 1.69.0 + toolchain: stable target: wasm32-unknown-unknown override: true components: rustfmt, clippy - name: Install wasm-opt - run: cargo install --version 0.112.0 wasm-opt + run: cargo install --version 0.114.0 wasm-opt - name: Build release contracts run: make contracts diff --git a/Makefile b/Makefile index b567e3db31..31127bc413 100644 --- a/Makefile +++ b/Makefile @@ -93,10 +93,6 @@ $(eval $(call add_cargo_workspace,contracts,contracts,--lib --target wasm32-unkn $(eval $(call add_cargo_workspace,wallet,nym-wallet)) $(eval $(call add_cargo_workspace,connect,nym-connect/desktop)) -# OVERRIDE: wasm-opt fails if the binary has been built with the latest rustc. -# Pin to the last working version. -contracts_BUILD_RELEASE_TOOLCHAIN := +1.69.0 - # ----------------------------------------------------------------------------- # SDK # ----------------------------------------------------------------------------- @@ -144,7 +140,7 @@ contracts: build-release-contracts wasm-opt-contracts wasm-opt-contracts: for contract in $(CONTRACTS_WASM); do \ - wasm-opt --disable-sign-ext -Os $(CONTRACTS_OUT_DIR)/$$contract -o $(CONTRACTS_OUT_DIR)/$$contract; \ + wasm-opt --signext-lowering -Os $(CONTRACTS_OUT_DIR)/$$contract -o $(CONTRACTS_OUT_DIR)/$$contract; \ done # Consider adding 's' to make plural consistent (beware: used in github workflow) diff --git a/contracts/mixnet/Makefile b/contracts/mixnet/Makefile index 01452be701..4583495c9a 100644 --- a/contracts/mixnet/Makefile +++ b/contracts/mixnet/Makefile @@ -1,5 +1,5 @@ opt: wasm - wasm-opt --disable-sign-ext -Os ../target/wasm32-unknown-unknown/release/mixnet_contract.wasm -o ../target/wasm32-unknown-unknown/release/mixnet_contract.wasm + wasm-opt --signext-lowering -Os ../target/wasm32-unknown-unknown/release/mixnet_contract.wasm -o ../target/wasm32-unknown-unknown/release/mixnet_contract.wasm wasm: RUSTFLAGS='-C link-arg=-s' cargo build --release --target wasm32-unknown-unknown From 5ce2e21abca40ebee04474c18bac6d58fb719dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 14:26:09 +0100 Subject: [PATCH 147/236] ci: iterate on ci-nym-vpn-ui-rust --- .github/workflows/ci-nym-vpn-ui-rust.yml | 26 +++++++++++++----------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci-nym-vpn-ui-rust.yml b/.github/workflows/ci-nym-vpn-ui-rust.yml index 57f257e1bc..780f33dcac 100644 --- a/.github/workflows/ci-nym-vpn-ui-rust.yml +++ b/.github/workflows/ci-nym-vpn-ui-rust.yml @@ -2,16 +2,13 @@ name: ci-nym-vpn-ui-rust on: workflow_dispatch: - push: - paths: - - 'nym-vpn/ui/src-tauri/**' pull_request: paths: - 'nym-vpn/ui/src-tauri/**' jobs: build: - runs-on: [self-hosted, custom-linux] + runs-on: custom-linux env: CARGO_TERM_COLOR: always CARGOTOML_PATH: ./nym-vpn/ui/src-tauri/Cargo.toml @@ -32,18 +29,23 @@ jobs: components: rustfmt, clippy - name: Prepare build - working-directory: nym-vpn/ui/ - run: mkdir dist + run: mkdir nym-vpn/ui/dist - - name: Check build - working-directory: nym-vpn/ui/src-tauri - run: cargo build --release --lib --features custom-protocol + # - name: Check build + # working-directory: nym-vpn/ui/src-tauri + # run: cargo build --release --lib --features custom-protocol + # + - name: Build + uses: actions-rs/cargo@v1 + with: + command: build + args: --manifest-path ${{ env.CARGOTOML_PATH }} --lib --features custom-protocol # - name: Run all tests # uses: actions-rs/cargo@v1 # with: # command: test -# args: --manifest-path ${{ env.CARGOTOML_PATH }} --workspace +# args: --manifest-path ${{ env.CARGOTOML_PATH }} - name: Check formatting uses: actions-rs/cargo@v1 @@ -56,10 +58,10 @@ jobs: continue-on-error: true with: token: ${{ secrets.GITHUB_TOKEN }} - args: --manifest-path ${{ env.CARGOTOML_PATH }} --workspace --all-features + args: --manifest-path ${{ env.CARGOTOML_PATH }} --all-features - name: Run clippy uses: actions-rs/cargo@v1 with: command: clippy - args: --manifest-path ${{ env.CARGOTOML_PATH }} --workspace --all-features -- -D warnings + args: --manifest-path ${{ env.CARGOTOML_PATH }} --all-features --all-targets -- -D warnings From 199817bed06b8e8084bbc1aa5a62746b3d7762d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 14:30:30 +0100 Subject: [PATCH 148/236] ci: more iterate on ci-nym-vpn-ui-rust --- .github/workflows/ci-nym-vpn-ui-rust.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci-nym-vpn-ui-rust.yml b/.github/workflows/ci-nym-vpn-ui-rust.yml index 780f33dcac..c60f11597d 100644 --- a/.github/workflows/ci-nym-vpn-ui-rust.yml +++ b/.github/workflows/ci-nym-vpn-ui-rust.yml @@ -31,10 +31,6 @@ jobs: - name: Prepare build run: mkdir nym-vpn/ui/dist - # - name: Check build - # working-directory: nym-vpn/ui/src-tauri - # run: cargo build --release --lib --features custom-protocol - # - name: Build uses: actions-rs/cargo@v1 with: @@ -53,14 +49,14 @@ jobs: command: fmt args: --manifest-path ${{ env.CARGOTOML_PATH }} --all -- --check - - uses: actions-rs/clippy-check@v1 - name: Clippy checks + - name: Annotate with clippy checks + uses: actions-rs/clippy-check@v1 continue-on-error: true with: token: ${{ secrets.GITHUB_TOKEN }} args: --manifest-path ${{ env.CARGOTOML_PATH }} --all-features - - name: Run clippy + - name: Clippy uses: actions-rs/cargo@v1 with: command: clippy From 6fbb6539effe86aa284b1053f827839c9dd8ff4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 14:36:07 +0100 Subject: [PATCH 149/236] ci: tidy ci-nym-vpn-ui-js --- .github/workflows/ci-nym-vpn-ui-js.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-nym-vpn-ui-js.yml b/.github/workflows/ci-nym-vpn-ui-js.yml index 5c3d286244..fc923aa43e 100644 --- a/.github/workflows/ci-nym-vpn-ui-js.yml +++ b/.github/workflows/ci-nym-vpn-ui-js.yml @@ -1,11 +1,7 @@ name: ci-nym-vpn-ui-js on: - push: - paths: - - 'nym-vpn/ui/src/**' - - 'nym-vpn/ui/package.json' - - 'nym-vpn/ui/index.html' + workflow_dispatch: pull_request: paths: - 'nym-vpn/ui/src/**' @@ -14,7 +10,7 @@ on: jobs: check: - runs-on: [ self-hosted, custom-linux ] + runs-on: custom-linux steps: - name: Checkout uses: actions/checkout@v4 From ebe693e5913ad829c8c30f185fa4795317405699 Mon Sep 17 00:00:00 2001 From: benedetta davico <46782255+benedettadavico@users.noreply.github.com> Date: Tue, 31 Oct 2023 14:37:57 +0100 Subject: [PATCH 150/236] Update publish-nym-wallet-macos.yml --- .github/workflows/publish-nym-wallet-macos.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/publish-nym-wallet-macos.yml b/.github/workflows/publish-nym-wallet-macos.yml index 63cb7426a7..af2db3dbf5 100644 --- a/.github/workflows/publish-nym-wallet-macos.yml +++ b/.github/workflows/publish-nym-wallet-macos.yml @@ -39,6 +39,7 @@ jobs: env: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | # create variables @@ -73,6 +74,7 @@ jobs: ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} From 5d8c5224ede9718f561304652db0b529a6f8c279 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 31 Oct 2023 15:44:22 +0100 Subject: [PATCH 151/236] added examples pages --- documentation/dev-portal/src/SUMMARY.md | 31 ++++++++++--------- .../dev-portal/src/examples/browser-only.md | 10 ++++++ .../src/examples/custom-services.md | 16 ++++++++++ .../dev-portal/src/examples/demos.md | 1 - .../src/examples/monorepo-examples.md | 5 +++ documentation/dev-portal/src/examples/rust.md | 1 - .../dev-portal/src/examples/typescript.md | 1 - .../dev-portal/src/examples/using-nrs.md | 17 ++++++++++ 8 files changed, 64 insertions(+), 18 deletions(-) create mode 100644 documentation/dev-portal/src/examples/browser-only.md create mode 100644 documentation/dev-portal/src/examples/custom-services.md delete mode 100644 documentation/dev-portal/src/examples/demos.md create mode 100644 documentation/dev-portal/src/examples/monorepo-examples.md delete mode 100644 documentation/dev-portal/src/examples/rust.md delete mode 100644 documentation/dev-portal/src/examples/typescript.md create mode 100644 documentation/dev-portal/src/examples/using-nrs.md diff --git a/documentation/dev-portal/src/SUMMARY.md b/documentation/dev-portal/src/SUMMARY.md index 7c9836c58a..b9909e8190 100644 --- a/documentation/dev-portal/src/SUMMARY.md +++ b/documentation/dev-portal/src/SUMMARY.md @@ -18,21 +18,21 @@ # User Manuals -- [NymConnect Monero](tutorials/monero.md) -- [NymConnect Matrix](tutorials/matrix.md) -- [NymConnect Telegram](tutorials/telegram.md) +- [NymConnect X Monero](tutorials/monero.md) +- [NymConnect X Matrix](tutorials/matrix.md) +- [NymConnect X Telegram](tutorials/telegram.md) # Code Examples -- [Rust](examples/rust.md) -- [Typescript](examples/typescript.md) -- [Nym Demos](examples/demos.md) -- [Community Apps](examples/community-apps.md) +- [Custom Service Providers](examples/custom-services.md) +- [Apps Using Network Requesters](examples/using-nrs.md) +- [Browser only](examples/browser-only.md) +- [Monorepo examples](examples/monorepo-examples.md) # Integrations - [Integration Options](integrations/integration-options.md) -- [Mixnet Integration](integrations/mixnet-integration.md) +[//]: # (- [Mixnet Integration](integrations/mixnet-integration.md)) - [Payment Integration](integrations/payment-integration.md) # Tutorials @@ -47,14 +47,15 @@ - [Preparing Your Service](tutorials/cosmos-service/service.md) - [Preparing Your Service pt2](tutorials/cosmos-service/service-src.md) - [Querying the Chain](tutorials/cosmos-service/querying.md) + - [Typescript](tutorials/typescript.md) - - [[DEPRECATED] Simple Service Provider](tutorials/simple-service-provider/simple-service-provider.md) - - [Tutorial Overview](tutorials/simple-service-provider/overview.md) - - [Preparing Your User Client Environment](tutorials/simple-service-provider/preparating-env.md) - - [Building Your User Client](tutorials/simple-service-provider/user-client.md) - - [Preparing Your Service Provider Environment](tutorials/simple-service-provider/preparating-env2.md) - - [Building Your Service Provider](tutorials/simple-service-provider/service-provider.md) - - [Sending a Message Through the Mixnet](tutorials/simple-service-provider/sending-message.md) + - [[DEPRECATED] Simple Service Provider](tutorials/simple-service-provider/simple-service-provider.md) + - [Tutorial Overview](tutorials/simple-service-provider/overview.md) + - [Preparing Your User Client Environment](tutorials/simple-service-provider/preparating-env.md) + - [Building Your User Client](tutorials/simple-service-provider/user-client.md) + - [Preparing Your Service Provider Environment](tutorials/simple-service-provider/preparating-env2.md) + - [Building Your Service Provider](tutorials/simple-service-provider/service-provider.md) + - [Sending a Message Through the Mixnet](tutorials/simple-service-provider/sending-message.md) # Events diff --git a/documentation/dev-portal/src/examples/browser-only.md b/documentation/dev-portal/src/examples/browser-only.md new file mode 100644 index 0000000000..9ee22ef1d8 --- /dev/null +++ b/documentation/dev-portal/src/examples/browser-only.md @@ -0,0 +1,10 @@ +# Browser only +With the Typescript SDK you can run a Nym client in a webworker - meaning you can connect to the mixnet through the browser without having to worry about any other code than your web framework. + +- NoTrustVerify have set up an example application using [`mixFetch`](https://sdk.nymtech.net/examples/mix-fetch) to fetch crypto prices from CoinGecko over the mixnet. + - [Website](https://notrustverify.github.io/mixfetch-examples/) + - [Coinbase](https://github.com/notrustverify/mixfetch-examples) + +- There is a coconut-scheme based Credential Library playground [here](https://coco-demo.nymtech.net/). This is a WASM implementation of our Coconut libraries which generate raw Coconut credentials. Test it to create and re-randomize your own credentials. For more information on what is happening here check out the [Coconut docs](https://nymtech.net/docs/coconut.html). + +- You can find a browser-based 'hello world' chat app [here](https://chat-demo.nymtech.net). Either open in two browser windows and send messages to yourself, or share with a friend and send messages to each other through the mixnet. diff --git a/documentation/dev-portal/src/examples/custom-services.md b/documentation/dev-portal/src/examples/custom-services.md new file mode 100644 index 0000000000..ce8262bb36 --- /dev/null +++ b/documentation/dev-portal/src/examples/custom-services.md @@ -0,0 +1,16 @@ +# Custom Services +Custom services involve two pieces of code that communicate via the mixnet: a client, and a custom server/service. This custom service will most likely interact with the wider internet / a clearnet service on your behalf, with the mixnet between you and the service, acting as a privacy shield. + +- PasteNym is a private pastebin alternative. It involves a browser-based frontend utilising the Typescript SDK and a Python-based backend service communicating with a standalone Nym Websocket Client. **If you're a Python developer, start here!**. + - [Frontend codebase](https://github.com/notrustverify/pastenym) + - [Backend codebase](https://github.com/notrustverify/pastenym-frontend) + +- Nostr-Nym is another application written by NoTrustVerify, standing between mixnet users and a Nostr server in order to protect their metadata from being revealed when gossiping. **Useful for Go and Python developers**. + - [Codebase](https://github.com/notrustverify/nostr-nym) + +- Spook and Nym-Ethtx are both examples of Ethereum transaction broadcasters utilising the mixnet, written in Rust. Since they were written before the release of the Rust SDK, they utilise standalone clients to communicate with the mixnet. + - [Spook](https://github.com/EdenBlockVC/spook) (**Typescript**) + - [Nym-Ethtx](https://github.com/noot/nym-ethtx) (**Rust**) + +- NymDrive is an early proof of concept application for privacy-enhanced file storage on IPFS. **JS and CSS**, and a good example of packaging as an Electrum app. + - [Codebase](https://github.com/saleel/nymdrive) diff --git a/documentation/dev-portal/src/examples/demos.md b/documentation/dev-portal/src/examples/demos.md deleted file mode 100644 index ddcf4dd8c4..0000000000 --- a/documentation/dev-portal/src/examples/demos.md +++ /dev/null @@ -1 +0,0 @@ -# Nym Demos diff --git a/documentation/dev-portal/src/examples/monorepo-examples.md b/documentation/dev-portal/src/examples/monorepo-examples.md new file mode 100644 index 0000000000..ad04287f20 --- /dev/null +++ b/documentation/dev-portal/src/examples/monorepo-examples.md @@ -0,0 +1,5 @@ +# Monorepo examples +As well as these examples, there are a bunch of examples for each SDK in the Nym monorepo. + +- [Rust SDK examples](https://github.com/nymtech/nym/tree/develop/sdk/rust/nym-sdk/examples) +- [Typescript SDK examples](https://github.com/nymtech/nym/tree/develop/sdk/typescript/examples) \ No newline at end of file diff --git a/documentation/dev-portal/src/examples/rust.md b/documentation/dev-portal/src/examples/rust.md deleted file mode 100644 index 2f1d5efed1..0000000000 --- a/documentation/dev-portal/src/examples/rust.md +++ /dev/null @@ -1 +0,0 @@ -# Rust diff --git a/documentation/dev-portal/src/examples/typescript.md b/documentation/dev-portal/src/examples/typescript.md deleted file mode 100644 index 42c9775801..0000000000 --- a/documentation/dev-portal/src/examples/typescript.md +++ /dev/null @@ -1 +0,0 @@ -# Typescript diff --git a/documentation/dev-portal/src/examples/using-nrs.md b/documentation/dev-portal/src/examples/using-nrs.md new file mode 100644 index 0000000000..0732340b79 --- /dev/null +++ b/documentation/dev-portal/src/examples/using-nrs.md @@ -0,0 +1,17 @@ +# Apps Using Network Requesters +These applications utilise custom app logic in the user-facing apps in order to communicate using the mixnet as a transport layer, without having to rely on custom server-side logic. Instead, they utilise existing Nym infrastructure - [Network Requesters](https://nymtech.net/operators/nodes/network-requester-setup.html) - with a custom whitelist addition. + +If you are sending 'normal' application traffic, and/or don't require and custom logic to be happening on the 'other side' of the mixnet, this is most likely the best option to take as a developer who wishes to privacy-enhance their application. + +> Nym will soon be switching from a whitelist-based approach to a blocklist-based approach to filtering traffic. As such, it will soon be even easier for developers to utilise the mixnet, as they will not have to run their own NRs or have to add their domains to the whitelist + +- DarkFi over Nym leverages Nym’s mixnet as a pluggable transport for DarkIRC, their p2p IRC variant. Users can anonymously connect to peers over the network, ensuring secure and private communication within the DarkFi ecosystem. Written in **Rust**. + - [Docs](https://darkrenaissance.github.io/darkfi/clients/nym_outbound.html?highlight=nym#3--run) + - [Github](https://github.com/darkrenaissance/darkfi/tree/master/doc) + +- MiniBolt is a complete guide to building a Bitcoin & Lightning full node on a personal computer. It has the capacity to run network traffic (transactions and syncing) over the mixnet, so you can privately sync your node and not expose your home IP to the wider world when interacting with the rest of the network! + - [Docs](https://v2.minibolt.info/bonus-guides/system/nym-mixnet#proxying-bitcoin-core) + - [Codebase](https://github.com/minibolt-guide/minibolt) + +- Email over Nym is a set of configuration options to set up a Network Requester to send and recieve emails over Nym, using something like Thunderbird. + - [Codebase](https://github.com/dial0ut/nymstr-email) \ No newline at end of file From d1160350b273ec27379902a5be66581b7161f370 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 31 Oct 2023 15:44:39 +0100 Subject: [PATCH 152/236] added notepad to gitignore file --- documentation/dev-portal/.gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/documentation/dev-portal/.gitignore b/documentation/dev-portal/.gitignore index c29699d0c0..1451d34afd 100644 --- a/documentation/dev-portal/.gitignore +++ b/documentation/dev-portal/.gitignore @@ -19,4 +19,6 @@ theme/ theme theme/* -.idea \ No newline at end of file +.idea + +notes \ No newline at end of file From 27810d473d131794336edbb64d7d29ee93448997 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 31 Oct 2023 15:45:00 +0100 Subject: [PATCH 153/236] added community examples --- documentation/dev-portal/src/examples/community-apps.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 documentation/dev-portal/src/examples/community-apps.md diff --git a/documentation/dev-portal/src/examples/community-apps.md b/documentation/dev-portal/src/examples/community-apps.md deleted file mode 100644 index b6c3fda9c6..0000000000 --- a/documentation/dev-portal/src/examples/community-apps.md +++ /dev/null @@ -1 +0,0 @@ -# Community Apps From 04fdc1dc60a5b283f5163b962482ccc4dbb6412c Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 31 Oct 2023 15:45:27 +0100 Subject: [PATCH 154/236] streamline integrations files --- .../src/integrations/integration-options.md | 14 +++++++++----- .../src/integrations/mixnet-integration.md | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/documentation/dev-portal/src/integrations/integration-options.md b/documentation/dev-portal/src/integrations/integration-options.md index 56f00a33da..328ec154a3 100644 --- a/documentation/dev-portal/src/integrations/integration-options.md +++ b/documentation/dev-portal/src/integrations/integration-options.md @@ -1,10 +1,14 @@ # Integration Options -If you've already gone through the different [Quick Start](../quickstart/overview.md) options, you have seen the possibilities avaliable to you for quickly connecting existing application code to another Nym process. +If you've already gone through the different [Quick Start](../quickstart/overview.md) options and had a look at the tutorials, you have seen the possibilities available to you for quickly connecting existing application code to another Nym process. -This section assumes you wish to integrate with Nym into your application code. +Below are a resources that will be useful for either beginning to integrate mixnet functionality into existing application code or build a new app using Nym. -The [integrations FAQ](../faq/integrations-faq.md) has a list of common questions regarding integrating with Nym and Nyx, as well as commonly required links. _This is a good place to start to get an overall idea of the tools and software avaliable to you_. +- **We suggest you begin with this [integration decision tree](https://sdk.nymtech.net/integrations)**. This will give you a better idea of what pieces of software (SDKs, standalone clients, service providers) your integration might involve, and what is currently possible to do with as little custom code as possible. + +- The [integrations FAQ](../faq/integrations-faq.md) has a list of common questions regarding integrating with Nym and Nyx, as well as commonly required links. + +- To get an idea of what is possible / has already been built, check the [community applications and resources](../community-resources/community-applications-and-guides.md) page, as well as the [developer tutorials codebase](https://github.com/nymtech/developer-tutorials). + +> If you wish to integrate with the Nyx blockchain to use `NYM` for payments, start with the [payment integration](./payment-integration.md) page. -If you wish to integrate with Nym to use the mixnet for application traffic, start with the [mixnet integration](./mixnet-integration.md) page. -If you wish to integrate with the Nyx blockchain to use `NYM` for payments, start with the [payment integration](./payment-integration.md) page. diff --git a/documentation/dev-portal/src/integrations/mixnet-integration.md b/documentation/dev-portal/src/integrations/mixnet-integration.md index 91e6c2d559..a26f0a885b 100644 --- a/documentation/dev-portal/src/integrations/mixnet-integration.md +++ b/documentation/dev-portal/src/integrations/mixnet-integration.md @@ -13,7 +13,7 @@ As outlined in the [clients overview documentation](https://nymtech.net/docs/cli #### Websocket client Your first option is the native websocket client. This is a compiled program that can run on Linux, Mac OS X, and Windows machines. It runs as a persistent process on a desktop or server machine. You can connect to it with any language that supports websockets. -You can see an example of how to connect to and manage interactions with this client in the [Simple Service Provider tutorial](../tutorials/simple-service-provider/simple-service-provider.md). +[//]: # (You can see an example of how to connect to and manage interactions with this client in the [Simple Service Provider tutorial](../tutorials/simple-service-provider/simple-service-provider.md).) #### Webassembly client If you’re working in JavaScript or Typescript in the browser, or building an edge computing app, you’ll likely want to choose the webassembly client. From 4b23cd94fd1298ee8a54dc43e7c86024b7dc9516 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 31 Oct 2023 15:46:25 +0100 Subject: [PATCH 155/236] streamlined node types --- documentation/dev-portal/src/infrastructure/node-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/dev-portal/src/infrastructure/node-types.md b/documentation/dev-portal/src/infrastructure/node-types.md index ba1a127d37..cb5e9c3d35 100644 --- a/documentation/dev-portal/src/infrastructure/node-types.md +++ b/documentation/dev-portal/src/infrastructure/node-types.md @@ -11,4 +11,4 @@ For more in-depth information on the network architecture, head to the [Network If you would like to concentrate on building an application that uses the mixnet: * Explore the [Quickstart](../quickstart/overview.md) options. * Check out examples of [Community Apps](../community-resources/community-applications-and-guides.md). -* Run through one of the [tutorials](../tutorials). +* Run through the [Rust SDK](../tutorials/rust-sdk.md) or [Typescript](../tutorials/typescript.md) tutorials. From eb7305e31c927ba7343ff14d10dc95d1580740bc Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 31 Oct 2023 16:01:54 +0100 Subject: [PATCH 156/236] add token economics paper info --- documentation/operators/src/faq/smoosh-faq.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index c14a562534..2950b7df54 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -62,6 +62,10 @@ Depends which [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators ## Token Economics & Rewards +```admonish info +For any details on Nym token economics and Nym Mixnet reward system, please read [Nym token economics paper](https://nymtech.net/nym-cryptoecon-paper.pdf). +``` + ### What are the incentives for the node operator? In the original setup there were no incentives to run a `network-requester`. After the transition all the users will buy multiple tickets of zkNyms credentials and use those as [anonymous e-cash](https://arxiv.org/abs/2303.08221) to pay for their data traffic ([`Nym API`](https://github.com/nymtech/nym/tree/master/nym-api) will do the do cryptographical checks to prevent double-spending). All collected fees get distributed to all active nodes proportionally to their work by the end of each epoch. From b072a080ae6c32d7ad482f859cf68456bcb51154 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 31 Oct 2023 17:03:37 +0100 Subject: [PATCH 157/236] added shipyard info --- documentation/dev-portal/src/SUMMARY.md | 5 ++ .../src/shipyard/challenges-overview.md | 53 +++++++++++++++++++ .../dev-portal/src/shipyard/general.md | 16 ++++++ .../dev-portal/src/shipyard/guidelines.md | 12 +++++ .../dev-portal/src/shipyard/infra.md | 5 ++ 5 files changed, 91 insertions(+) create mode 100644 documentation/dev-portal/src/shipyard/challenges-overview.md create mode 100644 documentation/dev-portal/src/shipyard/general.md create mode 100644 documentation/dev-portal/src/shipyard/guidelines.md create mode 100644 documentation/dev-portal/src/shipyard/infra.md diff --git a/documentation/dev-portal/src/SUMMARY.md b/documentation/dev-portal/src/SUMMARY.md index b9909e8190..cd930be17a 100644 --- a/documentation/dev-portal/src/SUMMARY.md +++ b/documentation/dev-portal/src/SUMMARY.md @@ -57,6 +57,11 @@ - [Building Your Service Provider](tutorials/simple-service-provider/service-provider.md) - [Sending a Message Through the Mixnet](tutorials/simple-service-provider/sending-message.md) +# Shipyard Builders Hackathon 2023 +- [General Info & Resources](shipyard/general.md) +- [Hackathon Challenges](shipyard/challenges-overview.md) +- [A Note on Infrastructure](shipyard/infra.md) +- [Submission Guidelines](shipyard/guidelines.md) # Events diff --git a/documentation/dev-portal/src/shipyard/challenges-overview.md b/documentation/dev-portal/src/shipyard/challenges-overview.md new file mode 100644 index 0000000000..f4a0be6b92 --- /dev/null +++ b/documentation/dev-portal/src/shipyard/challenges-overview.md @@ -0,0 +1,53 @@ +# Hackathon Challenges +There are a few different challenges to choose from, each with different approaches. It is also recommended to check out the _**Examples**_ directory above for inspiration, and if you have questions ask in the [Builders channel]() on Matrix. + +## Tooling challenge +The tooling challenge involves creating tooling for users, operators, or developers of Nym. + +### Examples of user-centric tools: +- Facilitate onboarding new users more easily to staking their Nym, and understanding the pros and cons, as well as finding a good node to stake on. Examples of tools like this: + - [ExploreNym dashboard](https://explorenym.net/) + +- Show information on a dashboard about the network. NOTE due to the amount of dashboards currently available, we expect a good justification for why / something to set this apart from existing ones e.g. it is presenting information that is not already presented, or it is presented in a different manner, such as a TUI or CLI app instead of a web dashboard - maybe an onion service, or no-JS site for those who do not wish to enable Javascript in their day to day browsing. Examples of tools like this: + - [NTV's node dashboard](https://status.notrustverify.ch/d/CW3L7dVVk/nym-mixnet?orgId=1) + - [IsNymUp dashboard](https://isnymup.com/) + +### Examples of operator-centric tooling: +- An APY calculator for determining different financial outcomes of running a node in different situations. + +- Scripting for updating and maintaining nodes. Examples of tools like this: + - [ExploreNym's bash scripts](https://github.com/ExploreNYM/bash-tool) + +- Scripting for packaging node binaries for different OSes. + +### Examples of developer-centric tooling: +- Tooling for use in development: are there pain points you’ve found when developing apps with Nym that you have created scripts/hacks/workarounds for? Is there a pain point that you’ve thought ‘oh it would be great if I could just do X’? These are often the best places to start for building out developer tooling - if you’ve run into this issue, it's very likely someone else already has, or will! + +- Interacting with one of the SDKs via FFI: perhaps you’re a Go developer who would love to have the functionality of one of the Nym SDKs. Building an FFI tool might be something that would make your life easier, and can be shared with other developers in your situation. + +## Integrations challenge +Integration options for Nym are currently relatively restrictive due to the manner in which Nym handles sending and receiving traffic (as unordered Sphinx packets). This challenge will involve (most likely) implementing custom logic for handling Nym traffic for an existing application. + +There are several potential avenues developers can take here: +- If your application (or the application you wish to modify) is written in either Javascript or Typescript, and relies on the `fetch` library to make API calls, then you can use its drop-in replacement: [`mixfetch`](). Perhaps you wish to interact with Coingecko, or a private search engine like Kagi without leaking your IP and metadata, or an RPC endpoint. + - Example with [NTV’s privacy-preserving Coingecko API](https://github.com/notrustverify/mixfetch-examples) + - [Mixfetch docs examples](https://github.com/nymtech/nym/tree/develop/sdk/typescript/examples) + +- If you instead have an application that is able to use any of the SOCKS5, 4a, or 4 protocols (a rule of thumb: if it can communicate over Tor, it will) then you can experiment with using Nym as the transport layer. + - For Rustaceans, check out our [socks5 rust sdk example](https://nymtech.net/docs/sdk/rust.html#socks-client-example). + - For those of you who aren’t Crustaceans, then you will have to run the [Socks Client]() alongside your application as a separate process. _NOTE If you are taking this route, please make sure to include detailed documentation on how you expect users to do this, as well as including any process management tools, scripts, and configs (e.g. if you use systemd then include the configuration file for the client, as well as initialisation logic) that may streamline this process._ + - [NTV's PasteNym backend](https://github.com/notrustverify/pastenym) is a great example of an application with this architecture. + +- Nym is not only useful for blockchain-related apps, but for anything that requires network level privacy! Email clients, messaging clients, and decentralised storage are all key elements of the privacy-enabled web. Several of these sorts of apps can be found in the [community apps page](../community-resources/community-applications-and-guides.md). + +- There is currently a proof of concept using Rust Libp2p with Nym as a transport layer. Perhaps you can think of an app that uses Gossipsub for p2p communication could benefit from network-level privacy. + - [GossipSub chat example](https://github.com/nymtech/nym/tree/develop/sdk/rust/nym-sdk/examples/libp2p_chat) + - [Chainsafe's Lighthouse Nym PoC](https://github.com/ChainSafe/lighthouse/blob/nym/USE_NYM.md#usage) + +- Alternatively if you know of an app that is written in Rust or TS and could benefit from using Nym, you could fork and modify it using the SDKs. Applications such as: + - Magic Wormhole (has a [rust implementation](https://github.com/magic-wormhole/magic-wormhole.rs)) + - [Qual](https://github.com/qaul/qaul.net) (uses Rust Libp2p) + - [Syncthing](https://github.com/syncthing/syncthing) + +### MiniApp challenge +Write an app, either using one of the SDKs or a standalone client (harder). Think of what you can ‘nymify’ e.g. a version of the [TorBirdy](https://support.torproject.org/glossary/torbirdy/) extension that uses Nym instead of Tor. This is very similar to the Integration challenge in terms of the different potential _architectures_ and approaches, but just for new applications. diff --git a/documentation/dev-portal/src/shipyard/general.md b/documentation/dev-portal/src/shipyard/general.md new file mode 100644 index 0000000000..f07f3f22ac --- /dev/null +++ b/documentation/dev-portal/src/shipyard/general.md @@ -0,0 +1,16 @@ +# General Info & Resources +Discussions and announcements will be taking place in the [builders channel on Matrix](https://matrix.to/#/#shipyardbuilders:nymtech.chat). This channel can be used for all discussions. + +There will be daily office horse between 12-14:00 CET. + +This is an open call and questions will be answered on a first come first serve basis. + +The timetable can be found on the [Shipyard website](https://nymtech.net/learn/shipyard). + +## Links +- You can find **code examples**, **tutorials**, & **quickstart** information here, on the Developer Portal. +- [Rust SDK docs](https://nymtech.net/docs/sdk/rust.html) +- [Typescript SDK docs](https://sdk.nymtech.net) +- [Platform docs](https://nymtech.net/docs) +- [NoTrustVerify's Awesome Nym list](https://github.com/notrustverify/awesome-nym) +- [Builders channel Matrix](https://matrix.to/#/#shipyardbuilders:nymtech.chat) diff --git a/documentation/dev-portal/src/shipyard/guidelines.md b/documentation/dev-portal/src/shipyard/guidelines.md new file mode 100644 index 0000000000..ac8a7b18a8 --- /dev/null +++ b/documentation/dev-portal/src/shipyard/guidelines.md @@ -0,0 +1,12 @@ +# Submission Guidelines +We expect to see the following for submissions: +- Working code demos hosted publicly (Gitlab, Github, some other git instance). +- Quality > quantity here: we’d prefer to see a contained, working, and well documented Proof of Concept over a sprawling and messy app that does more but is poorly explained and presented. _The repo must be open source and able to be used and modified by others. The license is up to you._ +- If you already have existing apps / projects you are more than welcome to extend them, instead of starting from scratch - we will only be looking at the NEW additions to make this fair. If you are doing this, make sure to write a detailed account of what it is you;ve added to the existing project, preferably with the possibility to see the ‘old’ version as well as the new one. +- Proper documentation: + - If an app / tool: + - How do you install and run the code? How is it to be used? + - An overview of the application architecture: what is it doing? Is it relying on other services? + - If a UI-based solution: + - How to run it locally? We are happy to also accept staging deployments as part of the submission (e.g. via Vercel) but this does not replace being able to run it locally. +- Please make sure that your application works on commonly reproducible system environments (e.g. if you’re developing on Artix Linux please check for the necessary dependencies for more common-place OSes such as Debian, or Arch). If you are developing on Windows please make sure that it works on non-Windows machines also. Where possible please try to include build and install instructions for a variety of OSes. diff --git a/documentation/dev-portal/src/shipyard/infra.md b/documentation/dev-portal/src/shipyard/infra.md new file mode 100644 index 0000000000..b5621f6ff6 --- /dev/null +++ b/documentation/dev-portal/src/shipyard/infra.md @@ -0,0 +1,5 @@ +# A Note on Infrastructure +If you are writing an application that requires sending messages through the mixnet, then you will either be relying on existing infrastructure nodes (network requesters), or writing your own custom service (for example, the service written as part of the Rust SDK tutorial). + +If you are relying on network requesters then chances are that the IPs or domains your app relies on will not already be on the whitelist. Ideally, you would [run your own,](https://nymtech.net/operators/nodes/network-requester-setup.html) but we will also run a few nodes in ‘open proxy’ mode and share the addresses so that you can use them when beginning to develop. + From 0e906b1a3d71589bdb60ac168af3c01acab3197b Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Tue, 31 Oct 2023 17:11:57 +0100 Subject: [PATCH 158/236] try change ifconfig.me -> icanhazip.com --- .../operators/src/nodes/gateway-setup.md | 84 ++++++++++--------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index d23e0ab02e..0fea8bba90 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -4,7 +4,7 @@ ```admonish info -As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` functionality which can be enabled [by the operator](./gateway-setup.md#initialising-gateway-with-network-requester). This combination is a basis of Nym exit gateway node - an essential piece in our new setup. Please read more in our [Project Smoosh FAQ](../faq/smoosh-faq.md) and [Exit Gateways Page](../legal/exit-gateway.md). We recommend operators begin to shift their setups to this new combined node, instead of operating two separate binaries. +As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` functionality which can be enabled [by the operator](./gateway-setup.md#initialising-gateway-with-network-requester). This combination is a basis of ***Nym Exit Gateway*** node - an essential piece in our new setup. Please read more in our [Project Smoosh FAQ](../faq/smoosh-faq.md) and [Exit Gateway](../legal/exit-gateway.md) pages. We recommend operators begin to shift their setups to this new combined node, instead of operating two separate binaries. ``` > Any syntax in `<>` brackets is a user's unique variable. Exchange with a corresponding name without the `<>` brackets. @@ -48,42 +48,17 @@ You can also check the various arguments required for individual commands with: ``` > Adding `--no-banner` startup flag will prevent Nym banner being printed even if run in tty environment. -### Initialising your gateway -To check available configuration options use: +## Initialising your Gateway + +As Nym developers build towards [Exit Gateway](../legal/exit-gateway.md) functionality, operators can now run their `nym-gateway` binary with in-build Network requester. Considering the plan to [*smoosh*](../faq/smoosh-faq.md) all the nodes into one binary and have wide opened Exit Gateways, we recommend this setup, instead of operating two separate binaries. + + +### Initialising Exit Gateway + +An operator can initialise the Exit Gateway functionality by: ``` - ./nym-gateway init --help -``` - -~~~admonish example collapsible=true title="Console output" -``` - -``` -~~~ - -The following command returns a gateway on your current IP with the `` of `supergateway`: - -``` -./nym-gateway init --id supergateway --host $(curl ifconfig.me) -``` - -~~~admonish example collapsible=true title="Console output" -``` - -``` -~~~ - -The `$(curl ifconfig.me)` command above returns your IP automatically using an external service. Alternatively, you can enter your IP manually if you wish. If you do this, remember to enter your IP **without** any port information. - - -#### Initialising gateway with network requester - -As some of the [Project Smoosh](../faq/smoosh-faq.md) changes getting implemented, network requester is smooshed with gateways. Such combination creates an exit gateway node, needed for new more open setup. - -An operator can initialise the exit gateway functionality by: - -``` -./nym-gateway init --id --host $(curl ifconfig.me) --with-network-requester +./nym-gateway init --id --host $(curl icanhazip.com) --with-network-requester ``` If we follow the previous example with `` chosen `superexitgateway`, adding the `--with-network-requester` flag, the outcome will be: @@ -91,15 +66,17 @@ If we follow the previous example with `` chosen `superexitgateway`, adding ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ You can see that the printed information besides *identity* and *sphinx keys* also includes a long string called *address*. This is the address to be provided to your local [socks5 client](https://nymtech.net/docs/clients/socks5-client.html) as a `--provider` if you wish to connect to your own exit gateway. -#### Add network requester to existing gateway +Additionally -If you already run a gateway and got it [upgraded](./maintenance.md#upgrading-your-node) to the [newest version](./gateway-setup.md#current-version), you can easily change its functionality to exit gateway. PAuse the gateway and run a command `setup-network-requester`. +#### Add Network requester to existing Gateway + +If you already run a gateway and got it [upgraded](./maintenance.md#upgrading-your-node) to the [newest version](./gateway-setup.md#current-version), you can easily change its functionality to exit gateway. Pause the gateway and run a command `setup-network-requester`. See the options: @@ -144,6 +121,37 @@ To read more about the configuration like whitelisted outbound requesters in `al Before you bond and run your gateway, please make sure the [firewall configuration](./maintenance.md#configure-your-firewall) is setup so your gateway can be reached from the outside. ``` +#### Initialising Gateway without Network requester + +In case you don't want to run your Gateway with the Exit Gateway functionality, you still can run a simple Gateway. + +To check available configuration options use: + +``` + ./nym-gateway init --help +``` + +~~~admonish example collapsible=true title="Console output" +``` + +``` +~~~ + +The following command returns a gateway on your current IP with the `` of `supergateway`: + +``` +./nym-gateway init --id supergateway --host $(curl icanhazip.com) +``` + +~~~admonish example collapsible=true title="Console output" +``` + +``` +~~~ + +The `$(curl icanhazip.com)` command above returns your IP automatically using an external service. Alternatively, you can enter your IP manually if you wish. If you do this, remember to enter your IP **without** any port information. + + ### Bonding your gateway #### Via the Desktop wallet From a10ebf342bcd894c96534cbca46a41eadaa5ea9e Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 31 Oct 2023 17:14:30 +0100 Subject: [PATCH 159/236] tweak --- documentation/dev-portal/src/shipyard/challenges-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/dev-portal/src/shipyard/challenges-overview.md b/documentation/dev-portal/src/shipyard/challenges-overview.md index f4a0be6b92..0a815b2d42 100644 --- a/documentation/dev-portal/src/shipyard/challenges-overview.md +++ b/documentation/dev-portal/src/shipyard/challenges-overview.md @@ -1,5 +1,5 @@ # Hackathon Challenges -There are a few different challenges to choose from, each with different approaches. It is also recommended to check out the _**Examples**_ directory above for inspiration, and if you have questions ask in the [Builders channel]() on Matrix. +There are a few different challenges to choose from, each with different approaches. It is also recommended to check out the _**Examples**_ directory above for inspiration. ## Tooling challenge The tooling challenge involves creating tooling for users, operators, or developers of Nym. From 37958ccb4e1c8d9e3fd7065be34a7fb36dfcc368 Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Mon, 9 Oct 2023 14:06:46 +0200 Subject: [PATCH 160/236] Add nodejs wrapper for wasm sphynx client --- .../packages/nodejs-client/.gitignore | 1 + .../packages/nodejs-client/README.md | 34 + .../packages/nodejs-client/package.json | 13 +- .../nodejs-client/rollup-cjs.config.mjs | 31 + .../nodejs-client/rollup-worker.config.mjs | 46 + .../nodejs-client/scripts/build-prod.sh | 20 + .../packages/nodejs-client/scripts/build.sh | 35 + .../scripts/buildPackageJson.mjs | 22 + .../packages/nodejs-client/src/index.ts | 72 +- .../nodejs-client/src/node-adapter.ts | 43 + .../nodejs-client/src/subscriptions.ts | 1 + .../packages/nodejs-client/src/types.ts | 27 +- .../src/typings/rollup-worker.d.ts | 2 + .../packages/nodejs-client/src/worker.ts | 261 ++ .../packages/nodejs-client/tsconfig.json | 31 +- .../packages/nodejs-client/yarn.lock | 2951 +++++++++++++++++ sdk/typescript/scripts/publish.sh | 2 + sdk/typescript/scripts/unpublish.sh | 2 + 18 files changed, 3512 insertions(+), 82 deletions(-) create mode 100644 sdk/typescript/packages/nodejs-client/.gitignore create mode 100644 sdk/typescript/packages/nodejs-client/README.md create mode 100644 sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs create mode 100644 sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs create mode 100755 sdk/typescript/packages/nodejs-client/scripts/build-prod.sh create mode 100755 sdk/typescript/packages/nodejs-client/scripts/build.sh create mode 100644 sdk/typescript/packages/nodejs-client/scripts/buildPackageJson.mjs create mode 100644 sdk/typescript/packages/nodejs-client/src/node-adapter.ts create mode 100644 sdk/typescript/packages/nodejs-client/yarn.lock diff --git a/sdk/typescript/packages/nodejs-client/.gitignore b/sdk/typescript/packages/nodejs-client/.gitignore new file mode 100644 index 0000000000..c573ec84f3 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/.gitignore @@ -0,0 +1 @@ +*/worker.js diff --git a/sdk/typescript/packages/nodejs-client/README.md b/sdk/typescript/packages/nodejs-client/README.md new file mode 100644 index 0000000000..db694fbe96 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/README.md @@ -0,0 +1,34 @@ +# Nym NodeJS wrapper for Sphinx webassembly client + +This package is a NodeJS client that uses the wasm from the [Sphinx webassembly client](https://github.com/nymtech/nym/blob/4890c528bcb519290de81ef968bb2ba1399914a4/wasm/client/README.md), runs it inside a NodeJS Worker thread and allows users to send and receive Sphinx packets to/from a Nym mixnet. + +## Usage + +```js +const { createNymMixnetClient } = require('../dist/cjs/index.js'); + +async () => { + const nym = await createNymMixnetClient(); + + nym.events.subscribeToTextMessageReceivedEvent(async (e) => { + if (e.args.payload === 'Hello') { + await nym.client.stop(); + } + }); + + const nymApiUrl = 'https://validator.nymtech.net/api/'; + + // start the client and connect to a gateway + await nym.client.start({ + nymApiUrl, + clientId: 'my-client', + }); + + nym.events.subscribeToConnected(async (e) => { + // send a message to yourself + const message = 'Hello'; + const recipient = await nym.client.selfAddress(); + await nym.client.send({ payload: { message, mimeType: 'text/plain' }, recipient }); + }); +}; +``` diff --git a/sdk/typescript/packages/nodejs-client/package.json b/sdk/typescript/packages/nodejs-client/package.json index fa92d27d10..985b48bdf6 100644 --- a/sdk/typescript/packages/nodejs-client/package.json +++ b/sdk/typescript/packages/nodejs-client/package.json @@ -6,11 +6,10 @@ "files": [ "dist/**/*" ], - "main": "dist/index.mjs", + "main": "dist/cjs/index.js", "scripts": { "build": "scripts/build-prod.sh", "build:dev": "scripts/build.sh", - "build:dev:esm": "scripts/build-dev-esm.sh", "build:worker": "rollup -c rollup-worker.config.mjs", "clean": "rimraf dist", "docs:dev": "run-p docs:watch docs:serve ", @@ -23,12 +22,14 @@ "lint:fix": "eslint src --fix", "start": "tsc -w", "start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'", - "test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache", "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-client-wasm-node": ">=1.2.0-rc.10 || ^1", - "comlink": "^4.3.1" + "@nymproject/nym-client-wasm-node": "^1.2.0", + "comlink": "^4.3.1", + "fake-indexeddb": "^4.0.2", + "rollup-plugin-polyfill": "^4.2.0", + "ws": "^8.14.2" }, "devDependencies": { "@babel/core": "^7.15.0", @@ -68,6 +69,7 @@ "rimraf": "^3.0.2", "rollup": "^3.9.1", "rollup-plugin-base64": "^1.0.1", + "rollup-plugin-modify": "^3.0.0", "rollup-plugin-web-worker-loader": "^1.6.1", "ts-jest": "^29.1.0", "ts-loader": "^9.4.2", @@ -75,6 +77,5 @@ "typescript": "^4.8.4" }, "private": false, - "type": "module", "types": "./dist/index.d.ts" } diff --git a/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs b/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs new file mode 100644 index 0000000000..cb5fe9ac74 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs @@ -0,0 +1,31 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import typescript from '@rollup/plugin-typescript'; +import resolve from '@rollup/plugin-node-resolve'; +import { wasm } from '@rollup/plugin-wasm'; +import webWorkerLoader from 'rollup-plugin-web-worker-loader'; +import replace from '@rollup/plugin-replace'; + +export default { + input: 'src/index.ts', + output: { + dir: 'dist/cjs', + format: 'cjs', + }, + plugins: [ + webWorkerLoader({ targetPlatform: 'node', inline: false }), + replace({ + values: { + "createURLWorkerFactory('web-worker-0.js')": + "createURLWorkerFactory(require('path').resolve(__dirname, 'web-worker-0.js'))", + }, + delimiters: ['', ''], + preventAssignment: true, + }), + resolve({ browser: false, extensions: ['.js', '.ts'] }), + wasm({ targetEnv: 'node', maxFileSize: 0 }), + typescript({ + compilerOptions: { outDir: 'dist/cjs', target: 'es5' }, + exclude: ['src/worker.ts'], + }), + ], +}; diff --git a/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs b/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs new file mode 100644 index 0000000000..b75c9820d1 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs @@ -0,0 +1,46 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import typescript from '@rollup/plugin-typescript'; +import resolve from '@rollup/plugin-node-resolve'; +import { wasm } from '@rollup/plugin-wasm'; +import commonjs from '@rollup/plugin-commonjs'; +import modify from 'rollup-plugin-modify'; + +export default { + input: 'src/worker.ts', + output: { + dir: 'dist/cjs', + format: 'cjs', + }, + external: ['util', 'fake-indexeddb'], + plugins: [ + resolve({ + browser: false, + preferBuiltins: true, + extensions: ['.js', '.ts'], + }), + commonjs(), + // TODO: One of the wasm functions calls `new WebSocket` at one point, which we aren't able to polyfill correctly yet. + modify({ + find: 'const ret = new WebSocket(getStringFromWasm0(arg0, arg1));', + replace: 'const ws = require("ws"); const ret = new ws.WebSocket(getStringFromWasm0(arg0, arg1));', + }), + // TODO: `getObject(...).require` seems to generate a warning on Webpack but with Rollup we get a panic since it can't require. + // By hard coding the require here, we can workaround that. + // Reference: https://github.com/rust-random/getrandom/issues/224 + modify({ find: 'getObject(arg0).require(getStringFromWasm0(arg1, arg2));', replace: 'require("crypto");' }), + // TODO: The NodeJS setTimeout returns a Timeout object instead of a timeout id as the browser API one does. + // check how we could polyfill this, instead of commenting it out. + modify({ + find: /const ret = getObject\(arg0\).setTimeout\(getObject\(arg1\), arg2\);\n\s*?_assertNum\((.*?)\)/, + replace: (match) => match.replace('_assertNum(ret)', '// _assertNum(ret)'), + }), + wasm({ targetEnv: 'node', maxFileSize: 0, fileName: '[name].wasm' }), + typescript({ + compilerOptions: { + outDir: 'dist/cjs', + declaration: false, + target: 'es5', + }, + }), + ], +}; diff --git a/sdk/typescript/packages/nodejs-client/scripts/build-prod.sh b/sdk/typescript/packages/nodejs-client/scripts/build-prod.sh new file mode 100755 index 0000000000..979b03297a --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/scripts/build-prod.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist || true +rm -rf ../../../../dist/ts/sdk/nodejs-client || true + +# run the build +scripts/build.sh +node scripts/buildPackageJson.mjs + +# move the output outside of the yarn/npm workspaces +mkdir -p ../../../../dist/ts/sdk +mv dist ../../../../dist/ts/sdk +mv ../../../../dist/ts/sdk/dist ../../../../dist/ts/sdk/nodejs-client + +echo "Output can be found in:" +realpath ../../../../dist/ts/sdk/nodejs-client diff --git a/sdk/typescript/packages/nodejs-client/scripts/build.sh b/sdk/typescript/packages/nodejs-client/scripts/build.sh new file mode 100755 index 0000000000..71bf0d64b6 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/scripts/build.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist || true + +#------------------------------------------------------- +# WEB WORKER (mix-fetch WASM) +#------------------------------------------------------- +# The web worker needs to be bundled because the WASM bundle needs to be loaded synchronously and all dependencies +# must be included in the worker script (because it is not loaded as an ES Module) + +# build the worker +rollup -c rollup-worker.config.mjs + +# move it next to the Typescript `src/index.ts` so it can be inlined by rollup +rm -f src/*.js +mv dist/cjs/worker.js src/worker.js + +#------------------------------------------------------- +# COMMON JS +#------------------------------------------------------- +# Some old build systems cannot fully handle ESM or ES2021, so build +# a CommonJS bundle targeting ES5 + +# build the SDK as a CommonJS bundle +rollup -c rollup-cjs.config.mjs + +#------------------------------------------------------- +# CLEAN UP +#------------------------------------------------------- + +cp README.md dist/cjs/README.md diff --git a/sdk/typescript/packages/nodejs-client/scripts/buildPackageJson.mjs b/sdk/typescript/packages/nodejs-client/scripts/buildPackageJson.mjs new file mode 100644 index 0000000000..592b17e1e0 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/scripts/buildPackageJson.mjs @@ -0,0 +1,22 @@ +import * as fs from 'fs'; + +// parse the package.json from the SDK, so we can keep fields like the name and version +const json = JSON.parse(fs.readFileSync('package.json').toString()); + +// defaults (NB: these are in the output file locations) +const browser = 'index.js'; +const main = 'index.js'; +const types = 'index.d.ts'; + +const getPackageJson = (type, suffix) => ({ + name: `${json.name}${suffix ? `-${suffix}` : ''}`, + version: json.version, + license: json.license, + author: json.author, + type, + browser, + main, + types, +}); + +fs.writeFileSync('dist/cjs/package.json', JSON.stringify(getPackageJson('commonjs', 'commonjs'), null, 2)); diff --git a/sdk/typescript/packages/nodejs-client/src/index.ts b/sdk/typescript/packages/nodejs-client/src/index.ts index e124b7136c..88133c28c2 100644 --- a/sdk/typescript/packages/nodejs-client/src/index.ts +++ b/sdk/typescript/packages/nodejs-client/src/index.ts @@ -1,43 +1,23 @@ import * as Comlink from 'comlink'; +import { Worker } from 'worker_threads'; + import InlineWasmWebWorker from 'web-worker:./worker'; import { BinaryMessageReceivedEvent, + Client, ConnectedEvent, EventKinds, - IWebWorker, - Client, Events, + IWebWorker, LoadedEvent, MimeTypes, + NymMixnetClient, + NymMixnetClientOptions, RawMessageReceivedEvent, StringMessageReceivedEvent, } from './types'; import { createSubscriptions } from './subscriptions'; - -/** - * Options for the Nym mixnet client. - * @property autoConvertStringMimeTypes - An array of mime types. - * @example - * ```typescript - * const client = await createNymMixnetClient({ - * autoConvertStringMimeTypes: [MimeTypes.ApplicationJson, MimeTypes.TextPlain], - * }); - * ``` - */ - -export interface NymMixnetClientOptions { - autoConvertStringMimeTypes?: string[] | MimeTypes[]; -} - -/** - * The client for the Nym mixnet which gives access to client methods and event subscriptions. - * Returned by the {@link createNymMixnetClient} function. - * - */ -export interface NymMixnetClient { - client: Client; - events: Events; -} +import nodeEndpoint from './node-adapter'; /** * Create a client to send and receive traffic from the Nym mixnet. @@ -57,16 +37,16 @@ export const createNymMixnetClient = async (options?: NymMixnetClientOptions): P const { getSubscriptions, addSubscription } = subscriptions; // listen to messages from the worker, parse them and let the subscribers handle them, catching any unhandled exceptions - worker.addEventListener('message', (msg) => { - if (msg.data && msg.data.kind) { - const subscribers = getSubscriptions(msg.data.kind); + worker.addListener('message', (msg: { kind: EventKinds; args: any }) => { + if (msg.kind) { + const subscribers = getSubscriptions(msg.kind); (subscribers || []).forEach((s) => { try { // let the subscriber handle the message - s(msg.data); + s(msg); } catch (e) { // eslint-disable-next-line no-console - console.error('Unhandled error in event handler', msg.data, e); + console.error('Unhandled error in event handler', msg, e); } }); } @@ -85,14 +65,14 @@ export const createNymMixnetClient = async (options?: NymMixnetClientOptions): P }; // let comlink handle interop with the web worker - const client: Client = Comlink.wrap(worker); + const client: Client = Comlink.wrap(nodeEndpoint(worker)); // set any options if (options?.autoConvertStringMimeTypes) { - await client.setTextMimeTypes(options.autoConvertStringMimeTypes); + client.setTextMimeTypes(options.autoConvertStringMimeTypes); } else { // set some sensible defaults for text mime types - await client.setTextMimeTypes([MimeTypes.ApplicationJson, MimeTypes.TextPlain]); + client.setTextMimeTypes([MimeTypes.ApplicationJson, MimeTypes.TextPlain]); } // pass the client interop and subscription manage back to the caller @@ -115,17 +95,13 @@ const createWorker = async () => // however, it will make this SDK bundle bigger because of Base64 inline data const worker = new InlineWasmWebWorker(); - worker.addEventListener('error', reject); - worker.addEventListener( - 'message', - (msg) => { - worker.removeEventListener('error', reject); - if (msg.data?.kind === EventKinds.Loaded) { - resolve(worker); - } else { - reject(msg); - } - }, - { once: true }, - ); + worker.addListener('error', reject); + worker.addListener('message', (msg: { kind: EventKinds; args: any }) => { + worker.removeListener('error', reject); + if (msg.kind === EventKinds.Loaded) { + resolve(worker); + } else { + reject(msg); + } + }); }); diff --git a/sdk/typescript/packages/nodejs-client/src/node-adapter.ts b/sdk/typescript/packages/nodejs-client/src/node-adapter.ts new file mode 100644 index 0000000000..aacc0dc6a8 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/src/node-adapter.ts @@ -0,0 +1,43 @@ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +// Borrowed from https://github.com/GoogleChromeLabs/comlink/blob/main/src/node-adapter.ts + +import { Endpoint } from 'comlink'; + +export interface NodeEndpoint { + postMessage(message: any, transfer?: any[]): void; + on(type: string, listener: EventListenerOrEventListenerObject, options?: {}): void; + off(type: string, listener: EventListenerOrEventListenerObject, options?: {}): void; + start?: () => void; +} + +export default function nodeEndpoint(nep: NodeEndpoint): Endpoint { + const listeners = new WeakMap(); + return { + postMessage: nep.postMessage.bind(nep), + addEventListener: (_, eh) => { + const l = (data: any) => { + if ('handleEvent' in eh) { + eh.handleEvent({ data } as MessageEvent); + } else { + eh({ data } as MessageEvent); + } + }; + nep.on('message', l); + listeners.set(eh, l); + }, + removeEventListener: (_, eh) => { + const l = listeners.get(eh); + if (!l) { + return; + } + nep.off('message', l); + listeners.delete(eh); + }, + start: nep.start && nep.start.bind(nep), + }; +} diff --git a/sdk/typescript/packages/nodejs-client/src/subscriptions.ts b/sdk/typescript/packages/nodejs-client/src/subscriptions.ts index d819591f8b..84b411da28 100644 --- a/sdk/typescript/packages/nodejs-client/src/subscriptions.ts +++ b/sdk/typescript/packages/nodejs-client/src/subscriptions.ts @@ -54,6 +54,7 @@ export const createSubscriptions = () => { try { handler(event); } catch (e: any) { + // eslint-disable-next-line no-console console.error(`Unhandled exception in handler for ${key}: `, e); } }); diff --git a/sdk/typescript/packages/nodejs-client/src/types.ts b/sdk/typescript/packages/nodejs-client/src/types.ts index c395877f76..528dc849d5 100644 --- a/sdk/typescript/packages/nodejs-client/src/types.ts +++ b/sdk/typescript/packages/nodejs-client/src/types.ts @@ -1,4 +1,29 @@ -import type { DebugWasm } from '@nymproject/nym-client-wasm'; +import type { DebugWasm } from '@nymproject/nym-client-wasm-node'; + +/** + * Options for the Nym mixnet client. + * @property autoConvertStringMimeTypes - An array of mime types. + * @example + * ```typescript + * const client = await createNymMixnetClient({ + * autoConvertStringMimeTypes: [MimeTypes.ApplicationJson, MimeTypes.TextPlain], + * }); + * ``` + */ + +export interface NymMixnetClientOptions { + autoConvertStringMimeTypes?: string[] | MimeTypes[]; +} + +/** + * The client for the Nym mixnet which gives access to client methods and event subscriptions. + * Returned by the {@link createNymMixnetClient} function. + * + */ +export interface NymMixnetClient { + client: Client; + events: Events; +} /** * diff --git a/sdk/typescript/packages/nodejs-client/src/typings/rollup-worker.d.ts b/sdk/typescript/packages/nodejs-client/src/typings/rollup-worker.d.ts index ead3d9e1f4..b3814fe6aa 100644 --- a/sdk/typescript/packages/nodejs-client/src/typings/rollup-worker.d.ts +++ b/sdk/typescript/packages/nodejs-client/src/typings/rollup-worker.d.ts @@ -1,4 +1,6 @@ declare module 'web-worker:*' { + import { Worker } from 'worker_threads'; + const WorkerFactory: new () => Worker; export default WorkerFactory; } diff --git a/sdk/typescript/packages/nodejs-client/src/worker.ts b/sdk/typescript/packages/nodejs-client/src/worker.ts index e69de29bb2..a3966a42de 100644 --- a/sdk/typescript/packages/nodejs-client/src/worker.ts +++ b/sdk/typescript/packages/nodejs-client/src/worker.ts @@ -0,0 +1,261 @@ +// eslint-disable-next-line import/first +import * as Comlink from 'comlink'; +import * as crypto from 'node:crypto'; +import * as fs from 'node:fs'; +import * as process from 'node:process'; +import { indexedDB } from 'fake-indexeddb'; +import { parentPort } from 'worker_threads'; +import '@nymproject/nym-client-wasm-node/nym_client_wasm_bg.wasm'; + +import { + ClientConfig, + NymClient, + NymClientBuilder, + decode_payload, + encode_payload_with_headers, + parse_utf8_string, + utf8_string_to_byte_array, +} from '@nymproject/nym-client-wasm-node'; + +import type { + BinaryMessageReceivedEvent, + ConnectedEvent, + IWebWorker, + LoadedEvent, + NymClientConfig, + OnRawPayloadFn, + RawMessageReceivedEvent, + StringMessageReceivedEvent, +} from './types'; + +import nodeEndpoint from './node-adapter'; +import { EventKinds, MimeTypes } from './types'; + +// polyfill setup +const globalVar = + // eslint-disable-next-line @typescript-eslint/no-implied-eval, no-restricted-globals, no-nested-ternary + typeof WorkerGlobalScope !== 'undefined' ? self : typeof global !== 'undefined' ? global : Function('return this;')(); + +globalVar.indexedDB = indexedDB; +globalVar.fs = fs; +globalVar.process = process; +globalVar.performance = performance; +globalVar.TextEncoder = TextEncoder; +globalVar.TextDecoder = TextDecoder; +globalVar.crypto = crypto; + +// eslint-disable-next-line no-console +console.log('[Nym WASM client] Starting Nym WASM web worker...'); + +/** + * Helper method to send typed messages. + * @param event The strongly typed message to send back to the calling thread. + * see https://nodejs.org/api/worker_threads.html#workerparentport + */ +// eslint-disable-next-line no-restricted-globals +const postMessageWithType = (event: E) => parentPort?.postMessage(event); + +/** + * This class holds the state of the Nym WASM client and provides any interop needed. + */ +class ClientWrapper { + client: NymClient | null = null; + + builder: NymClientBuilder | null = null; + + mimeTypes: string[] = [MimeTypes.TextPlain, MimeTypes.ApplicationJson]; + + /** + * Creates the WASM client and initialises it. + */ + init = (config: any, onRawPayloadHandler?: OnRawPayloadFn) => { + const onMessageHandler = (message: Uint8Array) => { + try { + if (onRawPayloadHandler) { + onRawPayloadHandler(message); + } + } catch (e) { + // eslint-disable-next-line no-console + console.error('Unhandled exception in `ClientWrapper.onRawPayloadHandler`: ', e); + } + }; + + this.builder = new NymClientBuilder(config, onMessageHandler); + }; + + /** + * Sets the mime-types that will be parsed for UTF-8 string content. + * + * @param mimeTypes An array of mime-types to treat as having string content. + */ + setTextMimeTypes = (mimeTypes: string[]) => { + this.mimeTypes = mimeTypes; + }; + + /** + * Gest the mime-types that are considered as string and will be automatically converted to byte arrays. + */ + getTextMimeTypes = () => this.mimeTypes; + + /** + * Returns the address of this client. + */ + selfAddress = () => { + if (!this.client) { + // eslint-disable-next-line no-console + console.error('Client has not been initialised. Please call `init` first.'); + return undefined; + } + return this.client.self_address(); + }; + + /** + * Connects to the gateway and starts the client sending traffic. + */ + start = async () => { + if (!this.builder) { + // eslint-disable-next-line no-console + console.error('Client config has not been initialised. Please call `init` first.'); + return; + } + // this is current limitation of wasm in rust - for async methods you can't take self by reference... + // I'm trying to figure out if I can somehow hack my way around it, but for time being you have to re-assign + // the object (it's the same one) + this.client = await this.builder.start_client(); + }; + + /** + * Stops the client and cleans up. + */ + stop = () => { + if (!this.client) { + // eslint-disable-next-line no-console + console.error('Client has not been initialised. Please call `init` first.'); + return; + } + this.client.free(); + this.client = null; + }; + + send = async ({ + payload, + recipient, + replySurbs = 0, + }: { + payload: Uint8Array; + recipient: string; + replySurbs?: number; + }) => { + if (!this.client) { + // eslint-disable-next-line no-console + console.error('Client has not been initialised. Please call `init` first.'); + return; + } + // TODO: currently we don't do anything with the result, it needs some typing and exposed back on the main thread + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const res = await this.client.send_anonymous_message(payload, recipient, replySurbs); + }; +} + +// this wrapper handles any state that the wasm-pack interop needs, e.g. holding an instance of the instantiated WASM code +const wrapper = new ClientWrapper(); + +const startHandler = async (config: NymClientConfig) => { + // create the client, passing handlers for events + wrapper.init(new ClientConfig(config), async (message) => { + // fire an event with the raw message + postMessageWithType({ + kind: EventKinds.RawMessageReceived, + args: { payload: message }, + }); + try { + // try to decode the payload to extract the mime-type, headers and payload body + const decodedPayload = decode_payload(message); + const { payload, headers } = decodedPayload; + const mimeType = decodedPayload.mimeType as MimeTypes; + if (wrapper.getTextMimeTypes().includes(mimeType)) { + const stringMessage = parse_utf8_string(payload); + // the payload is a string type (in the options at creation time, string mime-types are set, or fall back + // to defaults, such as `text/plain`, `application/json`, etc) + postMessageWithType({ + kind: EventKinds.StringMessageReceived, + args: { mimeType, payload: stringMessage, payloadRaw: payload, headers }, + }); + return; + } + // the payload is a binary type + postMessageWithType({ + kind: EventKinds.BinaryMessageReceived, + args: { mimeType, payload, headers }, + }); + } catch (e) { + // eslint-disable-next-line no-console + console.error('Failed to parse binary message', e); + } + }); + // start the client sending traffic + await wrapper.start(); + // get the address + const address = wrapper.selfAddress(); + postMessageWithType({ kind: EventKinds.Connected, args: { address } }); +}; + +// implement the public logic of this web worker (message exchange between the worker and caller is done by https://www.npmjs.com/package/comlink) +const webWorker: IWebWorker = { + start(config) { + // eslint-disable-next-line no-console + startHandler(config).catch((e) => console.error('[Nym WASM client] Failed to start', e)); + }, + stop() { + wrapper.stop(); + }, + selfAddress() { + return wrapper.selfAddress(); + }, + setTextMimeTypes(mimeTypes) { + wrapper.setTextMimeTypes(mimeTypes); + }, + getTextMimeTypes() { + return wrapper.getTextMimeTypes(); + }, + send(args) { + const { + recipient, + replySurbs, + payload: { mimeType, headers }, + } = args; + let payloadBytes = new Uint8Array(); + if (mimeType && wrapper.getTextMimeTypes().includes(mimeType) && typeof args.payload.message === 'string') { + payloadBytes = utf8_string_to_byte_array(args.payload.message); + } else if (typeof args.payload.message !== 'string') { + payloadBytes = args.payload.message; + } else { + // eslint-disable-next-line no-console + console.error( + "[Nym WASM client] Payload is a string. It should be a UintArray, or the mime-type should be set with `setTextMimeTypes` or in the options for `init({ autoConvertStringMimeTypes: ['text/plain', 'application/json'] })` for auto-conversion", + ); + return; + } + const payload = encode_payload_with_headers(mimeType || MimeTypes.ApplicationOctetStream, payloadBytes, headers); + wrapper + .send({ payload, recipient, replySurbs }) + // eslint-disable-next-line no-console + .catch((e) => console.error('[Nym WASM client] Failed to send message', e)); + }, + rawSend(args) { + const { recipient, payload, replySurbs } = args; + wrapper + .send({ payload, replySurbs, recipient }) + // eslint-disable-next-line no-console + .catch((e) => console.error('[Nym WASM client] Failed to send message', e)); + }, +}; + +// start comlink listening for messages and handle them above, if we are on a worker thread. +if (parentPort) { + Comlink.expose(webWorker, nodeEndpoint(parentPort)); +} + +// notify any listeners that the web worker has loaded - HOWEVER, the client has not been created and connected, +// listen for EventKinds.Connected before sending messages +postMessageWithType({ kind: EventKinds.Loaded, args: { loaded: true } }); diff --git a/sdk/typescript/packages/nodejs-client/tsconfig.json b/sdk/typescript/packages/nodejs-client/tsconfig.json index d613d363a3..5e2e667792 100644 --- a/sdk/typescript/packages/nodejs-client/tsconfig.json +++ b/sdk/typescript/packages/nodejs-client/tsconfig.json @@ -1,13 +1,7 @@ { "compileOnSave": false, "compilerOptions": { - "lib": [ - "es2021", - "dom", - "dom.iterable", - "esnext", - "webworker" - ], + "lib": ["es2021", "webworker"], "outDir": "./dist/", "module": "esnext", "target": "esnext", @@ -17,26 +11,9 @@ "skipLibCheck": true, "skipDefaultLibCheck": true, "declaration": true, + "allowSyntheticDefaultImports": true, "baseUrl": "." }, - "include": [ - "src/**/*.ts" - ], - "exclude": [ - "jest.config.js", - "webpack.config.js", - "webpack.prod.js", - "webpack.common.js", - "node_modules", - "**/node_modules", - "dist", - "**/dist", - "scripts", - "jest", - "__tests__", - "**/__tests__", - "__jest__", - "**/__jest__", - "config/*", - ] + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "**/node_modules", "dist", "**/dist", "scripts"] } diff --git a/sdk/typescript/packages/nodejs-client/yarn.lock b/sdk/typescript/packages/nodejs-client/yarn.lock new file mode 100644 index 0000000000..943e1eb3de --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/yarn.lock @@ -0,0 +1,2951 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@babel/runtime@^7.20.7": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.2.tgz#062b0ac103261d68a966c4c7baf2ae3e62ec3885" + integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg== + dependencies: + regenerator-runtime "^0.14.0" + +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4" + integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA== + +"@eslint/eslintrc@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" + integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.51.0": + version "8.51.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.51.0.tgz#6d419c240cfb2b66da37df230f7e7eef801c32fa" + integrity sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg== + +"@humanwhocodes/config-array@^0.11.11": + version "0.11.11" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.11.tgz#88a04c570dbbc7dd943e4712429c3df09bc32844" + integrity sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.3": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" + integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.19" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811" + integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nymproject/nym-client-wasm-node@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@nymproject/nym-client-wasm-node/-/nym-client-wasm-node-1.2.0.tgz#46abe6b7535e80107d837bc6cc47edc1734aa773" + integrity sha512-L2hvMuudTQJgS/ZGGCSCD2oroccf7jWYXrq/E0Qqu0IxLlyjnTJ1xWWwXzUuwzBs+V5YZb0VIdB0kAovGLA+VA== + +"@rollup/plugin-commonjs@^24.0.1": + version "24.1.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-24.1.0.tgz#79e54bd83bb64396761431eee6c44152ef322100" + integrity sha512-eSL45hjhCWI0jCCXcNtLVqM5N1JlBGvlFfY0m6oOYnLCJ6N0qEXoZql4sY2MOUArzhH4SA/qBpTxvvZp2Sc+DQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + commondir "^1.0.1" + estree-walker "^2.0.2" + glob "^8.0.3" + is-reference "1.2.1" + magic-string "^0.27.0" + +"@rollup/plugin-inject@^5.0.3": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz#616f3a73fe075765f91c5bec90176608bed277a3" + integrity sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg== + dependencies: + "@rollup/pluginutils" "^5.0.1" + estree-walker "^2.0.2" + magic-string "^0.30.3" + +"@rollup/plugin-node-resolve@^15.0.1": + version "15.2.3" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz#e5e0b059bd85ca57489492f295ce88c2d4b0daf9" + integrity sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + "@types/resolve" "1.20.2" + deepmerge "^4.2.2" + is-builtin-module "^3.2.1" + is-module "^1.0.0" + resolve "^1.22.1" + +"@rollup/plugin-replace@^5.0.2": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-5.0.4.tgz#fef548dc751d06747e8dca5b0e8e1fbf647ac7e1" + integrity sha512-E2hmRnlh09K8HGT0rOnnri9OTh+BILGr7NVJGB30S4E3cLRn3J0xjdiyOZ74adPs4NiAMgrjUMGAZNJDBgsdmQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + magic-string "^0.30.3" + +"@rollup/plugin-terser@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-terser/-/plugin-terser-0.2.1.tgz#dcf0b163216dafb64611b170a7667e76a7f03d2b" + integrity sha512-hV52c8Oo6/cXZZxVVoRNBb4zh+EKSHS4I1sedWV5pf0O+hTLSkrf6w86/V0AZutYtwBguB6HLKwz89WDBfwGOA== + dependencies: + serialize-javascript "^6.0.0" + smob "^0.0.6" + terser "^5.15.1" + +"@rollup/plugin-typescript@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-10.0.1.tgz#270b515b116ea28320e6bb62451c4767d49072d6" + integrity sha512-wBykxRLlX7EzL8BmUqMqk5zpx2onnmRMSw/l9M1sVfkJvdwfxogZQVNUM9gVMJbjRLDR5H6U0OMOrlDGmIV45A== + dependencies: + "@rollup/pluginutils" "^5.0.1" + resolve "^1.22.1" + +"@rollup/plugin-url@^8.0.1": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-url/-/plugin-url-8.0.2.tgz#aab4e209e9e012f65582bd99eb80b3bbdfe15afb" + integrity sha512-5yW2LP5NBEgkvIRSSEdJkmxe5cUNZKG3eenKtfJvSkxVm/xTTu7w+ayBtNwhozl1ZnTUCU0xFaRQR+cBl2H7TQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + make-dir "^3.1.0" + mime "^3.0.0" + +"@rollup/plugin-wasm@^6.1.1": + version "6.2.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-wasm/-/plugin-wasm-6.2.2.tgz#ea75fd8cc5ddba1e30bdc22e07cdbaf8d6d160bf" + integrity sha512-gpC4R1G9Ni92ZIRTexqbhX7U+9estZrbhP+9SRb0DW9xpB9g7j34r+J2hqrcW/lRI7dJaU84MxZM0Rt82tqYPQ== + dependencies: + "@rollup/pluginutils" "^5.0.2" + +"@rollup/pluginutils@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== + dependencies: + "@types/estree" "0.0.39" + estree-walker "^1.0.1" + picomatch "^2.2.2" + +"@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@^5.0.2": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.5.tgz#bbb4c175e19ebfeeb8c132c2eea0ecb89941a66c" + integrity sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + +"@types/estree@*", "@types/estree@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.2.tgz#ff02bc3dc8317cd668dfec247b750ba1f1d62453" + integrity sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA== + +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + +"@types/json-schema@^7.0.9": + version "7.0.13" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85" + integrity sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + +"@types/node@^16.7.13": + version "16.18.58" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.58.tgz#bf66f63983104ed57c754f4e84ccaf16f8235adb" + integrity sha512-YGncyA25/MaVtQkjWW9r0EFBukZ+JulsLcVZBlGUfIb96OBMjkoRWwQo5IEWJ8Fj06Go3GHw+bjYDitv6BaGsA== + +"@types/resolve@1.20.2": + version "1.20.2" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" + integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== + +"@types/semver@^7.3.12": + version "7.5.3" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.3.tgz#9a726e116beb26c24f1ccd6850201e1246122e04" + integrity sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw== + +"@typescript-eslint/eslint-plugin@^5.13.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" + integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== + dependencies: + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/type-utils" "5.62.0" + "@typescript-eslint/utils" "5.62.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.13.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" + integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== + dependencies: + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + +"@typescript-eslint/type-utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" + integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== + dependencies: + "@typescript-eslint/typescript-estree" "5.62.0" + "@typescript-eslint/utils" "5.62.0" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== + +"@typescript-eslint/typescript-estree@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.62.0", "@typescript-eslint/utils@^5.10.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + eslint-scope "^5.1.1" + semver "^7.3.7" + +"@typescript-eslint/visitor-keys@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== + dependencies: + "@typescript-eslint/types" "5.62.0" + eslint-visitor-keys "^3.3.0" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.8.2, acorn@^8.9.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-sequence-parser@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf" + integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg== + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +aria-query@^5.1.3: + version "5.3.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" + integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== + dependencies: + dequal "^2.0.3" + +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + +array-includes@^3.1.6: + version "3.1.7" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" + integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.findlastindex@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207" + integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + get-intrinsic "^1.2.1" + +array.prototype.flat@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.tosorted@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz#620eff7442503d66c799d95503f82b475745cefd" + integrity sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + get-intrinsic "^1.2.1" + +arraybuffer.prototype.slice@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" + integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + +ast-types-flow@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" + integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag== + +asynciterator.prototype@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz#8c5df0514936cdd133604dfcc9d3fb93f09b2b62" + integrity sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg== + dependencies: + has-symbols "^1.0.3" + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +axe-core@^4.6.2: + version "4.8.2" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.8.2.tgz#2f6f3cde40935825cf4465e3c1c9e77b240ff6ae" + integrity sha512-/dlp0fxyM3R8YW7MFzaHWXrf4zzbr0vaYb23VBFCl83R7nWNPg/yaQw2Dc8jzCMmDVLhSdzH8MjrsuIUuvX+6g== + +axobject-query@^3.1.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" + integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg== + dependencies: + dequal "^2.0.3" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-arraybuffer-es6@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/base64-arraybuffer-es6/-/base64-arraybuffer-es6-0.7.0.tgz#dbe1e6c87b1bf1ca2875904461a7de40f21abc86" + integrity sha512-ESyU/U1CFZDJUdr+neHRhNozeCv72Y7Vm0m1DCbjX3KBjT6eYocvAJlSk6+8+HkVwXlT1FNxhGW6q3UKAlCvvw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +builtin-modules@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@^3.5.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +cli-color@~2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-2.0.3.tgz#73769ba969080629670f3f2ef69a4bf4e7cc1879" + integrity sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ== + dependencies: + d "^1.0.1" + es5-ext "^0.10.61" + es6-iterator "^2.0.3" + memoizee "^0.4.15" + timers-ext "^0.1.7" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +comlink@^4.3.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.4.1.tgz#e568b8e86410b809e8600eb2cf40c189371ef981" + integrity sha512-+1dlx0aY5Jo1vHy/tSsIGpSkN4tS9rZSW8FIhG0JH/crs9wwweswIo/POr451r7bZww3hFbPAKnTpimzL/mm4Q== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@~9.4.0: + version "9.4.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" + integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +confusing-browser-globals@^1.0.10: + version "1.0.11" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" + integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +damerau-levenshtein@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" + integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +define-data-property@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" + integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== + dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +dequal@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +domexception@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" + integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== + dependencies: + webidl-conversions "^4.0.2" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +enhanced-resolve@^5.0.0: + version "5.15.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" + integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +es-abstract@^1.22.1: + version "1.22.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.2.tgz#90f7282d91d0ad577f505e423e52d4c1d93c1b8a" + integrity sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA== + dependencies: + array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.2" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.1" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.12" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.1" + safe-array-concat "^1.0.1" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.8" + string.prototype.trimend "^1.0.7" + string.prototype.trimstart "^1.0.7" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" + typed-array-byte-offset "^1.0.0" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.11" + +es-iterator-helpers@^1.0.12: + version "1.0.15" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz#bd81d275ac766431d19305923707c3efd9f1ae40" + integrity sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g== + dependencies: + asynciterator.prototype "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.1" + es-abstract "^1.22.1" + es-set-tostringtag "^2.0.1" + function-bind "^1.1.1" + get-intrinsic "^1.2.1" + globalthis "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + iterator.prototype "^1.1.2" + safe-array-concat "^1.0.1" + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: + version "0.10.62" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" + integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +es6-weak-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== + dependencies: + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-airbnb-base@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236" + integrity sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig== + dependencies: + confusing-browser-globals "^1.0.10" + object.assign "^4.1.2" + object.entries "^1.1.5" + semver "^6.3.0" + +eslint-config-airbnb-typescript@^16.1.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-16.2.0.tgz#9193fafd62f1cbf444895f4495eae334baf3265b" + integrity sha512-OUaMPZpTOZGKd5tXOjJ9PRU4iYNW/Z5DoHIynjsVK/FpkWdiY5+nxQW6TiJAlLwVI1l53xUOrnlZWtVBVQzuWA== + dependencies: + eslint-config-airbnb-base "^15.0.0" + +eslint-config-airbnb@^19.0.4: + version "19.0.4" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz#84d4c3490ad70a0ffa571138ebcdea6ab085fdc3" + integrity sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew== + dependencies: + eslint-config-airbnb-base "^15.0.0" + object.assign "^4.1.2" + object.entries "^1.1.5" + +eslint-config-prettier@^8.5.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" + integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== + +eslint-import-resolver-node@^0.3.2, eslint-import-resolver-node@^0.3.7: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== + dependencies: + debug "^3.2.7" + is-core-module "^2.13.0" + resolve "^1.22.4" + +eslint-import-resolver-root-import@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-root-import/-/eslint-import-resolver-root-import-1.0.4.tgz#82991138d8014b5e2283b27622ad1ba21f535609" + integrity sha512-c8cUQcELRBe0mnblBZJKEfL+jIUGR8pctK5gdru5N7bBOIve2WZ0R3KoO5GOksXJ4WzZhtcBS2xPaTJYEe4IdQ== + dependencies: + eslint-import-resolver-node "^0.3.2" + json5 "^2.1.0" + +eslint-module-utils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" + integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== + dependencies: + debug "^3.2.7" + +eslint-plugin-import@^2.25.4: + version "2.28.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz#63b8b5b3c409bfc75ebaf8fb206b07ab435482c4" + integrity sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A== + dependencies: + array-includes "^3.1.6" + array.prototype.findlastindex "^1.2.2" + array.prototype.flat "^1.3.1" + array.prototype.flatmap "^1.3.1" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.7" + eslint-module-utils "^2.8.0" + has "^1.0.3" + is-core-module "^2.13.0" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.fromentries "^2.0.6" + object.groupby "^1.0.0" + object.values "^1.1.6" + semver "^6.3.1" + tsconfig-paths "^3.14.2" + +eslint-plugin-jest@^26.1.1: + version "26.9.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz#7931c31000b1c19e57dbfb71bbf71b817d1bf949" + integrity sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng== + dependencies: + "@typescript-eslint/utils" "^5.10.0" + +eslint-plugin-jsx-a11y@^6.5.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz#fca5e02d115f48c9a597a6894d5bcec2f7a76976" + integrity sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA== + dependencies: + "@babel/runtime" "^7.20.7" + aria-query "^5.1.3" + array-includes "^3.1.6" + array.prototype.flatmap "^1.3.1" + ast-types-flow "^0.0.7" + axe-core "^4.6.2" + axobject-query "^3.1.1" + damerau-levenshtein "^1.0.8" + emoji-regex "^9.2.2" + has "^1.0.3" + jsx-ast-utils "^3.3.3" + language-tags "=1.0.5" + minimatch "^3.1.2" + object.entries "^1.1.6" + object.fromentries "^2.0.6" + semver "^6.3.0" + +eslint-plugin-prettier@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-react-hooks@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" + integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== + +eslint-plugin-react@^7.29.2: + version "7.33.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz#69ee09443ffc583927eafe86ffebb470ee737608" + integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw== + dependencies: + array-includes "^3.1.6" + array.prototype.flatmap "^1.3.1" + array.prototype.tosorted "^1.1.1" + doctrine "^2.1.0" + es-iterator-helpers "^1.0.12" + estraverse "^5.3.0" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.6" + object.fromentries "^2.0.6" + object.hasown "^1.1.2" + object.values "^1.1.6" + prop-types "^15.8.1" + resolve "^2.0.0-next.4" + semver "^6.3.1" + string.prototype.matchall "^4.0.8" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8.10.0: + version "8.51.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.51.0.tgz#4a82dae60d209ac89a5cff1604fea978ba4950f3" + integrity sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.2" + "@eslint/js" "8.51.0" + "@humanwhocodes/config-array" "^0.11.11" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + +ext@^1.1.2: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + +fake-indexeddb@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-4.0.2.tgz#e7a884158fa576e00f03e973b9874619947013e4" + integrity sha512-SdTwEhnakbgazc7W3WUXOJfGmhH0YfG4d+dRPOFoYDRTL6U5t8tvrmkf2W/C3W1jk2ylV7Wrnj44RASqpX/lEw== + dependencies: + realistic-structured-clone "^3.0.0" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-glob@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.1.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.1.tgz#a02a15fdec25a8f844ff7cc658f03dd99eb4609b" + integrity sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + +flatted@^3.2.9: + version "3.2.9" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" + integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^8.0.3: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +globals@^13.19.0: + version "13.23.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.23.0.tgz#ef31673c926a0976e1f61dab4dca57e0c0a8af02" + integrity sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA== + dependencies: + type-fest "^0.20.2" + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" + integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== + +ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + +is-async-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" + integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== + dependencies: + has-tostringtag "^1.0.0" + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-builtin-module@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" + integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== + dependencies: + builtin-modules "^3.3.0" + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + +is-date-object@^1.0.1, is-date-object@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finalizationregistry@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" + integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== + dependencies: + call-bind "^1.0.2" + +is-generator-function@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-map@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" + integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== + +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-promise@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + +is-reference@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== + dependencies: + "@types/estree" "*" + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-set@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" + integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== + dependencies: + which-typed-array "^1.1.11" + +is-weakmap@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" + integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-weakset@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d" + integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +iterator.prototype@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" + integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== + dependencies: + define-properties "^1.2.1" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + reflect.getprototypeof "^1.0.4" + set-function-name "^2.0.1" + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + +json5@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonc-parser@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3: + version "3.3.5" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== + dependencies: + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + object.assign "^4.1.4" + object.values "^1.1.6" + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +language-subtag-registry@~0.3.2: + version "0.3.22" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" + integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w== + +language-tags@=1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" + integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ== + dependencies: + language-subtag-registry "~0.3.2" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash@^4.7.0: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lru-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ== + dependencies: + es5-ext "~0.10.2" + +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + +magic-string@0.25.2: + version "0.25.2" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.2.tgz#139c3a729515ec55e96e69e82a11fe890a293ad9" + integrity sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg== + dependencies: + sourcemap-codec "^1.4.4" + +magic-string@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" + integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" + +magic-string@^0.30.3: + version "0.30.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9" + integrity sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + +make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +marked@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== + +memoizee@^0.4.15: + version "0.4.15" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72" + integrity sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ== + dependencies: + d "^1.0.1" + es5-ext "^0.10.53" + es6-weak-map "^2.0.3" + event-emitter "^0.3.5" + is-promise "^2.2.2" + lru-queue "^0.1.0" + next-tick "^1.1.0" + timers-ext "^0.1.7" + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.0, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + +minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.0: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.0: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +next-tick@1, next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +nodemon@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.0.1.tgz#affe822a2c5f21354466b2fc8ae83277d27dadc7" + integrity sha512-g9AZ7HmkhQkqXkRc20w+ZfQ73cHLbE8hnPbtaFbFtCumZsjyMhKk9LajQ07U5Ux28lvFjZ5X7HvWR1xzU8jHVw== + dependencies: + chokidar "^3.5.2" + debug "^3.2.7" + ignore-by-default "^1.0.1" + minimatch "^3.1.2" + pstree.remy "^1.1.8" + semver "^7.5.3" + simple-update-notifier "^2.0.0" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.5" + +nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== + dependencies: + abbrev "1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.12.3, object-inspect@^1.9.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.0.tgz#42695d3879e1cd5bda6df5062164d80c996e23e2" + integrity sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.2, object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.entries@^1.1.5, object.entries@^1.1.6: + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.7.tgz#2b47760e2a2e3a752f39dd874655c61a7f03c131" + integrity sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.fromentries@^2.0.6: + version "2.0.7" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" + integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.groupby@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee" + integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + +object.hasown@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.3.tgz#6a5f2897bb4d3668b8e79364f98ccf971bda55ae" + integrity sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA== + dependencies: + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.values@^1.1.6: + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +open@^8.0.0: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + +ospec@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ospec/-/ospec-3.1.0.tgz#d36b8e10110f58f63a463df2390a7a73fe9579a8" + integrity sha512-+nGtjV3vlADp+UGfL51miAh/hB4awPBkQrArhcgG4trAaoA2gKt5bf9w0m9ch9zOr555cHWaCHZEDiBOkNZSxw== + dependencies: + glob "^7.1.3" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +pstree.remy@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +react-is@^16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +realistic-structured-clone@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/realistic-structured-clone/-/realistic-structured-clone-3.0.0.tgz#7b518049ce2dad41ac32b421cd297075b00e3e35" + integrity sha512-rOjh4nuWkAqf9PWu6JVpOWD4ndI+JHfgiZeMmujYcPi+fvILUu7g6l26TC1K5aBIp34nV+jE1cDO75EKOfHC5Q== + dependencies: + domexception "^1.0.1" + typeson "^6.1.0" + typeson-registry "^1.0.0-alpha.20" + +reflect.getprototypeof@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3" + integrity sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + globalthis "^1.0.3" + which-builtin-type "^1.1.3" + +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + +regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" + integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + set-function-name "^2.0.0" + +reload@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/reload/-/reload-3.2.1.tgz#42d43e33e327efe1348c723272c6835fe333349a" + integrity sha512-ZdM8ZSEeI72zkhh6heMEvJ0vHZoovZXcJI6Zae8CzS7o5vO/WjZsAMMr0y1+3I/fCN7y7ZxABoUwwCswcLHkjQ== + dependencies: + cli-color "~2.0.0" + commander "~9.4.0" + finalhandler "~1.2.0" + minimist "~1.2.0" + open "^8.0.0" + serve-static "~1.15.0" + supervisor "~0.12.0" + ws "~8.11.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^1.22.1, resolve@^1.22.4: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^2.0.0-next.4: + version "2.0.0-next.5" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rollup-plugin-base64@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-base64/-/rollup-plugin-base64-1.0.1.tgz#b3529b94d23baeb66e1e3bffd04477fa792985eb" + integrity sha512-IbdX8fjuXO/Op3hYmRPjVo0VwcSenwsQDaDTFdoe+70B5ZGoLMtr96L2yhHXCfxv7HwZVvxZqLsuWj6VwzRt3g== + dependencies: + "@rollup/pluginutils" "^3.1.0" + +rollup-plugin-modify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-modify/-/rollup-plugin-modify-3.0.0.tgz#5326e11dfec247e8bbdd9507f3da1da1e5c7818b" + integrity sha512-p/ffs0Y2jz2dEnWjq1oVC7SY37tuS+aP7whoNaQz1EAAOPg+k3vKJo8cMMWx6xpdd0NzhX4y2YF9o/NPu5YR0Q== + dependencies: + magic-string "0.25.2" + ospec "3.1.0" + +rollup-plugin-polyfill@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-polyfill/-/rollup-plugin-polyfill-4.2.0.tgz#414c7ffca0557bf29a8f4e073b8eb7f4d02dac42" + integrity sha512-6eeOyn7nr2/xUOtB+MhydvqLrNKcSybGneOuWA+t8Q4rR9NQyeapzwuu5n6nX8OFfY1WI1sHconAofaC44IpuA== + +rollup-plugin-web-worker-loader@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-web-worker-loader/-/rollup-plugin-web-worker-loader-1.6.1.tgz#9d7a27575b64b0780fe4e8b3bc87470d217e485f" + integrity sha512-4QywQSz1NXFHKdyiou16mH3ijpcfLtLGOrAqvAqu1Gx+P8+zj+3gwC2BSL/VW1d+LW4nIHC8F7d7OXhs9UdR2A== + +rollup@^3.9.1: + version "3.29.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" + integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw== + optionalDependencies: + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-array-concat@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" + integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + isarray "^2.0.5" + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + +semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.4, semver@^7.3.7, semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-javascript@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" + integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== + dependencies: + randombytes "^2.1.0" + +serve-static@~1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-function-name@^2.0.0, set-function-name@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" + integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== + dependencies: + define-data-property "^1.0.1" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.0" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shiki@^0.14.1: + version "0.14.5" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.5.tgz#375dd214e57eccb04f0daf35a32aa615861deb93" + integrity sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw== + dependencies: + ansi-sequence-parser "^1.1.0" + jsonc-parser "^3.2.0" + vscode-oniguruma "^1.7.0" + vscode-textmate "^8.0.0" + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +simple-update-notifier@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" + integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== + dependencies: + semver "^7.5.3" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +smob@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/smob/-/smob-0.0.6.tgz#09b268fea916158a2781c152044c6155adbb8aa1" + integrity sha512-V21+XeNni+tTyiST1MHsa84AQhT1aFZipzPpOFAVB8DkHzwJyjjAmt9bgwnuZiZWnIbMo2duE29wybxv/7HWUw== + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +sourcemap-codec@^1.4.4: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +string.prototype.matchall@^4.0.8: + version "4.0.10" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz#a1553eb532221d4180c51581d6072cd65d1ee100" + integrity sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + regexp.prototype.flags "^1.5.0" + set-function-name "^2.0.0" + side-channel "^1.0.4" + +string.prototype.trim@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" + integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string.prototype.trimend@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" + integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string.prototype.trimstart@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" + integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supervisor@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/supervisor/-/supervisor-0.12.0.tgz#de7e6337015b291851c10f3538c4a7f04917ecc1" + integrity sha512-iBYeU5Or4WiiIa3+ns1DpHIiHjNNXSuYUiixKcznewwo4ImBJ8EobktaAo2csOcauhrz4SvKRTou8Z2C3W28+A== + +supports-color@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser@^5.15.1: + version "5.22.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.22.0.tgz#4f18103f84c5c9437aafb7a14918273310a8a49d" + integrity sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +timers-ext@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" + integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== + dependencies: + es5-ext "~0.10.46" + next-tick "1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +touch@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" + integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== + dependencies: + nopt "~1.0.10" + +tr46@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" + integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== + dependencies: + punycode "^2.1.1" + +ts-loader@^9.4.2: + version "9.5.0" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.5.0.tgz#f0a51dda37cc4d8e43e6cb14edebbc599b0c3aa2" + integrity sha512-LLlB/pkB4q9mW2yLdFMnK3dEHbrBjeZTYguaaIfusyojBgAGf5kF+O6KcWqiGzWqHk0LBsoolrp4VftEURhybg== + dependencies: + chalk "^4.1.0" + enhanced-resolve "^5.0.0" + micromatch "^4.0.0" + semver "^7.3.4" + source-map "^0.7.4" + +tsconfig-paths@^3.14.2: + version "3.14.2" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" + integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== + +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" + integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +typedoc@^0.24.8: + version "0.24.8" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.24.8.tgz#cce9f47ba6a8d52389f5e583716a2b3b4335b63e" + integrity sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w== + dependencies: + lunr "^2.3.9" + marked "^4.3.0" + minimatch "^9.0.0" + shiki "^0.14.1" + +typescript@^4.8.4: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + +typeson-registry@^1.0.0-alpha.20: + version "1.0.0-alpha.39" + resolved "https://registry.yarnpkg.com/typeson-registry/-/typeson-registry-1.0.0-alpha.39.tgz#9e0f5aabd5eebfcffd65a796487541196f4b1211" + integrity sha512-NeGDEquhw+yfwNhguLPcZ9Oj0fzbADiX4R0WxvoY8nGhy98IbzQy1sezjoEFWOywOboj/DWehI+/aUlRVrJnnw== + dependencies: + base64-arraybuffer-es6 "^0.7.0" + typeson "^6.0.0" + whatwg-url "^8.4.0" + +typeson@^6.0.0, typeson@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/typeson/-/typeson-6.1.0.tgz#5b2a53705a5f58ff4d6f82f965917cabd0d7448b" + integrity sha512-6FTtyGr8ldU0pfbvW/eOZrEtEkczHRUtduBnA90Jh9kMPCiFNnXIon3vF41N0S4tV1HHQt4Hk1j4srpESziCaA== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +undefsafe@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +vscode-oniguruma@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" + integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA== + +vscode-textmate@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d" + integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg== + +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + +whatwg-url@^8.4.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" + integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== + dependencies: + lodash "^4.7.0" + tr46 "^2.1.0" + webidl-conversions "^6.1.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-builtin-type@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" + integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== + dependencies: + function.prototype.name "^1.1.5" + has-tostringtag "^1.0.0" + is-async-function "^2.0.0" + is-date-object "^1.0.5" + is-finalizationregistry "^1.0.2" + is-generator-function "^1.0.10" + is-regex "^1.1.4" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.1" + which-typed-array "^1.1.9" + +which-collection@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" + integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== + dependencies: + is-map "^2.0.1" + is-set "^2.0.1" + is-weakmap "^2.0.1" + is-weakset "^2.0.1" + +which-typed-array@^1.1.11, which-typed-array@^1.1.9: + version "1.1.11" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" + integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@^8.14.2: + version "8.14.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" + integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== + +ws@~8.11.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" + integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/sdk/typescript/scripts/publish.sh b/sdk/typescript/scripts/publish.sh index 43084f930b..fff437da72 100755 --- a/sdk/typescript/scripts/publish.sh +++ b/sdk/typescript/scripts/publish.sh @@ -36,6 +36,8 @@ packages=( "ts/sdk/mix-fetch/esm" "ts/sdk/mix-fetch/esm-full-fat" +"ts/sdk/nodejs-client/cjs" + "ts/sdk/node-tester/cjs" "ts/sdk/node-tester/cjs-full-fat" "ts/sdk/node-tester/esm" diff --git a/sdk/typescript/scripts/unpublish.sh b/sdk/typescript/scripts/unpublish.sh index 99ef7b5e25..8d0671faa9 100755 --- a/sdk/typescript/scripts/unpublish.sh +++ b/sdk/typescript/scripts/unpublish.sh @@ -23,6 +23,8 @@ packages2=( "ts/sdk/mix-fetch/esm" "ts/sdk/mix-fetch/esm-full-fat" +"ts/sdk/nodejs-client/cjs" + "ts/sdk/node-tester/cjs" "ts/sdk/node-tester/cjs-full-fat" "ts/sdk/node-tester/esm" From 14d0d5dcbb76f49a1b0e069e2744aba8e4c1d61c Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Wed, 18 Oct 2023 07:42:06 +0200 Subject: [PATCH 161/236] Add mix-fetch for nodejs --- .../packages/mix-fetch-node/.babelrc | 3 + .../packages/mix-fetch-node/.gitignore | 2 + .../packages/mix-fetch-node/README.md | 14 + .../mix-fetch-node/internal-dev/index.mjs | 54 + .../packages/mix-fetch-node/jest.config.mjs | 16 + .../packages/mix-fetch-node/package.json | 71 + .../mix-fetch-node/rollup-cjs.config.mjs | 31 + .../mix-fetch-node/rollup-worker.config.mjs | 40 + .../scripts/build-prod-docs-collect.sh | 17 + .../mix-fetch-node/scripts/build-prod.sh | 20 + .../packages/mix-fetch-node/scripts/build.sh | 48 + .../scripts/buildPackageJson.mjs | 22 + .../mix-fetch-node/scripts/publish.sh | 17 + .../mix-fetch-node/src/create-mix-fetch.ts | 77 + .../packages/mix-fetch-node/src/index.ts | 57 + .../mix-fetch-node/src/node-adapter.ts | 43 + .../packages/mix-fetch-node/src/types.ts | 98 + .../worker/handle-response-mime-types.test.ts | 73 + .../src/worker/handle-response-mime-types.ts | 111 + .../mix-fetch-node/src/worker/index.ts | 8 + .../mix-fetch-node/src/worker/main.ts | 74 + .../mix-fetch-node/src/worker/polyfill.ts | 38 + .../mix-fetch-node/src/worker/wasm-loading.ts | 69 + .../mix-fetch-node/tsconfig.jest.json | 35 + .../packages/mix-fetch-node/tsconfig.json | 36 + .../packages/mix-fetch-node/typedoc.json | 32 + .../mix-fetch-node/typings/rollup-worker.d.ts | 6 + .../mix-fetch-node/typings/wasm_exec.d.ts | 11 + .../packages/mix-fetch-node/yarn.lock | 4428 +++++++++++++++++ sdk/typescript/scripts/publish.sh | 1 + sdk/typescript/scripts/unpublish.sh | 1 + wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go | 62 + 32 files changed, 5615 insertions(+) create mode 100644 sdk/typescript/packages/mix-fetch-node/.babelrc create mode 100644 sdk/typescript/packages/mix-fetch-node/.gitignore create mode 100644 sdk/typescript/packages/mix-fetch-node/README.md create mode 100644 sdk/typescript/packages/mix-fetch-node/internal-dev/index.mjs create mode 100644 sdk/typescript/packages/mix-fetch-node/jest.config.mjs create mode 100644 sdk/typescript/packages/mix-fetch-node/package.json create mode 100644 sdk/typescript/packages/mix-fetch-node/rollup-cjs.config.mjs create mode 100644 sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs create mode 100755 sdk/typescript/packages/mix-fetch-node/scripts/build-prod-docs-collect.sh create mode 100755 sdk/typescript/packages/mix-fetch-node/scripts/build-prod.sh create mode 100755 sdk/typescript/packages/mix-fetch-node/scripts/build.sh create mode 100644 sdk/typescript/packages/mix-fetch-node/scripts/buildPackageJson.mjs create mode 100755 sdk/typescript/packages/mix-fetch-node/scripts/publish.sh create mode 100644 sdk/typescript/packages/mix-fetch-node/src/create-mix-fetch.ts create mode 100644 sdk/typescript/packages/mix-fetch-node/src/index.ts create mode 100644 sdk/typescript/packages/mix-fetch-node/src/node-adapter.ts create mode 100644 sdk/typescript/packages/mix-fetch-node/src/types.ts create mode 100644 sdk/typescript/packages/mix-fetch-node/src/worker/handle-response-mime-types.test.ts create mode 100644 sdk/typescript/packages/mix-fetch-node/src/worker/handle-response-mime-types.ts create mode 100644 sdk/typescript/packages/mix-fetch-node/src/worker/index.ts create mode 100644 sdk/typescript/packages/mix-fetch-node/src/worker/main.ts create mode 100644 sdk/typescript/packages/mix-fetch-node/src/worker/polyfill.ts create mode 100644 sdk/typescript/packages/mix-fetch-node/src/worker/wasm-loading.ts create mode 100644 sdk/typescript/packages/mix-fetch-node/tsconfig.jest.json create mode 100644 sdk/typescript/packages/mix-fetch-node/tsconfig.json create mode 100644 sdk/typescript/packages/mix-fetch-node/typedoc.json create mode 100644 sdk/typescript/packages/mix-fetch-node/typings/rollup-worker.d.ts create mode 100644 sdk/typescript/packages/mix-fetch-node/typings/wasm_exec.d.ts create mode 100644 sdk/typescript/packages/mix-fetch-node/yarn.lock diff --git a/sdk/typescript/packages/mix-fetch-node/.babelrc b/sdk/typescript/packages/mix-fetch-node/.babelrc new file mode 100644 index 0000000000..0ef5ffc214 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@babel/env"] +} diff --git a/sdk/typescript/packages/mix-fetch-node/.gitignore b/sdk/typescript/packages/mix-fetch-node/.gitignore new file mode 100644 index 0000000000..71c42dc754 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/.gitignore @@ -0,0 +1,2 @@ +src/worker/*.js +docs diff --git a/sdk/typescript/packages/mix-fetch-node/README.md b/sdk/typescript/packages/mix-fetch-node/README.md new file mode 100644 index 0000000000..dc62208cd3 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/README.md @@ -0,0 +1,14 @@ +# Nym MixFetch + +This package is a drop-in replacement for `fetch` in NodeJS to send HTTP requests over the Nym Mixnet. + +## Usage + +```js +const { mixFetch } = require('@nymproject/mix-fetch-node'); + +... + +const response = await mixFetch('https://nymtech.net'); +const html = await response.text(); +``` diff --git a/sdk/typescript/packages/mix-fetch-node/internal-dev/index.mjs b/sdk/typescript/packages/mix-fetch-node/internal-dev/index.mjs new file mode 100644 index 0000000000..a49455449d --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/internal-dev/index.mjs @@ -0,0 +1,54 @@ +import { createMixFetch, disconnectMixFetch } from '../dist/cjs/index.js'; + +/** + * The main entry point + */ +(async () => { + console.log('Tester is starting up...'); + + const addr = + 'D274yd1h3L3pNJzdxE5VgJ7izAsAVMsDrQtFSkKUegfk.8J67cGbcwvrJKF3Kb16HVWWc9AnrFnEibNCm9zCkuVFu@Emswx6KXyjRfq1c2k4d4uD2e6nBSbH1biorCZUei8UNS'; + + console.log('About to set up mixFetch...'); + const { mixFetch } = await createMixFetch({ + preferredNetworkRequester: addr, + clientId: 'node-client1', + clientOverride: { + coverTraffic: { disableLoopCoverTrafficStream: true }, + traffic: { disableMainPoissonPacketDistribution: true }, + }, + mixFetchOverride: { requestTimeoutMs: 60000 }, + responseBodyConfigMap: {}, + extra: {}, + }); + + globalThis.mixFetch = mixFetch; + + if (!globalThis.mixFetch) { + console.error('Oh no! Could not create mixFetch'); + } else { + console.log('Ready!'); + } + + let url = 'https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt'; + console.log(`Using mixFetch to get ${url}...`); + const args = { mode: 'unsafe-ignore-cors' }; + + let resp = await mixFetch(url, args); + console.log({ resp }); + const text = await resp.text(); + + console.log('disconnecting'); + await disconnectMixFetch(); + console.log('disconnected! all further usages should fail'); + + // get an image + url = 'https://nymtech.net/favicon.svg'; + resp = await mixFetch(url, args); + console.log({ resp }); + const buffer = await resp.arrayBuffer(); + const type = resp.headers.get('Content-Type') || 'image/svg'; + const blobUrl = URL.createObjectURL(new Blob([buffer], { type })); + console.log(JSON.stringify({ bufferBytes: buffer.byteLength, blobUrl }, null, 2)); + console.log(blobUrl); +})(); diff --git a/sdk/typescript/packages/mix-fetch-node/jest.config.mjs b/sdk/typescript/packages/mix-fetch-node/jest.config.mjs new file mode 100644 index 0000000000..568dd98124 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/jest.config.mjs @@ -0,0 +1,16 @@ +import preset from 'ts-jest/presets/index.js'; + +/** @type {import('ts-jest').JestConfigWithTsJest} */ +export default { + ...preset.defaults, + verbose: true, + transform: { + '^.+\\.(ts|tsx)$': [ + 'ts-jest', + { + tsconfig: 'tsconfig.jest.json', + useESM: true, + }, + ], + }, +}; diff --git a/sdk/typescript/packages/mix-fetch-node/package.json b/sdk/typescript/packages/mix-fetch-node/package.json new file mode 100644 index 0000000000..013fb344fb --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/package.json @@ -0,0 +1,71 @@ +{ + "name": "@nymproject/mix-fetch-node", + "version": "1.2.0", + "description": "This package is a drop-in replacement for `fetch` in NodeJS to send HTTP requests over the Nym Mixnet.", + "license": "Apache-2.0", + "author": "Nym Technologies SA", + "files": [ + "dist/cjs/worker.js", + "dist/**/*" + ], + "main": "dist/cjs/index.js", + "scripts": { + "build": "scripts/build-prod.sh", + "build:dev": "scripts/build.sh", + "build:worker": "rollup -c rollup-worker.config.mjs", + "clean": "rimraf dist", + "docs:dev": "run-p docs:watch docs:serve ", + "docs:generate": "typedoc", + "docs:generate:prod": "typedoc --basePath ./docs/tsdoc/nymproject/sdk/", + "docs:prod:build": "scripts/build-prod-docs-collect.sh", + "docs:serve": "reload -b -d ./docs -p 3000", + "docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\"", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "tsc -w", + "start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'", + "test": "node --experimental-fetch --experimental-vm-modules node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache", + "tsc": "tsc --noEmit true" + }, + "dependencies": { + "@nymproject/mix-fetch-wasm-node": ">=1.2.0-rc.10 || ^1", + "comlink": "^4.3.1", + "fake-indexeddb": "^5.0.0", + "node-fetch": "^3.3.2", + "ws": "^8.14.2" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^24.0.1", + "@rollup/plugin-node-resolve": "^15.0.1", + "@rollup/plugin-replace": "^5.0.2", + "@rollup/plugin-typescript": "^10.0.1", + "@rollup/plugin-wasm": "^6.1.1", + "@types/jest": "^27.0.1", + "@types/node": "^16.7.13", + "@typescript-eslint/eslint-plugin": "^5.13.0", + "@typescript-eslint/parser": "^5.13.0", + "eslint": "^8.10.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-airbnb-typescript": "^16.1.0", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-root-import": "^1.0.4", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^26.1.1", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-prettier": "^4.0.0", + "jest": "^29.5.0", + "nodemon": "^2.0.21", + "reload": "^3.2.1", + "rimraf": "^3.0.2", + "rollup": "^3.9.1", + "rollup-plugin-base64": "^1.0.1", + "rollup-plugin-modify": "^3.0.0", + "rollup-plugin-web-worker-loader": "^1.6.1", + "ts-jest": "^29.1.0", + "ts-loader": "^9.4.2", + "typedoc": "^0.24.8", + "typescript": "^4.8.4" + }, + "private": false, + "types": "./dist/cjs/index.d.ts" +} diff --git a/sdk/typescript/packages/mix-fetch-node/rollup-cjs.config.mjs b/sdk/typescript/packages/mix-fetch-node/rollup-cjs.config.mjs new file mode 100644 index 0000000000..7a4af49fc2 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/rollup-cjs.config.mjs @@ -0,0 +1,31 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import replace from '@rollup/plugin-replace'; +import resolve from '@rollup/plugin-node-resolve'; +import typescript from '@rollup/plugin-typescript'; +import webWorkerLoader from 'rollup-plugin-web-worker-loader'; +import { wasm } from '@rollup/plugin-wasm'; + +export default { + input: 'src/index.ts', + output: { + dir: 'dist/cjs', + format: 'cjs', + }, + plugins: [ + webWorkerLoader({ targetPlatform: 'node', inline: false }), + replace({ + values: { + "createURLWorkerFactory('web-worker-0.js')": + "createURLWorkerFactory(require('path').resolve(__dirname, 'web-worker-0.js'))", + }, + delimiters: ['', ''], + preventAssignment: true, + }), + resolve({ browser: false, extensions: ['.js', '.ts'] }), + wasm({ targetEnv: 'node', maxFileSize: 0 }), + typescript({ + compilerOptions: { outDir: 'dist/cjs', target: 'es5' }, + exclude: ['src/worker.ts'], + }), + ], +}; diff --git a/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs b/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs new file mode 100644 index 0000000000..8df9ba5cb3 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs @@ -0,0 +1,40 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import commonjs from '@rollup/plugin-commonjs'; +import modify from 'rollup-plugin-modify'; +import resolve from '@rollup/plugin-node-resolve'; +import typescript from '@rollup/plugin-typescript'; +import { wasm } from '@rollup/plugin-wasm'; + +export default { + input: 'src/worker/index.ts', + output: { + dir: 'dist/cjs', + format: 'cjs', + }, + external: ['util', 'fake-indexeddb'], + plugins: [ + resolve({ + browser: false, + preferBuiltins: true, + extensions: ['.js', '.ts'], + }), + commonjs(), + // TODO: One of the wasm functions calls `new WebSocket` at one point, which we aren't able to polyfill correctly yet. + modify({ + find: 'const ret = new WebSocket(getStringFromWasm0(arg0, arg1));', + replace: 'const ws = require("ws"); const ret = new ws.WebSocket(getStringFromWasm0(arg0, arg1));', + }), + // TODO: `getObject(...).require` seems to generate a warning on Webpack but with Rollup we get a panic since it can't require. + // By hard coding the require here, we can workaround that. + // Reference: https://github.com/rust-random/getrandom/issues/224 + modify({ find: 'getObject(arg0).require(getStringFromWasm0(arg1, arg2));', replace: 'require("crypto");' }), + wasm({ targetEnv: 'node', maxFileSize: 0, fileName: '[name].wasm' }), + typescript({ + compilerOptions: { + outDir: 'dist/cjs', + declaration: false, + target: 'es5', + }, + }), + ], +}; diff --git a/sdk/typescript/packages/mix-fetch-node/scripts/build-prod-docs-collect.sh b/sdk/typescript/packages/mix-fetch-node/scripts/build-prod-docs-collect.sh new file mode 100755 index 0000000000..f672185300 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/scripts/build-prod-docs-collect.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch || true + +# run the build +yarn docs:generate:prod + +# move the output outside of the yarn/npm workspaces +mkdir -p ../../../../dist/ts/docs/tsdoc/nymproject +mv docs ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch + +echo "Output can be found in:" +realpath ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch diff --git a/sdk/typescript/packages/mix-fetch-node/scripts/build-prod.sh b/sdk/typescript/packages/mix-fetch-node/scripts/build-prod.sh new file mode 100755 index 0000000000..b56d1e0472 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/scripts/build-prod.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist || true +rm -rf ../../../../dist/ts/sdk/mix-fetch || true + +# run the build +scripts/build.sh +node scripts/buildPackageJson.mjs + +# move the output outside of the yarn/npm workspaces +mkdir -p ../../../../dist/ts/sdk +mv dist ../../../../dist/ts/sdk +mv ../../../../dist/ts/sdk/dist ../../../../dist/ts/sdk/mix-fetch + +echo "Output can be found in:" +realpath ../../../../dist/ts/sdk/mix-fetch diff --git a/sdk/typescript/packages/mix-fetch-node/scripts/build.sh b/sdk/typescript/packages/mix-fetch-node/scripts/build.sh new file mode 100755 index 0000000000..45196c1a2a --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/scripts/build.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist || true + +#------------------------------------------------------- +# WEB WORKER (mix-fetch WASM) +#------------------------------------------------------- +# The web worker needs to be bundled because the WASM bundle needs to be loaded synchronously and all dependencies +# must be included in the worker script (because it is not loaded as an ES Module) + +# build the worker +rollup -c rollup-worker.config.mjs + +# move it next to the Typescript `src/index.ts` so it can be inlined by rollup +rm -f src/worker/*.js +rm -f src/worker/*.wasm +mv dist/cjs/index.js src/worker/worker.js + +# move WASM files out of build area +mkdir -p dist/worker +mv dist/cjs/*.wasm dist/worker + +#------------------------------------------------------- +# COMMON JS +#------------------------------------------------------- +# Some old build systems cannot fully handle ESM or ES2021, so build +# a CommonJS bundle targeting ES5 + +# build the SDK as a CommonJS bundle +rollup -c rollup-cjs.config.mjs + +# move WASM files into place +cp dist/worker/*.wasm dist/cjs + +#------------------------------------------------------- +# CLEAN UP +#------------------------------------------------------- + +rm -rf dist/cjs/worker + +# copy README +cp README.md dist/cjs/README.md + + diff --git a/sdk/typescript/packages/mix-fetch-node/scripts/buildPackageJson.mjs b/sdk/typescript/packages/mix-fetch-node/scripts/buildPackageJson.mjs new file mode 100644 index 0000000000..592b17e1e0 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/scripts/buildPackageJson.mjs @@ -0,0 +1,22 @@ +import * as fs from 'fs'; + +// parse the package.json from the SDK, so we can keep fields like the name and version +const json = JSON.parse(fs.readFileSync('package.json').toString()); + +// defaults (NB: these are in the output file locations) +const browser = 'index.js'; +const main = 'index.js'; +const types = 'index.d.ts'; + +const getPackageJson = (type, suffix) => ({ + name: `${json.name}${suffix ? `-${suffix}` : ''}`, + version: json.version, + license: json.license, + author: json.author, + type, + browser, + main, + types, +}); + +fs.writeFileSync('dist/cjs/package.json', JSON.stringify(getPackageJson('commonjs', 'commonjs'), null, 2)); diff --git a/sdk/typescript/packages/mix-fetch-node/scripts/publish.sh b/sdk/typescript/packages/mix-fetch-node/scripts/publish.sh new file mode 100755 index 0000000000..a5cb97f78f --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/scripts/publish.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist || true +rm -rf ../../../../dist || true + +yarn +yarn build +cd ../../../../dist/sdk + +cd cjs +echo "Publishing CommonJS package to NPM.." +npm publish --access=public +cd .. diff --git a/sdk/typescript/packages/mix-fetch-node/src/create-mix-fetch.ts b/sdk/typescript/packages/mix-fetch-node/src/create-mix-fetch.ts new file mode 100644 index 0000000000..08e8811cf7 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/src/create-mix-fetch.ts @@ -0,0 +1,77 @@ +/* eslint-disable-next-line no-console */ + +import * as Comlink from 'comlink'; +import InlineWasmWebWorker from 'web-worker:./worker/worker'; +import { Worker } from 'node:worker_threads'; + +import nodeEndpoint from './node-adapter'; +import type { IMixFetchWebWorker } from './types'; +import { EventKinds, IMixFetch } from './types'; + +const createWorker = async () => + new Promise((resolve, reject) => { + // rollup will inline the built worker script, so that when the SDK is used in + // other projects, they will not need to mess around trying to bundle it + // however, it will make this SDK bundle bigger because of Base64 inline data + const worker = new InlineWasmWebWorker(); + + worker.addListener('error', reject); + worker.addListener('message', (msg: any) => { + worker.removeListener('error', reject); + if (msg.kind === EventKinds.Loaded) { + resolve(worker); + } else { + reject(msg); + } + }); + }); + +const convertHeaders = (headers: any): Headers => { + const out = new Headers(); + Object.keys(headers).forEach((key) => { + out.append(key, headers[key]); + }); + return out; +}; + +/** + * Use this method to initialise `mixFetch`. + * + * @returns An instance of `mixFetch` that you can use to make your requests using the same interface as `fetch`. + */ +export const createMixFetch = async (): Promise => { + // start the worker + const worker = await createWorker(); + + // bind with Comlink + const wrappedWorker = Comlink.wrap(nodeEndpoint(worker)); + + // handle the responses + const mixFetchWebWorker: IMixFetch = { + setupMixFetch: wrappedWorker.setupMixFetch, + mixFetch: async (url: string, args: any) => { + const workerResponse = await wrappedWorker.mixFetch(url, args); + if (!workerResponse) { + throw new Error('No response received'); + } + const { headers: headersRaw, status, statusText } = workerResponse; + + // reconstruct the Headers object instance from a plain object + const headers = convertHeaders(headersRaw); + + // handle blobs + if (workerResponse.body.blobUrl) { + const blob = await (await fetch(workerResponse.body.blobUrl)).blob(); + const body = await blob.arrayBuffer(); + return new Response(body, { headers, status, statusText }); + } + + // handle everything else + const body = Object.values(workerResponse.body)[0]; // we are expecting only one value to be set in `.body` + return new Response(body, { headers, status, statusText }); + }, + disconnectMixFetch: wrappedWorker.disconnectMixFetch, + }; + + return mixFetchWebWorker; +}; diff --git a/sdk/typescript/packages/mix-fetch-node/src/index.ts b/sdk/typescript/packages/mix-fetch-node/src/index.ts new file mode 100644 index 0000000000..e4bc233499 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/src/index.ts @@ -0,0 +1,57 @@ +/* eslint-disable no-underscore-dangle */ + +import type { SetupMixFetchOps, IMixFetchFn } from './types'; +import { createMixFetch as createMixFetchInternal } from './create-mix-fetch'; + +// this is the default timeout for getting a response +const REQUEST_TIMEOUT_MILLISECONDS = 60_000; + +export * from './types'; + +/** + * Create a global mixFetch instance and optionally configure settings. + * + * @param opts Optional settings + */ +export const createMixFetch = async (opts?: SetupMixFetchOps) => { + if (!(globalThis as any).__mixFetchGlobal) { + // load the worker and set up mixFetch with defaults + (globalThis as any).__mixFetchGlobal = await createMixFetchInternal(); + await (globalThis as any).__mixFetchGlobal.setupMixFetch(opts); + } + + return (globalThis as any).__mixFetchGlobal; +}; + +/** + * mixFetch is a drop-in replacement for the standard `fetch` interface. + * + * @param url The URL to fetch from. + * @param args Fetch options. + * @param opts Optionally configure mixFetch when it gets created. This only happens once, the first time it gets used. + */ +export const mixFetch: IMixFetchFn = async (url, args, opts?: SetupMixFetchOps) => { + // ensure mixFetch instance exists + const instance = await createMixFetch({ + mixFetchOverride: { + requestTimeoutMs: REQUEST_TIMEOUT_MILLISECONDS, + }, + ...opts, + }); + + // execute user request + return instance.mixFetch(url, args); +}; + +/** + * Stops the usage of mixFetch and disconnect the client from the mixnet. + */ +export const disconnectMixFetch = async (): Promise => { + // JS: I'm ignoring this lint (no-else-return) because I want to explicitly state + // that `__mixFetchGlobal` is definitely not null in the else branch. + if (!(globalThis as any).__mixFetchGlobal) { + throw new Error("mixFetch hasn't been setup"); + } else { + return (globalThis as any).__mixFetchGlobal.disconnectMixFetch(); + } +}; diff --git a/sdk/typescript/packages/mix-fetch-node/src/node-adapter.ts b/sdk/typescript/packages/mix-fetch-node/src/node-adapter.ts new file mode 100644 index 0000000000..aacc0dc6a8 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/src/node-adapter.ts @@ -0,0 +1,43 @@ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +// Borrowed from https://github.com/GoogleChromeLabs/comlink/blob/main/src/node-adapter.ts + +import { Endpoint } from 'comlink'; + +export interface NodeEndpoint { + postMessage(message: any, transfer?: any[]): void; + on(type: string, listener: EventListenerOrEventListenerObject, options?: {}): void; + off(type: string, listener: EventListenerOrEventListenerObject, options?: {}): void; + start?: () => void; +} + +export default function nodeEndpoint(nep: NodeEndpoint): Endpoint { + const listeners = new WeakMap(); + return { + postMessage: nep.postMessage.bind(nep), + addEventListener: (_, eh) => { + const l = (data: any) => { + if ('handleEvent' in eh) { + eh.handleEvent({ data } as MessageEvent); + } else { + eh({ data } as MessageEvent); + } + }; + nep.on('message', l); + listeners.set(eh, l); + }, + removeEventListener: (_, eh) => { + const l = listeners.get(eh); + if (!l) { + return; + } + nep.off('message', l); + listeners.delete(eh); + }, + start: nep.start && nep.start.bind(nep), + }; +} diff --git a/sdk/typescript/packages/mix-fetch-node/src/types.ts b/sdk/typescript/packages/mix-fetch-node/src/types.ts new file mode 100644 index 0000000000..be22b2b80c --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/src/types.ts @@ -0,0 +1,98 @@ +import type { MixFetchOpts } from '@nymproject/mix-fetch-wasm-node'; + +type IMixFetchWorkerFn = (url: string, args: any) => Promise; + +// export type IMixFetchFn = typeof fetch; +export type IMixFetchFn = (url: string, args: any, opts?: SetupMixFetchOps) => Promise; + +export type SetupMixFetchOps = MixFetchOpts & { + responseBodyConfigMap?: ResponseBodyConfigMap; +}; + +export interface IMixFetchWebWorker { + mixFetch: IMixFetchWorkerFn; + setupMixFetch: (opts?: SetupMixFetchOps) => Promise; + disconnectMixFetch: () => Promise; +} + +export interface IMixFetch { + mixFetch: IMixFetchFn; + setupMixFetch: (opts?: SetupMixFetchOps) => Promise; + disconnectMixFetch: () => Promise; +} + +export enum EventKinds { + Loaded = 'Loaded', +} + +export interface LoadedEvent { + kind: EventKinds.Loaded; + args: { + loaded: true; + }; +} + +export interface ResponseBody { + uint8array?: Uint8Array; + json?: any; + text?: string; + formData?: any; + blobUrl?: string; +} + +export type ResponseBodyMethod = 'uint8array' | 'json' | 'text' | 'formData' | 'blob'; + +export interface ResponseBodyConfigMap { + /** + * Set the response `Content-Type`s to decode as uint8array. + */ + uint8array?: Array; + + /** + * Set the response `Content-Type`s to decode with the `json()` response body method. + */ + json?: Array; + + /** + * Set the response `Content-Type`s to decode with the `text()` response body method. + */ + text?: Array; + + /** + * Set the response `Content-Type`s to decode with the `formData()` response body method. + */ + formData?: Array; + + /** + * Set the response `Content-Type`s to decode with the `blob()` response body method. + */ + blob?: Array; + /** + * Set this to the default fallback method. Set to `undefined` if you want to ignore unknown types. + */ + + fallback?: ResponseBodyMethod; +} + +/** + * Default values for the handling of response bodies. + */ +export const ResponseBodyConfigMapDefaults: ResponseBodyConfigMap = { + uint8array: ['application/octet-stream'], + json: ['application/json', 'text/json', /application\/json.*/, /text\/json\+.*/], + text: ['text/plain', /text\/plain.*/, 'text/html', /text\/html.*/], + formData: ['application/x-www-form-urlencoded', 'multipart/form-data'], + blob: [/image\/.*/, /video\/.*/], + fallback: 'blob', +}; + +export interface MixFetchWebWorkerResponse { + body: ResponseBody; + url: string; + headers: any; + status: number; + statusText: string; + type: string; + ok: boolean; + redirected: boolean; +} diff --git a/sdk/typescript/packages/mix-fetch-node/src/worker/handle-response-mime-types.test.ts b/sdk/typescript/packages/mix-fetch-node/src/worker/handle-response-mime-types.test.ts new file mode 100644 index 0000000000..747c073b3b --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/src/worker/handle-response-mime-types.test.ts @@ -0,0 +1,73 @@ +import { handleResponseMimeTypes } from './handle-response-mime-types'; + +describe('handleResponseMimeTypes', () => { + test('gracefully handles empty values', async () => { + const resp = await handleResponseMimeTypes(new Response()); + expect(Object.values(resp)).toHaveLength(0); + }); + + test('handles text', async () => { + const TEXT = 'This is text'; + const resp = await handleResponseMimeTypes( + new Response(TEXT, { headers: new Headers([['Content-Type', 'text/plain']]) }), + ); + expect(resp.text).toBe(TEXT); + }); + test('handles text (charset=utf-8)', async () => { + const TEXT = 'This is text'; + const resp = await handleResponseMimeTypes( + new Response(TEXT, { headers: new Headers([['Content-Type', 'text/plain; charset=utf-8']]) }), + ); + expect(resp.text).toBe(TEXT); + }); + test('handles html', async () => { + const TEXT = 'This is html'; + const resp = await handleResponseMimeTypes( + new Response(TEXT, { headers: new Headers([['Content-Type', 'text/html']]) }), + ); + expect(resp.text).toBe(TEXT); + }); + test('handles html (charset=utf-8)', async () => { + const TEXT = 'This is html'; + const resp = await handleResponseMimeTypes( + new Response(TEXT, { headers: new Headers([['Content-Type', 'text/html; charset=utf-8']]) }), + ); + expect(resp.text).toBe(TEXT); + }); + test('handles images', async () => { + const DATA = Buffer.from(new Uint8Array([0, 1, 2, 3])); + const resp = await handleResponseMimeTypes( + new Response(DATA, { headers: new Headers([['Content-Type', 'image/jpeg']]) }), + ); + expect(resp.blobUrl).toBeDefined(); + }); + test('handles videos', async () => { + const DATA = Buffer.from(new Uint8Array([0, 1, 2, 3])); + const resp = await handleResponseMimeTypes( + new Response(DATA, { headers: new Headers([['Content-Type', 'video/mpeg4']]) }), + ); + expect(resp.blobUrl).toBeDefined(); + }); + test('handles form data when URL encoded', async () => { + const formData = 'foo=bar&baz=42'; + const resp = await handleResponseMimeTypes( + new Response(formData, { headers: new Headers([['Content-Type', 'application/x-www-form-urlencoded']]) }), + ); + expect(resp.formData.foo).toBe('bar'); + expect(resp.formData.baz).toBe('42'); + }); + test('handles JSON data', async () => { + const json = '{ "foo": "bar", "baz": 42 }'; + const resp = await handleResponseMimeTypes( + new Response(json, { headers: new Headers([['Content-Type', 'application/json']]) }), + ); + expect(resp.text).toBe(json); + }); + test('handles JSON data (charset=utf-8)', async () => { + const json = '{ "foo": "bar", "baz": 42 }'; + const resp = await handleResponseMimeTypes( + new Response(json, { headers: new Headers([['Content-Type', 'application/json; charset=utf-8']]) }), + ); + expect(resp.text).toBe(json); + }); +}); diff --git a/sdk/typescript/packages/mix-fetch-node/src/worker/handle-response-mime-types.ts b/sdk/typescript/packages/mix-fetch-node/src/worker/handle-response-mime-types.ts new file mode 100644 index 0000000000..abcaa845f7 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/src/worker/handle-response-mime-types.ts @@ -0,0 +1,111 @@ +import type { ResponseBody, ResponseBodyConfigMap, ResponseBodyMethod } from '../types'; +import { ResponseBodyConfigMapDefaults } from '../types'; + +const getContentType = (response?: Response) => { + if (!response) { + return undefined; + } + + // this is what should be returned in the headers + if (response.headers.has('Content-Type')) { + return response.headers.get('Content-Type') as string; + } + + // handle weird servers that use lowercase headers + if (response.headers.has('content-type')) { + return response.headers.get('content-type') as string; + } + + // the Content-Type/content-type header is not part of the response + return undefined; +}; + +const doHandleResponseMethod = async (response: Response, method?: ResponseBodyMethod): Promise => { + switch (method) { + case 'uint8array': + return { + uint8array: new Uint8Array(await response.arrayBuffer()), + }; + case 'json': + case 'text': + return { text: await response.text() }; + case 'blob': { + const blob = await response.blob(); + const blobUrl = URL.createObjectURL(blob); + return { blobUrl }; + } + case 'formData': { + const formData: any = {}; + const data = await response.formData(); + // eslint-disable-next-line no-restricted-syntax + for (const pair of data.entries()) { + const [key, value] = pair; + formData[key] = value; + } + return { formData }; + } + default: + return {}; + } +}; + +const testIfIncluded = (value?: string, tests?: Array): boolean => { + if (!tests) { + return false; + } + if (!value) { + return false; + } + + for (let i = 0; i < tests.length; i += 1) { + const test = tests[i]; + if (typeof test === 'string' && value === test) { + return true; + } + if ((test as RegExp).test && (test as RegExp).test(value)) { + return true; + } + } + + // default return is false, because nothing above matched + return false; +}; + +export const handleResponseMimeTypes = async ( + response: Response, + config?: ResponseBodyConfigMap, +): Promise => { + // combine the user supplied config with the default + const finalConfig: ResponseBodyConfigMap = { ...ResponseBodyConfigMapDefaults, ...config }; + + const contentType = getContentType(response); + + // check if the headers say what the content type are, otherwise return the bytes of the response as a blob + if (!contentType) { + // no content type, or body, so the response is only the status, e.g. GET + if (!response.body) { + return {}; + } + + // handle fallback method + return doHandleResponseMethod(response, config?.fallback || 'blob'); + } + + if (testIfIncluded(contentType, finalConfig.uint8array)) { + return doHandleResponseMethod(response, 'uint8array'); + } + if (testIfIncluded(contentType, finalConfig.json)) { + return doHandleResponseMethod(response, 'json'); + } + if (testIfIncluded(contentType, finalConfig.text)) { + return doHandleResponseMethod(response, 'text'); + } + if (testIfIncluded(contentType, finalConfig.formData)) { + return doHandleResponseMethod(response, 'formData'); + } + if (testIfIncluded(contentType, finalConfig.blob)) { + return doHandleResponseMethod(response, 'blob'); + } + + return {}; +}; diff --git a/sdk/typescript/packages/mix-fetch-node/src/worker/index.ts b/sdk/typescript/packages/mix-fetch-node/src/worker/index.ts new file mode 100644 index 0000000000..81582206e3 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/src/worker/index.ts @@ -0,0 +1,8 @@ +import './polyfill'; +import { loadWasm } from './wasm-loading'; +import { run } from './main'; + +(async function main() { + await loadWasm(); + await run(); +})().catch((e: any) => console.error('Unhandled exception in mixFetch worker', e)); diff --git a/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts b/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts new file mode 100644 index 0000000000..e30e6c7cf8 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts @@ -0,0 +1,74 @@ +/* eslint-disable no-console */ + +import * as Comlink from 'comlink'; +import { parentPort } from 'node:worker_threads'; +import { setupMixFetch, disconnectMixFetch } from '@nymproject/mix-fetch-wasm-node'; + +import type { IMixFetchWebWorker, LoadedEvent } from '../types'; +import nodeEndpoint from '../node-adapter'; +import { EventKinds, ResponseBodyConfigMap, ResponseBodyConfigMapDefaults } from '../types'; +import { handleResponseMimeTypes } from './handle-response-mime-types'; + +/** + * Helper method to send typed messages. + * @param event The strongly typed message to send back to the calling thread. + */ +const postMessageWithType = (event: E) => parentPort?.postMessage(event); + +export async function run() { + const { mixFetch } = globalThis as any; + let responseBodyConfigMap: ResponseBodyConfigMap = ResponseBodyConfigMapDefaults; + + const mixFetchWebWorker: IMixFetchWebWorker = { + mixFetch: async (url, args) => { + console.log('[Worker] --- mixFetch ---', { url, args }); + + const response: Response = await mixFetch(url, args); + console.log('[Worker]', { response, json: JSON.stringify(response, null, 2) }); + + const bodyResponse = await handleResponseMimeTypes(response, responseBodyConfigMap); + console.log('[Worker]', { bodyResponse }); + + const headers: any = {}; + response.headers.forEach((value, key) => { + headers[key] = value; + }); + + const output = { + body: bodyResponse, + url: response.url, + headers, + status: response.status, + statusText: response.statusText, + type: response.type, + ok: response.ok, + redirected: response.redirected, + }; + + console.log('[Worker]', { output }); + + return output; + }, + setupMixFetch: async (opts) => { + console.log('[Worker] --- setupMixFetch ---', { opts }); + if (opts?.responseBodyConfigMap) { + responseBodyConfigMap = opts.responseBodyConfigMap; + } + await setupMixFetch(opts || {}); + }, + disconnectMixFetch: async () => { + console.log('[Worker] --- disconnectMixFetch ---'); + + await disconnectMixFetch(); + }, + }; + + // start comlink listening for messages and handle them above + if (parentPort) { + Comlink.expose(mixFetchWebWorker, nodeEndpoint(parentPort)); + } + + // notify any listeners that the web worker has loaded - HOWEVER, mixFetch hasn't been setup and the client started + // call `setupMixFetch` from the main thread to start the Nym client + postMessageWithType({ kind: EventKinds.Loaded, args: { loaded: true } }); +} diff --git a/sdk/typescript/packages/mix-fetch-node/src/worker/polyfill.ts b/sdk/typescript/packages/mix-fetch-node/src/worker/polyfill.ts new file mode 100644 index 0000000000..76c9dd6e2f --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/src/worker/polyfill.ts @@ -0,0 +1,38 @@ +import * as crypto from 'node:crypto'; +import * as fs from 'node:fs'; +import WebSocket from 'ws'; +import fetch, { Headers, Request, Response } from 'node-fetch'; +import { TextDecoder, TextEncoder } from 'node:util'; +import { Worker } from 'node:worker_threads'; +import { indexedDB } from 'fake-indexeddb'; + +(globalThis as any).performance = { + now() { + const [sec, nsec] = process.hrtime(); + return sec * 1000 + nsec / 1000000; + }, +}; + +(globalThis as any).TextDecoder = TextDecoder; +(globalThis as any).fetch = fetch; +(globalThis as any).Headers = Headers; +(globalThis as any).Request = Request; +(globalThis as any).Response = Response; +(globalThis as any).Headers = Headers; +(globalThis as any).fs = fs; +(globalThis as any).crypto = crypto; +(globalThis as any).WebSocket = WebSocket; +(globalThis as any).Worker = Worker; + +globalThis.process = process; +globalThis.TextEncoder = TextEncoder; +globalThis.Reflect = Reflect; +globalThis.Proxy = Proxy; +globalThis.Error = Error; +globalThis.Promise = Promise; +globalThis.Object = Object; +globalThis.indexedDB = indexedDB; + +// has to be loaded after all the polyfill action +// eslint-disable-next-line import/extensions, import/no-extraneous-dependencies +import('@nymproject/mix-fetch-wasm-node/wasm_exec'); diff --git a/sdk/typescript/packages/mix-fetch-node/src/worker/wasm-loading.ts b/sdk/typescript/packages/mix-fetch-node/src/worker/wasm-loading.ts new file mode 100644 index 0000000000..0eb698e0ec --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/src/worker/wasm-loading.ts @@ -0,0 +1,69 @@ +/* eslint-disable no-console */ +/// + +// Copyright 2020-2023 Nym Technologies SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import '@nymproject/mix-fetch-wasm-node/mix_fetch_wasm_bg.wasm'; + +// @ts-ignore +import getGoConnectionWasmBytes from '@nymproject/mix-fetch-wasm-node/go_conn.wasm'; + +import { + send_client_data, + start_new_mixnet_connection, + mix_fetch_initialised, + finish_mixnet_connection, + set_panic_hook, +} from '@nymproject/mix-fetch-wasm-node'; + +export async function loadGoWasm() { + // rollup will provide a function to get the Go connection WASM bytes here + const bytes = await getGoConnectionWasmBytes(); + + const go = new Go(); // Defined in wasm_exec.js + + // the WebAssembly runtime will parse the bytes and then start the Go runtime + const wasmObj = await WebAssembly.instantiate(bytes, go.importObject); + // eslint-disable-next-line no-console + console.log('Loaded GO WASM'); + + go.run(wasmObj); +} + +function setupRsGoBridge() { + const rsGoBridge = { + send_client_data, + start_new_mixnet_connection, + mix_fetch_initialised, + finish_mixnet_connection, + }; + + // and to discourage users from trying to call those methods directly) + // @ts-expect-error globalThis has index signature of any + // eslint-disable-next-line no-underscore-dangle + globalThis.__rs_go_bridge__ = rsGoBridge; +} + +export async function loadWasm() { + // load go WASM package + await loadGoWasm(); + + console.log('Loaded GO WASM'); + + // sets up better stack traces in case of in-rust panics + set_panic_hook(); + + setupRsGoBridge(); +} diff --git a/sdk/typescript/packages/mix-fetch-node/tsconfig.jest.json b/sdk/typescript/packages/mix-fetch-node/tsconfig.jest.json new file mode 100644 index 0000000000..90ad46a57b --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/tsconfig.jest.json @@ -0,0 +1,35 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "lib": ["es2021", "dom", "dom.iterable", "esnext", "webworker"], + "module": "esnext", + "target": "esnext", + "strict": true, + "moduleResolution": "node", + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "declaration": true, + "baseUrl": ".", + "esModuleInterop": true, + "allowJs": true, + "downlevelIteration": true + }, + "include": ["src/**/*.ts"], + "exclude": [ + "jest.*", + "webpack.config.js", + "webpack.prod.js", + "webpack.common.js", + "node_modules", + "**/node_modules", + "dist", + "**/dist", + "scripts", + "jest", + "__tests__", + "**/__tests__", + "__jest__", + "**/__jest__", + "config/*" + ] +} diff --git a/sdk/typescript/packages/mix-fetch-node/tsconfig.json b/sdk/typescript/packages/mix-fetch-node/tsconfig.json new file mode 100644 index 0000000000..8598dd51d0 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/tsconfig.json @@ -0,0 +1,36 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "lib": ["es2021", "dom", "dom.iterable", "esnext", "webworker"], + "outDir": "./dist/", + "module": "esnext", + "target": "esnext", + "allowJs": false, + "strict": true, + "allowSyntheticDefaultImports": true, + "moduleResolution": "node", + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "declaration": true, + "baseUrl": ".", + "downlevelIteration": true + }, + "include": ["src/**/*.ts", "src/*.ts", "typings"], + "exclude": [ + "jest.config.js", + "webpack.config.js", + "webpack.prod.js", + "webpack.common.js", + "node_modules", + "**/node_modules", + "dist", + "**/dist", + "scripts", + "jest", + "__tests__", + "**/__tests__", + "__jest__", + "**/__jest__", + "config/*" + ] +} diff --git a/sdk/typescript/packages/mix-fetch-node/typedoc.json b/sdk/typescript/packages/mix-fetch-node/typedoc.json new file mode 100644 index 0000000000..46a91d8237 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/typedoc.json @@ -0,0 +1,32 @@ +{ + "sort": ["kind"], + "entryPoints": ["./src/index.ts"], + "out": "./docs", + "exclude": ["./src/worker/**"], + "kindSortOrder": [ + "Function", + "Interface", + "TypeAlias", + "Reference", + "Project", + "Module", + "Namespace", + "Enum", + "EnumMember", + "Class", + "Constructor", + "Property", + "Variable", + "Accessor", + "Method", + "ObjectLiteral", + "Parameter", + "TypeParameter", + "TypeLiteral", + "CallSignature", + "ConstructorSignature", + "IndexSignature", + "GetSignature", + "SetSignature" + ] +} diff --git a/sdk/typescript/packages/mix-fetch-node/typings/rollup-worker.d.ts b/sdk/typescript/packages/mix-fetch-node/typings/rollup-worker.d.ts new file mode 100644 index 0000000000..d012fe9590 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/typings/rollup-worker.d.ts @@ -0,0 +1,6 @@ +declare module 'web-worker:*' { + import { Worker } from 'node:worker_threads'; + + const WorkerFactory: new () => Worker; + export default WorkerFactory; +} diff --git a/sdk/typescript/packages/mix-fetch-node/typings/wasm_exec.d.ts b/sdk/typescript/packages/mix-fetch-node/typings/wasm_exec.d.ts new file mode 100644 index 0000000000..82cee7251a --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/typings/wasm_exec.d.ts @@ -0,0 +1,11 @@ +declare module '@nymproject/mix-fetch-wasm-node/wasm_exec' { + export declare global { + class Go { + constructor(); + + importObject: any; + + run(goWasm: any); + } + } +} diff --git a/sdk/typescript/packages/mix-fetch-node/yarn.lock b/sdk/typescript/packages/mix-fetch-node/yarn.lock new file mode 100644 index 0000000000..e0bdcadf88 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/yarn.lock @@ -0,0 +1,4428 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== + dependencies: + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" + +"@babel/compat-data@^7.22.9": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.2.tgz#6a12ced93455827037bfb5ed8492820d60fc32cc" + integrity sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.2.tgz#ed10df0d580fff67c5f3ee70fd22e2e4c90a9f94" + integrity sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-module-transforms" "^7.23.0" + "@babel/helpers" "^7.23.2" + "@babel/parser" "^7.23.0" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.2" + "@babel/types" "^7.23.0" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.23.0", "@babel/generator@^7.7.2": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" + integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== + dependencies: + "@babel/types" "^7.23.0" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/helper-compilation-targets@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" + integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-validator-option" "^7.22.15" + browserslist "^4.21.9" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-module-transforms@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz#3ec246457f6c842c0aee62a01f60739906f7047e" + integrity sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/helper-validator-option@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040" + integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA== + +"@babel/helpers@^7.23.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.2.tgz#2832549a6e37d484286e15ba36a5330483cac767" + integrity sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ== + dependencies: + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.2" + "@babel/types" "^7.23.0" + +"@babel/highlight@^7.22.13": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" + integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" + integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.7.2": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918" + integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz#aac8d383b062c5072c647a31ef990c1d0af90272" + integrity sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/runtime@^7.20.7": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.2.tgz#062b0ac103261d68a966c4c7baf2ae3e62ec3885" + integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.22.15", "@babel/template@^7.3.3": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + +"@babel/traverse@^7.23.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" + integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.0" + "@babel/types" "^7.23.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.3.3": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" + integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4" + integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA== + +"@eslint/eslintrc@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" + integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.51.0": + version "8.51.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.51.0.tgz#6d419c240cfb2b66da37df230f7e7eef801c32fa" + integrity sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg== + +"@humanwhocodes/config-array@^0.11.11": + version "0.11.11" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.11.tgz#88a04c570dbbc7dd943e4712429c3df09bc32844" + integrity sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.19" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811" + integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nymproject/mix-fetch-wasm-node@>=1.2.0-rc.10 || ^1": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@nymproject/mix-fetch-wasm-node/-/mix-fetch-wasm-node-1.2.0.tgz#76439db4eb5fd4b95dcf6b6883cb5a059aeb5ad2" + integrity sha512-vdEO4WfY1ql+DXIMR4nHvIlTB9tzhALiVjzbbf7UBgrQLxPSFTD2oGwGOVfgpNvXv0F92rDj3AHRommKKGa5pw== + +"@rollup/plugin-commonjs@^24.0.1": + version "24.1.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-24.1.0.tgz#79e54bd83bb64396761431eee6c44152ef322100" + integrity sha512-eSL45hjhCWI0jCCXcNtLVqM5N1JlBGvlFfY0m6oOYnLCJ6N0qEXoZql4sY2MOUArzhH4SA/qBpTxvvZp2Sc+DQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + commondir "^1.0.1" + estree-walker "^2.0.2" + glob "^8.0.3" + is-reference "1.2.1" + magic-string "^0.27.0" + +"@rollup/plugin-node-resolve@^15.0.1": + version "15.2.3" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz#e5e0b059bd85ca57489492f295ce88c2d4b0daf9" + integrity sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + "@types/resolve" "1.20.2" + deepmerge "^4.2.2" + is-builtin-module "^3.2.1" + is-module "^1.0.0" + resolve "^1.22.1" + +"@rollup/plugin-replace@^5.0.2": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-5.0.4.tgz#fef548dc751d06747e8dca5b0e8e1fbf647ac7e1" + integrity sha512-E2hmRnlh09K8HGT0rOnnri9OTh+BILGr7NVJGB30S4E3cLRn3J0xjdiyOZ74adPs4NiAMgrjUMGAZNJDBgsdmQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + magic-string "^0.30.3" + +"@rollup/plugin-typescript@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-10.0.1.tgz#270b515b116ea28320e6bb62451c4767d49072d6" + integrity sha512-wBykxRLlX7EzL8BmUqMqk5zpx2onnmRMSw/l9M1sVfkJvdwfxogZQVNUM9gVMJbjRLDR5H6U0OMOrlDGmIV45A== + dependencies: + "@rollup/pluginutils" "^5.0.1" + resolve "^1.22.1" + +"@rollup/plugin-wasm@^6.1.1": + version "6.2.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-wasm/-/plugin-wasm-6.2.2.tgz#ea75fd8cc5ddba1e30bdc22e07cdbaf8d6d160bf" + integrity sha512-gpC4R1G9Ni92ZIRTexqbhX7U+9estZrbhP+9SRb0DW9xpB9g7j34r+J2hqrcW/lRI7dJaU84MxZM0Rt82tqYPQ== + dependencies: + "@rollup/pluginutils" "^5.0.2" + +"@rollup/pluginutils@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== + dependencies: + "@types/estree" "0.0.39" + estree-walker "^1.0.1" + picomatch "^2.2.2" + +"@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@^5.0.2": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.5.tgz#bbb4c175e19ebfeeb8c132c2eea0ecb89941a66c" + integrity sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinonjs/commons@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" + integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@types/babel__core@^7.1.14": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.2.tgz#215db4f4a35d710256579784a548907237728756" + integrity sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.5" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.5.tgz#281f4764bcbbbc51fdded0f25aa587b4ce14da95" + integrity sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.2" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.2.tgz#843e9f1f47c957553b0c374481dc4772921d6a6b" + integrity sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.2.tgz#4ddf99d95cfdd946ff35d2b65c978d9c9bf2645d" + integrity sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw== + dependencies: + "@babel/types" "^7.20.7" + +"@types/estree@*", "@types/estree@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.2.tgz#ff02bc3dc8317cd668dfec247b750ba1f1d62453" + integrity sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA== + +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + +"@types/graceful-fs@^4.1.3": + version "4.1.7" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.7.tgz#30443a2e64fd51113bc3e2ba0914d47109695e2a" + integrity sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#412e0725ef41cde73bfa03e0e833eaff41e0fd63" + integrity sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz#edc8e421991a3b4df875036d381fc0a5a982f549" + integrity sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^27.0.1": + version "27.5.2" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.5.2.tgz#ec49d29d926500ffb9fd22b84262e862049c026c" + integrity sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA== + dependencies: + jest-matcher-utils "^27.0.0" + pretty-format "^27.0.0" + +"@types/json-schema@^7.0.9": + version "7.0.13" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85" + integrity sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + +"@types/node@*": + version "20.8.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.6.tgz#0dbd4ebcc82ad0128df05d0e6f57e05359ee47fa" + integrity sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ== + dependencies: + undici-types "~5.25.1" + +"@types/node@^16.7.13": + version "16.18.58" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.58.tgz#bf66f63983104ed57c754f4e84ccaf16f8235adb" + integrity sha512-YGncyA25/MaVtQkjWW9r0EFBukZ+JulsLcVZBlGUfIb96OBMjkoRWwQo5IEWJ8Fj06Go3GHw+bjYDitv6BaGsA== + +"@types/resolve@1.20.2": + version "1.20.2" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" + integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== + +"@types/semver@^7.3.12": + version "7.5.3" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.3.tgz#9a726e116beb26c24f1ccd6850201e1246122e04" + integrity sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw== + +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + +"@types/yargs-parser@*": + version "21.0.1" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.1.tgz#07773d7160494d56aa882d7531aac7319ea67c3b" + integrity sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ== + +"@types/yargs@^17.0.8": + version "17.0.28" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.28.tgz#d106e4301fbacde3d1796ab27374dd16588ec851" + integrity sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@^5.13.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" + integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== + dependencies: + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/type-utils" "5.62.0" + "@typescript-eslint/utils" "5.62.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.13.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" + integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== + dependencies: + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + +"@typescript-eslint/type-utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" + integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== + dependencies: + "@typescript-eslint/typescript-estree" "5.62.0" + "@typescript-eslint/utils" "5.62.0" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== + +"@typescript-eslint/typescript-estree@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.62.0", "@typescript-eslint/utils@^5.10.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + eslint-scope "^5.1.1" + semver "^7.3.7" + +"@typescript-eslint/visitor-keys@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== + dependencies: + "@typescript-eslint/types" "5.62.0" + eslint-visitor-keys "^3.3.0" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.9.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-sequence-parser@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf" + integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3, anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +aria-query@^5.1.3: + version "5.3.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" + integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== + dependencies: + dequal "^2.0.3" + +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + +array-includes@^3.1.6: + version "3.1.7" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" + integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.findlastindex@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207" + integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + get-intrinsic "^1.2.1" + +array.prototype.flat@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +arraybuffer.prototype.slice@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" + integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + +ast-types-flow@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" + integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +axe-core@^4.6.2: + version "4.8.2" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.8.2.tgz#2f6f3cde40935825cf4465e3c1c9e77b240ff6ae" + integrity sha512-/dlp0fxyM3R8YW7MFzaHWXrf4zzbr0vaYb23VBFCl83R7nWNPg/yaQw2Dc8jzCMmDVLhSdzH8MjrsuIUuvX+6g== + +axobject-query@^3.1.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" + integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg== + dependencies: + dequal "^2.0.3" + +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.21.9: + version "4.22.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.1.tgz#ba91958d1a59b87dab6fed8dfbcb3da5e2e9c619" + integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ== + dependencies: + caniuse-lite "^1.0.30001541" + electron-to-chromium "^1.4.535" + node-releases "^2.0.13" + update-browserslist-db "^1.0.13" + +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +builtin-modules@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001541: + version "1.0.30001549" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001549.tgz#7d1a3dce7ea78c06ed72c32c2743ea364b3615aa" + integrity sha512-qRp48dPYSCYaP+KurZLhDYdVE+yEyht/3NlmcJgVQ2VMGt6JL36ndQ/7rgspdZsJuxDPFIo/OzBT2+GmIJ53BA== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +chokidar@^3.5.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cjs-module-lexer@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + +cli-color@~2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-2.0.3.tgz#73769ba969080629670f3f2ef69a4bf4e7cc1879" + integrity sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ== + dependencies: + d "^1.0.1" + es5-ext "^0.10.61" + es6-iterator "^2.0.3" + memoizee "^0.4.15" + timers-ext "^0.1.7" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +comlink@^4.3.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.4.1.tgz#e568b8e86410b809e8600eb2cf40c189371ef981" + integrity sha512-+1dlx0aY5Jo1vHy/tSsIGpSkN4tS9rZSW8FIhG0JH/crs9wwweswIo/POr451r7bZww3hFbPAKnTpimzL/mm4Q== + +commander@~9.4.0: + version "9.4.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" + integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +confusing-browser-globals@^1.0.10: + version "1.0.11" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" + integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +damerau-levenshtein@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" + integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== + +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +dedent@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" + integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +define-data-property@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" + integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== + dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +dequal@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff-sequences@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" + integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.535: + version "1.4.556" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.556.tgz#97385917eb6ea3ac6a3378cf87bb39ee1db96e76" + integrity sha512-6RPN0hHfzDU8D56E72YkDvnLw5Cj2NMXZGg3UkgyoHxjVhG99KZpsKgBWMmTy0Ei89xwan+rbRsVB9yzATmYzQ== + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +enhanced-resolve@^5.0.0: + version "5.15.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" + integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.22.1: + version "1.22.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.2.tgz#90f7282d91d0ad577f505e423e52d4c1d93c1b8a" + integrity sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA== + dependencies: + array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.2" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.1" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.12" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.1" + safe-array-concat "^1.0.1" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.8" + string.prototype.trimend "^1.0.7" + string.prototype.trimstart "^1.0.7" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" + typed-array-byte-offset "^1.0.0" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.11" + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: + version "0.10.62" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" + integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +es6-weak-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== + dependencies: + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-airbnb-base@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236" + integrity sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig== + dependencies: + confusing-browser-globals "^1.0.10" + object.assign "^4.1.2" + object.entries "^1.1.5" + semver "^6.3.0" + +eslint-config-airbnb-typescript@^16.1.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-16.2.0.tgz#9193fafd62f1cbf444895f4495eae334baf3265b" + integrity sha512-OUaMPZpTOZGKd5tXOjJ9PRU4iYNW/Z5DoHIynjsVK/FpkWdiY5+nxQW6TiJAlLwVI1l53xUOrnlZWtVBVQzuWA== + dependencies: + eslint-config-airbnb-base "^15.0.0" + +eslint-config-airbnb@^19.0.4: + version "19.0.4" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz#84d4c3490ad70a0ffa571138ebcdea6ab085fdc3" + integrity sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew== + dependencies: + eslint-config-airbnb-base "^15.0.0" + object.assign "^4.1.2" + object.entries "^1.1.5" + +eslint-config-prettier@^8.5.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" + integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== + +eslint-import-resolver-node@^0.3.2, eslint-import-resolver-node@^0.3.7: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== + dependencies: + debug "^3.2.7" + is-core-module "^2.13.0" + resolve "^1.22.4" + +eslint-import-resolver-root-import@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-root-import/-/eslint-import-resolver-root-import-1.0.4.tgz#82991138d8014b5e2283b27622ad1ba21f535609" + integrity sha512-c8cUQcELRBe0mnblBZJKEfL+jIUGR8pctK5gdru5N7bBOIve2WZ0R3KoO5GOksXJ4WzZhtcBS2xPaTJYEe4IdQ== + dependencies: + eslint-import-resolver-node "^0.3.2" + json5 "^2.1.0" + +eslint-module-utils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" + integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== + dependencies: + debug "^3.2.7" + +eslint-plugin-import@^2.25.4: + version "2.28.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz#63b8b5b3c409bfc75ebaf8fb206b07ab435482c4" + integrity sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A== + dependencies: + array-includes "^3.1.6" + array.prototype.findlastindex "^1.2.2" + array.prototype.flat "^1.3.1" + array.prototype.flatmap "^1.3.1" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.7" + eslint-module-utils "^2.8.0" + has "^1.0.3" + is-core-module "^2.13.0" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.fromentries "^2.0.6" + object.groupby "^1.0.0" + object.values "^1.1.6" + semver "^6.3.1" + tsconfig-paths "^3.14.2" + +eslint-plugin-jest@^26.1.1: + version "26.9.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz#7931c31000b1c19e57dbfb71bbf71b817d1bf949" + integrity sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng== + dependencies: + "@typescript-eslint/utils" "^5.10.0" + +eslint-plugin-jsx-a11y@^6.5.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz#fca5e02d115f48c9a597a6894d5bcec2f7a76976" + integrity sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA== + dependencies: + "@babel/runtime" "^7.20.7" + aria-query "^5.1.3" + array-includes "^3.1.6" + array.prototype.flatmap "^1.3.1" + ast-types-flow "^0.0.7" + axe-core "^4.6.2" + axobject-query "^3.1.1" + damerau-levenshtein "^1.0.8" + emoji-regex "^9.2.2" + has "^1.0.3" + jsx-ast-utils "^3.3.3" + language-tags "=1.0.5" + minimatch "^3.1.2" + object.entries "^1.1.6" + object.fromentries "^2.0.6" + semver "^6.3.0" + +eslint-plugin-prettier@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8.10.0: + version "8.51.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.51.0.tgz#4a82dae60d209ac89a5cff1604fea978ba4950f3" + integrity sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.2" + "@eslint/js" "8.51.0" + "@humanwhocodes/config-array" "^0.11.11" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + +ext@^1.1.2: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + +fake-indexeddb@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-5.0.0.tgz#c9f394d6d36db62760ad596ebec97ba3d700c95b" + integrity sha512-hGMsl73XgJAk5OtC8hFDSLUVzJ3Z1/C06YpFwI7DzCsEsmH5Mvkxplv3PK6uUL7XCYVBTzayp/4gD+cp7Qi8xQ== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-glob@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.1.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.1.tgz#a02a15fdec25a8f844ff7cc658f03dd99eb4609b" + integrity sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + +flatted@^3.2.9: + version "3.2.9" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" + integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2, fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^8.0.3: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.19.0: + version "13.23.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.23.0.tgz#ef31673c926a0976e1f61dab4dca57e0c0a8af02" + integrity sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA== + dependencies: + type-fest "^0.20.2" + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.2.4, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" + integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== + +ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-builtin-module@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" + integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== + dependencies: + builtin-modules "^3.3.0" + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-promise@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + +is-reference@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== + dependencies: + "@types/estree" "*" + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== + dependencies: + which-typed-array "^1.1.11" + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz#71e87707e8041428732518c6fb5211761753fbdf" + integrity sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.6" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" + integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" + integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" + integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^27.0.0: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" + integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== + dependencies: + chalk "^4.0.0" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + +jest-util@^29.0.0, jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^29.5.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + +json5@^2.1.0, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonc-parser@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + +jsx-ast-utils@^3.3.3: + version "3.3.5" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== + dependencies: + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + object.assign "^4.1.4" + object.values "^1.1.6" + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +language-subtag-registry@~0.3.2: + version "0.3.22" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" + integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w== + +language-tags@=1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" + integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ== + dependencies: + language-subtag-registry "~0.3.2" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lru-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ== + dependencies: + es5-ext "~0.10.2" + +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + +magic-string@0.25.2: + version "0.25.2" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.2.tgz#139c3a729515ec55e96e69e82a11fe890a293ad9" + integrity sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg== + dependencies: + sourcemap-codec "^1.4.4" + +magic-string@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" + integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" + +magic-string@^0.30.3: + version "0.30.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9" + integrity sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@1.x: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +marked@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== + +memoizee@^0.4.15: + version "0.4.15" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72" + integrity sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ== + dependencies: + d "^1.0.1" + es5-ext "^0.10.53" + es6-weak-map "^2.0.3" + event-emitter "^0.3.5" + is-promise "^2.2.2" + lru-queue "^0.1.0" + next-tick "^1.1.0" + timers-ext "^0.1.7" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.0, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.0: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.0: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +next-tick@1, next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.13: + version "2.0.13" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== + +nodemon@^2.0.21: + version "2.0.22" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.22.tgz#182c45c3a78da486f673d6c1702e00728daf5258" + integrity sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ== + dependencies: + chokidar "^3.5.2" + debug "^3.2.7" + ignore-by-default "^1.0.1" + minimatch "^3.1.2" + pstree.remy "^1.1.8" + semver "^5.7.1" + simple-update-notifier "^1.0.7" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.5" + +nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== + dependencies: + abbrev "1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +object-inspect@^1.12.3, object-inspect@^1.9.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.0.tgz#42695d3879e1cd5bda6df5062164d80c996e23e2" + integrity sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.2, object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.entries@^1.1.5, object.entries@^1.1.6: + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.7.tgz#2b47760e2a2e3a752f39dd874655c61a7f03c131" + integrity sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.fromentries@^2.0.6: + version "2.0.7" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" + integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.groupby@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee" + integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + +object.values@^1.1.6: + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +open@^8.0.0: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + +ospec@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ospec/-/ospec-3.1.0.tgz#d36b8e10110f58f63a463df2390a7a73fe9579a8" + integrity sha512-+nGtjV3vlADp+UGfL51miAh/hB4awPBkQrArhcgG4trAaoA2gKt5bf9w0m9ch9zOr555cHWaCHZEDiBOkNZSxw== + dependencies: + glob "^7.1.3" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pirates@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +pretty-format@^27.0.0, pretty-format@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + +pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +pstree.remy@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +pure-rand@^6.0.0: + version "6.0.4" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" + integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + +regexp.prototype.flags@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" + integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + set-function-name "^2.0.0" + +reload@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/reload/-/reload-3.2.1.tgz#42d43e33e327efe1348c723272c6835fe333349a" + integrity sha512-ZdM8ZSEeI72zkhh6heMEvJ0vHZoovZXcJI6Zae8CzS7o5vO/WjZsAMMr0y1+3I/fCN7y7ZxABoUwwCswcLHkjQ== + dependencies: + cli-color "~2.0.0" + commander "~9.4.0" + finalhandler "~1.2.0" + minimist "~1.2.0" + open "^8.0.0" + serve-static "~1.15.0" + supervisor "~0.12.0" + ws "~8.11.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + +resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.4: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rollup-plugin-base64@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-base64/-/rollup-plugin-base64-1.0.1.tgz#b3529b94d23baeb66e1e3bffd04477fa792985eb" + integrity sha512-IbdX8fjuXO/Op3hYmRPjVo0VwcSenwsQDaDTFdoe+70B5ZGoLMtr96L2yhHXCfxv7HwZVvxZqLsuWj6VwzRt3g== + dependencies: + "@rollup/pluginutils" "^3.1.0" + +rollup-plugin-modify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-modify/-/rollup-plugin-modify-3.0.0.tgz#5326e11dfec247e8bbdd9507f3da1da1e5c7818b" + integrity sha512-p/ffs0Y2jz2dEnWjq1oVC7SY37tuS+aP7whoNaQz1EAAOPg+k3vKJo8cMMWx6xpdd0NzhX4y2YF9o/NPu5YR0Q== + dependencies: + magic-string "0.25.2" + ospec "3.1.0" + +rollup-plugin-web-worker-loader@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-web-worker-loader/-/rollup-plugin-web-worker-loader-1.6.1.tgz#9d7a27575b64b0780fe4e8b3bc87470d217e485f" + integrity sha512-4QywQSz1NXFHKdyiou16mH3ijpcfLtLGOrAqvAqu1Gx+P8+zj+3gwC2BSL/VW1d+LW4nIHC8F7d7OXhs9UdR2A== + +rollup@^3.9.1: + version "3.29.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" + integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw== + optionalDependencies: + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-array-concat@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" + integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + isarray "^2.0.5" + +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + +semver@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.4, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +semver@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serve-static@~1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-function-name@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" + integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== + dependencies: + define-data-property "^1.0.1" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.0" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shiki@^0.14.1: + version "0.14.5" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.5.tgz#375dd214e57eccb04f0daf35a32aa615861deb93" + integrity sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw== + dependencies: + ansi-sequence-parser "^1.1.0" + jsonc-parser "^3.2.0" + vscode-oniguruma "^1.7.0" + vscode-textmate "^8.0.0" + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +simple-update-notifier@^1.0.7: + version "1.1.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz#67694c121de354af592b347cdba798463ed49c82" + integrity sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg== + dependencies: + semver "~7.0.0" + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +sourcemap-codec@^1.4.4: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.trim@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" + integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string.prototype.trimend@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" + integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string.prototype.trimstart@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" + integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supervisor@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/supervisor/-/supervisor-0.12.0.tgz#de7e6337015b291851c10f3538c4a7f04917ecc1" + integrity sha512-iBYeU5Or4WiiIa3+ns1DpHIiHjNNXSuYUiixKcznewwo4ImBJ8EobktaAo2csOcauhrz4SvKRTou8Z2C3W28+A== + +supports-color@^5.3.0, supports-color@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +timers-ext@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" + integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== + dependencies: + es5-ext "~0.10.46" + next-tick "1" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +touch@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" + integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== + dependencies: + nopt "~1.0.10" + +ts-jest@^29.1.0: + version "29.1.1" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.1.tgz#f58fe62c63caf7bfcc5cc6472082f79180f0815b" + integrity sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "4.x" + make-error "1.x" + semver "^7.5.3" + yargs-parser "^21.0.1" + +ts-loader@^9.4.2: + version "9.5.0" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.5.0.tgz#f0a51dda37cc4d8e43e6cb14edebbc599b0c3aa2" + integrity sha512-LLlB/pkB4q9mW2yLdFMnK3dEHbrBjeZTYguaaIfusyojBgAGf5kF+O6KcWqiGzWqHk0LBsoolrp4VftEURhybg== + dependencies: + chalk "^4.1.0" + enhanced-resolve "^5.0.0" + micromatch "^4.0.0" + semver "^7.3.4" + source-map "^0.7.4" + +tsconfig-paths@^3.14.2: + version "3.14.2" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" + integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== + +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" + integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +typedoc@^0.24.8: + version "0.24.8" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.24.8.tgz#cce9f47ba6a8d52389f5e583716a2b3b4335b63e" + integrity sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w== + dependencies: + lunr "^2.3.9" + marked "^4.3.0" + minimatch "^9.0.0" + shiki "^0.14.1" + +typescript@^4.8.4: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +undefsafe@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== + +undici-types@~5.25.1: + version "5.25.3" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.25.3.tgz#e044115914c85f0bcbb229f346ab739f064998c3" + integrity sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA== + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +v8-to-istanbul@^9.0.1: + version "9.1.3" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz#ea456604101cd18005ac2cae3cdd1aa058a6306b" + integrity sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + +vscode-oniguruma@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" + integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA== + +vscode-textmate@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d" + integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg== + +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +web-streams-polyfill@^3.0.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-typed-array@^1.1.11: + version "1.1.11" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" + integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +ws@^8.14.2: + version "8.14.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" + integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== + +ws@~8.11.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" + integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^21.0.1, yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.3.1: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/sdk/typescript/scripts/publish.sh b/sdk/typescript/scripts/publish.sh index fff437da72..03674df7b1 100755 --- a/sdk/typescript/scripts/publish.sh +++ b/sdk/typescript/scripts/publish.sh @@ -37,6 +37,7 @@ packages=( "ts/sdk/mix-fetch/esm-full-fat" "ts/sdk/nodejs-client/cjs" +"ts/sdk/mix-fetch-node/cjs" "ts/sdk/node-tester/cjs" "ts/sdk/node-tester/cjs-full-fat" diff --git a/sdk/typescript/scripts/unpublish.sh b/sdk/typescript/scripts/unpublish.sh index 8d0671faa9..52a02ed32b 100755 --- a/sdk/typescript/scripts/unpublish.sh +++ b/sdk/typescript/scripts/unpublish.sh @@ -24,6 +24,7 @@ packages2=( "ts/sdk/mix-fetch/esm-full-fat" "ts/sdk/nodejs-client/cjs" +"ts/sdk/mix-fetch-node/cjs" "ts/sdk/node-tester/cjs" "ts/sdk/node-tester/cjs-full-fat" diff --git a/wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go b/wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go index cdd2638cf1..19f7b94594 100644 --- a/wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go +++ b/wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go @@ -8,12 +8,74 @@ package main import ( "go-mix-conn/internal/bridge/go_bridge" "go-mix-conn/internal/state" + "syscall/js" ) var done chan struct{} func init() { println("[go init]: go module init") + + q := js.Global().Get("location") + if q.IsUndefined() { + println("location undefined") + } else { + println("location ok") + } + a := js.Global().Get("Error") + if a.IsUndefined() { + println("Error undefined") + } else { + println("Error ok") + } + b := js.Global().Get("Promise") + if b.IsUndefined() { + println("Promise undefined") + } else { + println("Promise ok") + } + c := js.Global().Get("Reflect") + if c.IsUndefined() { + println("Reflect undefined") + } else { + println("Reflect ok") + } + d := js.Global().Get("Object") + if d.IsUndefined() { + println("Object undefined") + } else { + println("Object ok") + } + e := js.Global().Get("Response") + if e.IsUndefined() { + println("Response undefined") + } else { + println("Response ok") + } + f := js.Global().Get("Request") + if f.IsUndefined() { + println("Request undefined") + } else { + println("Request ok") + } + g := js.Global().Get("Proxy") + if g.IsUndefined() { + println("Proxy undefined") + } else { + println("Proxy ok") + } + h := js.Global().Get("Headers") + if h.IsUndefined() { + println("Headers undefined") + } else { + println("Headers ok") + } + i := js.Global().Get("Uint8Array") + if i.IsUndefined() { + println("Uint8Array undefined") + } else { + println("Uint8Array ok") + } done = make(chan struct{}) state.InitialiseGlobalState() From 7129de4373d4b62e06a33dc877b7d605ac074033 Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Mon, 23 Oct 2023 12:14:59 +0200 Subject: [PATCH 162/236] Add hack for working with old nym gateways Signed-off-by: Sebastian Martinez --- .../client-core/src/client/topology_control/nym_api_provider.rs | 2 +- common/client-core/src/init/helpers.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/client-core/src/client/topology_control/nym_api_provider.rs b/common/client-core/src/client/topology_control/nym_api_provider.rs index 824294793b..5de16663de 100644 --- a/common/client-core/src/client/topology_control/nym_api_provider.rs +++ b/common/client-core/src/client/topology_control/nym_api_provider.rs @@ -69,7 +69,7 @@ impl NymApiTopologyProvider { Ok(mixes) => mixes, }; - let gateways = match self.validator_client.get_cached_described_gateways().await { + let gateways = match self.validator_client.get_cached_gateways().await { Err(err) => { error!("failed to get network gateways - {err}"); return None; diff --git a/common/client-core/src/init/helpers.rs b/common/client-core/src/init/helpers.rs index 4b50f0864b..b253ed44cf 100644 --- a/common/client-core/src/init/helpers.rs +++ b/common/client-core/src/init/helpers.rs @@ -67,7 +67,7 @@ pub async fn current_gateways( log::trace!("Fetching list of gateways from: {nym_api}"); - let gateways = client.get_cached_described_gateways().await?; + let gateways = client.get_cached_gateways().await?; let valid_gateways = gateways .into_iter() .filter_map(|gateway| gateway.try_into().ok()) From 06a96fa74acbf33545e152d903bac0dee251d19a Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Mon, 23 Oct 2023 12:15:25 +0200 Subject: [PATCH 163/236] Polishing nodejs-client and mix-fetch-node Signed-off-by: Sebastian Martinez --- .github/workflows/publish-sdk-npm.yml | 12 +- package.json | 6 +- .../mix-fetch/node-js/index.js} | 2 +- .../examples/mix-fetch/node-js/package.json | 14 + .../examples/mix-fetch/node-js/server.js | 55 + .../packages/mix-fetch-node/.babelrc | 3 - .../packages/mix-fetch-node/README.md | 2 +- .../packages/mix-fetch-node/package.json | 4 +- .../mix-fetch-node/rollup-worker.config.mjs | 15 +- .../scripts/build-prod-docs-collect.sh | 6 +- .../mix-fetch-node/scripts/build-prod.sh | 6 +- .../packages/mix-fetch-node/src/index.ts | 1 - .../mix-fetch-node/src/worker/index.ts | 1 + .../mix-fetch-node/src/worker/main.ts | 2 +- .../mix-fetch-node/src/worker/polyfill.ts | 3 +- .../packages/nodejs-client/README.md | 6 +- .../packages/nodejs-client/internal/index.js | 25 + .../packages/nodejs-client/package.json | 16 +- .../nodejs-client/rollup-cjs.config.mjs | 8 +- .../nodejs-client/rollup-worker.config.mjs | 12 +- .../packages/nodejs-client/src/index.ts | 4 +- .../packages/nodejs-client/src/polyfill.ts | 23 + .../packages/nodejs-client/src/types.ts | 4 +- .../packages/nodejs-client/src/worker.ts | 24 +- sdk/typescript/scripts/build-prod-sdk.sh | 2 +- sdk/typescript/scripts/publish.sh | 47 +- sdk/typescript/scripts/unpublish.sh | 31 +- yarn.lock | 1098 ++++++++++++++++- 28 files changed, 1249 insertions(+), 183 deletions(-) rename sdk/typescript/{packages/mix-fetch-node/internal-dev/index.mjs => examples/mix-fetch/node-js/index.js} (94%) create mode 100644 sdk/typescript/examples/mix-fetch/node-js/package.json create mode 100644 sdk/typescript/examples/mix-fetch/node-js/server.js delete mode 100644 sdk/typescript/packages/mix-fetch-node/.babelrc create mode 100644 sdk/typescript/packages/nodejs-client/internal/index.js create mode 100644 sdk/typescript/packages/nodejs-client/src/polyfill.ts diff --git a/.github/workflows/publish-sdk-npm.yml b/.github/workflows/publish-sdk-npm.yml index 5836a12e37..a0aa757379 100644 --- a/.github/workflows/publish-sdk-npm.yml +++ b/.github/workflows/publish-sdk-npm.yml @@ -12,7 +12,7 @@ jobs: uses: actions/setup-node@v3 with: node-version: 18 - registry-url: 'https://registry.npmjs.org' + registry-url: "https://registry.npmjs.org" - name: Setup yarn run: npm install -g yarn @@ -28,6 +28,16 @@ jobs: - name: Install wasm-opt run: cargo install wasm-opt + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: "1.20" + + - name: Install TinyGo + uses: acifani/setup-tinygo@v1 + with: + tinygo-version: "0.27.0" + - name: Install dependencies run: yarn diff --git a/package.json b/package.json index dd72164411..cd357e15a0 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ "sdk/typescript/packages/mui-theme", "sdk/typescript/packages/react-components", "sdk/typescript/packages/validator-client", + "sdk/typescript/packages/mix-fetch-node", + "sdk/typescript/packages/nodejs-client", "ts-packages/*", "nym-wallet", "nym-connect/**", @@ -34,7 +36,7 @@ "prebuild:ci": "yarn dev:on && yarn", "build:ci": "run-s build:types build:packages build:wasm build:ci:sdk", "postbuild:ci": "yarn dev:off", - "build:ci:sdk": "lerna run --scope '{@nymproject/sdk,@nymproject/node-tester,@nymproject/sdk-react,@nymproject/mix-fetch}' build:dev --stream", + "build:ci:sdk": "lerna run --scope '{@nymproject/sdk,@nymproject/node-tester,@nymproject/sdk-react,@nymproject/mix-fetch,@nymproject/nodejs-client,@nymproject/mix-fetch-node}' build --stream", "docs:prod:build": "run-s docs:prod:build:ws", "docs:prod:build:ws": "lerna run docs:prod:build --stream", "sdk:build": "./sdk/typescript/scripts/build-prod-sdk.sh", @@ -53,4 +55,4 @@ "@npmcli/node-gyp": "^3.0.0", "node-gyp": "^9.3.1" } -} \ No newline at end of file +} diff --git a/sdk/typescript/packages/mix-fetch-node/internal-dev/index.mjs b/sdk/typescript/examples/mix-fetch/node-js/index.js similarity index 94% rename from sdk/typescript/packages/mix-fetch-node/internal-dev/index.mjs rename to sdk/typescript/examples/mix-fetch/node-js/index.js index a49455449d..feaa5770c3 100644 --- a/sdk/typescript/packages/mix-fetch-node/internal-dev/index.mjs +++ b/sdk/typescript/examples/mix-fetch/node-js/index.js @@ -1,4 +1,4 @@ -import { createMixFetch, disconnectMixFetch } from '../dist/cjs/index.js'; +const { createMixFetch, disconnectMixFetch } = require('@nymproject/mix-fetch-node-commonjs'); /** * The main entry point diff --git a/sdk/typescript/examples/mix-fetch/node-js/package.json b/sdk/typescript/examples/mix-fetch/node-js/package.json new file mode 100644 index 0000000000..e8117ef02d --- /dev/null +++ b/sdk/typescript/examples/mix-fetch/node-js/package.json @@ -0,0 +1,14 @@ +{ + "name": "@nymproject/mix-fetch-node-js-example", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "scripts": { + "start": "node index.js", + "start:server": "node server.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "dependencies": { + "@nymproject/mix-fetch-node-commonjs": "^1.2.1-rc.2" + } +} diff --git a/sdk/typescript/examples/mix-fetch/node-js/server.js b/sdk/typescript/examples/mix-fetch/node-js/server.js new file mode 100644 index 0000000000..7e35bc1804 --- /dev/null +++ b/sdk/typescript/examples/mix-fetch/node-js/server.js @@ -0,0 +1,55 @@ +const express = require('express'); +const { mixFetch } = require('@nymproject/mix-fetch-node-commonjs'); + +const app = express(); +app.use(express.static('public')); + +app.get('/nym-fetch', async (req, res) => { + try { + const args = { + mode: 'unsafe-ignore-cors', + headers: { + 'Content-Type': 'application/json', + }, + }; + + const url = req.query.url; + + if (!url) { + return res.status(400).send('input a valid url'); + } + + const extra = { + hiddenGateways: [ + { + owner: 'n1ns3v70ul9gnl9l9fkyz8cyxfq75vjcmx8el0t3', + host: 'sandbox-gateway1.nymtech.net', + explicitIp: '35.158.238.80', + identityKey: 'HjNEDJuotWV8VD4ufeA1jeheTnfNJ7Jorevp57hgaZua', + sphinxKey: 'BoXeUD7ERGmzRauMjJD3itVNnQiH42ncUb6kcVLrb3dy', + }, + ], + }; + + const mixFetchOptions = { + nymApiUrl: 'https://sandbox-nym-api1.nymtech.net/api', + preferredGateway: 'HjNEDJuotWV8VD4ufeA1jeheTnfNJ7Jorevp57hgaZua', + preferredNetworkRequester: + 'AzGdJ4MU78Ex22NEWfeycbN7bt3PFZr1MtKstAdhfELG.GSxnKnvKPjjQm3FdtsgG5KyhP6adGbPHRmFWDH4XfUpP@HjNEDJuotWV8VD4ufeA1jeheTnfNJ7Jorevp57hgaZua', + mixFetchOverride: { + requestTimeoutMs: 60_000, + }, + forceTls: false, + extra, + }; + + const response = await mixFetch(url, args, mixFetchOptions); + const json = await response.json(); + res.send(json); + } catch (error) { + console.log(error); + res.status(500).send(error.message); + } +}); + +app.listen(3000, () => console.log('Server running on port 3000')); diff --git a/sdk/typescript/packages/mix-fetch-node/.babelrc b/sdk/typescript/packages/mix-fetch-node/.babelrc deleted file mode 100644 index 0ef5ffc214..0000000000 --- a/sdk/typescript/packages/mix-fetch-node/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/env"] -} diff --git a/sdk/typescript/packages/mix-fetch-node/README.md b/sdk/typescript/packages/mix-fetch-node/README.md index dc62208cd3..89050cb4f8 100644 --- a/sdk/typescript/packages/mix-fetch-node/README.md +++ b/sdk/typescript/packages/mix-fetch-node/README.md @@ -5,7 +5,7 @@ This package is a drop-in replacement for `fetch` in NodeJS to send HTTP request ## Usage ```js -const { mixFetch } = require('@nymproject/mix-fetch-node'); +const { mixFetch } = require('@nymproject/mix-fetch-node-commonjs'); ... diff --git a/sdk/typescript/packages/mix-fetch-node/package.json b/sdk/typescript/packages/mix-fetch-node/package.json index 013fb344fb..2df56711de 100644 --- a/sdk/typescript/packages/mix-fetch-node/package.json +++ b/sdk/typescript/packages/mix-fetch-node/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/mix-fetch-node", - "version": "1.2.0", + "version": "1.2.1-rc.2", "description": "This package is a drop-in replacement for `fetch` in NodeJS to send HTTP requests over the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -28,7 +28,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/mix-fetch-wasm-node": ">=1.2.0-rc.10 || ^1", + "@nymproject/mix-fetch-wasm-node": ">=1.2.0 || ^1", "comlink": "^4.3.1", "fake-indexeddb": "^5.0.0", "node-fetch": "^3.3.2", diff --git a/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs b/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs index 8df9ba5cb3..bc10b36ad1 100644 --- a/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs +++ b/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs @@ -11,7 +11,7 @@ export default { dir: 'dist/cjs', format: 'cjs', }, - external: ['util', 'fake-indexeddb'], + onwarn, plugins: [ resolve({ browser: false, @@ -19,11 +19,6 @@ export default { extensions: ['.js', '.ts'], }), commonjs(), - // TODO: One of the wasm functions calls `new WebSocket` at one point, which we aren't able to polyfill correctly yet. - modify({ - find: 'const ret = new WebSocket(getStringFromWasm0(arg0, arg1));', - replace: 'const ws = require("ws"); const ret = new ws.WebSocket(getStringFromWasm0(arg0, arg1));', - }), // TODO: `getObject(...).require` seems to generate a warning on Webpack but with Rollup we get a panic since it can't require. // By hard coding the require here, we can workaround that. // Reference: https://github.com/rust-random/getrandom/issues/224 @@ -38,3 +33,11 @@ export default { }), ], }; + +function onwarn(warning) { + // fake-indexeddb has a circular dependency that triggers a warning when rolled up + if (warning.code !== 'CIRCULAR_DEPENDENCY') { + // eslint-disable-next-line no-console + console.error(`(!) ${warning.message}`); + } +} diff --git a/sdk/typescript/packages/mix-fetch-node/scripts/build-prod-docs-collect.sh b/sdk/typescript/packages/mix-fetch-node/scripts/build-prod-docs-collect.sh index f672185300..a40a4a4a90 100755 --- a/sdk/typescript/packages/mix-fetch-node/scripts/build-prod-docs-collect.sh +++ b/sdk/typescript/packages/mix-fetch-node/scripts/build-prod-docs-collect.sh @@ -4,14 +4,14 @@ set -o errexit set -o nounset set -o pipefail -rm -rf ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch || true +rm -rf ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch-node || true # run the build yarn docs:generate:prod # move the output outside of the yarn/npm workspaces mkdir -p ../../../../dist/ts/docs/tsdoc/nymproject -mv docs ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch +mv docs ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch-node echo "Output can be found in:" -realpath ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch +realpath ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch-node diff --git a/sdk/typescript/packages/mix-fetch-node/scripts/build-prod.sh b/sdk/typescript/packages/mix-fetch-node/scripts/build-prod.sh index b56d1e0472..61377bdcf7 100755 --- a/sdk/typescript/packages/mix-fetch-node/scripts/build-prod.sh +++ b/sdk/typescript/packages/mix-fetch-node/scripts/build-prod.sh @@ -5,7 +5,7 @@ set -o nounset set -o pipefail rm -rf dist || true -rm -rf ../../../../dist/ts/sdk/mix-fetch || true +rm -rf ../../../../dist/ts/sdk/mix-fetch-node || true # run the build scripts/build.sh @@ -14,7 +14,7 @@ node scripts/buildPackageJson.mjs # move the output outside of the yarn/npm workspaces mkdir -p ../../../../dist/ts/sdk mv dist ../../../../dist/ts/sdk -mv ../../../../dist/ts/sdk/dist ../../../../dist/ts/sdk/mix-fetch +mv ../../../../dist/ts/sdk/dist ../../../../dist/ts/sdk/mix-fetch-node echo "Output can be found in:" -realpath ../../../../dist/ts/sdk/mix-fetch +realpath ../../../../dist/ts/sdk/mix-fetch-node diff --git a/sdk/typescript/packages/mix-fetch-node/src/index.ts b/sdk/typescript/packages/mix-fetch-node/src/index.ts index e4bc233499..04a83ea144 100644 --- a/sdk/typescript/packages/mix-fetch-node/src/index.ts +++ b/sdk/typescript/packages/mix-fetch-node/src/index.ts @@ -1,5 +1,4 @@ /* eslint-disable no-underscore-dangle */ - import type { SetupMixFetchOps, IMixFetchFn } from './types'; import { createMixFetch as createMixFetchInternal } from './create-mix-fetch'; diff --git a/sdk/typescript/packages/mix-fetch-node/src/worker/index.ts b/sdk/typescript/packages/mix-fetch-node/src/worker/index.ts index 81582206e3..24bfded826 100644 --- a/sdk/typescript/packages/mix-fetch-node/src/worker/index.ts +++ b/sdk/typescript/packages/mix-fetch-node/src/worker/index.ts @@ -1,4 +1,5 @@ import './polyfill'; + import { loadWasm } from './wasm-loading'; import { run } from './main'; diff --git a/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts b/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts index e30e6c7cf8..58cfb41a51 100644 --- a/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts +++ b/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts @@ -1,10 +1,10 @@ /* eslint-disable no-console */ +import type { IMixFetchWebWorker, LoadedEvent } from '../types'; import * as Comlink from 'comlink'; import { parentPort } from 'node:worker_threads'; import { setupMixFetch, disconnectMixFetch } from '@nymproject/mix-fetch-wasm-node'; -import type { IMixFetchWebWorker, LoadedEvent } from '../types'; import nodeEndpoint from '../node-adapter'; import { EventKinds, ResponseBodyConfigMap, ResponseBodyConfigMapDefaults } from '../types'; import { handleResponseMimeTypes } from './handle-response-mime-types'; diff --git a/sdk/typescript/packages/mix-fetch-node/src/worker/polyfill.ts b/sdk/typescript/packages/mix-fetch-node/src/worker/polyfill.ts index 76c9dd6e2f..7c88d9b088 100644 --- a/sdk/typescript/packages/mix-fetch-node/src/worker/polyfill.ts +++ b/sdk/typescript/packages/mix-fetch-node/src/worker/polyfill.ts @@ -1,8 +1,8 @@ +import { TextDecoder, TextEncoder } from 'node:util'; import * as crypto from 'node:crypto'; import * as fs from 'node:fs'; import WebSocket from 'ws'; import fetch, { Headers, Request, Response } from 'node-fetch'; -import { TextDecoder, TextEncoder } from 'node:util'; import { Worker } from 'node:worker_threads'; import { indexedDB } from 'fake-indexeddb'; @@ -18,7 +18,6 @@ import { indexedDB } from 'fake-indexeddb'; (globalThis as any).Headers = Headers; (globalThis as any).Request = Request; (globalThis as any).Response = Response; -(globalThis as any).Headers = Headers; (globalThis as any).fs = fs; (globalThis as any).crypto = crypto; (globalThis as any).WebSocket = WebSocket; diff --git a/sdk/typescript/packages/nodejs-client/README.md b/sdk/typescript/packages/nodejs-client/README.md index db694fbe96..9d98f59891 100644 --- a/sdk/typescript/packages/nodejs-client/README.md +++ b/sdk/typescript/packages/nodejs-client/README.md @@ -5,15 +5,13 @@ This package is a NodeJS client that uses the wasm from the [Sphinx webassembly ## Usage ```js -const { createNymMixnetClient } = require('../dist/cjs/index.js'); +const { createNymMixnetClient } = require('@nymproject/nodejs-client-commonjs'); async () => { const nym = await createNymMixnetClient(); nym.events.subscribeToTextMessageReceivedEvent(async (e) => { - if (e.args.payload === 'Hello') { - await nym.client.stop(); - } + console.log("message received", e.args.payload); }); const nymApiUrl = 'https://validator.nymtech.net/api/'; diff --git a/sdk/typescript/packages/nodejs-client/internal/index.js b/sdk/typescript/packages/nodejs-client/internal/index.js new file mode 100644 index 0000000000..2ec5e5cb7e --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/internal/index.js @@ -0,0 +1,25 @@ +const { createNymMixnetClient } = require('../dist/cjs/index.js'); + +(async () => { + const nym = await createNymMixnetClient(); + + nym.events.subscribeToTextMessageReceivedEvent(async ({ args: { payload, mimeType } }) => { + console.log(`received message: ${payload}`); + console.log(`with mimeType: ${mimeType}`); + }); + + // start the client and connect to a gateway + await nym.client.start({ + nymApiUrl: 'https://validator.nymtech.net/api/', + clientId: 'my-client', + }); + + nym.events.subscribeToConnected(async (e) => { + // send a message to yourself + const message = 'Hello'; + const recipient = await nym.client.selfAddress(); + console.log('main thread address: ', recipient); + console.log(`sending "${message}" to ourselves...`); + await nym.client.send({ payload: { message, mimeType: 'text/plain' }, recipient }); + }); +})(); diff --git a/sdk/typescript/packages/nodejs-client/package.json b/sdk/typescript/packages/nodejs-client/package.json index 985b48bdf6..7a30d73cc3 100644 --- a/sdk/typescript/packages/nodejs-client/package.json +++ b/sdk/typescript/packages/nodejs-client/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/nodejs-client", - "version": "1.2.0-rc.10", + "version": "1.2.1-rc.3", "license": "Apache-2.0", "author": "Nym Technologies SA", "files": [ @@ -25,29 +25,20 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-client-wasm-node": "^1.2.0", + "@nymproject/nym-client-wasm-node": ">=1.2.0 || ^1", "comlink": "^4.3.1", "fake-indexeddb": "^4.0.2", "rollup-plugin-polyfill": "^4.2.0", "ws": "^8.14.2" }, "devDependencies": { - "@babel/core": "^7.15.0", - "@babel/plugin-transform-async-to-generator": "^7.14.5", - "@babel/preset-env": "^7.15.0", - "@babel/preset-react": "^7.14.5", - "@babel/preset-typescript": "^7.15.0", - "@nymproject/eslint-config-react-typescript": "^1.0.0", "@rollup/plugin-commonjs": "^24.0.1", - "@rollup/plugin-inject": "^5.0.3", "@rollup/plugin-json": "^6.0.0", "@rollup/plugin-node-resolve": "^15.0.1", "@rollup/plugin-replace": "^5.0.2", - "@rollup/plugin-terser": "^0.2.1", "@rollup/plugin-typescript": "^10.0.1", "@rollup/plugin-url": "^8.0.1", "@rollup/plugin-wasm": "^6.1.1", - "@types/jest": "^27.0.1", "@types/node": "^16.7.13", "@typescript-eslint/eslint-plugin": "^5.13.0", "@typescript-eslint/parser": "^5.13.0", @@ -62,8 +53,6 @@ "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-react": "^7.29.2", "eslint-plugin-react-hooks": "^4.3.0", - "handlebars": "^4.7.8", - "jest": "^29.5.0", "nodemon": "3.0.1", "reload": "^3.2.1", "rimraf": "^3.0.2", @@ -71,7 +60,6 @@ "rollup-plugin-base64": "^1.0.1", "rollup-plugin-modify": "^3.0.0", "rollup-plugin-web-worker-loader": "^1.6.1", - "ts-jest": "^29.1.0", "ts-loader": "^9.4.2", "typedoc": "^0.24.8", "typescript": "^4.8.4" diff --git a/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs b/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs index cb5fe9ac74..7a4af49fc2 100644 --- a/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs +++ b/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs @@ -1,9 +1,9 @@ /* eslint-disable import/no-extraneous-dependencies */ -import typescript from '@rollup/plugin-typescript'; -import resolve from '@rollup/plugin-node-resolve'; -import { wasm } from '@rollup/plugin-wasm'; -import webWorkerLoader from 'rollup-plugin-web-worker-loader'; import replace from '@rollup/plugin-replace'; +import resolve from '@rollup/plugin-node-resolve'; +import typescript from '@rollup/plugin-typescript'; +import webWorkerLoader from 'rollup-plugin-web-worker-loader'; +import { wasm } from '@rollup/plugin-wasm'; export default { input: 'src/index.ts', diff --git a/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs b/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs index b75c9820d1..b1b40b0a0b 100644 --- a/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs +++ b/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs @@ -1,9 +1,9 @@ /* eslint-disable import/no-extraneous-dependencies */ -import typescript from '@rollup/plugin-typescript'; -import resolve from '@rollup/plugin-node-resolve'; -import { wasm } from '@rollup/plugin-wasm'; import commonjs from '@rollup/plugin-commonjs'; import modify from 'rollup-plugin-modify'; +import resolve from '@rollup/plugin-node-resolve'; +import typescript from '@rollup/plugin-typescript'; +import { wasm } from '@rollup/plugin-wasm'; export default { input: 'src/worker.ts', @@ -11,7 +11,6 @@ export default { dir: 'dist/cjs', format: 'cjs', }, - external: ['util', 'fake-indexeddb'], plugins: [ resolve({ browser: false, @@ -19,11 +18,6 @@ export default { extensions: ['.js', '.ts'], }), commonjs(), - // TODO: One of the wasm functions calls `new WebSocket` at one point, which we aren't able to polyfill correctly yet. - modify({ - find: 'const ret = new WebSocket(getStringFromWasm0(arg0, arg1));', - replace: 'const ws = require("ws"); const ret = new ws.WebSocket(getStringFromWasm0(arg0, arg1));', - }), // TODO: `getObject(...).require` seems to generate a warning on Webpack but with Rollup we get a panic since it can't require. // By hard coding the require here, we can workaround that. // Reference: https://github.com/rust-random/getrandom/issues/224 diff --git a/sdk/typescript/packages/nodejs-client/src/index.ts b/sdk/typescript/packages/nodejs-client/src/index.ts index 88133c28c2..ccc9041a50 100644 --- a/sdk/typescript/packages/nodejs-client/src/index.ts +++ b/sdk/typescript/packages/nodejs-client/src/index.ts @@ -21,8 +21,8 @@ import nodeEndpoint from './node-adapter'; /** * Create a client to send and receive traffic from the Nym mixnet. - * @required - * @returns + * @param options - An optional of options + * @returns { Promise } A new instance of the NymMixnetClient. * @example * ```typescript * const client = await createNymMixnetClient(); diff --git a/sdk/typescript/packages/nodejs-client/src/polyfill.ts b/sdk/typescript/packages/nodejs-client/src/polyfill.ts new file mode 100644 index 0000000000..425b49b5fa --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/src/polyfill.ts @@ -0,0 +1,23 @@ +import * as crypto from 'node:crypto'; +import * as fs from 'node:fs'; +import ws from 'ws'; +import { TextDecoder, TextEncoder } from 'node:util'; +import { Worker } from 'node:worker_threads'; +import { indexedDB } from 'fake-indexeddb'; +import { performance } from 'node:perf_hooks'; + +(globalThis as any).performance = performance; +(globalThis as any).TextDecoder = TextDecoder; +(globalThis as any).fs = fs; +(globalThis as any).crypto = crypto; +(globalThis as any).ws = ws; +(globalThis as any).Worker = Worker; + +globalThis.process = process; +globalThis.TextEncoder = TextEncoder; +globalThis.Reflect = Reflect; +globalThis.Proxy = Proxy; +globalThis.Error = Error; +globalThis.Promise = Promise; +globalThis.Object = Object; +globalThis.indexedDB = indexedDB; diff --git a/sdk/typescript/packages/nodejs-client/src/types.ts b/sdk/typescript/packages/nodejs-client/src/types.ts index 528dc849d5..89b7df770a 100644 --- a/sdk/typescript/packages/nodejs-client/src/types.ts +++ b/sdk/typescript/packages/nodejs-client/src/types.ts @@ -10,7 +10,6 @@ import type { DebugWasm } from '@nymproject/nym-client-wasm-node'; * }); * ``` */ - export interface NymMixnetClientOptions { autoConvertStringMimeTypes?: string[] | MimeTypes[]; } @@ -18,7 +17,8 @@ export interface NymMixnetClientOptions { /** * The client for the Nym mixnet which gives access to client methods and event subscriptions. * Returned by the {@link createNymMixnetClient} function. - * + * @property client - The sphinx nym wasm client. + * @property events - Different streams of events provided by the client. */ export interface NymMixnetClient { client: Client; diff --git a/sdk/typescript/packages/nodejs-client/src/worker.ts b/sdk/typescript/packages/nodejs-client/src/worker.ts index a3966a42de..a1a8bea3f1 100644 --- a/sdk/typescript/packages/nodejs-client/src/worker.ts +++ b/sdk/typescript/packages/nodejs-client/src/worker.ts @@ -1,9 +1,6 @@ -// eslint-disable-next-line import/first +import './polyfill'; + import * as Comlink from 'comlink'; -import * as crypto from 'node:crypto'; -import * as fs from 'node:fs'; -import * as process from 'node:process'; -import { indexedDB } from 'fake-indexeddb'; import { parentPort } from 'worker_threads'; import '@nymproject/nym-client-wasm-node/nym_client_wasm_bg.wasm'; @@ -31,19 +28,6 @@ import type { import nodeEndpoint from './node-adapter'; import { EventKinds, MimeTypes } from './types'; -// polyfill setup -const globalVar = - // eslint-disable-next-line @typescript-eslint/no-implied-eval, no-restricted-globals, no-nested-ternary - typeof WorkerGlobalScope !== 'undefined' ? self : typeof global !== 'undefined' ? global : Function('return this;')(); - -globalVar.indexedDB = indexedDB; -globalVar.fs = fs; -globalVar.process = process; -globalVar.performance = performance; -globalVar.TextEncoder = TextEncoder; -globalVar.TextDecoder = TextDecoder; -globalVar.crypto = crypto; - // eslint-disable-next-line no-console console.log('[Nym WASM client] Starting Nym WASM web worker...'); @@ -52,7 +36,6 @@ console.log('[Nym WASM client] Starting Nym WASM web worker...'); * @param event The strongly typed message to send back to the calling thread. * see https://nodejs.org/api/worker_threads.html#workerparentport */ -// eslint-disable-next-line no-restricted-globals const postMessageWithType = (event: E) => parentPort?.postMessage(event); /** @@ -152,8 +135,7 @@ class ClientWrapper { return; } // TODO: currently we don't do anything with the result, it needs some typing and exposed back on the main thread - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const res = await this.client.send_anonymous_message(payload, recipient, replySurbs); + await this.client.send_anonymous_message(payload, recipient, replySurbs); }; } diff --git a/sdk/typescript/scripts/build-prod-sdk.sh b/sdk/typescript/scripts/build-prod-sdk.sh index 70a0175abe..7dd1332b9c 100755 --- a/sdk/typescript/scripts/build-prod-sdk.sh +++ b/sdk/typescript/scripts/build-prod-sdk.sh @@ -14,7 +14,7 @@ rm -rf dist || true yarn build:wasm # build the Typescript SDK packages -yarn build:sdk +yarn build:ci:sdk # build documentation yarn docs:prod:build diff --git a/sdk/typescript/scripts/publish.sh b/sdk/typescript/scripts/publish.sh index 03674df7b1..dabea53c6c 100755 --- a/sdk/typescript/scripts/publish.sh +++ b/sdk/typescript/scripts/publish.sh @@ -10,46 +10,9 @@ set -o pipefail cd dist -#packages=( -#chat-app/parcel -#chat-app/plain-html -#chat-app/react-webpack-with-theme-example -#chrome-extension -#firefox-extension -#node-tester/parcel -#node-tester/plain-html -#node-tester/react -#react/mui-theme -#react/sdk-react -#) packages=( -"wasm/client" -"wasm/mix-fetch" -"wasm/node-tester" -"wasm/extension-storage" - -"node/wasm/client" -"node/wasm/mix-fetch" - -"ts/sdk/mix-fetch/cjs" -"ts/sdk/mix-fetch/cjs-full-fat" -"ts/sdk/mix-fetch/esm" -"ts/sdk/mix-fetch/esm-full-fat" - "ts/sdk/nodejs-client/cjs" "ts/sdk/mix-fetch-node/cjs" - -"ts/sdk/node-tester/cjs" -"ts/sdk/node-tester/cjs-full-fat" -"ts/sdk/node-tester/esm" -"ts/sdk/node-tester/esm-full-fat" - -"ts/sdk/sdk/cjs" -"ts/sdk/sdk/cjs-full-fat" -"ts/sdk/sdk/esm" -"ts/sdk/sdk/esm-full-fat" - -"ts/sdk/contract-clients" ) pushd () { @@ -57,7 +20,7 @@ pushd () { } popd () { - command popd "$@" > /dev/null + command popd > /dev/null } echo "Summary of versions of packages to publish:" @@ -65,8 +28,8 @@ echo "" for item in "${packages[@]}" do pushd "$item" - cat package.json | jq -r '. | "📦 " + .version + " " +.name' - popd + jq -r '. | "📦 " + .version + " " +.name' < package.json + popd done echo "" @@ -79,8 +42,8 @@ do (( COUNTER++ )) pushd "$item" echo "🚀 Publishing $item... (${COUNTER} of ${#packages[@]})" - cat package.json | jq -r '. | .name + " " +.version' - npm publish --access=public + jq -r '. | .name + " " +.version' < package.json + npm publish --access=public --verbose popd echo "" done diff --git a/sdk/typescript/scripts/unpublish.sh b/sdk/typescript/scripts/unpublish.sh index 52a02ed32b..aa1bf4a8ee 100755 --- a/sdk/typescript/scripts/unpublish.sh +++ b/sdk/typescript/scripts/unpublish.sh @@ -7,34 +7,8 @@ set -o pipefail cd dist packages=( -"ts/sdk/node-tester/cjs" -"ts/sdk/node-tester/cjs-full-fat" -"ts/sdk/node-tester/esm" -"ts/sdk/node-tester/esm-full-fat" -) -packages2=( -"wasm/client" -"wasm/mix-fetch" -"wasm/node-tester" -"wasm/extension-storage" - -"ts/sdk/mix-fetch/cjs" -"ts/sdk/mix-fetch/cjs-full-fat" -"ts/sdk/mix-fetch/esm" -"ts/sdk/mix-fetch/esm-full-fat" - "ts/sdk/nodejs-client/cjs" "ts/sdk/mix-fetch-node/cjs" - -"ts/sdk/node-tester/cjs" -"ts/sdk/node-tester/cjs-full-fat" -"ts/sdk/node-tester/esm" -"ts/sdk/node-tester/esm-full-fat" - -"ts/sdk/sdk/cjs" -"ts/sdk/sdk/cjs-full-fat" -"ts/sdk/sdk/esm" -"ts/sdk/sdk/esm-full-fat" ) pushd () { @@ -42,7 +16,7 @@ pushd () { } popd () { - command popd "$@" > /dev/null + command popd > /dev/null } echo "Summary of versions of packages to publish:" @@ -50,7 +24,7 @@ echo "" for item in "${packages[@]}" do pushd "$item" - cat package.json | jq -r '. | "📦 " + .version + " " +.name' + jq -r '. | "📦 " + .version + " " +.name' < package.json popd done @@ -68,4 +42,3 @@ do done echo "" echo "✅ Done" - diff --git a/yarn.lock b/yarn.lock index 1d5fec6aef..3309ce67f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -83,6 +83,27 @@ json5 "^2.2.3" semver "^6.3.1" +"@babel/core@^7.11.6": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.2.tgz#ed10df0d580fff67c5f3ee70fd22e2e4c90a9f94" + integrity sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-module-transforms" "^7.23.0" + "@babel/helpers" "^7.23.2" + "@babel/parser" "^7.23.0" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.2" + "@babel/types" "^7.23.0" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.22.15", "@babel/generator@^7.23.0", "@babel/generator@^7.7.2": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" @@ -301,7 +322,7 @@ "@babel/traverse" "^7.23.0" "@babel/types" "^7.23.0" -"@babel/helpers@^7.22.15": +"@babel/helpers@^7.22.15", "@babel/helpers@^7.23.2": version "7.23.2" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.2.tgz#2832549a6e37d484286e15ba36a5330483cac767" integrity sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ== @@ -525,7 +546,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-jsx@^7.22.5": +"@babel/plugin-syntax-jsx@^7.22.5", "@babel/plugin-syntax-jsx@^7.7.2": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918" integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg== @@ -1920,6 +1941,18 @@ jest-util "^27.5.1" slash "^3.0.0" +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + "@jest/core@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626" @@ -1954,6 +1987,40 @@ slash "^3.0.0" strip-ansi "^6.0.0" +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + "@jest/environment@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74" @@ -1964,6 +2031,16 @@ "@types/node" "*" jest-mock "^27.5.1" +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + "@jest/expect-utils@^28.1.3": version "28.1.3" resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.3.tgz#58561ce5db7cd253a7edddbc051fb39dda50f525" @@ -1978,6 +2055,14 @@ dependencies: jest-get-type "^29.6.3" +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + "@jest/fake-timers@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" @@ -1990,6 +2075,18 @@ jest-mock "^27.5.1" jest-util "^27.5.1" +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + "@jest/globals@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b" @@ -1999,6 +2096,16 @@ "@jest/types" "^27.5.1" expect "^27.5.1" +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + "@jest/reporters@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04" @@ -2030,6 +2137,36 @@ terminal-link "^2.0.0" v8-to-istanbul "^8.1.0" +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + "@jest/schemas@^28.1.3": version "28.1.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-28.1.3.tgz#ad8b86a66f11f33619e3d7e1dcddd7f2d40ff905" @@ -2053,6 +2190,15 @@ graceful-fs "^4.2.9" source-map "^0.6.0" +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + "@jest/test-result@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb" @@ -2063,6 +2209,16 @@ "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + "@jest/test-sequencer@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b" @@ -2073,6 +2229,16 @@ jest-haste-map "^27.5.1" jest-runtime "^27.5.1" +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + "@jest/transform@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" @@ -2115,6 +2281,27 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + "@jest/types@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" @@ -2209,6 +2396,14 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jridgewell/trace-mapping@^0.3.18": + version "0.3.20" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" + integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" @@ -2950,6 +3145,22 @@ is-module "^1.0.0" resolve "^1.22.1" +"@rollup/plugin-replace@^5.0.2": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-5.0.4.tgz#fef548dc751d06747e8dca5b0e8e1fbf647ac7e1" + integrity sha512-E2hmRnlh09K8HGT0rOnnri9OTh+BILGr7NVJGB30S4E3cLRn3J0xjdiyOZ74adPs4NiAMgrjUMGAZNJDBgsdmQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + magic-string "^0.30.3" + +"@rollup/plugin-typescript@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-10.0.1.tgz#270b515b116ea28320e6bb62451c4767d49072d6" + integrity sha512-wBykxRLlX7EzL8BmUqMqk5zpx2onnmRMSw/l9M1sVfkJvdwfxogZQVNUM9gVMJbjRLDR5H6U0OMOrlDGmIV45A== + dependencies: + "@rollup/pluginutils" "^5.0.1" + resolve "^1.22.1" + "@rollup/plugin-typescript@^11.0.0": version "11.1.5" resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-11.1.5.tgz#039c763bf943a5921f3f42be255895e75764cb91" @@ -2958,6 +3169,31 @@ "@rollup/pluginutils" "^5.0.1" resolve "^1.22.1" +"@rollup/plugin-url@^8.0.1": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-url/-/plugin-url-8.0.2.tgz#aab4e209e9e012f65582bd99eb80b3bbdfe15afb" + integrity sha512-5yW2LP5NBEgkvIRSSEdJkmxe5cUNZKG3eenKtfJvSkxVm/xTTu7w+ayBtNwhozl1ZnTUCU0xFaRQR+cBl2H7TQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + make-dir "^3.1.0" + mime "^3.0.0" + +"@rollup/plugin-wasm@^6.1.1": + version "6.2.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-wasm/-/plugin-wasm-6.2.2.tgz#ea75fd8cc5ddba1e30bdc22e07cdbaf8d6d160bf" + integrity sha512-gpC4R1G9Ni92ZIRTexqbhX7U+9estZrbhP+9SRb0DW9xpB9g7j34r+J2hqrcW/lRI7dJaU84MxZM0Rt82tqYPQ== + dependencies: + "@rollup/pluginutils" "^5.0.2" + +"@rollup/pluginutils@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== + dependencies: + "@types/estree" "0.0.39" + estree-walker "^1.0.1" + picomatch "^2.2.2" + "@rollup/pluginutils@^5.0.1": version "5.0.4" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.4.tgz#74f808f9053d33bafec0cc98e7b835c9667d32ba" @@ -2967,6 +3203,15 @@ estree-walker "^2.0.2" picomatch "^2.3.1" +"@rollup/pluginutils@^5.0.2": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.5.tgz#bbb4c175e19ebfeeb8c132c2eea0ecb89941a66c" + integrity sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + "@sapphire/utilities@^3.11.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@sapphire/utilities/-/utilities-3.13.0.tgz#04fd73281ad4cd63c2c87ffbac3faa393d77cf95" @@ -3110,6 +3355,20 @@ dependencies: type-detect "4.0.8" +"@sinonjs/commons@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" + integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@sinonjs/fake-timers@^8.0.1": version "8.1.0" resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7" @@ -4645,6 +4904,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.2.tgz#ff02bc3dc8317cd668dfec247b750ba1f1d62453" integrity sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA== +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + "@types/estree@^0.0.51": version "0.0.51" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" @@ -4710,6 +4974,13 @@ dependencies: "@types/node" "*" +"@types/graceful-fs@^4.1.3": + version "4.1.8" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.8.tgz#417e461e4dc79d957dc3107f45fe4973b09c2915" + integrity sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw== + dependencies: + "@types/node" "*" + "@types/hast@^2.0.0": version "2.3.6" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.6.tgz#bb8b05602112a26d22868acb70c4b20984ec7086" @@ -5769,6 +6040,11 @@ ansi-regex@^6.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== +ansi-sequence-parser@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf" + integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -6193,6 +6469,19 @@ babel-jest@^27.5.1: graceful-fs "^4.2.9" slash "^3.0.0" +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + babel-loader@^8.0.0, babel-loader@^8.2.3, babel-loader@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.3.0.tgz#124936e841ba4fe8176786d6ff28add1f134d6a8" @@ -6244,6 +6533,16 @@ babel-plugin-jest-hoist@^27.5.1: "@types/babel__core" "^7.0.0" "@types/babel__traverse" "^7.0.6" +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + babel-plugin-macros@^3.0.1, babel-plugin-macros@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" @@ -6339,6 +6638,14 @@ babel-preset-jest@^27.5.1: babel-plugin-jest-hoist "^27.5.1" babel-preset-current-node-syntax "^1.0.0" +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + bail@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" @@ -6361,6 +6668,11 @@ base-x@^3.0.2, base-x@^3.0.6: dependencies: safe-buffer "^5.0.1" +base64-arraybuffer-es6@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/base64-arraybuffer-es6/-/base64-arraybuffer-es6-0.7.0.tgz#dbe1e6c87b1bf1ca2875904461a7de40f21abc86" + integrity sha512-ESyU/U1CFZDJUdr+neHRhNozeCv72Y7Vm0m1DCbjX3KBjT6eYocvAJlSk6+8+HkVwXlT1FNxhGW6q3UKAlCvvw== + base64-js@^1.0.2, base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -7124,6 +7436,17 @@ cli-boxes@^2.2.1: resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== +cli-color@~2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-2.0.3.tgz#73769ba969080629670f3f2ef69a4bf4e7cc1879" + integrity sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ== + dependencies: + d "^1.0.1" + es5-ext "^0.10.61" + es6-iterator "^2.0.3" + memoizee "^0.4.15" + timers-ext "^0.1.7" + cli-cursor@3.1.0, cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -7344,6 +7667,11 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +comlink@^4.3.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.4.1.tgz#e568b8e86410b809e8600eb2cf40c189371ef981" + integrity sha512-+1dlx0aY5Jo1vHy/tSsIGpSkN4tS9rZSW8FIhG0JH/crs9wwweswIo/POr451r7bZww3hFbPAKnTpimzL/mm4Q== + comma-separated-tokens@^1.0.0: version "1.0.8" resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" @@ -7384,6 +7712,11 @@ commander@^9.4.1: resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== +commander@~9.4.0: + version "9.4.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" + integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== + common-path-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" @@ -7567,6 +7900,11 @@ convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -7727,6 +8065,19 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -8119,6 +8470,14 @@ d3-zoom@^2.0.0: d3-selection "2" d3-transition "2" +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + damerau-levenshtein@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" @@ -8129,6 +8488,11 @@ dargs@^7.0.0: resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + data-urls@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" @@ -8223,6 +8587,11 @@ dedent@0.7.0, dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== +dedent@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" + integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== + deep-equal@^2.0.5: version "2.2.2" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.2.tgz#9b2635da569a13ba8e1cc159c2f744071b115daa" @@ -8573,6 +8942,13 @@ domelementtype@^2.0.1, domelementtype@^2.2.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== +domexception@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" + integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== + dependencies: + webidl-conversions "^4.0.2" + domexception@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" @@ -8695,6 +9071,11 @@ elliptic@^6.5.3, elliptic@^6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + emittery@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" @@ -8941,16 +9322,52 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: + version "0.10.62" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" + integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + es5-shim@^4.5.13: version "4.6.7" resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.6.7.tgz#bc67ae0fc3dd520636e0a1601cc73b450ad3e955" integrity sha512-jg21/dmlrNQI7JyyA2w7n+yifSxBng0ZralnSfVZjoCawgNTCnS+yBCyVM9DL5itm7SUnDGgv7hcq2XCZX4iRQ== +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + es6-shim@^0.35.5: version "0.35.8" resolved "https://registry.yarnpkg.com/es6-shim/-/es6-shim-0.35.8.tgz#89216f6fbf8bacba3f897c8c0e814d2a41c05fb7" integrity sha512-Twf7I2v4/1tLoIXMT8HlqaBSS5H2wQTs2wx3MNYCI8K1R1/clXyCazrcVCPm/FuO9cyV8+leEaZOWD5C253NDg== +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +es6-weak-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== + dependencies: + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -9386,6 +9803,11 @@ estree-walker@^0.6.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== +estree-walker@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== + estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" @@ -9408,6 +9830,14 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + eventemitter3@^4.0.0, eventemitter3@^4.0.1, eventemitter3@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -9518,7 +9948,7 @@ expect@^28.1.3: jest-message-util "^28.1.3" jest-util "^28.1.3" -expect@^29.0.0: +expect@^29.0.0, expect@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== @@ -9571,6 +10001,13 @@ express@^4.17.1, express@^4.17.3, express@^4.18.2: utils-merge "1.0.1" vary "~1.1.2" +ext@^1.1.2: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -9614,6 +10051,18 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +fake-indexeddb@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-4.0.2.tgz#e7a884158fa576e00f03e973b9874619947013e4" + integrity sha512-SdTwEhnakbgazc7W3WUXOJfGmhH0YfG4d+dRPOFoYDRTL6U5t8tvrmkf2W/C3W1jk2ylV7Wrnj44RASqpX/lEw== + dependencies: + realistic-structured-clone "^3.0.0" + +fake-indexeddb@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-5.0.0.tgz#c9f394d6d36db62760ad596ebec97ba3d700c95b" + integrity sha512-hGMsl73XgJAk5OtC8hFDSLUVzJ3Z1/C06YpFwI7DzCsEsmH5Mvkxplv3PK6uUL7XCYVBTzayp/4gD+cp7Qi8xQ== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -9662,7 +10111,7 @@ fast-json-parse@^1.0.3: resolved "https://registry.yarnpkg.com/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" integrity sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw== -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -9732,6 +10181,14 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + fetch-retry@^5.0.2: version "5.0.6" resolved "https://registry.yarnpkg.com/fetch-retry/-/fetch-retry-5.0.6.tgz#17d0bc90423405b7a88b74355bf364acd2a7fa56" @@ -9809,7 +10266,7 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.2.0: +finalhandler@1.2.0, finalhandler@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== @@ -10018,6 +10475,13 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -11596,6 +12060,11 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== +is-promise@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + is-reference@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" @@ -11808,6 +12277,17 @@ istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: istanbul-lib-coverage "^3.2.0" semver "^6.3.0" +istanbul-lib-instrument@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz#71e87707e8041428732518c6fb5211761753fbdf" + integrity sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + istanbul-lib-report@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" @@ -11891,6 +12371,15 @@ jest-changed-files@^27.5.1: execa "^5.0.0" throat "^6.0.1" +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + jest-circus@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc" @@ -11916,6 +12405,32 @@ jest-circus@^27.5.1: stack-utils "^2.0.3" throat "^6.0.1" +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + jest-cli@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145" @@ -11934,6 +12449,23 @@ jest-cli@^27.5.1: prompts "^2.0.1" yargs "^16.2.0" +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + jest-config@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41" @@ -11964,6 +12496,34 @@ jest-config@^27.5.1: slash "^3.0.0" strip-json-comments "^3.1.1" +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + "jest-diff@>=29.4.3 < 30", jest-diff@^29.4.1, jest-diff@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" @@ -12001,6 +12561,13 @@ jest-docblock@^27.5.1: dependencies: detect-newline "^3.0.0" +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + jest-each@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e" @@ -12012,6 +12579,17 @@ jest-each@^27.5.1: jest-util "^27.5.1" pretty-format "^27.5.1" +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + jest-environment-jsdom@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546" @@ -12037,6 +12615,18 @@ jest-environment-node@^27.5.1: jest-mock "^27.5.1" jest-util "^27.5.1" +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + jest-get-type@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" @@ -12093,6 +12683,25 @@ jest-haste-map@^27.5.1: optionalDependencies: fsevents "^2.3.2" +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + jest-jasmine2@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" @@ -12124,6 +12733,14 @@ jest-leak-detector@^27.5.1: jest-get-type "^27.5.1" pretty-format "^27.5.1" +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" @@ -12207,6 +12824,15 @@ jest-mock@^27.0.6, jest-mock@^27.5.1: "@jest/types" "^27.5.1" "@types/node" "*" +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + jest-pnp-resolver@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" @@ -12222,6 +12848,11 @@ jest-regex-util@^27.5.1: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + jest-resolve-dependencies@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" @@ -12231,6 +12862,14 @@ jest-resolve-dependencies@^27.5.1: jest-regex-util "^27.5.1" jest-snapshot "^27.5.1" +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + jest-resolve@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384" @@ -12247,6 +12886,21 @@ jest-resolve@^27.5.1: resolve.exports "^1.1.0" slash "^3.0.0" +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + jest-runner@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5" @@ -12274,6 +12928,33 @@ jest-runner@^27.5.1: source-map-support "^0.5.6" throat "^6.0.1" +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + jest-runtime@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af" @@ -12302,6 +12983,34 @@ jest-runtime@^27.5.1: slash "^3.0.0" strip-bom "^4.0.0" +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + jest-serializer@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" @@ -12346,6 +13055,32 @@ jest-snapshot@^27.5.1: pretty-format "^27.5.1" semver "^7.3.2" +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + jest-util@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" @@ -12382,7 +13117,7 @@ jest-util@^28.1.3: graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-util@^29.7.0: +jest-util@^29.0.0, jest-util@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== @@ -12406,6 +13141,18 @@ jest-validate@^27.5.1: leven "^3.1.0" pretty-format "^27.5.1" +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + jest-watcher@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2" @@ -12419,6 +13166,20 @@ jest-watcher@^27.5.1: jest-util "^27.5.1" string-length "^4.0.1" +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + jest-worker@^26.5.0, jest-worker@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" @@ -12437,6 +13198,16 @@ jest-worker@^27.0.2, jest-worker@^27.4.5, jest-worker@^27.5.1: merge-stream "^2.0.0" supports-color "^8.0.0" +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + jest@^27.1.0: version "27.5.1" resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc" @@ -12446,16 +13217,15 @@ jest@^27.1.0: import-local "^3.0.2" jest-cli "^27.5.1" -joi@^17.11.0: - version "17.11.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.11.0.tgz#aa9da753578ec7720e6f0ca2c7046996ed04fc1a" - integrity sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ== +jest@^29.5.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== dependencies: - "@hapi/hoek" "^9.0.0" - "@hapi/topo" "^5.0.0" - "@sideway/address" "^4.1.3" - "@sideway/formula" "^3.0.1" - "@sideway/pinpoint" "^2.0.0" + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" js-sha3@^0.8.0: version "0.8.0" @@ -12582,7 +13352,7 @@ json5@^1.0.1, json5@^1.0.2: dependencies: minimist "^1.2.0" -jsonc-parser@3.2.0, jsonc-parser@^3.0.0: +jsonc-parser@3.2.0, jsonc-parser@^3.0.0, jsonc-parser@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== @@ -13133,6 +13903,13 @@ lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.1.tgz#0a3be479df549cca0e5d693ac402ff19537a6b7a" integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g== +lru-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ== + dependencies: + es5-ext "~0.10.2" + lunr@^2.3.9: version "2.3.9" resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" @@ -13148,6 +13925,13 @@ lz-string@^1.5.0: resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== +magic-string@0.25.2: + version "0.25.2" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.2.tgz#139c3a729515ec55e96e69e82a11fe890a293ad9" + integrity sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg== + dependencies: + sourcemap-codec "^1.4.4" + magic-string@^0.25.3: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -13169,6 +13953,13 @@ magic-string@^0.30.2: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" +magic-string@^0.30.3: + version "0.30.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9" + integrity sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + make-dir@4.0.0, make-dir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" @@ -13268,7 +14059,7 @@ markdown-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/markdown-extensions/-/markdown-extensions-1.1.1.tgz#fea03b539faeaee9b4ef02a3769b455b189f7fc3" integrity sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q== -marked@^4.0.16: +marked@^4.0.16, marked@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== @@ -13466,6 +14257,20 @@ memfs@^3.1.2, memfs@^3.2.2, memfs@^3.4.1, memfs@^3.4.3: dependencies: fs-monkey "^1.0.4" +memoizee@^0.4.15: + version "0.4.15" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72" + integrity sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ== + dependencies: + d "^1.0.1" + es5-ext "^0.10.53" + es6-weak-map "^2.0.3" + event-emitter "^0.3.5" + is-promise "^2.2.2" + lru-queue "^0.1.0" + next-tick "^1.1.0" + timers-ext "^0.1.7" + memoizerific@^1.11.3: version "1.11.3" resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" @@ -13897,6 +14702,11 @@ mime@^2.4.4: resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -13992,7 +14802,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: +minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6, minimist@~1.2.0: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -14287,6 +15097,11 @@ nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0: resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz#26c8a3cee6cc05fbcf1e333cd2fc3e003326c0b5" integrity sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw== +next-tick@1, next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -14334,6 +15149,11 @@ node-dir@^0.1.10: dependencies: minimatch "^3.0.2" +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -14348,6 +15168,15 @@ node-fetch@^2.6.1, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-fetch@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + node-forge@^1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -14419,6 +15248,22 @@ node-releases@^2.0.13: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== +nodemon@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.0.1.tgz#affe822a2c5f21354466b2fc8ae83277d27dadc7" + integrity sha512-g9AZ7HmkhQkqXkRc20w+ZfQ73cHLbE8hnPbtaFbFtCumZsjyMhKk9LajQ07U5Ux28lvFjZ5X7HvWR1xzU8jHVw== + dependencies: + chokidar "^3.5.2" + debug "^3.2.7" + ignore-by-default "^1.0.1" + minimatch "^3.1.2" + pstree.remy "^1.1.8" + semver "^7.5.3" + simple-update-notifier "^2.0.0" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.5" + nodemon@^2.0.21: version "2.0.22" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.22.tgz#182c45c3a78da486f673d6c1702e00728daf5258" @@ -14874,7 +15719,7 @@ open@^7.0.3: is-docker "^2.0.0" is-wsl "^2.1.1" -open@^8.0.9, open@^8.4.0: +open@^8.0.0, open@^8.0.9, open@^8.4.0: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== @@ -14925,6 +15770,13 @@ os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== +ospec@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ospec/-/ospec-3.1.0.tgz#d36b8e10110f58f63a463df2390a7a73fe9579a8" + integrity sha512-+nGtjV3vlADp+UGfL51miAh/hB4awPBkQrArhcgG4trAaoA2gKt5bf9w0m9ch9zOr555cHWaCHZEDiBOkNZSxw== + dependencies: + glob "^7.1.3" + p-all@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-all/-/p-all-2.1.0.tgz#91419be56b7dee8fe4c5db875d55e0da084244a0" @@ -14970,7 +15822,7 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2: +p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -15364,7 +16216,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.0, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.0, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -16071,6 +16923,11 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== +pure-rand@^6.0.0: + version "6.0.4" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" + integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== + qr.js@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f" @@ -16538,6 +17395,15 @@ readonly-date@^1.0.0: resolved "https://registry.yarnpkg.com/readonly-date/-/readonly-date-1.0.0.tgz#5af785464d8c7d7c40b9d738cbde8c646f97dcd9" integrity sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ== +realistic-structured-clone@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/realistic-structured-clone/-/realistic-structured-clone-3.0.0.tgz#7b518049ce2dad41ac32b421cd297075b00e3e35" + integrity sha512-rOjh4nuWkAqf9PWu6JVpOWD4ndI+JHfgiZeMmujYcPi+fvILUu7g6l26TC1K5aBIp34nV+jE1cDO75EKOfHC5Q== + dependencies: + domexception "^1.0.1" + typeson "^6.1.0" + typeson-registry "^1.0.0-alpha.20" + recharts-scale@^0.4.4: version "0.4.5" resolved "https://registry.yarnpkg.com/recharts-scale/-/recharts-scale-0.4.5.tgz#0969271f14e732e642fcc5bd4ab270d6e87dd1d9" @@ -16678,6 +17544,20 @@ relateurl@^0.2.7: resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== +reload@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/reload/-/reload-3.2.1.tgz#42d43e33e327efe1348c723272c6835fe333349a" + integrity sha512-ZdM8ZSEeI72zkhh6heMEvJ0vHZoovZXcJI6Zae8CzS7o5vO/WjZsAMMr0y1+3I/fCN7y7ZxABoUwwCswcLHkjQ== + dependencies: + cli-color "~2.0.0" + commander "~9.4.0" + finalhandler "~1.2.0" + minimist "~1.2.0" + open "^8.0.0" + serve-static "~1.15.0" + supervisor "~0.12.0" + ws "~8.11.0" + remark-external-links@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/remark-external-links/-/remark-external-links-8.0.0.tgz#308de69482958b5d1cd3692bc9b725ce0240f345" @@ -16874,6 +17754,11 @@ resolve.exports@^1.1.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.1.tgz#05cfd5b3edf641571fd46fa608b610dda9ead999" integrity sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ== +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.3.2, resolve@^1.9.0: version "1.22.6" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.6.tgz#dd209739eca3aef739c626fea1b4f3c506195362" @@ -16954,6 +17839,13 @@ ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.2: hash-base "^3.0.0" inherits "^2.0.1" +rollup-plugin-base64@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-base64/-/rollup-plugin-base64-1.0.1.tgz#b3529b94d23baeb66e1e3bffd04477fa792985eb" + integrity sha512-IbdX8fjuXO/Op3hYmRPjVo0VwcSenwsQDaDTFdoe+70B5ZGoLMtr96L2yhHXCfxv7HwZVvxZqLsuWj6VwzRt3g== + dependencies: + "@rollup/pluginutils" "^3.1.0" + rollup-plugin-dts@^5.0.0, rollup-plugin-dts@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/rollup-plugin-dts/-/rollup-plugin-dts-5.3.1.tgz#c2841269a3a5cb986b7791b0328e6a178eba108f" @@ -16972,6 +17864,14 @@ rollup-plugin-inject@^3.0.0: magic-string "^0.25.3" rollup-pluginutils "^2.8.1" +rollup-plugin-modify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-modify/-/rollup-plugin-modify-3.0.0.tgz#5326e11dfec247e8bbdd9507f3da1da1e5c7818b" + integrity sha512-p/ffs0Y2jz2dEnWjq1oVC7SY37tuS+aP7whoNaQz1EAAOPg+k3vKJo8cMMWx6xpdd0NzhX4y2YF9o/NPu5YR0Q== + dependencies: + magic-string "0.25.2" + ospec "3.1.0" + rollup-plugin-node-polyfills@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz#53092a2744837164d5b8a28812ba5f3ff61109fd" @@ -16979,6 +17879,16 @@ rollup-plugin-node-polyfills@^0.2.1: dependencies: rollup-plugin-inject "^3.0.0" +rollup-plugin-polyfill@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-polyfill/-/rollup-plugin-polyfill-4.2.0.tgz#414c7ffca0557bf29a8f4e073b8eb7f4d02dac42" + integrity sha512-6eeOyn7nr2/xUOtB+MhydvqLrNKcSybGneOuWA+t8Q4rR9NQyeapzwuu5n6nX8OFfY1WI1sHconAofaC44IpuA== + +rollup-plugin-web-worker-loader@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-web-worker-loader/-/rollup-plugin-web-worker-loader-1.6.1.tgz#9d7a27575b64b0780fe4e8b3bc87470d217e485f" + integrity sha512-4QywQSz1NXFHKdyiou16mH3ijpcfLtLGOrAqvAqu1Gx+P8+zj+3gwC2BSL/VW1d+LW4nIHC8F7d7OXhs9UdR2A== + rollup-pluginutils@^2.8.1: version "2.8.2" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" @@ -16993,6 +17903,13 @@ rollup@^3.17.2, rollup@^3.2.1: optionalDependencies: fsevents "~2.3.2" +rollup@^3.9.1: + version "3.29.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" + integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw== + optionalDependencies: + fsevents "~2.3.2" + rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -17269,7 +18186,7 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.15.0: +serve-static@1.15.0, serve-static@~1.15.0: version "1.15.0" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== @@ -17399,6 +18316,16 @@ shiki@^0.10.1: vscode-oniguruma "^1.6.1" vscode-textmate "5.2.0" +shiki@^0.14.1: + version "0.14.5" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.5.tgz#375dd214e57eccb04f0daf35a32aa615861deb93" + integrity sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw== + dependencies: + ansi-sequence-parser "^1.1.0" + jsonc-parser "^3.2.0" + vscode-oniguruma "^1.7.0" + vscode-textmate "^8.0.0" + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -17457,6 +18384,13 @@ simple-update-notifier@^1.0.7: dependencies: semver "~7.0.0" +simple-update-notifier@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" + integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== + dependencies: + semver "^7.5.3" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -17575,6 +18509,14 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -17603,7 +18545,7 @@ source-map@^0.7.0, source-map@^0.7.3: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== -sourcemap-codec@^1.4.8: +sourcemap-codec@^1.4.4, sourcemap-codec@^1.4.8: version "1.4.8" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== @@ -18062,6 +19004,11 @@ stylis@4.2.0: resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== +supervisor@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/supervisor/-/supervisor-0.12.0.tgz#de7e6337015b291851c10f3538c4a7f04917ecc1" + integrity sha512-iBYeU5Or4WiiIa3+ns1DpHIiHjNNXSuYUiixKcznewwo4ImBJ8EobktaAo2csOcauhrz4SvKRTou8Z2C3W28+A== + supports-color@8.1.1, supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -18384,6 +19331,14 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +timers-ext@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" + integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== + dependencies: + es5-ext "~0.10.46" + next-tick "1" + tiny-case@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03" @@ -18560,6 +19515,20 @@ ts-jest@^27.0.5: semver "7.x" yargs-parser "20.x" +ts-jest@^29.1.0: + version "29.1.1" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.1.tgz#f58fe62c63caf7bfcc5cc6472082f79180f0815b" + integrity sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "4.x" + make-error "1.x" + semver "^7.5.3" + yargs-parser "^21.0.1" + ts-loader@^9.4.2: version "9.4.4" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.4.tgz#6ceaf4d58dcc6979f84125335904920884b7cee4" @@ -18753,6 +19722,16 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== + typed-array-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" @@ -18815,6 +19794,16 @@ typedoc@^0.22.13: minimatch "^5.1.0" shiki "^0.10.1" +typedoc@^0.24.8: + version "0.24.8" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.24.8.tgz#cce9f47ba6a8d52389f5e583716a2b3b4335b63e" + integrity sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w== + dependencies: + lunr "^2.3.9" + marked "^4.3.0" + minimatch "^9.0.0" + shiki "^0.14.1" + "typescript@>=3 < 6": version "5.2.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" @@ -18825,6 +19814,20 @@ typescript@^4.6.2, typescript@^4.8.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +typeson-registry@^1.0.0-alpha.20: + version "1.0.0-alpha.39" + resolved "https://registry.yarnpkg.com/typeson-registry/-/typeson-registry-1.0.0-alpha.39.tgz#9e0f5aabd5eebfcffd65a796487541196f4b1211" + integrity sha512-NeGDEquhw+yfwNhguLPcZ9Oj0fzbADiX4R0WxvoY8nGhy98IbzQy1sezjoEFWOywOboj/DWehI+/aUlRVrJnnw== + dependencies: + base64-arraybuffer-es6 "^0.7.0" + typeson "^6.0.0" + whatwg-url "^8.4.0" + +typeson@^6.0.0, typeson@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/typeson/-/typeson-6.1.0.tgz#5b2a53705a5f58ff4d6f82f965917cabd0d7448b" + integrity sha512-6FTtyGr8ldU0pfbvW/eOZrEtEkczHRUtduBnA90Jh9kMPCiFNnXIon3vF41N0S4tV1HHQt4Hk1j4srpESziCaA== + uglify-js@^3.1.4: version "3.17.4" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" @@ -19272,6 +20275,15 @@ v8-to-istanbul@^9.0.0: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" +v8-to-istanbul@^9.0.1: + version "9.1.3" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz#ea456604101cd18005ac2cae3cdd1aa058a6306b" + integrity sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + validate-npm-package-license@3.0.4, validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -19377,7 +20389,7 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== -vscode-oniguruma@^1.6.1: +vscode-oniguruma@^1.6.1, vscode-oniguruma@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA== @@ -19387,6 +20399,11 @@ vscode-textmate@5.2.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== +vscode-textmate@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d" + integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg== + w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" @@ -19401,7 +20418,7 @@ w3c-xmlserializer@^2.0.0: dependencies: xml-name-validator "^3.0.0" -walker@^1.0.7, walker@~1.0.5: +walker@^1.0.7, walker@^1.0.8, walker@~1.0.5: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== @@ -19453,11 +20470,21 @@ web-namespaces@^1.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== +web-streams-polyfill@^3.0.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + webidl-conversions@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" @@ -19711,7 +20738,7 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -whatwg-url@^8.0.0, whatwg-url@^8.5.0: +whatwg-url@^8.0.0, whatwg-url@^8.4.0, whatwg-url@^8.5.0: version "8.7.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== @@ -19893,6 +20920,14 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + write-json-file@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-3.2.0.tgz#65bbdc9ecd8a1458e15952770ccbadfcff5fe62a" @@ -19919,11 +20954,16 @@ ws@^7, ws@^7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -ws@^8.13.0, ws@^8.2.3: +ws@^8.13.0, ws@^8.14.2, ws@^8.2.3: version "8.14.2" resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== +ws@~8.11.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" + integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== + x-default-browser@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/x-default-browser/-/x-default-browser-0.4.0.tgz#70cf0da85da7c0ab5cb0f15a897f2322a6bdd481" @@ -20024,7 +21064,7 @@ yargs-parser@20.x, yargs-parser@^20.2.2, yargs-parser@^20.2.3, yargs-parser@^20. resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs-parser@21.1.1, yargs-parser@^21.1.1: +yargs-parser@21.1.1, yargs-parser@^21.0.1, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== @@ -20052,7 +21092,7 @@ yargs@16.2.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.6.2: +yargs@^17.3.1, yargs@^17.6.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From d941d9257101574564895bb714409baf31ef6801 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Wed, 1 Nov 2023 10:58:41 +0100 Subject: [PATCH 164/236] add --with-exit-policy flag --- documentation/operators/src/faq/smoosh-faq.md | 8 ++++---- .../operators/src/nodes/gateway-setup.md | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index 2950b7df54..e0fa8bc8f3 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -46,12 +46,12 @@ We created an [entire page](../legal/exit-gateway.md) about the technical and le The operators running Gateways would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short [*allowed.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a more permissive setup. An [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients. -### How will the design be implemented? +### How will the Exit policy be implemented? -The progression will have three steps: +The progression of exit policy on Gateways will have three steps: -1. By default the [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) filtering will be disabled and the current [*allowed.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) filtering is going to continue be used. This is to prevent operators getting surprised by upgrading their gateways/network requesters and suddenly be widely open to the internet. To enable the new exit policy, operators must use `--with-exit-policy` flag or modify the *config.toml* file. ✅ -2. Relatively soon the exit policy will become the default. To disable this exit policy, operators must use `--disable-network-requester` flag. +1. By default the [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) filtering will be disabled and the current [*allowed.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) filtering is going to continue be used. This is to prevent operators getting surprised by upgrading their Gateways (or Network requesters) and suddenly be widely open to the internet. To enable the new exit policy, operators must use `--with-exit-policy` flag or modify the *config.toml* file. ✅ +2. Relatively soon the exit policy will be part of the Gateway setup by default. To disable this exit policy, operators must use `--disable-exit-policy` flag. 3. Further down the line, it will be the only option. Then the *allowed.list* will be completely removed. Keep in mind this only relates to changes happening on Gateway and Network Requester side. Whether this will be optional or mandatory depends on the chosen [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators). diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 0fea8bba90..9d4a0d673a 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -50,23 +50,29 @@ You can also check the various arguments required for individual commands with: ## Initialising your Gateway -As Nym developers build towards [Exit Gateway](../legal/exit-gateway.md) functionality, operators can now run their `nym-gateway` binary with in-build Network requester. Considering the plan to [*smoosh*](../faq/smoosh-faq.md) all the nodes into one binary and have wide opened Exit Gateways, we recommend this setup, instead of operating two separate binaries. +As Nym developers build towards [Exit Gateway](../legal/exit-gateway.md) functionality, operators can now run their `nym-gateway` binary with in-build Network requester and include the our new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). Considering the plan to [*smoosh*](../faq/smoosh-faq.md) all the nodes into one binary and have wide opened Exit Gateways, we recommend this setup, instead of operating two separate binaries. +```admonish warning +Before you start an Exit Gateway, read our [Operators Legal Forum](../legal/exit-gateway.md) page and [*Project Smoosh FAQ*](../faq/smoosh-faq.md). +``` + +```admonish info +There has been an ongoing development with dynamic upgrades. Follow the status of the Project Smoosh [changes](../faq/smoosh-faq.md#what-are-the-changes) and the progression state of Exit policy [implementation](../faq/smoosh-faq.html#how-will-the-exit-policy-be-implemented) to be up to date with the current design. +``` ### Initialising Exit Gateway -An operator can initialise the Exit Gateway functionality by: +An operator can initialise the Exit Gateway functionality by adding Network requester with the new exit policy option: ``` -./nym-gateway init --id --host $(curl icanhazip.com) --with-network-requester +./nym-gateway init --id --host $(curl icanhazip.com) --with-network-requester --with-exit-policy ``` -If we follow the previous example with `` chosen `superexitgateway`, adding the `--with-network-requester` flag, the outcome will be: - +If we follow the previous example with `` chosen `superexitgateway`, adding the `--with-network-requester` and `--with-exit-policy` flags, the outcome will be: ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ From bd50119152c3b3e7f3b4f1a28d4cd16b23d3e713 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Wed, 1 Nov 2023 11:00:01 +0100 Subject: [PATCH 165/236] change --host -> 146.70.170.3 --- documentation/operators/src/nodes/gateway-setup.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 9d4a0d673a..fcfb37bf46 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -65,14 +65,14 @@ There has been an ongoing development with dynamic upgrades. Follow the status o An operator can initialise the Exit Gateway functionality by adding Network requester with the new exit policy option: ``` -./nym-gateway init --id --host $(curl icanhazip.com) --with-network-requester --with-exit-policy +./nym-gateway init --id --host $(curl ifcfg.me) --with-network-requester --with-exit-policy ``` If we follow the previous example with `` chosen `superexitgateway`, adding the `--with-network-requester` and `--with-exit-policy` flags, the outcome will be: ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ @@ -146,16 +146,16 @@ To check available configuration options use: The following command returns a gateway on your current IP with the `` of `supergateway`: ``` -./nym-gateway init --id supergateway --host $(curl icanhazip.com) +./nym-gateway init --id supergateway --host $(curl ifcfg.me) ``` ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ -The `$(curl icanhazip.com)` command above returns your IP automatically using an external service. Alternatively, you can enter your IP manually if you wish. If you do this, remember to enter your IP **without** any port information. +The `$(curl ifcfg.me)` command above returns your IP automatically using an external service. Alternatively, you can enter your IP manually if you wish. If you do this, remember to enter your IP **without** any port information. ### Bonding your gateway From 5406396c3cbf2ece7c1bf885bd5f8c0bf6bf6770 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Wed, 1 Nov 2023 11:00:43 +0100 Subject: [PATCH 166/236] syntax fix --- documentation/operators/src/faq/smoosh-faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index e0fa8bc8f3..99f31661a8 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -24,7 +24,7 @@ As we shared in our blog post article [*What does it take to build the wolds mos Project smoosh will have three steps: 1. Combine the `gateway` and `network-requester` into one binary ✅ -2. Create [exit gateway](../legal/exit-gateway.md): Take the gateway binary including network requester combined in \#1 and switch from [*allowed.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) ✅ +2. Create [Exit Gateway](../legal/exit-gateway.md): Take the gateway binary including network requester combined in \#1 and switch from [*allowed.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) ✅ 3. Combine all the nodes in the Nym Mixnet into one binary, that is `mixnode`, `gateway` (entry and exit) and `network-requester`. These three steps will be staggered over time - period of several months, and will be implemented one by one with enough time to take in feedback and fix bugs in between. From 07037341c5abbc5e00ab0be5235f30eb0e441f6f Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Wed, 1 Nov 2023 11:06:44 +0100 Subject: [PATCH 167/236] change --host to -4 https://ifconfig.me --- documentation/operators/src/nodes/gateway-setup.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index fcfb37bf46..179f0df6f2 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -65,14 +65,14 @@ There has been an ongoing development with dynamic upgrades. Follow the status o An operator can initialise the Exit Gateway functionality by adding Network requester with the new exit policy option: ``` -./nym-gateway init --id --host $(curl ifcfg.me) --with-network-requester --with-exit-policy +./nym-gateway init --id --host $(curl -4 https://ifconfig.me) --with-network-requester --with-exit-policy ``` If we follow the previous example with `` chosen `superexitgateway`, adding the `--with-network-requester` and `--with-exit-policy` flags, the outcome will be: ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ @@ -146,16 +146,16 @@ To check available configuration options use: The following command returns a gateway on your current IP with the `` of `supergateway`: ``` -./nym-gateway init --id supergateway --host $(curl ifcfg.me) +./nym-gateway init --id supergateway --host $(curl -4 https://ifconfig.me) ``` ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ -The `$(curl ifcfg.me)` command above returns your IP automatically using an external service. Alternatively, you can enter your IP manually if you wish. If you do this, remember to enter your IP **without** any port information. +The `$(curl -4 https://ifconfig.me)` command above returns your IP automatically using an external service. Alternatively, you can enter your IP manually if you wish. If you do this, remember to enter your IP **without** any port information. ### Bonding your gateway From 1370192823b2d528adcaf25f970b956f280d5ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 1 Nov 2023 10:31:59 +0000 Subject: [PATCH 168/236] print info on exit policy on embedded NR init (#4086) --- common/types/src/gateway.rs | 2 ++ gateway/src/commands/helpers.rs | 1 + gateway/src/node/helpers.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/common/types/src/gateway.rs b/common/types/src/gateway.rs index 3b546320b6..750871e881 100644 --- a/common/types/src/gateway.rs +++ b/common/types/src/gateway.rs @@ -119,6 +119,7 @@ pub struct GatewayNetworkRequesterDetails { pub encryption_key: String, pub open_proxy: bool, + pub exit_policy: bool, pub enabled_statistics: bool, // just a convenience wrapper around all the keys @@ -140,6 +141,7 @@ impl fmt::Display for GatewayNetworkRequesterDetails { writeln!(f, "\taddress: {}", self.address)?; writeln!(f, "\tuses open proxy: {}", self.open_proxy)?; + writeln!(f, "\tuses exit policy: {}", self.exit_policy)?; writeln!(f, "\tsends statistics: {}", self.enabled_statistics)?; writeln!(f, "\tallow list path: {}", self.allow_list_path)?; diff --git a/gateway/src/commands/helpers.rs b/gateway/src/commands/helpers.rs index f4ef8640e9..23ebd77afd 100644 --- a/gateway/src/commands/helpers.rs +++ b/gateway/src/commands/helpers.rs @@ -302,6 +302,7 @@ pub(crate) async fn initialise_local_network_requester( enabled: gateway_config.network_requester.enabled, identity_key: address.identity().to_string(), encryption_key: address.encryption_key().to_string(), + exit_policy: !nr_cfg.network_requester.use_deprecated_allow_list, open_proxy: nr_cfg.network_requester.open_proxy, enabled_statistics: nr_cfg.network_requester.enabled_statistics, address: address.to_string(), diff --git a/gateway/src/node/helpers.rs b/gateway/src/node/helpers.rs index 0b8fc9c994..d3cf2fdae4 100644 --- a/gateway/src/node/helpers.rs +++ b/gateway/src/node/helpers.rs @@ -60,6 +60,7 @@ pub(crate) fn node_details(config: &Config) -> Result Date: Tue, 31 Oct 2023 20:50:24 +0100 Subject: [PATCH 169/236] ci: rename to ci-binary-config-checker --- .../{ci-binary-checker.yml => ci-binary-config-checker.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{ci-binary-checker.yml => ci-binary-config-checker.yml} (96%) diff --git a/.github/workflows/ci-binary-checker.yml b/.github/workflows/ci-binary-config-checker.yml similarity index 96% rename from .github/workflows/ci-binary-checker.yml rename to .github/workflows/ci-binary-config-checker.yml index ec08504816..07e14d6738 100644 --- a/.github/workflows/ci-binary-checker.yml +++ b/.github/workflows/ci-binary-config-checker.yml @@ -1,4 +1,4 @@ -name: Run config checks on all binaries +name: ci-binary-config-checker on: workflow_dispatch: From 143036c2a2579ec5215e962462032e44fd8ae676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 21:08:14 +0100 Subject: [PATCH 170/236] ci: rename cd-docs --- .github/workflows/cd-docs.yml | 4 ++-- .github/workflows/ci-docs.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cd-docs.yml b/.github/workflows/cd-docs.yml index 2e7d024f60..df0ae9dc66 100644 --- a/.github/workflows/cd-docs.yml +++ b/.github/workflows/cd-docs.yml @@ -1,4 +1,4 @@ -name: CD docs +name: cd-docs on: workflow_dispatch: @@ -26,7 +26,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --workspace --release --all + args: --workspace --release - name: Install mdbook run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4.33" mdbook) - name: Install mdbook plugins diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index b503516e70..3bcf0a2679 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -26,7 +26,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --workspace --release --all + args: --workspace --release - name: Install mdbook run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4.35" mdbook) - name: Install mdbook plugins From 241169140e6bea4ab93dfc164f473c1db279a311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 20:55:45 +0100 Subject: [PATCH 171/236] ci: move nightly to ubuntu-20.04 --- .github/workflows/nightly-build.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 9185c9f304..0e5492539c 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -4,26 +4,26 @@ on: workflow_dispatch: schedule: - cron: '14 1 * * *' + jobs: build: strategy: fail-fast: false matrix: rust: [stable, beta] - os: [custom-linux, windows10, custom-runner-mac-m1] + os: [ubuntu-20.04, windows10, custom-runner-mac-m1] runs-on: ${{ matrix.os }} env: CARGO_TERM_COLOR: always continue-on-error: true steps: - - name: Install Dependencies (Linux) - run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler - continue-on-error: true - if: matrix.os == 'custom-linux' - - name: Check out repository code uses: actions/checkout@v3 + - name: Install Dependencies (Linux) + run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler + if: matrix.os == 'ubuntu-20.04' + - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: @@ -42,31 +42,31 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --workspace + args: --release --workspace - name: Build examples uses: actions-rs/cargo@v1 with: command: build - args: --workspace --examples + args: --release --workspace --examples - name: Run unit tests uses: actions-rs/cargo@v1 with: command: test - args: --workspace + args: --release --workspace - name: Run slow unit tests uses: actions-rs/cargo@v1 with: command: test - args: --workspace -- --ignored + args: --release --workspace -- --ignored - name: Clippy uses: actions-rs/cargo@v1 with: command: clippy - args: --workspace --all-targets -- -D warnings + args: --release --workspace --all-targets -- -D warnings notification: needs: build From f3442c6964f1125e2ff3f52af0765a79aea180c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 21:17:13 +0100 Subject: [PATCH 172/236] ci: sort out nightly wallet build --- .../workflows/nightly-nym-wallet-build.yml | 30 +++++-------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/.github/workflows/nightly-nym-wallet-build.yml b/.github/workflows/nightly-nym-wallet-build.yml index f4d32bd396..1cdb70def2 100644 --- a/.github/workflows/nightly-nym-wallet-build.yml +++ b/.github/workflows/nightly-nym-wallet-build.yml @@ -5,27 +5,24 @@ on: schedule: - cron: '14 1 * * *' -defaults: - run: - working-directory: nym-wallet - jobs: build: strategy: fail-fast: false matrix: - os: [custom-ubuntu-20.04, macos-latest, windows10] + os: [ubuntu-20.04, macos-latest, windows10] runs-on: ${{ matrix.os }} env: CARGO_TERM_COLOR: always + MANIFEST_PATH: --manifest-path nym-wallet/Cargo.toml continue-on-error: true steps: - name: Check out repository code uses: actions/checkout@v3 - name: Install Dependencies (Linux) - run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler - if: matrix.os == 'custom-ubuntu-20.04' + run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools + if: matrix.os == 'ubuntu-20.04' - name: Install rust toolchain uses: actions-rs/toolchain@v1 @@ -35,40 +32,29 @@ jobs: override: true components: rustfmt, clippy - - name: Install Protoc - uses: arduino/setup-protoc@v2 - if: matrix.os == 'macos-latest' - - name: Check formatting uses: actions-rs/cargo@v1 with: command: fmt - args: --all -- --check + args: ${{ env.MANIFEST_PATH }} --all -- --check - name: Build uses: actions-rs/cargo@v1 with: command: build - args: --workspace + args: ${{ env.MANIFEST_PATH }} --release --workspace - name: Unit tests uses: actions-rs/cargo@v1 with: command: test - args: --workspace - - - name: Annotate with clippy warnings - uses: actions-rs/clippy-check@v1 - continue-on-error: true - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --workspace + args: ${{ env.MANIFEST_PATH }} --workspace - name: Clippy uses: actions-rs/cargo@v1 with: command: clippy - args: --workspace --all-targets -- -D warnings + args: ${{ env.MANIFEST_PATH }} --workspace --all-targets -- -D warnings notification: needs: build From 6e9a588c1affe0e5b124021a56af8d7718bd8639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 21:53:52 +0100 Subject: [PATCH 173/236] ci: nightly-build sed debug = false --- .github/workflows/nightly-build.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 0e5492539c..9572abfa77 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -50,23 +50,28 @@ jobs: command: build args: --release --workspace --examples + - name: Set debug to false + run: | + sed -i.bak 's/\[profile.dev\]/\[profile.dev\]\ndebug = false/' Cargo.toml + git diff + - name: Run unit tests uses: actions-rs/cargo@v1 with: command: test - args: --release --workspace + args: --workspace - name: Run slow unit tests uses: actions-rs/cargo@v1 with: command: test - args: --release --workspace -- --ignored + args: --workspace -- --ignored - name: Clippy uses: actions-rs/cargo@v1 with: command: clippy - args: --release --workspace --all-targets -- -D warnings + args: --workspace --all-targets -- -D warnings notification: needs: build From f28e0b529e8b87d38372cd99fe37cfd16a73413f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 22:05:37 +0100 Subject: [PATCH 174/236] ci: use macos-latest in nightly-build --- .github/workflows/nightly-build.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 9572abfa77..3365011f38 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -11,7 +11,7 @@ jobs: fail-fast: false matrix: rust: [stable, beta] - os: [ubuntu-20.04, windows10, custom-runner-mac-m1] + os: [ubuntu-20.04, windows10, macos-latest] runs-on: ${{ matrix.os }} env: CARGO_TERM_COLOR: always @@ -32,6 +32,12 @@ jobs: override: true components: rustfmt, clippy + - name: Install Protoc + uses: arduino/setup-protoc@v2 + if: matrix.os == 'macos-latest' + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Check formatting uses: actions-rs/cargo@v1 with: From 7da2ce362dbffc4f2e3bb92fe7e69af18efd7e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 31 Oct 2023 21:32:54 +0100 Subject: [PATCH 175/236] ci: create nightly-nym-connect-desktop-build --- .../workflows/ci-nym-connect-desktop-rust.yml | 12 +-- .../nightly-nym-connect-desktop-build.yml | 92 +++++++++++++++++++ 2 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/nightly-nym-connect-desktop-build.yml diff --git a/.github/workflows/ci-nym-connect-desktop-rust.yml b/.github/workflows/ci-nym-connect-desktop-rust.yml index e5e56b8f43..77d5a0607b 100644 --- a/.github/workflows/ci-nym-connect-desktop-rust.yml +++ b/.github/workflows/ci-nym-connect-desktop-rust.yml @@ -33,6 +33,12 @@ jobs: override: true components: rustfmt, clippy + - name: Check formatting + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --manifest-path nym-connect/desktop/Cargo.toml --all -- --check + - name: Build all binaries uses: actions-rs/cargo@v1 with: @@ -45,12 +51,6 @@ jobs: command: test args: --manifest-path nym-connect/desktop/Cargo.toml --workspace - - name: Check formatting - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --manifest-path nym-connect/desktop/Cargo.toml --all -- --check - - uses: actions-rs/clippy-check@v1 name: Clippy checks continue-on-error: true diff --git a/.github/workflows/nightly-nym-connect-desktop-build.yml b/.github/workflows/nightly-nym-connect-desktop-build.yml new file mode 100644 index 0000000000..a0705c6e1c --- /dev/null +++ b/.github/workflows/nightly-nym-connect-desktop-build.yml @@ -0,0 +1,92 @@ +name: nightly-nym-wallet-build + +on: + workflow_dispatch: + schedule: + - cron: '14 1 * * *' + +jobs: + build: + strategy: + fail-fast: false + matrix: + os: [ubuntu-20.04, macos-latest, windows10] + runs-on: ${{ matrix.os }} + env: + CARGO_TERM_COLOR: always + MANIFEST_PATH: --manifest-path nym-connect/desktop/Cargo.toml + continue-on-error: true + steps: + - name: Check out repository code + uses: actions/checkout@v3 + + - name: Install Dependencies (Linux) + run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools + if: matrix.os == 'ubuntu-20.04' + + - name: Install rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + components: rustfmt, clippy + + - name: Check formatting + uses: actions-rs/cargo@v1 + with: + command: fmt + args: ${{ env.MANIFEST_PATH }} --all -- --check + + - name: Build + uses: actions-rs/cargo@v1 + with: + command: build + args: ${{ env.MANIFEST_PATH }} --release --workspace + + - name: Unit tests + uses: actions-rs/cargo@v1 + with: + command: test + args: ${{ env.MANIFEST_PATH }} --workspace + + - name: Clippy + uses: actions-rs/cargo@v1 + with: + command: clippy + args: ${{ env.MANIFEST_PATH }} --workspace --all-targets -- -D warnings + + notification: + needs: build + runs-on: custom-linux + steps: + - name: Collect jobs status + uses: technote-space/workflow-conclusion-action@v2 + - name: Check out repository code + uses: actions/checkout@v3 + - name: install npm + uses: actions/setup-node@v3 + if: env.WORKFLOW_CONCLUSION == 'failure' + with: + node-version: 18 + - name: Matrix - Node Install + if: env.WORKFLOW_CONCLUSION == 'failure' + run: npm install + working-directory: .github/workflows/support-files + - name: Matrix - Send Notification + if: env.WORKFLOW_CONCLUSION == 'failure' + env: + NYM_NOTIFICATION_KIND: nightly + NYM_PROJECT_NAME: "nym-connect-desktop-nightly-build" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}" + GIT_BRANCH: "${GITHUB_REF##*/}" + IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}" + MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}" + MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_NIGHTLY }}" + MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}" + MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}" + MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}" + uses: docker://keybaseio/client:stable-node + with: + args: .github/workflows/support-files/notifications/entry_point.sh From 73fe7ebec7d40a9e4e34b6f5054841a79c97c4a8 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Wed, 1 Nov 2023 12:00:16 +0100 Subject: [PATCH 176/236] finish exit gateway setup --- .../operators/src/nodes/gateway-setup.md | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 179f0df6f2..401323b6ff 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -65,7 +65,7 @@ There has been an ongoing development with dynamic upgrades. Follow the status o An operator can initialise the Exit Gateway functionality by adding Network requester with the new exit policy option: ``` -./nym-gateway init --id --host $(curl -4 https://ifconfig.me) --with-network-requester --with-exit-policy +./nym-gateway init --id --host $(curl -4 https://ifconfig.me) --with-network-requester --with-exit-policy true ``` If we follow the previous example with `` chosen `superexitgateway`, adding the `--with-network-requester` and `--with-exit-policy` flags, the outcome will be: @@ -76,13 +76,13 @@ If we follow the previous example with `` chosen `superexitgateway`, adding ``` ~~~ -You can see that the printed information besides *identity* and *sphinx keys* also includes a long string called *address*. This is the address to be provided to your local [socks5 client](https://nymtech.net/docs/clients/socks5-client.html) as a `--provider` if you wish to connect to your own exit gateway. +You can see that the printed information besides *identity* and *sphinx keys* also includes a long string called *address*. This is the address to be provided to your local [socks5 client](https://nymtech.net/docs/clients/socks5-client.html) as a `--provider` if you wish to connect to your own Exit Gateway. Additionally -#### Add Network requester to existing Gateway +#### Add Network requester to an existing Gateway -If you already run a gateway and got it [upgraded](./maintenance.md#upgrading-your-node) to the [newest version](./gateway-setup.md#current-version), you can easily change its functionality to exit gateway. Pause the gateway and run a command `setup-network-requester`. +If you already [upgraded](./maintenance.md#upgrading-your-node) your Gateway to the [newest version](./gateway-setup.md#current-version) and initialised without a Network requester, you can easily change its functionality to Exit Gateway with a command `setup-network-requester`. See the options: @@ -96,19 +96,28 @@ See the options: ``` ~~~ -Run with `--enabled true` flag choosing `` as `supergateway`: +To setup Exit Gateway functionality with our new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) add a flag `--with-exit-policy true`. ``` -./nym-gateway setup-network-requester --enabled true --id supergateway +./nym-gateway setup-network-requester --enabled true --with-exit-policy true --id ``` +Example choosing `` as `exit-gateway`: + +``` +./nym-gateway setup-network-requester --enabled true --with-exit-policy true --id exit-gateway +``` +(In the following output we first initialised the Gateway without the functionality and then ran the command above.) + ~~~admonish example collapsible=true title="Console output" ``` - + + + ``` ~~~ -In case there are any problems, you can also change it manually by editing the gateway config stored in `/home/user/.nym/gateways//config/config.toml` where the line under `[network_requester]` needs to be edited from `false` to `true`. +In case there are any unexpected problems, you can also change it manually by editing the Gateway config stored in `/home/user/.nym/gateways//config/config.toml` where the line under `[network_requester]` needs to be edited from `false` to `true`. ``` [network_requester] @@ -116,17 +125,15 @@ In case there are any problems, you can also change it manually by editing the g enabled = true ``` -Save, exit and restart your gateway. Now it is a post-smooshed exit gateway. +Save, exit and restart your gateway. Now you are an operator of post-smooshed Exit gateway. All information about network requester part of your exit gateway is in `/home/user/.nym/gateways/snus/config/network_requester_config.toml`. +For now you can run Gateway without Network requester or with and without the new exit policy. This will soon change as we inform in our [Project Smoosh FAQ](../faq/smoosh-faq.html#how-will-the-exit-policy-be-implemented). + To read more about the configuration like whitelisted outbound requesters in `allowed.list` and other useful information, see the page [*Network Requester Whitelist*](network-requester-setup.md#using-your-network-requester). -```admonish info -Before you bond and run your gateway, please make sure the [firewall configuration](./maintenance.md#configure-your-firewall) is setup so your gateway can be reached from the outside. -``` - #### Initialising Gateway without Network requester In case you don't want to run your Gateway with the Exit Gateway functionality, you still can run a simple Gateway. @@ -143,15 +150,15 @@ To check available configuration options use: ``` ~~~ -The following command returns a gateway on your current IP with the `` of `supergateway`: +The following command returns a gateway on your current IP with the `` of `simple-gateway`: ``` -./nym-gateway init --id supergateway --host $(curl -4 https://ifconfig.me) +./nym-gateway init --id simple-gateway --host $(curl -4 https://ifconfig.me) ``` ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ @@ -160,6 +167,10 @@ The `$(curl -4 https://ifconfig.me)` command above returns your IP automatically ### Bonding your gateway +```admonish info +Before you bond and run your Gateway, please make sure the [firewall configuration](./maintenance.md#configure-your-firewall) is setup so your gateway can be reached from the outside. +``` + #### Via the Desktop wallet You can bond your gateway via the Desktop wallet. @@ -187,7 +198,7 @@ It will look something like this: |_| |_|\__, |_| |_| |_| |___/ - (nym-gateway - version v1.1.29) + (nym-gateway - version v1.1.31) >>> attempting to sign 2Mf8xYytgEeyJke9LA7TjhHoGQWNBEfgHZtTyy2krFJfGHSiqy7FLgTnauSkQepCZTqKN5Yfi34JQCuog9k6FGA2EjsdpNGAWHZiuUGDipyJ6UksNKRxnFKhYW7ri4MRduyZwbR98y5fQMLAwHne1Tjm9cXYCn8McfigNt77WAYwBk5bRRKmC34BJMmWcAxphcLES2v9RdSR68tkHSpy2C8STfdmAQs3tZg8bJS5Qa8pQdqx14TnfQAPLk3QYCynfUJvgcQTrg29aqCasceGRpKdQ3Tbn81MLXAGAs7JLBbiMEAhCezAr2kEN8kET1q54zXtKz6znTPgeTZoSbP8rzf4k2JKHZYWrHYF9JriXepuZTnyxAKAxvGFPBk8Z6KAQi33NRQkwd7MPyttatHna6kG9x7knffV6ebGzgRBf7NV27LurH8x4L1uUXwm1v1UYCA1WSBQ9Pp2JW69k5v5v7G9gBy8RUcZnMbeL26Qqb8WkuGcmuHhaFfoqSfV7PRHPpPT4M8uRqUyR4bjUtSJJM1yh6QSeZk9BEazzoJqPeYeGoiFDZ3LMj2jesbJweQR4caaYuRczK92UGSSqu9zBKmE45a @@ -209,7 +220,7 @@ It will look something like this: * Your gateway is now bonded. -> You are asked to `sign` a transaction on bonding so that the mixnet smart contract is able to map your nym address to your node. This allows us to create a nonce for each account and defend against replay attacks. +> You are asked to `sign` a transaction on bonding so that the Mixnet smart contract is able to map your Nym address to your node. This allows us to create a nonce for each account and defend against replay attacks. #### Via the CLI (power users) If you want to bond your mix node via the CLI, then check out the [relevant section in the Nym CLI](https://nymtech.net/docs/tools/nym-cli.html#bond-a-mix-node) docs. From 784ee5ace8a04b4fdb6c59b5a3a541add80359ff Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Wed, 1 Nov 2023 13:28:49 +0100 Subject: [PATCH 177/236] Revert "Add hack for working with old nym gateways" This reverts commit 7129de4373d4b62e06a33dc877b7d605ac074033. To avoid breaking wss --- .../client-core/src/client/topology_control/nym_api_provider.rs | 2 +- common/client-core/src/init/helpers.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/client-core/src/client/topology_control/nym_api_provider.rs b/common/client-core/src/client/topology_control/nym_api_provider.rs index 5de16663de..824294793b 100644 --- a/common/client-core/src/client/topology_control/nym_api_provider.rs +++ b/common/client-core/src/client/topology_control/nym_api_provider.rs @@ -69,7 +69,7 @@ impl NymApiTopologyProvider { Ok(mixes) => mixes, }; - let gateways = match self.validator_client.get_cached_gateways().await { + let gateways = match self.validator_client.get_cached_described_gateways().await { Err(err) => { error!("failed to get network gateways - {err}"); return None; diff --git a/common/client-core/src/init/helpers.rs b/common/client-core/src/init/helpers.rs index b253ed44cf..4b50f0864b 100644 --- a/common/client-core/src/init/helpers.rs +++ b/common/client-core/src/init/helpers.rs @@ -67,7 +67,7 @@ pub async fn current_gateways( log::trace!("Fetching list of gateways from: {nym_api}"); - let gateways = client.get_cached_gateways().await?; + let gateways = client.get_cached_described_gateways().await?; let valid_gateways = gateways .into_iter() .filter_map(|gateway| gateway.try_into().ok()) From 610f7e88ca6f643005d93e6cb9de8ac798a91d7f Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Wed, 1 Nov 2023 14:44:51 +0100 Subject: [PATCH 178/236] add example setup-network-requester --- .../operators/src/nodes/gateway-setup.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 401323b6ff..c6a85ec792 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -102,22 +102,22 @@ To setup Exit Gateway functionality with our new [exit policy](https://nymtech.n ./nym-gateway setup-network-requester --enabled true --with-exit-policy true --id ``` -Example choosing `` as `exit-gateway`: +Say we have a gateway with `` as `new-gateway`, originally initialised and ran without the Exit Gateway functionality. To change the setup, run: + ``` -./nym-gateway setup-network-requester --enabled true --with-exit-policy true --id exit-gateway +./nym-gateway setup-network-requester --enabled true --with-exit-policy true --id new-gateway ``` -(In the following output we first initialised the Gateway without the functionality and then ran the command above.) ~~~admonish example collapsible=true title="Console output" ``` - - - + + + ``` ~~~ -In case there are any unexpected problems, you can also change it manually by editing the Gateway config stored in `/home/user/.nym/gateways//config/config.toml` where the line under `[network_requester]` needs to be edited from `false` to `true`. +In case there are any unexpected problems, you can also change it manually by editing the Gateway config file stored in `/home/user/.nym/gateways//config/config.toml` where the line under `[network_requester]` needs to be edited from `false` to `true`. ``` [network_requester] @@ -127,7 +127,7 @@ enabled = true Save, exit and restart your gateway. Now you are an operator of post-smooshed Exit gateway. -All information about network requester part of your exit gateway is in `/home/user/.nym/gateways/snus/config/network_requester_config.toml`. +All information about network requester part of your exit gateway is in `/home/user/.nym/gateways//config/network_requester_config.toml`. For now you can run Gateway without Network requester or with and without the new exit policy. This will soon change as we inform in our [Project Smoosh FAQ](../faq/smoosh-faq.html#how-will-the-exit-policy-be-implemented). From 4262e2e2f68ca7723193e1ca2f34f06d8914bc62 Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Wed, 1 Nov 2023 15:57:23 +0100 Subject: [PATCH 179/236] fix: adding some polyfills to nodejs-client and mix-fetch During the merge of the nodejs-wasm-client there seems to be some losses, this commit makes nodejs-client and the nodejs mix-fetch work with the internal tools. Still looking into Tommys qa feedback. --- .../packages/mix-fetch-node/internal/index.js | 54 +++++++++++++++++++ .../mix-fetch-node/rollup-worker.config.mjs | 14 ++--- .../nodejs-client/rollup-cjs.config.mjs | 2 +- .../nodejs-client/rollup-worker.config.mjs | 6 +++ .../packages/nodejs-client/src/polyfill.ts | 4 +- yarn.lock | 11 ++++ 6 files changed, 79 insertions(+), 12 deletions(-) create mode 100644 sdk/typescript/packages/mix-fetch-node/internal/index.js diff --git a/sdk/typescript/packages/mix-fetch-node/internal/index.js b/sdk/typescript/packages/mix-fetch-node/internal/index.js new file mode 100644 index 0000000000..5804f8c631 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/internal/index.js @@ -0,0 +1,54 @@ +const { createMixFetch, disconnectMixFetch } = require('../dist/cjs/index.js'); + +/** + * The main entry point + */ +(async () => { + console.log('Tester is starting up...'); + + const addr = + 'D274yd1h3L3pNJzdxE5VgJ7izAsAVMsDrQtFSkKUegfk.8J67cGbcwvrJKF3Kb16HVWWc9AnrFnEibNCm9zCkuVFu@Emswx6KXyjRfq1c2k4d4uD2e6nBSbH1biorCZUei8UNS'; + + console.log('About to set up mixFetch...'); + const { mixFetch } = await createMixFetch({ + preferredNetworkRequester: addr, + clientId: 'node-client1', + clientOverride: { + coverTraffic: { disableLoopCoverTrafficStream: true }, + traffic: { disableMainPoissonPacketDistribution: true }, + }, + mixFetchOverride: { requestTimeoutMs: 60000 }, + responseBodyConfigMap: {}, + extra: {}, + }); + + globalThis.mixFetch = mixFetch; + + if (!globalThis.mixFetch) { + console.error('Oh no! Could not create mixFetch'); + } else { + console.log('Ready!'); + } + + let url = 'https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt'; + console.log(`Using mixFetch to get ${url}...`); + const args = { mode: 'unsafe-ignore-cors' }; + + let resp = await mixFetch(url, args); + console.log({ resp }); + const text = await resp.text(); + + console.log('disconnecting'); + await disconnectMixFetch(); + console.log('disconnected! all further usages should fail'); + + // get an image + url = 'https://nymtech.net/favicon.svg'; + resp = await mixFetch(url, args); + console.log({ resp }); + const buffer = await resp.arrayBuffer(); + const type = resp.headers.get('Content-Type') || 'image/svg'; + const blobUrl = URL.createObjectURL(new Blob([buffer], { type })); + console.log(JSON.stringify({ bufferBytes: buffer.byteLength, blobUrl }, null, 2)); + console.log(blobUrl); +})(); diff --git a/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs b/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs index bc10b36ad1..0912356e47 100644 --- a/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs +++ b/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs @@ -11,7 +11,7 @@ export default { dir: 'dist/cjs', format: 'cjs', }, - onwarn, + external: ['util', 'fake-indexeddb'], plugins: [ resolve({ browser: false, @@ -19,6 +19,10 @@ export default { extensions: ['.js', '.ts'], }), commonjs(), + modify({ + find: 'const ret = new WebSocket(getStringFromWasm0(arg0, arg1));', + replace: 'const ws = require("ws"); const ret = new ws.WebSocket(getStringFromWasm0(arg0, arg1));', + }), // TODO: `getObject(...).require` seems to generate a warning on Webpack but with Rollup we get a panic since it can't require. // By hard coding the require here, we can workaround that. // Reference: https://github.com/rust-random/getrandom/issues/224 @@ -33,11 +37,3 @@ export default { }), ], }; - -function onwarn(warning) { - // fake-indexeddb has a circular dependency that triggers a warning when rolled up - if (warning.code !== 'CIRCULAR_DEPENDENCY') { - // eslint-disable-next-line no-console - console.error(`(!) ${warning.message}`); - } -} diff --git a/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs b/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs index 7a4af49fc2..a1b3701df4 100644 --- a/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs +++ b/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs @@ -12,6 +12,7 @@ export default { format: 'cjs', }, plugins: [ + resolve({ browser: false, extensions: ['.js', '.ts'] }), webWorkerLoader({ targetPlatform: 'node', inline: false }), replace({ values: { @@ -21,7 +22,6 @@ export default { delimiters: ['', ''], preventAssignment: true, }), - resolve({ browser: false, extensions: ['.js', '.ts'] }), wasm({ targetEnv: 'node', maxFileSize: 0 }), typescript({ compilerOptions: { outDir: 'dist/cjs', target: 'es5' }, diff --git a/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs b/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs index b1b40b0a0b..484b55d010 100644 --- a/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs +++ b/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs @@ -11,6 +11,7 @@ export default { dir: 'dist/cjs', format: 'cjs', }, + external: ['util', 'fake-indexeddb'], plugins: [ resolve({ browser: false, @@ -18,6 +19,11 @@ export default { extensions: ['.js', '.ts'], }), commonjs(), + // TODO: One of the wasm functions calls `new WebSocket` at one point, which we aren't able to polyfill correctly yet. + modify({ + find: 'const ret = new WebSocket(getStringFromWasm0(arg0, arg1));', + replace: 'const ws = require("ws"); const ret = new ws.WebSocket(getStringFromWasm0(arg0, arg1));', + }), // TODO: `getObject(...).require` seems to generate a warning on Webpack but with Rollup we get a panic since it can't require. // By hard coding the require here, we can workaround that. // Reference: https://github.com/rust-random/getrandom/issues/224 diff --git a/sdk/typescript/packages/nodejs-client/src/polyfill.ts b/sdk/typescript/packages/nodejs-client/src/polyfill.ts index 425b49b5fa..3dceb23ba9 100644 --- a/sdk/typescript/packages/nodejs-client/src/polyfill.ts +++ b/sdk/typescript/packages/nodejs-client/src/polyfill.ts @@ -1,6 +1,6 @@ import * as crypto from 'node:crypto'; import * as fs from 'node:fs'; -import ws from 'ws'; +import WebSocket from 'ws'; import { TextDecoder, TextEncoder } from 'node:util'; import { Worker } from 'node:worker_threads'; import { indexedDB } from 'fake-indexeddb'; @@ -10,7 +10,7 @@ import { performance } from 'node:perf_hooks'; (globalThis as any).TextDecoder = TextDecoder; (globalThis as any).fs = fs; (globalThis as any).crypto = crypto; -(globalThis as any).ws = ws; +(globalThis as any).WebSocket = WebSocket; (globalThis as any).Worker = Worker; globalThis.process = process; diff --git a/yarn.lock b/yarn.lock index 3309ce67f6..1602bf8355 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13227,6 +13227,17 @@ jest@^29.5.0: import-local "^3.0.2" jest-cli "^29.7.0" +joi@^17.11.0: + version "17.11.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.11.0.tgz#aa9da753578ec7720e6f0ca2c7046996ed04fc1a" + integrity sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.3" + "@sideway/formula" "^3.0.1" + "@sideway/pinpoint" "^2.0.0" + js-sha3@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" From 11e383659969e65cda14a2239af484e898f793ed Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Wed, 1 Nov 2023 16:31:02 +0100 Subject: [PATCH 180/236] spellcheck + table format fix --- documentation/docs/src/sdk/rust.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/documentation/docs/src/sdk/rust.md b/documentation/docs/src/sdk/rust.md index b62353a9d6..884c71bc9c 100644 --- a/documentation/docs/src/sdk/rust.md +++ b/documentation/docs/src/sdk/rust.md @@ -1,12 +1,12 @@ # Rust SDK -The Rust SDK allows developers building applications in Rust to import and interact with Nym clients as they would any other dependency, instead of running the client as a seperate process on their machine. This makes both developing and running applications much easier, reducing complexity in the development process (not having to restart another client in a seperate console window/tab) and being able to have a single binary for other people to use. +The Rust SDK allows developers building applications in Rust to import and interact with Nym clients as they would any other dependency, instead of running the client as a separate process on their machine. This makes both developing and running applications much easier, reducing complexity in the development process (not having to restart another client in a separate console window/tab) and being able to have a single binary for other people to use. Currently developers can use the Rust SDK to import either websocket client ([`nym-client`](../clients/websocket-client.md)) or [`socks-client`](../clients/socks5-client.md) functionality into their Rust code. ## Development status The SDK is still somewhat a work in progress: interfaces are fairly stable but still may change in subsequent releases. -The `nym-sdk` crate is **not yet availiable via [crates.io](https://crates.io)**. As such, in order to import the crate you must specify the Nym monorepo in your `Cargo.toml` file: +The `nym-sdk` crate is **not yet available via [crates.io](https://crates.io)**. As such, in order to import the crate you must specify the Nym monorepo in your `Cargo.toml` file: ```toml nym-sdk = { git = "https://github.com/nymtech/nym" } @@ -17,10 +17,10 @@ In order to generate the crate docs run `cargo doc --open` from `nym/sdk/rust/ny In the future the SDK will be made up of several components, each of which will allow developers to interact with different parts of Nym's infrastructure. | Component | Functionality | Released | -| --------- | ------------------------------------------------------------------------------------- | -------- | -| Mixnet | Create / load clients & keypairs, subscribe to Mixnet events, send & receive messages | ✔️ | -| Coconut | Create & verify Coconut credentials | 🛠️ | -| Validator | Sign & broadcast Nyx blockchain transactions, query the blockchain | ❌ | +|-----------|---------------------------------------------------------------------------------------|----------| +| Mixnet | Create / load clients & keypairs, subscribe to Mixnet events, send & receive messages | ✔️ | +| Coconut | Create & verify Coconut credentials | 🛠️ | +| Validator | Sign & broadcast Nyx blockchain transactions, query the blockchain | ❌ | The `mixnet` component currently exposes the logic of two clients: the [websocket client](../clients/websocket-client.md), and the [socks](../clients/socks5-client.md) client. From 41caad4dbfe1b7525328eb18739140339306752b Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Wed, 1 Nov 2023 16:41:11 +0100 Subject: [PATCH 181/236] Fix the getRandomValue crypto polyfill issue Signed-off-by: Sebastian Martinez --- .../packages/mix-fetch-node/rollup-worker.config.mjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs b/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs index 0912356e47..a471223521 100644 --- a/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs +++ b/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs @@ -27,6 +27,10 @@ export default { // By hard coding the require here, we can workaround that. // Reference: https://github.com/rust-random/getrandom/issues/224 modify({ find: 'getObject(arg0).require(getStringFromWasm0(arg1, arg2));', replace: 'require("crypto");' }), + modify({ + find: 'getObject(arg0).getRandomValues(getObject(arg1));', + replace: 'require("crypto").getRandomValues(getObject(arg1));', + }), wasm({ targetEnv: 'node', maxFileSize: 0, fileName: '[name].wasm' }), typescript({ compilerOptions: { From df010ef3046efb2cc6e8f8d1a63e2829590b554b Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Wed, 1 Nov 2023 16:41:50 +0100 Subject: [PATCH 182/236] Update mix-fetch-node to rc.3 Signed-off-by: Sebastian Martinez --- sdk/typescript/packages/mix-fetch-node/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/typescript/packages/mix-fetch-node/package.json b/sdk/typescript/packages/mix-fetch-node/package.json index 2df56711de..0fb709c9db 100644 --- a/sdk/typescript/packages/mix-fetch-node/package.json +++ b/sdk/typescript/packages/mix-fetch-node/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/mix-fetch-node", - "version": "1.2.1-rc.2", + "version": "1.2.1-rc.3", "description": "This package is a drop-in replacement for `fetch` in NodeJS to send HTTP requests over the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", From 50da1b1606637db5d48b54c5df1f1ab327848667 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Wed, 1 Nov 2023 17:23:28 +0100 Subject: [PATCH 183/236] add wss host setup --- .../operators/src/nodes/gateway-setup.md | 4 +- .../operators/src/nodes/maintenance.md | 160 +++++++++++++++--- 2 files changed, 140 insertions(+), 24 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index c6a85ec792..fc4988c943 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -82,7 +82,7 @@ Additionally #### Add Network requester to an existing Gateway -If you already [upgraded](./maintenance.md#upgrading-your-node) your Gateway to the [newest version](./gateway-setup.md#current-version) and initialised without a Network requester, you can easily change its functionality to Exit Gateway with a command `setup-network-requester`. +If you already [upgraded](./maintenance.md#upgrading-your-node) your Gateway to the [latest version](./gateway-setup.md#current-version) and initialised without a Network requester, you can easily change its functionality to Exit Gateway with a command `setup-network-requester`. See the options: @@ -168,7 +168,7 @@ The `$(curl -4 https://ifconfig.me)` command above returns your IP automatically ### Bonding your gateway ```admonish info -Before you bond and run your Gateway, please make sure the [firewall configuration](./maintenance.md#configure-your-firewall) is setup so your gateway can be reached from the outside. +Before you bond and re-run your Gateway, please make sure the [firewall configuration](./maintenance.md#configure-your-firewall) is setup so your gateway can be reached from the outside. You can also setup WSS on your Gateway, the steps are on the [Maintenance page](./maintenance.md#configure-your-firewall) below. ``` #### Via the Desktop wallet diff --git a/documentation/operators/src/nodes/maintenance.md b/documentation/operators/src/nodes/maintenance.md index 03bb33a0f3..6ee74d59ca 100644 --- a/documentation/operators/src/nodes/maintenance.md +++ b/documentation/operators/src/nodes/maintenance.md @@ -103,36 +103,120 @@ Running the command `df -H` will return the size of the various partitions of yo If the `/dev/sda` partition is almost full, try pruning some of the `.gz` syslog archives and restart your validator process. -## Moving a node -In case of a need to move a node from one machine to another and avoiding to lose the delegation, here are few steps how to do it. +## Run Web Secure Socket (WSS) on Gateway -The following examples transfers a mix node (in case of other nodes, change the `mixnodes` in the command for the `` of your desire. +Now you can run WSS on your Gateway. -* Pause your node process. +### WSS on an existing Gateway -Assuming both machines are remote VPS. +In case you already run a working Gateway and want to add WSS on it, here are the pre-requisites to running WSS on Gateways: -* Make sure your `~/.ssh/.pub` is in both of the machines `~/.ssh/authorized_keys` file -* Create a `mixnodes` folder in the target VPS. Ssh in from your terminal and run: +* You need to use the latest `nym-gateway` binary [version](./gateway-setup.md#current-version) and restart it. +* That will add the relevant fields to update your config. +* These two values will be added and need to be amended in your config.toml: ```sh -# in case none of the nym configs was created previously -mkdir ~/.nym - -#in case no nym mix node was initialized previously -mkdir ~/.nym/mixnodes +clients_wss_port = 0 +hostname = "" ``` -* Move the node data (keys) and config file to the new machine by opening a local terminal (as that one's ssh key is authorized in both of the machines) and running: + +Then you can run this: + ```sh -scp -r -3 @:~/.nym/mixnodes/ @:~/.nym/mixnodes/ -``` -* Re-run init (remember that init doesn't overwrite existing keys) to generate a config with the new listening address etc. -* Change the node smart contract info via the wallet interface. Otherwise the keys will point to the old IP address in the smart contract, and the node will not be able to be connected, and it will fail up-time checks. -* Re-run the node from the new location. +port=$1 // in the example below we will use 9001 +host=$2 = // this would be a domain name registered for your Gateway for example: mainnet-gateway2.nymtech.net + + +sed -i "s/clients_wss_port = 0/clients_wss_port = ${port}/" ${HOME}/.nym/gateways/*/config/config.toml +sed -i "s|hostname = ''|hostname = '${host}'|" ${HOME}/.nym/gateways/*/config/config.toml +``` +The following shell script can be run: + +```sh +#!/bin/bash + +if [ "$#" -ne 2 ]; then + echo "Usage: sudo ./install_run_caddy.sh " + exit 1 +fi + +host=$1 +port_value=$2 + +apt install -y debian-keyring debian-archive-keyring apt-transport-https +apt --fix-broken install + +curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg + +curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list + +apt update +apt install caddy + +systemctl enable caddy.service + +cd /etc/caddy + +# check if Caddyfile exists, if it does, remove and insert a new one +if [ -f Caddyfile ]; then + echo "removing caddyfile inserting a new one" + rm -f Caddyfile +fi + +cat <> Caddyfile +${host}:${port_value} { + @websockets { + header Connection *Upgrade* + header Upgrade websocket + } + reverse_proxy @websockets localhost:9000 +} +EOF + +cat Caddyfile + +echo "script completed successfully!" + +systemctl restart caddy.service +echo "have a nice day!" +exit 0 + +``` + +Although your gateway is Now ready to use its `wss_port`, your server may not be ready - the following commands will allow you to set up a properly configured firewall using `ufw`: + +```sh +ufw allow 9001/tcp +``` + +Lastly don't forget to restart your Gateway, now the API will render the WSS details for this gateway: + + +### WSS on a new Gateway + +These steps are for an operator who is setting up a Gateway for the first time and wants to run it with WSS. + +New flags will need to be added to the `init` and `run` command. The `--host` option is still accepted for now, but can and should be replaced with `--listening-address`, this is the IP address which is used for receiving sphinx packets and listening to client data. + +Another flag `--public-ips` is required; it's a comma separated list of IP’s that are announced to the `nym-api`, it is usually the address which is used for bonding. + +If the operator wishes to run WSS, an optional `--hostname` flag is also required, that can be something like `mainnet-gateway2.nymtech.net`. Make sure to enable all necessary [ports](maintenance.md#configure-your-firewall) on the Gateway. + +The gateway will then be accessible on something like: *http://85.159.211.99:8080/api/v1/swagger/index.html* + +Are you seeing something like: *this node attempted to announce an invalid public address: 0.0.0.0.*? + +Please modify `[host.public_ips]` section of your config file stored as `~/.nym/gateways//config/config.toml`. + +If so the flags are going to be slightly different: + +``` +--listening-address "0.0.0.0" --public-ips "$(curl -4 https://ifconfig.me)" +``` + +## Configure your firewall -## VPS Setup and Automation -### Configure your firewall Although your `` is now ready to receive traffic, your server may not be. The following commands will allow you to set up a firewall using `ufw`. ```sh @@ -153,7 +237,7 @@ Finally open your `` p2p port, as well as ports for ssh and ports for verl ```sh # for mix node, gateway and network requester -sudo ufw allow 1789,1790,8000,9000,22/tcp +sudo ufw allow 1789,1790,8000,9000,9001,22/tcp # for validator sudo ufw allow 1317,26656,26660,22,80,443/tcp @@ -166,6 +250,8 @@ sudo ufw status For more information about your node's port configuration, check the [port reference table](./maintenance.md#gateway-port-reference) below. +## VPS Setup and Automation + ### Automating your node with nohup, tmux and systemd Although it’s not totally necessary, it's useful to have the mix node automatically start at system boot time. @@ -398,7 +484,7 @@ Failed to accept incoming connection - Os { code: 24, kind: Other, message: "Too This means that the operating system is preventing network connections from being made. -#### Set the ulimit via `systemd` service file +#### Set the `ulimit` via `systemd` service file > Replace `` variable with `nym-mixnode`, `nym-gateway` or `nym-network-requester` according the node you running on your machine. @@ -481,6 +567,35 @@ username soft nofile 4096 Then reboot your server and restart your mix node. +## Moving a node + +In case of a need to move a node from one machine to another and avoiding to lose the delegation, here are few steps how to do it. + +The following examples transfers a mix node (in case of other nodes, change the `mixnodes` in the command for the `` of your desire. + +* Pause your node process. + +Assuming both machines are remote VPS. + +* Make sure your `~/.ssh/.pub` is in both of the machines `~/.ssh/authorized_keys` file +* Create a `mixnodes` folder in the target VPS. Ssh in from your terminal and run: + +```sh +# in case none of the nym configs was created previously +mkdir ~/.nym + +#in case no nym mix node was initialized previously +mkdir ~/.nym/mixnodes +``` +* Move the node data (keys) and config file to the new machine by opening a local terminal (as that one's ssh key is authorized in both of the machines) and running: +```sh +scp -r -3 @:~/.nym/mixnodes/ @:~/.nym/mixnodes/ +``` +* Re-run init (remember that init doesn't overwrite existing keys) to generate a config with the new listening address etc. +* Change the node smart contract info via the wallet interface. Otherwise the keys will point to the old IP address in the smart contract, and the node will not be able to be connected, and it will fail up-time checks. +* Re-run the node from the new location. + + ## Virtual IPs and hosting via Google & AWS For true internet decentralization we encourage operators to use diverse VPS providers instead of the largest companies offering such services. If for some reasons you have already running AWS or Google and want to setup a `` there, please read the following. @@ -680,6 +795,7 @@ All ``-specific port configuration can be found in `$HOME/.nym// Date: Wed, 1 Nov 2023 17:34:55 +0100 Subject: [PATCH 184/236] new directory structure for rust SDK docs --- documentation/docs/src/SUMMARY.md | 13 +++++- documentation/docs/src/clients/overview.md | 4 +- documentation/docs/src/introduction.md | 2 +- documentation/docs/src/sdk/rust/examples.md | 2 + .../docs/src/sdk/rust/message-helpers.md | 2 + .../docs/src/sdk/rust/message-types.md | 7 +++ documentation/docs/src/sdk/{ => rust}/rust.md | 46 +++++++++---------- .../docs/src/sdk/rust/troubleshooting.md | 3 ++ 8 files changed, 52 insertions(+), 27 deletions(-) create mode 100644 documentation/docs/src/sdk/rust/examples.md create mode 100644 documentation/docs/src/sdk/rust/message-helpers.md create mode 100644 documentation/docs/src/sdk/rust/message-types.md rename documentation/docs/src/sdk/{ => rust}/rust.md (86%) create mode 100644 documentation/docs/src/sdk/rust/troubleshooting.md diff --git a/documentation/docs/src/SUMMARY.md b/documentation/docs/src/SUMMARY.md index 8e4f7c6127..b9dd5a4191 100644 --- a/documentation/docs/src/SUMMARY.md +++ b/documentation/docs/src/SUMMARY.md @@ -29,7 +29,18 @@ # SDK - [Typescript SDK](sdk/typescript.md) -- [Rust SDK](sdk/rust.md) +- [Rust SDK](sdk/rust/rust.md) + - [Message Types](sdk/rust/message-types.md) + - [Message Helpers](sdk/rust/message-helpers.md) + - [Troubleshooting](sdk/rust/troubleshooting.md) + - [Examples](sdk/rust/examples.md) + - [Simple Send](sdk/rust/examples/simple.md) + - [Create and Store Keys](sdk/rust/examples/keys.md) + - [Manual Storage](sdk/rust/examples/storage.md) + - [Use Custom Network Topology](sdk/rust/examples/custom-network.md) + - [Socks Proxy](sdk/rust/examples/socks.md) + - [Split Send and Receive](sdk/rust/examples/split-send.md) + - [Testnet Bandwidth Cred](sdk/rust/examples/credential.md) # Wallet - [Desktop Wallet](wallet/desktop-wallet.md) diff --git a/documentation/docs/src/clients/overview.md b/documentation/docs/src/clients/overview.md index c8d2db1503..b9b5686dbd 100644 --- a/documentation/docs/src/clients/overview.md +++ b/documentation/docs/src/clients/overview.md @@ -25,7 +25,7 @@ You need to choose which one you want incorporate into your app. Which one you u ### The websocket client Your first option is the native websocket client (`nym-client`). This is a compiled program that can run on Linux, Mac OS X, and Windows machines. It can be run as a persistent process on a desktop or server machine. You can connect to it with **any language that supports websockets**. -_Rust developers can import websocket client functionality into their code via the [Rust SDK](../sdk/rust.md)_. +_Rust developers can import websocket client functionality into their code via the [Rust SDK](../sdk/rust/rust.md)_. ### The webassembly client If you're working in JavaScript or Typescript in the browser, or building an [edge computing](https://en.wikipedia.org/wiki/Edge_computing) app, you'll likely want to choose the webassembly client. @@ -39,7 +39,7 @@ The `nym-socks5-client` is useful for allowing existing applications to use the When used as a standalone client, it's less flexible as a way of writing custom applications than the other clients, but able to be used to proxy application traffic through the mixnet without having to make any code changes. -_Rust developers can import socks client functionality into their code via the [Rust SDK](../sdk/rust.md)_. +_Rust developers can import socks client functionality into their code via the [Rust SDK](../sdk/rust/rust.md)_. ## Commonalities between clients All Nym client packages present basically the same capabilities to the privacy application developer. They need to run as a persistent process in order to stay connected and ready to receive any incoming messages from their gateway nodes. They register and authenticate to gateways, and encrypt Sphinx packets. diff --git a/documentation/docs/src/introduction.md b/documentation/docs/src/introduction.md index 9e5912ba07..c9b4c4a7d5 100644 --- a/documentation/docs/src/introduction.md +++ b/documentation/docs/src/introduction.md @@ -15,7 +15,7 @@ If you're specically looking for TypeScript/JavaScript related information such **SDK examples:** * [Typescript SDK](https://sdk.nymtech.net/) -* [Rust SDK](./sdk/rust.md) +* [Rust SDK](sdk/rust/rust.md) **Nyx** * [Interacting with the Nyx chain](./nyx/interacting-with-chain.md) diff --git a/documentation/docs/src/sdk/rust/examples.md b/documentation/docs/src/sdk/rust/examples.md new file mode 100644 index 0000000000..544f7fb418 --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples.md @@ -0,0 +1,2 @@ +# Examples +TODO split examples into subdirectory with their own individual files \ No newline at end of file diff --git a/documentation/docs/src/sdk/rust/message-helpers.md b/documentation/docs/src/sdk/rust/message-helpers.md new file mode 100644 index 0000000000..478e12a7ab --- /dev/null +++ b/documentation/docs/src/sdk/rust/message-helpers.md @@ -0,0 +1,2 @@ +# Message Helpers +TODO pull in dealing with incoming non-empty messages and fn()s from tutorial \ No newline at end of file diff --git a/documentation/docs/src/sdk/rust/message-types.md b/documentation/docs/src/sdk/rust/message-types.md new file mode 100644 index 0000000000..20d959b127 --- /dev/null +++ b/documentation/docs/src/sdk/rust/message-types.md @@ -0,0 +1,7 @@ +# Message Types + +TODO expand! + +There are two methods for sending messages through the mixnet using your client: +* `send_plain_message()` is the most simple: pass the recipient address and the message you wish to send as a string (this was previously `send_str()`). This is a nicer-to-use wrapper around `send_message()`. +* `send_message()` allows you to also define the amount of SURBs to send along with your message (which is sent as bytes). diff --git a/documentation/docs/src/sdk/rust.md b/documentation/docs/src/sdk/rust/rust.md similarity index 86% rename from documentation/docs/src/sdk/rust.md rename to documentation/docs/src/sdk/rust/rust.md index 884c71bc9c..c593b3aa6e 100644 --- a/documentation/docs/src/sdk/rust.md +++ b/documentation/docs/src/sdk/rust/rust.md @@ -1,20 +1,9 @@ # Rust SDK The Rust SDK allows developers building applications in Rust to import and interact with Nym clients as they would any other dependency, instead of running the client as a separate process on their machine. This makes both developing and running applications much easier, reducing complexity in the development process (not having to restart another client in a separate console window/tab) and being able to have a single binary for other people to use. -Currently developers can use the Rust SDK to import either websocket client ([`nym-client`](../clients/websocket-client.md)) or [`socks-client`](../clients/socks5-client.md) functionality into their Rust code. +Currently developers can use the Rust SDK to import either websocket client ([`nym-client`](../../clients/websocket-client.md)) or [`socks-client`](../../clients/socks5-client.md) functionality into their Rust code. -## Development status -The SDK is still somewhat a work in progress: interfaces are fairly stable but still may change in subsequent releases. - -The `nym-sdk` crate is **not yet available via [crates.io](https://crates.io)**. As such, in order to import the crate you must specify the Nym monorepo in your `Cargo.toml` file: - -```toml -nym-sdk = { git = "https://github.com/nymtech/nym" } -``` - -In order to generate the crate docs run `cargo doc --open` from `nym/sdk/rust/nym-sdk/` - -In the future the SDK will be made up of several components, each of which will allow developers to interact with different parts of Nym's infrastructure. +In the future the SDK will be made up of several components, each of which will allow developers to interact with different parts of Nym infrastructure. | Component | Functionality | Released | |-----------|---------------------------------------------------------------------------------------|----------| @@ -22,18 +11,27 @@ In the future the SDK will be made up of several components, each of which will | Coconut | Create & verify Coconut credentials | 🛠️ | | Validator | Sign & broadcast Nyx blockchain transactions, query the blockchain | ❌ | -The `mixnet` component currently exposes the logic of two clients: the [websocket client](../clients/websocket-client.md), and the [socks](../clients/socks5-client.md) client. +The `mixnet` component currently exposes the logic of two clients: the [websocket client](../../clients/websocket-client.md), and the [socks](../../clients/socks5-client.md) client. The `coconut` component is currently being worked on. Right now it exposes logic allowing for the creation of coconut credentials on the Sandbox testnet. +### Development status +The SDK is still somewhat a work in progress: interfaces are fairly stable but still may change in subsequent releases. + +### Installation +The `nym-sdk` crate is **not yet available via [crates.io](https://crates.io)**. As such, in order to import the crate you must specify the Nym monorepo in your `Cargo.toml` file: + +TODO add note on branch import for stability - `master` should be last release +```toml +nym-sdk = { git = "https://github.com/nymtech/nym" } +``` + +### Generate Crate Docs +In order to generate the crate docs run `cargo doc --open` from `nym/sdk/rust/nym-sdk/` + ## Websocket client examples > All the codeblocks below can be found in the `nym-sdk` [examples directory](https://github.com/nymtech/nym/tree/master/sdk/rust/nym-sdk/examples) in the monorepo. Just navigate to `nym/sdk/rust/nym-sdk/examples/` and run the files from there. If you wish to run these outside of the workspace - such as if you want to use one as the basis for your own project - then make sure to import the `sdk`, `tokio`, and `nym_bin_common` crates. -### Different message types -There are two methods for sending messages through the mixnet using your client: -* `send_plain_message()` is the most simple: pass the recipient address and the message you wish to send as a string (this was previously `send_str()`). This is a nicer-to-use wrapper around `send_message()`. -* `send_message()` allows you to also define the amount of SURBs to send along with your message (which is sent as bytes). - ### Simple example Lets look at a very simple example of how you can import and use the websocket client in a piece of Rust code (`examples/simple.rs`): @@ -89,7 +87,7 @@ The number of SURBs is set [here](https://github.com/nymtech/nym/blob/master/sdk {{#include ../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:33}} ``` -You can read more about how SURBs function under the hood [here](../architecture/traffic-flow.md#private-replies-using-surbs). +You can read more about how SURBs function under the hood [here](../../architecture/traffic-flow.md#private-replies-using-surbs). In order to reply to an incoming message using SURBs, you can construct a `recipient` from the `sender_tag` sent along with the message you wish to reply to: @@ -124,7 +122,7 @@ If you need to split the different actions of your client across different tasks ``` ## Socks client example -There is also the option to embed the [`socks5-client`](../clients/socks5-client.md) into your app code (`examples/socks5.rs`): +There is also the option to embed the [`socks5-client`](../../clients/socks5-client.md) into your app code (`examples/socks5.rs`): ```rust,noplayground {{#include ../../../../sdk/rust/nym-sdk/examples/socks5.rs}} @@ -135,10 +133,12 @@ If you are looking at implementing Nym as a transport layer for a crypto wallet ``` ## Coconut credential generation -The following code shows how you can use the SDK to create and use a [credential](../bandwidth-credentials.md) representing paid bandwidth on the Sandbox testnet. +The following code shows how you can use the SDK to create and use a [credential](../../bandwidth-credentials.md) representing paid bandwidth on the Sandbox testnet. ```rust,noplayground {{#include ../../../../sdk/rust/nym-sdk/examples/bandwidth.rs}} ``` -You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](../coconut.md). +You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](../../coconut.md). + + diff --git a/documentation/docs/src/sdk/rust/troubleshooting.md b/documentation/docs/src/sdk/rust/troubleshooting.md new file mode 100644 index 0000000000..c8de2e5e37 --- /dev/null +++ b/documentation/docs/src/sdk/rust/troubleshooting.md @@ -0,0 +1,3 @@ +# Troubleshooting +TODO note on poisson dance and not immediately killing client process +TODO note on listening for non-empty messages and point towards helpers From 8cf0b3adae73040014ab4a2b299b1df3fbb5aac8 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Wed, 1 Nov 2023 21:01:47 +0100 Subject: [PATCH 185/236] first draft of expanded rust stuff --- documentation/docs/src/SUMMARY.md | 2 + documentation/docs/src/sdk/rust/examples.md | 12 +- .../docs/src/sdk/rust/examples/cargo.md | 36 ++++++ .../docs/src/sdk/rust/examples/credential.md | 9 ++ .../src/sdk/rust/examples/custom-network.md | 18 +++ .../docs/src/sdk/rust/examples/keys.md | 28 +++++ .../docs/src/sdk/rust/examples/simple.md | 8 ++ .../docs/src/sdk/rust/examples/socks.md | 10 ++ .../docs/src/sdk/rust/examples/split-send.md | 6 + .../docs/src/sdk/rust/examples/storage.md | 6 + .../docs/src/sdk/rust/examples/surbs.md | 16 +++ .../docs/src/sdk/rust/message-types.md | 4 +- documentation/docs/src/sdk/rust/rust.md | 112 ------------------ 13 files changed, 151 insertions(+), 116 deletions(-) create mode 100644 documentation/docs/src/sdk/rust/examples/cargo.md create mode 100644 documentation/docs/src/sdk/rust/examples/credential.md create mode 100644 documentation/docs/src/sdk/rust/examples/custom-network.md create mode 100644 documentation/docs/src/sdk/rust/examples/keys.md create mode 100644 documentation/docs/src/sdk/rust/examples/simple.md create mode 100644 documentation/docs/src/sdk/rust/examples/socks.md create mode 100644 documentation/docs/src/sdk/rust/examples/split-send.md create mode 100644 documentation/docs/src/sdk/rust/examples/storage.md create mode 100644 documentation/docs/src/sdk/rust/examples/surbs.md diff --git a/documentation/docs/src/SUMMARY.md b/documentation/docs/src/SUMMARY.md index b9dd5a4191..24a625cfb2 100644 --- a/documentation/docs/src/SUMMARY.md +++ b/documentation/docs/src/SUMMARY.md @@ -37,10 +37,12 @@ - [Simple Send](sdk/rust/examples/simple.md) - [Create and Store Keys](sdk/rust/examples/keys.md) - [Manual Storage](sdk/rust/examples/storage.md) + - [Anonymous Replies](sdk/rust/examples/surbs.md) - [Use Custom Network Topology](sdk/rust/examples/custom-network.md) - [Socks Proxy](sdk/rust/examples/socks.md) - [Split Send and Receive](sdk/rust/examples/split-send.md) - [Testnet Bandwidth Cred](sdk/rust/examples/credential.md) + - [Example Cargo file](sdk/rust/examples/cargo.md) # Wallet - [Desktop Wallet](wallet/desktop-wallet.md) diff --git a/documentation/docs/src/sdk/rust/examples.md b/documentation/docs/src/sdk/rust/examples.md index 544f7fb418..e612a7d59d 100644 --- a/documentation/docs/src/sdk/rust/examples.md +++ b/documentation/docs/src/sdk/rust/examples.md @@ -1,2 +1,12 @@ # Examples -TODO split examples into subdirectory with their own individual files \ No newline at end of file + +All the following examples can be found in the `nym-sdk` [examples directory](https://github.com/nymtech/nym/tree/master/sdk/rust/nym-sdk/examples) in the monorepo. Just navigate to `nym/sdk/rust/nym-sdk/examples/` and run the files from there with: + +```sh +cargo run --example +``` + +If you wish to run these outside of the workspace - such as if you want to use one as the basis for your own project - then make sure to import the `sdk`, `tokio`, and `nym_bin_common` crates. + +An example `Cargo.toml` file can be found in the examples folder. + diff --git a/documentation/docs/src/sdk/rust/examples/cargo.md b/documentation/docs/src/sdk/rust/examples/cargo.md new file mode 100644 index 0000000000..4c96e05fc5 --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/cargo.md @@ -0,0 +1,36 @@ +# Example Cargo File +This file imports the basic requirements for running these pieces of example code, and can be used as the basis for your own cargo project. + +TODO versioning check +```toml +[package] +name = "your_app" +version = "x.y.z" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# Async runtime +tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] } +# Used for (de)serialising incoming and outgoing messages +serde = "1.0.152" +serde_json = "1.0.91" +# Nym clients, addressing, etc +nym-sdk = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" } +nym-sphinx-addressing = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" } +nym-bin-common = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" } +nym-sphinx-anonymous-replies = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" } +# Additional dependencies if you're interacting with Nyx or another Cosmos SDK blockchain +cosmrs = "=0.14.0" +nym-validator-client = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" } + +# If you're building an app with a client and server / serivce this might be a useful structure for your repo +[[bin]] +name = "client" +path = "bin/client.rs" + +[[bin]] +name = "service" +path = "bin/service.rs" +``` \ No newline at end of file diff --git a/documentation/docs/src/sdk/rust/examples/credential.md b/documentation/docs/src/sdk/rust/examples/credential.md new file mode 100644 index 0000000000..d0fe29bbbd --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/credential.md @@ -0,0 +1,9 @@ +# Coconut credential generation +The following code shows how you can use the SDK to create and use a [credential](../../bandwidth-credentials.md) representing paid bandwidth on the Sandbox testnet. + +```rust,noplayground +{{#include ../../../../sdk/rust/nym-sdk/examples/bandwidth.rs}} +``` + +You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](../../coconut.md). + diff --git a/documentation/docs/src/sdk/rust/examples/custom-network.md b/documentation/docs/src/sdk/rust/examples/custom-network.md new file mode 100644 index 0000000000..0ad226f953 --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/custom-network.md @@ -0,0 +1,18 @@ +# Importing and using a custom network topology +If you want to send traffic through a sub-set of nodes (for instance, ones you control, or a small test setup) when developing, debugging, or performing research, you will need to import these nodes as a custom network topology, instead of grabbing it from the [`Mainnet Nym-API`](https://validator.nymtech.net/api/swagger/index.html) (`examples/custom_topology_provider.rs`). + +There are two ways to do this: + +## Import a custom Nym API endpoint +If you are also running a Validator and Nym API for your network, you can specify that endpoint as such and interact with it as clients usually do (under the hood): + +```rust,noplayground +{{#include ../../../../sdk/rust/nym-sdk/examples/custom_topology_provider.rs}} +``` + +## Import a specific topology manually +If you aren't running a Validator and Nym API, and just want to import a specific sub-set of mix nodes, you can simply overwrite the grabbed topology manually: + +```rust,noplayground +{{#include ../../../../sdk/rust/nym-sdk/examples/manually_overwrite_topology.rs}} +``` diff --git a/documentation/docs/src/sdk/rust/examples/keys.md b/documentation/docs/src/sdk/rust/examples/keys.md new file mode 100644 index 0000000000..6e2f66d986 --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/keys.md @@ -0,0 +1,28 @@ +# Key Creation and Use +The previous example involves ephemeral keys - if we want to create and then maintain a client identity over time, our code becomes a little more complex as we need to create, store, and conditionally load these keys (`examples/builder_with_storage`): + +```rust,noplayground +{{#include ../../../../sdk/rust/nym-sdk/examples/builder_with_storage.rs}} +``` + +As seen in the example above, the `mixnet::MixnetClientBuilder::new()` function handles checking for keys in a storage location, loading them if present, or creating them and storing them if not, making client key management very simple. + +Assuming our client config is stored in `/tmp/mixnet-client`, the following files are generated: +``` +$ tree /tmp/mixnet-client + +mixnet-client +├── ack_key.pem +├── db.sqlite +├── db.sqlite-shm +├── db.sqlite-wal +├── gateway_details.json +├── gateway_shared.pem +├── persistent_reply_store.sqlite +├── private_encryption.pem +├── private_identity.pem +├── public_encryption.pem +└── public_identity.pem + +1 directory, 11 files +``` diff --git a/documentation/docs/src/sdk/rust/examples/simple.md b/documentation/docs/src/sdk/rust/examples/simple.md new file mode 100644 index 0000000000..b3d5f9d268 --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/simple.md @@ -0,0 +1,8 @@ +# Simple Send +Lets look at a very simple example of how you can import and use the websocket client in a piece of Rust code (`examples/simple.rs`). + +Simply importing the `nym_sdk` crate into your project allows you to create a client and send traffic through the mixnet. + +```rust,noplayground +{{#include ../../../../sdk/rust/nym-sdk/examples/simple.rs}} +``` diff --git a/documentation/docs/src/sdk/rust/examples/socks.md b/documentation/docs/src/sdk/rust/examples/socks.md new file mode 100644 index 0000000000..5e81780e2e --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/socks.md @@ -0,0 +1,10 @@ +# Socks Proxy +There is also the option to embed the [`socks5-client`](../../clients/socks5-client.md) into your app code (`examples/socks5.rs`): + +```admonish info +If you are looking at implementing Nym as a transport layer for a crypto wallet or desktop app, this is probably the best place to start if they can speak SOCKS5, 4a, or 4. +``` + +```rust,noplayground +{{#include ../../../../sdk/rust/nym-sdk/examples/socks5.rs}} +``` diff --git a/documentation/docs/src/sdk/rust/examples/split-send.md b/documentation/docs/src/sdk/rust/examples/split-send.md new file mode 100644 index 0000000000..32db90c17c --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/split-send.md @@ -0,0 +1,6 @@ +# Send and Receive in Different Tasks +If you need to split the different actions of your client across different tasks, you can do so like this: + +```rust, noplayground +{{#include ../../../../sdk/rust/nym-sdk/examples/parallel_sending_and_receiving.rs}} +``` diff --git a/documentation/docs/src/sdk/rust/examples/storage.md b/documentation/docs/src/sdk/rust/examples/storage.md new file mode 100644 index 0000000000..4d430f36ac --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/storage.md @@ -0,0 +1,6 @@ +# Manually Handled Storage +If you're integrating mixnet functionality into an existing app and want to integrate saving client configs and keys into your existing storage logic, you can manually perform the actions taken automatically above (`examples/manually_handle_keys_and_config.rs`) + +```rust,noplayground +{{#include ../../../../sdk/rust/nym-sdk/examples/manually_handle_storage.rs}} +``` diff --git a/documentation/docs/src/sdk/rust/examples/surbs.md b/documentation/docs/src/sdk/rust/examples/surbs.md new file mode 100644 index 0000000000..013b2e82e4 --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/surbs.md @@ -0,0 +1,16 @@ +# Anonymous Replies with SURBs (Single Use Reply Blocks) +Both functions used to send messages through the mixnet (`send_message` and `send_plain_message`) send a pre-determined number of SURBs along with their messages by default. + +The number of SURBs is set [here](https://github.com/nymtech/nym/blob/master/sdk/rust/nym-sdk/src/mixnet/client.rs#L33). + +```rust,noplayground +{{#include ../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:33}} +``` + +You can read more about how SURBs function under the hood [here](../../architecture/traffic-flow.md#private-replies-using-surbs). + +In order to reply to an incoming message using SURBs, you can construct a `recipient` from the `sender_tag` sent along with the message you wish to reply to: + +```rust,noplayground +{{#include ../../../../sdk/rust/nym-sdk/examples/surb-reply.rs}} +``` diff --git a/documentation/docs/src/sdk/rust/message-types.md b/documentation/docs/src/sdk/rust/message-types.md index 20d959b127..c5adf83377 100644 --- a/documentation/docs/src/sdk/rust/message-types.md +++ b/documentation/docs/src/sdk/rust/message-types.md @@ -1,7 +1,5 @@ # Message Types - -TODO expand! - +[//]: # (TODO expand! ) There are two methods for sending messages through the mixnet using your client: * `send_plain_message()` is the most simple: pass the recipient address and the message you wish to send as a string (this was previously `send_str()`). This is a nicer-to-use wrapper around `send_message()`. * `send_message()` allows you to also define the amount of SURBs to send along with your message (which is sent as bytes). diff --git a/documentation/docs/src/sdk/rust/rust.md b/documentation/docs/src/sdk/rust/rust.md index c593b3aa6e..2ce11c4ed3 100644 --- a/documentation/docs/src/sdk/rust/rust.md +++ b/documentation/docs/src/sdk/rust/rust.md @@ -29,116 +29,4 @@ nym-sdk = { git = "https://github.com/nymtech/nym" } ### Generate Crate Docs In order to generate the crate docs run `cargo doc --open` from `nym/sdk/rust/nym-sdk/` -## Websocket client examples -> All the codeblocks below can be found in the `nym-sdk` [examples directory](https://github.com/nymtech/nym/tree/master/sdk/rust/nym-sdk/examples) in the monorepo. Just navigate to `nym/sdk/rust/nym-sdk/examples/` and run the files from there. If you wish to run these outside of the workspace - such as if you want to use one as the basis for your own project - then make sure to import the `sdk`, `tokio`, and `nym_bin_common` crates. - -### Simple example -Lets look at a very simple example of how you can import and use the websocket client in a piece of Rust code (`examples/simple.rs`): - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/simple.rs}} -``` - -Simply importing the `nym_sdk` crate into your project allows you to create a client and send traffic through the mixnet. - -### Creating and storing keypairs -The example above involves ephemeral keys - if we want to create and then maintain a client identity over time, our code becomes a little more complex as we need to create, store, and conditionally load these keys (`examples/builder_with_storage`): - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/builder_with_storage.rs}} -``` - -As seen in the example above, the `mixnet::MixnetClientBuilder::new()` function handles checking for keys in a storage location, loading them if present, or creating them and storing them if not, making client key management very simple. - -Assuming our client config is stored in `/tmp/mixnet-client`, the following files are generated: -``` -$ tree /tmp/mixnet-client - -mixnet-client -├── ack_key.pem -├── db.sqlite -├── db.sqlite-shm -├── db.sqlite-wal -├── gateway_details.json -├── gateway_shared.pem -├── persistent_reply_store.sqlite -├── private_encryption.pem -├── private_identity.pem -├── public_encryption.pem -└── public_identity.pem - -1 directory, 11 files -``` - -### Manually handling storage -If you're integrating mixnet functionality into an existing app and want to integrate saving client configs and keys into your existing storage logic, you can manually perform the actions taken automatically above (`examples/manually_handle_keys_and_config.rs`) - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/manually_handle_storage.rs}} -``` - -### Anonymous replies with SURBs -Both functions used to send messages through the mixnet (`send_message` and `send_plain_message`) send a pre-determined number of SURBs along with their messages by default. - -The number of SURBs is set [here](https://github.com/nymtech/nym/blob/master/sdk/rust/nym-sdk/src/mixnet/client.rs#L33). - - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:33}} -``` - -You can read more about how SURBs function under the hood [here](../../architecture/traffic-flow.md#private-replies-using-surbs). - -In order to reply to an incoming message using SURBs, you can construct a `recipient` from the `sender_tag` sent along with the message you wish to reply to: - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/surb-reply.rs}} -``` - -### Importing and using a custom network topology -If you want to send traffic through a sub-set of nodes (for instance, ones you control, or a small test setup) when developing, debugging, or performing research, you will need to import these nodes as a custom network topology, instead of grabbing it from the [`Mainnet Nym-API`](https://validator.nymtech.net/api/swagger/index.html) (`examples/custom_topology_provider.rs`). - -There are two ways to do this: - -#### Import a custom Nym API endpoint -If you are also running a Validator and Nym API for your network, you can specify that endpoint as such and interact with it as clients usually do (under the hood): - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/custom_topology_provider.rs}} -``` - -#### Import a specific topology manually -If you aren't running a Validator and Nym API, and just want to import a specific sub-set of mix nodes, you can simply overwrite the grabbed topology manually: - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/manually_overwrite_topology.rs}} -``` - -### Send and receive in different tasks -If you need to split the different actions of your client across different tasks, you can do so like this: - -```rust, noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/parallel_sending_and_receiving.rs}} -``` - -## Socks client example -There is also the option to embed the [`socks5-client`](../../clients/socks5-client.md) into your app code (`examples/socks5.rs`): - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/socks5.rs}} -``` - -```admonish info -If you are looking at implementing Nym as a transport layer for a crypto wallet or desktop app, this is probably the best place to start. -``` - -## Coconut credential generation -The following code shows how you can use the SDK to create and use a [credential](../../bandwidth-credentials.md) representing paid bandwidth on the Sandbox testnet. - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/bandwidth.rs}} -``` - -You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](../../coconut.md). - From 1a6334f5484db0ceda09afcd7246ee21ef7e78ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 2 Nov 2023 08:38:26 +0100 Subject: [PATCH 186/236] ci: fix typo in workflow name --- .github/workflows/nightly-nym-connect-desktop-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly-nym-connect-desktop-build.yml b/.github/workflows/nightly-nym-connect-desktop-build.yml index a0705c6e1c..1022c342c1 100644 --- a/.github/workflows/nightly-nym-connect-desktop-build.yml +++ b/.github/workflows/nightly-nym-connect-desktop-build.yml @@ -1,4 +1,4 @@ -name: nightly-nym-wallet-build +name: nightly-nym-connect-build on: workflow_dispatch: From e5ef62d7e73a2099e1c0981b2df9e13461cc4971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Wed, 1 Nov 2023 15:51:44 +0100 Subject: [PATCH 187/236] ci: switch nightly-build to github hosted windows-latest --- .github/workflows/nightly-build.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 3365011f38..3dcabf2b28 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -11,7 +11,7 @@ jobs: fail-fast: false matrix: rust: [stable, beta] - os: [ubuntu-20.04, windows10, macos-latest] + os: [ubuntu-20.04, windows-latest, macos-latest] runs-on: ${{ matrix.os }} env: CARGO_TERM_COLOR: always @@ -34,7 +34,7 @@ jobs: - name: Install Protoc uses: arduino/setup-protoc@v2 - if: matrix.os == 'macos-latest' + if: matrix.os == 'macos-latest' || matrix.os == 'windows-latest' with: repo-token: ${{ secrets.GITHUB_TOKEN }} @@ -56,11 +56,20 @@ jobs: command: build args: --release --workspace --examples - - name: Set debug to false + # To avoid running out of disk space, skip generating debug symbols + - name: Set debug to false (unix) + if: matrix.os == 'ubuntu-20.04' || matrix.os == 'macos-latest' run: | sed -i.bak 's/\[profile.dev\]/\[profile.dev\]\ndebug = false/' Cargo.toml git diff + - name: Set debug to false (win) + if: matrix.os == 'windows-latest' + shell: pwsh + run: | + (Get-Content Cargo.toml) -replace '\[profile.dev\]', "`$&`ndebug = false" | Set-Content Cargo.toml + git diff + - name: Run unit tests uses: actions-rs/cargo@v1 with: From 48391d22529f519e55adb3691e494c72c635b1b0 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 2 Nov 2023 08:56:13 +0100 Subject: [PATCH 188/236] remove ./ from SUMMARY.md --- documentation/operators/src/SUMMARY.md | 33 +++++++++++++------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/documentation/operators/src/SUMMARY.md b/documentation/operators/src/SUMMARY.md index b349782408..5d1a7049bb 100644 --- a/documentation/operators/src/SUMMARY.md +++ b/documentation/operators/src/SUMMARY.md @@ -3,32 +3,33 @@ - [Introduction](introduction.md) # Binaries -- [Pre-built Binaries](./binaries/pre-built-binaries.md) - - [Binary Initialisation and Configuration](./binaries/init-and-config.md) -- [Building from Source](./binaries/building-nym.md) + +- [Pre-built Binaries](binaries/pre-built-binaries.md) + - [Binary Initialisation and Configuration](binaries/init-and-config.md) +- [Building from Source](binaries/building-nym.md) # Operators Guides -- [Mixnet Nodes Setup](./nodes/setup-guides.md) - - [Preliminary Steps](./preliminary-steps.md) - - [Mix Node](./nodes/mix-node-setup.md) - - [Gateway](./nodes/gateway-setup.md) - - [Network Requester](./nodes/network-requester-setup.md) -- [Nyx Validator Setup](./nodes/validator-setup.md) -- [Maintenance](./nodes/maintenance.md) -- [Troubleshooting](./nodes/troubleshooting.md) +- [Mixnet Nodes Setup](nodes/setup-guides.md) + - [Preliminary Steps](preliminary-steps.md) + - [Mix Node](nodes/mix-node-setup.md) + - [Gateway](nodes/gateway-setup.md) + - [Network Requester](nodes/network-requester-setup.md) +- [Nyx Validator Setup](nodes/validator-setup.md) +- [Maintenance](nodes/maintenance.md) +- [Troubleshooting](nodes/troubleshooting.md) # FAQ -- [Mix Nodes](./faq/mixnodes-faq.md) -- [Project Smoosh](./faq/smoosh-faq.md) +- [Mix Nodes](faq/mixnodes-faq.md) +- [Project Smoosh](faq/smoosh-faq.md) # Legal Forum -- [Exit Gateway](./legal/exit-gateway.md) - - [Switzerland](./legal/swiss.md) - - [United States](./legal/united-states.md) +- [Exit Gateway](legal/exit-gateway.md) + - [Switzerland](legal/swiss.md) + - [United States](legal/united-states.md) --- # Misc. From 06e656840aa9f36160099c340dcb53f7d5dd9630 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 2 Nov 2023 08:58:56 +0100 Subject: [PATCH 189/236] change syntax *binary* -> --- documentation/operators/src/faq/smoosh-faq.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index 99f31661a8..18930857e4 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -24,7 +24,7 @@ As we shared in our blog post article [*What does it take to build the wolds mos Project smoosh will have three steps: 1. Combine the `gateway` and `network-requester` into one binary ✅ -2. Create [Exit Gateway](../legal/exit-gateway.md): Take the gateway binary including network requester combined in \#1 and switch from [*allowed.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) ✅ +2. Create [Exit Gateway](../legal/exit-gateway.md): Take the gateway binary including network requester combined in \#1 and switch from [`allowed.list`](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) ✅ 3. Combine all the nodes in the Nym Mixnet into one binary, that is `mixnode`, `gateway` (entry and exit) and `network-requester`. These three steps will be staggered over time - period of several months, and will be implemented one by one with enough time to take in feedback and fix bugs in between. @@ -44,15 +44,15 @@ We created an [entire page](../legal/exit-gateway.md) about the technical and le ### What is the change from allow list to deny list? -The operators running Gateways would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short [*allowed.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a more permissive setup. An [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients. +The operators running Gateways would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short [`allowed.list`](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a more permissive setup. An [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients. ### How will the Exit policy be implemented? The progression of exit policy on Gateways will have three steps: -1. By default the [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) filtering will be disabled and the current [*allowed.list*](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) filtering is going to continue be used. This is to prevent operators getting surprised by upgrading their Gateways (or Network requesters) and suddenly be widely open to the internet. To enable the new exit policy, operators must use `--with-exit-policy` flag or modify the *config.toml* file. ✅ +1. By default the [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) filtering will be disabled and the current [`allowed.list`](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) filtering is going to continue be used. This is to prevent operators getting surprised by upgrading their Gateways (or Network requesters) and suddenly be widely open to the internet. To enable the new exit policy, operators must use `--with-exit-policy` flag or modify the `config.toml` file. ✅ 2. Relatively soon the exit policy will be part of the Gateway setup by default. To disable this exit policy, operators must use `--disable-exit-policy` flag. -3. Further down the line, it will be the only option. Then the *allowed.list* will be completely removed. +3. Further down the line, it will be the only option. Then the `allowed.list` will be completely removed. Keep in mind this only relates to changes happening on Gateway and Network Requester side. Whether this will be optional or mandatory depends on the chosen [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators). From 0f05f6e1ee19d7d743d4a6aeccced404068b1429 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 2 Nov 2023 09:06:33 +0100 Subject: [PATCH 190/236] change phrasing --- documentation/operators/src/faq/smoosh-faq.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index 18930857e4..c8c5ee875d 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -58,12 +58,12 @@ Keep in mind this only relates to changes happening on Gateway and Network Reque ### Can I run a mix node only? -Depends which [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators) will be the final one. In case of the first one - yes. In case of the second option, all the nodes will be setup with gateway functionality turned on. +It depends which [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators) will ultimately be used. In case of the first - yes. In case of the second option, all the nodes will be setup with Exit Gateway functionality turned on. ## Token Economics & Rewards ```admonish info -For any details on Nym token economics and Nym Mixnet reward system, please read [Nym token economics paper](https://nymtech.net/nym-cryptoecon-paper.pdf). +For any specifics on Nym token economics and Nym Mixnet reward system, please read the [Nym token economics paper](https://nymtech.net/nym-cryptoecon-paper.pdf). ``` ### What are the incentives for the node operator? @@ -84,6 +84,8 @@ The nodes which are initialized to run as mix nodes and gateways will be chosen I case we go with \#2, all nodes active in the epoch will be rewarded proportionally according their work. +In either way, Nym will share all the specifics beforehand. + ### How will be the staking and inflation after project Smoosh? We must run tests to see how many users pay. We may need to keep inflation on if not enough people pay to keep high quality gateways on in the early stage of the transition. From ca512ca1ad11b4764ddc6984f4bde89f8c5040e1 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 2 Nov 2023 09:10:13 +0100 Subject: [PATCH 191/236] change phrasing --- documentation/operators/src/faq/smoosh-faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index c8c5ee875d..5c8705eb60 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -88,7 +88,7 @@ In either way, Nym will share all the specifics beforehand. ### How will be the staking and inflation after project Smoosh? -We must run tests to see how many users pay. We may need to keep inflation on if not enough people pay to keep high quality gateways on in the early stage of the transition. +Nym will run tests to count how much payment comes from the users of the Mixnet and if that covers the reward payments. If not, we may need to keep inflation on to secure incentives for high quality gateways in the early stage of the transition. ### When project smooth will be launched, it would be the mixmining pool that will pay for the gateway rewards based on amount of traffic routed ? From 79d9ddd463637bb764921adebc97247e50f8cab7 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 2 Nov 2023 09:57:35 +0100 Subject: [PATCH 192/236] add correct cmdrun auto flow --- documentation/operators/src/nodes/gateway-setup.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index fc4988c943..62ea6dbe65 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -111,9 +111,8 @@ Say we have a gateway with `` as `new-gateway`, originally initialised and r ~~~admonish example collapsible=true title="Console output" ``` - - - + + ``` ~~~ From 9b93b30aede57b87f4f248012937f3f3501e05f9 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 2 Nov 2023 10:01:01 +0100 Subject: [PATCH 193/236] add reversed proxy ports --- documentation/operators/src/nodes/maintenance.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/documentation/operators/src/nodes/maintenance.md b/documentation/operators/src/nodes/maintenance.md index 6ee74d59ca..5a08724d61 100644 --- a/documentation/operators/src/nodes/maintenance.md +++ b/documentation/operators/src/nodes/maintenance.md @@ -239,6 +239,9 @@ Finally open your `` p2p port, as well as ports for ssh and ports for verl # for mix node, gateway and network requester sudo ufw allow 1789,1790,8000,9000,9001,22/tcp +# In case of reverse proxy for the Gateway swagger page add: +sudo ufw allow 8080,80/443 + # for validator sudo ufw allow 1317,26656,26660,22,80,443/tcp ``` From c667bb91c776715c66d447ac5b7faa1f594cffd4 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 10:24:03 +0100 Subject: [PATCH 194/236] tweak --- documentation/dev-portal/src/shipyard/challenges-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/dev-portal/src/shipyard/challenges-overview.md b/documentation/dev-portal/src/shipyard/challenges-overview.md index 0a815b2d42..4e02f5a797 100644 --- a/documentation/dev-portal/src/shipyard/challenges-overview.md +++ b/documentation/dev-portal/src/shipyard/challenges-overview.md @@ -8,7 +8,7 @@ The tooling challenge involves creating tooling for users, operators, or develop - Facilitate onboarding new users more easily to staking their Nym, and understanding the pros and cons, as well as finding a good node to stake on. Examples of tools like this: - [ExploreNym dashboard](https://explorenym.net/) -- Show information on a dashboard about the network. NOTE due to the amount of dashboards currently available, we expect a good justification for why / something to set this apart from existing ones e.g. it is presenting information that is not already presented, or it is presented in a different manner, such as a TUI or CLI app instead of a web dashboard - maybe an onion service, or no-JS site for those who do not wish to enable Javascript in their day to day browsing. Examples of tools like this: +- Show information on a dashboard about the network. NOTE due to the amount of dashboards currently available, we expect a good justification for why / something to set this apart from existing ones e.g. it is presenting information that is not already presented, or it is presented in a different manner, such as a TUI or CLI app instead of a web dashboard - maybe an onion service, or no-JS site for those who do not wish to enable Javascript in their day-to-day browsing. Examples of tools like this: - [NTV's node dashboard](https://status.notrustverify.ch/d/CW3L7dVVk/nym-mixnet?orgId=1) - [IsNymUp dashboard](https://isnymup.com/) From 6122817ab6018baf6a2d779f6323603a38f2dde9 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 10:24:25 +0100 Subject: [PATCH 195/236] fixed broken link --- documentation/docs/mdbook-admonish.css | 172 ++++++++++-------- .../docs/src/architecture/traffic-flow.md | 4 +- 2 files changed, 94 insertions(+), 82 deletions(-) diff --git a/documentation/docs/mdbook-admonish.css b/documentation/docs/mdbook-admonish.css index e0a3365532..244bc9ade7 100644 --- a/documentation/docs/mdbook-admonish.css +++ b/documentation/docs/mdbook-admonish.css @@ -1,18 +1,31 @@ @charset "UTF-8"; :root { - --md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,"); - --md-details-icon: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--note: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--abstract: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--info: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--tip: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--success: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--question: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--warning: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--failure: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--danger: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--bug: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--example: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--quote: + url("data:image/svg+xml;charset=utf-8,"); + --md-details-icon: + url("data:image/svg+xml;charset=utf-8,"); } :is(.admonition) { @@ -62,7 +75,7 @@ a.admonition-anchor-link::before { content: "§"; } -:is(.admonition-title, summary.admonition-title) { +:is(.admonition-title, summary) { position: relative; min-height: 4rem; margin-block: 0; @@ -73,13 +86,13 @@ a.admonition-anchor-link::before { background-color: rgba(68, 138, 255, 0.1); display: flex; } -:is(.admonition-title, summary.admonition-title) p { +:is(.admonition-title, summary) p { margin: 0; } -html :is(.admonition-title, summary.admonition-title):last-child { +html :is(.admonition-title, summary):last-child { margin-bottom: 0; } -:is(.admonition-title, summary.admonition-title)::before { +:is(.admonition-title, summary)::before { position: absolute; top: 0.625em; inset-inline-start: 1.6rem; @@ -94,7 +107,7 @@ html :is(.admonition-title, summary.admonition-title):last-child { -webkit-mask-size: contain; content: ""; } -:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link { +:is(.admonition-title, summary):hover a.admonition-anchor-link { display: initial; } @@ -119,204 +132,204 @@ details[open].admonition > summary.admonition-title::after { transform: rotate(90deg); } -:is(.admonition):is(.admonish-note) { +:is(.admonition):is(.note) { border-color: #448aff; } -:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) { +:is(.note) > :is(.admonition-title, summary) { background-color: rgba(68, 138, 255, 0.1); } -:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before { +:is(.note) > :is(.admonition-title, summary)::before { background-color: #448aff; - mask-image: var(--md-admonition-icon--admonish-note); - -webkit-mask-image: var(--md-admonition-icon--admonish-note); + mask-image: var(--md-admonition-icon--note); + -webkit-mask-image: var(--md-admonition-icon--note); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) { +:is(.admonition):is(.abstract, .summary, .tldr) { border-color: #00b0ff; } -:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) { +:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary) { background-color: rgba(0, 176, 255, 0.1); } -:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before { +:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary)::before { background-color: #00b0ff; - mask-image: var(--md-admonition-icon--admonish-abstract); - -webkit-mask-image: var(--md-admonition-icon--admonish-abstract); + mask-image: var(--md-admonition-icon--abstract); + -webkit-mask-image: var(--md-admonition-icon--abstract); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-info, .admonish-todo) { +:is(.admonition):is(.info, .todo) { border-color: #00b8d4; } -:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) { +:is(.info, .todo) > :is(.admonition-title, summary) { background-color: rgba(0, 184, 212, 0.1); } -:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before { +:is(.info, .todo) > :is(.admonition-title, summary)::before { background-color: #00b8d4; - mask-image: var(--md-admonition-icon--admonish-info); - -webkit-mask-image: var(--md-admonition-icon--admonish-info); + mask-image: var(--md-admonition-icon--info); + -webkit-mask-image: var(--md-admonition-icon--info); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) { +:is(.admonition):is(.tip, .hint, .important) { border-color: #00bfa5; } -:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) { +:is(.tip, .hint, .important) > :is(.admonition-title, summary) { background-color: rgba(0, 191, 165, 0.1); } -:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before { +:is(.tip, .hint, .important) > :is(.admonition-title, summary)::before { background-color: #00bfa5; - mask-image: var(--md-admonition-icon--admonish-tip); - -webkit-mask-image: var(--md-admonition-icon--admonish-tip); + mask-image: var(--md-admonition-icon--tip); + -webkit-mask-image: var(--md-admonition-icon--tip); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) { +:is(.admonition):is(.success, .check, .done) { border-color: #00c853; } -:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) { +:is(.success, .check, .done) > :is(.admonition-title, summary) { background-color: rgba(0, 200, 83, 0.1); } -:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before { +:is(.success, .check, .done) > :is(.admonition-title, summary)::before { background-color: #00c853; - mask-image: var(--md-admonition-icon--admonish-success); - -webkit-mask-image: var(--md-admonition-icon--admonish-success); + mask-image: var(--md-admonition-icon--success); + -webkit-mask-image: var(--md-admonition-icon--success); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) { +:is(.admonition):is(.question, .help, .faq) { border-color: #64dd17; } -:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) { +:is(.question, .help, .faq) > :is(.admonition-title, summary) { background-color: rgba(100, 221, 23, 0.1); } -:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before { +:is(.question, .help, .faq) > :is(.admonition-title, summary)::before { background-color: #64dd17; - mask-image: var(--md-admonition-icon--admonish-question); - -webkit-mask-image: var(--md-admonition-icon--admonish-question); + mask-image: var(--md-admonition-icon--question); + -webkit-mask-image: var(--md-admonition-icon--question); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) { +:is(.admonition):is(.warning, .caution, .attention) { border-color: #ff9100; } -:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) { +:is(.warning, .caution, .attention) > :is(.admonition-title, summary) { background-color: rgba(255, 145, 0, 0.1); } -:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before { +:is(.warning, .caution, .attention) > :is(.admonition-title, summary)::before { background-color: #ff9100; - mask-image: var(--md-admonition-icon--admonish-warning); - -webkit-mask-image: var(--md-admonition-icon--admonish-warning); + mask-image: var(--md-admonition-icon--warning); + -webkit-mask-image: var(--md-admonition-icon--warning); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) { +:is(.admonition):is(.failure, .fail, .missing) { border-color: #ff5252; } -:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) { +:is(.failure, .fail, .missing) > :is(.admonition-title, summary) { background-color: rgba(255, 82, 82, 0.1); } -:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before { +:is(.failure, .fail, .missing) > :is(.admonition-title, summary)::before { background-color: #ff5252; - mask-image: var(--md-admonition-icon--admonish-failure); - -webkit-mask-image: var(--md-admonition-icon--admonish-failure); + mask-image: var(--md-admonition-icon--failure); + -webkit-mask-image: var(--md-admonition-icon--failure); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-danger, .admonish-error) { +:is(.admonition):is(.danger, .error) { border-color: #ff1744; } -:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) { +:is(.danger, .error) > :is(.admonition-title, summary) { background-color: rgba(255, 23, 68, 0.1); } -:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before { +:is(.danger, .error) > :is(.admonition-title, summary)::before { background-color: #ff1744; - mask-image: var(--md-admonition-icon--admonish-danger); - -webkit-mask-image: var(--md-admonition-icon--admonish-danger); + mask-image: var(--md-admonition-icon--danger); + -webkit-mask-image: var(--md-admonition-icon--danger); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-bug) { +:is(.admonition):is(.bug) { border-color: #f50057; } -:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) { +:is(.bug) > :is(.admonition-title, summary) { background-color: rgba(245, 0, 87, 0.1); } -:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before { +:is(.bug) > :is(.admonition-title, summary)::before { background-color: #f50057; - mask-image: var(--md-admonition-icon--admonish-bug); - -webkit-mask-image: var(--md-admonition-icon--admonish-bug); + mask-image: var(--md-admonition-icon--bug); + -webkit-mask-image: var(--md-admonition-icon--bug); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-example) { +:is(.admonition):is(.example) { border-color: #7c4dff; } -:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) { +:is(.example) > :is(.admonition-title, summary) { background-color: rgba(124, 77, 255, 0.1); } -:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before { +:is(.example) > :is(.admonition-title, summary)::before { background-color: #7c4dff; - mask-image: var(--md-admonition-icon--admonish-example); - -webkit-mask-image: var(--md-admonition-icon--admonish-example); + mask-image: var(--md-admonition-icon--example); + -webkit-mask-image: var(--md-admonition-icon--example); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-quote, .admonish-cite) { +:is(.admonition):is(.quote, .cite) { border-color: #9e9e9e; } -:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) { +:is(.quote, .cite) > :is(.admonition-title, summary) { background-color: rgba(158, 158, 158, 0.1); } -:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before { +:is(.quote, .cite) > :is(.admonition-title, summary)::before { background-color: #9e9e9e; - mask-image: var(--md-admonition-icon--admonish-quote); - -webkit-mask-image: var(--md-admonition-icon--admonish-quote); + mask-image: var(--md-admonition-icon--quote); + -webkit-mask-image: var(--md-admonition-icon--quote); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; @@ -327,8 +340,7 @@ details[open].admonition > summary.admonition-title::after { background-color: var(--sidebar-bg); } -.ayu :is(.admonition), -.coal :is(.admonition) { +.ayu :is(.admonition), .coal :is(.admonition) { background-color: var(--theme-hover); } diff --git a/documentation/docs/src/architecture/traffic-flow.md b/documentation/docs/src/architecture/traffic-flow.md index 09a2501abd..863a03f577 100644 --- a/documentation/docs/src/architecture/traffic-flow.md +++ b/documentation/docs/src/architecture/traffic-flow.md @@ -5,7 +5,7 @@ When you send data across the internet, it can be recorded by a wide range of ob Even if the content of a network request is encrypted, observers can still see that data was transmitted, its size, frequency of transmission, and gather metadata from unencrypted parts of the data (such as IP routing information). Adversaries may then combine all the leaked information to probabilistically de-anonymize users. -The Nym mixnet provides very strong security guarantees against this sort of surveillance. It _packetizes_ and _mixes_ together IP traffic from many users inside the _mixnet_. +The Nym mixnet provides very strong security guarantees against this sort of surveillance. It _packetises_ and _mixes_ together IP traffic from many users inside the _mixnet_. > If you're into comparisons, the Nym mixnet is conceptually similar to other systems such as Tor, but provides improved protections against end-to-end timing attacks which can de-anonymize users. When Tor was first fielded, in 2002, those kinds of attacks were regarded as science fiction. But the future is now here. @@ -69,7 +69,7 @@ From your Nym client, your encrypted traffic is sent to: Whatever is on the 'other side' of the mixnet from your client, all traffic will travel this way through the mixnet. If you are sending traffic to a service external to Nym (such as a chat application's servers) then your traffic will be sent from the recieving Nym client to an application that will proxy it 'out' of the mixnet to these servers, shielding your metadata from them. P2P (peer-to-peer) applications, unlike the majority of apps, might want to keep all of their traffic entirely 'within' the mixnet, as they don't have to necessarily make outbound network requests to application servers. They would simply have their local application code communicate with their Nym clients, and not forward traffic anywhere 'outside' of the mixnet. ## Acks & Package Retransmission -Whenever a hop is completed, the recieving node will send back an acknowledgement ('ack') so that the sending node knows that the packet was recieved. If it does not recieve an ack after sending, it will resend the packet, as it assumes that the packet was dropped for some reason. This is done under the hood by the binaries themselves, and is never something that developers and node operators have to worry about dealing with themselves. +Whenever a hop is completed, the receiving node will send back an acknowledgement ('ack') so that the sending node knows that the packet was received. If it does not receive an ack after sending, it will resend the packet, as it assumes that the packet was dropped for some reason. This is done under the hood by the binaries themselves, and is never something that developers and node operators have to worry about dealing with themselves. Packet retransmission means that if a client sends 100 packets to a gateway, but only receives an acknowledgement ('ack') for 95 of them, it will resend those 5 packets to the gateway again, to make sure that all packets are received. All nodes in the mixnet support packet retransmission. From aa7dd1ecf96d10f6f90739eea694ea8bee143787 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 10:24:46 +0100 Subject: [PATCH 196/236] admonish plugin upgrade --- documentation/docs/book.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/documentation/docs/book.toml b/documentation/docs/book.toml index 093c35eea0..a11f82cbbd 100644 --- a/documentation/docs/book.toml +++ b/documentation/docs/book.toml @@ -6,6 +6,9 @@ language = "en" multilingual = false # for the moment - ideally work on chinese, brazillian, spanish next src = "src" +[rust] +edition = "2018" + ################# # PREPROCESSORS # ################# @@ -42,7 +45,7 @@ turn-off = true [preprocessor.admonish] command = "mdbook-admonish" -assets_version = "3.0.0" # do not edit: managed by `mdbook-admonish install` +assets_version = "2.0.1" # do not edit: managed by `mdbook-admonish install` # variables preprocessor: import variables into files # https://gitlab.com/tglman/mdbook-variables/ From bc21fa3a7ed611c4a65f5772861f93de86de190f Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 10:25:10 +0100 Subject: [PATCH 197/236] fix broken imports --- documentation/docs/src/sdk/rust/examples/credential.md | 6 +++--- documentation/docs/src/sdk/rust/examples/custom-network.md | 4 ++-- documentation/docs/src/sdk/rust/examples/keys.md | 2 +- documentation/docs/src/sdk/rust/examples/simple.md | 2 +- documentation/docs/src/sdk/rust/examples/socks.md | 4 ++-- documentation/docs/src/sdk/rust/examples/split-send.md | 2 +- documentation/docs/src/sdk/rust/examples/storage.md | 2 +- documentation/docs/src/sdk/rust/examples/surbs.md | 6 +++--- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/documentation/docs/src/sdk/rust/examples/credential.md b/documentation/docs/src/sdk/rust/examples/credential.md index d0fe29bbbd..e62cfb454a 100644 --- a/documentation/docs/src/sdk/rust/examples/credential.md +++ b/documentation/docs/src/sdk/rust/examples/credential.md @@ -1,9 +1,9 @@ # Coconut credential generation -The following code shows how you can use the SDK to create and use a [credential](../../bandwidth-credentials.md) representing paid bandwidth on the Sandbox testnet. +The following code shows how you can use the SDK to create and use a [credential](../../../bandwidth-credentials.md) representing paid bandwidth on the Sandbox testnet. ```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/bandwidth.rs}} +{{#include ../../../../../../sdk/rust/nym-sdk/examples/bandwidth.rs}} ``` -You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](../../coconut.md). +You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](../../../coconut.md). diff --git a/documentation/docs/src/sdk/rust/examples/custom-network.md b/documentation/docs/src/sdk/rust/examples/custom-network.md index 0ad226f953..ae0f145a3b 100644 --- a/documentation/docs/src/sdk/rust/examples/custom-network.md +++ b/documentation/docs/src/sdk/rust/examples/custom-network.md @@ -7,12 +7,12 @@ There are two ways to do this: If you are also running a Validator and Nym API for your network, you can specify that endpoint as such and interact with it as clients usually do (under the hood): ```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/custom_topology_provider.rs}} +{{#include ../../../../../../sdk/rust/nym-sdk/examples/custom_topology_provider.rs}} ``` ## Import a specific topology manually If you aren't running a Validator and Nym API, and just want to import a specific sub-set of mix nodes, you can simply overwrite the grabbed topology manually: ```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/manually_overwrite_topology.rs}} +{{#include ../../../../../../sdk/rust/nym-sdk/examples/manually_overwrite_topology.rs}} ``` diff --git a/documentation/docs/src/sdk/rust/examples/keys.md b/documentation/docs/src/sdk/rust/examples/keys.md index 6e2f66d986..84746dcfd6 100644 --- a/documentation/docs/src/sdk/rust/examples/keys.md +++ b/documentation/docs/src/sdk/rust/examples/keys.md @@ -2,7 +2,7 @@ The previous example involves ephemeral keys - if we want to create and then maintain a client identity over time, our code becomes a little more complex as we need to create, store, and conditionally load these keys (`examples/builder_with_storage`): ```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/builder_with_storage.rs}} +{{#include ../../../../../../sdk/rust/nym-sdk/examples/builder_with_storage.rs}} ``` As seen in the example above, the `mixnet::MixnetClientBuilder::new()` function handles checking for keys in a storage location, loading them if present, or creating them and storing them if not, making client key management very simple. diff --git a/documentation/docs/src/sdk/rust/examples/simple.md b/documentation/docs/src/sdk/rust/examples/simple.md index b3d5f9d268..20872ce96b 100644 --- a/documentation/docs/src/sdk/rust/examples/simple.md +++ b/documentation/docs/src/sdk/rust/examples/simple.md @@ -4,5 +4,5 @@ Lets look at a very simple example of how you can import and use the websocket c Simply importing the `nym_sdk` crate into your project allows you to create a client and send traffic through the mixnet. ```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/simple.rs}} +{{#include ../../../../../../sdk/rust/nym-sdk/examples/simple.rs}} ``` diff --git a/documentation/docs/src/sdk/rust/examples/socks.md b/documentation/docs/src/sdk/rust/examples/socks.md index 5e81780e2e..de027e9011 100644 --- a/documentation/docs/src/sdk/rust/examples/socks.md +++ b/documentation/docs/src/sdk/rust/examples/socks.md @@ -1,10 +1,10 @@ # Socks Proxy -There is also the option to embed the [`socks5-client`](../../clients/socks5-client.md) into your app code (`examples/socks5.rs`): +There is also the option to embed the [`socks5-client`](../../../clients/socks5-client.md) into your app code (`examples/socks5.rs`): ```admonish info If you are looking at implementing Nym as a transport layer for a crypto wallet or desktop app, this is probably the best place to start if they can speak SOCKS5, 4a, or 4. ``` ```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/socks5.rs}} +{{#include ../../../../../../sdk/rust/nym-sdk/examples/socks5.rs}} ``` diff --git a/documentation/docs/src/sdk/rust/examples/split-send.md b/documentation/docs/src/sdk/rust/examples/split-send.md index 32db90c17c..6b7cf69789 100644 --- a/documentation/docs/src/sdk/rust/examples/split-send.md +++ b/documentation/docs/src/sdk/rust/examples/split-send.md @@ -2,5 +2,5 @@ If you need to split the different actions of your client across different tasks, you can do so like this: ```rust, noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/parallel_sending_and_receiving.rs}} +{{#include ../../../../../../sdk/rust/nym-sdk/examples/parallel_sending_and_receiving.rs}} ``` diff --git a/documentation/docs/src/sdk/rust/examples/storage.md b/documentation/docs/src/sdk/rust/examples/storage.md index 4d430f36ac..bc68bca9ff 100644 --- a/documentation/docs/src/sdk/rust/examples/storage.md +++ b/documentation/docs/src/sdk/rust/examples/storage.md @@ -2,5 +2,5 @@ If you're integrating mixnet functionality into an existing app and want to integrate saving client configs and keys into your existing storage logic, you can manually perform the actions taken automatically above (`examples/manually_handle_keys_and_config.rs`) ```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/manually_handle_storage.rs}} +{{#include ../../../../../../sdk/rust/nym-sdk/examples/manually_handle_storage.rs}} ``` diff --git a/documentation/docs/src/sdk/rust/examples/surbs.md b/documentation/docs/src/sdk/rust/examples/surbs.md index 013b2e82e4..404d74ba1d 100644 --- a/documentation/docs/src/sdk/rust/examples/surbs.md +++ b/documentation/docs/src/sdk/rust/examples/surbs.md @@ -4,13 +4,13 @@ Both functions used to send messages through the mixnet (`send_message` and `sen The number of SURBs is set [here](https://github.com/nymtech/nym/blob/master/sdk/rust/nym-sdk/src/mixnet/client.rs#L33). ```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:33}} +{{#include ../../../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:33}} ``` -You can read more about how SURBs function under the hood [here](../../architecture/traffic-flow.md#private-replies-using-surbs). +You can read more about how SURBs function under the hood [here](../../../architecture/traffic-flow.md#private-replies-using-surbs). In order to reply to an incoming message using SURBs, you can construct a `recipient` from the `sender_tag` sent along with the message you wish to reply to: ```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/surb-reply.rs}} +{{#include ../../../../../../sdk/rust/nym-sdk/examples/surb-reply.rs}} ``` From 2334109721814bd170e8dc9126b83ac32baebf55 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 10:25:37 +0100 Subject: [PATCH 198/236] tweak --- documentation/docs/src/sdk/rust/examples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/src/sdk/rust/examples.md b/documentation/docs/src/sdk/rust/examples.md index e612a7d59d..648c32fa0d 100644 --- a/documentation/docs/src/sdk/rust/examples.md +++ b/documentation/docs/src/sdk/rust/examples.md @@ -8,5 +8,5 @@ cargo run --example If you wish to run these outside of the workspace - such as if you want to use one as the basis for your own project - then make sure to import the `sdk`, `tokio`, and `nym_bin_common` crates. -An example `Cargo.toml` file can be found in the examples folder. +An example `Cargo.toml` file can be found [here](examples/cargo.md). From 9a592df4f0668df24cbb0fef66142d969189d7e7 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 10:26:07 +0100 Subject: [PATCH 199/236] updated import info --- documentation/docs/src/sdk/rust/rust.md | 18 +++++++++++++++++- .../docs/src/sdk/rust/troubleshooting.md | 5 +++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/documentation/docs/src/sdk/rust/rust.md b/documentation/docs/src/sdk/rust/rust.md index 2ce11c4ed3..3062e1ff32 100644 --- a/documentation/docs/src/sdk/rust/rust.md +++ b/documentation/docs/src/sdk/rust/rust.md @@ -21,11 +21,27 @@ The SDK is still somewhat a work in progress: interfaces are fairly stable but s ### Installation The `nym-sdk` crate is **not yet available via [crates.io](https://crates.io)**. As such, in order to import the crate you must specify the Nym monorepo in your `Cargo.toml` file: -TODO add note on branch import for stability - `master` should be last release ```toml nym-sdk = { git = "https://github.com/nymtech/nym" } ``` +By default the above command will import the current `HEAD` of the default branch, which in our case is `develop`. Assuming instead you wish to pull in another branch (e.g. `master` or a particular release) you can specify this like so: + +```toml +# importing HEAD of master branch +nym-sdk = { git = "https://github.com/nymtech/nym", branch = "master" } +# importing HEAD of the third release of 2023, codename 'kinder' +nym-sdk = { git = "https://github.com/nymtech/nym", branch = "release/2023.3-kinder" } +``` + +You can also define a particular git commit to use as your import like so: + +```toml +nym-sdk = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" } +``` + +Since the `HEAD` of `master` is always the most recent release, we recommend developers use that for their imports, unless they have a reason to pull in a specific historic version of the code. + ### Generate Crate Docs In order to generate the crate docs run `cargo doc --open` from `nym/sdk/rust/nym-sdk/` diff --git a/documentation/docs/src/sdk/rust/troubleshooting.md b/documentation/docs/src/sdk/rust/troubleshooting.md index c8de2e5e37..51676ff6ec 100644 --- a/documentation/docs/src/sdk/rust/troubleshooting.md +++ b/documentation/docs/src/sdk/rust/troubleshooting.md @@ -1,3 +1,4 @@ # Troubleshooting -TODO note on poisson dance and not immediately killing client process -TODO note on listening for non-empty messages and point towards helpers +TODO note on 'task client is being dropped' +TODO note on poisson dance and not immediately killing client process +TODO note on listening for non-empty messages and point towards helpers From 082886ab19e52ea9824d3ca9c1272c67e6d81977 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 10:35:57 +0100 Subject: [PATCH 200/236] removed todo - checked dependency versioning --- documentation/docs/src/sdk/rust/examples/cargo.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/documentation/docs/src/sdk/rust/examples/cargo.md b/documentation/docs/src/sdk/rust/examples/cargo.md index 4c96e05fc5..e425e124ed 100644 --- a/documentation/docs/src/sdk/rust/examples/cargo.md +++ b/documentation/docs/src/sdk/rust/examples/cargo.md @@ -1,7 +1,6 @@ # Example Cargo File This file imports the basic requirements for running these pieces of example code, and can be used as the basis for your own cargo project. -TODO versioning check ```toml [package] name = "your_app" @@ -17,13 +16,13 @@ tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] } serde = "1.0.152" serde_json = "1.0.91" # Nym clients, addressing, etc -nym-sdk = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" } -nym-sphinx-addressing = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" } -nym-bin-common = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" } -nym-sphinx-anonymous-replies = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" } +nym-sdk = { git = "https://github.com/nymtech/nym", branch = "master" } +nym-sphinx-addressing = { git = "https://github.com/nymtech/nym", branch = "master" } +nym-bin-common = { git = "https://github.com/nymtech/nym", branch = "master" } +nym-sphinx-anonymous-replies = { git = "https://github.com/nymtech/nym", branch = "master" } # Additional dependencies if you're interacting with Nyx or another Cosmos SDK blockchain cosmrs = "=0.14.0" -nym-validator-client = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" } +nym-validator-client = { git = "https://github.com/nymtech/nym", branch = "master" } # If you're building an app with a client and server / serivce this might be a useful structure for your repo [[bin]] From 01605534f7185b7b876e04b96c34abaaaf1a6d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 2 Nov 2023 07:43:45 +0100 Subject: [PATCH 201/236] ci: change nightly-nym-wallet-build to windows-latest --- .github/workflows/nightly-nym-wallet-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly-nym-wallet-build.yml b/.github/workflows/nightly-nym-wallet-build.yml index 1cdb70def2..b310ca4fa0 100644 --- a/.github/workflows/nightly-nym-wallet-build.yml +++ b/.github/workflows/nightly-nym-wallet-build.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-20.04, macos-latest, windows10] + os: [ubuntu-20.04, macos-latest, windows-latest] runs-on: ${{ matrix.os }} env: CARGO_TERM_COLOR: always From b9088a8ddad1e5589dd0f291a4633c489efc9a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 2 Nov 2023 07:46:32 +0100 Subject: [PATCH 202/236] ci: switch nightly-nym-connect-desktop-build to windows-latest --- .github/workflows/nightly-nym-connect-desktop-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nightly-nym-connect-desktop-build.yml b/.github/workflows/nightly-nym-connect-desktop-build.yml index 1022c342c1..1e4560f979 100644 --- a/.github/workflows/nightly-nym-connect-desktop-build.yml +++ b/.github/workflows/nightly-nym-connect-desktop-build.yml @@ -1,4 +1,4 @@ -name: nightly-nym-connect-build +name: nightly-nym-connect-desktop-build on: workflow_dispatch: @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-20.04, macos-latest, windows10] + os: [ubuntu-20.04, macos-latest, windows-latest] runs-on: ${{ matrix.os }} env: CARGO_TERM_COLOR: always From 0173bc748bf717c05c90ca3b809afb206aba49d3 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Thu, 2 Nov 2023 11:56:31 +0100 Subject: [PATCH 203/236] add smoosh link to intro --- documentation/operators/src/legal/exit-gateway.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index 328633faf2..4cac80d7de 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -6,8 +6,9 @@ The entire content of this page is under [Creative Commons Attribution 4.0 Inter This page is a part of Nym Community Legal Forum and its content is composed by shared advices in [Node Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) (Matrix chat) as well as though pull requests done by the node operators directly to our [repository](https://github.com/nymtech/nym/tree/develop/documentation/operators/src), reviewed by Nym DevRels. -This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating gateways and opening these to any online service. Such setup needs a **clear policy**, one which will remain the **same for all operators** running Nym nodes. The [proposed **Exit policy**](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) is a combination of two existing safeguards: [Tor Null ‘deny’ list](https://tornull.org/) and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). +This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating Gateways and opening these to any online service. Such setup needs a **clear policy**, one which will remain the **same for all operators** running Nym nodes. The [proposed **Exit policy**](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) is a combination of two existing safeguards: [Tor Null ‘deny’ list](https://tornull.org/) and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). +All the technical changes on the side of Nym nodes - ***Project Smoosh** - are described in the [FAQ section](../faq/smoosh-faq.md). ```admonish warning Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the operator channels ([Element](https://matrix.to/#/#operators:nymtech.chat), [Discord](https://discord.com/invite/nym), [Telegram](https://t.me/nymchan_help_chat)) to share best practices and experiences. @@ -54,7 +55,7 @@ Previous setup: Running nodes supporting strict SOCKS5 app-based traffic | Financial | | - Low revenues for operators due to limited product traction | -The new setup: Running nodes supporting traffic of any online service (with safeguards in the form of an denylist) +The new setup: Running nodes supporting traffic of any online service (with safeguards in the form of a denylist) | **Dimension** | **Pros** | **Cons** | | :--- | :--- | :--- | From 72553623a76ff15a0b4d040af6dcc90aaee45dab Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 13:10:05 +0100 Subject: [PATCH 204/236] first pass at troubleshooting doc --- .../docs/src/sdk/rust/troubleshooting.md | 117 +++++++++++++++++- 1 file changed, 114 insertions(+), 3 deletions(-) diff --git a/documentation/docs/src/sdk/rust/troubleshooting.md b/documentation/docs/src/sdk/rust/troubleshooting.md index 51676ff6ec..458a4eaab4 100644 --- a/documentation/docs/src/sdk/rust/troubleshooting.md +++ b/documentation/docs/src/sdk/rust/troubleshooting.md @@ -1,4 +1,115 @@ # Troubleshooting -TODO note on 'task client is being dropped' -TODO note on poisson dance and not immediately killing client process -TODO note on listening for non-empty messages and point towards helpers +Below are several common issues or questions you may have. + +If you come across something that isn't explained here, [PRs are welcome](https://github.com/nymtech/nym/issues/new/choose). + +## Verbose `task client is being dropped` logging +### On client shutdown (expected) +If this is happening at the end of your code when disconnecting your client, this is fine; we just have a verbose client! When calling `client.disconnect().await` this is simply informing you that the client is shutting down. + +On client shutdown / disconnect this is to be expected - this can be seen in many of the code examples as well. We use the [`nym_bin_common::logging`](https://github.com/nymtech/nym/blob/develop/common/bin-common/src/logging/mod.rs) import to set logging in our example code. This defaults to `INFO` level. + +If you wish to quickly lower the verbosity of your client process logs when developing you can prepend your command with `RUST_LOG=`. + +If you want to run the `builder.rs` example with only `WARN` level logging and below: + +```sh +cargo run --example builder +``` + +Becomes: + +```sh +RUST_LOG=warn cargo run --example builder +``` + +You can also make the logging _more_ verbose with: + +```sh +RUST_LOG=debug cargo run --example builder +``` + +### Not on client shutdown (unexpected) +If this is happening unexpectedly then you might be shutting your client process down too early. See the [accidentally killing your client process](#accidentally-killing-your-client-process-too-early) below for possible explanations and how to fix this issue. + +[//]: # (TODO note on poisson dance and not immediately killing client process) +## Accidentally killing your client process too early +If you are seeing either of the following errors when trying to run a client, specifically sending a message, then you may be accidentally killing your client process. + +```sh + 2023-11-02T10:31:03.930Z INFO TaskClient-BaseNymClient-real_traffic_controller-ack_control-action_controller > the task client is getting dropped + 2023-11-02T10:31:04.625Z INFO TaskClient-BaseNymClient-received_messages_buffer-request_receiver > the task client is getting dropped + 2023-11-02T10:31:04.626Z DEBUG nym_client_core::client::real_messages_control::acknowledgement_control::input_message_listener > InputMessageListener: Exiting + 2023-11-02T10:31:04.626Z INFO TaskClient-BaseNymClient-real_traffic_controller-ack_control-input_message_listener > the task client is getting dropped + 2023-11-02T10:31:04.626Z INFO TaskClient-BaseNymClient-real_traffic_controller-reply_control > the task client is getting dropped + 2023-11-02T10:31:04.626Z DEBUG nym_client_core::client::real_messages_control > The reply controller has finished execution! + 2023-11-02T10:31:04.626Z DEBUG nym_client_core::client::real_messages_control::acknowledgement_control > The input listener has finished execution! + 2023-11-02T10:31:04.626Z INFO nym_task::manager > All registered tasks succesfully shutdown +``` + +```sh + 2023-11-02T11:22:08.408Z ERROR TaskClient-BaseNymClient-topology_refresher > Assuming this means we should shutdown... + 2023-11-02T11:22:08.408Z ERROR TaskClient-BaseNymClient-mix_traffic_controller > Polling shutdown failed: channel closed + 2023-11-02T11:22:08.408Z INFO TaskClient-BaseNymClient-gateway_transceiver-child > the task client is getting dropped + 2023-11-02T11:22:08.408Z ERROR TaskClient-BaseNymClient-mix_traffic_controller > Assuming this means we should shutdown... +thread 'tokio-runtime-worker' panicked at 'action control task has died: TrySendError { kind: Disconnected }', /home/.local/share/cargo/git/checkouts/nym-fbd2f6ea2e760da9/a800cba/common/client-core/src/client/real_messages_control/message_handler.rs:634:14 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + 2023-11-02T11:22:08.477Z INFO TaskClient-BaseNymClient-real_traffic_controller-ack_control-input_message_listener > the task client is getting dropped + 2023-11-02T11:22:08.477Z ERROR TaskClient-BaseNymClient-real_traffic_controller-ack_control-input_message_listener > Polling shutdown failed: channel closed + 2023-11-02T11:22:08.477Z ERROR TaskClient-BaseNymClient-real_traffic_controller-ack_control-input_message_listener > Assuming this means we should shutdown... +``` + +Using the following piece of code as an example: + +```rust +use nym_sdk::mixnet::{MixnetClient, MixnetMessageSender, Recipient}; +use clap::Parser; + +#[derive(Debug, Clone, Parser)] +enum Opts { + Client { + recipient: Recipient + } +} + +#[tokio::main] +async fn main() { + let opts: Opts = Parser::parse(); + nym_bin_common::logging::setup_logging(); + + let mut nym_client = MixnetClient::connect_new().await.expect("Could not build Nym client"); + + match opts { + Opts::Client { recipient } => { + nym_client.send_plain_message(recipient, "some message string").await.expect("send failed"); + } + } +} +``` + +This is a simplified snippet of code for sending a simple hardcoded message with the following command: + +```sh +cargo run client +``` + +You might assume that `send`-ing your message would _just work_ as `nym_client.send_plain_message()` is an async function; you might expect that the client will block until the message is actually sent into the mixnet, then shutdown. + +However, this is not true. + +**This will only block until the message is put into client's internal queue**. Therefore in the above example, the client is being shut down before the message is _actually sent to the mixnet_; after being placed in the client's internal queue, there is still work to be done under the hood, such as route encrypting the message and placing it amongst the stream of cover traffic. + +The simple solution? Make sure the program/client stays active, either by calling `sleep`, or listening out for new messages. As sending a one-shot message without listening out for a response is likely not what you'll be doing, then you will be then awaiting a response (see the [message helpers page](message-helpers.md) for an example of this). + +Furthermore, you should always **manually disconnect your client** with `client.disconnect().await` as seen in the code examples. This is important as your client is writing to a local DB and dealing with SURB storage. + +## Client receives empty messages when listening for response +If you are sending out a message, it makes sense for your client to then listen out for incoming messages; this would probably be the reply you get from the service you've sent a message to. + +You might however be receiving messages without data attached to them / empty payloads. This is most likely because your client is receiving a message containing a [SURB request](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs) - a SURB requesting more SURB packets to be sent to the service, in order for them to have enough packets (with a big enough overall payload) to split the entire response to your initial request across. + +Whether the `data` of a SURB request being empty is a feature or a bug is to be decided - there is some discussion surrounding whether we can use SURB requests to send additional data to streamline the process of sending large replies across the mixnet. + +You can find a few helper functions [here](message-helpers.md) to help deal with this issue in the meantime. + +> If you can think of a more succinct or different way of handling this do reach out - we're happy to hear other opinions \ No newline at end of file From a4bb4ec6c52c78ddacbefbaf2b0b9e333df01198 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 13:19:54 +0100 Subject: [PATCH 205/236] first pass at helper messages --- documentation/docs/src/sdk/rust/message-helpers.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/documentation/docs/src/sdk/rust/message-helpers.md b/documentation/docs/src/sdk/rust/message-helpers.md index 478e12a7ab..d783cd2e25 100644 --- a/documentation/docs/src/sdk/rust/message-helpers.md +++ b/documentation/docs/src/sdk/rust/message-helpers.md @@ -1,2 +1,10 @@ # Message Helpers -TODO pull in dealing with incoming non-empty messages and fn()s from tutorial \ No newline at end of file + +## Handling incoming messages +As seen in the [Chain querier tutorial](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/) when listening out for a response to a sent message (e.g. if you have sent a request to a service, and are awaiting the response) you will want to await [non-empty messages (more info on this here)](troubleshooting.md#client-receives-empty-messages-when-listening-for-response). This can be done with something like the helper functions [here](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/src/lib.rs#L71). + +## Iterating over incoming messages +It is recommended to use `nym_client.next().await` over `nym_client.wait_for_messages().await` as the latter will return one message at a time which will probably be easier to deal with. See the [parallel send and receive example](https://github.com/nymtech/nym/blob/2993e85c7a17bd5b68171751a48b731b2394ee03/sdk/rust/nym-sdk/examples/parallel_sending_and_receiving.rs#L23-L25) for an example. + +## Remember to disconnect your client +You should always **manually disconnect your client** with `client.disconnect().await` as seen in the code examples. This is important as your client is writing to a local DB and dealing with SURB storage. From 6e9eb26e2775df7e221efbf075363425a1dda52e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Walther?= Date: Thu, 2 Nov 2023 14:07:45 +0100 Subject: [PATCH 206/236] Github Actions: fix cd-docs --- .github/workflows/cd-docs.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.github/workflows/cd-docs.yml b/.github/workflows/cd-docs.yml index df0ae9dc66..1cf2025534 100644 --- a/.github/workflows/cd-docs.yml +++ b/.github/workflows/cd-docs.yml @@ -51,18 +51,6 @@ jobs: TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/ EXCLUDE: "/node_modules/" - - name: Deploy branch master to prod - if: github.ref == 'refs/heads/master' - uses: easingthemes/ssh-deploy@main - env: - SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }} - ARGS: "-rltgoDzvO --delete" - SOURCE: "dist/docs/" - REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_PROD }} - REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }} - TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/ - EXCLUDE: "/node_modules/" - - name: Post process run: cd documentation && ./post_process.sh continue-on-error: false From c4be55e82467b13286d5e643363f5bed0de6ad4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Walther?= Date: Thu, 2 Nov 2023 14:52:30 +0100 Subject: [PATCH 207/236] Github actions: remove deployment to website-dev --- .github/workflows/cd-docs.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.github/workflows/cd-docs.yml b/.github/workflows/cd-docs.yml index 1cf2025534..a5169a3f26 100644 --- a/.github/workflows/cd-docs.yml +++ b/.github/workflows/cd-docs.yml @@ -39,18 +39,6 @@ jobs: run: cd documentation && ./build_all_to_dist.sh continue-on-error: false - - name: Deploy branch master to dev - continue-on-error: true - uses: easingthemes/ssh-deploy@main - env: - SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }} - ARGS: "-rltgoDzvO --delete" - SOURCE: "dist/docs/" - REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_DEV }} - REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }} - TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/ - EXCLUDE: "/node_modules/" - - name: Post process run: cd documentation && ./post_process.sh continue-on-error: false From 52736881db211e6fe723392cf4d68bdd1f1de248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 2 Nov 2023 16:36:40 +0100 Subject: [PATCH 208/236] Update Cargo.lock --- nym-wallet/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index ec32ea6a33..77fbfe47eb 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -3706,7 +3706,7 @@ dependencies = [ [[package]] name = "nym_wallet" -version = "1.2.9" +version = "1.2.10" dependencies = [ "async-trait", "base64 0.13.1", From bcfea21501392732a44bcc6537d6a538ae717553 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 17:13:37 +0100 Subject: [PATCH 209/236] upgraded mdbook-admonish version --- .github/workflows/ci-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index b503516e70..780e82bdb1 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -32,7 +32,7 @@ jobs: - name: Install mdbook plugins run: | cargo install --vers "=0.2.2" mdbook-variables && cargo install \ - --vers "^1.8.0" mdbook-admonish --force && cargo install --vers \ + --vers "^3.0.0" mdbook-admonish --force && cargo install --vers \ "^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" mdbook-theme \ && cargo install --vers "^0.7.7" mdbook-linkcheck \ # && cd documentation \ From e9a0c6f8d0011caa0c29b3fd1e0f7d0ade02f555 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 17:13:55 +0100 Subject: [PATCH 210/236] added code example to helpers --- .../docs/src/sdk/rust/message-helpers.md | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/documentation/docs/src/sdk/rust/message-helpers.md b/documentation/docs/src/sdk/rust/message-helpers.md index d783cd2e25..e7ce201fa7 100644 --- a/documentation/docs/src/sdk/rust/message-helpers.md +++ b/documentation/docs/src/sdk/rust/message-helpers.md @@ -1,7 +1,67 @@ # Message Helpers ## Handling incoming messages -As seen in the [Chain querier tutorial](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/) when listening out for a response to a sent message (e.g. if you have sent a request to a service, and are awaiting the response) you will want to await [non-empty messages (more info on this here)](troubleshooting.md#client-receives-empty-messages-when-listening-for-response). This can be done with something like the helper functions [here](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/src/lib.rs#L71). +As seen in the [Chain querier tutorial](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/) when listening out for a response to a sent message (e.g. if you have sent a request to a service, and are awaiting the response) you will want to await [non-empty messages (if you don't know why, read the info on this here)](troubleshooting.md#client-receives-empty-messages-when-listening-for-response). This can be done with something like the helper functions [here](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/src/lib.rs#L71): + +```rust +use nym_sdk::mixnet::ReconstructedMessage; + +pub async fn wait_for_non_empty_message( + client: &mut MixnetClient, +) -> anyhow::Result { + while let Some(mut new_message) = client.wait_for_messages().await { + if !new_message.is_empty() { + return Ok(new_message.pop().unwrap()); + } + } + + bail!("did not receive any non-empty message") +} + +pub fn handle_response(message: ReconstructedMessage) -> anyhow::Result { + ResponseTypes::try_deserialize(message.message) +} + +// Note here that the only difference between handling a request and a response +// is that a request will have a sender_tag to parse. +// +// This is used for anonymous replies with SURBs. +pub fn handle_request( + message: ReconstructedMessage, +) -> anyhow::Result<(RequestTypes, Option)> { + let request = RequestTypes::try_deserialize(message.message)?; + Ok((request, message.sender_tag)) +} +``` + +The above helper functions are used as such by the client in tutorial example: it sends a message to the service (what the message is isn't important - just that your client has sent a message _somewhere_ and you are awaiting a response), waits for a _non_empty_ message, then handles it (then logs it - but you can do whatever you want, parse it, etc): + +```rust +// [snip] + +// Send serialised request to service via mixnet what is await-ed here is +// placing the message in the client's message queue, NOT the sending itself. +let _ = client + .send_message(sp_address, message.serialize(), Default::default()) + .await; + +// Await a non-empty message +let received = wait_for_non_empty_message(client).await?; + +// Handle the response received (the non-empty message awaited above) +let sp_response = handle_response(received)?; + +// Match JSON -> ResponseType +let res = match sp_response { + crate::ResponseTypes::Balance(response) => { + println!("{:#?}", response); + response.balance + } +}; + +// [snip] +``` +([repo code on Github here](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/src/client.rs#L19)) ## Iterating over incoming messages It is recommended to use `nym_client.next().await` over `nym_client.wait_for_messages().await` as the latter will return one message at a time which will probably be easier to deal with. See the [parallel send and receive example](https://github.com/nymtech/nym/blob/2993e85c7a17bd5b68171751a48b731b2394ee03/sdk/rust/nym-sdk/examples/parallel_sending_and_receiving.rs#L23-L25) for an example. From a9c40e76dc05be26d3b905eb63806146be1ddbc2 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 17:17:06 +0100 Subject: [PATCH 211/236] revert previous --- .github/workflows/ci-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index 780e82bdb1..b503516e70 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -32,7 +32,7 @@ jobs: - name: Install mdbook plugins run: | cargo install --vers "=0.2.2" mdbook-variables && cargo install \ - --vers "^3.0.0" mdbook-admonish --force && cargo install --vers \ + --vers "^1.8.0" mdbook-admonish --force && cargo install --vers \ "^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" mdbook-theme \ && cargo install --vers "^0.7.7" mdbook-linkcheck \ # && cd documentation \ From 60912ff8efd017a9ddba0797f82ee114dcc0c099 Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Thu, 2 Nov 2023 18:19:34 +0100 Subject: [PATCH 212/236] Fix sdk publish action (#4088) * fix: sdk publish script The bash implementation used in the GitHub CI runner seems to have an issue with incrementing a variable with `(( COUNTER++ ))` while `(( COUNTER=+1 ))` works fine. * Add more sdk packages to workspace and normalize build sdk scripts * Disable workspaces in npm publish sdk Signed-off-by: Sebastian Martinez * Continue publishing even when it fails Signed-off-by: Sebastian Martinez --------- Signed-off-by: Sebastian Martinez --- package.json | 7 ++++- sdk/typescript/scripts/publish.sh | 44 ++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index cd357e15a0..bd928a454e 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,11 @@ "sdk/typescript/packages/validator-client", "sdk/typescript/packages/mix-fetch-node", "sdk/typescript/packages/nodejs-client", + "sdk/typescript/packages/node-tester", + "sdk/typescript/packages/sdk-react", + "sdk/typescript/packages/mix-fetch", + "sdk/typescript/packages/sdk", + "sdk/typescript/codegen/contract-clients", "ts-packages/*", "nym-wallet", "nym-connect/**", @@ -36,7 +41,7 @@ "prebuild:ci": "yarn dev:on && yarn", "build:ci": "run-s build:types build:packages build:wasm build:ci:sdk", "postbuild:ci": "yarn dev:off", - "build:ci:sdk": "lerna run --scope '{@nymproject/sdk,@nymproject/node-tester,@nymproject/sdk-react,@nymproject/mix-fetch,@nymproject/nodejs-client,@nymproject/mix-fetch-node}' build --stream", + "build:ci:sdk": "lerna run --scope '{@nymproject/sdk,@nymproject/node-tester,@nymproject/contract-clients,@nymproject/sdk-react,@nymproject/mix-fetch,@nymproject/nodejs-client,@nymproject/mix-fetch-node}' build --stream", "docs:prod:build": "run-s docs:prod:build:ws", "docs:prod:build:ws": "lerna run docs:prod:build --stream", "sdk:build": "./sdk/typescript/scripts/build-prod-sdk.sh", diff --git a/sdk/typescript/scripts/publish.sh b/sdk/typescript/scripts/publish.sh index dabea53c6c..3c59953776 100755 --- a/sdk/typescript/scripts/publish.sh +++ b/sdk/typescript/scripts/publish.sh @@ -10,9 +10,46 @@ set -o pipefail cd dist +#packages=( +#chat-app/parcel +#chat-app/plain-html +#chat-app/react-webpack-with-theme-example +#chrome-extension +#firefox-extension +#node-tester/parcel +#node-tester/plain-html +#node-tester/react +#react/mui-theme +#react/sdk-react +#) packages=( +"wasm/client" +"wasm/mix-fetch" +"wasm/node-tester" +"wasm/extension-storage" + +"node/wasm/client" +"node/wasm/mix-fetch" + +"ts/sdk/mix-fetch/cjs" +"ts/sdk/mix-fetch/cjs-full-fat" +"ts/sdk/mix-fetch/esm" +"ts/sdk/mix-fetch/esm-full-fat" + "ts/sdk/nodejs-client/cjs" "ts/sdk/mix-fetch-node/cjs" + +"ts/sdk/node-tester/cjs" +"ts/sdk/node-tester/cjs-full-fat" +"ts/sdk/node-tester/esm" +"ts/sdk/node-tester/esm-full-fat" + +"ts/sdk/sdk/cjs" +"ts/sdk/sdk/cjs-full-fat" +"ts/sdk/sdk/esm" +"ts/sdk/sdk/esm-full-fat" + +"ts/sdk/contract-clients" ) pushd () { @@ -39,14 +76,13 @@ COUNTER=0 for item in "${packages[@]}" do - (( COUNTER++ )) + (( COUNTER+=1 )) pushd "$item" echo "🚀 Publishing $item... (${COUNTER} of ${#packages[@]})" - jq -r '. | .name + " " +.version' < package.json - npm publish --access=public --verbose + cat package.json | jq -r '. | .name + " " +.version' + npm publish --access=public --verbose --workspaces false || true popd echo "" done echo "" echo "✅ Done" - From 554010b5cb3ee79bdcb42593eeb4aadc188f9d5a Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Thu, 2 Nov 2023 19:17:35 +0000 Subject: [PATCH 213/236] Add NodeJS mixFetch to version bump tool --- tools/internal/sdk-version-bump/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/internal/sdk-version-bump/src/main.rs b/tools/internal/sdk-version-bump/src/main.rs index e6472ca676..31528a3c4f 100644 --- a/tools/internal/sdk-version-bump/src/main.rs +++ b/tools/internal/sdk-version-bump/src/main.rs @@ -186,6 +186,7 @@ fn initialise_internal_packages>(root: P) -> InternalPackages { packages.register_json("sdk/typescript/examples/node-tester/plain-html"); packages.register_json("sdk/typescript/examples/node-tester/react"); packages.register_json("sdk/typescript/packages/mix-fetch"); + packages.register_json("sdk/typescript/packages/mix-fetch-node"); packages.register_json("sdk/typescript/packages/mix-fetch/internal-dev"); packages.register_json("sdk/typescript/packages/mix-fetch/internal-dev/parcel"); packages.register_json("sdk/typescript/packages/node-tester"); From 1582c13f622303a8da843c9baf5b4ea45c523729 Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Thu, 2 Nov 2023 19:24:53 +0000 Subject: [PATCH 214/236] Update SDK contract client --- sdk/typescript/codegen/contract-clients/package.json | 4 ++-- .../codegen/contract-clients/src/NameService.client.ts | 2 +- .../codegen/contract-clients/src/NameService.types.ts | 7 ++++++- tools/internal/sdk-version-bump/src/main.rs | 1 + 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/sdk/typescript/codegen/contract-clients/package.json b/sdk/typescript/codegen/contract-clients/package.json index 856942d621..49e3d1fc99 100644 --- a/sdk/typescript/codegen/contract-clients/package.json +++ b/sdk/typescript/codegen/contract-clients/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/contract-clients", - "version": "1.2.0", + "version": "1.2.1", "description": "A client for all Nym smart contracts", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -27,4 +27,4 @@ }, "private": false, "types": "./dist/index.d.ts" -} \ No newline at end of file +} diff --git a/sdk/typescript/codegen/contract-clients/src/NameService.client.ts b/sdk/typescript/codegen/contract-clients/src/NameService.client.ts index 5f5444f0fc..a92b351fb1 100644 --- a/sdk/typescript/codegen/contract-clients/src/NameService.client.ts +++ b/sdk/typescript/codegen/contract-clients/src/NameService.client.ts @@ -6,8 +6,8 @@ import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; import { StdFee } from "@cosmjs/amino"; -import { Uint128, InstantiateMsg, Coin, ExecuteMsg, Address, NymName, MessageSignature, NameDetails, QueryMsg, MigrateMsg, Addr, PagedNamesListResponse, RegisteredName, NamesListResponse, ConfigResponse, ContractVersion, ContractBuildInformation, Uint32 } from "./NameService.types"; import { GetCw2ContractVersionResponse } from './types'; +import { Uint128, InstantiateMsg, Coin, ExecuteMsg, Address, NymName, MessageSignature, NameDetails, NymAddressInner, QueryMsg, MigrateMsg, Addr, PagedNamesListResponse, RegisteredName, NamesListResponse, ConfigResponse, ContractVersion, ContractBuildInformation, Uint32 } from "./NameService.types"; export interface NameServiceReadOnlyInterface { contractAddress: string; nameId: ({ diff --git a/sdk/typescript/codegen/contract-clients/src/NameService.types.ts b/sdk/typescript/codegen/contract-clients/src/NameService.types.ts index c9d80b5936..e80cdfc843 100644 --- a/sdk/typescript/codegen/contract-clients/src/NameService.types.ts +++ b/sdk/typescript/codegen/contract-clients/src/NameService.types.ts @@ -32,7 +32,7 @@ export type ExecuteMsg = { }; }; export type Address = { - nym_address: string; + nym_address: NymAddressInner; }; export type NymName = string; export type MessageSignature = number[]; @@ -41,6 +41,11 @@ export interface NameDetails { identity_key: string; name: NymName; } +export interface NymAddressInner { + client_enc: string; + client_id: string; + gateway_id: string; +} export type QueryMsg = { name_id: { name_id: number; diff --git a/tools/internal/sdk-version-bump/src/main.rs b/tools/internal/sdk-version-bump/src/main.rs index 31528a3c4f..85c82c1d3c 100644 --- a/tools/internal/sdk-version-bump/src/main.rs +++ b/tools/internal/sdk-version-bump/src/main.rs @@ -193,6 +193,7 @@ fn initialise_internal_packages>(root: P) -> InternalPackages { packages.register_json("sdk/typescript/packages/nodejs-client"); packages.register_json("sdk/typescript/packages/sdk"); packages.register_json("sdk/typescript/packages/sdk-react"); + packages.register_json("sdk/typescript/codegen/contract-clients"); // dependencies that will have their versions adjusted in the above packages packages.register_known_js_dependency("@nymproject/mix-fetch"); From d64613006cbb502502a9e92f66ecc0a6f352db15 Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Thu, 2 Nov 2023 19:29:02 +0000 Subject: [PATCH 215/236] Release Typescript SDK to version 1.2.1 --- Cargo.lock | 10 ++--- nym-browser-extension/storage/Cargo.toml | 2 +- sdk/typescript/docs/package.json | 12 +++--- .../examples/chat-app/parcel/package.json | 33 ++++++++-------- .../examples/chat-app/plain-html/package.json | 31 +++++++-------- .../package.json | 38 +++++++++---------- .../examples/chrome-extension/package.json | 15 ++++---- .../examples/firefox-extension/package.json | 21 +++++----- .../examples/mix-fetch/browser/package.json | 21 +++++----- .../examples/node-tester/parcel/package.json | 33 ++++++++-------- .../node-tester/plain-html/package.json | 31 +++++++-------- .../examples/node-tester/react/package.json | 13 ++++--- .../packages/mix-fetch-node/package.json | 4 +- .../mix-fetch/internal-dev/package.json | 17 +++++---- .../internal-dev/parcel/package.json | 19 +++++----- .../packages/mix-fetch/package.json | 4 +- .../packages/node-tester/package.json | 4 +- .../packages/nodejs-client/package.json | 4 +- .../packages/sdk-react/package.json | 6 +-- sdk/typescript/packages/sdk/package.json | 4 +- wasm/client/Cargo.toml | 2 +- wasm/full-nym-wasm/Cargo.toml | 2 +- wasm/mix-fetch/Cargo.toml | 2 +- wasm/node-tester/Cargo.toml | 2 +- 24 files changed, 170 insertions(+), 160 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 72fad02808..60c1986590 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2994,7 +2994,7 @@ dependencies = [ [[package]] name = "extension-storage" -version = "1.2.0" +version = "1.2.1" dependencies = [ "bip39", "console_error_panic_hook", @@ -5559,7 +5559,7 @@ dependencies = [ [[package]] name = "mix-fetch-wasm" -version = "1.2.0" +version = "1.2.1" dependencies = [ "async-trait", "futures", @@ -6260,7 +6260,7 @@ dependencies = [ [[package]] name = "nym-client-wasm" -version = "1.2.0" +version = "1.2.1" dependencies = [ "anyhow", "futures", @@ -6953,7 +6953,7 @@ dependencies = [ [[package]] name = "nym-node-tester-wasm" -version = "1.2.0" +version = "1.2.1" dependencies = [ "futures", "js-sys", @@ -7555,7 +7555,7 @@ dependencies = [ [[package]] name = "nym-wasm-sdk" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mix-fetch-wasm", "nym-client-wasm", diff --git a/nym-browser-extension/storage/Cargo.toml b/nym-browser-extension/storage/Cargo.toml index 86ee9de5f9..aee9afb118 100644 --- a/nym-browser-extension/storage/Cargo.toml +++ b/nym-browser-extension/storage/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "extension-storage" -version = "1.2.0" +version = "1.2.1" edition = "2021" license = "Apache-2.0" repository = "https://github.com/nymtech/nym" diff --git a/sdk/typescript/docs/package.json b/sdk/typescript/docs/package.json index 0fcfab0d3d..580a99614e 100644 --- a/sdk/typescript/docs/package.json +++ b/sdk/typescript/docs/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/ts-sdk-docs", - "version": "1.2.0", + "version": "1.2.1", "description": "Nym Typescript SDK Docs", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -28,10 +28,10 @@ "@mui/icons-material": "^5.14.9", "@mui/lab": "^5.0.0-alpha.145", "@mui/material": "^5.14.8", - "@nymproject/contract-clients": ">=1.2.0-rc.10 || ^1", - "@nymproject/mix-fetch": ">=1.2.0-rc.10 || ^1", - "@nymproject/mix-fetch-full-fat": ">=1.2.0-rc.10 || ^1", - "@nymproject/sdk-full-fat": ">=1.2.0-rc.10 || ^1", + "@nymproject/contract-clients": ">=1.2.1-rc.0 || ^1", + "@nymproject/mix-fetch": ">=1.2.1-rc.0 || ^1", + "@nymproject/mix-fetch-full-fat": ">=1.2.1-rc.0 || ^1", + "@nymproject/sdk-full-fat": ">=1.2.1-rc.0 || ^1", "chain-registry": "^1.19.0", "cosmjs-types": "^0.8.0", "next": "^13.4.19", @@ -51,4 +51,4 @@ "typescript": "^4.9.3" }, "private": false -} +} \ No newline at end of file diff --git a/sdk/typescript/examples/chat-app/parcel/package.json b/sdk/typescript/examples/chat-app/parcel/package.json index bf72e13983..646d5610fe 100644 --- a/sdk/typescript/examples/chat-app/parcel/package.json +++ b/sdk/typescript/examples/chat-app/parcel/package.json @@ -1,12 +1,21 @@ { "name": "@nymproject/sdk-example-plain-html-parcel", + "version": "1.0.1", "description": "An example project that uses WASM and plain HTML bundled with Parcel v2", - "version": "1.0.0", "license": "Apache-2.0", - "source": "src/index.html", - "browserslist": "> 0.5%, last 2 versions, not dead", + "scripts": { + "build": "npx parcel build", + "build:serve": "npx serve dist", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "npx parcel", + "test": "jest", + "test:watch": "jest --watch", + "tsc": "tsc", + "tsc:watch": "tsc --watch" + }, "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" }, "devDependencies": { "@types/jest": "^27.0.1", @@ -29,15 +38,7 @@ "ts-jest": "^27.0.5", "typescript": "^4.6.2" }, - "scripts": { - "start": "npx parcel", - "build": "npx parcel build", - "build:serve": "npx serve dist", - "test": "jest", - "test:watch": "jest --watch", - "tsc": "tsc", - "tsc:watch": "tsc --watch", - "lint": "eslint src", - "lint:fix": "eslint src --fix" - } -} + "private": false, + "browserslist": "> 0.5%, last 2 versions, not dead", + "source": "src/index.html" +} \ No newline at end of file diff --git a/sdk/typescript/examples/chat-app/plain-html/package.json b/sdk/typescript/examples/chat-app/plain-html/package.json index 5e6774c951..7cdf5deddc 100644 --- a/sdk/typescript/examples/chat-app/plain-html/package.json +++ b/sdk/typescript/examples/chat-app/plain-html/package.json @@ -1,10 +1,22 @@ { "name": "@nymproject/sdk-example-plain-html", + "version": "1.0.1", "description": "An example project that uses WASM and plain HTML", - "version": "1.0.0", "license": "Apache-2.0", + "scripts": { + "build": "webpack build --progress --config webpack.prod.js", + "build:dev": "webpack build --progress", + "build:serve": "npx serve dist", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "webpack serve --progress --port 3000", + "test": "jest", + "test:watch": "jest --watch", + "tsc": "tsc", + "tsc:watch": "tsc --watch" + }, "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" }, "devDependencies": { "@babel/core": "^7.15.0", @@ -49,16 +61,5 @@ "webpack-dev-server": "^4.5.0", "webpack-merge": "^5.8.0" }, - "scripts": { - "start": "webpack serve --progress --port 3000", - "build": "webpack build --progress --config webpack.prod.js", - "build:dev": "webpack build --progress", - "build:serve": "npx serve dist", - "test": "jest", - "test:watch": "jest --watch", - "tsc": "tsc", - "tsc:watch": "tsc --watch", - "lint": "eslint src", - "lint:fix": "eslint src --fix" - } -} + "private": false +} \ No newline at end of file diff --git a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json index 47fedbf21d..48813124dd 100644 --- a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json +++ b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json @@ -1,15 +1,26 @@ { "name": "@nymproject/sdk-example-react-webpack-wasm", + "version": "1.0.1", "description": "An example project that uses WASM, React, Webpack, Typescript and the Nym theme + components library", - "version": "1.0.0", "license": "Apache-2.0", + "scripts": { + "build": "webpack build --progress --config webpack.prod.js", + "build:dev": "webpack build --progress", + "build:serve": "npx serve dist", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "webpack serve --progress --port 3000", + "test": "jest", + "test:watch": "jest --watch", + "tsc": "tsc", + "tsc:watch": "tsc --watch" + }, "dependencies": { "@mui/icons-material": "^5.5.0", "@mui/lab": "^5.0.0-alpha.72", "@mui/material": "^5.0.1", "@mui/styles": "^5.0.1", - "react-mui-dropzone": "^4.0.6", - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1", + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", @@ -72,22 +83,11 @@ "webpack-favicons": "^1.3.8", "webpack-merge": "^5.8.0" }, + "private": false, "overrides": { - "react": "^18.2.0", - "react-dom": "^18.2.0", "@types/react": "^18.0.26", - "@types/react-dom": "^18.0.10" - }, - "scripts": { - "start": "webpack serve --progress --port 3000", - "build": "webpack build --progress --config webpack.prod.js", - "build:dev": "webpack build --progress", - "build:serve": "npx serve dist", - "test": "jest", - "test:watch": "jest --watch", - "tsc": "tsc", - "tsc:watch": "tsc --watch", - "lint": "eslint src", - "lint:fix": "eslint src --fix" + "@types/react-dom": "^18.0.10", + "react": "^18.2.0", + "react-dom": "^18.2.0" } -} +} \ No newline at end of file diff --git a/sdk/typescript/examples/chrome-extension/package.json b/sdk/typescript/examples/chrome-extension/package.json index 507b9cdec8..5880b8d4e8 100644 --- a/sdk/typescript/examples/chrome-extension/package.json +++ b/sdk/typescript/examples/chrome-extension/package.json @@ -1,20 +1,21 @@ { "name": "@nymproject/sdk-example-chrome-extension", - "version": "1.0.0", + "version": "1.0.1", "description": "This is an example of how Nym can be used within the context of a Chrome extension.", + "license": "ISC", + "author": "", "main": "index.js", "scripts": { "build": "webpack" }, - "author": "", - "license": "ISC", + "dependencies": { + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" + }, "devDependencies": { "clean-webpack-plugin": "^4.0.0", "copy-webpack-plugin": "^11.0.0", "webpack": "^5.88.1", "webpack-cli": "^5.1.4" }, - "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" - } -} + "private": false +} \ No newline at end of file diff --git a/sdk/typescript/examples/firefox-extension/package.json b/sdk/typescript/examples/firefox-extension/package.json index 1d14e425a5..9615a1cf04 100644 --- a/sdk/typescript/examples/firefox-extension/package.json +++ b/sdk/typescript/examples/firefox-extension/package.json @@ -1,20 +1,21 @@ { "name": "@nymproject/sdk-example-firefox-extension", - "version": "1.0.0", + "version": "1.0.1", "description": "This is an example of how Nym can be used within the context of a Firefox extension.", - "main": "index.js", - "author": "", "license": "ISC", + "author": "", + "main": "index.js", + "scripts": { + "build": "yarn webpack" + }, + "dependencies": { + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" + }, "devDependencies": { "copy-webpack-plugin": "^11.0.0", "webpack": "^5.88.1", "webpack-cli": "^5.1.4", "worker-loader": "^3.0.8" }, - "scripts": { - "build": "yarn webpack" - }, - "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" - } -} + "private": false +} \ No newline at end of file diff --git a/sdk/typescript/examples/mix-fetch/browser/package.json b/sdk/typescript/examples/mix-fetch/browser/package.json index 1ec0e2d6c6..4de1922b38 100644 --- a/sdk/typescript/examples/mix-fetch/browser/package.json +++ b/sdk/typescript/examples/mix-fetch/browser/package.json @@ -1,15 +1,16 @@ { "name": "@nymproject/mix-fetch-example-parcel", - "version": "1.0.0", + "version": "1.0.1", "license": "Apache-2.0", - "source": "src/index.html", - "dependencies": { - "parcel": "^2.9.3", - "@nymproject/mix-fetch": ">=1.2.0-rc.10 || ^1" - }, "scripts": { - "start": "parcel --no-cache", "build": "parcel build --no-cache --no-content-hash", - "serve": "serve dist" - } -} + "serve": "serve dist", + "start": "parcel --no-cache" + }, + "dependencies": { + "@nymproject/mix-fetch": ">=1.2.1-rc.0 || ^1", + "parcel": "^2.9.3" + }, + "private": false, + "source": "src/index.html" +} \ No newline at end of file diff --git a/sdk/typescript/examples/node-tester/parcel/package.json b/sdk/typescript/examples/node-tester/parcel/package.json index 905b3747eb..015b816fda 100644 --- a/sdk/typescript/examples/node-tester/parcel/package.json +++ b/sdk/typescript/examples/node-tester/parcel/package.json @@ -1,12 +1,21 @@ { "name": "@nymproject/sdk-example-node-tester-plain-html-parcel", + "version": "1.0.1", "description": "An example project that uses WASM and plain HTML bundled with Parcel v2", - "version": "1.0.0", "license": "Apache-2.0", - "source": "src/index.html", - "browserslist": "> 0.5%, last 2 versions, not dead", + "scripts": { + "build": "npx parcel build", + "build:serve": "npx serve dist", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "npx parcel", + "test": "jest", + "test:watch": "jest --watch", + "tsc": "tsc", + "tsc:watch": "tsc --watch" + }, "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" }, "devDependencies": { "@types/jest": "^27.0.1", @@ -29,15 +38,7 @@ "ts-jest": "^27.0.5", "typescript": "^4.6.2" }, - "scripts": { - "start": "npx parcel", - "build": "npx parcel build", - "build:serve": "npx serve dist", - "test": "jest", - "test:watch": "jest --watch", - "tsc": "tsc", - "tsc:watch": "tsc --watch", - "lint": "eslint src", - "lint:fix": "eslint src --fix" - } -} + "private": false, + "browserslist": "> 0.5%, last 2 versions, not dead", + "source": "src/index.html" +} \ No newline at end of file diff --git a/sdk/typescript/examples/node-tester/plain-html/package.json b/sdk/typescript/examples/node-tester/plain-html/package.json index 225060d813..bf59e74f0d 100644 --- a/sdk/typescript/examples/node-tester/plain-html/package.json +++ b/sdk/typescript/examples/node-tester/plain-html/package.json @@ -1,10 +1,22 @@ { "name": "@nymproject/sdk-example-node-tester-plain-html", + "version": "1.0.1", "description": "An example project that uses WASM node tester and plain HTML", - "version": "1.0.0", "license": "Apache-2.0", + "scripts": { + "build": "webpack build --progress --config webpack.prod.js", + "build:dev": "webpack build --progress", + "build:serve": "npx serve dist", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "webpack serve --progress --port 3000", + "test": "jest", + "test:watch": "jest --watch", + "tsc": "tsc", + "tsc:watch": "tsc --watch" + }, "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" }, "devDependencies": { "@babel/core": "^7.15.0", @@ -49,16 +61,5 @@ "webpack-dev-server": "^4.5.0", "webpack-merge": "^5.8.0" }, - "scripts": { - "start": "webpack serve --progress --port 3000", - "build": "webpack build --progress --config webpack.prod.js", - "build:dev": "webpack build --progress", - "build:serve": "npx serve dist", - "test": "jest", - "test:watch": "jest --watch", - "tsc": "tsc", - "tsc:watch": "tsc --watch", - "lint": "eslint src", - "lint:fix": "eslint src --fix" - } -} + "private": false +} \ No newline at end of file diff --git a/sdk/typescript/examples/node-tester/react/package.json b/sdk/typescript/examples/node-tester/react/package.json index e07e69ad32..9f3b2394e7 100644 --- a/sdk/typescript/examples/node-tester/react/package.json +++ b/sdk/typescript/examples/node-tester/react/package.json @@ -1,19 +1,20 @@ { "name": "@nymproject/sdk-example-node-tester-react", + "version": "1.0.1", "description": "An example project that uses WASM node tester and React", - "version": "1.0.0", "license": "Apache-2.0", + "scripts": { + "start": "parcel index.html" + }, "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.14.0", "@mui/material": "^5.14.0", - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1", + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1", "parcel": "^2.9.3", "react": "^18.2.0", "react-dom": "^18.2.0" }, - "scripts": { - "start": "parcel index.html" - } -} + "private": false +} \ No newline at end of file diff --git a/sdk/typescript/packages/mix-fetch-node/package.json b/sdk/typescript/packages/mix-fetch-node/package.json index 0fb709c9db..3efd987e43 100644 --- a/sdk/typescript/packages/mix-fetch-node/package.json +++ b/sdk/typescript/packages/mix-fetch-node/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/mix-fetch-node", - "version": "1.2.1-rc.3", + "version": "1.2.1", "description": "This package is a drop-in replacement for `fetch` in NodeJS to send HTTP requests over the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -28,7 +28,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/mix-fetch-wasm-node": ">=1.2.0 || ^1", + "@nymproject/mix-fetch-wasm-node": ">=1.2.1-rc.0 || ^1", "comlink": "^4.3.1", "fake-indexeddb": "^5.0.0", "node-fetch": "^3.3.2", diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/package.json b/sdk/typescript/packages/mix-fetch/internal-dev/package.json index 18d4c82220..9965510bdb 100644 --- a/sdk/typescript/packages/mix-fetch/internal-dev/package.json +++ b/sdk/typescript/packages/mix-fetch/internal-dev/package.json @@ -1,9 +1,14 @@ { "name": "@nymproject/mix-fetch-tester-webpack", - "version": "1.0.0", + "version": "1.0.1", "license": "Apache-2.0", + "scripts": { + "build": "webpack build --progress --config webpack.prod.js", + "serve": "npx serve dist", + "start": "webpack serve --progress --port 3000" + }, "dependencies": { - "@nymproject/mix-fetch": ">=1.2.0-rc.10 || ^1" + "@nymproject/mix-fetch": ">=1.2.1-rc.0 || ^1" }, "devDependencies": { "@babel/core": "^7.22.10", @@ -49,9 +54,5 @@ "webpack-dev-server": "^4.15.1", "webpack-merge": "^5.9.0" }, - "scripts": { - "start": "webpack serve --progress --port 3000", - "build": "webpack build --progress --config webpack.prod.js", - "serve": "npx serve dist" - } -} + "private": false +} \ No newline at end of file diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json b/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json index 1983ca9c06..6849466cd3 100644 --- a/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json +++ b/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json @@ -1,14 +1,15 @@ { "name": "@nymproject/mix-fetch-tester-parcel", - "version": "1.0.0", + "version": "1.0.1", "license": "Apache-2.0", - "source": "../src/index.html", - "dependencies": { - "@nymproject/mix-fetch": ">=1.2.0-rc.10 || ^1" - }, "scripts": { - "start": "npx parcel --no-cache", "build": "npx parcel build --no-cache --no-content-hash", - "serve": "npx serve dist" - } -} + "serve": "npx serve dist", + "start": "npx parcel --no-cache" + }, + "dependencies": { + "@nymproject/mix-fetch": ">=1.2.1-rc.0 || ^1" + }, + "private": false, + "source": "../src/index.html" +} \ No newline at end of file diff --git a/sdk/typescript/packages/mix-fetch/package.json b/sdk/typescript/packages/mix-fetch/package.json index a5350b9012..f58088197b 100644 --- a/sdk/typescript/packages/mix-fetch/package.json +++ b/sdk/typescript/packages/mix-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/mix-fetch", - "version": "1.2.0", + "version": "1.2.1", "description": "This package is a drop-in replacement for `fetch` to send HTTP requests over the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -33,7 +33,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/mix-fetch-wasm": ">=1.2.0-rc.10 || ^1", + "@nymproject/mix-fetch-wasm": ">=1.2.1-rc.0 || ^1", "comlink": "^4.3.1" }, "devDependencies": { diff --git a/sdk/typescript/packages/node-tester/package.json b/sdk/typescript/packages/node-tester/package.json index f01028da1f..acb32c0b19 100644 --- a/sdk/typescript/packages/node-tester/package.json +++ b/sdk/typescript/packages/node-tester/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/node-tester", - "version": "1.2.0", + "version": "1.2.1", "description": "This package provides a tester that can send test packets to mixnode that is part of the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -25,7 +25,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-node-tester-wasm": ">=1.2.0-rc.10 || ^1", + "@nymproject/nym-node-tester-wasm": ">=1.2.1-rc.0 || ^1", "comlink": "^4.3.1" }, "devDependencies": { diff --git a/sdk/typescript/packages/nodejs-client/package.json b/sdk/typescript/packages/nodejs-client/package.json index 7a30d73cc3..d1d46f532d 100644 --- a/sdk/typescript/packages/nodejs-client/package.json +++ b/sdk/typescript/packages/nodejs-client/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/nodejs-client", - "version": "1.2.1-rc.3", + "version": "1.2.1", "license": "Apache-2.0", "author": "Nym Technologies SA", "files": [ @@ -25,7 +25,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-client-wasm-node": ">=1.2.0 || ^1", + "@nymproject/nym-client-wasm-node": ">=1.2.1-rc.0 || ^1", "comlink": "^4.3.1", "fake-indexeddb": "^4.0.2", "rollup-plugin-polyfill": "^4.2.0", diff --git a/sdk/typescript/packages/sdk-react/package.json b/sdk/typescript/packages/sdk-react/package.json index aa298a5a9d..b6dafc5d23 100644 --- a/sdk/typescript/packages/sdk-react/package.json +++ b/sdk/typescript/packages/sdk-react/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk-react", - "version": "1.2.0", + "version": "1.2.1", "license": "Apache-2.0", "author": "Nym Technologies SA", "files": [ @@ -20,7 +20,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" }, "devDependencies": { "@babel/core": "^7.17.5", @@ -67,4 +67,4 @@ "private": false, "type": "module", "types": "./dist/index.d.ts" -} +} \ No newline at end of file diff --git a/sdk/typescript/packages/sdk/package.json b/sdk/typescript/packages/sdk/package.json index 62102504ac..23e4b803ce 100644 --- a/sdk/typescript/packages/sdk/package.json +++ b/sdk/typescript/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk", - "version": "1.2.0", + "version": "1.2.1", "license": "Apache-2.0", "author": "Nym Technologies SA", "files": [ @@ -30,7 +30,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-client-wasm": ">=1.2.0-rc.10 || ^1", + "@nymproject/nym-client-wasm": ">=1.2.1-rc.0 || ^1", "comlink": "^4.3.1" }, "devDependencies": { diff --git a/wasm/client/Cargo.toml b/wasm/client/Cargo.toml index 5b8dda73da..8651e223d5 100644 --- a/wasm/client/Cargo.toml +++ b/wasm/client/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-client-wasm" authors = ["Dave Hrycyszyn ", "Jedrzej Stuczynski "] -version = "1.2.0" +version = "1.2.1" edition = "2021" keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"] license = "Apache-2.0" diff --git a/wasm/full-nym-wasm/Cargo.toml b/wasm/full-nym-wasm/Cargo.toml index d2cd98d808..0902eb625c 100644 --- a/wasm/full-nym-wasm/Cargo.toml +++ b/wasm/full-nym-wasm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-wasm-sdk" authors = ["Jedrzej Stuczynski "] -version = "1.2.0" +version = "1.2.1" edition = "2021" keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"] license = "Apache-2.0" diff --git a/wasm/mix-fetch/Cargo.toml b/wasm/mix-fetch/Cargo.toml index 50e5d61af2..3416758a3a 100644 --- a/wasm/mix-fetch/Cargo.toml +++ b/wasm/mix-fetch/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "mix-fetch-wasm" authors = ["Jedrzej Stuczynski "] -version = "1.2.0" +version = "1.2.1" edition = "2021" keywords = ["nym", "fetch", "wasm", "webassembly", "privacy"] license = "Apache-2.0" diff --git a/wasm/node-tester/Cargo.toml b/wasm/node-tester/Cargo.toml index 7c75e6c9b1..0397d64349 100644 --- a/wasm/node-tester/Cargo.toml +++ b/wasm/node-tester/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-node-tester-wasm" authors = ["Jedrzej Stuczynski "] -version = "1.2.0" +version = "1.2.1" edition = "2021" keywords = ["nym", "sphinx", "webassembly", "privacy", "tester"] license = "Apache-2.0" From 13aeca9c8895a78bae6adc5e7f79900258eb3cef Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Thu, 2 Nov 2023 21:37:47 +0000 Subject: [PATCH 216/236] Fix lint error --- sdk/typescript/packages/mix-fetch-node/src/worker/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts b/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts index 58cfb41a51..ee3a86ad3f 100644 --- a/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts +++ b/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts @@ -1,9 +1,9 @@ /* eslint-disable no-console */ -import type { IMixFetchWebWorker, LoadedEvent } from '../types'; import * as Comlink from 'comlink'; import { parentPort } from 'node:worker_threads'; import { setupMixFetch, disconnectMixFetch } from '@nymproject/mix-fetch-wasm-node'; +import type { IMixFetchWebWorker, LoadedEvent } from '../types'; import nodeEndpoint from '../node-adapter'; import { EventKinds, ResponseBodyConfigMap, ResponseBodyConfigMapDefaults } from '../types'; From 77aa58083d05a41f8acc60dda74225f23a7cf734 Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Thu, 2 Nov 2023 21:56:27 +0000 Subject: [PATCH 217/236] Fix lint error --- .../src/components/Accounts/modals/MultiAccountHowTo.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx b/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx index 05ddc018ad..620a21ae8a 100644 --- a/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx +++ b/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx @@ -21,7 +21,8 @@ export const MultiAccountHowTo = ({ show, handleClose }: { show: boolean; handle } /> - If you don’t have a password set for your account, log out, click on login with password and follow the forgot my password flow + If you don’t have a password set for your account, log out, click on login with password and follow the forgot + my password flow If you already have a password, log in to the wallet using your password then try create/import accounts From d151b907d1fa628e41dd5638822c5437d9718297 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Thu, 2 Nov 2023 23:36:14 +0100 Subject: [PATCH 218/236] added open proxies --- documentation/dev-portal/src/shipyard/infra.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/documentation/dev-portal/src/shipyard/infra.md b/documentation/dev-portal/src/shipyard/infra.md index b5621f6ff6..21d4af6dba 100644 --- a/documentation/dev-portal/src/shipyard/infra.md +++ b/documentation/dev-portal/src/shipyard/infra.md @@ -3,3 +3,10 @@ If you are writing an application that requires sending messages through the mix If you are relying on network requesters then chances are that the IPs or domains your app relies on will not already be on the whitelist. Ideally, you would [run your own,](https://nymtech.net/operators/nodes/network-requester-setup.html) but we will also run a few nodes in ‘open proxy’ mode and share the addresses so that you can use them when beginning to develop. +## Node Details: +- NR1 + - Location: Singapore + - Nym Address: `FDeWfd8q686PWLXJDCqNJTCbydTk1KSux5HVftimsPyx.9XyThN4yh92eTMuLp1NvWicRZob8Ei5xpba9dvcMLxcN@9Byd9VAtyYMnbVAcqdoQxJnq76XEg2dbxbiF5Aa5Jj9J` +- NR2 + - Location: Frankfurt + - Nym Address: `BNypKaGiGY8GNRN4gpV95GcaVS8n7CrHuoZNgQ2ezqv2ACpaixzuaSzuMajVQj6aR7cbpbvp676tm21MiLbX1gni@678qVUJ21uwxZBhp3r56z7GRf6gMh3NYDHruTegPtgMf` \ No newline at end of file From 50c994d2edfce339d999f3b85ea67101f00aae2f Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Fri, 3 Nov 2023 00:19:33 +0100 Subject: [PATCH 219/236] fixed addr --- documentation/dev-portal/src/shipyard/infra.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/dev-portal/src/shipyard/infra.md b/documentation/dev-portal/src/shipyard/infra.md index 21d4af6dba..73c3afadb3 100644 --- a/documentation/dev-portal/src/shipyard/infra.md +++ b/documentation/dev-portal/src/shipyard/infra.md @@ -9,4 +9,4 @@ If you are relying on network requesters then chances are that the IPs or domain - Nym Address: `FDeWfd8q686PWLXJDCqNJTCbydTk1KSux5HVftimsPyx.9XyThN4yh92eTMuLp1NvWicRZob8Ei5xpba9dvcMLxcN@9Byd9VAtyYMnbVAcqdoQxJnq76XEg2dbxbiF5Aa5Jj9J` - NR2 - Location: Frankfurt - - Nym Address: `BNypKaGiGY8GNRN4gpV95GcaVS8n7CrHuoZNgQ2ezqv2ACpaixzuaSzuMajVQj6aR7cbpbvp676tm21MiLbX1gni@678qVUJ21uwxZBhp3r56z7GRf6gMh3NYDHruTegPtgMf` \ No newline at end of file + - Nym Address: `BNypKaGiGY8GNRN4gpV95GcaVS8n7CrHuoZNgQ2ezqv2.ACpaixzuaSzuMajVQj6aR7cbpbvp676tm21MiLbX1gni@678qVUJ21uwxZBhp3r56z7GRf6gMh3NYDHruTegPtgMf` \ No newline at end of file From 7e6a4c073fd357aa4697d644ea1f67e276b84c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 3 Nov 2023 09:00:27 +0100 Subject: [PATCH 220/236] ci: cargo clean before clippy in nightly build --- .github/workflows/nightly-build.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 3dcabf2b28..3cadf150a2 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -82,6 +82,11 @@ jobs: command: test args: --workspace -- --ignored + - name: Clean + uses: actions-rs/cargo@v1 + with: + command: clean + - name: Clippy uses: actions-rs/cargo@v1 with: From 22dbdf0cd2c7e4018639119aa6909419fa5c2f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 27 Oct 2023 12:38:11 +0200 Subject: [PATCH 221/236] Create IpForwarderService --- Cargo.lock | 3 + common/wireguard/src/lib.rs | 7 ++- common/wireguard/src/platform/linux/mod.rs | 2 +- .../src/platform/linux/tun_device.rs | 6 +- service-providers/ip-packet-router/Cargo.toml | 3 + service-providers/ip-packet-router/src/lib.rs | 55 ++++++++++++++++++- 6 files changed, 66 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 72fad02808..5ed1e3fdb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6658,9 +6658,12 @@ dependencies = [ "nym-service-providers-common", "nym-sphinx", "nym-task", + "nym-wireguard", + "nym-wireguard-types", "serde", "serde_json", "thiserror", + "tokio", ] [[package]] diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index dc226c56fd..bd5aa47b4f 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -11,7 +11,7 @@ mod packet_relayer; mod platform; mod registered_peers; mod setup; -mod tun_task_channel; +pub mod tun_task_channel; mod udp_listener; mod wg_tunnel; @@ -20,7 +20,7 @@ use std::sync::Arc; // Currently the module related to setting up the virtual network device is platform specific. #[cfg(target_os = "linux")] -use platform::linux::tun_device; +pub use platform::linux::tun_device; /// Start wireguard UDP listener and TUN device /// @@ -39,7 +39,8 @@ pub async fn start_wireguard( let peers_by_tag = Arc::new(tokio::sync::Mutex::new(wg_tunnel::PeersByTag::new())); // Start the tun device that is used to relay traffic outbound - let (tun, tun_task_tx, tun_task_response_rx) = tun_device::TunDevice::new(peers_by_ip.clone()); + let (tun, tun_task_tx, tun_task_response_rx) = + tun_device::TunDevice::new(Some(peers_by_ip.clone())); tun.start(); // If we want to have the tun device on a separate host, it's the tun_task and diff --git a/common/wireguard/src/platform/linux/mod.rs b/common/wireguard/src/platform/linux/mod.rs index ebe0ba212c..fdf1de229d 100644 --- a/common/wireguard/src/platform/linux/mod.rs +++ b/common/wireguard/src/platform/linux/mod.rs @@ -1 +1 @@ -pub(crate) mod tun_device; +pub mod tun_device; diff --git a/common/wireguard/src/platform/linux/tun_device.rs b/common/wireguard/src/platform/linux/tun_device.rs index 348abdb609..1bf84eb52d 100644 --- a/common/wireguard/src/platform/linux/tun_device.rs +++ b/common/wireguard/src/platform/linux/tun_device.rs @@ -43,7 +43,7 @@ pub struct TunDevice { tun_task_response_tx: TunTaskResponseTx, // The routing table, as how wireguard does it - peers_by_ip: Arc>, + peers_by_ip: Option>>, // This is an alternative to the routing table, where we just match outgoing source IP with // incoming destination IP. @@ -52,7 +52,7 @@ pub struct TunDevice { impl TunDevice { pub fn new( - peers_by_ip: Arc>, + peers_by_ip: Option>>, ) -> (Self, TunTaskTx, TunTaskResponseRx) { let tun = setup_tokio_tun_device( format!("{TUN_BASE_NAME}%d").as_str(), @@ -123,7 +123,7 @@ impl TunDevice { // This is how wireguard does it, by consulting the AllowedIPs table. if false { - let peers = self.peers_by_ip.lock().await; + let peers = self.peers_by_ip.as_ref().unwrap().lock().await; if let Some(peer_tx) = peers.longest_match(dst_addr).map(|(_, tx)| tx) { log::info!("Forward packet to wg tunnel"); peer_tx diff --git a/service-providers/ip-packet-router/Cargo.toml b/service-providers/ip-packet-router/Cargo.toml index c01c13cfb4..93deae5a48 100644 --- a/service-providers/ip-packet-router/Cargo.toml +++ b/service-providers/ip-packet-router/Cargo.toml @@ -18,6 +18,9 @@ nym-sdk = { path = "../../sdk/rust/nym-sdk" } nym-service-providers-common = { path = "../common" } nym-sphinx = { path = "../../common/nymsphinx" } nym-task = { path = "../../common/task" } +nym-wireguard = { path = "../../common/wireguard" } +nym-wireguard-types = { path = "../../common/wireguard-types" } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } thiserror = { workspace = true } +tokio = { workspace = true, features = ["rt-multi-thread", "net", "io-util"] } diff --git a/service-providers/ip-packet-router/src/lib.rs b/service-providers/ip-packet-router/src/lib.rs index 9aadf5f50a..ca4f0481c1 100644 --- a/service-providers/ip-packet-router/src/lib.rs +++ b/service-providers/ip-packet-router/src/lib.rs @@ -1,12 +1,13 @@ use std::path::Path; use error::IpForwarderError; -use futures::channel::oneshot; +use futures::{channel::oneshot, StreamExt}; use nym_client_core::{ client::mix_traffic::transceiver::GatewayTransceiver, config::disk_persistence::CommonClientPaths, HardcodedTopologyProvider, TopologyProvider, }; use nym_sdk::{mixnet::Recipient, NymNetworkDetails}; +use nym_sphinx::receiver::ReconstructedMessage; use nym_task::{TaskClient, TaskHandle}; use crate::config::BaseClientConfig; @@ -95,12 +96,12 @@ impl IpForwarderBuilder { pub async fn run_service_provider(self) -> Result<(), IpForwarderError> { // Used to notify tasks to shutdown. Not all tasks fully supports this (yet). - let shutdown: TaskHandle = self.shutdown.map(Into::into).unwrap_or_default(); + let task_handle: TaskHandle = self.shutdown.map(Into::into).unwrap_or_default(); // Connect to the mixnet let mixnet_client = create_mixnet_client( &self.config.base, - shutdown.get_handle().named("nym_sdk::MixnetClient"), + task_handle.get_handle().named("nym_sdk::MixnetClient"), self.custom_gateway_transceiver, self.custom_topology_provider, self.wait_for_gateway, @@ -110,6 +111,19 @@ impl IpForwarderBuilder { let self_address = *mixnet_client.nym_address(); + // Create the TUN device that we interact with the rest of the world with + let (tun, tun_task_tx, tun_task_response_rx) = + nym_wireguard::tun_device::TunDevice::new(None); + + let ip_forwarder_service = IpForwarderService { + config: self.config, + tun, + tun_task_tx, + tun_task_response_rx, + mixnet_client, + task_handle, + }; + log::info!("The address of this client is: {self_address}"); log::info!("All systems go. Press CTRL-C to stop the server."); @@ -120,6 +134,41 @@ impl IpForwarderBuilder { } } + ip_forwarder_service.run().await + } +} + +struct IpForwarderService { + config: Config, + tun: nym_wireguard::tun_device::TunDevice, + tun_task_tx: nym_wireguard::tun_task_channel::TunTaskTx, + tun_task_response_rx: nym_wireguard::tun_task_channel::TunTaskResponseRx, + mixnet_client: nym_sdk::mixnet::MixnetClient, + task_handle: TaskHandle, +} + +impl IpForwarderService { + async fn run(mut self) -> Result<(), IpForwarderError> { + let mut task_client = self.task_handle.fork("main_loop"); + while !task_client.is_shutdown() { + tokio::select! { + _ = task_client.recv() => { + log::debug!("IpForwarderService [main loop]: received shutdown"); + }, + msg = self.mixnet_client.next() => match msg { + Some(msg) => self.on_message(msg).await, + None => { + log::trace!("IpForwarderService [main loop]: stopping since channel closed"); + break; + }, + } + } + } + log::info!("IpForwarderService: stopping"); + Ok(()) + } + + async fn on_message(&mut self, reconstructed: ReconstructedMessage) { todo!(); } } From 833a1b118e2282610932333de66b7ae6c3fcbdff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 27 Oct 2023 17:32:25 +0200 Subject: [PATCH 222/236] on_message --- Cargo.lock | 2 + common/wireguard/src/tun_task_channel.rs | 4 +- service-providers/ip-packet-router/Cargo.toml | 2 + .../ip-packet-router/src/error.rs | 10 ++- service-providers/ip-packet-router/src/lib.rs | 80 ++++++++++++++++--- 5 files changed, 84 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5ed1e3fdb0..2916eadb0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6649,6 +6649,7 @@ dependencies = [ name = "nym-ip-packet-router" version = "0.1.0" dependencies = [ + "etherparse", "futures", "log", "nym-bin-common", @@ -6662,6 +6663,7 @@ dependencies = [ "nym-wireguard-types", "serde", "serde_json", + "tap", "thiserror", "tokio", ] diff --git a/common/wireguard/src/tun_task_channel.rs b/common/wireguard/src/tun_task_channel.rs index 1cbd6985da..8928aa6049 100644 --- a/common/wireguard/src/tun_task_channel.rs +++ b/common/wireguard/src/tun_task_channel.rs @@ -7,7 +7,7 @@ pub struct TunTaskTx(mpsc::Sender); pub(crate) struct TunTaskRx(mpsc::Receiver); impl TunTaskTx { - pub(crate) async fn send( + pub async fn send( &self, data: TunTaskPayload, ) -> Result<(), tokio::sync::mpsc::error::SendError> { @@ -40,7 +40,7 @@ impl TunTaskResponseTx { } impl TunTaskResponseRx { - pub(crate) async fn recv(&mut self) -> Option { + pub async fn recv(&mut self) -> Option { self.0.recv().await } } diff --git a/service-providers/ip-packet-router/Cargo.toml b/service-providers/ip-packet-router/Cargo.toml index 93deae5a48..3aa52688f4 100644 --- a/service-providers/ip-packet-router/Cargo.toml +++ b/service-providers/ip-packet-router/Cargo.toml @@ -9,6 +9,7 @@ edition.workspace = true license.workspace = true [dependencies] +etherparse = "0.13.0" futures = { workspace = true } log = { workspace = true } nym-bin-common = { path = "../../common/bin-common" } @@ -22,5 +23,6 @@ nym-wireguard = { path = "../../common/wireguard" } nym-wireguard-types = { path = "../../common/wireguard-types" } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } +tap.workspace = true thiserror = { workspace = true } tokio = { workspace = true, features = ["rt-multi-thread", "net", "io-util"] } diff --git a/service-providers/ip-packet-router/src/error.rs b/service-providers/ip-packet-router/src/error.rs index 7a0268fb61..1fb4be6ad6 100644 --- a/service-providers/ip-packet-router/src/error.rs +++ b/service-providers/ip-packet-router/src/error.rs @@ -12,7 +12,7 @@ pub enum IpForwarderError { FailedToLoadConfig(String), // TODO: add more details here - #[error("Failed to validate the loaded config")] + #[error("failed to validate the loaded config")] ConfigValidationFailure, #[error("failed local version check, client and config mismatch")] @@ -26,4 +26,12 @@ pub enum IpForwarderError { #[error("the entity wrapping the network requester has disconnected")] DisconnectedParent, + + #[error("failed to parse incoming packet: {source}")] + PacketParseFailed { + source: etherparse::ReadError, + }, + + #[error("parsed packet is missing IP header")] + PacketMissingHeader, } diff --git a/service-providers/ip-packet-router/src/lib.rs b/service-providers/ip-packet-router/src/lib.rs index ca4f0481c1..2cfaffbbe7 100644 --- a/service-providers/ip-packet-router/src/lib.rs +++ b/service-providers/ip-packet-router/src/lib.rs @@ -1,4 +1,4 @@ -use std::path::Path; +use std::{net::IpAddr, path::Path}; use error::IpForwarderError; use futures::{channel::oneshot, StreamExt}; @@ -6,9 +6,13 @@ use nym_client_core::{ client::mix_traffic::transceiver::GatewayTransceiver, config::disk_persistence::CommonClientPaths, HardcodedTopologyProvider, TopologyProvider, }; -use nym_sdk::{mixnet::Recipient, NymNetworkDetails}; +use nym_sdk::{ + mixnet::{InputMessage, MixnetMessageSender, Recipient}, + NymNetworkDetails, +}; use nym_sphinx::receiver::ReconstructedMessage; use nym_task::{TaskClient, TaskHandle}; +use tap::TapFallible; use crate::config::BaseClientConfig; @@ -115,7 +119,7 @@ impl IpForwarderBuilder { let (tun, tun_task_tx, tun_task_response_rx) = nym_wireguard::tun_device::TunDevice::new(None); - let ip_forwarder_service = IpForwarderService { + let ip_forwarder_service = IpForwarder { config: self.config, tun, tun_task_tx, @@ -138,7 +142,7 @@ impl IpForwarderBuilder { } } -struct IpForwarderService { +struct IpForwarder { config: Config, tun: nym_wireguard::tun_device::TunDevice, tun_task_tx: nym_wireguard::tun_task_channel::TunTaskTx, @@ -147,7 +151,7 @@ struct IpForwarderService { task_handle: TaskHandle, } -impl IpForwarderService { +impl IpForwarder { async fn run(mut self) -> Result<(), IpForwarderError> { let mut task_client = self.task_handle.fork("main_loop"); while !task_client.is_shutdown() { @@ -155,21 +159,75 @@ impl IpForwarderService { _ = task_client.recv() => { log::debug!("IpForwarderService [main loop]: received shutdown"); }, - msg = self.mixnet_client.next() => match msg { - Some(msg) => self.on_message(msg).await, - None => { + msg = self.mixnet_client.next() => { + if let Some(msg) = msg { + self.on_message(msg).await.ok(); + } else { log::trace!("IpForwarderService [main loop]: stopping since channel closed"); break; - }, + }; + }, + packet = self.tun_task_response_rx.recv() => { + if let Some((tag, packet)) = packet { + // let input_message = InputMessage { + // }; + // self.mixnet_client + // .send(input_message) + // .await + // .tap_err(|err| { + // log::error!("IpForwarderService [main loop]: failed to send packet to mixnet: {err}"); + // }) + // .ok(); + } else { + log::trace!("IpForwarderService [main loop]: stopping since channel closed"); + break; + } } + } } log::info!("IpForwarderService: stopping"); Ok(()) } - async fn on_message(&mut self, reconstructed: ReconstructedMessage) { - todo!(); + async fn on_message( + &mut self, + reconstructed: ReconstructedMessage, + ) -> Result<(), IpForwarderError> { + log::info!("Received message: {:?}", reconstructed.sender_tag); + + let headers = etherparse::SlicedPacket::from_ip(&reconstructed.message).map_err(|err| { + log::warn!("Received non-IP packet: {err}"); + IpForwarderError::PacketParseFailed { source: err } + })?; + + let (src_addr, dst_addr): (IpAddr, IpAddr) = match headers.ip { + Some(etherparse::InternetSlice::Ipv4(ipv4_header, _)) => ( + ipv4_header.source_addr().into(), + ipv4_header.destination_addr().into(), + ), + Some(etherparse::InternetSlice::Ipv6(ipv6_header, _)) => ( + ipv6_header.source_addr().into(), + ipv6_header.destination_addr().into(), + ), + None => { + log::warn!("Received non-IP packet"); + return Err(IpForwarderError::PacketMissingHeader); + } + }; + log::info!("Received packet: {src_addr} -> {dst_addr}"); + + // TODO: set the tag correctly. Can we just reuse sender_tag? + let tag = 0; + self.tun_task_tx + .send((tag, reconstructed.message)) + .await + .tap_err(|err| { + log::error!("Failed to send packet to tun device: {err}"); + }) + .ok(); + + Ok(()) } } From bb0fb71a213f17559650fc10402d3b4071d65380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 2 Nov 2023 11:42:50 +0100 Subject: [PATCH 223/236] Rename remaining places to ip packet router --- gateway/src/error.rs | 4 +- gateway/src/node/mod.rs | 2 +- .../ip-packet-router/src/config/mod.rs | 22 ++++----- .../src/config/persistence.rs | 8 ++-- .../ip-packet-router/src/config/template.rs | 2 +- .../ip-packet-router/src/error.rs | 2 +- service-providers/ip-packet-router/src/lib.rs | 46 +++++++++---------- 7 files changed, 43 insertions(+), 43 deletions(-) diff --git a/gateway/src/error.rs b/gateway/src/error.rs index d69b8eb480..470e5421c4 100644 --- a/gateway/src/error.rs +++ b/gateway/src/error.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::node::storage::error::StorageError; -use nym_ip_packet_router::error::IpForwarderError; +use nym_ip_packet_router::error::IpPacketRouterError; use nym_network_requester::error::{ClientCoreError, NetworkRequesterError}; use nym_validator_client::nyxd::error::NyxdError; use nym_validator_client::nyxd::AccountId; @@ -110,7 +110,7 @@ pub(crate) enum GatewayError { #[error("there was an issue with the local ip packet router: {source}")] IpPacketRouterFailure { #[from] - source: IpForwarderError, + source: IpPacketRouterError, }, #[error("failed to startup local network requester")] diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index d3851a671c..573453e3de 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -346,7 +346,7 @@ impl Gateway { // TODO: well, wire it up internally to gateway traffic, shutdowns, etc. let (on_start_tx, on_start_rx) = oneshot::channel(); - let mut ip_builder = nym_ip_packet_router::IpForwarderBuilder::new(ip_opts.config.clone()) + let mut ip_builder = nym_ip_packet_router::IpPacketRouterBuilder::new(ip_opts.config.clone()) .with_shutdown(shutdown) .with_custom_gateway_transceiver(Box::new(transceiver)) .with_wait_for_gateway(true) diff --git a/service-providers/ip-packet-router/src/config/mod.rs b/service-providers/ip-packet-router/src/config/mod.rs index 19bcaedc49..4b6b811bda 100644 --- a/service-providers/ip-packet-router/src/config/mod.rs +++ b/service-providers/ip-packet-router/src/config/mod.rs @@ -12,28 +12,28 @@ use std::{ path::{Path, PathBuf}, }; -use crate::config::persistence::IpForwarderPaths; +use crate::config::persistence::IpPacketRouterPaths; use self::template::CONFIG_TEMPLATE; mod persistence; mod template; -const DEFAULT_IP_FORWARDERS_DIR: &str = "ip-forwarder"; +const DEFAULT_IP_PACKET_ROUTER_DIR: &str = "ip-packet-router"; -/// Derive default path to ip forwarder's config directory. -/// It should get resolved to `$HOME/.nym/service-providers/ip-forwareder//config` +/// Derive default path to ip packet routers' config directory. +/// It should get resolved to `$HOME/.nym/service-providers/ip-packet-router//config` pub fn default_config_directory>(id: P) -> PathBuf { must_get_home() .join(NYM_DIR) .join(DEFAULT_SERVICE_PROVIDERS_DIR) - .join(DEFAULT_IP_FORWARDERS_DIR) + .join(DEFAULT_IP_PACKET_ROUTER_DIR) .join(id) .join(DEFAULT_CONFIG_DIR) } -/// Derive default path to ip forwarder's config file. -/// It should get resolved to `$HOME/.nym/service-providers/ip-forwarder//config/config.toml` +/// Derive default path to ip packet routers' config file. +/// It should get resolved to `$HOME/.nym/service-providers/ip-packet-router//config/config.toml` pub fn default_config_filepath>(id: P) -> PathBuf { default_config_directory(id).join(DEFAULT_CONFIG_FILENAME) } @@ -44,7 +44,7 @@ pub fn default_data_directory>(id: P) -> PathBuf { must_get_home() .join(NYM_DIR) .join(DEFAULT_SERVICE_PROVIDERS_DIR) - .join(DEFAULT_IP_FORWARDERS_DIR) + .join(DEFAULT_IP_PACKET_ROUTER_DIR) .join(id) .join(DEFAULT_DATA_DIR) } @@ -55,7 +55,7 @@ pub struct Config { #[serde(flatten)] pub base: BaseClientConfig, - pub storage_paths: IpForwarderPaths, + pub storage_paths: IpPacketRouterPaths, pub logging: LoggingSettings, } @@ -70,13 +70,13 @@ impl Config { pub fn new>(id: S) -> Self { Config { base: BaseClientConfig::new(id.as_ref(), env!("CARGO_PKG_VERSION")), - storage_paths: IpForwarderPaths::new_base(default_data_directory(id.as_ref())), + storage_paths: IpPacketRouterPaths::new_base(default_data_directory(id.as_ref())), logging: Default::default(), } } pub fn with_data_directory>(mut self, data_directory: P) -> Self { - self.storage_paths = IpForwarderPaths::new_base(data_directory); + self.storage_paths = IpPacketRouterPaths::new_base(data_directory); self } diff --git a/service-providers/ip-packet-router/src/config/persistence.rs b/service-providers/ip-packet-router/src/config/persistence.rs index 17276d36b3..7f60a98f8c 100644 --- a/service-providers/ip-packet-router/src/config/persistence.rs +++ b/service-providers/ip-packet-router/src/config/persistence.rs @@ -8,21 +8,21 @@ use std::path::{Path, PathBuf}; pub const DEFAULT_DESCRIPTION_FILENAME: &str = "description.toml"; #[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)] -pub struct IpForwarderPaths { +pub struct IpPacketRouterPaths { #[serde(flatten)] pub common_paths: CommonClientPaths, /// Location of the file containing our description - pub ip_forwarder_description: PathBuf, + pub ip_packet_router_description: PathBuf, } -impl IpForwarderPaths { +impl IpPacketRouterPaths { pub fn new_base>(base_data_directory: P) -> Self { let base_dir = base_data_directory.as_ref(); Self { common_paths: CommonClientPaths::new_base(base_dir), - ip_forwarder_description: base_dir.join(DEFAULT_DESCRIPTION_FILENAME), + ip_packet_router_description: base_dir.join(DEFAULT_DESCRIPTION_FILENAME), } } } diff --git a/service-providers/ip-packet-router/src/config/template.rs b/service-providers/ip-packet-router/src/config/template.rs index 2da118a580..bbd9e18d5d 100644 --- a/service-providers/ip-packet-router/src/config/template.rs +++ b/service-providers/ip-packet-router/src/config/template.rs @@ -76,7 +76,7 @@ allowed_list_location = '{{ storage_paths.allowed_list_location }}' unknown_list_location = '{{ storage_paths.unknown_list_location }}' # Path to file containing description of this network-requester. -ip_forwarder_description = '{{ storage_paths.ip_forwarder_description }}' +ip_packet_router_description = '{{ storage_paths.ip_packet_router_description }}' ##### logging configuration options ##### diff --git a/service-providers/ip-packet-router/src/error.rs b/service-providers/ip-packet-router/src/error.rs index 1fb4be6ad6..20f0c3d319 100644 --- a/service-providers/ip-packet-router/src/error.rs +++ b/service-providers/ip-packet-router/src/error.rs @@ -1,7 +1,7 @@ pub use nym_client_core::error::ClientCoreError; #[derive(thiserror::Error, Debug)] -pub enum IpForwarderError { +pub enum IpPacketRouterError { #[error("I/O error: {0}")] IoError(#[from] std::io::Error), diff --git a/service-providers/ip-packet-router/src/lib.rs b/service-providers/ip-packet-router/src/lib.rs index 2cfaffbbe7..4e720b04ac 100644 --- a/service-providers/ip-packet-router/src/lib.rs +++ b/service-providers/ip-packet-router/src/lib.rs @@ -1,6 +1,6 @@ use std::{net::IpAddr, path::Path}; -use error::IpForwarderError; +use error::IpPacketRouterError; use futures::{channel::oneshot, StreamExt}; use nym_client_core::{ client::mix_traffic::transceiver::GatewayTransceiver, @@ -32,7 +32,7 @@ impl OnStartData { } } -pub struct IpForwarderBuilder { +pub struct IpPacketRouterBuilder { config: Config, wait_for_gateway: bool, custom_topology_provider: Option>, @@ -41,7 +41,7 @@ pub struct IpForwarderBuilder { on_start: Option>, } -impl IpForwarderBuilder { +impl IpPacketRouterBuilder { pub fn new(config: Config) -> Self { Self { config, @@ -92,13 +92,13 @@ impl IpForwarderBuilder { pub fn with_stored_topology>( mut self, file: P, - ) -> Result { + ) -> Result { self.custom_topology_provider = Some(Box::new(HardcodedTopologyProvider::new_from_file(file)?)); Ok(self) } - pub async fn run_service_provider(self) -> Result<(), IpForwarderError> { + pub async fn run_service_provider(self) -> Result<(), IpPacketRouterError> { // Used to notify tasks to shutdown. Not all tasks fully supports this (yet). let task_handle: TaskHandle = self.shutdown.map(Into::into).unwrap_or_default(); @@ -119,7 +119,7 @@ impl IpForwarderBuilder { let (tun, tun_task_tx, tun_task_response_rx) = nym_wireguard::tun_device::TunDevice::new(None); - let ip_forwarder_service = IpForwarder { + let ip_packet_router_service = IpPacketRouter { config: self.config, tun, tun_task_tx, @@ -134,15 +134,15 @@ impl IpForwarderBuilder { if let Some(on_start) = self.on_start { if on_start.send(OnStartData::new(self_address)).is_err() { // the parent has dropped the channel before receiving the response - return Err(IpForwarderError::DisconnectedParent); + return Err(IpPacketRouterError::DisconnectedParent); } } - ip_forwarder_service.run().await + ip_packet_router_service.run().await } } -struct IpForwarder { +struct IpPacketRouter { config: Config, tun: nym_wireguard::tun_device::TunDevice, tun_task_tx: nym_wireguard::tun_task_channel::TunTaskTx, @@ -151,19 +151,19 @@ struct IpForwarder { task_handle: TaskHandle, } -impl IpForwarder { - async fn run(mut self) -> Result<(), IpForwarderError> { +impl IpPacketRouter { + async fn run(mut self) -> Result<(), IpPacketRouterError> { let mut task_client = self.task_handle.fork("main_loop"); while !task_client.is_shutdown() { tokio::select! { _ = task_client.recv() => { - log::debug!("IpForwarderService [main loop]: received shutdown"); + log::debug!("IpPacketRouter [main loop]: received shutdown"); }, msg = self.mixnet_client.next() => { if let Some(msg) = msg { self.on_message(msg).await.ok(); } else { - log::trace!("IpForwarderService [main loop]: stopping since channel closed"); + log::trace!("IpPacketRouter [main loop]: stopping since channel closed"); break; }; }, @@ -175,30 +175,30 @@ impl IpForwarder { // .send(input_message) // .await // .tap_err(|err| { - // log::error!("IpForwarderService [main loop]: failed to send packet to mixnet: {err}"); + // log::error!("IpPacketRouter [main loop]: failed to send packet to mixnet: {err}"); // }) // .ok(); } else { - log::trace!("IpForwarderService [main loop]: stopping since channel closed"); + log::trace!("IpPacketRouter [main loop]: stopping since channel closed"); break; } } } } - log::info!("IpForwarderService: stopping"); + log::info!("IpPacketRouter: stopping"); Ok(()) } async fn on_message( &mut self, reconstructed: ReconstructedMessage, - ) -> Result<(), IpForwarderError> { + ) -> Result<(), IpPacketRouterError> { log::info!("Received message: {:?}", reconstructed.sender_tag); let headers = etherparse::SlicedPacket::from_ip(&reconstructed.message).map_err(|err| { log::warn!("Received non-IP packet: {err}"); - IpForwarderError::PacketParseFailed { source: err } + IpPacketRouterError::PacketParseFailed { source: err } })?; let (src_addr, dst_addr): (IpAddr, IpAddr) = match headers.ip { @@ -212,7 +212,7 @@ impl IpForwarder { ), None => { log::warn!("Received non-IP packet"); - return Err(IpForwarderError::PacketMissingHeader); + return Err(IpPacketRouterError::PacketMissingHeader); } }; log::info!("Received packet: {src_addr} -> {dst_addr}"); @@ -242,7 +242,7 @@ async fn create_mixnet_client( custom_topology_provider: Option>, wait_for_gateway: bool, paths: &CommonClientPaths, -) -> Result { +) -> Result { let debug_config = config.debug; let storage_paths = nym_sdk::mixnet::StoragePaths::from(paths.clone()); @@ -250,7 +250,7 @@ async fn create_mixnet_client( let mut client_builder = nym_sdk::mixnet::MixnetClientBuilder::new_with_default_storage(storage_paths) .await - .map_err(|err| IpForwarderError::FailedToSetupMixnetClient { source: err })? + .map_err(|err| IpPacketRouterError::FailedToSetupMixnetClient { source: err })? .network_details(NymNetworkDetails::new_from_env()) .debug_config(debug_config) .custom_shutdown(shutdown) @@ -267,10 +267,10 @@ async fn create_mixnet_client( let mixnet_client = client_builder .build() - .map_err(|err| IpForwarderError::FailedToSetupMixnetClient { source: err })?; + .map_err(|err| IpPacketRouterError::FailedToSetupMixnetClient { source: err })?; mixnet_client .connect_to_mixnet() .await - .map_err(|err| IpForwarderError::FailedToConnectToMixnet { source: err }) + .map_err(|err| IpPacketRouterError::FailedToConnectToMixnet { source: err }) } From 5f5ac4449c3e712d2864b6405409143627680c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 2 Nov 2023 14:16:58 +0100 Subject: [PATCH 224/236] send back to mixnet --- service-providers/ip-packet-router/src/lib.rs | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/service-providers/ip-packet-router/src/lib.rs b/service-providers/ip-packet-router/src/lib.rs index 4e720b04ac..5ef1ad41a0 100644 --- a/service-providers/ip-packet-router/src/lib.rs +++ b/service-providers/ip-packet-router/src/lib.rs @@ -11,7 +11,7 @@ use nym_sdk::{ NymNetworkDetails, }; use nym_sphinx::receiver::ReconstructedMessage; -use nym_task::{TaskClient, TaskHandle}; +use nym_task::{connections::TransmissionLane, TaskClient, TaskHandle}; use tap::TapFallible; use crate::config::BaseClientConfig; @@ -118,10 +118,11 @@ impl IpPacketRouterBuilder { // Create the TUN device that we interact with the rest of the world with let (tun, tun_task_tx, tun_task_response_rx) = nym_wireguard::tun_device::TunDevice::new(None); + tun.start(); let ip_packet_router_service = IpPacketRouter { config: self.config, - tun, + // tun, tun_task_tx, tun_task_response_rx, mixnet_client, @@ -144,7 +145,7 @@ impl IpPacketRouterBuilder { struct IpPacketRouter { config: Config, - tun: nym_wireguard::tun_device::TunDevice, + // tun: nym_wireguard::tun_device::TunDevice, tun_task_tx: nym_wireguard::tun_task_channel::TunTaskTx, tun_task_response_rx: nym_wireguard::tun_task_channel::TunTaskResponseRx, mixnet_client: nym_sdk::mixnet::MixnetClient, @@ -154,6 +155,7 @@ struct IpPacketRouter { impl IpPacketRouter { async fn run(mut self) -> Result<(), IpPacketRouterError> { let mut task_client = self.task_handle.fork("main_loop"); + while !task_client.is_shutdown() { tokio::select! { _ = task_client.recv() => { @@ -168,16 +170,21 @@ impl IpPacketRouter { }; }, packet = self.tun_task_response_rx.recv() => { - if let Some((tag, packet)) = packet { - // let input_message = InputMessage { - // }; - // self.mixnet_client - // .send(input_message) - // .await - // .tap_err(|err| { - // log::error!("IpPacketRouter [main loop]: failed to send packet to mixnet: {err}"); - // }) - // .ok(); + if let Some((_tag, packet)) = packet { + // TODO: basically we need to map the tag to the recipient + // For now we just hardcode the recipient + let recipient = Recipient::try_from_base58_string("sfl;sdf").unwrap(); + let lane = TransmissionLane::General; + let packet_type = None; + let input_message = InputMessage::new_regular(recipient, packet, lane, packet_type); + + self.mixnet_client + .send(input_message) + .await + .tap_err(|err| { + log::error!("IpPacketRouter [main loop]: failed to send packet to mixnet: {err}"); + }) + .ok(); } else { log::trace!("IpPacketRouter [main loop]: stopping since channel closed"); break; @@ -218,9 +225,9 @@ impl IpPacketRouter { log::info!("Received packet: {src_addr} -> {dst_addr}"); // TODO: set the tag correctly. Can we just reuse sender_tag? - let tag = 0; + let peer_tag = 0; self.tun_task_tx - .send((tag, reconstructed.message)) + .send((peer_tag, reconstructed.message)) .await .tap_err(|err| { log::error!("Failed to send packet to tun device: {err}"); From 6beb77e464f9ea26a72d9f2ace174750cb90965d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 2 Nov 2023 14:18:27 +0100 Subject: [PATCH 225/236] rustfmt --- gateway/src/node/mod.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 573453e3de..d3764c635a 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -346,11 +346,12 @@ impl Gateway { // TODO: well, wire it up internally to gateway traffic, shutdowns, etc. let (on_start_tx, on_start_rx) = oneshot::channel(); - let mut ip_builder = nym_ip_packet_router::IpPacketRouterBuilder::new(ip_opts.config.clone()) - .with_shutdown(shutdown) - .with_custom_gateway_transceiver(Box::new(transceiver)) - .with_wait_for_gateway(true) - .with_on_start(on_start_tx); + let mut ip_builder = + nym_ip_packet_router::IpPacketRouterBuilder::new(ip_opts.config.clone()) + .with_shutdown(shutdown) + .with_custom_gateway_transceiver(Box::new(transceiver)) + .with_wait_for_gateway(true) + .with_on_start(on_start_tx); if let Some(custom_mixnet) = &ip_opts.custom_mixnet_path { ip_builder = ip_builder.with_stored_topology(custom_mixnet)? From 71a409cc0dcd949209574e693fa14b3f3e64ae17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 2 Nov 2023 17:01:35 +0100 Subject: [PATCH 226/236] Add RoutingMode enum --- .../src/platform/linux/tun_device.rs | 84 +++++++++++++------ 1 file changed, 58 insertions(+), 26 deletions(-) diff --git a/common/wireguard/src/platform/linux/tun_device.rs b/common/wireguard/src/platform/linux/tun_device.rs index 1bf84eb52d..196102394f 100644 --- a/common/wireguard/src/platform/linux/tun_device.rs +++ b/common/wireguard/src/platform/linux/tun_device.rs @@ -42,11 +42,35 @@ pub struct TunDevice { // And when we get replies, this is where we should send it tun_task_response_tx: TunTaskResponseTx, + routing_mode: RoutingMode, +} + +enum RoutingMode { // The routing table, as how wireguard does it - peers_by_ip: Option>>, + AllowedIps(AllowedIpsInner), // This is an alternative to the routing table, where we just match outgoing source IP with // incoming destination IP. + Nat(NatInner), +} + +impl RoutingMode { + fn new_nat() -> Self { + RoutingMode::Nat(NatInner { + nat_table: HashMap::new(), + }) + } + + fn new_allowed_ips(peers_by_ip: Arc>) -> Self { + RoutingMode::AllowedIps(AllowedIpsInner { peers_by_ip }) + } +} + +struct AllowedIpsInner { + peers_by_ip: Arc>, +} + +struct NatInner { nat_table: HashMap, } @@ -65,12 +89,16 @@ impl TunDevice { let (tun_task_tx, tun_task_rx) = tun_task_channel(); let (tun_task_response_tx, tun_task_response_rx) = tun_task_response_channel(); + let routing_mode = match peers_by_ip { + Some(peers_by_ip) => RoutingMode::new_allowed_ips(peers_by_ip), + None => RoutingMode::new_nat(), + }; + let tun_device = TunDevice { tun_task_rx, tun_task_response_tx, tun, - peers_by_ip, - nat_table: HashMap::new(), + routing_mode, }; (tun_device, tun_task_tx, tun_task_response_rx) @@ -93,7 +121,9 @@ impl TunDevice { ); // TODO: expire old entries - self.nat_table.insert(src_addr, tag); + if let RoutingMode::Nat(nat_table) = &mut self.routing_mode { + nat_table.nat_table.insert(src_addr, tag); + } self.tun .write_all(&packet) @@ -121,30 +151,32 @@ impl TunDevice { // Route packet to the correct peer. - // This is how wireguard does it, by consulting the AllowedIPs table. - if false { - let peers = self.peers_by_ip.as_ref().unwrap().lock().await; - if let Some(peer_tx) = peers.longest_match(dst_addr).map(|(_, tx)| tx) { - log::info!("Forward packet to wg tunnel"); - peer_tx - .send(Event::Ip(packet.to_vec().into())) - .await - .tap_err(|err| log::error!("{err}")) - .ok(); - return; + match self.routing_mode { + // This is how wireguard does it, by consulting the AllowedIPs table. + RoutingMode::AllowedIps(ref peers_by_ip) => { + let peers = peers_by_ip.peers_by_ip.as_ref().lock().await; + if let Some(peer_tx) = peers.longest_match(dst_addr).map(|(_, tx)| tx) { + log::info!("Forward packet to wg tunnel"); + peer_tx + .send(Event::Ip(packet.to_vec().into())) + .await + .tap_err(|err| log::error!("{err}")) + .ok(); + return; + } } - } - // But we do it by consulting the NAT table. - { - if let Some(tag) = self.nat_table.get(&dst_addr) { - log::info!("Forward packet to wg tunnel with tag: {tag}"); - self.tun_task_response_tx - .send((*tag, packet.to_vec())) - .await - .tap_err(|err| log::error!("{err}")) - .ok(); - return; + // But we do it by consulting the NAT table. + RoutingMode::Nat(ref nat_table) => { + if let Some(tag) = nat_table.nat_table.get(&dst_addr) { + log::info!("Forward packet to wg tunnel with tag: {tag}"); + self.tun_task_response_tx + .send((*tag, packet.to_vec())) + .await + .tap_err(|err| log::error!("{err}")) + .ok(); + return; + } } } From 90c40b76f57c1b90feb21bf21ad391abac09a099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 2 Nov 2023 17:01:49 +0100 Subject: [PATCH 227/236] rustfmt --- service-providers/ip-packet-router/src/error.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/service-providers/ip-packet-router/src/error.rs b/service-providers/ip-packet-router/src/error.rs index 20f0c3d319..8bf599e232 100644 --- a/service-providers/ip-packet-router/src/error.rs +++ b/service-providers/ip-packet-router/src/error.rs @@ -28,9 +28,7 @@ pub enum IpPacketRouterError { DisconnectedParent, #[error("failed to parse incoming packet: {source}")] - PacketParseFailed { - source: etherparse::ReadError, - }, + PacketParseFailed { source: etherparse::ReadError }, #[error("parsed packet is missing IP header")] PacketMissingHeader, From 756aca36ad74bc70bfb287bc3d2b1af922410269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 3 Nov 2023 09:25:53 +0100 Subject: [PATCH 228/236] Take RoutingMode as argument --- common/wireguard/src/lib.rs | 17 ++++++++++++----- .../wireguard/src/platform/linux/tun_device.rs | 18 +++++++----------- service-providers/ip-packet-router/src/lib.rs | 9 +++++---- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index bd5aa47b4f..9d734ce8d9 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -32,17 +32,24 @@ pub async fn start_wireguard( task_client: nym_task::TaskClient, gateway_client_registry: Arc, ) -> Result<(), Box> { - // We can either index peers by their IP like standard wireguard + // TODO: make this configurable + + // We can optionally index peers by their IP like standard wireguard. If we don't then we do + // plain NAT where we match incoming destination IP with outgoing source IP. let peers_by_ip = Arc::new(tokio::sync::Mutex::new(network_table::NetworkTable::new())); - // ... or by their tunnel tag, which is a random number assigned to them - let peers_by_tag = Arc::new(tokio::sync::Mutex::new(wg_tunnel::PeersByTag::new())); + // Alternative 1: + let routing_mode = tun_device::RoutingMode::new_allowed_ips(peers_by_ip.clone()); + // Alternative 2: + //let routing_mode = tun_device::RoutingMode::new_nat(); // Start the tun device that is used to relay traffic outbound - let (tun, tun_task_tx, tun_task_response_rx) = - tun_device::TunDevice::new(Some(peers_by_ip.clone())); + let (tun, tun_task_tx, tun_task_response_rx) = tun_device::TunDevice::new(routing_mode); tun.start(); + // We also index peers by a tag + let peers_by_tag = Arc::new(tokio::sync::Mutex::new(wg_tunnel::PeersByTag::new())); + // If we want to have the tun device on a separate host, it's the tun_task and // tun_task_response channels that needs to be sent over the network to the host where the tun // device is running. diff --git a/common/wireguard/src/platform/linux/tun_device.rs b/common/wireguard/src/platform/linux/tun_device.rs index 196102394f..638c00ce3f 100644 --- a/common/wireguard/src/platform/linux/tun_device.rs +++ b/common/wireguard/src/platform/linux/tun_device.rs @@ -45,7 +45,7 @@ pub struct TunDevice { routing_mode: RoutingMode, } -enum RoutingMode { +pub enum RoutingMode { // The routing table, as how wireguard does it AllowedIps(AllowedIpsInner), @@ -55,28 +55,29 @@ enum RoutingMode { } impl RoutingMode { - fn new_nat() -> Self { + pub fn new_nat() -> Self { RoutingMode::Nat(NatInner { nat_table: HashMap::new(), }) } - fn new_allowed_ips(peers_by_ip: Arc>) -> Self { + pub fn new_allowed_ips(peers_by_ip: Arc>) -> Self { RoutingMode::AllowedIps(AllowedIpsInner { peers_by_ip }) } } -struct AllowedIpsInner { +pub struct AllowedIpsInner { peers_by_ip: Arc>, } -struct NatInner { +pub struct NatInner { nat_table: HashMap, } impl TunDevice { pub fn new( - peers_by_ip: Option>>, + routing_mode: RoutingMode, + // peers_by_ip: Option>>, ) -> (Self, TunTaskTx, TunTaskResponseRx) { let tun = setup_tokio_tun_device( format!("{TUN_BASE_NAME}%d").as_str(), @@ -89,11 +90,6 @@ impl TunDevice { let (tun_task_tx, tun_task_rx) = tun_task_channel(); let (tun_task_response_tx, tun_task_response_rx) = tun_task_response_channel(); - let routing_mode = match peers_by_ip { - Some(peers_by_ip) => RoutingMode::new_allowed_ips(peers_by_ip), - None => RoutingMode::new_nat(), - }; - let tun_device = TunDevice { tun_task_rx, tun_task_response_tx, diff --git a/service-providers/ip-packet-router/src/lib.rs b/service-providers/ip-packet-router/src/lib.rs index 5ef1ad41a0..2dd483817d 100644 --- a/service-providers/ip-packet-router/src/lib.rs +++ b/service-providers/ip-packet-router/src/lib.rs @@ -116,12 +116,13 @@ impl IpPacketRouterBuilder { let self_address = *mixnet_client.nym_address(); // Create the TUN device that we interact with the rest of the world with - let (tun, tun_task_tx, tun_task_response_rx) = - nym_wireguard::tun_device::TunDevice::new(None); + let (tun, tun_task_tx, tun_task_response_rx) = nym_wireguard::tun_device::TunDevice::new( + nym_wireguard::tun_device::RoutingMode::new_nat(), + ); tun.start(); let ip_packet_router_service = IpPacketRouter { - config: self.config, + _config: self.config, // tun, tun_task_tx, tun_task_response_rx, @@ -144,7 +145,7 @@ impl IpPacketRouterBuilder { } struct IpPacketRouter { - config: Config, + _config: Config, // tun: nym_wireguard::tun_device::TunDevice, tun_task_tx: nym_wireguard::tun_task_channel::TunTaskTx, tun_task_response_rx: nym_wireguard::tun_task_channel::TunTaskResponseRx, From 60b1c1208a2f6eba2fde4fa6023884ce0ef321b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 3 Nov 2023 09:31:17 +0100 Subject: [PATCH 229/236] NYM_CLIENT_ADDR --- service-providers/ip-packet-router/src/lib.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/service-providers/ip-packet-router/src/lib.rs b/service-providers/ip-packet-router/src/lib.rs index 2dd483817d..2abd76c129 100644 --- a/service-providers/ip-packet-router/src/lib.rs +++ b/service-providers/ip-packet-router/src/lib.rs @@ -172,9 +172,15 @@ impl IpPacketRouter { }, packet = self.tun_task_response_rx.recv() => { if let Some((_tag, packet)) = packet { - // TODO: basically we need to map the tag to the recipient - // For now we just hardcode the recipient - let recipient = Recipient::try_from_base58_string("sfl;sdf").unwrap(); + // Read recipient from env variable NYM_CLIENT_ADDR which is a base58 + // string of the nym-address of the client that the packet should be + // sent back to. + let recipient_addr = std::env::var("NYM_CLIENT_ADDR").expect("NYM_CLIENT_ADDR not set"); + let recipient = Recipient::try_from_base58_string(recipient_addr).expect("NYM_CLIENT_ADDR is not a valid nym address"); + + // In the near future we will let the client expose it's nym-address + // directly, and after that, provide SURBS + let lane = TransmissionLane::General; let packet_type = None; let input_message = InputMessage::new_regular(recipient, packet, lane, packet_type); From 462c15887eb65cde1b6be0ca38139002b5a11551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 3 Nov 2023 10:03:05 +0100 Subject: [PATCH 230/236] Fix compilation on non-linux --- service-providers/ip-packet-router/src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/service-providers/ip-packet-router/src/lib.rs b/service-providers/ip-packet-router/src/lib.rs index 2abd76c129..6369e87774 100644 --- a/service-providers/ip-packet-router/src/lib.rs +++ b/service-providers/ip-packet-router/src/lib.rs @@ -33,6 +33,7 @@ impl OnStartData { } pub struct IpPacketRouterBuilder { + #[allow(unused)] config: Config, wait_for_gateway: bool, custom_topology_provider: Option>, @@ -98,6 +99,12 @@ impl IpPacketRouterBuilder { Ok(self) } + #[cfg(not(target_os = "linux"))] + pub async fn run_service_provider(self) -> Result<(), IpPacketRouterError> { + todo!("service provider is not yet supported on this platform") + } + + #[cfg(target_os = "linux")] pub async fn run_service_provider(self) -> Result<(), IpPacketRouterError> { // Used to notify tasks to shutdown. Not all tasks fully supports this (yet). let task_handle: TaskHandle = self.shutdown.map(Into::into).unwrap_or_default(); @@ -144,6 +151,7 @@ impl IpPacketRouterBuilder { } } +#[allow(unused)] struct IpPacketRouter { _config: Config, // tun: nym_wireguard::tun_device::TunDevice, @@ -153,6 +161,7 @@ struct IpPacketRouter { task_handle: TaskHandle, } +#[allow(unused)] impl IpPacketRouter { async fn run(mut self) -> Result<(), IpPacketRouterError> { let mut task_client = self.task_handle.fork("main_loop"); @@ -249,6 +258,7 @@ impl IpPacketRouter { // This is NOT in the SDK since we don't want to expose any of the client-core config types. // We could however consider moving it to a crate in common in the future. // TODO: refactor this function and its arguments +#[allow(unused)] async fn create_mixnet_client( config: &BaseClientConfig, shutdown: TaskClient, From 807e7e588f9fe43880f9ff0fb95f920afb59f2e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 3 Nov 2023 10:49:39 +0100 Subject: [PATCH 231/236] Remove expect on NYM_CLIENT_ADDR --- service-providers/ip-packet-router/src/lib.rs | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/service-providers/ip-packet-router/src/lib.rs b/service-providers/ip-packet-router/src/lib.rs index 6369e87774..4957c2c02d 100644 --- a/service-providers/ip-packet-router/src/lib.rs +++ b/service-providers/ip-packet-router/src/lib.rs @@ -184,23 +184,28 @@ impl IpPacketRouter { // Read recipient from env variable NYM_CLIENT_ADDR which is a base58 // string of the nym-address of the client that the packet should be // sent back to. - let recipient_addr = std::env::var("NYM_CLIENT_ADDR").expect("NYM_CLIENT_ADDR not set"); - let recipient = Recipient::try_from_base58_string(recipient_addr).expect("NYM_CLIENT_ADDR is not a valid nym address"); - + // // In the near future we will let the client expose it's nym-address // directly, and after that, provide SURBS + let recipient = std::env::var("NYM_CLIENT_ADDR").ok().and_then(|addr| { + Recipient::try_from_base58_string(addr).ok() + }); - let lane = TransmissionLane::General; - let packet_type = None; - let input_message = InputMessage::new_regular(recipient, packet, lane, packet_type); + if let Some(recipient) = recipient { + let lane = TransmissionLane::General; + let packet_type = None; + let input_message = InputMessage::new_regular(recipient, packet, lane, packet_type); - self.mixnet_client - .send(input_message) - .await - .tap_err(|err| { - log::error!("IpPacketRouter [main loop]: failed to send packet to mixnet: {err}"); - }) - .ok(); + self.mixnet_client + .send(input_message) + .await + .tap_err(|err| { + log::error!("IpPacketRouter [main loop]: failed to send packet to mixnet: {err}"); + }) + .ok(); + } else { + log::error!("NYM_CLIENT_ADDR not set or invalid"); + } } else { log::trace!("IpPacketRouter [main loop]: stopping since channel closed"); break; From 43bd1ba419bb1048c1a8fb20fe18cdfd385fb30b Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Fri, 3 Nov 2023 10:59:00 +0100 Subject: [PATCH 232/236] updated mdbook admonish assets --- documentation/operators/book.toml | 2 +- documentation/operators/mdbook-admonish.css | 172 +++++++++++--------- 2 files changed, 93 insertions(+), 81 deletions(-) diff --git a/documentation/operators/book.toml b/documentation/operators/book.toml index 56a5b00162..d238a5c745 100644 --- a/documentation/operators/book.toml +++ b/documentation/operators/book.toml @@ -42,7 +42,7 @@ turn-off = true [preprocessor.admonish] command = "mdbook-admonish" -assets_version = "3.0.0" # do not edit: managed by `mdbook-admonish install` +assets_version = "2.0.1" # do not edit: managed by `mdbook-admonish install` # variables preprocessor: import variables into files # https://gitlab.com/tglman/mdbook-variables/ diff --git a/documentation/operators/mdbook-admonish.css b/documentation/operators/mdbook-admonish.css index e0a3365532..244bc9ade7 100644 --- a/documentation/operators/mdbook-admonish.css +++ b/documentation/operators/mdbook-admonish.css @@ -1,18 +1,31 @@ @charset "UTF-8"; :root { - --md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,"); - --md-details-icon: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--note: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--abstract: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--info: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--tip: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--success: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--question: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--warning: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--failure: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--danger: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--bug: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--example: + url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--quote: + url("data:image/svg+xml;charset=utf-8,"); + --md-details-icon: + url("data:image/svg+xml;charset=utf-8,"); } :is(.admonition) { @@ -62,7 +75,7 @@ a.admonition-anchor-link::before { content: "§"; } -:is(.admonition-title, summary.admonition-title) { +:is(.admonition-title, summary) { position: relative; min-height: 4rem; margin-block: 0; @@ -73,13 +86,13 @@ a.admonition-anchor-link::before { background-color: rgba(68, 138, 255, 0.1); display: flex; } -:is(.admonition-title, summary.admonition-title) p { +:is(.admonition-title, summary) p { margin: 0; } -html :is(.admonition-title, summary.admonition-title):last-child { +html :is(.admonition-title, summary):last-child { margin-bottom: 0; } -:is(.admonition-title, summary.admonition-title)::before { +:is(.admonition-title, summary)::before { position: absolute; top: 0.625em; inset-inline-start: 1.6rem; @@ -94,7 +107,7 @@ html :is(.admonition-title, summary.admonition-title):last-child { -webkit-mask-size: contain; content: ""; } -:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link { +:is(.admonition-title, summary):hover a.admonition-anchor-link { display: initial; } @@ -119,204 +132,204 @@ details[open].admonition > summary.admonition-title::after { transform: rotate(90deg); } -:is(.admonition):is(.admonish-note) { +:is(.admonition):is(.note) { border-color: #448aff; } -:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) { +:is(.note) > :is(.admonition-title, summary) { background-color: rgba(68, 138, 255, 0.1); } -:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before { +:is(.note) > :is(.admonition-title, summary)::before { background-color: #448aff; - mask-image: var(--md-admonition-icon--admonish-note); - -webkit-mask-image: var(--md-admonition-icon--admonish-note); + mask-image: var(--md-admonition-icon--note); + -webkit-mask-image: var(--md-admonition-icon--note); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) { +:is(.admonition):is(.abstract, .summary, .tldr) { border-color: #00b0ff; } -:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) { +:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary) { background-color: rgba(0, 176, 255, 0.1); } -:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before { +:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary)::before { background-color: #00b0ff; - mask-image: var(--md-admonition-icon--admonish-abstract); - -webkit-mask-image: var(--md-admonition-icon--admonish-abstract); + mask-image: var(--md-admonition-icon--abstract); + -webkit-mask-image: var(--md-admonition-icon--abstract); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-info, .admonish-todo) { +:is(.admonition):is(.info, .todo) { border-color: #00b8d4; } -:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) { +:is(.info, .todo) > :is(.admonition-title, summary) { background-color: rgba(0, 184, 212, 0.1); } -:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before { +:is(.info, .todo) > :is(.admonition-title, summary)::before { background-color: #00b8d4; - mask-image: var(--md-admonition-icon--admonish-info); - -webkit-mask-image: var(--md-admonition-icon--admonish-info); + mask-image: var(--md-admonition-icon--info); + -webkit-mask-image: var(--md-admonition-icon--info); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) { +:is(.admonition):is(.tip, .hint, .important) { border-color: #00bfa5; } -:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) { +:is(.tip, .hint, .important) > :is(.admonition-title, summary) { background-color: rgba(0, 191, 165, 0.1); } -:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before { +:is(.tip, .hint, .important) > :is(.admonition-title, summary)::before { background-color: #00bfa5; - mask-image: var(--md-admonition-icon--admonish-tip); - -webkit-mask-image: var(--md-admonition-icon--admonish-tip); + mask-image: var(--md-admonition-icon--tip); + -webkit-mask-image: var(--md-admonition-icon--tip); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) { +:is(.admonition):is(.success, .check, .done) { border-color: #00c853; } -:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) { +:is(.success, .check, .done) > :is(.admonition-title, summary) { background-color: rgba(0, 200, 83, 0.1); } -:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before { +:is(.success, .check, .done) > :is(.admonition-title, summary)::before { background-color: #00c853; - mask-image: var(--md-admonition-icon--admonish-success); - -webkit-mask-image: var(--md-admonition-icon--admonish-success); + mask-image: var(--md-admonition-icon--success); + -webkit-mask-image: var(--md-admonition-icon--success); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) { +:is(.admonition):is(.question, .help, .faq) { border-color: #64dd17; } -:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) { +:is(.question, .help, .faq) > :is(.admonition-title, summary) { background-color: rgba(100, 221, 23, 0.1); } -:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before { +:is(.question, .help, .faq) > :is(.admonition-title, summary)::before { background-color: #64dd17; - mask-image: var(--md-admonition-icon--admonish-question); - -webkit-mask-image: var(--md-admonition-icon--admonish-question); + mask-image: var(--md-admonition-icon--question); + -webkit-mask-image: var(--md-admonition-icon--question); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) { +:is(.admonition):is(.warning, .caution, .attention) { border-color: #ff9100; } -:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) { +:is(.warning, .caution, .attention) > :is(.admonition-title, summary) { background-color: rgba(255, 145, 0, 0.1); } -:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before { +:is(.warning, .caution, .attention) > :is(.admonition-title, summary)::before { background-color: #ff9100; - mask-image: var(--md-admonition-icon--admonish-warning); - -webkit-mask-image: var(--md-admonition-icon--admonish-warning); + mask-image: var(--md-admonition-icon--warning); + -webkit-mask-image: var(--md-admonition-icon--warning); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) { +:is(.admonition):is(.failure, .fail, .missing) { border-color: #ff5252; } -:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) { +:is(.failure, .fail, .missing) > :is(.admonition-title, summary) { background-color: rgba(255, 82, 82, 0.1); } -:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before { +:is(.failure, .fail, .missing) > :is(.admonition-title, summary)::before { background-color: #ff5252; - mask-image: var(--md-admonition-icon--admonish-failure); - -webkit-mask-image: var(--md-admonition-icon--admonish-failure); + mask-image: var(--md-admonition-icon--failure); + -webkit-mask-image: var(--md-admonition-icon--failure); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-danger, .admonish-error) { +:is(.admonition):is(.danger, .error) { border-color: #ff1744; } -:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) { +:is(.danger, .error) > :is(.admonition-title, summary) { background-color: rgba(255, 23, 68, 0.1); } -:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before { +:is(.danger, .error) > :is(.admonition-title, summary)::before { background-color: #ff1744; - mask-image: var(--md-admonition-icon--admonish-danger); - -webkit-mask-image: var(--md-admonition-icon--admonish-danger); + mask-image: var(--md-admonition-icon--danger); + -webkit-mask-image: var(--md-admonition-icon--danger); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-bug) { +:is(.admonition):is(.bug) { border-color: #f50057; } -:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) { +:is(.bug) > :is(.admonition-title, summary) { background-color: rgba(245, 0, 87, 0.1); } -:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before { +:is(.bug) > :is(.admonition-title, summary)::before { background-color: #f50057; - mask-image: var(--md-admonition-icon--admonish-bug); - -webkit-mask-image: var(--md-admonition-icon--admonish-bug); + mask-image: var(--md-admonition-icon--bug); + -webkit-mask-image: var(--md-admonition-icon--bug); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-example) { +:is(.admonition):is(.example) { border-color: #7c4dff; } -:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) { +:is(.example) > :is(.admonition-title, summary) { background-color: rgba(124, 77, 255, 0.1); } -:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before { +:is(.example) > :is(.admonition-title, summary)::before { background-color: #7c4dff; - mask-image: var(--md-admonition-icon--admonish-example); - -webkit-mask-image: var(--md-admonition-icon--admonish-example); + mask-image: var(--md-admonition-icon--example); + -webkit-mask-image: var(--md-admonition-icon--example); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.admonish-quote, .admonish-cite) { +:is(.admonition):is(.quote, .cite) { border-color: #9e9e9e; } -:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) { +:is(.quote, .cite) > :is(.admonition-title, summary) { background-color: rgba(158, 158, 158, 0.1); } -:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before { +:is(.quote, .cite) > :is(.admonition-title, summary)::before { background-color: #9e9e9e; - mask-image: var(--md-admonition-icon--admonish-quote); - -webkit-mask-image: var(--md-admonition-icon--admonish-quote); + mask-image: var(--md-admonition-icon--quote); + -webkit-mask-image: var(--md-admonition-icon--quote); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; @@ -327,8 +340,7 @@ details[open].admonition > summary.admonition-title::after { background-color: var(--sidebar-bg); } -.ayu :is(.admonition), -.coal :is(.admonition) { +.ayu :is(.admonition), .coal :is(.admonition) { background-color: var(--theme-hover); } From ba48b71b23f2bade86f41c84c4f7124d2d3a2885 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Fri, 3 Nov 2023 11:29:20 +0100 Subject: [PATCH 233/236] install admonish to all books --- documentation/dev-portal/book.toml | 2 +- documentation/dev-portal/mdbook-admonish.css | 172 +++++++++---------- documentation/docs/book.toml | 2 +- documentation/docs/mdbook-admonish.css | 172 +++++++++---------- documentation/operators/book.toml | 2 +- documentation/operators/mdbook-admonish.css | 172 +++++++++---------- 6 files changed, 243 insertions(+), 279 deletions(-) diff --git a/documentation/dev-portal/book.toml b/documentation/dev-portal/book.toml index 1012ec22f9..d0dfbe0674 100644 --- a/documentation/dev-portal/book.toml +++ b/documentation/dev-portal/book.toml @@ -43,7 +43,7 @@ turn-off = true [preprocessor.admonish] command = "mdbook-admonish" -assets_version = "2.0.1" # do not edit: managed by `mdbook-admonish install` +assets_version = "3.0.0" # do not edit: managed by `mdbook-admonish install` # variables preprocessor: import variables into files # https://gitlab.com/tglman/mdbook-variables/ diff --git a/documentation/dev-portal/mdbook-admonish.css b/documentation/dev-portal/mdbook-admonish.css index 244bc9ade7..e0a3365532 100644 --- a/documentation/dev-portal/mdbook-admonish.css +++ b/documentation/dev-portal/mdbook-admonish.css @@ -1,31 +1,18 @@ @charset "UTF-8"; :root { - --md-admonition-icon--note: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--abstract: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--info: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--tip: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--success: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--question: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--warning: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--failure: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--danger: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--bug: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--example: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--quote: - url("data:image/svg+xml;charset=utf-8,"); - --md-details-icon: - url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,"); + --md-details-icon: url("data:image/svg+xml;charset=utf-8,"); } :is(.admonition) { @@ -75,7 +62,7 @@ a.admonition-anchor-link::before { content: "§"; } -:is(.admonition-title, summary) { +:is(.admonition-title, summary.admonition-title) { position: relative; min-height: 4rem; margin-block: 0; @@ -86,13 +73,13 @@ a.admonition-anchor-link::before { background-color: rgba(68, 138, 255, 0.1); display: flex; } -:is(.admonition-title, summary) p { +:is(.admonition-title, summary.admonition-title) p { margin: 0; } -html :is(.admonition-title, summary):last-child { +html :is(.admonition-title, summary.admonition-title):last-child { margin-bottom: 0; } -:is(.admonition-title, summary)::before { +:is(.admonition-title, summary.admonition-title)::before { position: absolute; top: 0.625em; inset-inline-start: 1.6rem; @@ -107,7 +94,7 @@ html :is(.admonition-title, summary):last-child { -webkit-mask-size: contain; content: ""; } -:is(.admonition-title, summary):hover a.admonition-anchor-link { +:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link { display: initial; } @@ -132,204 +119,204 @@ details[open].admonition > summary.admonition-title::after { transform: rotate(90deg); } -:is(.admonition):is(.note) { +:is(.admonition):is(.admonish-note) { border-color: #448aff; } -:is(.note) > :is(.admonition-title, summary) { +:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(68, 138, 255, 0.1); } -:is(.note) > :is(.admonition-title, summary)::before { +:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before { background-color: #448aff; - mask-image: var(--md-admonition-icon--note); - -webkit-mask-image: var(--md-admonition-icon--note); + mask-image: var(--md-admonition-icon--admonish-note); + -webkit-mask-image: var(--md-admonition-icon--admonish-note); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.abstract, .summary, .tldr) { +:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) { border-color: #00b0ff; } -:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary) { +:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(0, 176, 255, 0.1); } -:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary)::before { +:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before { background-color: #00b0ff; - mask-image: var(--md-admonition-icon--abstract); - -webkit-mask-image: var(--md-admonition-icon--abstract); + mask-image: var(--md-admonition-icon--admonish-abstract); + -webkit-mask-image: var(--md-admonition-icon--admonish-abstract); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.info, .todo) { +:is(.admonition):is(.admonish-info, .admonish-todo) { border-color: #00b8d4; } -:is(.info, .todo) > :is(.admonition-title, summary) { +:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(0, 184, 212, 0.1); } -:is(.info, .todo) > :is(.admonition-title, summary)::before { +:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before { background-color: #00b8d4; - mask-image: var(--md-admonition-icon--info); - -webkit-mask-image: var(--md-admonition-icon--info); + mask-image: var(--md-admonition-icon--admonish-info); + -webkit-mask-image: var(--md-admonition-icon--admonish-info); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.tip, .hint, .important) { +:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) { border-color: #00bfa5; } -:is(.tip, .hint, .important) > :is(.admonition-title, summary) { +:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(0, 191, 165, 0.1); } -:is(.tip, .hint, .important) > :is(.admonition-title, summary)::before { +:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before { background-color: #00bfa5; - mask-image: var(--md-admonition-icon--tip); - -webkit-mask-image: var(--md-admonition-icon--tip); + mask-image: var(--md-admonition-icon--admonish-tip); + -webkit-mask-image: var(--md-admonition-icon--admonish-tip); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.success, .check, .done) { +:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) { border-color: #00c853; } -:is(.success, .check, .done) > :is(.admonition-title, summary) { +:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(0, 200, 83, 0.1); } -:is(.success, .check, .done) > :is(.admonition-title, summary)::before { +:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before { background-color: #00c853; - mask-image: var(--md-admonition-icon--success); - -webkit-mask-image: var(--md-admonition-icon--success); + mask-image: var(--md-admonition-icon--admonish-success); + -webkit-mask-image: var(--md-admonition-icon--admonish-success); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.question, .help, .faq) { +:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) { border-color: #64dd17; } -:is(.question, .help, .faq) > :is(.admonition-title, summary) { +:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(100, 221, 23, 0.1); } -:is(.question, .help, .faq) > :is(.admonition-title, summary)::before { +:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before { background-color: #64dd17; - mask-image: var(--md-admonition-icon--question); - -webkit-mask-image: var(--md-admonition-icon--question); + mask-image: var(--md-admonition-icon--admonish-question); + -webkit-mask-image: var(--md-admonition-icon--admonish-question); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.warning, .caution, .attention) { +:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) { border-color: #ff9100; } -:is(.warning, .caution, .attention) > :is(.admonition-title, summary) { +:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(255, 145, 0, 0.1); } -:is(.warning, .caution, .attention) > :is(.admonition-title, summary)::before { +:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before { background-color: #ff9100; - mask-image: var(--md-admonition-icon--warning); - -webkit-mask-image: var(--md-admonition-icon--warning); + mask-image: var(--md-admonition-icon--admonish-warning); + -webkit-mask-image: var(--md-admonition-icon--admonish-warning); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.failure, .fail, .missing) { +:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) { border-color: #ff5252; } -:is(.failure, .fail, .missing) > :is(.admonition-title, summary) { +:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(255, 82, 82, 0.1); } -:is(.failure, .fail, .missing) > :is(.admonition-title, summary)::before { +:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before { background-color: #ff5252; - mask-image: var(--md-admonition-icon--failure); - -webkit-mask-image: var(--md-admonition-icon--failure); + mask-image: var(--md-admonition-icon--admonish-failure); + -webkit-mask-image: var(--md-admonition-icon--admonish-failure); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.danger, .error) { +:is(.admonition):is(.admonish-danger, .admonish-error) { border-color: #ff1744; } -:is(.danger, .error) > :is(.admonition-title, summary) { +:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(255, 23, 68, 0.1); } -:is(.danger, .error) > :is(.admonition-title, summary)::before { +:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before { background-color: #ff1744; - mask-image: var(--md-admonition-icon--danger); - -webkit-mask-image: var(--md-admonition-icon--danger); + mask-image: var(--md-admonition-icon--admonish-danger); + -webkit-mask-image: var(--md-admonition-icon--admonish-danger); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.bug) { +:is(.admonition):is(.admonish-bug) { border-color: #f50057; } -:is(.bug) > :is(.admonition-title, summary) { +:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(245, 0, 87, 0.1); } -:is(.bug) > :is(.admonition-title, summary)::before { +:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before { background-color: #f50057; - mask-image: var(--md-admonition-icon--bug); - -webkit-mask-image: var(--md-admonition-icon--bug); + mask-image: var(--md-admonition-icon--admonish-bug); + -webkit-mask-image: var(--md-admonition-icon--admonish-bug); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.example) { +:is(.admonition):is(.admonish-example) { border-color: #7c4dff; } -:is(.example) > :is(.admonition-title, summary) { +:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(124, 77, 255, 0.1); } -:is(.example) > :is(.admonition-title, summary)::before { +:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before { background-color: #7c4dff; - mask-image: var(--md-admonition-icon--example); - -webkit-mask-image: var(--md-admonition-icon--example); + mask-image: var(--md-admonition-icon--admonish-example); + -webkit-mask-image: var(--md-admonition-icon--admonish-example); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.quote, .cite) { +:is(.admonition):is(.admonish-quote, .admonish-cite) { border-color: #9e9e9e; } -:is(.quote, .cite) > :is(.admonition-title, summary) { +:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(158, 158, 158, 0.1); } -:is(.quote, .cite) > :is(.admonition-title, summary)::before { +:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before { background-color: #9e9e9e; - mask-image: var(--md-admonition-icon--quote); - -webkit-mask-image: var(--md-admonition-icon--quote); + mask-image: var(--md-admonition-icon--admonish-quote); + -webkit-mask-image: var(--md-admonition-icon--admonish-quote); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; @@ -340,7 +327,8 @@ details[open].admonition > summary.admonition-title::after { background-color: var(--sidebar-bg); } -.ayu :is(.admonition), .coal :is(.admonition) { +.ayu :is(.admonition), +.coal :is(.admonition) { background-color: var(--theme-hover); } diff --git a/documentation/docs/book.toml b/documentation/docs/book.toml index a11f82cbbd..d87f16e8f9 100644 --- a/documentation/docs/book.toml +++ b/documentation/docs/book.toml @@ -45,7 +45,7 @@ turn-off = true [preprocessor.admonish] command = "mdbook-admonish" -assets_version = "2.0.1" # do not edit: managed by `mdbook-admonish install` +assets_version = "3.0.0" # do not edit: managed by `mdbook-admonish install` # variables preprocessor: import variables into files # https://gitlab.com/tglman/mdbook-variables/ diff --git a/documentation/docs/mdbook-admonish.css b/documentation/docs/mdbook-admonish.css index 244bc9ade7..e0a3365532 100644 --- a/documentation/docs/mdbook-admonish.css +++ b/documentation/docs/mdbook-admonish.css @@ -1,31 +1,18 @@ @charset "UTF-8"; :root { - --md-admonition-icon--note: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--abstract: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--info: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--tip: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--success: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--question: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--warning: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--failure: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--danger: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--bug: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--example: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--quote: - url("data:image/svg+xml;charset=utf-8,"); - --md-details-icon: - url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,"); + --md-details-icon: url("data:image/svg+xml;charset=utf-8,"); } :is(.admonition) { @@ -75,7 +62,7 @@ a.admonition-anchor-link::before { content: "§"; } -:is(.admonition-title, summary) { +:is(.admonition-title, summary.admonition-title) { position: relative; min-height: 4rem; margin-block: 0; @@ -86,13 +73,13 @@ a.admonition-anchor-link::before { background-color: rgba(68, 138, 255, 0.1); display: flex; } -:is(.admonition-title, summary) p { +:is(.admonition-title, summary.admonition-title) p { margin: 0; } -html :is(.admonition-title, summary):last-child { +html :is(.admonition-title, summary.admonition-title):last-child { margin-bottom: 0; } -:is(.admonition-title, summary)::before { +:is(.admonition-title, summary.admonition-title)::before { position: absolute; top: 0.625em; inset-inline-start: 1.6rem; @@ -107,7 +94,7 @@ html :is(.admonition-title, summary):last-child { -webkit-mask-size: contain; content: ""; } -:is(.admonition-title, summary):hover a.admonition-anchor-link { +:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link { display: initial; } @@ -132,204 +119,204 @@ details[open].admonition > summary.admonition-title::after { transform: rotate(90deg); } -:is(.admonition):is(.note) { +:is(.admonition):is(.admonish-note) { border-color: #448aff; } -:is(.note) > :is(.admonition-title, summary) { +:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(68, 138, 255, 0.1); } -:is(.note) > :is(.admonition-title, summary)::before { +:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before { background-color: #448aff; - mask-image: var(--md-admonition-icon--note); - -webkit-mask-image: var(--md-admonition-icon--note); + mask-image: var(--md-admonition-icon--admonish-note); + -webkit-mask-image: var(--md-admonition-icon--admonish-note); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.abstract, .summary, .tldr) { +:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) { border-color: #00b0ff; } -:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary) { +:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(0, 176, 255, 0.1); } -:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary)::before { +:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before { background-color: #00b0ff; - mask-image: var(--md-admonition-icon--abstract); - -webkit-mask-image: var(--md-admonition-icon--abstract); + mask-image: var(--md-admonition-icon--admonish-abstract); + -webkit-mask-image: var(--md-admonition-icon--admonish-abstract); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.info, .todo) { +:is(.admonition):is(.admonish-info, .admonish-todo) { border-color: #00b8d4; } -:is(.info, .todo) > :is(.admonition-title, summary) { +:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(0, 184, 212, 0.1); } -:is(.info, .todo) > :is(.admonition-title, summary)::before { +:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before { background-color: #00b8d4; - mask-image: var(--md-admonition-icon--info); - -webkit-mask-image: var(--md-admonition-icon--info); + mask-image: var(--md-admonition-icon--admonish-info); + -webkit-mask-image: var(--md-admonition-icon--admonish-info); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.tip, .hint, .important) { +:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) { border-color: #00bfa5; } -:is(.tip, .hint, .important) > :is(.admonition-title, summary) { +:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(0, 191, 165, 0.1); } -:is(.tip, .hint, .important) > :is(.admonition-title, summary)::before { +:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before { background-color: #00bfa5; - mask-image: var(--md-admonition-icon--tip); - -webkit-mask-image: var(--md-admonition-icon--tip); + mask-image: var(--md-admonition-icon--admonish-tip); + -webkit-mask-image: var(--md-admonition-icon--admonish-tip); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.success, .check, .done) { +:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) { border-color: #00c853; } -:is(.success, .check, .done) > :is(.admonition-title, summary) { +:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(0, 200, 83, 0.1); } -:is(.success, .check, .done) > :is(.admonition-title, summary)::before { +:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before { background-color: #00c853; - mask-image: var(--md-admonition-icon--success); - -webkit-mask-image: var(--md-admonition-icon--success); + mask-image: var(--md-admonition-icon--admonish-success); + -webkit-mask-image: var(--md-admonition-icon--admonish-success); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.question, .help, .faq) { +:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) { border-color: #64dd17; } -:is(.question, .help, .faq) > :is(.admonition-title, summary) { +:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(100, 221, 23, 0.1); } -:is(.question, .help, .faq) > :is(.admonition-title, summary)::before { +:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before { background-color: #64dd17; - mask-image: var(--md-admonition-icon--question); - -webkit-mask-image: var(--md-admonition-icon--question); + mask-image: var(--md-admonition-icon--admonish-question); + -webkit-mask-image: var(--md-admonition-icon--admonish-question); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.warning, .caution, .attention) { +:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) { border-color: #ff9100; } -:is(.warning, .caution, .attention) > :is(.admonition-title, summary) { +:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(255, 145, 0, 0.1); } -:is(.warning, .caution, .attention) > :is(.admonition-title, summary)::before { +:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before { background-color: #ff9100; - mask-image: var(--md-admonition-icon--warning); - -webkit-mask-image: var(--md-admonition-icon--warning); + mask-image: var(--md-admonition-icon--admonish-warning); + -webkit-mask-image: var(--md-admonition-icon--admonish-warning); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.failure, .fail, .missing) { +:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) { border-color: #ff5252; } -:is(.failure, .fail, .missing) > :is(.admonition-title, summary) { +:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(255, 82, 82, 0.1); } -:is(.failure, .fail, .missing) > :is(.admonition-title, summary)::before { +:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before { background-color: #ff5252; - mask-image: var(--md-admonition-icon--failure); - -webkit-mask-image: var(--md-admonition-icon--failure); + mask-image: var(--md-admonition-icon--admonish-failure); + -webkit-mask-image: var(--md-admonition-icon--admonish-failure); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.danger, .error) { +:is(.admonition):is(.admonish-danger, .admonish-error) { border-color: #ff1744; } -:is(.danger, .error) > :is(.admonition-title, summary) { +:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(255, 23, 68, 0.1); } -:is(.danger, .error) > :is(.admonition-title, summary)::before { +:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before { background-color: #ff1744; - mask-image: var(--md-admonition-icon--danger); - -webkit-mask-image: var(--md-admonition-icon--danger); + mask-image: var(--md-admonition-icon--admonish-danger); + -webkit-mask-image: var(--md-admonition-icon--admonish-danger); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.bug) { +:is(.admonition):is(.admonish-bug) { border-color: #f50057; } -:is(.bug) > :is(.admonition-title, summary) { +:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(245, 0, 87, 0.1); } -:is(.bug) > :is(.admonition-title, summary)::before { +:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before { background-color: #f50057; - mask-image: var(--md-admonition-icon--bug); - -webkit-mask-image: var(--md-admonition-icon--bug); + mask-image: var(--md-admonition-icon--admonish-bug); + -webkit-mask-image: var(--md-admonition-icon--admonish-bug); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.example) { +:is(.admonition):is(.admonish-example) { border-color: #7c4dff; } -:is(.example) > :is(.admonition-title, summary) { +:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(124, 77, 255, 0.1); } -:is(.example) > :is(.admonition-title, summary)::before { +:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before { background-color: #7c4dff; - mask-image: var(--md-admonition-icon--example); - -webkit-mask-image: var(--md-admonition-icon--example); + mask-image: var(--md-admonition-icon--admonish-example); + -webkit-mask-image: var(--md-admonition-icon--admonish-example); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.quote, .cite) { +:is(.admonition):is(.admonish-quote, .admonish-cite) { border-color: #9e9e9e; } -:is(.quote, .cite) > :is(.admonition-title, summary) { +:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(158, 158, 158, 0.1); } -:is(.quote, .cite) > :is(.admonition-title, summary)::before { +:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before { background-color: #9e9e9e; - mask-image: var(--md-admonition-icon--quote); - -webkit-mask-image: var(--md-admonition-icon--quote); + mask-image: var(--md-admonition-icon--admonish-quote); + -webkit-mask-image: var(--md-admonition-icon--admonish-quote); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; @@ -340,7 +327,8 @@ details[open].admonition > summary.admonition-title::after { background-color: var(--sidebar-bg); } -.ayu :is(.admonition), .coal :is(.admonition) { +.ayu :is(.admonition), +.coal :is(.admonition) { background-color: var(--theme-hover); } diff --git a/documentation/operators/book.toml b/documentation/operators/book.toml index d238a5c745..56a5b00162 100644 --- a/documentation/operators/book.toml +++ b/documentation/operators/book.toml @@ -42,7 +42,7 @@ turn-off = true [preprocessor.admonish] command = "mdbook-admonish" -assets_version = "2.0.1" # do not edit: managed by `mdbook-admonish install` +assets_version = "3.0.0" # do not edit: managed by `mdbook-admonish install` # variables preprocessor: import variables into files # https://gitlab.com/tglman/mdbook-variables/ diff --git a/documentation/operators/mdbook-admonish.css b/documentation/operators/mdbook-admonish.css index 244bc9ade7..e0a3365532 100644 --- a/documentation/operators/mdbook-admonish.css +++ b/documentation/operators/mdbook-admonish.css @@ -1,31 +1,18 @@ @charset "UTF-8"; :root { - --md-admonition-icon--note: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--abstract: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--info: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--tip: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--success: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--question: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--warning: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--failure: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--danger: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--bug: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--example: - url("data:image/svg+xml;charset=utf-8,"); - --md-admonition-icon--quote: - url("data:image/svg+xml;charset=utf-8,"); - --md-details-icon: - url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,"); + --md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,"); + --md-details-icon: url("data:image/svg+xml;charset=utf-8,"); } :is(.admonition) { @@ -75,7 +62,7 @@ a.admonition-anchor-link::before { content: "§"; } -:is(.admonition-title, summary) { +:is(.admonition-title, summary.admonition-title) { position: relative; min-height: 4rem; margin-block: 0; @@ -86,13 +73,13 @@ a.admonition-anchor-link::before { background-color: rgba(68, 138, 255, 0.1); display: flex; } -:is(.admonition-title, summary) p { +:is(.admonition-title, summary.admonition-title) p { margin: 0; } -html :is(.admonition-title, summary):last-child { +html :is(.admonition-title, summary.admonition-title):last-child { margin-bottom: 0; } -:is(.admonition-title, summary)::before { +:is(.admonition-title, summary.admonition-title)::before { position: absolute; top: 0.625em; inset-inline-start: 1.6rem; @@ -107,7 +94,7 @@ html :is(.admonition-title, summary):last-child { -webkit-mask-size: contain; content: ""; } -:is(.admonition-title, summary):hover a.admonition-anchor-link { +:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link { display: initial; } @@ -132,204 +119,204 @@ details[open].admonition > summary.admonition-title::after { transform: rotate(90deg); } -:is(.admonition):is(.note) { +:is(.admonition):is(.admonish-note) { border-color: #448aff; } -:is(.note) > :is(.admonition-title, summary) { +:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(68, 138, 255, 0.1); } -:is(.note) > :is(.admonition-title, summary)::before { +:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before { background-color: #448aff; - mask-image: var(--md-admonition-icon--note); - -webkit-mask-image: var(--md-admonition-icon--note); + mask-image: var(--md-admonition-icon--admonish-note); + -webkit-mask-image: var(--md-admonition-icon--admonish-note); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.abstract, .summary, .tldr) { +:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) { border-color: #00b0ff; } -:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary) { +:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(0, 176, 255, 0.1); } -:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary)::before { +:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before { background-color: #00b0ff; - mask-image: var(--md-admonition-icon--abstract); - -webkit-mask-image: var(--md-admonition-icon--abstract); + mask-image: var(--md-admonition-icon--admonish-abstract); + -webkit-mask-image: var(--md-admonition-icon--admonish-abstract); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.info, .todo) { +:is(.admonition):is(.admonish-info, .admonish-todo) { border-color: #00b8d4; } -:is(.info, .todo) > :is(.admonition-title, summary) { +:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(0, 184, 212, 0.1); } -:is(.info, .todo) > :is(.admonition-title, summary)::before { +:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before { background-color: #00b8d4; - mask-image: var(--md-admonition-icon--info); - -webkit-mask-image: var(--md-admonition-icon--info); + mask-image: var(--md-admonition-icon--admonish-info); + -webkit-mask-image: var(--md-admonition-icon--admonish-info); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.tip, .hint, .important) { +:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) { border-color: #00bfa5; } -:is(.tip, .hint, .important) > :is(.admonition-title, summary) { +:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(0, 191, 165, 0.1); } -:is(.tip, .hint, .important) > :is(.admonition-title, summary)::before { +:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before { background-color: #00bfa5; - mask-image: var(--md-admonition-icon--tip); - -webkit-mask-image: var(--md-admonition-icon--tip); + mask-image: var(--md-admonition-icon--admonish-tip); + -webkit-mask-image: var(--md-admonition-icon--admonish-tip); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.success, .check, .done) { +:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) { border-color: #00c853; } -:is(.success, .check, .done) > :is(.admonition-title, summary) { +:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(0, 200, 83, 0.1); } -:is(.success, .check, .done) > :is(.admonition-title, summary)::before { +:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before { background-color: #00c853; - mask-image: var(--md-admonition-icon--success); - -webkit-mask-image: var(--md-admonition-icon--success); + mask-image: var(--md-admonition-icon--admonish-success); + -webkit-mask-image: var(--md-admonition-icon--admonish-success); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.question, .help, .faq) { +:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) { border-color: #64dd17; } -:is(.question, .help, .faq) > :is(.admonition-title, summary) { +:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(100, 221, 23, 0.1); } -:is(.question, .help, .faq) > :is(.admonition-title, summary)::before { +:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before { background-color: #64dd17; - mask-image: var(--md-admonition-icon--question); - -webkit-mask-image: var(--md-admonition-icon--question); + mask-image: var(--md-admonition-icon--admonish-question); + -webkit-mask-image: var(--md-admonition-icon--admonish-question); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.warning, .caution, .attention) { +:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) { border-color: #ff9100; } -:is(.warning, .caution, .attention) > :is(.admonition-title, summary) { +:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(255, 145, 0, 0.1); } -:is(.warning, .caution, .attention) > :is(.admonition-title, summary)::before { +:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before { background-color: #ff9100; - mask-image: var(--md-admonition-icon--warning); - -webkit-mask-image: var(--md-admonition-icon--warning); + mask-image: var(--md-admonition-icon--admonish-warning); + -webkit-mask-image: var(--md-admonition-icon--admonish-warning); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.failure, .fail, .missing) { +:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) { border-color: #ff5252; } -:is(.failure, .fail, .missing) > :is(.admonition-title, summary) { +:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(255, 82, 82, 0.1); } -:is(.failure, .fail, .missing) > :is(.admonition-title, summary)::before { +:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before { background-color: #ff5252; - mask-image: var(--md-admonition-icon--failure); - -webkit-mask-image: var(--md-admonition-icon--failure); + mask-image: var(--md-admonition-icon--admonish-failure); + -webkit-mask-image: var(--md-admonition-icon--admonish-failure); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.danger, .error) { +:is(.admonition):is(.admonish-danger, .admonish-error) { border-color: #ff1744; } -:is(.danger, .error) > :is(.admonition-title, summary) { +:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(255, 23, 68, 0.1); } -:is(.danger, .error) > :is(.admonition-title, summary)::before { +:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before { background-color: #ff1744; - mask-image: var(--md-admonition-icon--danger); - -webkit-mask-image: var(--md-admonition-icon--danger); + mask-image: var(--md-admonition-icon--admonish-danger); + -webkit-mask-image: var(--md-admonition-icon--admonish-danger); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.bug) { +:is(.admonition):is(.admonish-bug) { border-color: #f50057; } -:is(.bug) > :is(.admonition-title, summary) { +:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(245, 0, 87, 0.1); } -:is(.bug) > :is(.admonition-title, summary)::before { +:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before { background-color: #f50057; - mask-image: var(--md-admonition-icon--bug); - -webkit-mask-image: var(--md-admonition-icon--bug); + mask-image: var(--md-admonition-icon--admonish-bug); + -webkit-mask-image: var(--md-admonition-icon--admonish-bug); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.example) { +:is(.admonition):is(.admonish-example) { border-color: #7c4dff; } -:is(.example) > :is(.admonition-title, summary) { +:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(124, 77, 255, 0.1); } -:is(.example) > :is(.admonition-title, summary)::before { +:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before { background-color: #7c4dff; - mask-image: var(--md-admonition-icon--example); - -webkit-mask-image: var(--md-admonition-icon--example); + mask-image: var(--md-admonition-icon--admonish-example); + -webkit-mask-image: var(--md-admonition-icon--admonish-example); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; -webkit-mask-repeat: no-repeat; } -:is(.admonition):is(.quote, .cite) { +:is(.admonition):is(.admonish-quote, .admonish-cite) { border-color: #9e9e9e; } -:is(.quote, .cite) > :is(.admonition-title, summary) { +:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) { background-color: rgba(158, 158, 158, 0.1); } -:is(.quote, .cite) > :is(.admonition-title, summary)::before { +:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before { background-color: #9e9e9e; - mask-image: var(--md-admonition-icon--quote); - -webkit-mask-image: var(--md-admonition-icon--quote); + mask-image: var(--md-admonition-icon--admonish-quote); + -webkit-mask-image: var(--md-admonition-icon--admonish-quote); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-size: contain; @@ -340,7 +327,8 @@ details[open].admonition > summary.admonition-title::after { background-color: var(--sidebar-bg); } -.ayu :is(.admonition), .coal :is(.admonition) { +.ayu :is(.admonition), +.coal :is(.admonition) { background-color: var(--theme-hover); } From 02459f5d53a333b76ac73109861e758e906e68b6 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Mon, 6 Nov 2023 12:51:37 +0100 Subject: [PATCH 234/236] added links + typo fixes --- .../community-resources/community-applications-and-guides.md | 4 +--- documentation/dev-portal/src/examples/browser-only.md | 4 ++-- documentation/dev-portal/src/examples/custom-services.md | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/documentation/dev-portal/src/community-resources/community-applications-and-guides.md b/documentation/dev-portal/src/community-resources/community-applications-and-guides.md index 5186dceae1..85a842342d 100644 --- a/documentation/dev-portal/src/community-resources/community-applications-and-guides.md +++ b/documentation/dev-portal/src/community-resources/community-applications-and-guides.md @@ -1,8 +1,6 @@ # Community Applications -We love seeing our developer community create applications using Nym. If you would like to share your application with the community, please submit a pull request to the `main` branch of the `nymtech/dev-portal` [repository](https://github.com/nymtech/dev-portal). - - +If you would like to share your application here, please submit a pull request to the `main` branch of the `nymtech/dev-portal` [repository](https://github.com/nymtech/dev-portal). ## Pastenym diff --git a/documentation/dev-portal/src/examples/browser-only.md b/documentation/dev-portal/src/examples/browser-only.md index 9ee22ef1d8..e9f8a74a06 100644 --- a/documentation/dev-portal/src/examples/browser-only.md +++ b/documentation/dev-portal/src/examples/browser-only.md @@ -1,9 +1,9 @@ # Browser only With the Typescript SDK you can run a Nym client in a webworker - meaning you can connect to the mixnet through the browser without having to worry about any other code than your web framework. -- NoTrustVerify have set up an example application using [`mixFetch`](https://sdk.nymtech.net/examples/mix-fetch) to fetch crypto prices from CoinGecko over the mixnet. +- [NoTrustVerify](https://notrustverify.ch/) have set up an example application using [`mixFetch`](https://sdk.nymtech.net/examples/mix-fetch) to fetch crypto prices from CoinGecko over the mixnet. - [Website](https://notrustverify.github.io/mixfetch-examples/) - - [Coinbase](https://github.com/notrustverify/mixfetch-examples) + - [Codebase](https://github.com/notrustverify/mixfetch-examples) - There is a coconut-scheme based Credential Library playground [here](https://coco-demo.nymtech.net/). This is a WASM implementation of our Coconut libraries which generate raw Coconut credentials. Test it to create and re-randomize your own credentials. For more information on what is happening here check out the [Coconut docs](https://nymtech.net/docs/coconut.html). diff --git a/documentation/dev-portal/src/examples/custom-services.md b/documentation/dev-portal/src/examples/custom-services.md index ce8262bb36..4602ffa7f0 100644 --- a/documentation/dev-portal/src/examples/custom-services.md +++ b/documentation/dev-portal/src/examples/custom-services.md @@ -5,7 +5,7 @@ Custom services involve two pieces of code that communicate via the mixnet: a cl - [Frontend codebase](https://github.com/notrustverify/pastenym) - [Backend codebase](https://github.com/notrustverify/pastenym-frontend) -- Nostr-Nym is another application written by NoTrustVerify, standing between mixnet users and a Nostr server in order to protect their metadata from being revealed when gossiping. **Useful for Go and Python developers**. +- Nostr-Nym is another application written by [NoTrustVerify](https://notrustverify.ch/), standing between mixnet users and a Nostr server in order to protect their metadata from being revealed when gossiping. **Useful for Go and Python developers**. - [Codebase](https://github.com/notrustverify/nostr-nym) - Spook and Nym-Ethtx are both examples of Ethereum transaction broadcasters utilising the mixnet, written in Rust. Since they were written before the release of the Rust SDK, they utilise standalone clients to communicate with the mixnet. From 66f012c70eb80149d425331b14e0171f998ed4c9 Mon Sep 17 00:00:00 2001 From: serinko <97586125+serinko@users.noreply.github.com> Date: Mon, 6 Nov 2023 16:18:13 +0100 Subject: [PATCH 235/236] add exit policy to existing NR --- .../operators/src/nodes/gateway-setup.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 62ea6dbe65..93ca3e7735 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -57,7 +57,7 @@ Before you start an Exit Gateway, read our [Operators Legal Forum](../legal/exit ``` ```admonish info -There has been an ongoing development with dynamic upgrades. Follow the status of the Project Smoosh [changes](../faq/smoosh-faq.md#what-are-the-changes) and the progression state of Exit policy [implementation](../faq/smoosh-faq.html#how-will-the-exit-policy-be-implemented) to be up to date with the current design. +There has been an ongoing development with dynamic upgrades. Follow the status of the Project Smoosh [changes](../faq/smoosh-faq.md#what-are-the-changes) and the progression state of exit policy [implementation](../faq/smoosh-faq.html#how-will-the-exit-policy-be-implemented) to be up to date with the current design. ``` ### Initialising Exit Gateway @@ -126,11 +126,23 @@ enabled = true Save, exit and restart your gateway. Now you are an operator of post-smooshed Exit gateway. -All information about network requester part of your exit gateway is in `/home/user/.nym/gateways//config/network_requester_config.toml`. +#### Enable Nym exit policy to an existing Gateway with Network requester functionality + +In case you already added Network Requester functionality to your Gateway as described above but haven't enabled the [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) there is an easy tweak to do so and turn your node into [Nym Exit Gateway](../faq/smoosh-faq.md#what-are-the-changes). + +Open the config file stored at `.nym/gateways//config/network_requester_config.tom` and set: +```sh +use_deprecated_allow_list = false +``` +Save, exit and restart your gateway. Now you are an operator of post-smooshed Exit gateway. + +```admonish info +All information about network requester part of your Exit Gateway is in `/home/user/.nym/gateways//config/network_requester_config.toml`. +``` For now you can run Gateway without Network requester or with and without the new exit policy. This will soon change as we inform in our [Project Smoosh FAQ](../faq/smoosh-faq.html#how-will-the-exit-policy-be-implemented). -To read more about the configuration like whitelisted outbound requesters in `allowed.list` and other useful information, see the page [*Network Requester Whitelist*](network-requester-setup.md#using-your-network-requester). +To read more about the configuration like whitelisted outbound requesters in `allowed.list` and other useful information, see the page [*Network requester whitelist*](network-requester-setup.md#using-your-network-requester). #### Initialising Gateway without Network requester From 268588daac9fb80b19cb7fa32f963e68e2a26828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 6 Nov 2023 19:05:11 +0000 Subject: [PATCH 236/236] Feature/tls mixnet client (#4103) * adjusting ts mixnet client constructor * added forceTls argument to 'ClientOptsSimple' * more sdk types removed * fixed import * removed go debug code * printing wasm blob version on load * version bump * temporarily removed 'nym/nym/wasm/full-nym-wasm' * changed workspaces definition * correctly setting initial rc.0 suffix * updated crate versions * reverted 'useWorkspaces' lerna option * Fix up dependency versions * Add dev mode toggle to SDK publish scripts * Show location of WASM package * Change dev mode and CI build order * Bump package versions in SDK docs * Remove two versions of `mix-fetch` from SDK docs and only use `-full-fat` version * Remove old arguments for mixFetch and rename to bust cache * Remove `nym-wasm-sdk` from linting * Release v1.2.3 of Typescript SDK * Force WSS on mixnet client * Bump TS SDK to 1.2.4-rc.0 * Clean up lock file * Update node-tester version to 1.2.3 in nym-wallet --------- Co-authored-by: Mark Sinclair --- Cargo.lock | 19 +- Cargo.toml | 2 +- Makefile | 4 +- nym-browser-extension/storage/Cargo.toml | 2 +- nym-wallet/package.json | 29 +- package.json | 9 +- .../codegen/contract-clients/package.json | 4 +- .../{mixfetch.tsx => mix-fetch.tsx} | 15 +- sdk/typescript/docs/components/traffic.tsx | 1 + sdk/typescript/docs/package.json | 11 +- sdk/typescript/docs/pages/examples/mixnet.mdx | 1 + .../docs/pages/playground/mixfetch.mdx | 2 +- .../examples/chat-app/parcel/package.json | 4 +- .../examples/chat-app/plain-html/package.json | 4 +- .../package.json | 4 +- .../examples/chrome-extension/package.json | 4 +- .../examples/firefox-extension/package.json | 4 +- .../examples/mix-fetch/browser/package.json | 4 +- .../examples/node-tester/parcel/package.json | 4 +- .../node-tester/plain-html/package.json | 4 +- .../examples/node-tester/react/package.json | 4 +- .../packages/mix-fetch-node/package.json | 4 +- .../mix-fetch/internal-dev/package.json | 4 +- .../internal-dev/parcel/package.json | 4 +- .../packages/mix-fetch/package.json | 5 +- .../scripts/showDependencyLocation.cjs | 8 + .../packages/node-tester/package.json | 4 +- .../packages/nodejs-client/package.json | 4 +- .../packages/nodejs-client/src/types.ts | 36 +- .../packages/nodejs-client/src/worker.ts | 55 +- .../packages/sdk-react/package.json | 4 +- sdk/typescript/packages/sdk/package.json | 5 +- .../sdk/scripts/showDependencyLocation.cjs | 8 + .../packages/sdk/src/mixnet/wasm/types.ts | 36 +- .../packages/sdk/src/mixnet/wasm/worker.ts | 48 +- sdk/typescript/scripts/build-prod-sdk.sh | 7 + sdk/typescript/scripts/dev-mode-add.mjs | 2 +- sdk/typescript/scripts/dev-mode-remove.mjs | 2 +- .../internal/sdk-version-bump/src/helpers.rs | 7 +- tools/internal/sdk-version-bump/src/main.rs | 12 +- tools/nymvisor/src/upgrades/http_upstream.rs | 2 + wasm/client/Cargo.toml | 3 +- wasm/client/src/client.rs | 31 +- wasm/client/src/lib.rs | 13 + wasm/full-nym-wasm/Cargo.toml | 2 +- wasm/mix-fetch/Cargo.toml | 3 +- wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go | 62 - wasm/mix-fetch/internal-dev/worker.js | 13 - wasm/mix-fetch/src/lib.rs | 3 +- wasm/node-tester/Cargo.toml | 2 +- yarn.lock | 1099 +---------------- 51 files changed, 227 insertions(+), 1396 deletions(-) rename sdk/typescript/docs/components/{mixfetch.tsx => mix-fetch.tsx} (83%) create mode 100644 sdk/typescript/packages/mix-fetch/scripts/showDependencyLocation.cjs create mode 100644 sdk/typescript/packages/sdk/scripts/showDependencyLocation.cjs create mode 100644 tools/nymvisor/src/upgrades/http_upstream.rs diff --git a/Cargo.lock b/Cargo.lock index 4190432be9..e4f53a877f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2994,7 +2994,7 @@ dependencies = [ [[package]] name = "extension-storage" -version = "1.2.1" +version = "1.2.4-rc.0" dependencies = [ "bip39", "console_error_panic_hook", @@ -5559,12 +5559,13 @@ dependencies = [ [[package]] name = "mix-fetch-wasm" -version = "1.2.1" +version = "1.2.4-rc.0" dependencies = [ "async-trait", "futures", "http-api-client", "js-sys", + "nym-bin-common", "nym-ordered-buffer", "nym-service-providers-common", "nym-socks5-requests", @@ -6260,11 +6261,12 @@ dependencies = [ [[package]] name = "nym-client-wasm" -version = "1.2.1" +version = "1.2.4-rc.0" dependencies = [ "anyhow", "futures", "js-sys", + "nym-bin-common", "nym-node-tester-utils", "nym-node-tester-wasm", "rand 0.7.3", @@ -6958,7 +6960,7 @@ dependencies = [ [[package]] name = "nym-node-tester-wasm" -version = "1.2.1" +version = "1.2.4-rc.0" dependencies = [ "futures", "js-sys", @@ -7558,15 +7560,6 @@ dependencies = [ "ts-rs", ] -[[package]] -name = "nym-wasm-sdk" -version = "1.2.1" -dependencies = [ - "mix-fetch-wasm", - "nym-client-wasm", - "nym-node-tester-wasm", -] - [[package]] name = "nym-wireguard" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index a7d470c6a7..01195764d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -105,7 +105,7 @@ members = [ "tools/nym-nr-query", "tools/ts-rs-cli", "wasm/client", - "wasm/full-nym-wasm", +# "wasm/full-nym-wasm", "wasm/mix-fetch", "wasm/node-tester", ] diff --git a/Makefile b/Makefile index 31127bc413..499a0d7d71 100644 --- a/Makefile +++ b/Makefile @@ -104,7 +104,7 @@ sdk-wasm-build: $(MAKE) -C wasm/client $(MAKE) -C wasm/node-tester $(MAKE) -C wasm/mix-fetch - $(MAKE) -C wasm/full-nym-wasm + #$(MAKE) -C wasm/full-nym-wasm # run this from npm/yarn to ensure tools are in the path, e.g. yarn build:sdk from root of repo sdk-typescript-build: @@ -114,7 +114,7 @@ sdk-typescript-build: yarn --cwd sdk/typescript/codegen/contract-clients build # NOTE: These targets are part of the main workspace (but not as wasm32-unknown-unknown) -WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm nym-wasm-sdk +WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm sdk-wasm-test: #cargo test $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings diff --git a/nym-browser-extension/storage/Cargo.toml b/nym-browser-extension/storage/Cargo.toml index aee9afb118..73359a92ab 100644 --- a/nym-browser-extension/storage/Cargo.toml +++ b/nym-browser-extension/storage/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "extension-storage" -version = "1.2.1" +version = "1.2.4-rc.0" edition = "2021" license = "Apache-2.0" repository = "https://github.com/nymtech/nym" diff --git a/nym-wallet/package.json b/nym-wallet/package.json index 93b1793711..fe35c4fd30 100644 --- a/nym-wallet/package.json +++ b/nym-wallet/package.json @@ -1,24 +1,24 @@ { "name": "@nymproject/nym-wallet-app", - "version": "1.2.10", - "main": "index.js", + "version": "1.2.12-rc.0", "license": "MIT", + "main": "index.js", "scripts": { - "prewebpack:dev": "yarn --cwd .. build", - "webpack:dev": "yarn webpack serve --config webpack.dev.js", - "webpack:prod": "yarn webpack --progress --config webpack.prod.js", - "tauri:dev": "yarn tauri dev", - "tauri:build": "yarn tauri build", - "tsc": "tsc --noEmit true", - "tsc:watch": "tsc --noEmit true --watch", - "dev": "run-p tauri:dev webpack:dev", - "prebuild": "yarn --cwd .. build", "build": "run-s webpack:prod tauri:build", + "dev": "run-p tauri:dev webpack:dev", "lint": "eslint src", "lint:fix": "eslint src --fix", + "prebuild": "yarn --cwd .. build", "prestorybook": "yarn --cwd .. build", + "prewebpack:dev": "yarn --cwd .. build", "storybook": "start-storybook -p 6006", - "storybook:build": "build-storybook" + "storybook:build": "build-storybook", + "tauri:build": "yarn tauri build", + "tauri:dev": "yarn tauri dev", + "tsc": "tsc --noEmit true", + "tsc:watch": "tsc --noEmit true --watch", + "webpack:dev": "yarn webpack serve --config webpack.dev.js", + "webpack:prod": "yarn webpack --progress --config webpack.prod.js" }, "dependencies": { "@emotion/react": "^11.7.0", @@ -29,7 +29,7 @@ "@mui/styles": "^5.2.2", "@mui/utils": "^5.7.0", "@nymproject/mui-theme": "^1.0.0", - "@nymproject/node-tester": "^1.0.0", + "@nymproject/node-tester": "^1.2.3", "@nymproject/react": "^1.0.0", "@nymproject/types": "^1.0.0", "@storybook/react": "^6.5.15", @@ -123,5 +123,6 @@ "webpack-dev-server": "^4.5.0", "webpack-favicons": "^1.3.8", "webpack-merge": "^5.8.0" - } + }, + "private": false } \ No newline at end of file diff --git a/package.json b/package.json index bd928a454e..856bce8b69 100644 --- a/package.json +++ b/package.json @@ -10,13 +10,6 @@ "sdk/typescript/packages/mui-theme", "sdk/typescript/packages/react-components", "sdk/typescript/packages/validator-client", - "sdk/typescript/packages/mix-fetch-node", - "sdk/typescript/packages/nodejs-client", - "sdk/typescript/packages/node-tester", - "sdk/typescript/packages/sdk-react", - "sdk/typescript/packages/mix-fetch", - "sdk/typescript/packages/sdk", - "sdk/typescript/codegen/contract-clients", "ts-packages/*", "nym-wallet", "nym-connect/**", @@ -60,4 +53,4 @@ "@npmcli/node-gyp": "^3.0.0", "node-gyp": "^9.3.1" } -} +} \ No newline at end of file diff --git a/sdk/typescript/codegen/contract-clients/package.json b/sdk/typescript/codegen/contract-clients/package.json index 49e3d1fc99..084a355e49 100644 --- a/sdk/typescript/codegen/contract-clients/package.json +++ b/sdk/typescript/codegen/contract-clients/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/contract-clients", - "version": "1.2.1", + "version": "1.2.4-rc.0", "description": "A client for all Nym smart contracts", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -27,4 +27,4 @@ }, "private": false, "types": "./dist/index.d.ts" -} +} \ No newline at end of file diff --git a/sdk/typescript/docs/components/mixfetch.tsx b/sdk/typescript/docs/components/mix-fetch.tsx similarity index 83% rename from sdk/typescript/docs/components/mixfetch.tsx rename to sdk/typescript/docs/components/mix-fetch.tsx index 564de818e4..e77e7e49d3 100644 --- a/sdk/typescript/docs/components/mixfetch.tsx +++ b/sdk/typescript/docs/components/mix-fetch.tsx @@ -7,23 +7,11 @@ import Box from '@mui/material/Box'; import { mixFetch } from '@nymproject/mix-fetch-full-fat'; import Stack from '@mui/material/Stack'; import Paper from '@mui/material/Paper'; -import type { SetupMixFetchOps } from '@nymproject/mix-fetch'; +import type { SetupMixFetchOps } from '@nymproject/mix-fetch-full-fat'; const defaultUrl = 'https://nymtech.net/favicon.svg'; const args = { mode: 'unsafe-ignore-cors' }; -const extra = { - hiddenGateways: [ - { - owner: 'n1kymvkx6vsq7pvn6hfurkpg06h3j4gxj4em7tlg', - host: 'gateway1.nymtech.net', - explicitIp: '213.219.38.119', - identityKey: 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM', - sphinxKey: 'CYcrjoJ8GT7Dp54zViUyyRUfegeRCyPifWQZHRgMZrfX', - }, - ], -}; - const mixFetchOptions: SetupMixFetchOps = { preferredGateway: 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM', // with WSS preferredNetworkRequester: @@ -32,7 +20,6 @@ const mixFetchOptions: SetupMixFetchOps = { requestTimeoutMs: 60_000, }, forceTls: true, // force WSS - extra, // manually set the gateway details for WSS so certificates will work for hostname }; export const MixFetch = () => { diff --git a/sdk/typescript/docs/components/traffic.tsx b/sdk/typescript/docs/components/traffic.tsx index 9205382d2d..07b00355ec 100644 --- a/sdk/typescript/docs/components/traffic.tsx +++ b/sdk/typescript/docs/components/traffic.tsx @@ -26,6 +26,7 @@ export const Traffic = () => { await client?.client.start({ clientId: crypto.randomUUID(), nymApiUrl, + forceTls: true, // force WSS }); // check when is connected and set the self address diff --git a/sdk/typescript/docs/package.json b/sdk/typescript/docs/package.json index 580a99614e..0339a8e9bf 100644 --- a/sdk/typescript/docs/package.json +++ b/sdk/typescript/docs/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/ts-sdk-docs", - "version": "1.2.1", + "version": "1.2.4-rc.0", "description": "Nym Typescript SDK Docs", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -28,10 +28,9 @@ "@mui/icons-material": "^5.14.9", "@mui/lab": "^5.0.0-alpha.145", "@mui/material": "^5.14.8", - "@nymproject/contract-clients": ">=1.2.1-rc.0 || ^1", - "@nymproject/mix-fetch": ">=1.2.1-rc.0 || ^1", - "@nymproject/mix-fetch-full-fat": ">=1.2.1-rc.0 || ^1", - "@nymproject/sdk-full-fat": ">=1.2.1-rc.0 || ^1", + "@nymproject/contract-clients": ">=1.2.4-rc.0 || ^1", + "@nymproject/mix-fetch-full-fat": ">=1.2.4-rc.0 || ^1", + "@nymproject/sdk-full-fat": ">=1.2.4-rc.0 || ^1", "chain-registry": "^1.19.0", "cosmjs-types": "^0.8.0", "next": "^13.4.19", @@ -51,4 +50,4 @@ "typescript": "^4.9.3" }, "private": false -} \ No newline at end of file +} diff --git a/sdk/typescript/docs/pages/examples/mixnet.mdx b/sdk/typescript/docs/pages/examples/mixnet.mdx index 20c80af4e8..d7f47b5809 100644 --- a/sdk/typescript/docs/pages/examples/mixnet.mdx +++ b/sdk/typescript/docs/pages/examples/mixnet.mdx @@ -70,6 +70,7 @@ export function MixnetClient() { await client?.client.start({ clientId: crypto.randomUUID(), nymApiUrl, + forceTls: true, // force WSS }); // Check when is connected and set the self address diff --git a/sdk/typescript/docs/pages/playground/mixfetch.mdx b/sdk/typescript/docs/pages/playground/mixfetch.mdx index 6b8b9c24f7..0d67a7e228 100644 --- a/sdk/typescript/docs/pages/playground/mixfetch.mdx +++ b/sdk/typescript/docs/pages/playground/mixfetch.mdx @@ -1,6 +1,6 @@ # mixFetch -import { MixFetch } from '../../components/mixfetch' +import { MixFetch } from '../../components/mix-fetch' import Box from '@mui/material/Box'; import FormattedMixFetchExampleCode from '../../code-examples/mixfetch-example-code.mdx'; diff --git a/sdk/typescript/examples/chat-app/parcel/package.json b/sdk/typescript/examples/chat-app/parcel/package.json index 646d5610fe..dcab7e23d6 100644 --- a/sdk/typescript/examples/chat-app/parcel/package.json +++ b/sdk/typescript/examples/chat-app/parcel/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk-example-plain-html-parcel", - "version": "1.0.1", + "version": "1.0.4-rc.0", "description": "An example project that uses WASM and plain HTML bundled with Parcel v2", "license": "Apache-2.0", "scripts": { @@ -15,7 +15,7 @@ "tsc:watch": "tsc --watch" }, "dependencies": { - "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" + "@nymproject/sdk": ">=1.2.2-rc.0 || ^1" }, "devDependencies": { "@types/jest": "^27.0.1", diff --git a/sdk/typescript/examples/chat-app/plain-html/package.json b/sdk/typescript/examples/chat-app/plain-html/package.json index 7cdf5deddc..f2515cb2c0 100644 --- a/sdk/typescript/examples/chat-app/plain-html/package.json +++ b/sdk/typescript/examples/chat-app/plain-html/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk-example-plain-html", - "version": "1.0.1", + "version": "1.0.4-rc.0", "description": "An example project that uses WASM and plain HTML", "license": "Apache-2.0", "scripts": { @@ -16,7 +16,7 @@ "tsc:watch": "tsc --watch" }, "dependencies": { - "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" + "@nymproject/sdk": ">=1.2.2-rc.0 || ^1" }, "devDependencies": { "@babel/core": "^7.15.0", diff --git a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json index 48813124dd..56184f8aa3 100644 --- a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json +++ b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk-example-react-webpack-wasm", - "version": "1.0.1", + "version": "1.0.4-rc.0", "description": "An example project that uses WASM, React, Webpack, Typescript and the Nym theme + components library", "license": "Apache-2.0", "scripts": { @@ -20,7 +20,7 @@ "@mui/lab": "^5.0.0-alpha.72", "@mui/material": "^5.0.1", "@mui/styles": "^5.0.1", - "@nymproject/sdk": ">=1.2.1-rc.0 || ^1", + "@nymproject/sdk": ">=1.2.2-rc.0 || ^1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", diff --git a/sdk/typescript/examples/chrome-extension/package.json b/sdk/typescript/examples/chrome-extension/package.json index 5880b8d4e8..293e3b791f 100644 --- a/sdk/typescript/examples/chrome-extension/package.json +++ b/sdk/typescript/examples/chrome-extension/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk-example-chrome-extension", - "version": "1.0.1", + "version": "1.0.4-rc.0", "description": "This is an example of how Nym can be used within the context of a Chrome extension.", "license": "ISC", "author": "", @@ -9,7 +9,7 @@ "build": "webpack" }, "dependencies": { - "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" + "@nymproject/sdk": ">=1.2.2-rc.0 || ^1" }, "devDependencies": { "clean-webpack-plugin": "^4.0.0", diff --git a/sdk/typescript/examples/firefox-extension/package.json b/sdk/typescript/examples/firefox-extension/package.json index 9615a1cf04..19b7c49405 100644 --- a/sdk/typescript/examples/firefox-extension/package.json +++ b/sdk/typescript/examples/firefox-extension/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk-example-firefox-extension", - "version": "1.0.1", + "version": "1.0.4-rc.0", "description": "This is an example of how Nym can be used within the context of a Firefox extension.", "license": "ISC", "author": "", @@ -9,7 +9,7 @@ "build": "yarn webpack" }, "dependencies": { - "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" + "@nymproject/sdk": ">=1.2.2-rc.0 || ^1" }, "devDependencies": { "copy-webpack-plugin": "^11.0.0", diff --git a/sdk/typescript/examples/mix-fetch/browser/package.json b/sdk/typescript/examples/mix-fetch/browser/package.json index 4de1922b38..db7817668e 100644 --- a/sdk/typescript/examples/mix-fetch/browser/package.json +++ b/sdk/typescript/examples/mix-fetch/browser/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/mix-fetch-example-parcel", - "version": "1.0.1", + "version": "1.0.4-rc.0", "license": "Apache-2.0", "scripts": { "build": "parcel build --no-cache --no-content-hash", @@ -8,7 +8,7 @@ "start": "parcel --no-cache" }, "dependencies": { - "@nymproject/mix-fetch": ">=1.2.1-rc.0 || ^1", + "@nymproject/mix-fetch": ">=1.2.2-rc.0 || ^1", "parcel": "^2.9.3" }, "private": false, diff --git a/sdk/typescript/examples/node-tester/parcel/package.json b/sdk/typescript/examples/node-tester/parcel/package.json index 015b816fda..4a5de4273e 100644 --- a/sdk/typescript/examples/node-tester/parcel/package.json +++ b/sdk/typescript/examples/node-tester/parcel/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk-example-node-tester-plain-html-parcel", - "version": "1.0.1", + "version": "1.0.4-rc.0", "description": "An example project that uses WASM and plain HTML bundled with Parcel v2", "license": "Apache-2.0", "scripts": { @@ -15,7 +15,7 @@ "tsc:watch": "tsc --watch" }, "dependencies": { - "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" + "@nymproject/sdk": ">=1.2.2-rc.0 || ^1" }, "devDependencies": { "@types/jest": "^27.0.1", diff --git a/sdk/typescript/examples/node-tester/plain-html/package.json b/sdk/typescript/examples/node-tester/plain-html/package.json index bf59e74f0d..1f3266ba9c 100644 --- a/sdk/typescript/examples/node-tester/plain-html/package.json +++ b/sdk/typescript/examples/node-tester/plain-html/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk-example-node-tester-plain-html", - "version": "1.0.1", + "version": "1.0.4-rc.0", "description": "An example project that uses WASM node tester and plain HTML", "license": "Apache-2.0", "scripts": { @@ -16,7 +16,7 @@ "tsc:watch": "tsc --watch" }, "dependencies": { - "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" + "@nymproject/sdk": ">=1.2.2-rc.0 || ^1" }, "devDependencies": { "@babel/core": "^7.15.0", diff --git a/sdk/typescript/examples/node-tester/react/package.json b/sdk/typescript/examples/node-tester/react/package.json index 9f3b2394e7..69fe0317ee 100644 --- a/sdk/typescript/examples/node-tester/react/package.json +++ b/sdk/typescript/examples/node-tester/react/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk-example-node-tester-react", - "version": "1.0.1", + "version": "1.0.4-rc.0", "description": "An example project that uses WASM node tester and React", "license": "Apache-2.0", "scripts": { @@ -11,7 +11,7 @@ "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.14.0", "@mui/material": "^5.14.0", - "@nymproject/sdk": ">=1.2.1-rc.0 || ^1", + "@nymproject/sdk": ">=1.2.2-rc.0 || ^1", "parcel": "^2.9.3", "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/sdk/typescript/packages/mix-fetch-node/package.json b/sdk/typescript/packages/mix-fetch-node/package.json index 3efd987e43..0e4e937e90 100644 --- a/sdk/typescript/packages/mix-fetch-node/package.json +++ b/sdk/typescript/packages/mix-fetch-node/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/mix-fetch-node", - "version": "1.2.1", + "version": "1.2.4-rc.0", "description": "This package is a drop-in replacement for `fetch` in NodeJS to send HTTP requests over the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -28,7 +28,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/mix-fetch-wasm-node": ">=1.2.1-rc.0 || ^1", + "@nymproject/mix-fetch-wasm-node": ">=1.2.4-rc.0 || ^1", "comlink": "^4.3.1", "fake-indexeddb": "^5.0.0", "node-fetch": "^3.3.2", diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/package.json b/sdk/typescript/packages/mix-fetch/internal-dev/package.json index 9965510bdb..aa982ba57e 100644 --- a/sdk/typescript/packages/mix-fetch/internal-dev/package.json +++ b/sdk/typescript/packages/mix-fetch/internal-dev/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/mix-fetch-tester-webpack", - "version": "1.0.1", + "version": "1.0.4-rc.0", "license": "Apache-2.0", "scripts": { "build": "webpack build --progress --config webpack.prod.js", @@ -8,7 +8,7 @@ "start": "webpack serve --progress --port 3000" }, "dependencies": { - "@nymproject/mix-fetch": ">=1.2.1-rc.0 || ^1" + "@nymproject/mix-fetch": ">=1.2.2-rc.0 || ^1" }, "devDependencies": { "@babel/core": "^7.22.10", diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json b/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json index 6849466cd3..3cd4ceb362 100644 --- a/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json +++ b/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/mix-fetch-tester-parcel", - "version": "1.0.1", + "version": "1.0.4-rc.0", "license": "Apache-2.0", "scripts": { "build": "npx parcel build --no-cache --no-content-hash", @@ -8,7 +8,7 @@ "start": "npx parcel --no-cache" }, "dependencies": { - "@nymproject/mix-fetch": ">=1.2.1-rc.0 || ^1" + "@nymproject/mix-fetch": ">=1.2.2-rc.0 || ^1" }, "private": false, "source": "../src/index.html" diff --git a/sdk/typescript/packages/mix-fetch/package.json b/sdk/typescript/packages/mix-fetch/package.json index f58088197b..60d005ea5a 100644 --- a/sdk/typescript/packages/mix-fetch/package.json +++ b/sdk/typescript/packages/mix-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/mix-fetch", - "version": "1.2.1", + "version": "1.2.4-rc.0", "description": "This package is a drop-in replacement for `fetch` to send HTTP requests over the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -27,13 +27,14 @@ "docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\"", "lint": "eslint src", "lint:fix": "eslint src --fix", + "prebuild": "node scripts/showDependencyLocation.cjs", "start": "tsc -w", "start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'", "test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache", "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/mix-fetch-wasm": ">=1.2.1-rc.0 || ^1", + "@nymproject/mix-fetch-wasm": ">=1.2.4-rc.0 || ^1", "comlink": "^4.3.1" }, "devDependencies": { diff --git a/sdk/typescript/packages/mix-fetch/scripts/showDependencyLocation.cjs b/sdk/typescript/packages/mix-fetch/scripts/showDependencyLocation.cjs new file mode 100644 index 0000000000..2843f899e2 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/scripts/showDependencyLocation.cjs @@ -0,0 +1,8 @@ +const fs = require('fs'); + +const packageName = '@nymproject/mix-fetch-wasm'; +const packageJsonPath = require.resolve(packageName + '/package.json'); + +const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString()); + +console.log(`🟢🟢🟢 ${packageName} is at ${packageJsonPath} is version ${packageJson.version}`); diff --git a/sdk/typescript/packages/node-tester/package.json b/sdk/typescript/packages/node-tester/package.json index acb32c0b19..d76dc6178c 100644 --- a/sdk/typescript/packages/node-tester/package.json +++ b/sdk/typescript/packages/node-tester/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/node-tester", - "version": "1.2.1", + "version": "1.2.4-rc.0", "description": "This package provides a tester that can send test packets to mixnode that is part of the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -25,7 +25,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-node-tester-wasm": ">=1.2.1-rc.0 || ^1", + "@nymproject/nym-node-tester-wasm": ">=1.2.4-rc.0 || ^1", "comlink": "^4.3.1" }, "devDependencies": { diff --git a/sdk/typescript/packages/nodejs-client/package.json b/sdk/typescript/packages/nodejs-client/package.json index d1d46f532d..9b7f46706e 100644 --- a/sdk/typescript/packages/nodejs-client/package.json +++ b/sdk/typescript/packages/nodejs-client/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/nodejs-client", - "version": "1.2.1", + "version": "1.2.4-rc.0", "license": "Apache-2.0", "author": "Nym Technologies SA", "files": [ @@ -25,7 +25,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-client-wasm-node": ">=1.2.1-rc.0 || ^1", + "@nymproject/nym-client-wasm-node": ">=1.2.4-rc.0 || ^1", "comlink": "^4.3.1", "fake-indexeddb": "^4.0.2", "rollup-plugin-polyfill": "^4.2.0", diff --git a/sdk/typescript/packages/nodejs-client/src/types.ts b/sdk/typescript/packages/nodejs-client/src/types.ts index 89b7df770a..f16bffa9e0 100644 --- a/sdk/typescript/packages/nodejs-client/src/types.ts +++ b/sdk/typescript/packages/nodejs-client/src/types.ts @@ -1,4 +1,4 @@ -import type { DebugWasm } from '@nymproject/nym-client-wasm-node'; +import type { ClientOpts } from '@nymproject/nym-client-wasm-node'; /** * Options for the Nym mixnet client. @@ -32,7 +32,7 @@ export interface NymMixnetClient { * @internal */ export interface IWebWorker { - start: (config: NymClientConfig) => void; + start: (opts?: ClientOpts) => void; stop: () => void; selfAddress: () => string | undefined; setTextMimeTypes: (mimeTypes: string[]) => void; @@ -55,7 +55,7 @@ export interface Client { * }); * */ - start: (config: NymClientConfig) => Promise; + start: (opts?: ClientOpts) => Promise; /** * Stop the client. * @example @@ -155,36 +155,6 @@ export interface Client { rawSend: (args: { payload: Uint8Array; recipient: string; replySurbs?: number }) => Promise; } -/** - * The configuration passed to the {@link Client.start} method of the {@link Client} - */ -export interface NymClientConfig { - /** - * A human-readable id for the client. - */ - clientId: string; - - /** - * The URL of a validator API to query for the network topology. - */ - nymApiUrl: string; - - /** - * Optional. The identity key of the preferred gateway to connect to. - */ - preferredGatewayIdentityKey?: string; - - /** - * Optional. The listener websocket of the preferred gateway to connect to. - */ - gatewayListener?: string; - - /** - * Optional. Settings for the WASM client. - */ - debug?: DebugWasm; -} - export interface Events { /** * @see {@link LoadedEvent} diff --git a/sdk/typescript/packages/nodejs-client/src/worker.ts b/sdk/typescript/packages/nodejs-client/src/worker.ts index a1a8bea3f1..75c7fadd46 100644 --- a/sdk/typescript/packages/nodejs-client/src/worker.ts +++ b/sdk/typescript/packages/nodejs-client/src/worker.ts @@ -5,13 +5,12 @@ import { parentPort } from 'worker_threads'; import '@nymproject/nym-client-wasm-node/nym_client_wasm_bg.wasm'; import { - ClientConfig, NymClient, - NymClientBuilder, decode_payload, encode_payload_with_headers, parse_utf8_string, utf8_string_to_byte_array, + ClientOpts, } from '@nymproject/nym-client-wasm-node'; import type { @@ -19,7 +18,6 @@ import type { ConnectedEvent, IWebWorker, LoadedEvent, - NymClientConfig, OnRawPayloadFn, RawMessageReceivedEvent, StringMessageReceivedEvent, @@ -44,28 +42,8 @@ const postMessageWithType = (event: E) => parentPort?.postMessage(event); class ClientWrapper { client: NymClient | null = null; - builder: NymClientBuilder | null = null; - mimeTypes: string[] = [MimeTypes.TextPlain, MimeTypes.ApplicationJson]; - /** - * Creates the WASM client and initialises it. - */ - init = (config: any, onRawPayloadHandler?: OnRawPayloadFn) => { - const onMessageHandler = (message: Uint8Array) => { - try { - if (onRawPayloadHandler) { - onRawPayloadHandler(message); - } - } catch (e) { - // eslint-disable-next-line no-console - console.error('Unhandled exception in `ClientWrapper.onRawPayloadHandler`: ', e); - } - }; - - this.builder = new NymClientBuilder(config, onMessageHandler); - }; - /** * Sets the mime-types that will be parsed for UTF-8 string content. * @@ -95,16 +73,22 @@ class ClientWrapper { /** * Connects to the gateway and starts the client sending traffic. */ - start = async () => { - if (!this.builder) { - // eslint-disable-next-line no-console - console.error('Client config has not been initialised. Please call `init` first.'); - return; - } + start = async (opts?: ClientOpts, onRawPayloadHandler?: OnRawPayloadFn) => { + const onMessageHandler = (message: Uint8Array) => { + try { + if (onRawPayloadHandler) { + onRawPayloadHandler(message); + } + } catch (e) { + // eslint-disable-next-line no-console + console.error('Unhandled exception in `ClientWrapper.onRawPayloadHandler`: ', e); + } + }; + // this is current limitation of wasm in rust - for async methods you can't take self by reference... // I'm trying to figure out if I can somehow hack my way around it, but for time being you have to re-assign // the object (it's the same one) - this.client = await this.builder.start_client(); + this.client = await new NymClient(onMessageHandler, opts); }; /** @@ -142,9 +126,9 @@ class ClientWrapper { // this wrapper handles any state that the wasm-pack interop needs, e.g. holding an instance of the instantiated WASM code const wrapper = new ClientWrapper(); -const startHandler = async (config: NymClientConfig) => { +const startHandler = async (opts?: ClientOpts) => { // create the client, passing handlers for events - wrapper.init(new ClientConfig(config), async (message) => { + await wrapper.start(opts, async (message) => { // fire an event with the raw message postMessageWithType({ kind: EventKinds.RawMessageReceived, @@ -175,8 +159,7 @@ const startHandler = async (config: NymClientConfig) => { console.error('Failed to parse binary message', e); } }); - // start the client sending traffic - await wrapper.start(); + // get the address const address = wrapper.selfAddress(); postMessageWithType({ kind: EventKinds.Connected, args: { address } }); @@ -184,9 +167,9 @@ const startHandler = async (config: NymClientConfig) => { // implement the public logic of this web worker (message exchange between the worker and caller is done by https://www.npmjs.com/package/comlink) const webWorker: IWebWorker = { - start(config) { + start(opts?: ClientOpts) { // eslint-disable-next-line no-console - startHandler(config).catch((e) => console.error('[Nym WASM client] Failed to start', e)); + startHandler(opts).catch((e) => console.error('[Nym WASM client] Failed to start', e)); }, stop() { wrapper.stop(); diff --git a/sdk/typescript/packages/sdk-react/package.json b/sdk/typescript/packages/sdk-react/package.json index b6dafc5d23..672aa34617 100644 --- a/sdk/typescript/packages/sdk-react/package.json +++ b/sdk/typescript/packages/sdk-react/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk-react", - "version": "1.2.1", + "version": "1.2.4-rc.0", "license": "Apache-2.0", "author": "Nym Technologies SA", "files": [ @@ -20,7 +20,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" + "@nymproject/sdk": ">=1.2.2-rc.0 || ^1" }, "devDependencies": { "@babel/core": "^7.17.5", diff --git a/sdk/typescript/packages/sdk/package.json b/sdk/typescript/packages/sdk/package.json index 23e4b803ce..331d685846 100644 --- a/sdk/typescript/packages/sdk/package.json +++ b/sdk/typescript/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk", - "version": "1.2.1", + "version": "1.2.4-rc.0", "license": "Apache-2.0", "author": "Nym Technologies SA", "files": [ @@ -24,13 +24,14 @@ "docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\"", "lint": "eslint src", "lint:fix": "eslint src --fix", + "prebuild": "node scripts/showDependencyLocation.cjs", "start": "tsc -w", "start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'", "test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache", "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-client-wasm": ">=1.2.1-rc.0 || ^1", + "@nymproject/nym-client-wasm": ">=1.2.4-rc.0 || ^1", "comlink": "^4.3.1" }, "devDependencies": { diff --git a/sdk/typescript/packages/sdk/scripts/showDependencyLocation.cjs b/sdk/typescript/packages/sdk/scripts/showDependencyLocation.cjs new file mode 100644 index 0000000000..08028dcbcf --- /dev/null +++ b/sdk/typescript/packages/sdk/scripts/showDependencyLocation.cjs @@ -0,0 +1,8 @@ +const fs = require('fs'); + +const packageName = '@nymproject/nym-client-wasm'; +const packageJsonPath = require.resolve(packageName + '/package.json'); + +const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString()); + +console.log(`🟢🟢🟢 ${packageName} is at ${packageJsonPath} is version ${packageJson.version}`); diff --git a/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts b/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts index c395877f76..0f22f1bcd6 100644 --- a/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts +++ b/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts @@ -1,4 +1,4 @@ -import type { DebugWasm } from '@nymproject/nym-client-wasm'; +import type { ClientOpts } from '@nymproject/nym-client-wasm'; /** * @@ -7,7 +7,7 @@ import type { DebugWasm } from '@nymproject/nym-client-wasm'; * @internal */ export interface IWebWorker { - start: (config: NymClientConfig) => void; + start: (opts?: ClientOpts) => void; stop: () => void; selfAddress: () => string | undefined; setTextMimeTypes: (mimeTypes: string[]) => void; @@ -30,7 +30,7 @@ export interface Client { * }); * */ - start: (config: NymClientConfig) => Promise; + start: (opts?: ClientOpts) => Promise; /** * Stop the client. * @example @@ -130,36 +130,6 @@ export interface Client { rawSend: (args: { payload: Uint8Array; recipient: string; replySurbs?: number }) => Promise; } -/** - * The configuration passed to the {@link Client.start} method of the {@link Client} - */ -export interface NymClientConfig { - /** - * A human-readable id for the client. - */ - clientId: string; - - /** - * The URL of a validator API to query for the network topology. - */ - nymApiUrl: string; - - /** - * Optional. The identity key of the preferred gateway to connect to. - */ - preferredGatewayIdentityKey?: string; - - /** - * Optional. The listener websocket of the preferred gateway to connect to. - */ - gatewayListener?: string; - - /** - * Optional. Settings for the WASM client. - */ - debug?: DebugWasm; -} - export interface Events { /** * @see {@link LoadedEvent} diff --git a/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts b/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts index 90330f37b5..0f848433b8 100644 --- a/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts +++ b/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts @@ -17,12 +17,11 @@ import wasmBytes from '@nymproject/nym-client-wasm/nym_client_wasm_bg.wasm'; // eslint-disable-next-line import/no-extraneous-dependencies import init, { NymClient, - NymClientBuilder, - ClientConfig, decode_payload, parse_utf8_string, utf8_string_to_byte_array, encode_payload_with_headers, + ClientOpts, } from '@nymproject/nym-client-wasm'; import type { @@ -30,7 +29,6 @@ import type { ConnectedEvent, IWebWorker, LoadedEvent, - NymClientConfig, OnRawPayloadFn, RawMessageReceivedEvent, StringMessageReceivedEvent, @@ -56,27 +54,8 @@ const postMessageWithType = (event: E) => self.postMessage(event); class ClientWrapper { client: NymClient | null = null; - builder: NymClientBuilder | null = null; - mimeTypes: string[] = [MimeTypes.TextPlain, MimeTypes.ApplicationJson]; - /** - * Creates the WASM client and initialises it. - */ - init = (config: ClientConfig, onRawPayloadHandler?: OnRawPayloadFn) => { - const onMessageHandler = (message: Uint8Array) => { - try { - if (onRawPayloadHandler) { - onRawPayloadHandler(message); - } - } catch (e) { - console.error('Unhandled exception in `ClientWrapper.onRawPayloadHandler`: ', e); - } - }; - - this.builder = new NymClientBuilder(config, onMessageHandler); - }; - /** * Sets the mime-types that will be parsed for UTF-8 string content. * @@ -106,16 +85,22 @@ class ClientWrapper { /** * Connects to the gateway and starts the client sending traffic. */ - start = async () => { - if (!this.builder) { - console.error('Client config has not been initialised. Please call `init` first.'); - return; - } + start = async (opts?: ClientOpts, onRawPayloadHandler?: OnRawPayloadFn) => { + const onMessageHandler = (message: Uint8Array) => { + try { + if (onRawPayloadHandler) { + onRawPayloadHandler(message); + } + } catch (e) { + // eslint-disable-next-line no-console + console.error('Unhandled exception in `ClientWrapper.onRawPayloadHandler`: ', e); + } + }; // this is current limitation of wasm in rust - for async methods you can't take self by reference... // I'm trying to figure out if I can somehow hack my way around it, but for time being you have to re-assign // the object (it's the same one) - this.client = await this.builder.start_client(); + this.client = await new NymClient(onMessageHandler, opts); }; /** @@ -158,9 +143,9 @@ init(wasmBytes()) // this wrapper handles any state that the wasm-pack interop needs, e.g. holding an instance of the instantiated WASM code const wrapper = new ClientWrapper(); - const startHandler = async (config: NymClientConfig) => { + const startHandler = async (opts?: ClientOpts) => { // create the client, passing handlers for events - wrapper.init(new ClientConfig(config), async (message) => { + await wrapper.start(opts, async (message) => { // fire an event with the raw message postMessageWithType({ kind: EventKinds.RawMessageReceived, @@ -195,9 +180,6 @@ init(wasmBytes()) } }); - // start the client sending traffic - await wrapper.start(); - // get the address const address = wrapper.selfAddress(); postMessageWithType({ kind: EventKinds.Connected, args: { address } }); diff --git a/sdk/typescript/scripts/build-prod-sdk.sh b/sdk/typescript/scripts/build-prod-sdk.sh index 7dd1332b9c..3b3b5dcf9e 100755 --- a/sdk/typescript/scripts/build-prod-sdk.sh +++ b/sdk/typescript/scripts/build-prod-sdk.sh @@ -13,8 +13,15 @@ rm -rf dist || true # use wasm-pack to build packages yarn build:wasm +# enable dev mode and then install dev packages +yarn dev:on +yarn + # build the Typescript SDK packages yarn build:ci:sdk # build documentation yarn docs:prod:build + +# turn dev mode off +yarn dev:off diff --git a/sdk/typescript/scripts/dev-mode-add.mjs b/sdk/typescript/scripts/dev-mode-add.mjs index 24bffbfbc2..edecdae96b 100644 --- a/sdk/typescript/scripts/dev-mode-add.mjs +++ b/sdk/typescript/scripts/dev-mode-add.mjs @@ -2,7 +2,7 @@ import fs from 'fs'; const packageJson = JSON.parse(fs.readFileSync('package.json').toString()); -const devWorkspace = ['sdk/typescript/packages/**', 'sdk/typescript/examples/**']; +const devWorkspace = ['sdk/typescript/packages/**', 'sdk/typescript/examples/**', 'sdk/typescript/codegen/**']; if (!packageJson.workspaces.includes(devWorkspace)) { // add packageJson.workspaces.push(...devWorkspace); diff --git a/sdk/typescript/scripts/dev-mode-remove.mjs b/sdk/typescript/scripts/dev-mode-remove.mjs index a8317d8e7f..ce897efbd0 100644 --- a/sdk/typescript/scripts/dev-mode-remove.mjs +++ b/sdk/typescript/scripts/dev-mode-remove.mjs @@ -2,7 +2,7 @@ import fs from 'fs'; const packageJson = JSON.parse(fs.readFileSync('package.json').toString()); -const devWorkspace = ['sdk/typescript/packages/**', 'sdk/typescript/examples/**']; +const devWorkspace = ['sdk/typescript/packages/**', 'sdk/typescript/examples/**', 'sdk/typescript/codegen/**']; // remove packageJson.workspaces = packageJson.workspaces.filter((w) => !devWorkspace.includes(w)); diff --git a/tools/internal/sdk-version-bump/src/helpers.rs b/tools/internal/sdk-version-bump/src/helpers.rs index 455ea3487c..55d293d798 100644 --- a/tools/internal/sdk-version-bump/src/helpers.rs +++ b/tools/internal/sdk-version-bump/src/helpers.rs @@ -29,7 +29,12 @@ pub(crate) trait ReleasePackage: Sized { fn bump_version(&mut self, pre_release: bool) -> anyhow::Result<()> { let version = self.get_current_version()?; let updated = if pre_release { - version.try_bump_prerelease()? + if version.pre.is_empty() { + let patch_updated = version.try_bump_patch_without_pre()?; + patch_updated.set_initial_release_candidate()? + } else { + version.try_bump_prerelease()? + } } else { version.try_bump_patch_without_pre()? }; diff --git a/tools/internal/sdk-version-bump/src/main.rs b/tools/internal/sdk-version-bump/src/main.rs index 85c82c1d3c..ae6590e03e 100644 --- a/tools/internal/sdk-version-bump/src/main.rs +++ b/tools/internal/sdk-version-bump/src/main.rs @@ -170,7 +170,7 @@ fn initialise_internal_packages>(root: P) -> InternalPackages { packages.register_cargo("wasm/mix-fetch"); packages.register_cargo("wasm/client"); packages.register_cargo("wasm/node-tester"); - packages.register_cargo("wasm/full-nym-wasm"); + // packages.register_cargo("wasm/full-nym-wasm"); packages.register_cargo("nym-browser-extension/storage"); // js packages that will have their package.json modified @@ -196,6 +196,16 @@ fn initialise_internal_packages>(root: P) -> InternalPackages { packages.register_json("sdk/typescript/codegen/contract-clients"); // dependencies that will have their versions adjusted in the above packages + + // WASM NodeJS + packages.register_known_js_dependency("@nymproject/nym-client-wasm-node"); + packages.register_known_js_dependency("@nymproject/mix-fetch-wasm-node"); + + // WASM + packages.register_known_js_dependency("@nymproject/nym-node-tester-wasm"); + packages.register_known_js_dependency("@nymproject/nym-client-wasm"); + packages.register_known_js_dependency("@nymproject/mix-fetch-wasm"); + packages.register_known_js_dependency("@nymproject/mix-fetch"); packages.register_known_js_dependency("@nymproject/mix-fetch-full-fat"); packages.register_known_js_dependency("@nymproject/mui-theme"); diff --git a/tools/nymvisor/src/upgrades/http_upstream.rs b/tools/nymvisor/src/upgrades/http_upstream.rs new file mode 100644 index 0000000000..38dc36ebc3 --- /dev/null +++ b/tools/nymvisor/src/upgrades/http_upstream.rs @@ -0,0 +1,2 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 diff --git a/wasm/client/Cargo.toml b/wasm/client/Cargo.toml index 8651e223d5..a50f7b8bd8 100644 --- a/wasm/client/Cargo.toml +++ b/wasm/client/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-client-wasm" authors = ["Dave Hrycyszyn ", "Jedrzej Stuczynski "] -version = "1.2.1" +version = "1.2.4-rc.0" edition = "2021" keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"] license = "Apache-2.0" @@ -25,6 +25,7 @@ wasm-bindgen-futures = { workspace = true } thiserror = { workspace = true } tsify = { workspace = true, features = ["js"] } +nym-bin-common = { path = "../../common/bin-common" } wasm-client-core = { path = "../../common/wasm/client-core" } wasm-utils = { path = "../../common/wasm/utils" } diff --git a/wasm/client/src/client.rs b/wasm/client/src/client.rs index 7586281e23..0db708d074 100644 --- a/wasm/client/src/client.rs +++ b/wasm/client/src/client.rs @@ -63,6 +63,7 @@ pub struct NymClient { #[wasm_bindgen] pub struct NymClientBuilder { config: ClientConfig, + force_tls: bool, custom_topology: Option, preferred_gateway: Option, @@ -72,15 +73,16 @@ pub struct NymClientBuilder { #[wasm_bindgen] impl NymClientBuilder { - #[wasm_bindgen(constructor)] - pub fn new( + fn new( config: ClientConfig, on_message: js_sys::Function, + force_tls: bool, preferred_gateway: Option, storage_passphrase: Option, ) -> Self { NymClientBuilder { config, + force_tls, custom_topology: None, storage_passphrase, on_message, @@ -109,6 +111,7 @@ impl NymClientBuilder { Ok(NymClientBuilder { config: full_config, + force_tls: false, custom_topology: Some(topology.try_into()?), on_message, storage_passphrase: None, @@ -149,9 +152,15 @@ impl NymClientBuilder { // if we provided hardcoded topology, get gateway from it, otherwise get it the 'standard' way let init_res = if let Some(topology) = &self.custom_topology { - setup_from_topology(user_chosen, false, topology, &client_store).await? + setup_from_topology(user_chosen, self.force_tls, topology, &client_store).await? } else { - setup_gateway_from_api(&client_store, false, user_chosen, &nym_api_endpoints).await? + setup_gateway_from_api( + &client_store, + self.force_tls, + user_chosen, + &nym_api_endpoints, + ) + .await? }; let packet_type = self.config.base.debug.traffic.packet_type; @@ -205,6 +214,9 @@ pub struct ClientOptsSimple { #[tsify(optional)] pub(crate) storage_passphrase: Option, + + #[tsify(optional)] + pub(crate) force_tls: Option, } #[derive(Tsify, Debug, Default, Clone, Serialize, Deserialize)] @@ -249,9 +261,16 @@ impl NymClient { if let Some(opts) = opts { let preferred_gateway = opts.preferred_gateway; let storage_passphrase = opts.storage_passphrase; - NymClientBuilder::new(config, on_message, preferred_gateway, storage_passphrase) + let force_tls = opts.force_tls.unwrap_or_default(); + NymClientBuilder::new( + config, + on_message, + force_tls, + preferred_gateway, + storage_passphrase, + ) } else { - NymClientBuilder::new(config, on_message, None, None) + NymClientBuilder::new(config, on_message, false, None, None) } .start_client_async() .await diff --git a/wasm/client/src/lib.rs b/wasm/client/src/lib.rs index aed1179aaa..96f671e29a 100644 --- a/wasm/client/src/lib.rs +++ b/wasm/client/src/lib.rs @@ -16,3 +16,16 @@ mod response_pusher; #[cfg(target_arch = "wasm32")] pub use wasm_client_core::set_panic_hook; + +#[cfg(target_arch = "wasm32")] +use wasm_bindgen::prelude::*; + +#[wasm_bindgen(start)] +#[cfg(target_arch = "wasm32")] +pub fn main() { + wasm_utils::console_log!("[rust main]: rust module loaded"); + wasm_utils::console_log!( + "wasm client version used: {:#?}", + nym_bin_common::bin_info!() + ); +} diff --git a/wasm/full-nym-wasm/Cargo.toml b/wasm/full-nym-wasm/Cargo.toml index 0902eb625c..9ad01b8a17 100644 --- a/wasm/full-nym-wasm/Cargo.toml +++ b/wasm/full-nym-wasm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-wasm-sdk" authors = ["Jedrzej Stuczynski "] -version = "1.2.1" +version = "1.2.2" edition = "2021" keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"] license = "Apache-2.0" diff --git a/wasm/mix-fetch/Cargo.toml b/wasm/mix-fetch/Cargo.toml index 3416758a3a..7654e37e7a 100644 --- a/wasm/mix-fetch/Cargo.toml +++ b/wasm/mix-fetch/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "mix-fetch-wasm" authors = ["Jedrzej Stuczynski "] -version = "1.2.1" +version = "1.2.4-rc.0" edition = "2021" keywords = ["nym", "fetch", "wasm", "webassembly", "privacy"] license = "Apache-2.0" @@ -27,6 +27,7 @@ wasm-bindgen-futures = { workspace = true } thiserror = { workspace = true } tsify = { workspace = true, features = ["js"] } +nym-bin-common = { path = "../../common/bin-common" } http-api-client = { path = "../../common/http-api-client" } nym-socks5-requests = { path = "../../common/socks5/requests" } nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" } diff --git a/wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go b/wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go index 19f7b94594..cdd2638cf1 100644 --- a/wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go +++ b/wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go @@ -8,74 +8,12 @@ package main import ( "go-mix-conn/internal/bridge/go_bridge" "go-mix-conn/internal/state" - "syscall/js" ) var done chan struct{} func init() { println("[go init]: go module init") - - q := js.Global().Get("location") - if q.IsUndefined() { - println("location undefined") - } else { - println("location ok") - } - a := js.Global().Get("Error") - if a.IsUndefined() { - println("Error undefined") - } else { - println("Error ok") - } - b := js.Global().Get("Promise") - if b.IsUndefined() { - println("Promise undefined") - } else { - println("Promise ok") - } - c := js.Global().Get("Reflect") - if c.IsUndefined() { - println("Reflect undefined") - } else { - println("Reflect ok") - } - d := js.Global().Get("Object") - if d.IsUndefined() { - println("Object undefined") - } else { - println("Object ok") - } - e := js.Global().Get("Response") - if e.IsUndefined() { - println("Response undefined") - } else { - println("Response ok") - } - f := js.Global().Get("Request") - if f.IsUndefined() { - println("Request undefined") - } else { - println("Request ok") - } - g := js.Global().Get("Proxy") - if g.IsUndefined() { - println("Proxy undefined") - } else { - println("Proxy ok") - } - h := js.Global().Get("Headers") - if h.IsUndefined() { - println("Headers undefined") - } else { - println("Headers ok") - } - i := js.Global().Get("Uint8Array") - if i.IsUndefined() { - println("Uint8Array undefined") - } else { - println("Uint8Array ok") - } done = make(chan struct{}) state.InitialiseGlobalState() diff --git a/wasm/mix-fetch/internal-dev/worker.js b/wasm/mix-fetch/internal-dev/worker.js index 57fbcf1161..d6b42657b2 100644 --- a/wasm/mix-fetch/internal-dev/worker.js +++ b/wasm/mix-fetch/internal-dev/worker.js @@ -160,18 +160,6 @@ async function nativeSetup() { requestTimeoutMs: 10000 } - const extra = { - hiddenGateways: [ - { - owner: "LoveIslandEnjoyer", - host: "gateway1.nymtech.net", - explicitIp: "213.219.38.119", - identityKey: "E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM", - sphinxKey: "CYcrjoJ8GT7Dp54zViUyyRUfegeRCyPifWQZHRgMZrfX" - } - ] - } - await setupMixFetch({ // preferredNetworkRequester, preferredGateway: "E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM", @@ -181,7 +169,6 @@ async function nativeSetup() { clientId: "my-client", clientOverride: noCoverTrafficOverride, mixFetchOverride, - extra }) } diff --git a/wasm/mix-fetch/src/lib.rs b/wasm/mix-fetch/src/lib.rs index 1f3f62111b..45eca23467 100644 --- a/wasm/mix-fetch/src/lib.rs +++ b/wasm/mix-fetch/src/lib.rs @@ -30,5 +30,6 @@ use wasm_bindgen::prelude::*; #[wasm_bindgen(start)] #[cfg(target_arch = "wasm32")] pub fn main() { - wasm_utils::console_log!("[rust main]: rust module loaded") + wasm_utils::console_log!("[rust main]: rust module loaded"); + wasm_utils::console_log!("mix fetch version used: {:#?}", nym_bin_common::bin_info!()); } diff --git a/wasm/node-tester/Cargo.toml b/wasm/node-tester/Cargo.toml index 0397d64349..b88e68d2aa 100644 --- a/wasm/node-tester/Cargo.toml +++ b/wasm/node-tester/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-node-tester-wasm" authors = ["Jedrzej Stuczynski "] -version = "1.2.1" +version = "1.2.4-rc.0" edition = "2021" keywords = ["nym", "sphinx", "webassembly", "privacy", "tester"] license = "Apache-2.0" diff --git a/yarn.lock b/yarn.lock index 1602bf8355..16e582e01f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -83,27 +83,6 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/core@^7.11.6": - version "7.23.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.2.tgz#ed10df0d580fff67c5f3ee70fd22e2e4c90a9f94" - integrity sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.22.13" - "@babel/generator" "^7.23.0" - "@babel/helper-compilation-targets" "^7.22.15" - "@babel/helper-module-transforms" "^7.23.0" - "@babel/helpers" "^7.23.2" - "@babel/parser" "^7.23.0" - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.2" - "@babel/types" "^7.23.0" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - "@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.22.15", "@babel/generator@^7.23.0", "@babel/generator@^7.7.2": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" @@ -322,7 +301,7 @@ "@babel/traverse" "^7.23.0" "@babel/types" "^7.23.0" -"@babel/helpers@^7.22.15", "@babel/helpers@^7.23.2": +"@babel/helpers@^7.22.15": version "7.23.2" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.2.tgz#2832549a6e37d484286e15ba36a5330483cac767" integrity sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ== @@ -546,7 +525,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-jsx@^7.22.5", "@babel/plugin-syntax-jsx@^7.7.2": +"@babel/plugin-syntax-jsx@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918" integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg== @@ -1941,18 +1920,6 @@ jest-util "^27.5.1" slash "^3.0.0" -"@jest/console@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" - integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - "@jest/core@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626" @@ -1987,40 +1954,6 @@ slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/core@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" - integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== - dependencies: - "@jest/console" "^29.7.0" - "@jest/reporters" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.7.0" - jest-config "^29.7.0" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-resolve-dependencies "^29.7.0" - jest-runner "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - jest-watcher "^29.7.0" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - "@jest/environment@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74" @@ -2031,16 +1964,6 @@ "@types/node" "*" jest-mock "^27.5.1" -"@jest/environment@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" - integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== - dependencies: - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - "@jest/expect-utils@^28.1.3": version "28.1.3" resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.3.tgz#58561ce5db7cd253a7edddbc051fb39dda50f525" @@ -2055,14 +1978,6 @@ dependencies: jest-get-type "^29.6.3" -"@jest/expect@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" - integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== - dependencies: - expect "^29.7.0" - jest-snapshot "^29.7.0" - "@jest/fake-timers@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" @@ -2075,18 +1990,6 @@ jest-mock "^27.5.1" jest-util "^27.5.1" -"@jest/fake-timers@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" - integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== - dependencies: - "@jest/types" "^29.6.3" - "@sinonjs/fake-timers" "^10.0.2" - "@types/node" "*" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-util "^29.7.0" - "@jest/globals@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b" @@ -2096,16 +1999,6 @@ "@jest/types" "^27.5.1" expect "^27.5.1" -"@jest/globals@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" - integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/types" "^29.6.3" - jest-mock "^29.7.0" - "@jest/reporters@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04" @@ -2137,36 +2030,6 @@ terminal-link "^2.0.0" v8-to-istanbul "^8.1.0" -"@jest/reporters@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" - integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^6.0.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - jest-worker "^29.7.0" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" - "@jest/schemas@^28.1.3": version "28.1.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-28.1.3.tgz#ad8b86a66f11f33619e3d7e1dcddd7f2d40ff905" @@ -2190,15 +2053,6 @@ graceful-fs "^4.2.9" source-map "^0.6.0" -"@jest/source-map@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" - integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== - dependencies: - "@jridgewell/trace-mapping" "^0.3.18" - callsites "^3.0.0" - graceful-fs "^4.2.9" - "@jest/test-result@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb" @@ -2209,16 +2063,6 @@ "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-result@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" - integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== - dependencies: - "@jest/console" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - "@jest/test-sequencer@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b" @@ -2229,16 +2073,6 @@ jest-haste-map "^27.5.1" jest-runtime "^27.5.1" -"@jest/test-sequencer@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" - integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== - dependencies: - "@jest/test-result" "^29.7.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - slash "^3.0.0" - "@jest/transform@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" @@ -2281,27 +2115,6 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" -"@jest/transform@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" - integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.2" - "@jest/types@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" @@ -2396,14 +2209,6 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@jridgewell/trace-mapping@^0.3.18": - version "0.3.20" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" - integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" @@ -2891,10 +2696,10 @@ resolved "https://registry.yarnpkg.com/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-16.10.0.tgz#7410a51d0f8be631eec9552f01b2e5946285927c" integrity sha512-5iV2NKZnzxJwZZ4DM5JVbRG/nkhAbzEskKaLBB82PmYGKzaDHuMHP1lcPoD/rtYMlowZgNA/RQndfKvPBPwmXA== -"@nymproject/node-tester@^1.0.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@nymproject/node-tester/-/node-tester-1.2.0.tgz#c611c1f3455787cd464ccc09b0f10ed98f6c30e9" - integrity sha512-QR6zHt/FytEMQCLnRt4wHrBqd/hRQjk43/whTn8mgNbzNdSjGNe0IomR2Iz45ZW+ei0k4Z5FgHEK4GhllJULiQ== +"@nymproject/node-tester@^1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@nymproject/node-tester/-/node-tester-1.2.3.tgz#79fbde8b69e2d1180eed897557c4610a1aa1038f" + integrity sha512-VDFdH2ddIcXXamwkMbeHA88Xa/S2iPWh9QxkFggppvHS1d6gmnNHAZxXm3Uuhx7pCpzKldA0OT7qohMg9GW9xg== "@nymproject/nym-validator-client@^0.18.0": version "0.18.0" @@ -3145,22 +2950,6 @@ is-module "^1.0.0" resolve "^1.22.1" -"@rollup/plugin-replace@^5.0.2": - version "5.0.4" - resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-5.0.4.tgz#fef548dc751d06747e8dca5b0e8e1fbf647ac7e1" - integrity sha512-E2hmRnlh09K8HGT0rOnnri9OTh+BILGr7NVJGB30S4E3cLRn3J0xjdiyOZ74adPs4NiAMgrjUMGAZNJDBgsdmQ== - dependencies: - "@rollup/pluginutils" "^5.0.1" - magic-string "^0.30.3" - -"@rollup/plugin-typescript@^10.0.1": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-10.0.1.tgz#270b515b116ea28320e6bb62451c4767d49072d6" - integrity sha512-wBykxRLlX7EzL8BmUqMqk5zpx2onnmRMSw/l9M1sVfkJvdwfxogZQVNUM9gVMJbjRLDR5H6U0OMOrlDGmIV45A== - dependencies: - "@rollup/pluginutils" "^5.0.1" - resolve "^1.22.1" - "@rollup/plugin-typescript@^11.0.0": version "11.1.5" resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-11.1.5.tgz#039c763bf943a5921f3f42be255895e75764cb91" @@ -3169,31 +2958,6 @@ "@rollup/pluginutils" "^5.0.1" resolve "^1.22.1" -"@rollup/plugin-url@^8.0.1": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@rollup/plugin-url/-/plugin-url-8.0.2.tgz#aab4e209e9e012f65582bd99eb80b3bbdfe15afb" - integrity sha512-5yW2LP5NBEgkvIRSSEdJkmxe5cUNZKG3eenKtfJvSkxVm/xTTu7w+ayBtNwhozl1ZnTUCU0xFaRQR+cBl2H7TQ== - dependencies: - "@rollup/pluginutils" "^5.0.1" - make-dir "^3.1.0" - mime "^3.0.0" - -"@rollup/plugin-wasm@^6.1.1": - version "6.2.2" - resolved "https://registry.yarnpkg.com/@rollup/plugin-wasm/-/plugin-wasm-6.2.2.tgz#ea75fd8cc5ddba1e30bdc22e07cdbaf8d6d160bf" - integrity sha512-gpC4R1G9Ni92ZIRTexqbhX7U+9estZrbhP+9SRb0DW9xpB9g7j34r+J2hqrcW/lRI7dJaU84MxZM0Rt82tqYPQ== - dependencies: - "@rollup/pluginutils" "^5.0.2" - -"@rollup/pluginutils@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" - integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== - dependencies: - "@types/estree" "0.0.39" - estree-walker "^1.0.1" - picomatch "^2.2.2" - "@rollup/pluginutils@^5.0.1": version "5.0.4" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.4.tgz#74f808f9053d33bafec0cc98e7b835c9667d32ba" @@ -3203,15 +2967,6 @@ estree-walker "^2.0.2" picomatch "^2.3.1" -"@rollup/pluginutils@^5.0.2": - version "5.0.5" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.5.tgz#bbb4c175e19ebfeeb8c132c2eea0ecb89941a66c" - integrity sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q== - dependencies: - "@types/estree" "^1.0.0" - estree-walker "^2.0.2" - picomatch "^2.3.1" - "@sapphire/utilities@^3.11.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@sapphire/utilities/-/utilities-3.13.0.tgz#04fd73281ad4cd63c2c87ffbac3faa393d77cf95" @@ -3355,20 +3110,6 @@ dependencies: type-detect "4.0.8" -"@sinonjs/commons@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" - integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^10.0.2": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== - dependencies: - "@sinonjs/commons" "^3.0.0" - "@sinonjs/fake-timers@^8.0.1": version "8.1.0" resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7" @@ -4904,11 +4645,6 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.2.tgz#ff02bc3dc8317cd668dfec247b750ba1f1d62453" integrity sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA== -"@types/estree@0.0.39": - version "0.0.39" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" - integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== - "@types/estree@^0.0.51": version "0.0.51" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" @@ -4974,13 +4710,6 @@ dependencies: "@types/node" "*" -"@types/graceful-fs@^4.1.3": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.8.tgz#417e461e4dc79d957dc3107f45fe4973b09c2915" - integrity sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw== - dependencies: - "@types/node" "*" - "@types/hast@^2.0.0": version "2.3.6" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.6.tgz#bb8b05602112a26d22868acb70c4b20984ec7086" @@ -6040,11 +5769,6 @@ ansi-regex@^6.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== -ansi-sequence-parser@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf" - integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg== - ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -6469,19 +6193,6 @@ babel-jest@^27.5.1: graceful-fs "^4.2.9" slash "^3.0.0" -babel-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" - integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== - dependencies: - "@jest/transform" "^29.7.0" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.6.3" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - babel-loader@^8.0.0, babel-loader@^8.2.3, babel-loader@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.3.0.tgz#124936e841ba4fe8176786d6ff28add1f134d6a8" @@ -6533,16 +6244,6 @@ babel-plugin-jest-hoist@^27.5.1: "@types/babel__core" "^7.0.0" "@types/babel__traverse" "^7.0.6" -babel-plugin-jest-hoist@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" - integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - babel-plugin-macros@^3.0.1, babel-plugin-macros@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" @@ -6638,14 +6339,6 @@ babel-preset-jest@^27.5.1: babel-plugin-jest-hoist "^27.5.1" babel-preset-current-node-syntax "^1.0.0" -babel-preset-jest@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" - integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== - dependencies: - babel-plugin-jest-hoist "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - bail@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" @@ -6668,11 +6361,6 @@ base-x@^3.0.2, base-x@^3.0.6: dependencies: safe-buffer "^5.0.1" -base64-arraybuffer-es6@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/base64-arraybuffer-es6/-/base64-arraybuffer-es6-0.7.0.tgz#dbe1e6c87b1bf1ca2875904461a7de40f21abc86" - integrity sha512-ESyU/U1CFZDJUdr+neHRhNozeCv72Y7Vm0m1DCbjX3KBjT6eYocvAJlSk6+8+HkVwXlT1FNxhGW6q3UKAlCvvw== - base64-js@^1.0.2, base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -7436,17 +7124,6 @@ cli-boxes@^2.2.1: resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== -cli-color@~2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-2.0.3.tgz#73769ba969080629670f3f2ef69a4bf4e7cc1879" - integrity sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ== - dependencies: - d "^1.0.1" - es5-ext "^0.10.61" - es6-iterator "^2.0.3" - memoizee "^0.4.15" - timers-ext "^0.1.7" - cli-cursor@3.1.0, cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -7667,11 +7344,6 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -comlink@^4.3.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.4.1.tgz#e568b8e86410b809e8600eb2cf40c189371ef981" - integrity sha512-+1dlx0aY5Jo1vHy/tSsIGpSkN4tS9rZSW8FIhG0JH/crs9wwweswIo/POr451r7bZww3hFbPAKnTpimzL/mm4Q== - comma-separated-tokens@^1.0.0: version "1.0.8" resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" @@ -7712,11 +7384,6 @@ commander@^9.4.1: resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== -commander@~9.4.0: - version "9.4.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" - integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== - common-path-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" @@ -7900,11 +7567,6 @@ convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -8065,19 +7727,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" -create-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" - integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-config "^29.7.0" - jest-util "^29.7.0" - prompts "^2.0.1" - create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -8470,14 +8119,6 @@ d3-zoom@^2.0.0: d3-selection "2" d3-transition "2" -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - damerau-levenshtein@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" @@ -8488,11 +8129,6 @@ dargs@^7.0.0: resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== -data-uri-to-buffer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" - integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== - data-urls@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" @@ -8587,11 +8223,6 @@ dedent@0.7.0, dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== -dedent@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" - integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== - deep-equal@^2.0.5: version "2.2.2" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.2.tgz#9b2635da569a13ba8e1cc159c2f744071b115daa" @@ -8942,13 +8573,6 @@ domelementtype@^2.0.1, domelementtype@^2.2.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== -domexception@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" - integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== - dependencies: - webidl-conversions "^4.0.2" - domexception@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" @@ -9071,11 +8695,6 @@ elliptic@^6.5.3, elliptic@^6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - emittery@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" @@ -9322,52 +8941,16 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: - version "0.10.62" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" - integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== - dependencies: - es6-iterator "^2.0.3" - es6-symbol "^3.1.3" - next-tick "^1.1.0" - es5-shim@^4.5.13: version "4.6.7" resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.6.7.tgz#bc67ae0fc3dd520636e0a1601cc73b450ad3e955" integrity sha512-jg21/dmlrNQI7JyyA2w7n+yifSxBng0ZralnSfVZjoCawgNTCnS+yBCyVM9DL5itm7SUnDGgv7hcq2XCZX4iRQ== -es6-iterator@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - es6-shim@^0.35.5: version "0.35.8" resolved "https://registry.yarnpkg.com/es6-shim/-/es6-shim-0.35.8.tgz#89216f6fbf8bacba3f897c8c0e814d2a41c05fb7" integrity sha512-Twf7I2v4/1tLoIXMT8HlqaBSS5H2wQTs2wx3MNYCI8K1R1/clXyCazrcVCPm/FuO9cyV8+leEaZOWD5C253NDg== -es6-symbol@^3.1.1, es6-symbol@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== - dependencies: - d "^1.0.1" - ext "^1.1.2" - -es6-weak-map@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" - integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== - dependencies: - d "1" - es5-ext "^0.10.46" - es6-iterator "^2.0.3" - es6-symbol "^3.1.1" - escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -9803,11 +9386,6 @@ estree-walker@^0.6.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== -estree-walker@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" - integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== - estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" @@ -9830,14 +9408,6 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -event-emitter@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== - dependencies: - d "1" - es5-ext "~0.10.14" - eventemitter3@^4.0.0, eventemitter3@^4.0.1, eventemitter3@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -9948,7 +9518,7 @@ expect@^28.1.3: jest-message-util "^28.1.3" jest-util "^28.1.3" -expect@^29.0.0, expect@^29.7.0: +expect@^29.0.0: version "29.7.0" resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== @@ -10001,13 +9571,6 @@ express@^4.17.1, express@^4.17.3, express@^4.18.2: utils-merge "1.0.1" vary "~1.1.2" -ext@^1.1.2: - version "1.7.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" - integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== - dependencies: - type "^2.7.2" - extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -10051,18 +9614,6 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -fake-indexeddb@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-4.0.2.tgz#e7a884158fa576e00f03e973b9874619947013e4" - integrity sha512-SdTwEhnakbgazc7W3WUXOJfGmhH0YfG4d+dRPOFoYDRTL6U5t8tvrmkf2W/C3W1jk2ylV7Wrnj44RASqpX/lEw== - dependencies: - realistic-structured-clone "^3.0.0" - -fake-indexeddb@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-5.0.0.tgz#c9f394d6d36db62760ad596ebec97ba3d700c95b" - integrity sha512-hGMsl73XgJAk5OtC8hFDSLUVzJ3Z1/C06YpFwI7DzCsEsmH5Mvkxplv3PK6uUL7XCYVBTzayp/4gD+cp7Qi8xQ== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -10111,7 +9662,7 @@ fast-json-parse@^1.0.3: resolved "https://registry.yarnpkg.com/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" integrity sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw== -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -10181,14 +9732,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -fetch-blob@^3.1.2, fetch-blob@^3.1.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" - integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== - dependencies: - node-domexception "^1.0.0" - web-streams-polyfill "^3.0.3" - fetch-retry@^5.0.2: version "5.0.6" resolved "https://registry.yarnpkg.com/fetch-retry/-/fetch-retry-5.0.6.tgz#17d0bc90423405b7a88b74355bf364acd2a7fa56" @@ -10266,7 +9809,7 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.2.0, finalhandler@~1.2.0: +finalhandler@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== @@ -10475,13 +10018,6 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -formdata-polyfill@^4.0.10: - version "4.0.10" - resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" - integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== - dependencies: - fetch-blob "^3.1.2" - forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -12060,11 +11596,6 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-promise@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" - integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== - is-reference@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" @@ -12277,17 +11808,6 @@ istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: istanbul-lib-coverage "^3.2.0" semver "^6.3.0" -istanbul-lib-instrument@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz#71e87707e8041428732518c6fb5211761753fbdf" - integrity sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^7.5.4" - istanbul-lib-report@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" @@ -12371,15 +11891,6 @@ jest-changed-files@^27.5.1: execa "^5.0.0" throat "^6.0.1" -jest-changed-files@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" - integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== - dependencies: - execa "^5.0.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - jest-circus@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc" @@ -12405,32 +11916,6 @@ jest-circus@^27.5.1: stack-utils "^2.0.3" throat "^6.0.1" -jest-circus@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" - integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^1.0.0" - is-generator-fn "^2.0.0" - jest-each "^29.7.0" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - pretty-format "^29.7.0" - pure-rand "^6.0.0" - slash "^3.0.0" - stack-utils "^2.0.3" - jest-cli@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145" @@ -12449,23 +11934,6 @@ jest-cli@^27.5.1: prompts "^2.0.1" yargs "^16.2.0" -jest-cli@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" - integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== - dependencies: - "@jest/core" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - chalk "^4.0.0" - create-jest "^29.7.0" - exit "^0.1.2" - import-local "^3.0.2" - jest-config "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - yargs "^17.3.1" - jest-config@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41" @@ -12496,34 +11964,6 @@ jest-config@^27.5.1: slash "^3.0.0" strip-json-comments "^3.1.1" -jest-config@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" - integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.7.0" - "@jest/types" "^29.6.3" - babel-jest "^29.7.0" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.7.0" - jest-environment-node "^29.7.0" - jest-get-type "^29.6.3" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-runner "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-json-comments "^3.1.1" - "jest-diff@>=29.4.3 < 30", jest-diff@^29.4.1, jest-diff@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" @@ -12561,13 +12001,6 @@ jest-docblock@^27.5.1: dependencies: detect-newline "^3.0.0" -jest-docblock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" - integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== - dependencies: - detect-newline "^3.0.0" - jest-each@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e" @@ -12579,17 +12012,6 @@ jest-each@^27.5.1: jest-util "^27.5.1" pretty-format "^27.5.1" -jest-each@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" - integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - jest-get-type "^29.6.3" - jest-util "^29.7.0" - pretty-format "^29.7.0" - jest-environment-jsdom@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546" @@ -12615,18 +12037,6 @@ jest-environment-node@^27.5.1: jest-mock "^27.5.1" jest-util "^27.5.1" -jest-environment-node@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" - integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - jest-util "^29.7.0" - jest-get-type@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" @@ -12683,25 +12093,6 @@ jest-haste-map@^27.5.1: optionalDependencies: fsevents "^2.3.2" -jest-haste-map@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" - integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== - dependencies: - "@jest/types" "^29.6.3" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - jest-worker "^29.7.0" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - jest-jasmine2@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" @@ -12733,14 +12124,6 @@ jest-leak-detector@^27.5.1: jest-get-type "^27.5.1" pretty-format "^27.5.1" -jest-leak-detector@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" - integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== - dependencies: - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" @@ -12824,15 +12207,6 @@ jest-mock@^27.0.6, jest-mock@^27.5.1: "@jest/types" "^27.5.1" "@types/node" "*" -jest-mock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" - integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-util "^29.7.0" - jest-pnp-resolver@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" @@ -12848,11 +12222,6 @@ jest-regex-util@^27.5.1: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== -jest-regex-util@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" - integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== - jest-resolve-dependencies@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" @@ -12862,14 +12231,6 @@ jest-resolve-dependencies@^27.5.1: jest-regex-util "^27.5.1" jest-snapshot "^27.5.1" -jest-resolve-dependencies@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" - integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== - dependencies: - jest-regex-util "^29.6.3" - jest-snapshot "^29.7.0" - jest-resolve@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384" @@ -12886,21 +12247,6 @@ jest-resolve@^27.5.1: resolve.exports "^1.1.0" slash "^3.0.0" -jest-resolve@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" - integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-pnp-resolver "^1.2.2" - jest-util "^29.7.0" - jest-validate "^29.7.0" - resolve "^1.20.0" - resolve.exports "^2.0.0" - slash "^3.0.0" - jest-runner@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5" @@ -12928,33 +12274,6 @@ jest-runner@^27.5.1: source-map-support "^0.5.6" throat "^6.0.1" -jest-runner@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" - integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== - dependencies: - "@jest/console" "^29.7.0" - "@jest/environment" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.7.0" - jest-environment-node "^29.7.0" - jest-haste-map "^29.7.0" - jest-leak-detector "^29.7.0" - jest-message-util "^29.7.0" - jest-resolve "^29.7.0" - jest-runtime "^29.7.0" - jest-util "^29.7.0" - jest-watcher "^29.7.0" - jest-worker "^29.7.0" - p-limit "^3.1.0" - source-map-support "0.5.13" - jest-runtime@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af" @@ -12983,34 +12302,6 @@ jest-runtime@^27.5.1: slash "^3.0.0" strip-bom "^4.0.0" -jest-runtime@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" - integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/globals" "^29.7.0" - "@jest/source-map" "^29.6.3" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - strip-bom "^4.0.0" - jest-serializer@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" @@ -13055,32 +12346,6 @@ jest-snapshot@^27.5.1: pretty-format "^27.5.1" semver "^7.3.2" -jest-snapshot@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" - integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.7.0" - graceful-fs "^4.2.9" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - natural-compare "^1.4.0" - pretty-format "^29.7.0" - semver "^7.5.3" - jest-util@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" @@ -13117,7 +12382,7 @@ jest-util@^28.1.3: graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-util@^29.0.0, jest-util@^29.7.0: +jest-util@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== @@ -13141,18 +12406,6 @@ jest-validate@^27.5.1: leven "^3.1.0" pretty-format "^27.5.1" -jest-validate@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" - integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== - dependencies: - "@jest/types" "^29.6.3" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.6.3" - leven "^3.1.0" - pretty-format "^29.7.0" - jest-watcher@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2" @@ -13166,20 +12419,6 @@ jest-watcher@^27.5.1: jest-util "^27.5.1" string-length "^4.0.1" -jest-watcher@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" - integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== - dependencies: - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.7.0" - string-length "^4.0.1" - jest-worker@^26.5.0, jest-worker@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" @@ -13198,16 +12437,6 @@ jest-worker@^27.0.2, jest-worker@^27.4.5, jest-worker@^27.5.1: merge-stream "^2.0.0" supports-color "^8.0.0" -jest-worker@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" - integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== - dependencies: - "@types/node" "*" - jest-util "^29.7.0" - merge-stream "^2.0.0" - supports-color "^8.0.0" - jest@^27.1.0: version "27.5.1" resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc" @@ -13217,16 +12446,6 @@ jest@^27.1.0: import-local "^3.0.2" jest-cli "^27.5.1" -jest@^29.5.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" - integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== - dependencies: - "@jest/core" "^29.7.0" - "@jest/types" "^29.6.3" - import-local "^3.0.2" - jest-cli "^29.7.0" - joi@^17.11.0: version "17.11.0" resolved "https://registry.yarnpkg.com/joi/-/joi-17.11.0.tgz#aa9da753578ec7720e6f0ca2c7046996ed04fc1a" @@ -13363,7 +12582,7 @@ json5@^1.0.1, json5@^1.0.2: dependencies: minimist "^1.2.0" -jsonc-parser@3.2.0, jsonc-parser@^3.0.0, jsonc-parser@^3.2.0: +jsonc-parser@3.2.0, jsonc-parser@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== @@ -13914,13 +13133,6 @@ lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.1.tgz#0a3be479df549cca0e5d693ac402ff19537a6b7a" integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g== -lru-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" - integrity sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ== - dependencies: - es5-ext "~0.10.2" - lunr@^2.3.9: version "2.3.9" resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" @@ -13936,13 +13148,6 @@ lz-string@^1.5.0: resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== -magic-string@0.25.2: - version "0.25.2" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.2.tgz#139c3a729515ec55e96e69e82a11fe890a293ad9" - integrity sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg== - dependencies: - sourcemap-codec "^1.4.4" - magic-string@^0.25.3: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -13964,13 +13169,6 @@ magic-string@^0.30.2: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" -magic-string@^0.30.3: - version "0.30.5" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9" - integrity sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.15" - make-dir@4.0.0, make-dir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" @@ -14070,7 +13268,7 @@ markdown-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/markdown-extensions/-/markdown-extensions-1.1.1.tgz#fea03b539faeaee9b4ef02a3769b455b189f7fc3" integrity sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q== -marked@^4.0.16, marked@^4.3.0: +marked@^4.0.16: version "4.3.0" resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== @@ -14268,20 +13466,6 @@ memfs@^3.1.2, memfs@^3.2.2, memfs@^3.4.1, memfs@^3.4.3: dependencies: fs-monkey "^1.0.4" -memoizee@^0.4.15: - version "0.4.15" - resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72" - integrity sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ== - dependencies: - d "^1.0.1" - es5-ext "^0.10.53" - es6-weak-map "^2.0.3" - event-emitter "^0.3.5" - is-promise "^2.2.2" - lru-queue "^0.1.0" - next-tick "^1.1.0" - timers-ext "^0.1.7" - memoizerific@^1.11.3: version "1.11.3" resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" @@ -14713,11 +13897,6 @@ mime@^2.4.4: resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== -mime@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" - integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -14813,7 +13992,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6, minimist@~1.2.0: +minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -15108,11 +14287,6 @@ nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0: resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz#26c8a3cee6cc05fbcf1e333cd2fc3e003326c0b5" integrity sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw== -next-tick@1, next-tick@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" - integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== - nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -15160,11 +14334,6 @@ node-dir@^0.1.10: dependencies: minimatch "^3.0.2" -node-domexception@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" - integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== - node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -15179,15 +14348,6 @@ node-fetch@^2.6.1, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" - integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== - dependencies: - data-uri-to-buffer "^4.0.0" - fetch-blob "^3.1.4" - formdata-polyfill "^4.0.10" - node-forge@^1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -15259,22 +14419,6 @@ node-releases@^2.0.13: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== -nodemon@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.0.1.tgz#affe822a2c5f21354466b2fc8ae83277d27dadc7" - integrity sha512-g9AZ7HmkhQkqXkRc20w+ZfQ73cHLbE8hnPbtaFbFtCumZsjyMhKk9LajQ07U5Ux28lvFjZ5X7HvWR1xzU8jHVw== - dependencies: - chokidar "^3.5.2" - debug "^3.2.7" - ignore-by-default "^1.0.1" - minimatch "^3.1.2" - pstree.remy "^1.1.8" - semver "^7.5.3" - simple-update-notifier "^2.0.0" - supports-color "^5.5.0" - touch "^3.1.0" - undefsafe "^2.0.5" - nodemon@^2.0.21: version "2.0.22" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.22.tgz#182c45c3a78da486f673d6c1702e00728daf5258" @@ -15730,7 +14874,7 @@ open@^7.0.3: is-docker "^2.0.0" is-wsl "^2.1.1" -open@^8.0.0, open@^8.0.9, open@^8.4.0: +open@^8.0.9, open@^8.4.0: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== @@ -15781,13 +14925,6 @@ os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== -ospec@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/ospec/-/ospec-3.1.0.tgz#d36b8e10110f58f63a463df2390a7a73fe9579a8" - integrity sha512-+nGtjV3vlADp+UGfL51miAh/hB4awPBkQrArhcgG4trAaoA2gKt5bf9w0m9ch9zOr555cHWaCHZEDiBOkNZSxw== - dependencies: - glob "^7.1.3" - p-all@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-all/-/p-all-2.1.0.tgz#91419be56b7dee8fe4c5db875d55e0da084244a0" @@ -15833,7 +14970,7 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -16227,7 +15364,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.0, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.0, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -16934,11 +16071,6 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== -pure-rand@^6.0.0: - version "6.0.4" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" - integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== - qr.js@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f" @@ -17406,15 +16538,6 @@ readonly-date@^1.0.0: resolved "https://registry.yarnpkg.com/readonly-date/-/readonly-date-1.0.0.tgz#5af785464d8c7d7c40b9d738cbde8c646f97dcd9" integrity sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ== -realistic-structured-clone@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/realistic-structured-clone/-/realistic-structured-clone-3.0.0.tgz#7b518049ce2dad41ac32b421cd297075b00e3e35" - integrity sha512-rOjh4nuWkAqf9PWu6JVpOWD4ndI+JHfgiZeMmujYcPi+fvILUu7g6l26TC1K5aBIp34nV+jE1cDO75EKOfHC5Q== - dependencies: - domexception "^1.0.1" - typeson "^6.1.0" - typeson-registry "^1.0.0-alpha.20" - recharts-scale@^0.4.4: version "0.4.5" resolved "https://registry.yarnpkg.com/recharts-scale/-/recharts-scale-0.4.5.tgz#0969271f14e732e642fcc5bd4ab270d6e87dd1d9" @@ -17555,20 +16678,6 @@ relateurl@^0.2.7: resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== -reload@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/reload/-/reload-3.2.1.tgz#42d43e33e327efe1348c723272c6835fe333349a" - integrity sha512-ZdM8ZSEeI72zkhh6heMEvJ0vHZoovZXcJI6Zae8CzS7o5vO/WjZsAMMr0y1+3I/fCN7y7ZxABoUwwCswcLHkjQ== - dependencies: - cli-color "~2.0.0" - commander "~9.4.0" - finalhandler "~1.2.0" - minimist "~1.2.0" - open "^8.0.0" - serve-static "~1.15.0" - supervisor "~0.12.0" - ws "~8.11.0" - remark-external-links@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/remark-external-links/-/remark-external-links-8.0.0.tgz#308de69482958b5d1cd3692bc9b725ce0240f345" @@ -17765,11 +16874,6 @@ resolve.exports@^1.1.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.1.tgz#05cfd5b3edf641571fd46fa608b610dda9ead999" integrity sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ== -resolve.exports@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" - integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== - resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.3.2, resolve@^1.9.0: version "1.22.6" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.6.tgz#dd209739eca3aef739c626fea1b4f3c506195362" @@ -17850,13 +16954,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.2: hash-base "^3.0.0" inherits "^2.0.1" -rollup-plugin-base64@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-base64/-/rollup-plugin-base64-1.0.1.tgz#b3529b94d23baeb66e1e3bffd04477fa792985eb" - integrity sha512-IbdX8fjuXO/Op3hYmRPjVo0VwcSenwsQDaDTFdoe+70B5ZGoLMtr96L2yhHXCfxv7HwZVvxZqLsuWj6VwzRt3g== - dependencies: - "@rollup/pluginutils" "^3.1.0" - rollup-plugin-dts@^5.0.0, rollup-plugin-dts@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/rollup-plugin-dts/-/rollup-plugin-dts-5.3.1.tgz#c2841269a3a5cb986b7791b0328e6a178eba108f" @@ -17875,14 +16972,6 @@ rollup-plugin-inject@^3.0.0: magic-string "^0.25.3" rollup-pluginutils "^2.8.1" -rollup-plugin-modify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-modify/-/rollup-plugin-modify-3.0.0.tgz#5326e11dfec247e8bbdd9507f3da1da1e5c7818b" - integrity sha512-p/ffs0Y2jz2dEnWjq1oVC7SY37tuS+aP7whoNaQz1EAAOPg+k3vKJo8cMMWx6xpdd0NzhX4y2YF9o/NPu5YR0Q== - dependencies: - magic-string "0.25.2" - ospec "3.1.0" - rollup-plugin-node-polyfills@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz#53092a2744837164d5b8a28812ba5f3ff61109fd" @@ -17890,16 +16979,6 @@ rollup-plugin-node-polyfills@^0.2.1: dependencies: rollup-plugin-inject "^3.0.0" -rollup-plugin-polyfill@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-polyfill/-/rollup-plugin-polyfill-4.2.0.tgz#414c7ffca0557bf29a8f4e073b8eb7f4d02dac42" - integrity sha512-6eeOyn7nr2/xUOtB+MhydvqLrNKcSybGneOuWA+t8Q4rR9NQyeapzwuu5n6nX8OFfY1WI1sHconAofaC44IpuA== - -rollup-plugin-web-worker-loader@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-web-worker-loader/-/rollup-plugin-web-worker-loader-1.6.1.tgz#9d7a27575b64b0780fe4e8b3bc87470d217e485f" - integrity sha512-4QywQSz1NXFHKdyiou16mH3ijpcfLtLGOrAqvAqu1Gx+P8+zj+3gwC2BSL/VW1d+LW4nIHC8F7d7OXhs9UdR2A== - rollup-pluginutils@^2.8.1: version "2.8.2" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" @@ -17914,13 +16993,6 @@ rollup@^3.17.2, rollup@^3.2.1: optionalDependencies: fsevents "~2.3.2" -rollup@^3.9.1: - version "3.29.4" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" - integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw== - optionalDependencies: - fsevents "~2.3.2" - rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -18197,7 +17269,7 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.15.0, serve-static@~1.15.0: +serve-static@1.15.0: version "1.15.0" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== @@ -18327,16 +17399,6 @@ shiki@^0.10.1: vscode-oniguruma "^1.6.1" vscode-textmate "5.2.0" -shiki@^0.14.1: - version "0.14.5" - resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.5.tgz#375dd214e57eccb04f0daf35a32aa615861deb93" - integrity sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw== - dependencies: - ansi-sequence-parser "^1.1.0" - jsonc-parser "^3.2.0" - vscode-oniguruma "^1.7.0" - vscode-textmate "^8.0.0" - side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -18395,13 +17457,6 @@ simple-update-notifier@^1.0.7: dependencies: semver "~7.0.0" -simple-update-notifier@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" - integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== - dependencies: - semver "^7.5.3" - sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -18520,14 +17575,6 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -18556,7 +17603,7 @@ source-map@^0.7.0, source-map@^0.7.3: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== -sourcemap-codec@^1.4.4, sourcemap-codec@^1.4.8: +sourcemap-codec@^1.4.8: version "1.4.8" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== @@ -19015,11 +18062,6 @@ stylis@4.2.0: resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== -supervisor@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/supervisor/-/supervisor-0.12.0.tgz#de7e6337015b291851c10f3538c4a7f04917ecc1" - integrity sha512-iBYeU5Or4WiiIa3+ns1DpHIiHjNNXSuYUiixKcznewwo4ImBJ8EobktaAo2csOcauhrz4SvKRTou8Z2C3W28+A== - supports-color@8.1.1, supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -19342,14 +18384,6 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" -timers-ext@^0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" - integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== - dependencies: - es5-ext "~0.10.46" - next-tick "1" - tiny-case@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03" @@ -19526,20 +18560,6 @@ ts-jest@^27.0.5: semver "7.x" yargs-parser "20.x" -ts-jest@^29.1.0: - version "29.1.1" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.1.tgz#f58fe62c63caf7bfcc5cc6472082f79180f0815b" - integrity sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA== - dependencies: - bs-logger "0.x" - fast-json-stable-stringify "2.x" - jest-util "^29.0.0" - json5 "^2.2.3" - lodash.memoize "4.x" - make-error "1.x" - semver "^7.5.3" - yargs-parser "^21.0.1" - ts-loader@^9.4.2: version "9.4.4" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.4.tgz#6ceaf4d58dcc6979f84125335904920884b7cee4" @@ -19733,16 +18753,6 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.7.2: - version "2.7.2" - resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" - integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== - typed-array-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" @@ -19805,16 +18815,6 @@ typedoc@^0.22.13: minimatch "^5.1.0" shiki "^0.10.1" -typedoc@^0.24.8: - version "0.24.8" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.24.8.tgz#cce9f47ba6a8d52389f5e583716a2b3b4335b63e" - integrity sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w== - dependencies: - lunr "^2.3.9" - marked "^4.3.0" - minimatch "^9.0.0" - shiki "^0.14.1" - "typescript@>=3 < 6": version "5.2.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" @@ -19825,20 +18825,6 @@ typescript@^4.6.2, typescript@^4.8.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== -typeson-registry@^1.0.0-alpha.20: - version "1.0.0-alpha.39" - resolved "https://registry.yarnpkg.com/typeson-registry/-/typeson-registry-1.0.0-alpha.39.tgz#9e0f5aabd5eebfcffd65a796487541196f4b1211" - integrity sha512-NeGDEquhw+yfwNhguLPcZ9Oj0fzbADiX4R0WxvoY8nGhy98IbzQy1sezjoEFWOywOboj/DWehI+/aUlRVrJnnw== - dependencies: - base64-arraybuffer-es6 "^0.7.0" - typeson "^6.0.0" - whatwg-url "^8.4.0" - -typeson@^6.0.0, typeson@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/typeson/-/typeson-6.1.0.tgz#5b2a53705a5f58ff4d6f82f965917cabd0d7448b" - integrity sha512-6FTtyGr8ldU0pfbvW/eOZrEtEkczHRUtduBnA90Jh9kMPCiFNnXIon3vF41N0S4tV1HHQt4Hk1j4srpESziCaA== - uglify-js@^3.1.4: version "3.17.4" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" @@ -20286,15 +19272,6 @@ v8-to-istanbul@^9.0.0: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" -v8-to-istanbul@^9.0.1: - version "9.1.3" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz#ea456604101cd18005ac2cae3cdd1aa058a6306b" - integrity sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^2.0.0" - validate-npm-package-license@3.0.4, validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -20400,7 +19377,7 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== -vscode-oniguruma@^1.6.1, vscode-oniguruma@^1.7.0: +vscode-oniguruma@^1.6.1: version "1.7.0" resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA== @@ -20410,11 +19387,6 @@ vscode-textmate@5.2.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== -vscode-textmate@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d" - integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg== - w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" @@ -20429,7 +19401,7 @@ w3c-xmlserializer@^2.0.0: dependencies: xml-name-validator "^3.0.0" -walker@^1.0.7, walker@^1.0.8, walker@~1.0.5: +walker@^1.0.7, walker@~1.0.5: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== @@ -20481,21 +19453,11 @@ web-namespaces@^1.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== -web-streams-polyfill@^3.0.3: - version "3.2.1" - resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" - integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== - webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== -webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== - webidl-conversions@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" @@ -20749,7 +19711,7 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -whatwg-url@^8.0.0, whatwg-url@^8.4.0, whatwg-url@^8.5.0: +whatwg-url@^8.0.0, whatwg-url@^8.5.0: version "8.7.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== @@ -20931,14 +19893,6 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write-file-atomic@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - write-json-file@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-3.2.0.tgz#65bbdc9ecd8a1458e15952770ccbadfcff5fe62a" @@ -20965,16 +19919,11 @@ ws@^7, ws@^7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -ws@^8.13.0, ws@^8.14.2, ws@^8.2.3: +ws@^8.13.0, ws@^8.2.3: version "8.14.2" resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== -ws@~8.11.0: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" - integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== - x-default-browser@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/x-default-browser/-/x-default-browser-0.4.0.tgz#70cf0da85da7c0ab5cb0f15a897f2322a6bdd481" @@ -21075,7 +20024,7 @@ yargs-parser@20.x, yargs-parser@^20.2.2, yargs-parser@^20.2.3, yargs-parser@^20. resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs-parser@21.1.1, yargs-parser@^21.0.1, yargs-parser@^21.1.1: +yargs-parser@21.1.1, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== @@ -21103,7 +20052,7 @@ yargs@16.2.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.3.1, yargs@^17.6.2: +yargs@^17.6.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==

jU?lMi@tgxr7CqX_r3uw^y4tVU3Pm0sw;|1WSUO%?=bG`*Kmz6u4{#ti;T7AWIBAEh!(Y zz>O01&#X?Ds@L)Sb{CkG#Yz4$3o d@96)?#cz^xWoA}>B$xmI002ovPDHLkV1l3&k#zt7 literal 0 HcmV?d00001 diff --git a/nym-vpn/ui/src-tauri/icons/Square310x310Logo.png b/nym-vpn/ui/src-tauri/icons/Square310x310Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f9bc04839491e66c07b16ab03743c0c53b4109cc GIT binary patch literal 8591 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 JPDHLkV1lm|RXG3v literal 0 HcmV?d00001 diff --git a/nym-vpn/ui/src-tauri/icons/Square71x71Logo.png b/nym-vpn/ui/src-tauri/icons/Square71x71Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..63440d7984936a9caa89275928d8dce97e4d033b GIT binary patch literal 2011 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∓t$dRJGIadE?vc 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 Kx8Vjl{{H|h@<;Lj literal 0 HcmV?d00001 diff --git a/nym-vpn/ui/src-tauri/icons/icon.ico b/nym-vpn/ui/src-tauri/icons/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b3636e4b22ba65db9061cd60a77b02c92022dfd6 GIT binary patch literal 86642 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 AKmY&$ literal 0 HcmV?d00001 diff --git a/nym-vpn/ui/src-tauri/icons/icon.png b/nym-vpn/ui/src-tauri/icons/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e1cd2619e0b5ec089cbba5ec7b03ddf2b1dfceb6 GIT binary patch literal 14183 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

%)9&2D+b@Pmtf%bLH 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�Z>{6H{{g~{msau7egd6fVGsP*h-)CkL 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 i3-<-209~Rz92GF%, force_tls: bool, - hidden_gateways: Vec, storage_passphrase: Option, } @@ -63,16 +59,11 @@ impl MixFetchClientBuilder { force_tls: bool, preferred_gateway: Option, storage_passphrase: Option, - hack_opts: Option, ) -> Self { MixFetchClientBuilder { config, preferred_gateway, force_tls, - hidden_gateways: hack_opts - .unwrap_or_default() - .hidden_gateways - .unwrap_or_default(), storage_passphrase, } } @@ -105,11 +96,14 @@ impl MixFetchClientBuilder { ClientStorage::new_async(&self.config.base.client.id, self.storage_passphrase.take()) .await?; - let uses_hidden = !self.hidden_gateways.is_empty(); let user_chosen = self.preferred_gateway.clone(); - let gateways = get_combined_gateways(self.hidden_gateways, &nym_api_endpoints).await?; - let init_res = - setup_gateway_wasm(&client_store, self.force_tls, user_chosen, &gateways).await?; + let init_res = setup_gateway_from_api( + &client_store, + self.force_tls, + user_chosen, + &nym_api_endpoints, + ) + .await?; let storage = Self::initialise_storage(&self.config, client_store); @@ -122,12 +116,6 @@ impl MixFetchClientBuilder { if let Ok(reuse_setup) = GatewaySetup::try_reuse_connection(init_res) { base_builder = base_builder.with_gateway_setup(reuse_setup); } - if uses_hidden { - base_builder = base_builder.with_topology_provider(Box::new( - _hack__get_topology_provider(gateways, &nym_api_endpoints).await?, - )) - } - let mut started_client = base_builder.start_base().await?; let self_address = started_client.address; @@ -158,17 +146,10 @@ impl MixFetchClient { force_tls: bool, preferred_gateway: Option, storage_passphrase: Option, - hack_opts: Option, ) -> Result { - MixFetchClientBuilder::new( - config, - force_tls, - preferred_gateway, - storage_passphrase, - hack_opts, - ) - .start_client_async() - .await + MixFetchClientBuilder::new(config, force_tls, preferred_gateway, storage_passphrase) + .start_client_async() + .await } #[wasm_bindgen(constructor)] @@ -178,18 +159,11 @@ impl MixFetchClient { force_tls: bool, preferred_gateway: Option, storage_passphrase: Option, - hack_opts: Option, ) -> Promise { future_to_promise(async move { - Self::new_async( - config, - force_tls, - preferred_gateway, - storage_passphrase, - hack_opts, - ) - .await - .into_promise_result() + Self::new_async(config, force_tls, preferred_gateway, storage_passphrase) + .await + .into_promise_result() }) } diff --git a/wasm/mix-fetch/src/fetch.rs b/wasm/mix-fetch/src/fetch.rs index 995b27e2b2..2fd8da80dc 100644 --- a/wasm/mix-fetch/src/fetch.rs +++ b/wasm/mix-fetch/src/fetch.rs @@ -13,7 +13,6 @@ use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; use wasm_bindgen_futures::future_to_promise; use wasm_client_core::config::r#override::DebugWasmOverride; -use wasm_client_core::topology::SerializableGateway; use wasm_utils::console_log; use wasm_utils::error::PromisableResultError; @@ -44,9 +43,6 @@ pub struct MixFetchOpts { #[tsify(optional)] pub(crate) mix_fetch_override: Option, - - #[tsify(optional)] - pub(crate) extra: HackOpts, } #[derive(Tsify, Debug, Clone, Serialize, Deserialize)] @@ -67,15 +63,6 @@ pub struct MixFetchOptsSimple { pub(crate) storage_passphrase: Option, } -#[derive(Tsify, Debug, Default, Clone, Serialize, Deserialize)] -#[tsify(into_wasm_abi, from_wasm_abi)] -#[serde(rename_all = "camelCase")] -#[doc(hidden)] -pub struct HackOpts { - #[tsify(optional)] - pub(crate) hidden_gateways: Option>, -} - impl<'a> From<&'a MixFetchOpts> for MixFetchConfigOpts { fn from(value: &'a MixFetchOpts) -> Self { MixFetchConfigOpts { @@ -118,7 +105,7 @@ pub fn setup_mix_fetch(opts: MixFetchOpts) -> Promise { config.override_mix_fetch_debug(dbg) } - setup_mix_fetch_async(config, opts.base, opts.extra) + setup_mix_fetch_async(config, opts.base) .await .map(|_| JsValue::undefined()) .map_promise_err() @@ -132,7 +119,7 @@ pub fn setup_mix_fetch_with_config(config: MixFetchConfig, opts: MixFetchOptsSim } future_to_promise(async move { - setup_mix_fetch_async(config, opts, Default::default()) + setup_mix_fetch_async(config, opts) .await .map(|_| JsValue::undefined()) .map_promise_err() @@ -171,19 +158,12 @@ pub(super) fn mix_fetch_client() -> Result<&'static MixFetchClient, MixFetchErro async fn setup_mix_fetch_async( config: MixFetchConfig, opts: MixFetchOptsSimple, - hack_opts: HackOpts, ) -> Result<(), MixFetchError> { let preferred_gateway = opts.preferred_gateway; let storage_passphrase = opts.storage_passphrase; let force_tls = opts.force_tls.unwrap_or_default(); - let client = MixFetchClient::new_async( - config, - force_tls, - preferred_gateway, - storage_passphrase, - Some(hack_opts), - ) - .await?; + let client = + MixFetchClient::new_async(config, force_tls, preferred_gateway, storage_passphrase).await?; set_mix_fetch_client(client)?; Ok(()) } diff --git a/wasm/mix-fetch/src/harbourmaster.rs b/wasm/mix-fetch/src/harbourmaster.rs index 862f6a316a..089919d9d5 100644 --- a/wasm/mix-fetch/src/harbourmaster.rs +++ b/wasm/mix-fetch/src/harbourmaster.rs @@ -4,10 +4,13 @@ // this exists inside mix-fetch rather than being made into repo-wide library since it's a temporary solution // until the API is finalised and endpoints are moved to nym-api -use reqwest::{IntoUrl, Response, StatusCode}; +use async_trait::async_trait; +use http_api_client::{ApiClient, HttpClientError, NO_PARAMS}; use serde::Deserialize; -use thiserror::Error; -use url::Url; + +pub use http_api_client::Client; + +pub type HarbourMasterApiError = HttpClientError; mod routes { pub const API_VERSION: &str = "v1"; @@ -17,79 +20,12 @@ mod routes { pub const NEW: &str = "new"; } -// most of it is copied from the nym-api client -type PathSegments<'a> = &'a [&'a str]; -type Params<'a, K, V> = &'a [(K, V)]; - -const NO_PARAMS: Params<'_, &'_ str, &'_ str> = &[]; - -#[derive(Debug, Error)] -pub enum HarbourMasterApiError { - #[error("there was an issue with the REST request: {source}")] - ReqwestClientError { - #[from] - source: reqwest::Error, - }, - - #[error("not found")] - NotFound, - - #[error("request failed with error message: {0}")] - GenericRequestFailure(String), -} - -pub struct Client { - url: Url, - reqwest_client: reqwest::Client, -} - -impl Client { - pub fn new(url: U) -> Result { - let reqwest_client = reqwest::Client::new(); - Ok(Self { - url: url.into_url()?, - reqwest_client, - }) - } - - async fn send_get_request( - &self, - path: PathSegments<'_>, - params: Params<'_, K, V>, - ) -> Result - where - K: AsRef, - V: AsRef, - { - let url = create_api_url(&self.url, path, params); - Ok(self.reqwest_client.get(url).send().await?) - } - - async fn query_harbourmaster( - &self, - path: PathSegments<'_>, - params: Params<'_, K, V>, - ) -> Result - where - for<'a> T: Deserialize<'a>, - K: AsRef, - V: AsRef, - { - let res = self.send_get_request(path, params).await?; - if res.status().is_success() { - Ok(res.json().await?) - } else if res.status() == StatusCode::NOT_FOUND { - Err(HarbourMasterApiError::NotFound) - } else { - Err(HarbourMasterApiError::GenericRequestFailure( - res.text().await?, - )) - } - } - +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +pub trait HarbourMasterApiClientExt: ApiClient { // since it's a temporary thing don't worry about paging. - pub async fn get_services_new(&self) -> Result, HarbourMasterApiError> { - self.query_harbourmaster( + async fn get_services_new(&self) -> Result, HarbourMasterApiError> { + self.get_json( &[routes::API_VERSION, routes::SERVICES, routes::NEW], NO_PARAMS, ) @@ -97,29 +33,9 @@ impl Client { } } -fn create_api_url, V: AsRef>( - base: &Url, - segments: PathSegments<'_>, - params: Params<'_, K, V>, -) -> Url { - let mut url = base.clone(); - let mut path_segments = url - .path_segments_mut() - .expect("provided validator url does not have a base!"); - for segment in segments { - let segment = segment.strip_prefix('/').unwrap_or(segment); - let segment = segment.strip_suffix('/').unwrap_or(segment); - - path_segments.push(segment); - } - drop(path_segments); - - if !params.is_empty() { - url.query_pairs_mut().extend_pairs(params); - } - - url -} +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +impl HarbourMasterApiClientExt for Client {} // https://gitlab.nymte.ch/nym/shipyard-test-and-earn/-/blob/main/harbour-master/src/http/mod.rs#L13 #[derive(Debug, Deserialize)] diff --git a/wasm/mix-fetch/src/helpers.rs b/wasm/mix-fetch/src/helpers.rs index 0ba09bacea..e675c7d005 100644 --- a/wasm/mix-fetch/src/helpers.rs +++ b/wasm/mix-fetch/src/helpers.rs @@ -3,14 +3,10 @@ use crate::error::MixFetchError; use crate::harbourmaster; +use crate::harbourmaster::HarbourMasterApiClientExt; use rand::seq::SliceRandom; use rand::thread_rng; -use std::collections::HashMap; -use url::Url; -use wasm_client_core::init::helpers::{current_gateways, current_mixnodes}; -use wasm_client_core::topology::{gateway, SerializableGateway}; -use wasm_client_core::{HardcodedTopologyProvider, NymTopology}; -use wasm_utils::{console_log, console_warn}; +use wasm_utils::console_log; // since this client is temporary (and will be properly integrated into nym-api eventually), // we're using hardcoded URL for mainnet @@ -23,7 +19,7 @@ pub(crate) async fn get_network_requester( return Ok(sp); } - let client = harbourmaster::Client::new(HARBOUR_MASTER)?; + let client = harbourmaster::Client::new_url(HARBOUR_MASTER, None)?; let providers = client.get_services_new().await?; console_log!( "obtained list of {} service providers on the network", @@ -39,55 +35,3 @@ pub(crate) async fn get_network_requester( .cloned() .ok_or(MixFetchError::NoNetworkRequesters) } - -pub(crate) async fn get_combined_gateways( - hidden: Vec, - nym_apis: &[Url], -) -> Result, MixFetchError> { - let mut rng = thread_rng(); - - let mut api_gateways = current_gateways(&mut rng, nym_apis).await?; - if !hidden.is_empty() { - // make sure to override duplicates - let mut gateways: HashMap<_, _> = api_gateways - .into_iter() - .map(|g| (g.identity_key.to_base58_string(), g)) - .collect(); - - for node in hidden { - let id = node.identity_key.clone(); - let converted: Result = node.try_into(); - match converted { - Err(err) => { - console_warn!("failed to add gateway '{id}' into the topology: {err}"); - } - Ok(gateway) => { - if gateways - .insert(gateway.identity_key.to_base58_string(), gateway) - .is_some() - { - console_warn!("overridden gateway '{id}'") - } - } - } - } - - api_gateways = gateways.into_values().collect(); - } - - Ok(api_gateways) -} - -#[allow(non_snake_case)] -pub(crate) async fn _hack__get_topology_provider( - combined_gateways: Vec, - nym_apis: &[Url], -) -> Result { - let mut rng = thread_rng(); - - let mixnodes = current_mixnodes(&mut rng, nym_apis).await?; - Ok(HardcodedTopologyProvider::new(NymTopology::new_unordered( - mixnodes, - combined_gateways, - ))) -} From 6a9b9cd0dd376c01ab2b2c956bf2ee3f4be32c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Thu, 19 Oct 2023 12:06:09 +0100 Subject: [PATCH 025/236] making sure to start local gateway in 'local' mode (#4019) --- scripts/localnet_start.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/localnet_start.sh b/scripts/localnet_start.sh index 3fb93de20a..ac2a059547 100755 --- a/scripts/localnet_start.sh +++ b/scripts/localnet_start.sh @@ -36,11 +36,10 @@ tmux start-server tmux new-session -d -s localnet -n Mixnet -d "/usr/bin/env sh -c \" cargo run --release --bin nym-mixnode -- run --id mix1-$suffix \"" tmux split-window -t localnet:0 "/usr/bin/env sh -c \" cargo run --release --bin nym-mixnode -- run --id mix2-$suffix \"" tmux split-window -t localnet:0 "/usr/bin/env sh -c \" cargo run --release --bin nym-mixnode -- run --id mix3-$suffix \"" -tmux split-window -t localnet:0 "/usr/bin/env sh -c \" cargo run --release --bin nym-gateway -- run --id gateway-$suffix \"" - -echo "waiting for nym-gateway to launch on port 9000..." +tmux split-window -t localnet:0 "/usr/bin/env sh -c \" cargo run --release --bin nym-gateway -- run --id gateway-$suffix --local \"" while ! nc -z localhost 9000; do + echo "waiting for nym-gateway to launch on port 9000..." sleep 2 done From 107cec39f4d55e62531db9288692dd9d242afcf7 Mon Sep 17 00:00:00 2001 From: Shubham kashyap <110350667+Shubhamkashyap1601@users.noreply.github.com> Date: Thu, 19 Oct 2023 16:43:36 +0530 Subject: [PATCH 026/236] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fec13cd406..e1a976f529 100644 --- a/README.md +++ b/README.md @@ -50,10 +50,10 @@ Node, node operator and delegator rewards are determined according to the princi ||ratio of stake operator has pledged to their node to the token circulating supply. ||fraction of total effort undertaken by node `i`, set to `1/k`. ||number of nodes stakeholders are incentivised to create, set by the validators, a matter of governance. Currently determined by the `reward set` size, and set to 720 in testnet Sandbox. -||Sybil attack resistance parameter - the higher this parameter is set the stronger the reduction in competitiveness gets for a Sybil attacker. -||declared profit margin of operator `i`, defaults to 10% in. +||A Sybil attack resistance parameter - the higher this parameter is set, the stronger the reduction in competitiveness for a Sybil attacker. +||declared profit margin of operator `i`, defaults to 10%. ||uptime of node `i`, scaled to 0 - 1, for the rewarding epoch -||cost of operating node `i` for the duration of the rewarding epoch, set to 40 NYMT. +||cost of operating node `i` for the duration of the rewarding epoch, set to 40 NYMTs. Node reward for node `i` is determined as: From 474c496226ae5ad5e9b95bd35aeb735498ad7938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 19 Oct 2023 14:40:43 +0200 Subject: [PATCH 027/236] Handle ipv6 in tun device Handle IPv6 in tun device. Remove bunch of unwraps and correctly handle errors. Deduplicate parse_src_address. --- .../src/platform/linux/tun_device.rs | 64 ++++++++++++------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/common/wireguard/src/platform/linux/tun_device.rs b/common/wireguard/src/platform/linux/tun_device.rs index e2db4be030..c99840aff9 100644 --- a/common/wireguard/src/platform/linux/tun_device.rs +++ b/common/wireguard/src/platform/linux/tun_device.rs @@ -1,4 +1,7 @@ -use std::{net::Ipv4Addr, sync::Arc}; +use std::{ + net::{IpAddr, Ipv4Addr}, + sync::Arc, +}; use etherparse::{InternetSlice, SlicedPacket}; use tap::TapFallible; @@ -63,12 +66,13 @@ impl TunDevice { } fn handle_tun_read(&self, packet: &[u8]) { - let dst_addr = boringtun::noise::Tunn::dst_address(packet).unwrap(); - - let headers = SlicedPacket::from_ip(packet).unwrap(); - let src_addr = match headers.ip.unwrap() { - InternetSlice::Ipv4(ip, _) => ip.source_addr().to_string(), - InternetSlice::Ipv6(ip, _) => ip.source_addr().to_string(), + let Some(dst_addr) = boringtun::noise::Tunn::dst_address(packet) else { + log::error!("Unable to parse dst_address in packet that was supposed to be written to tun device"); + return; + }; + let Some(src_addr) = parse_src_address(packet) else { + log::error!("Unable to parse src_address in packet that was supposed to be written to tun device"); + return; }; log::info!( "iface: read Packet({src_addr} -> {dst_addr}, {} bytes)", @@ -76,35 +80,41 @@ impl TunDevice { ); // Route packet to the correct peer. - if let Some(peer_tx) = self - .peers_by_ip - .lock() - .unwrap() - .longest_match(dst_addr) - .map(|(_, tx)| tx) - { + let Ok(peers) = self.peers_by_ip.lock() else { + log::error!("Failed to lock peers_by_ip, aborting tun device read"); + return; + }; + if let Some(peer_tx) = peers.longest_match(dst_addr).map(|(_, tx)| tx) { log::info!("Forward packet to wg tunnel"); peer_tx .send(Event::Ip(packet.to_vec().into())) .tap_err(|err| log::error!("{err}")) - .unwrap(); + .ok(); } else { log::info!("No peer found, packet dropped"); } } async fn handle_tun_write(&mut self, data: Vec) { - let headers = SlicedPacket::from_ip(&data).unwrap(); - let (source_addr, destination_addr) = match headers.ip.unwrap() { - InternetSlice::Ipv4(ip, _) => (ip.source_addr(), ip.destination_addr()), - InternetSlice::Ipv6(_, _) => unimplemented!(), + let Some(dst_addr) = boringtun::noise::Tunn::dst_address(&data) else { + log::error!("Unable to parse dst_address in packet that was supposed to be written to tun device"); + return; + }; + let Some(src_addr) = parse_src_address(&data) else { + log::error!("Unable to parse src_address in packet that was supposed to be written to tun device"); + return; }; - log::info!( - "iface: write Packet({source_addr} -> {destination_addr}, {} bytes)", + "iface: write Packet({src_addr} -> {dst_addr}, {} bytes)", data.len() ); - self.tun.write_all(&data).await.unwrap(); + self.tun + .write_all(&data) + .await + .tap_err(|err| { + log::error!("iface: write error: {err}"); + }) + .ok(); } pub async fn run(mut self) { @@ -136,3 +146,13 @@ impl TunDevice { tokio::spawn(async move { self.run().await }); } } + +fn parse_src_address(packet: &[u8]) -> Option { + let headers = SlicedPacket::from_ip(packet) + .tap_err(|err| log::error!("Unable to parse IP packet: {err:?}")) + .ok()?; + Some(match headers.ip? { + InternetSlice::Ipv4(ip, _) => ip.source_addr().into(), + InternetSlice::Ipv6(ip, _) => ip.source_addr().into(), + }) +} From 89fad5c667cc99b31047d01f4ac7dc2ba46fc87b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 19 Oct 2023 14:51:18 +0200 Subject: [PATCH 028/236] Fix log typo --- common/wireguard/src/platform/linux/tun_device.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/wireguard/src/platform/linux/tun_device.rs b/common/wireguard/src/platform/linux/tun_device.rs index c99840aff9..5486e20f03 100644 --- a/common/wireguard/src/platform/linux/tun_device.rs +++ b/common/wireguard/src/platform/linux/tun_device.rs @@ -67,11 +67,11 @@ impl TunDevice { fn handle_tun_read(&self, packet: &[u8]) { let Some(dst_addr) = boringtun::noise::Tunn::dst_address(packet) else { - log::error!("Unable to parse dst_address in packet that was supposed to be written to tun device"); + log::error!("Unable to parse dst_address in packet that was read from tun device"); return; }; let Some(src_addr) = parse_src_address(packet) else { - log::error!("Unable to parse src_address in packet that was supposed to be written to tun device"); + log::error!("Unable to parse src_address in packet that was read from tun device"); return; }; log::info!( From 396112bc8be0a3bb151ca97e1e491f39e4a8d1cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 20 Oct 2023 11:10:55 +0200 Subject: [PATCH 029/236] wg: use tags to forward packets (#4022) * Explicit type for TunTaskRx * Add tag to correctly forward incoming packets --- Cargo.lock | 1 + common/wireguard/Cargo.toml | 5 +- common/wireguard/src/lib.rs | 26 ++++++- .../src/platform/linux/tun_device.rs | 74 +++++++++++++------ common/wireguard/src/udp_listener.rs | 9 ++- common/wireguard/src/wg_tunnel.rs | 26 +++++-- 6 files changed, 106 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24f0e34659..5c80148210 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7541,6 +7541,7 @@ dependencies = [ "log", "nym-task", "nym-wireguard-types", + "rand 0.8.5", "serde", "tap", "thiserror", diff --git a/common/wireguard/Cargo.toml b/common/wireguard/Cargo.toml index 25cb796cc4..bddacbca1f 100644 --- a/common/wireguard/Cargo.toml +++ b/common/wireguard/Cargo.toml @@ -26,11 +26,12 @@ ip_network = "0.4.1" ip_network_table = "0.2.0" log.workspace = true nym-task = { path = "../task" } +nym-wireguard-types = { path = "../wireguard-types" } +rand.workspace = true +serde = { workspace = true, features = ["derive"] } tap.workspace = true thiserror.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "net", "io-util"] } -serde = { workspace = true, features = ["derive"] } -nym-wireguard-types = { path = "../wireguard-types" } [target.'cfg(target_os = "linux")'.dependencies] tokio-tun = "0.9.0" diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index 5a4520d6c2..0df9e8ce1a 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -20,12 +20,25 @@ use std::sync::Arc; #[cfg(target_os = "linux")] use platform::linux::tun_device; +type TunTaskPayload = (u64, Vec); + #[derive(Clone)] -pub struct TunTaskTx(tokio::sync::mpsc::UnboundedSender>); +pub struct TunTaskTx(tokio::sync::mpsc::UnboundedSender); impl TunTaskTx { - fn send(&self, packet: Vec) -> Result<(), tokio::sync::mpsc::error::SendError>> { - self.0.send(packet) + fn send( + &self, + data: TunTaskPayload, + ) -> Result<(), tokio::sync::mpsc::error::SendError> { + self.0.send(data) + } +} + +pub struct TunTaskRx(tokio::sync::mpsc::UnboundedReceiver); + +impl TunTaskRx { + async fn recv(&mut self) -> Option { + self.0.recv().await } } @@ -39,16 +52,21 @@ pub async fn start_wireguard( task_client: nym_task::TaskClient, gateway_client_registry: Arc, ) -> Result<(), Box> { + // We can either index peers by their IP like standard wireguard let peers_by_ip = Arc::new(std::sync::Mutex::new(network_table::NetworkTable::new())); + // ... or by their tunnel tag, which is a random number assigned to them + let peers_by_tag = Arc::new(std::sync::Mutex::new(wg_tunnel::PeersByTag::new())); + // Start the tun device that is used to relay traffic outbound - let (tun, tun_task_tx) = tun_device::TunDevice::new(peers_by_ip.clone()); + let (tun, tun_task_tx) = tun_device::TunDevice::new(peers_by_ip.clone(), peers_by_tag.clone()); tun.start(); // Start the UDP listener that clients connect to let udp_listener = udp_listener::WgUdpListener::new( tun_task_tx, peers_by_ip, + peers_by_tag, Arc::clone(&gateway_client_registry), ) .await?; diff --git a/common/wireguard/src/platform/linux/tun_device.rs b/common/wireguard/src/platform/linux/tun_device.rs index 5486e20f03..deea1937c1 100644 --- a/common/wireguard/src/platform/linux/tun_device.rs +++ b/common/wireguard/src/platform/linux/tun_device.rs @@ -1,4 +1,5 @@ use std::{ + collections::HashMap, net::{IpAddr, Ipv4Addr}, sync::Arc, }; @@ -14,7 +15,8 @@ use crate::{ event::Event, setup::{TUN_BASE_NAME, TUN_DEVICE_ADDRESS, TUN_DEVICE_NETMASK}, udp_listener::PeersByIp, - TunTaskTx, + wg_tunnel::PeersByTag, + TunTaskPayload, TunTaskRx, TunTaskTx, }; fn setup_tokio_tun_device(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> tokio_tun::Tun { @@ -36,15 +38,22 @@ pub struct TunDevice { tun: tokio_tun::Tun, // Incoming data that we should send - tun_task_rx: mpsc::UnboundedReceiver>, + // tun_task_rx: mpsc::UnboundedReceiver>, + tun_task_rx: TunTaskRx, // The routing table. // An alternative would be to do NAT by just matching incoming with outgoing. peers_by_ip: Arc>, + + nat_table: HashMap, + peers_by_tag: Arc>, } impl TunDevice { - pub fn new(peers_by_ip: Arc>) -> (Self, TunTaskTx) { + pub fn new( + peers_by_ip: Arc>, + peers_by_tag: Arc>, + ) -> (Self, TunTaskTx) { let tun = setup_tokio_tun_device( format!("{TUN_BASE_NAME}%d").as_str(), TUN_DEVICE_ADDRESS.parse().unwrap(), @@ -53,13 +62,16 @@ impl TunDevice { log::info!("Created TUN device: {}", tun.name()); // Channels to communicate with the other tasks - let (tun_task_tx, tun_task_rx) = mpsc::unbounded_channel::>(); + let (tun_task_tx, tun_task_rx) = mpsc::unbounded_channel(); let tun_task_tx = TunTaskTx(tun_task_tx); + let tun_task_rx = TunTaskRx(tun_task_rx); let tun_device = TunDevice { tun_task_rx, tun, peers_by_ip, + nat_table: HashMap::new(), + peers_by_tag, }; (tun_device, tun_task_tx) @@ -80,36 +92,56 @@ impl TunDevice { ); // Route packet to the correct peer. - let Ok(peers) = self.peers_by_ip.lock() else { - log::error!("Failed to lock peers_by_ip, aborting tun device read"); - return; - }; - if let Some(peer_tx) = peers.longest_match(dst_addr).map(|(_, tx)| tx) { - log::info!("Forward packet to wg tunnel"); - peer_tx - .send(Event::Ip(packet.to_vec().into())) - .tap_err(|err| log::error!("{err}")) - .ok(); - } else { - log::info!("No peer found, packet dropped"); + if false { + let Ok(peers) = self.peers_by_ip.lock() else { + log::error!("Failed to lock peers_by_ip, aborting tun device read"); + return; + }; + if let Some(peer_tx) = peers.longest_match(dst_addr).map(|(_, tx)| tx) { + log::info!("Forward packet to wg tunnel"); + peer_tx + .send(Event::Ip(packet.to_vec().into())) + .tap_err(|err| log::error!("{err}")) + .ok(); + return; + } } + + { + if let Some(tag) = self.nat_table.get(&dst_addr) { + log::info!("Forward packet to wg tunnel with tag: {tag}"); + self.peers_by_tag.lock().unwrap().get(tag).and_then(|tx| { + tx.send(Event::Ip(packet.to_vec().into())) + .tap_err(|err| log::error!("{err}")) + .ok() + }); + return; + } + } + + log::info!("No peer found, packet dropped"); } - async fn handle_tun_write(&mut self, data: Vec) { - let Some(dst_addr) = boringtun::noise::Tunn::dst_address(&data) else { + async fn handle_tun_write(&mut self, data: TunTaskPayload) { + let (tag, packet) = data; + let Some(dst_addr) = boringtun::noise::Tunn::dst_address(&packet) else { log::error!("Unable to parse dst_address in packet that was supposed to be written to tun device"); return; }; - let Some(src_addr) = parse_src_address(&data) else { + let Some(src_addr) = parse_src_address(&packet) else { log::error!("Unable to parse src_address in packet that was supposed to be written to tun device"); return; }; log::info!( "iface: write Packet({src_addr} -> {dst_addr}, {} bytes)", - data.len() + packet.len() ); + + // TODO: expire old entries + self.nat_table.insert(src_addr, tag); + self.tun - .write_all(&data) + .write_all(&packet) .await .tap_err(|err| { log::error!("iface: write error: {err}"); diff --git a/common/wireguard/src/udp_listener.rs b/common/wireguard/src/udp_listener.rs index 045dd7e892..fa68962bf1 100644 --- a/common/wireguard/src/udp_listener.rs +++ b/common/wireguard/src/udp_listener.rs @@ -24,6 +24,7 @@ use crate::{ network_table::NetworkTable, registered_peers::{RegisteredPeer, RegisteredPeers}, setup::{self, WG_ADDRESS, WG_PORT}, + wg_tunnel::PeersByTag, TunTaskTx, }; @@ -57,6 +58,9 @@ pub struct WgUdpListener { // The routing table, as defined by wireguard peers_by_ip: Arc>, + // ... or alternatively we can map peers by their tag + peers_by_tag: Arc>, + // The UDP socket to the peer udp: Arc, @@ -73,6 +77,7 @@ impl WgUdpListener { pub async fn new( tun_task_tx: TunTaskTx, peers_by_ip: Arc>, + peers_by_tag: Arc>, gateway_client_registry: Arc, ) -> Result> { let wg_address = SocketAddr::new(WG_ADDRESS.parse().unwrap(), WG_PORT); @@ -94,6 +99,7 @@ impl WgUdpListener { static_public, registered_peers, peers_by_ip, + peers_by_tag, udp, tun_task_tx, rate_limiter, @@ -194,7 +200,7 @@ impl WgUdpListener { // NOTE: we are NOT passing in the existing rate_limiter. Re-visit this // choice later. log::warn!("Creating new rate limiter, consider re-using?"); - let (join_handle, peer_tx) = crate::wg_tunnel::start_wg_tunnel( + let (join_handle, peer_tx, tag) = crate::wg_tunnel::start_wg_tunnel( addr, self.udp.clone(), self.static_private.clone(), @@ -205,6 +211,7 @@ impl WgUdpListener { ); self.peers_by_ip.lock().unwrap().insert(registered_peer.allowed_ips, peer_tx.clone()); + self.peers_by_tag.lock().unwrap().insert(tag, peer_tx.clone()); peer_tx.send(Event::Wg(buf[..len].to_vec().into())) .tap_err(|e| log::error!("{e}")) diff --git a/common/wireguard/src/wg_tunnel.rs b/common/wireguard/src/wg_tunnel.rs index 5eb4d3647c..cfc10d5057 100644 --- a/common/wireguard/src/wg_tunnel.rs +++ b/common/wireguard/src/wg_tunnel.rs @@ -1,4 +1,4 @@ -use std::{net::SocketAddr, sync::Arc, time::Duration}; +use std::{collections::HashMap, net::SocketAddr, sync::Arc, time::Duration}; use async_recursion::async_recursion; use boringtun::{ @@ -22,6 +22,9 @@ const HANDSHAKE_MAX_RATE: u64 = 10; const MAX_PACKET: usize = 65535; +// We index the tunnels by tag +pub(crate) type PeersByTag = HashMap>; + pub struct WireGuardTunnel { // Incoming data from the UDP socket received in the main event loop peer_rx: mpsc::UnboundedReceiver, @@ -44,6 +47,8 @@ pub struct WireGuardTunnel { // Send data to the task that handles sending data through the tun device tun_task_tx: TunTaskTx, + + tag: u64, } impl Drop for WireGuardTunnel { @@ -63,7 +68,7 @@ impl WireGuardTunnel { peer_allowed_ips: ip_network::IpNetwork, // rate_limiter: Option, tunnel_tx: TunTaskTx, - ) -> (Self, mpsc::UnboundedSender) { + ) -> (Self, mpsc::UnboundedSender, u64) { let local_addr = udp.local_addr().unwrap(); let peer_addr = udp.peer_addr(); log::info!("New wg tunnel: endpoint: {endpoint}, local_addr: {local_addr}, peer_addr: {peer_addr:?}"); @@ -98,6 +103,11 @@ impl WireGuardTunnel { let mut allowed_ips = NetworkTable::new(); allowed_ips.insert(peer_allowed_ips, ()); + // random u64 + use rand::RngCore; + let mut rng = rand::rngs::OsRng; + let tag = rng.next_u64(); + let tunnel = WireGuardTunnel { peer_rx, udp, @@ -107,9 +117,10 @@ impl WireGuardTunnel { close_tx, close_rx, tun_task_tx: tunnel_tx, + tag, }; - (tunnel, peer_tx) + (tunnel, peer_tx, tag) } fn close(&self) { @@ -198,14 +209,14 @@ impl WireGuardTunnel { } TunnResult::WriteToTunnelV4(packet, addr) => { if self.allowed_ips.longest_match(addr).is_some() { - self.tun_task_tx.send(packet.to_vec()).unwrap(); + self.tun_task_tx.send((self.tag, packet.to_vec())).unwrap(); } else { warn!("Packet from {addr} not in allowed_ips"); } } TunnResult::WriteToTunnelV6(packet, addr) => { if self.allowed_ips.longest_match(addr).is_some() { - self.tun_task_tx.send(packet.to_vec()).unwrap(); + self.tun_task_tx.send((self.tag, packet.to_vec())).unwrap(); } else { warn!("Packet (v6) from {addr} not in allowed_ips"); } @@ -311,8 +322,9 @@ pub(crate) fn start_wg_tunnel( ) -> ( tokio::task::JoinHandle, mpsc::UnboundedSender, + u64, ) { - let (mut tunnel, peer_tx) = WireGuardTunnel::new( + let (mut tunnel, peer_tx, tag) = WireGuardTunnel::new( udp, endpoint, static_private, @@ -325,5 +337,5 @@ pub(crate) fn start_wg_tunnel( tunnel.spin_off().await; peer_static_public }); - (join_handle, peer_tx) + (join_handle, peer_tx, tag) } From d9f088f36efdea101ba6a309bf565127bc748e5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 20 Oct 2023 15:17:03 +0200 Subject: [PATCH 030/236] Fully wrap tun task channel in strong type (#4023) --- common/wireguard/src/lib.rs | 23 +--------------- .../src/platform/linux/tun_device.rs | 12 +++------ common/wireguard/src/tun_task_channel.rs | 26 +++++++++++++++++++ common/wireguard/src/udp_listener.rs | 2 +- common/wireguard/src/wg_tunnel.rs | 3 ++- 5 files changed, 33 insertions(+), 33 deletions(-) create mode 100644 common/wireguard/src/tun_task_channel.rs diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index 0df9e8ce1a..813ba4718f 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -10,6 +10,7 @@ mod network_table; mod platform; mod registered_peers; mod setup; +mod tun_task_channel; mod udp_listener; mod wg_tunnel; @@ -20,28 +21,6 @@ use std::sync::Arc; #[cfg(target_os = "linux")] use platform::linux::tun_device; -type TunTaskPayload = (u64, Vec); - -#[derive(Clone)] -pub struct TunTaskTx(tokio::sync::mpsc::UnboundedSender); - -impl TunTaskTx { - fn send( - &self, - data: TunTaskPayload, - ) -> Result<(), tokio::sync::mpsc::error::SendError> { - self.0.send(data) - } -} - -pub struct TunTaskRx(tokio::sync::mpsc::UnboundedReceiver); - -impl TunTaskRx { - async fn recv(&mut self) -> Option { - self.0.recv().await - } -} - /// Start wireguard UDP listener and TUN device /// /// # Errors diff --git a/common/wireguard/src/platform/linux/tun_device.rs b/common/wireguard/src/platform/linux/tun_device.rs index deea1937c1..c714eb6cdf 100644 --- a/common/wireguard/src/platform/linux/tun_device.rs +++ b/common/wireguard/src/platform/linux/tun_device.rs @@ -6,17 +6,14 @@ use std::{ use etherparse::{InternetSlice, SlicedPacket}; use tap::TapFallible; -use tokio::{ - io::{AsyncReadExt, AsyncWriteExt}, - sync::mpsc::{self}, -}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; use crate::{ event::Event, setup::{TUN_BASE_NAME, TUN_DEVICE_ADDRESS, TUN_DEVICE_NETMASK}, + tun_task_channel::{tun_task_channel, TunTaskPayload, TunTaskRx, TunTaskTx}, udp_listener::PeersByIp, wg_tunnel::PeersByTag, - TunTaskPayload, TunTaskRx, TunTaskTx, }; fn setup_tokio_tun_device(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> tokio_tun::Tun { @@ -38,7 +35,6 @@ pub struct TunDevice { tun: tokio_tun::Tun, // Incoming data that we should send - // tun_task_rx: mpsc::UnboundedReceiver>, tun_task_rx: TunTaskRx, // The routing table. @@ -62,9 +58,7 @@ impl TunDevice { log::info!("Created TUN device: {}", tun.name()); // Channels to communicate with the other tasks - let (tun_task_tx, tun_task_rx) = mpsc::unbounded_channel(); - let tun_task_tx = TunTaskTx(tun_task_tx); - let tun_task_rx = TunTaskRx(tun_task_rx); + let (tun_task_tx, tun_task_rx) = tun_task_channel(); let tun_device = TunDevice { tun_task_rx, diff --git a/common/wireguard/src/tun_task_channel.rs b/common/wireguard/src/tun_task_channel.rs new file mode 100644 index 0000000000..423243d27e --- /dev/null +++ b/common/wireguard/src/tun_task_channel.rs @@ -0,0 +1,26 @@ +pub(crate) type TunTaskPayload = (u64, Vec); + +#[derive(Clone)] +pub struct TunTaskTx(tokio::sync::mpsc::UnboundedSender); + +pub(crate) struct TunTaskRx(tokio::sync::mpsc::UnboundedReceiver); + +impl TunTaskTx { + pub(crate) fn send( + &self, + data: TunTaskPayload, + ) -> Result<(), tokio::sync::mpsc::error::SendError> { + self.0.send(data) + } +} + +impl TunTaskRx { + pub(crate) async fn recv(&mut self) -> Option { + self.0.recv().await + } +} + +pub(crate) fn tun_task_channel() -> (TunTaskTx, TunTaskRx) { + let (tun_task_tx, tun_task_rx) = tokio::sync::mpsc::unbounded_channel(); + (TunTaskTx(tun_task_tx), TunTaskRx(tun_task_rx)) +} diff --git a/common/wireguard/src/udp_listener.rs b/common/wireguard/src/udp_listener.rs index fa68962bf1..e06e0feb20 100644 --- a/common/wireguard/src/udp_listener.rs +++ b/common/wireguard/src/udp_listener.rs @@ -24,8 +24,8 @@ use crate::{ network_table::NetworkTable, registered_peers::{RegisteredPeer, RegisteredPeers}, setup::{self, WG_ADDRESS, WG_PORT}, + tun_task_channel::TunTaskTx, wg_tunnel::PeersByTag, - TunTaskTx, }; const MAX_PACKET: usize = 65535; diff --git a/common/wireguard/src/wg_tunnel.rs b/common/wireguard/src/wg_tunnel.rs index cfc10d5057..f9308fbe2c 100644 --- a/common/wireguard/src/wg_tunnel.rs +++ b/common/wireguard/src/wg_tunnel.rs @@ -15,7 +15,8 @@ use tokio::{ }; use crate::{ - error::WgError, event::Event, network_table::NetworkTable, registered_peers::PeerIdx, TunTaskTx, + error::WgError, event::Event, network_table::NetworkTable, registered_peers::PeerIdx, + tun_task_channel::TunTaskTx, }; const HANDSHAKE_MAX_RATE: u64 = 10; From 85d172e54a33900023261a8fb66400aa279538e6 Mon Sep 17 00:00:00 2001 From: benedetta davico <46782255+benedettadavico@users.noreply.github.com> Date: Mon, 23 Oct 2023 11:56:16 +0200 Subject: [PATCH 031/236] updating details for QA env (#4027) * updating details for QA env * cargo fmt --- .../examples/query_name_service.rs | 2 +- .../query_service_provider_directory.rs | 2 +- envs/qa-qwerty.env | 28 ----------------- envs/qa.env | 30 ++++++++++--------- envs/sandbox.env | 11 ++++--- nym-wallet/nym-wallet-types/src/network/qa.rs | 21 +++++++------ nym-wallet/src/constants.ts | 3 +- 7 files changed, 34 insertions(+), 63 deletions(-) delete mode 100644 envs/qa-qwerty.env diff --git a/common/client-libs/validator-client/examples/query_name_service.rs b/common/client-libs/validator-client/examples/query_name_service.rs index f705cb3564..bf5001c86e 100644 --- a/common/client-libs/validator-client/examples/query_name_service.rs +++ b/common/client-libs/validator-client/examples/query_name_service.rs @@ -9,7 +9,7 @@ use nym_validator_client::nyxd::contract_traits::{ #[tokio::main] async fn main() { - setup_env(Some("../../../envs/qa-qwerty.env")); + setup_env(Some("../../../envs/qa.env")); let network_details = NymNetworkDetails::new_from_env(); let config = nym_validator_client::Config::try_from_nym_network_details(&network_details).unwrap(); diff --git a/common/client-libs/validator-client/examples/query_service_provider_directory.rs b/common/client-libs/validator-client/examples/query_service_provider_directory.rs index e489564e94..c0cd2b1399 100644 --- a/common/client-libs/validator-client/examples/query_service_provider_directory.rs +++ b/common/client-libs/validator-client/examples/query_service_provider_directory.rs @@ -9,7 +9,7 @@ use nym_validator_client::nyxd::contract_traits::{ #[tokio::main] async fn main() { - setup_env(Some("../../../envs/qa-qwerty.env")); + setup_env(Some("../../../envs/qa.env")); let network_details = NymNetworkDetails::new_from_env(); let config = nym_validator_client::Config::try_from_nym_network_details(&network_details).unwrap(); diff --git a/envs/qa-qwerty.env b/envs/qa-qwerty.env deleted file mode 100644 index 9080c9d37b..0000000000 --- a/envs/qa-qwerty.env +++ /dev/null @@ -1,28 +0,0 @@ -CONFIGURED=true - -NETWORK_NAME=qa-qwerty - -RUST_LOG=info -RUST_BACKTRACE=1 - -BECH32_PREFIX=n -MIX_DENOM=unym -MIX_DENOM_DISPLAY=nym -STAKE_DENOM=unyx -STAKE_DENOM_DISPLAY=nyx -DENOMS_EXPONENT=6 -MIXNET_CONTRACT_ADDRESS=n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g -VESTING_CONTRACT_ADDRESS=n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw -COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n19d2nwj7fdhxqmyvgy8lf3ad49a6vmww4shryhrkj2mqk36att66s6xzszw -GROUP_CONTRACT_ADDRESS=n1fqquzw4mk0pkamgr2ywt2v7h2j9nuyjjn4gvpy8zlpp6xn0uyuzqfm28l5 -MULTISIG_CONTRACT_ADDRESS=n1gaq3666chd5348apj8cka8t2mckv7azp9espyr7wgpxyuzur5d0sazpysy -COCONUT_DKG_CONTRACT_ADDRESS=n18yadscxw8v35dds7ksv3j0svmjh3h6e7tmxpadk96mvgz27zygkshuf4vs -EPHEMERA_CONTRACT_ADDRESS=n18yadscxw8v35dds7ksv3j0svmjh3h6e7tmxpadk96mvgz27zygkshuf4vs -REWARDING_VALIDATOR_ADDRESS=n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy -SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS=n1qsn2655eflc0nx2uwqtwyv5kad5dwm4c0gn72yr4q4de5r3jaz2slvqjgt -NAME_SERVICE_CONTRACT_ADDRESS=n1cm2u5vfjd3zalfw0p65xyh4tcrw3hjlm0960gzhewga449h4mgas77mjkl -STATISTICS_SERVICE_DOMAIN_ADDRESS="https://mainnet-stats.nymte.ch:8090" -NYXD="https://qwerty-validator.qa.nymte.ch/" -NYM_API="https://qwerty-validator-api.qa.nymte.ch/api/" - -DKG_TIME_CONFIGURATION="600,300,300,60,60,1209600" diff --git a/envs/qa.env b/envs/qa.env index 82bb8b9d3c..21c8014d1b 100644 --- a/envs/qa.env +++ b/envs/qa.env @@ -1,26 +1,28 @@ CONFIGURED=true -NETWORK_NAME=qa - RUST_LOG=info RUST_BACKTRACE=1 - +NETWORK_NAME=qa BECH32_PREFIX=n MIX_DENOM=unym MIX_DENOM_DISPLAY=nym STAKE_DENOM=unyx STAKE_DENOM_DISPLAY=nyx DENOMS_EXPONENT=6 -MIXNET_CONTRACT_ADDRESS=n1rjzps6qrmdqmf0xz4cn4x4rcmqeqzq6hnzqg4wcvd0r2lyasdq5sepn5s8 -VESTING_CONTRACT_ADDRESS=n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav -COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n1ghd753shjuwexxywmgs4xz7x2q732vcn7ty4yw -GROUP_CONTRACT_ADDRESS=n1rw8fw2mpcpzzq3jpa4e52ufawnmj5a4u68p35umvgskewuw0nlzsaa5w4m -MULTISIG_CONTRACT_ADDRESS=n17p9rzwnnfxcjp32un9ug7yhhzgtkhvl988qccs -COCONUT_DKG_CONTRACT_ADDRESS=n17p9rzwnnfxcjp32un9ug7yhhzgtkhvl988qccs -EPHEMERA_CONTRACT_ADDRESS=n1fc7nakzuyfn2qzkclafcsc54asamnclg064962lwne40w2lq558qftzjza -REWARDING_VALIDATOR_ADDRESS=n1tfzd4qz3a45u8p4mr5zmzv66457uwjgcl05jdq -STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0" -NYXD="https://qa-validator.nymtech.net" -NYM_API="https://qa-validator-api.nymtech.net/api/" + +MIXNET_CONTRACT_ADDRESS=n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g +VESTING_CONTRACT_ADDRESS=n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw +COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n1w798gp0zqv3s9hjl3jlnwxtwhykga6rn93p46q2crsdqhaj3y4gs68f74j +GROUP_CONTRACT_ADDRESS=n1sthrn5ep8ls5vzz8f9gp89khhmedahhdqd244dh9uqzk3hx2pzrsvf7zgk +MULTISIG_CONTRACT_ADDRESS=n1sr06m8yqg0wzqqyqvzvp5t07dj4nevx9u8qc7j4qa72qu8e3ct8qledthy +COCONUT_DKG_CONTRACT_ADDRESS=n1udfs22xpxle475m2nz7u47jfa3vngncdegmczwwdx00cmetypa3s7uyuqn +REWARDING_VALIDATOR_ADDRESS=n1rfvpsynktze6wvn6ldskj8xgwfzzk5v6pnff39 +NAME_SERVICE_CONTRACT_ADDRESS=n1qum2tr7hh4y7ruzew68c64myjec0dq2s2njf6waja5t0w879lutqadamme +SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS=n13ehuhysn5mqjeaheeuew2gjs785f6k7jm8vfsqg3jhtpkwppcmzq6m2hmz + +STATISTICS_SERVICE_DOMAIN_ADDRESS="https://mainnet-stats.nymte.ch:8090" +EXPLORER_API=https://qa-network-explorer.qa.nymte.ch/api +NYXD="https://qa-validator.qa.nymte.ch/" +NYM_API="https://qa-nym-api.qa.nymte.ch/api" DKG_TIME_CONFIGURATION="600,300,300,60,60,1209600" diff --git a/envs/sandbox.env b/envs/sandbox.env index b4a66a70d1..2510e3c4f0 100644 --- a/envs/sandbox.env +++ b/envs/sandbox.env @@ -1,10 +1,8 @@ CONFIGURED=true -NETWORK_NAME=sandbox - RUST_LOG=info RUST_BACKTRACE=1 - +NETWORK_NAME=sandbox BECH32_PREFIX=n MIX_DENOM=unym MIX_DENOM_DISPLAY=nym @@ -19,9 +17,10 @@ COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n16a32stm6kknhq5cc8rx77elr66pygf2hfszw7wvpq74 GROUP_CONTRACT_ADDRESS=n1pd7kfgvr5tpcv0xnlv46c4jsq9jg2r799xxrcwqdm4l2jhq2pjwqrmz5ju MULTISIG_CONTRACT_ADDRESS=n14ph4e660eyqz0j36zlkaey4zgzexm5twkmjlqaequxr2cjm9eprqsmad6k COCONUT_DKG_CONTRACT_ADDRESS=n1ahg0erc2fs6xx3j5m8sfx3ryuzdjh6kf6qm9plsf865fltekyrfsesac6a -EPHEMERA_CONTRACT_ADDRESS="nymt1gwk6muhmzeuxje7df7rjvqwl2vex0kj4t2hwuzmyx5k62kfusu5qk4k5z4" +NAME_SERVICE_CONTRACT_ADDRESS=n12ne7qtmdwd0j03t9t5es8md66wq4e5xg9neladrsag8fx3y89rcs36asfp +SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS=n1ps5yutd7sufwg058qd7ac7ldnlazsvmhzqwucsfxmm445d70u8asqxpur4 STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0" +EXPLORER_API=https://sandbox-explorer.nymtech.net/api NYXD="https://sandbox-validator1.nymtech.net" -NYM_API="https://sandbox-nym-api1.nymtech.net/api/" -EXPLORER_API="https://sandbox-explorer.nymtech.net/api/" +NYM_API="https://sandbox-nym-api1.nymtech.net/api" \ No newline at end of file diff --git a/nym-wallet/nym-wallet-types/src/network/qa.rs b/nym-wallet/nym-wallet-types/src/network/qa.rs index 605cc63fdd..f036b51c4d 100644 --- a/nym-wallet/nym-wallet-types/src/network/qa.rs +++ b/nym-wallet/nym-wallet-types/src/network/qa.rs @@ -12,23 +12,22 @@ pub(crate) const STAKE_DENOM: DenomDetails = DenomDetails::new("unyx", "nyx", 6) // -- Contract addresses -- pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = - "n10qt8wg0n7z740ssvf3urmvgtjhxpyp74hxqvqt7z226gykuus7eq5u9pvq"; + "n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g"; pub(crate) const VESTING_CONTRACT_ADDRESS: &str = - "n1vguuxez2h5ekltfj9gjd62fs5k4rl2zy5hfrncasykzw08rezpfstk9xtk"; + "n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw"; pub(crate) const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str = - "n1ghd753shjuwexxywmgs4xz7x2q732vcn7ty4yw"; + "n1w798gp0zqv3s9hjl3jlnwxtwhykga6rn93p46q2crsdqhaj3y4gs68f74j"; pub(crate) const GROUP_CONTRACT_ADDRESS: &str = - "n1g4xlpqy29m50j5y69reguae328tc9y83l4299pf2wmjn0xczq5js3704ql"; + "n1sthrn5ep8ls5vzz8f9gp89khhmedahhdqd244dh9uqzk3hx2pzrsvf7zgk"; pub(crate) const MULTISIG_CONTRACT_ADDRESS: &str = - "n1p54qvfde6mpnqvz3dnpa78x2qyyr5k4sgw9qr97mxjgklc5gze9sv6t964"; + "n1sr06m8yqg0wzqqyqvzvp5t07dj4nevx9u8qc7j4qa72qu8e3ct8qledthy"; pub(crate) const COCONUT_DKG_CONTRACT_ADDRESS: &str = - "n1xqkp8x4gqwjnhemtemc5dqhwll6w6rrgpywvhka7sh8vz8swul9sp3lv3w"; -pub(crate) const EPHEMERA_CONTRACT_ADDRESS: &str = - "n1xqkp8x4gqwjnhemtemc5dqhwll6w6rrgpywvhka7sh8vz8swul9sp3lv3w"; + "n1udfs22xpxle475m2nz7u47jfa3vngncdegmczwwdx00cmetypa3s7uyuqn"; +pub(crate) const EPHEMERA_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; pub(crate) const SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS: &str = - "n1nhdr07kmjns2x8dnp53tdk4qxreze8zdxj6xucyvkdj9tta73rjqa96wps"; + "n13ehuhysn5mqjeaheeuew2gjs785f6k7jm8vfsqg3jhtpkwppcmzq6m2hmz"; pub(crate) const NAME_SERVICE_CONTRACT_ADDRESS: &str = - "n1uz24lsnwxvhep8m3gjec7ev86twlhlqrf5rphlgn3rda3zu048ssjqr5w9"; + "n1qum2tr7hh4y7ruzew68c64myjec0dq2s2njf6waja5t0w879lutqadamme"; // -- Constructor functions -- @@ -39,7 +38,7 @@ pub(crate) fn validators() -> Vec { )] } -pub(crate) const EXPLORER_API: &str = "https://qa-explorer.qa.nymte.ch/api/"; +pub(crate) const EXPLORER_API: &str = "https://qa-network-explorer.qa.nymte.ch/api/"; pub(crate) fn network_details() -> nym_network_defaults::NymNetworkDetails { nym_network_defaults::NymNetworkDetails { diff --git a/nym-wallet/src/constants.ts b/nym-wallet/src/constants.ts index 55770cd39b..890724fbdb 100644 --- a/nym-wallet/src/constants.ts +++ b/nym-wallet/src/constants.ts @@ -1,5 +1,4 @@ const QA_VALIDATOR_URL = 'https://qa-nym-api.qa.nymte.ch/api'; -const QWERTY_VALIDATOR_URL = 'https://qwerty-validator-api.qa.nymte.ch/api'; const MAINNET_VALIDATOR_URL = 'https://validator.nymtech.net/api/'; -export { QA_VALIDATOR_URL, QWERTY_VALIDATOR_URL, MAINNET_VALIDATOR_URL }; +export { QA_VALIDATOR_URL, MAINNET_VALIDATOR_URL }; From bf500948b2732dcaac78fc2acbdf3059ebc5412f Mon Sep 17 00:00:00 2001 From: pierre Date: Mon, 23 Oct 2023 14:07:31 +0200 Subject: [PATCH 032/236] init --- Cargo.toml | 2 +- nym-vpn/ui/.eslintrc.cjs | 20 + nym-vpn/ui/.gitignore | 24 + nym-vpn/ui/.prettierignore | 2 + nym-vpn/ui/.vscode/extensions.json | 3 + nym-vpn/ui/README.md | 31 + nym-vpn/ui/index.html | 14 + nym-vpn/ui/package.json | 38 + nym-vpn/ui/prettier.config.js | 9 + nym-vpn/ui/public/tauri.svg | 6 + nym-vpn/ui/public/vite.svg | 1 + nym-vpn/ui/src-tauri/.gitignore | 4 + nym-vpn/ui/src-tauri/Cargo.lock | 3678 +++++++++++++++++ nym-vpn/ui/src-tauri/Cargo.toml | 23 + nym-vpn/ui/src-tauri/build.rs | 3 + nym-vpn/ui/src-tauri/icons/128x128.png | Bin 0 -> 3512 bytes nym-vpn/ui/src-tauri/icons/128x128@2x.png | Bin 0 -> 7012 bytes nym-vpn/ui/src-tauri/icons/32x32.png | Bin 0 -> 974 bytes .../ui/src-tauri/icons/Square107x107Logo.png | Bin 0 -> 2863 bytes .../ui/src-tauri/icons/Square142x142Logo.png | Bin 0 -> 3858 bytes .../ui/src-tauri/icons/Square150x150Logo.png | Bin 0 -> 3966 bytes .../ui/src-tauri/icons/Square284x284Logo.png | Bin 0 -> 7737 bytes .../ui/src-tauri/icons/Square30x30Logo.png | Bin 0 -> 903 bytes .../ui/src-tauri/icons/Square310x310Logo.png | Bin 0 -> 8591 bytes .../ui/src-tauri/icons/Square44x44Logo.png | Bin 0 -> 1299 bytes .../ui/src-tauri/icons/Square71x71Logo.png | Bin 0 -> 2011 bytes .../ui/src-tauri/icons/Square89x89Logo.png | Bin 0 -> 2468 bytes nym-vpn/ui/src-tauri/icons/StoreLogo.png | Bin 0 -> 1523 bytes nym-vpn/ui/src-tauri/icons/icon.icns | Bin 0 -> 98451 bytes nym-vpn/ui/src-tauri/icons/icon.ico | Bin 0 -> 86642 bytes nym-vpn/ui/src-tauri/icons/icon.png | Bin 0 -> 14183 bytes nym-vpn/ui/src-tauri/src/main.rs | 15 + nym-vpn/ui/src-tauri/tauri.conf.json | 46 + nym-vpn/ui/src/App.css | 7 + nym-vpn/ui/src/App.tsx | 53 + nym-vpn/ui/src/assets/react.svg | 1 + nym-vpn/ui/src/dev/setup.ts | 11 + nym-vpn/ui/src/dev/tauri-cmd-mocks/greet.ts | 3 + nym-vpn/ui/src/dev/tauri-cmd-mocks/index.ts | 2 + nym-vpn/ui/src/main.tsx | 17 + nym-vpn/ui/src/styles.css | 109 + nym-vpn/ui/src/vite-env.d.ts | 1 + nym-vpn/ui/tsconfig.json | 25 + nym-vpn/ui/tsconfig.node.json | 10 + nym-vpn/ui/vite.config.ts | 20 + nym-vpn/ui/yarn.lock | 2102 ++++++++++ 46 files changed, 6279 insertions(+), 1 deletion(-) create mode 100644 nym-vpn/ui/.eslintrc.cjs create mode 100644 nym-vpn/ui/.gitignore create mode 100644 nym-vpn/ui/.prettierignore create mode 100644 nym-vpn/ui/.vscode/extensions.json create mode 100644 nym-vpn/ui/README.md create mode 100644 nym-vpn/ui/index.html create mode 100644 nym-vpn/ui/package.json create mode 100644 nym-vpn/ui/prettier.config.js create mode 100644 nym-vpn/ui/public/tauri.svg create mode 100644 nym-vpn/ui/public/vite.svg create mode 100644 nym-vpn/ui/src-tauri/.gitignore create mode 100644 nym-vpn/ui/src-tauri/Cargo.lock create mode 100644 nym-vpn/ui/src-tauri/Cargo.toml create mode 100644 nym-vpn/ui/src-tauri/build.rs create mode 100644 nym-vpn/ui/src-tauri/icons/128x128.png create mode 100644 nym-vpn/ui/src-tauri/icons/128x128@2x.png create mode 100644 nym-vpn/ui/src-tauri/icons/32x32.png create mode 100644 nym-vpn/ui/src-tauri/icons/Square107x107Logo.png create mode 100644 nym-vpn/ui/src-tauri/icons/Square142x142Logo.png create mode 100644 nym-vpn/ui/src-tauri/icons/Square150x150Logo.png create mode 100644 nym-vpn/ui/src-tauri/icons/Square284x284Logo.png create mode 100644 nym-vpn/ui/src-tauri/icons/Square30x30Logo.png create mode 100644 nym-vpn/ui/src-tauri/icons/Square310x310Logo.png create mode 100644 nym-vpn/ui/src-tauri/icons/Square44x44Logo.png create mode 100644 nym-vpn/ui/src-tauri/icons/Square71x71Logo.png create mode 100644 nym-vpn/ui/src-tauri/icons/Square89x89Logo.png create mode 100644 nym-vpn/ui/src-tauri/icons/StoreLogo.png create mode 100644 nym-vpn/ui/src-tauri/icons/icon.icns create mode 100644 nym-vpn/ui/src-tauri/icons/icon.ico create mode 100644 nym-vpn/ui/src-tauri/icons/icon.png create mode 100644 nym-vpn/ui/src-tauri/src/main.rs create mode 100644 nym-vpn/ui/src-tauri/tauri.conf.json create mode 100644 nym-vpn/ui/src/App.css create mode 100644 nym-vpn/ui/src/App.tsx create mode 100644 nym-vpn/ui/src/assets/react.svg create mode 100644 nym-vpn/ui/src/dev/setup.ts create mode 100644 nym-vpn/ui/src/dev/tauri-cmd-mocks/greet.ts create mode 100644 nym-vpn/ui/src/dev/tauri-cmd-mocks/index.ts create mode 100644 nym-vpn/ui/src/main.tsx create mode 100644 nym-vpn/ui/src/styles.css create mode 100644 nym-vpn/ui/src/vite-env.d.ts create mode 100644 nym-vpn/ui/tsconfig.json create mode 100644 nym-vpn/ui/tsconfig.node.json create mode 100644 nym-vpn/ui/vite.config.ts create mode 100644 nym-vpn/ui/yarn.lock diff --git a/Cargo.toml b/Cargo.toml index 4b18c15e2c..93b62803db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -119,7 +119,7 @@ default-members = [ "explorer-api", ] -exclude = ["explorer", "contracts", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "cpu-cycles"] +exclude = ["explorer", "contracts", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "nym-vpn/ui/src-tauri", "cpu-cycles"] [workspace.package] authors = ["Nym Technologies SA"] diff --git a/nym-vpn/ui/.eslintrc.cjs b/nym-vpn/ui/.eslintrc.cjs new file mode 100644 index 0000000000..a1a2282c97 --- /dev/null +++ b/nym-vpn/ui/.eslintrc.cjs @@ -0,0 +1,20 @@ +module.exports = { + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react/recommended', + 'plugin:react/jsx-runtime', + 'prettier', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + project: './tsconfig.json', + }, + plugins: ['@typescript-eslint'], + root: true, + settings: { + react: { + version: 'detect', + }, + }, +}; diff --git a/nym-vpn/ui/.gitignore b/nym-vpn/ui/.gitignore new file mode 100644 index 0000000000..a547bf36d8 --- /dev/null +++ b/nym-vpn/ui/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/nym-vpn/ui/.prettierignore b/nym-vpn/ui/.prettierignore new file mode 100644 index 0000000000..8cb9ac2499 --- /dev/null +++ b/nym-vpn/ui/.prettierignore @@ -0,0 +1,2 @@ +src-tauri/target +src-tauri/src diff --git a/nym-vpn/ui/.vscode/extensions.json b/nym-vpn/ui/.vscode/extensions.json new file mode 100644 index 0000000000..24d7cc6de8 --- /dev/null +++ b/nym-vpn/ui/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"] +} diff --git a/nym-vpn/ui/README.md b/nym-vpn/ui/README.md new file mode 100644 index 0000000000..5d2ff29980 --- /dev/null +++ b/nym-vpn/ui/README.md @@ -0,0 +1,31 @@ +# NymVPN UI app for desktop clients + +This is the application UI layer for the next NymVPN clients. + +## Install + +``` +yarn +``` + +## Dev + +``` +yarn dev:app +``` + +## Dev in the browser + +For convenience and better development experience, we can run the +app in dev mode in the browser + +``` +yarn dev:browser +``` + +#### Tauri commands mock + +In browser mode requires all tauri [commands](https://tauri.app/v1/guides/features/command) (IPC calls) in use to be mocked. +When creating new tauri command, be sure to add the corresponding +mock definition into `nym-vpn/ui/src/dev/tauri-cmd-mocks/` and +update `nym-vpn/ui/src/dev/setup.ts` accordingly. diff --git a/nym-vpn/ui/index.html b/nym-vpn/ui/index.html new file mode 100644 index 0000000000..03abf55f90 --- /dev/null +++ b/nym-vpn/ui/index.html @@ -0,0 +1,14 @@ + + + + + + + Tauri + React + TS + + + +

OQ>`gI*X1@nVfw>FPq3b8P3b*dZqrX>`a?vI zv0i9R>7_2W=_fJ$L83Whn1mZrXiD^rE4& z3jtO!{eGeku-+wl?$S?T`h7$%v7Qn=bLpoty-)N$))S(4UHWRKZy|aQ>oL(&m!2~H zUZNLRkBFYQ^wXGr579HMheVHE`sqx+o9JDvSNbSY?LBhoXE6P)TCc}u`Ob6-ucN|R zrtri82XopxHphr`1h0MoJ)4NQ+p6DgkQ>`gI*X1_- zJf>eq^gh-zttq{y%WeAkOuv@sJ**d6Q+lb(ZTbaFzlP`q*85shdZo*4`X;7tCVGzb zf!35B>yvYvej(GZCVID_!zsT5MS2#MW&Ip4NMY^%B9@ZZDP{_9pew02NrPikco#G7 zDpKjRQE51yN}>;%I;<3$!poR`CD9YC_laJ*^h=n21<_-y_lVwi>6bG7a-v6AFNofA z>6bD6GNOlA&xl^Q^vjukDba`cSv*~$=PvyUre8wz3hN!BcU}6GOwWj3Vm&3gIILhC zwOw;~MjPf;EaYMm(r<*oyL+;Tr|_a?FdYEqHbITlE~*pENG+G7`LeaJ31$koFLb$0?=k%>qK6F~dY2(Q|4p1C zQr$7Clw9v^NMR$vJ6Ot@BxQgfE0+*GYv`=)+{yGcL@%)(6TR!w?_&BHMDJrgB6`QA z-_7*XiQdC{Nc7aD-^29Nh+bfQsN0I#tBFg$m+2|dGptuck6ro}rmrS?7waX_BbVN1 z`l&?kV7*WD(52tU^iyiR9-AfG(L;i(@+}&w@_&0D!h1WJ3L_>*b`P(1Gl4V*$mu<_}QY7*3^kK)#bKM_(`U(B>DjB ziPn_f)#Wz*DW=CnFR|Xyn$mM!ZquJ;`cXvhV?EQF(tEnxrVp5YB++|VFSMrgQkUEG zXPABj(F?5iwWjn+m)rDbnSMCYbF2@vru0ysoZIy0n0^@1vxW|*{4NyfSyYrmoeC+e z-9OJ#4y{wn6ke$-sVY63We+1Zh4%vE4k4B9G%5|1>l1y@)M2I26yA$WkBFXPy+`!Y zrN6}VgNYtvy&!turB_T}LG%dg8PR(#{bi;vCwhqWF3}5@{tDBV5q&sQv^4XnwnOyX zrN7Gbr9`i=o)SHC>8~+;3DE~wPlzrKE11IDx;Z?f4fAytvY3RFjSzTuUl#EcUfv9* z1HdjP|XmH(d^`*EaKTa zXTZBG;JXcyRW;|hLSw359O!aeXC5x47rXyE#=96VHKsdVU2ek{GyLB$-obdK zF@;An?Pg(fFH0EyuNY4;9%@YCi7vO*d?~~K1>*_EV~r`iqswjhGKT*%#$$}98dG?# z%We2_hW``BBaCMnQ+Q98+wc_({{hCs1`fT+aC$xR>*$V9uYumt5W?E~!7St-amWDF zMxUM%JZs>r)kF;c2aJ~(j|tv&;fFB%?=jxTctr4y3qO?Me~0lN#zTUqF8nZt|1HJ~ zj1P4yQ9Cqo;fFK)`xwtLUJ*QY;YTq1Z!n%=d_eHXg&)cA12NvkcuDZkg&)Q6zm|AC z1dC_WnYxb3YMZH(zba-nhk|sV7PGj&!t0VY)&-8;7>eRJ8%$RxVc6AtqHd*C)$s2x zrD_Iep;XPlAZkJ%*uwj?ogMgHh098Tw}!?P0V(3VIwv z{}iJ+MvGC<;~DxrjCL`aje?%Q&_BUwiqXy}Xu{Ax#%PSuWEAv7hW?R78>6#GU}SzS znP!I}thYMJ!fJH(hY~iUvryL7jLu?>sWWFsm)rW=lNtU87_YX%U7^Mlp6PNMzKY?$ zkMRMsF1O*QGW@$3?_<2DF@+CwxeZ^<@ZZIF596iA z6h74DHaunc?_j*Zc%?CgNBU&khM&gp-^O^}z~Ky^L6M#|MLE);5W?E~=`7^8WQd)X z(^XVe4jUSqmOF!Kzlp2dZB!Ym)+czil|3}sSZ@u(e*@zw#(M-GxbQO>{_7Y|FkTS6 zbm3<)`~Zx{7|#jbcj0Rp{%aVIFrE>-=fXP-|5c2K81E9iaN%b&{5u#QPDQ7~4#9I5 zeh$Nb1>+UQQ-X`53Ffq?H^*RbkfC|vbu8nTamJvL0dFp45zod|&0IRjTWzm)r158NNTpV~lq+rtm_S+wjX6{&kE;7|%4O@V+j$ z;g>V~r!gKjaOg~iK|S2->RwQV^z@E~5H{Sqf`$AP4yizGPR0?uXy9ysb|u62!}tK> z3Bhw0eig&NhVc^PF~Ktzo-_Qb81G{|B6#Y;uV(mHFkWChBzWS&H#7Xp7|$_2)J;&e zme_?~!|*R*Ji~ZJ@W_Q<%kVE^yo>Px!9y2*9mBsM@p=RnPiK>HDhm!V+JA`S3?9fb zwK)*1qwOPPuV--!@Vcapb%A3yfuc~WdPKQl67~k4jJv_AYV`McshZJWBvmu|i`!H> zZ&on$a~K`^c(gGJdLu(Wi_rl_D=4z{r!~Eap`XEMAEV_c=*PZ_?ikM-I6xT`=^0LxBOMBBz(!|%7P6ZRF_UovT}8b;8k#z?Y^QV|(>{r-+-+1D zs#X$w=s7-q+|Te`G2X#=pWu}Xe}Lhiz<7%Bg5U!e{vg9Yj`0NJIl)U8{t&}=!FY`E zjNm;N{xHMmVm!ilm*9m9e}v&XWBiAr`I@s~huFExE}8u?Z2th+DY3<|1V>KL9D&s@ zv5oyv7O@kKIM7DGd%ss7on2jPIG!f!@kjeS!DE(RH)D^n32*j}nE$Tjp{|_|amQ)3 zA7}0k*!?zg(^1_gn7ci87a}(q)qRq=+hKP<^7K9_C@XwMs%NH?riMF*gde}exQ$xPpMjoZ5wm1O-FZPr6#}|pa=4G__*BuZgX+R+A1d};^{csXyGSUiqtzbt z&)di|c92KqOo-etS>X&QHZlMT_f=)Fsi6FAoTH9joAUz8nIUsZoC8I7&O)4{j%J(l zBFmXBbNV<3ite2KaE>~&5#K?v6eiiDKqIt`O@-YEwAvC^v;dtZiqT$F_%G0)brP#}Iq3k2nLa|HaLfIjy zg<|{3g<|EheZN1?+jC5;ru@gEv2ACK&06HmTK%r?dq1A>-(o%eg+KYaQK}>%Z}vzxCU{^Sj^uz2E7V`iU;O1?{q=!=^Zmd5yTAX3 zfBeBe{qw*4>%aZ`fBf)2|LcDo^rQd&ap*1fmUv6OW!`dcg?F$Qd53t1dWU(3dq;Rj zdPjM&x6(V>JH|WKJI*`aJHbo56TOqXlf6~mDc-5xYA^Lp^G^59@YZ-|dS`iSy^eRb zcaFEtTkmb~HhSlJUGF^aeD4BplXszak$16|d6#&XdY5^Zdslc@dRKY5ceS_KyT-fL zyUx4byTL2G8@-#no4s4STfN)7+r6H5hj*uUmv^^!k9V)P#p`?bdG~t{cn^9Hc@KM! zc%}EK_n7y%_k{PP_muavH}IbEp7oydp7&nxUi4n_D(_|Q74KE=HScxr4ew2F=)L8= z?Y-l@>%Hf_?|tBf{$hWLztmsmFZWmY2m6tKh<~Vmn18r`gny)elpp&m{iFS3{A2y& z{Nw!-{KP-eKgmDYU*(_TpX#snQ~xyobpH&0jen+pmcQ2T_-Fg)`0M=j{sw=ef3Dy4 z&-2gsFYq_{7y1|Z7yFriiGQhonSZ%|g@2`gm7n`p`N|{OkQ2{KCJ{zsbMZ zzs0}RzszJH&8zyE;$p#PBnu>Xi(`j7gL`H%Zg_)q#z z`A_=;{~7;T|2hA8{{{a=|0TcjU-n<|U-e(}U-#ee-}Hz6TmIYrJN~==d;a_W2YwhV z4weKw@*chG1iGZqNn}chDYlG{8>w_DDBDgWQDY!YfCAc-XEx0}C1$P8@ z26qK_2loW`23vxDa9?nL@Idfj@KEq@@CeKwJsLa~JRUp|JQ+L{JRJ;zXM$&g=Yr>h z7lIdqm*oE{F_78AUpwEQvnbo=``^LCj4<4Ei}+->Xl%~O)8#PZW$}9Gs{gj`s`m*B zIy6~g-=l^m@;%~}(AQ6&P;<^*`H4m@n=>K4(tuA({XNCdLN2SX)PRpPgWb)t@d>!l zVjRA8O65av@C98@K5s-WTQD&VmceClk-WR9T(;i?jC#hW!&8dn?Gog& zg%j}C6ytCSc_l|ga@p9#OjtJaYe83h)Pn!Qctn01Bwi=SCTh(mm)Z4HUk1r-sU8d? zJ~<8KpvZh1)Uj)9t_AAWAKK~!`T=e^OL$3a{YFBywVel!m4*6c9C=<-(K+c4SB|J|OLY&Z*MVVl(2XZDH!V;b% z35jgDWtITH?L3D1&*;XJgJiapF$GFJpS6Aohu&ya+KB*>!NO6HOvXTsqu zVNfTSFNX#bb(19bxhdwUqpWQP{s^n8Z=9YcYHwU@3NsIyXid$?7kgNpO&cA_^rwhk z%F~b0heYq~>Clg2`jbSDv7Ts6)xG;EhaNNi38D`_iMC9rHKpf!IrNoGf1KzE)(1q- z_IBt;GyO55cXvf~kF=)hp6VHhwz;)qnEoiy6Z{nQis&8vF}+PcmgyzY3;gWl1d3v1 z1`}$Fz&h}23y!m_>P{Z1S#xngAwP|qlgto`jHO@MAJ5c>i8{bfuuDc!PhjdpL@i`* zZ0g!kPq0IqfYvo(>Vrh>%je=4HG+_j+yW;u^#P&|@v}`j5b}}gNld+;sC{{Vc2n0b zgnXoWGE?s(Y9&WBM(wDlE;zUADyH^{8e%n9w`+H*r!aL(Lv0L7I^q`HFd8xgDL52z zebdsmQ~s$|R;T=XYuR)pnVhULC*@FU>g3RI-GhHM)9)erK;C=P=oQhs`i}o?Cx?{j zcN4wWxal5jiN3C@uDgC(L7RRW)9)gB)wmfL=tEssrAPXCPi^|?Ouv)p5!U;*!F{Fuh0g1nUD`SEUbK`k73>o#bAC|Y(eLd3)qW9p#bVE-*f%U|tZ(#ZjRELl6 z4ZWaGFxH=#+v>iN>DSk~7$L#IGM|3y*_Q`V{V|aAAmRvvkBM{j7cL@?ettfeZ5^L1tsZ#z#8VH(p|8H72~Qmd%*3BP(mVn@nq}fA8sX+llE?re8|*1nY&? zlwRs`n|>M7FClu2^}g2h*hH7x^vju^5k10sr8T8T`=}10O}~Qa7ZW|idZ;y}C%W9G zU&-`~h(46_jb^XLT2p#Qm)rEKn0_JA2Ut(Fru0;|^)@|c`X-{64PA^0p(r|oWIFDU zyLx{>3TyXQvy=-+O0SUu`jGssN~fW->95U9KcDCY);mN`T>3RkKac1+)^nKJZ+=RQ zUHY|5?-IR>^-kS;*Hi7Vr6QMp9n;SxdI#%0*u%}bhc5kkrf(#AN^~;%8R`kEww8GV z(>D-3!Fs=O@t$a*1D9SfeLc}*tcOG|UHXkoUq|#1>j&V?E)FtS0dpNr+xEGMWt>AY zhVnaz`m6){wSuBxd%EUue&7>$H(OQ>2G6cpGZ-u-YX*aZHkM9`-NMukQF~bJkD}hn z)U`y-uv(0w-p16kh}ywwcNFz@rk+XE1gq&NYLBUFh#Fxv9!0%_sb>&%h`);pM^W!& z>ghx+v06cqHCWoR?qcd`4Ye^?>kEyXfGR!P-_~i}ZDloBOKaH-)_StOrduzyraIox z_07aROkYj(0_#Jf$1eR|rk_gm9P5$R^q@hP+fF@On0^Y;Gpr|CQ+ijI+w?xuR}sB~ z^^Vq*Ug&b0ejn3MCVGnXOlwN->vEfZKhsYldV=+y)|5Wbw&#{C< zNJ1AUWH!M}+c^`SX9*EWNO3~PCYWhEXTl3C;b4*w`gI)8#h( zWu`AB`T*-)ttq{y%We8AOkYCu66?9vlwRs`oBk@(7ZbgY^}g1WUg>h1{uq z(3;XieRgisUuXIU_20IbHj`t0Nc7mHzrpnPiJmp|0ImatqUf}ST2<>1=~P$;HWGZ3 zrMyQ{I*k<2E24)DolV;fnf@-(Q>+h&Ud^+|EYsg&`a49Av0f5=;L_h_`rAa0uwD?o zbm{Lf{Vk%0SkH;xcj@mkeMt1-glH<}e3KEq=hEL}`kO?ru-+wl?$Y09`Wr+qvECti z=F&f4`s=k`kIkyR*f+Z>YzpsC!~qAhvwJqjh*M;HwI5!>#pb$n)vvrp)~4538#sy! zCVgVpXR>Qbh@Ow97Td3;tyl` zGeqxTy{|Q;SGwG$AI|gv(NnAsw5Ie>U#Q!rAHnpeiJoA6Nc7mHAIbEmh#q4-(weG! zs>^M4KZ@y35Mn-%CDeEk9JYc z^!|VpHgG$dr94)rm?^xp(Sr!C+u+y~-Z6}OlvKLks5EFX(K}5YR%)#IN8raYy(D@M z>k-jYmwp`6A0c{y^^oX^OFy3J4--Ad`cO9x)mUPeege}UB6^1Pis+F`PniB7(YshL zi5|N26Pf-1(K}f06MeY5V|0HK)9)vGiuE4R#bE^p(L{52MjPhIEaW~Ck~Bi#-H|Nf zDZGJR4Y9-N0C1H}P$RW|onS_4!`(zZ?TErAm?=DG!YM3a3rQH@gi03im3PjBQ(3~j zB%zNJN}FJ&@SF*&S;9Rep}+|}n_#B!oCzsQxSJ$oI3c$QW(v=la2iXvizIY#Lf0mk zDLiMw=`7(+l91qp)FzlIJZHigEa4845aEQ_CYUKaXTlnm&}$?#j{}hDNHE^bo-kOC zc&3%rNbvSrHY33b{~=hUHFcs+b-ArqKa1(N5q*I5L~Ba#>T;XDmg%<=y~KJ)Yf8^` zxlQjd{T8D4v7Tv7={;R;)6Zu5%|!2Ez0jJ{OI>c$&tdvaL@%)3*P7BRU2fCYG5toO z=U5+TP3fUN_qXZmnO+b*Yv|CsbfG9ZgT7XEicWDqk*<{ z*vRzjiJoG;Ao{?ipUd>?h#q4-Cwl49yG*~9=n>X4qW4|;c}%~C=poj-MDMxu^O?Sx z=tKO6ryZgfF8unYK5m%fSVInf7LPl%qm^b47ORjsSB*#w=!D^*zA6rS8e z!`+%=L^^`Ih~-^L)~4TB8#s!4P!vaTN3R7O#e53yV#}(5;T1J&28Ow0&A_l|V}DFO zX=O~koTweFW}~Q=F!eH`CRj~JQ7>icr9_Re8jqr0#?(uQI+TA?ZMJJTih4OyGolW# zT0xOD0=l=ZVCuz0?PIkZMZJ=#7ZJ67_2WbzoOB{Q{zQvEJ93(koqV(>F8ye4=--KG2%d!(Hu= zmVLu@4b#sfdW`iU(PNi>Ez`S1kFXwTP1QZs<+d$z9n;SxdWiKzYf8^_xlO;G=^KeY zY~0&GoQ$=m^g@^0^c$GIf#_93hg1GQ-8rFo$`?m}uJ;F|uz_2_Qr6cgb_%c2g9t8b zaBK?iM#ilpl`b2V1}!Ffx2eNQp((tZn0^k?`&f^N-f`(SGyQC$_plxkJ$C80Fug7m{UrY21>lM*Mmwp@5&mwvk>jR<>^&h^rHT2t=ekRd7STBiQx%3{> z*AP9$dY|axu!4hV*Ml7A$U9ib86+fbgg~>7WD!r{rFs{L9Zm;;ciIFsQaim)FeA0$ zE~1`xL}3%m6rMBTE|zc_Nf_XSN*3`Ho-^TYmXMN!K29iYf|+{+S9B?%c$$Zdj|!gD5UVF{;@gbq&V+5|I&=S=9cgjFOV!3n8NFjIKWg!@>+ z$s{4d39(HuQ+UpV`&q(CjfCcL05Tm3#=F>Kne~VdSXqq(PpoA#60GE{h0I7W(waI^ zr@GvBvU`x}3DE~wPqe1=t}eIf4>A1&qL*0jXie$4F1P6qGyQm?_pzR7P3b*dZqpxO z`f)_>VZG3r(o0=#(@UlwOY|J;eXS|I(&aY&QKlb5^bG3*ttmZpbzzS&{b-_h8#?qZ z9Vm*p9U& zm;Myfk0g4C^^E9!m;N-hZ4Py^_b{gm;M~n52^KfY}VVAPT}=bSj!ZiIN;!-*Ik-pL^^_dp5;YkZHmU) zz)_q-QLw3A3pk4T6y6J#RRhC=Yt{@5yOK2n!>o;^lR_^tbp=rqtfr%=FEMpFQ6sFz zqo@^Aml1V{@2?k*qQ1=3r9>TIwNm%jL%WM^*H@Ujgs6S2mZPYzGIcRgGpy#LsIM_K zBx(n%-BHxnnfifeZ`0ctxTQiPQ+Qo{m$SAG>T+A%-(~uc=q1(@ttmaz#%9mxm#UOv?Z`3Jf3NLQ-Ac9L89Gk-XfN`&rO6QGAgBB4zZtAd7XbLY} z!mdRpdWQ9o=%Gtr%=A}@-o^S*?>@CVhx#UsZM$;`(_bNaiuH=wTh^E`2%EUm|*h^&ZiCE`0^lUnF{n^@8Z)u!3t(cWw^PXu~|1g}gvQ zDtYJI`Wy-G9>^k|!t3eADVh@<07f=Jjntm66U<1hkMFHp+5|I&=S(<+B|JwG3Y^fh z3FZ%Joe77sgl9=Yh7)p|V5ab#35T(SXGlVd6FN4*OyM~b4rd7ik`UvB#3q<2JZHiY zEa7RA5aNW$CYUKaXTp&z;VF_(;X5i1Wl^?PGll0&IEp1aNfJt&Ft7<`3eTAkvxFxa z35}6p4`ezL9Oyd%xAllCt*l0ZkJqvp2^O-lX1r5sO?Lyj+|~^o&Gg5Jo@2ezn$jbE zpW!zB7^Xi;^bG5v)|8&;a+`iE(@Uavu^wwp=^b5e(~o2NBScTJo@!0$xh}Wq$20w5 zq9<6-w5If)F1P6?F#RE-$5=14ru0&m+w_F#4-!3U=+L`_P!ye3t~*A(4!SKt3L6QY z$Wk64DMNYha?|cJq8AOFT?lXz)9)wx0P9_%=PvzZrr$^O66-0^Gnc-K>3yR2v7QjU z>(WnQ`WB-1upSdVb?K)v{a&IMSdWOFxb)RbzlZ1<)I9-koG^(#G1rQJg?gu*1e(@%a?q z8J1N8!#ir$3=D_xRDec@7`L%>s%Z^Vdqf>zwGxjWpp~WSnM}Q%sC}%Kqo`*w^){jw zSnZ9Xu4U@2M9r|8kD_*%dJ9ogtae9H&t~e)M2)eUjG~^y)SHMJVl^5?UB}cL8)~DS z4&liYbl?`bZtB0@%4*t-;SEf`f#?IQ$68Z*SC`xLjZD9u z=q1)uttma%DZQu5ZF-mK*Al&l^+Ib(FLk+1Kac6x5WT>9Uu#OQ zbh%AGpXr;4o@0HWHKoV;p z^(JX>Yzpr}#$81!oi-{Br~H!WgQgBEg{JT>V)~UtPq5x6dg;_mD$rnS(I(bOyM~bu4M^bl2GD=flV+|c+Q0D zSi-p^p}+}!n_#B!oC(*ngpG}a#z-&+nT`bejb|FM9`Ob%tC8S_S~erWOjg!RWfWRd z9ppfl+j{ka>FbH!#d@hVr4MzvO}~-p>xkaLdZjg`N3Lf{-Nf{Bh@N6S)SA*0U2d!U z%}hU==n2+ittq{u%We8COz#jq#(JtXrDwX_rr*l+wM37w-qo7Y3tev0Z)5sdL=PJ} z^e#hq{+sBuQr$7Clw9v^NMY^%c9wD`Ng3eB$|Xe48akW8>oI)|(MznyMDM!vJD7e3 z(fe4Bh~9DOcQXBSqW7>K5b9cxYU0xGW_n8W4C@uqW0!sp(^nI{ zi}jM|kxRdq>8BFCgY`bqLzljV>8I3sJvK|Wr&D;T3Tv6d69*j3m~Y!0BhnFEpXIG0 zYm+qA29Dwwih>>Jr`W;%=2Lk0Syl}UPp(-rFdS|z6f;~1+gLi;c0W^3BI*FE6%<)z zsrmp@Pb6v|tK}%_gG^0`T41#|iuw>!PatZB)qE87VWu8W)DBj=qo|KC^*Ev?SWQP! zOQs%6)CjBbDC(n3J*J^H+o{mVRe15%jz6Dx%*txuc62S9f!h#2TQt&|I+3Qj+|~&{ z&h(W;A7DMvn$o+v+@?Rl^qA-+);n5LdalcD`jbpQis*f;XIfKwPnX;Dr2|aUqbW&))S(O!wRPGwr&p3Xv2J!g)Al^Wg`UM z-Iql?g_k#j=>YIGo1jK&VVz(`YK0`tNUdiR%oLt8;dPeqW4Y!gAj1K<4KOo!&VV;q zz<=X_6bE!{fSJH^2E54veuM*J9FW)mGk@m{7_xwaa6pIyA{$_)@0*4JjHmZF@-0(+*b3&4F4C5Cm4@4rtpp~x8X||{?8bX zF`jBn;khoi;Y%6*PZ*Cdo@q?sJzZ|YmofYY7!Mmb^d`gU^~kTIJ3_q%dPhSD8~H6~ zA^(U&2B0>cbC41|Yv8QatYG**V7$b5Oz^G?KbYZvkMTanBZ7Bac*O9(!*~zlA;D7@ zeh9<=7UKoRhq{%h9h$iCLmB>kjOQ4y2p+re!x;WI7|$?1Ab8}$4`=v+81G`dBzWk; zk6`#;OS~R}#k1*5T}NfL&D6;BN zbw^oM4gda9s%CH&O4SSuqBfPzsKpHZ3yfCN@Mr^ytf~}U$Aoy;WjiH9Gr437gSbC~Ip*XR*fAnX{wIZT;Pchyj_`rpq z!SG+lc!KeQ;H3*+!|($z9%DQwc;AJe$?#vpc!cqc;5`?97Q=rP;~~bo1TS3pT84iI zke|XK6{yY0ID!`q zoDI+}XZU^?A7DHoc<#clVEETCUSd2Zc;>>dWcXJx-p6=E@YIE0#qh6Syuf%!@Wh4Z z4F595bBqsl6I87wcHvhu{7V?mFkTTna^ag9{zZ&;F+L!8=)$jI_!lHzkHF&TY%)$| z!68Qb4{@Bq16igv2ZD99{oHdci(7!#C2gz=9J>h=g<91k$_lykvj1GM~+871BfuWzp=m4V?6xsUInidTG3`YAHEk{9bWay_c znq#yW1-*%(`(m_<(QFj-W`^#A(G;VdQP5i$Iv=AkMw3y{TN%2yMH{2DNMLj_PM6zy ztJ^HBMrV6T*o@9XSz9wYi#4WBZXI22>u+yo_@^*Flugv&sm2tZ>2e$1WB8sJuQ1-# zn8FKPZo}_j_#PM^U_95D!b@Fl!|!DHJdBqZ?`urql`gm8cQJed<2{TIG^X%SpD)|+ zyBR)?@dD#Rg2yiW9)|CZ@w|ZpltGc6;Y2yop|A#QbapQb*-eI+$+&^8qTU`2O&wXb zQ`*9`PvR{Gpj*lOGhVP2;4#xWguUzEd*e}L?i z*y31%BPVE%!0MOS#{LM4*a=4*Xd~dg->Z+#uC6s4Pm}fdqkW#BwEVgmdyGwZvvORKY?XkNMxyh*Rj7Q6G2`$KicBh7*Bwx<}o4Q7*lk^6%Y-KUv58@n-f4{W#}=%c2sZyYdqYYD?~ z0QWl$=*OW*#gLCfs>70p$TQJSt~G%_2b=RU z%L!yo7w16HofDCq`gCD)UST=)9nAB6510ZSgni+w_Jyma$OBEk5RRYvnBFHCla+zL zFx*!zte~=TAzUJ47K$TAE|mAHP_GotTP~E32~Z26@zo2*8*dj4N4`>?w$&@eUX}}G zAE6eCT_P9C4oNK(+fObOE0^v2{dwM=V`4SsKNgK`J8Nv#B5&4~*}nJVIsYwI(_bk5 zH$Jw_uZ;bl_#-Z;-@{)!-=DK+?)Sfgw{#e0w}{Sd(b$}mr<*OkDDnQbuB;eake#!{ zz6I@^E`8y$mKVyQRmT&XWkP@VbZK;rBRFPc6v)&646g#3G*bH!PN072aWra-;6~62?g<5_|LM5DXa@#zPRZ#6#6ylyM8NW2dIvkW%pR^oLt-~;WE*6Q`!GD&))}1b1H*0+B@!1EB&m5m+UN>`m_W0J~b?~2Mu(4-~*UcW^W_;U& z#EZ@AwjSShd>ipP_|G!f_FIeB!QDZ|;jfnK&o1@$hU&t5&D&rnjlAVsmiuIySu_ncs@(iD%%T~v{p6OOWfqC;DmUtEvq=1% zGW}nSgblWu~_$OVzKJh#A4m6iN*g1dv5|RS9KitzwRdq2?2U+M(q8>CcriV zgAq11dYw37l1WC6voLE&GD$qiEKDYucqU-CRvH1~u{V2z06iALV{bOo>}?kFFxa$h zY}$JpW4n#PZrj-WtLjvprRw&5EtE;V|M#W!eR^HD&;6Y`b@p@5J>@$!DnIxubZK6F z-)~Wo!(aWCxF>_w?ljkTQ5yo~A3G!Hw6M#9cJDOmvQ7g5TD;S!2f_}DdN91hwK>pm zLhE-Lbv)QFjbe`#{X7R-!qcd~!R}}dc2v>NbFnQvjk+1^h2~=D=x1n2N{ddT-US*t zPy|9pKW~S{eXO+eY1HyzKeHX)5QQKU(0?PRQD98s&TBwt>UGAVp!5z4_KO&91e+)P zi~j|Mq30YcZGW0ujV^62;ma1#CU1Y*k{z%CS%`PTx3y#&FxB>_of?Oo59Zk(k^{p9 z30rhwd1ehrm;sN0nJ5@E^E*HvMHxfLB-mm!7t-cnusMT*mB4Hi3^H$r(%eD8mV)gl z*gOn2Z&0vhU^)s0dA&nvyFtOI(Sg(~fV_j=3I`AK@rL>F4abgRJG6K}GxYio3eXOX zMg#2Pihud{FBbUcumDW$9xY-ISSXIpnLBU0`3tsRxWkS+EgIW-mtA+;{at%3-gB?L z_t|&9{Y&FZ4mj|jgAZAH=wXMy`#tYHV%d>Lz3=E_-hb@!<38}g<3IG_6IM)=f9=;l z@*BT-;=lT>-~QLX^Sl3MqmclKCTMN^L+X}ZA?kL<@xT|n?;hsXHaBtzh z!u^E@3J(@OU3jR_EIeFzr0{6rvBKkpCkjs%T7}OPo+>K=yg;xvT zE4)_te&Gj&9~OFr9~E9N{J8K&;myKN3O_CM3qLFTyzq;{TZLa1epPt8P${k|t}d=A zt}U)Bt}mWmtQOBGZYZ8vJgaziabxkE;$-pM;(5jMix(6xEM8Q+xL7M*QoOWyS@H7X z6~!xyR~75UtBcnZHx;ifURS)nxVbo0yrFnw@uuR<#Vy5KinkW0i?Qk5vw;> ztTWUH-I9){cBm8fR6Iy%R_b~~eLzur1PRp9A*iPt>ivqk5;gNse1JErs#OEMPeGL* zX>`6lEA6&A7%x!Qa2cCLs6$v$B^i7byn(`hI)^pDz}K}(Q#JlS%!Ld zM2&K(iZpqC4Mh~m-m#v{<8XD3>sa~hK<3>bcR8}(4x;>vX%~auR~k+X^^>@bhJL4_ zJ1<1x38?a-)nClh?=1Q`hJJ^lE7vbgp|NGWzvV3Yq@mxg=*k6#_G|5*|7Fq7HT2sQ z9o-G!w1+G6N;U+m?w@gI!Ot`BX$4n@pZB6ie;BJj1uBbvzMJRsTQENfhD$k!_}zU(}}&i<6! zEb-a#JT=F%BTvuebJ=a?!e!(Y~ zyvdNSQe?MD)sy|p#k1w$wT679BI6d-s3-F;yUs?w&XBKAjRd@{+By!7^M@%4=1}>SUvXNY^awh>P$*)4?~?Y)Jqk$nNnNBP;W5QOB8iFrQ&8W zV_0p08x6IlsP&XOH4OD8L%mp0-BT~0Tlhe2R$Xs4)Qc4L6Ugw;$}rF^26~}_emsGm zGK8YH80G~LGt%&6fT@AM+X0c?qTd?0Jnlc=as9aeB-GV62hpY|yk3z3V^*6!ZP@22 z_K6AG?FgawHSoIM-R;SanG$?b;H)0Nu|d{V)eC-8XZApX$E zv&tO?evX3E^C)j|-k9ah(#nJ1Y2X_bd}*S2Q(!#8ZHt^`^SccEYz3czX?$e#8KE(~ zD{>b7ZbLsy(OVH6vaHE#25~Eo(VrZqirf{3LHa!=k~3W-G~UO%E9y%)>CG31IO&!ptqu;fP#`E7i(k9{?-Ew@tgj36|g)#__@RS=|PpSer!0Ih1G-O&lu{@6t$PGHupg^%4+IUhT2!uPDW>w*no=i+ zq0SiU>k&1YAykm2`mIS>Z--vd44R$~WS%4Z$dP?R)`!Op(uu&As?fO0t&5!1=YG!6 zdy3vm={2D-y&-ZI{RKn+p`v$E`n1rP-V!;B{-UA(K+)SNy(u)Nw?)pPf8Nl)ujn%= zeMV?Z?~0s7|AL{vrs%Dd-Vqwp`yyx2Uo!OXDS9)d_k_muNokz3=xsxPRney-IyCuH zAnH~W<%+}#v6yoIMH9<+T`YdG&=w`dB+;`5Gh6tQ!F83=^+;(@Zbs32FcFUqf(D8Htn>_kyQ zF>I4aQwDz~S6yPjijg;E__~R$qhgzhVuPgBB69Aq@EeBwiXyjC^5n4OZyNGf6}g#` zE5nk%WyoJq4NLxxA%9tsYbm)qEV*mQUsB}Bl-wDX z{9Qx-q9Ru#GL-QOh*+^^;uy@7;njfUDMQ;~{gk1%8&dp~p%0?L>cRc@4D}^N?WEN1 zFx1x!^$UtRlTzEmP`_`epI6joN^K28{ehvrsHoE^wJ{9!hlcusqSjOD)G*YZp?*$L zCsS%|80wD<^?60@@0ygX$}rT|4Rt1>M&+~za6M(H>=u@~%+Tq_fy`5e=N#Ej8M>se zU*+!a$}}EH)grptPV|PMe^${uDSc9COrH`tYjF9dp+BqW?UY^@8q*shXVHIR=+7wn zOiG^?8q-@MXVHIZ=uazpE2TGu#`LzxS@gc4Kc(o+ls+RgrgufoqW{d$Kcnc4l->~< z)B7T4(SL5}Ek&P>=s0BnQMb(~_oSpkET-K5!o>2Vi^WeFT2T*zxNd|qQ--$;?g^!I zEm9h2O-1j-bUkJGrJ+Br=#weEq3G>A`mYTAF-5PY^l3$($)mq*=#MITC8gICy_H9= ztn&Mdx%qlT(fhk#=K1DpQqh}v^i_ubu%h=;dR5UIdGytW-cDMMbAYfO|6sVF;9lsIJ|k){m(oZyAA>XUW z^_1Klmb}4`8;V>@$(>=zXBzT7iaZ&Sp^R5S#ELZ&$6%%mX9X-z8SZviKV|6C{$D?3 zsAOUFl;Lbcy-QKMDYXZpQC3qo8tR>j+D@sRVW{UA>K%&OOsTD5sFQ|zyP{5~)W$H> za}D)2MXjgQsbQ$+8S1p6PNvk_Fx2x6^;Si#q}1v#)C&ytmWUcn8T#;+t)4Pe;q(Z2 zH#B=E(uIM{eeM=V_EUx)AfrCFA~YWU)kMx3{#|6~H!FHKrB4ct=~E(S(Jwain-sm1 z((6KFdPC$add<*pRP=UApB5U^TOw!CFER8R6up_!n?hrHN8~K}rG`GG=#7-#78=ug zB4^PrGxW`hKAqCLLSuSG8s{wf<%WK}qEAJ1X!7eI>Q)rxKAfa7u-so^V!6)6;-?Hv zQBq72;mnlbN`t#rDP4<{2IU%x-i_&c%5asTZ&LKhls>KKojiKo(63SSYD%9{^mZQo zYD2$T(JLvvuISA?`Zb1LSM+}RHcU;?8+r6ihJKZzcT@VLqEF}1uQl{56}^+vacl!q z2AW~@c5_pPUG$V;Dlf|GOq5rsDBDq#Pz+~Cq$$HvI0A_3SxsWVijg;ExZcEexr(h7 z#Rf^6jL5lza-8J2v5Azz}%(3fQtQJ|?=;knids#nlfzK&GSssbwGT&fMT7jxFx0yZ z^{j{*(Rz5^m)e+AfrHNm4xR1^WS%md>BxS{&?SBSGF=}|6O)Dv6EYdm%~OVkp>I(1 zPD-x|jmK$qk+TMu_Zs>cir!A?HK8$mTI4MHeTH6D^qG`CB{ZhDM9!k$Z|J8hdMl+j zg~s%@$XWCU41K+#H&gnI(3sv8Ig9?Fp|4Z)MoRApjp==nv*@2T^tFmU9nqo5p8`=g z`6&0Kq(Us*<%YKy9x}14aj}FcL)3#Ht{dUZl%Z*GtCiCANNJ!o6ulGE^_1aZLtmxn zlPP^#(c5|SM-089=+%@yrRXzx^hXW-Q|S)wN(!$lcqA{T)IFn`??^4ETSi;Cc$~4GVtOfd4K9*HUnISny{J_-|A2WD4#K z3x3Xk|5pmGMqr#JfQa>JCXT?&5@rIGX9<5p)G$flNbp<{p!PvDR6R*}-a!9n3hkuO z?l92L8R#h~bS8zihk?Fep#LL#{{B?JF>3h$)ws=#;T|H~BKPT@6yF}xvi7W`!c z|BDnplftJ3#_*QNS@5qI_@AfnRtj$ljNxsOv*2Gf@c*2`n<;!oU<~hyoCSZy!2c|T zPp9yXz!=^aISbw~@IOuAQxP26;yQ@BEk?N~MHC`2lY+0ANdAN(@pFP!)L$U28_~?1 z;OmBVa;kDIQW;=P1@FXgND@@jFn{@mf&Xy|pG@IX3f|6xf78JKQwp!9@VbJ}u^KbnFkBQTWhDu`I0T5$wsLhyQ^ z@`PX|QT>FVPlua@(OVW(PY8Z&p#LU?c2Z~;M5C&PzG0xhn?h$&XnPpwn+EzjDYThF zTf;zqVxa#zg-)l?#xT&I8t8AQ(0U4;8V1@o(BDd-lPR<|4D@FP`ma)GC52Xpf&Sb; zPYlp#LePhE?ev78IzMMZ@QVQE3Bhj?*iQ(0(Mfqwohkz3Azn@7tRdc82L2lCiuSjE@1z&C8D^mDW1jh*hh`QNC zxxZabd0%59Ie{Ya6N09w$SU_Dnwb!+HM9?>D%T>FLA8d0cVoDo5Uexs52f(Q6h5us zGkNg!27Y`Bucq)R1#jiSPdD%nrtm(w@$#z-bp>zc!K()TffU|L;WY(scUbVb27F`+o=m}=VZrAa@Uj$KO~LJ9!RH(B5h=J5fuU^o z;iz1!Pt7<2Ga?F<9G$UxtnLR%?x zW*F$j26}i3ZKTlVFwmNT9+pCHx5LxO}St@0xlGYbm%lEckW<9!tTKDY!c<_znYJl!B`%xHByH zP6OU41y@pVdsy&Y2D~GIu`7Uvf3B+|qvY%o8|xOu<45m(c98&~<5g2}i{K7IcLgat zsJ+|7xkH+mUU0nN=e1aGoV)t$)79@W(1iqb-4JNr1?ZM?r|3B>h8d|(0rsVk`lc9> zy%%#G4hd<5I5+J|b#;4)6C6CJk$@OQf@YQN=p50MiiqoUi0EDu(E^I7l|}?&enfQ@ z5!dk$(S0VO`4mwzjR?g2h-xY#uJa+H`%OgKQACY2A`tTS8xSITz(h2UBAQMk z0x>_Ls)~r)gb>k#CZf3%(Nr1{i1`s!R7BiHgor+EBAP=H)zgST%#WxqrI3p^w;3U# zhfGAH6j3dW2*mt|dMcupOJRtpX(DomW%sm)#)m_|#PxJCkN68It(9=f&V^Q(9p6s9>#u%i z4z?oRPzx1WUY&C0M;^Sv6Gc227nC ze^Q378hVC-YA;{|oXX~^y1`Jj7ch4Oub)cbVa&#^TGulTReJ%$<20k?TRCDiSJ$%) zReJ$*=No!m@mS1Rbv@fqwHGjVV40`lse7|hHyWyT1Lj=2dMX~LH7oTTLml7<3{Us* z^CVt_^yg({)vw7w=K7^wfyKw2K-PITolN&9xZz|;j~vf6bnOgG9l_96Cs_35M6@jW zd4{gtfw?!r{aU_1{*QI9$Ps&4^z#i}`vcQ&)5=MdLYD)ev*;HXx^@VrUIdH}A;$6& zJ9aj9ztGUNN3i(yBA{u<&L@Q?*}yL{aP1Myy%OThu6;N3^E`rGZ0On}nA1bZo%t}IYf zGk;h^R*|{XM529zMfPbceSt-byjtga9=UGF+T~X>EZSj> zZtyUP29Q#;p{xuT;9VW~JYHfaUw(i$MSRz-LDBYGoUr`4ZXtU?{hC1L4oExssz;gw zxuc#yOv&;^mc=(2x_0zcOX*#CV28HIThP4LkhP;PVmEP%I9o4Z#HD@=&MJg9Nz#oCD&#nPZ_dy^o1UJqX|FRKw0870Lli$w6OX+KR*!#gG*s>AtC>>8V{b0?CPUSZzR;O&G^!Sly}8tz4OKh( zs-@IAh{mwm0$U7KJNg>nu{T%OTMSh@`uap-fXXnc-fE!Q&)3Hj=qW=af7&p$m#>ux z^W-6zw;ARDA73W|EUH!*(aB*P$E{fywA>!J-12GjFZ{oxgLh^F?8+O%lVh{x_f8HOwV;O+%RP5 zea*pW0-eKQbaA7B@`<5Ln&N(+i9|d0s;kPgBGAl;|9(T$e!V)W_o|wLFOT4Ed=zTt z0|u_$dMOWcTjNXjK?B!by_AEwt?{M%X#>|zy_A2siZV;=lh8CP4;i|4>eWn*-cvQm z`zXw+pG`y8PQ7CPa!}g5XKSuOmB_E0(fwgV*G|3MVf?;+cBq8o>=w3BIj3ImuuDxC z`*~{&kC-U6Q?GhtE+~ZPEDociNkQbXY`~=8(ZJ_16ua^AlLF@-&QA)wKR7g4-lX8M zK<2JVyYZ?iKX9{= zpEP9c%1il#^X}eeBex7$yYlL!I!{TNn~nS#L)NamoEJG?cqO6rvgt0EEj0)%FFpn^OFK}%!U;v!RjILGlr^NdDY3lo;o!Q^;tvJuDqO| zG*3l`Y_sb6Swq#XywH1DG}S`RP>lOD|NxP31i>`I4b)S6HcLy*RH%`_ixbTxA}2h+%{w4ylXXx#gzM( zO)T1#S2gNE5Lb^2iyO>_f&5ntPP_6_e&71aB(<3CMofYJRYTXVyp(6Qo}y3Y(O)ri z?aHf>W@lH?t9kT}p=(!Ov1c~0bL{35?Ow^Ff6dUfD=&A9eP{xd?y0JGWp=(!O%0U~BZQxlF4TxvlM4|RBJyFQ@3HMDCrFP|2jS>V3qnkC1 zlqL$Lu)s24qVTQ2=W!J~@A4CcKKT~#69w-{4O<3hpzNmy-wtH%r?m4f^!CMQS{_#eJ$C@xHDv9;OSvNSby6z&9-Ec=BSX~= zywDF=q$~O!o0a;yp=t+S=m#vKHix19*if|tFZ2TzQPKC)S`T>im^&V^%Pv1r=#p0fKT+@=&af!uO%$qu%vC_U?CKEN z59RA(2PvfDDIhOFIoy;CP<8x2{z?TVe4;Y2}7c2rL6HluR_mJ76Y+cg;#XuzV| zF|41B7^{c$lZL9@b~)!8e)@qf$7ZFTYpB|7*8mq|xw@WbsM>8;Cv{pSF2-`H=Nqba z+cm(&ST6MfL)C7(8mX@0Vl0<>p`mKGT?1T<cxgSz-54gMZ4{aomL{Q8sW@D;cA1^ zZo8Bxv)FMZ(kn6DjhMm{g=-95yX}fSnE`D^8QlBY%QE;TL)UJ*+~M%P8Z{NYCmxKl z=+_#$a@#eFKeNPJnl{XJ2Cm$8)uN&TcG2$4a-F4JZ{W&pm-3aSy_x0uO51GU%57IQ z)f~q)urGyXY?HgtB%x>AcICP_n=&yfw_UOSG%z$eCBryrj<9UjIl>JA&qFHbs4Gkn z$j?BSB1oZ`ZHjPX0CNwe9CdXF>`UiV3}IWP0@ z*l$_x1mR`_R?fPV-?CbybuM^|0V`)+%5T}w4$*EgVCAfJb+~6u_U6Z73 zXcGm-qq|&}SN9wE$2slX;8s)kR=K=-z`&KWu1X5uDwkIe8n|-S)l1zCZI#QbPaC*$ z*40hnTjlcVAp=*=x;iPmr!sUhuLo@!xN_E|9HdnQ#-+u(e9G#cA2x91tSfeq1}!|g zG}A2{$~8$5L}JSOBPJ5%tgE9`o{VT_Ch(}Cotzf%W@_xVf_v|DS@w9$z?HMEMhcJJ zQlcFyvF3U({kVZEXI;weT1#mjdqgwOI-W3a<*X}qy9Syz6+Cf}rZs=kz?HKu&!eZ4sQCLaNr&E?@Y8^XygohKG~k&4=3Ys;=Zc+- zfsMS6G;U`);xZwtUOj8z%0-uRS?0Su?+y(Ok@srvXAM}n=xUKUJUDiPmJ5E)fR&3b z<*jUJH)t~ktXy;{Z)HQfL3`eSm5VOrt!!vFXrD7+<)UjUvN4os^f5-YC@OmP5y1esB+O&AyqxJIt=vl2C7_i_2#2u9*VxjX4Uiy2C7_i zbyBD}6Klps)yaR!K$VNG0nWs7p=|?IF1nhjrs7O27y3m5RW7;)I1|f-e#t&vkV5ih(N^UA+{(RgSJY2CiImDbHmcrFmcE ztWNH02CiImbyCfH0%NmO^Lo&)8@O`O)lT8wB^SfJyQD15zhU4j(lPZ+1cw$Ly`-|=FF8i*5D;HhLEt>XR))5Cz zS!M8516MA(CR3Yh&t>gA`1cHad0N1gTQnTPK(^9Iy|x2Q1Nz2ASFR(r*G!DcMOP(C z4o(BWs}aUYPXpu)d?>2}rUBm%cpg1Dr(Av-;Jl^zX@GZNhQ;3%n(Q|Veh|RiD=DX3 z%2V2un4RmDcX^eS$3HZ1<(Mn>TL#9cNATRyde4BBV=m_b%@_OHu;3pVuyV}Rio8*Q z#zQ+ld)t4iAXrpx=v;s)0{jmm0p-!^dN zn5&Y)y{{~Wd#6!Z@XBhvy;?cu>WA|J(cs=!7Q?;Ms4Vy@16Pi@oOd;E7Vj%d`k~0? zW(c<0z?EYzbgvdoV7#v^hI?;7S(>jg@KV|UD`#kZ(UjrdNm3Skt${1YT*?`mc8cWP zJ7vMw8Mt!H6+1(N7QP8qLOXfatDJ(GqzEE0PXpGQNR(r)*taFps}api15P(I<(Nx( zL5tl`BD@mA-MA=h3#uBpa?GW?pv|Zw8vEj_D9hMq7`SrG6?;JgOWrGJouRgzBn!5wY2tVPiwi((9SY&<(O+0Pir%InxAdp$}v|Z)f|T~V0jv; zPcCrN0OOdel^5ei6Qgp>6?;g7@`pans7eVGs#NTa%2cOwLIl~4xscHVMot>A za?BOG6ayaLm=Ec>I`He6C@~ z5e<^$>45X0<+3F-!xx)4m1C~R;hLW%V!g?Ga8xr;<(Lbdt!*h+M?Htduu;#a0GoG6 zeaH15TgvRYh#e4ygj^EhOdNAn(nvszA_1`XCdCo4OC%o=*Xa<^r6wZhn5z#Se%LCQ z8W8g%no%j@Ivygr%tSOFYQ~mwFO3Mq{D|21l1~xW`4G|NCL-sUtD8myVtzzTl_G8f zLPS@Xh@4}tP8t!2`4Kf#MBFBXh^{mdImcY>G$Ii5BbrtbaT^gLy2?c49CM)us;Dr4 zm>*GHMZ|4Jh^THNa*nyst5p;ci1`uKR7A$7+0`Z@=a_3+dyu&%1WX)rP458})>UqD zcm-});DNTgh?S8p($g2dh!uw}(*9t+h=rUkE{<-;0!bH3(M2pgba82P5i^=DE{iT= zrqD$?D3&8a1JXq}m=-+d3~}e^V zJ!s~M)(E@o*-~zf_?(3^cUNlnJ^uE@_#ao{)>dpd8Uvk-iN<}xhmL-nzK)hDqfR<) zd`@Y!G-nNX?U_^l)Vgt)!#Z6`#nRk0rO~xqzLv9gK-*FV0Z9m*kD-`4A2dwh!Y_-$OCL#m5JaElQTXK{e1Q9qE25Aqd`LJmS>^H78F`Gctpt+GIx63kz3v)h z7hR%S=q^Ey&?Tya?h+WCE>R71m%y%ciRz!b1g4`)RQuc|unt|Ky5}x|0q7FdJi6p$ ztaPoB0hR8|1yJc0q?K+i)w!H%^-M;!0w+|;W~(YbTvC7Lt8i-ugc}3(SGekfUzbB| z0gL0;Wl(?k>r$*d?rLeAW;+;Q@%VOfb!?n+0I$v;r>7$Lb!40#jm+O%+WzYMG{6v=T(t}kU22$f;{N|Eh}89)+7wwISMvc0{8 zk?rFpjBH;oVPyMx2_xH|rFqAXQ0)NxJc?{wekfyPOT2`U9pEL5>_9JJWCwW(BRkkj z7}+5#%{_jE>K#Njmm)h^AbjOxR)@pcY6sVdykheviEukBRhhnImeGsjfTkP zP-I8S4;0x^Uc$)U=Ov8nXfI)8$9M@Nd%u@3vSV2qJ${7R3W#i!B0ElgpvXSpC5-HY zUc$(Z_Yy|-AunNMANCSPb^=Sq<42$&q9ReG$R^Oe9<@pnBa0S}ESxATyniQXjKFj71%nJz@k)Z z@yZFnb@YZGNIUilz4U|5+c^YO|D zupPs;gbD{v-j;acEgeJ0Cwnbpfv&Db}F6f>)M_#i$*_ zD@TZiRJ-uXdnFZA_3+AjB&Ad}@yff!8dP=h%Hd)$s@izvFtI9CeY|q0Se}{&ys}hs zhuU1ca)@Y1jR{^kSW-ca4PH4&Qc5imUO7;#K`j+tIY2B%Eg4=}B37lA4zG-h<*6ma zD<#Pt>JjkD{-PnZop@zGNd>j7cx7KnDYdW8oI67{Lqz$?2;5~)|gE4zsqsMojE^S`#K-3 z?7nWdq*z|Q9!r6f=Pem6FI$faIeG4qoy$wtqsmU6vt+DXT91ix^5~L9<;CkU*-kDl z*{M9X9u4E<0$L4*G~k8|M*lmP#!8Dy{>PEhj^+95Pjw#}{!_?>pb?BqmaT{J!qWB7 zkC)a%|GIcR^m}9LOLMSC3O7-z0lx#@Q~-nHeeib|ycPcLjCaG|F$BQhMaY1^V4@>O zc8W=qCLqD}y%@G9!xl4a4~D&qVY@R7lz_~SVN^C9Y@A^whV9R={TQ|{!}ehqR0b%( zF^sCBgDqv)Aq+d1VFxknK!zQ_FeoZe7h~8`&JVbL1jF9Tu=gH;(? zF>G0Yy`N#nFzjfCy^mo>G3-c&LAihyGKNvV?2-wE9U5=^@z_!5K_`|E7|B1g7&^}a zcb=mw+!Xqs{(qRX&lE9{Op9EMT^GZ zv-8fo?24b=@U#2w?}E=Bdo11)KYQV4@4fed&%XQaw?BSL_!+0qk|hVg=fDFGIv78P z;Abg)4n6cR_#A%tyWfMK_u}UW`Yc;^Bz%rK>U~G!=a^&O51(U?U49&WJ^&xwgT}6b zyCc>$@QZ2$f}8Cox&^zF4=Q1+3x}RvTaKCy&)n__7Pi=>`#ZgIoa=Z$$nx4G{X%_nC=sY zPxoU6=yo}s=+iwP)7?b;VcV4OXF^Pz@I$vE;m?P=IpIrP!oP@`;oclf_=@2Z{*nQ@ z4L&P;!pAV-FChNFZA$nnAtp}v0b7yqZ-%=$;Y(b?Uqj7ss|hB2`S1yU)d1aomE}I+ zB~19Y5x?IyCH(ae6DNG%tw{J!!`+Juiz-K^;D z1MVKiju!$01(g~9yfOf1Qe{7rVcx{M^bzd~V z5?OY7T1?lj=;VeEKops_AHIy>Hj>BMK#Xh--T{)O`FJ4D-o-4%eW9zWprc3eXp z_ie~uuuXP+Fhs?=&v&{%j%<8>in=dm-3N{hLg)Kv0J81~fpuxGJE{H<;^z!f-CA8@ z4iP;QB4W))F%NNw3FAgLevAf=6?hQmes!%$w_qm|ZYl2RIkU_rV4OcTGQz`p9MZ#} z9-o~LcoNrEL*(rt=)_VUA(xx%^gASMb;aNDY=H)$ZU=yS$l;c1pg5HZ8TYO+_qvDr z>AhnG$komCdcrAa4fqb*u;=4n*mp6;e_`^P5ku9);GX8EG2p%R&pLk>A!TQnd$DX# zMZo70#q#vVHwv4NDUPh%0<(mPg-}H1Ldh>u#+96=n1^uCBq~eA3iO>=1OefBH7#F& zT|$IsafD;{%|}C)VEL7Hxxgep1UlOU8lymvh7jnSG!Ur`54Eszj9_*SDok%Lhze72 zh5H8uXvY!wxFUp;!@;HJWmS4`1HeQ(JjXqr9~`0`qi4E7fK`btWex>vT<-flpQ2|! zTgo4T+hNfY(y*ocVfYSTetQI^heUc5rMD&IV<;WP zw>^%+t}Hx(!lc~wBue*+)I#YgVSEN9SX?Hpo7eqh38QaWj}{PMKpQ=r9b3wFQOp0&!h0NMEeDl_T_Ldp)gKD)&q8* zuRQC;e8mDyPtK`O`3~ZEnUKMVsJsvVh7XwC_fSaJRy_5myHLyFc5%G3GUBrz%gC{u zDl8-4ko009sfv-PklZB_6_UT_o2ZN&zycMKe_(-1$TPyDA|jbXMdXh;9F>s2V1WwA z@327S<53|{0eMp-Dj{`IiHgXVDft7wjY`QX z;ZrHOL?kLE>qMe*A`B`fzY>Yci7SMX|MGq#w5hJba-PqY|LaWtyUjINrpA^O)ym81 zA+&!QG;GJPrQC($P5Qb9us!H0`!)MP11MWt{_)o4pb6awYi+&-r8Txe|BXT?z1{o; z+b`T<;Ah937LCEG+ittVN*jI_VzXdH{`=wv-z%mf>AlL7;YCet`}y`~n@> zmU1n=M+CY@1iD9r#ZVIDt_pl;oB$WT=1FP3Idc}JLo~%LP0)`3i7i!T^^51a(Pbpp@cucbSN%EB2XC;fy$5wP=@#} zR*%|9tSKT{E%+!*Bz$bP zr3`~V9J9_Xp_M0|;T0Cp4n~AMy0;OhOaxa;`4?A9S>TjGK$Eh4JYC-{IE1@!cC*J_eJ4G08lT7BnCk z*6s2F!xpKnI})PY%M}kSj=uC^QRJ5$wv@3bmUzGUprUBngWH2@+#a}G;cZN}qS_ak74+2FP}4vvuKr^`al zPxngKfTm^J?xu!mUuu6&FF*m?J#Lub`FHW7P>*M@wC@JL6w9L_=&r6T*5V2+g6l%# z3N62Ig$9u-G&e%7@P}3lX5XikPdL3?STm@S>+1D<$U<(naFy+y)$a9ZiJdWdSi8Ga zG5a`ik@qh|aJ@SJ;(B!!IGGSIYPYn`F9e-$cTEDmh9gaatZB5db#b?5w=6FP%tH=? zFWnFZ#z~uToU{s4w3Ev)SXm1x5yAB>aZ2PDND26w(KYU+5GOYogVqY;wLNIv9F2?; zI-M^E+ArJ`ZAVVirt{%ubhgwK9(_* zdo={)e2{>dL%Ht{2;SBC`@@WY*dU@3UDKl4ru)sD``hMz+amuW>wZ+=pP)sC%q%xI zI4@rzOV+OPgJxcUj297?fMy5tYT;EEk8^&Te!5)0{$XiEsH^5CA-k*ImZm*B5gSY* z+&enZ@1LF%d|l`irf*8$Ji4o*neLW)82-EG)Pc=SIOS62km; zbOffiP!|R)D}PhXCvmA~Vob(hl{4Rv=V+i!xxMB{)ex<&c)+IZNuT1va%1|n0*%V3 zBY;sEx5g7=cBoI=Rwp?KaAugF0+&}4+=$XL%8z|DgTtTa^d%I95e>QAb9))tc*T#W4M|7 zNGzwMC3i1-aQD)BdVf{~hRB=aZm|Nh25DeB8SAIWqkE(sz#F(xn8>=p^(H^Z-efd- zl>pmgC~0$`q~$$n>Z!s-70*AXto+iQj~(o{y5jF(6JS+D3ocW6v?heS%T-#pE=`4q zPxCo+wB#06pnUo{01kx1gdYW-@Mk=4qyFgY_!`CBt=N@;q9FfveDW&yQ*0NC0ByMBW7z^Fckc*O7B%6 zcAlL2$vl@C>R7Nj#l_tvbIQk^gzfSYH^DC-=U!!)E{@NeI1sMk)D|0y6X6e-q>6Z~z49%0*ZkhW|>%mLi_t8=j*M!{* z7uBMhJ)byEEh8*$L2rpVtb{*sY)=hUoEH|ZQA5!d3!$DvTo-hDU_R-zJ(dvnFwU34 z*RY$BE<*&$BYb9uzi=L~~%e1!$Qdr@}VTH@CnixQ37u}khW48odImg`Y63#Jr@5Qg$ z$2mqyt#BDtDY~4Jya_pWGUgQOurjWRc`e3tP=_h~m8hg-O`;4N6NW^f6>4mErXJk)Tf67f)DU#QSKx5vchQfqFy{s7G{B%1{G-;;IlD#4zYt9~9@IhF#N4M$ICS4kC~aA_N_>h8RBK zY$u3LccdGFPCgLW5(^l_5hX^75Vr2F)P;m?3=rzBe-iIw%f)v@F`qH2rxBG4dC8MW~p5iW<1ML8J zNsWSQ{#T4+n}ktg2Mu+BBIFTPe{HBe7qZcs-r zpn_iLqfifPyr`fQ=`00Z-*MsL&@2|!+*JCIf84*&tUg&BQ6IO|A`32IzmQD(@UNfx z(Q*t-{&0gYu20H)d-U=izP=Ye?nOQ~IfOk%^gKKQ<0yba0kL!wvzU@H>7{fF=W!Dm1Cgtq`o%ZAAA!KUIoO@LG+<_0_mkd zc_;8t_gWyl7l@yC;|Jaj%=qBB&fNLbGUmCJXR%CAjEr68Mx{qU@QIqtb5%*Ef&(Sl zHOE|}Tyx9zrUHbM z^=?X5El!pQlq?Y_St5jF*+O_zh=P-aQTWW&JGpMn2+qlZ*oI8jodLp2+lN!KWK=}G zod~YB@{q#SRu(8(Tv_zE=$;S-Ckvw(SP1XW2+qk$2PraO&zdAR1B8=xm@K2Dwt<2f zE+7dmNHn3UJ|1wK`TkW$3GAQ0_r2{I*X9cW_jJIqc1yQKyP1IF$0divK0ikIxNwn4lWa9qp|6kMtk;G|S}T*DNz*8`5V^Y5v?6YYK) za9qrmgkok}v!93HoF7qen;*Z*2)@<%v1XMY9&n2BtQ0ys(2rSRMu6X`knwjaWBff7 zF`K0I0nbTtN3jg(cQ#}M=OiUh-0~W-a{_}?R2p0)e39dphhqs1&jo?T1#EwzB^qII z)y$cw@S}4AQRJ$s`xOBPgs*9uP27jllBn&fl}K)4*d82H(0@9>*dBWcEYS*B0WLj` znY-T=Xq;7h3N75ts)Y-Kbi2>c77NYjri+o#LrR;0#wp!HXcE|WuI<@zPXrt%70-wd z(Y3lLy|eYdsxDruD?S=7&Tckbbqkt0__~bXGW$xZFc%{KpkqV0k$2u<>fhOF zAL(W%_GgDEI4ORT-N@DL+;Ai7b|C2nZBTfGAp%V*M4(xP2s9%k-E1wqAVk5s`58Oh zZdMUOBX>!-k##$Obc5D5=q3W`CIaauLeR|)UoQ_)ux=Oy_~Xi6{H5`nBFLY|dw3Q@3?+?<{> z+%CH6dNnQygxH3((w!krw$fHi>Lr?BrAEN9mE1e5(2Z=xsz>167kE5Fa&F{o5qltn zWaDM80K_XCkn>VCLX?jN5L?8bEarz=14jDR9<2c5!3|FRX&;%l2QL{6TuR`Q?*|wI zB4_17LOvVf=DhH006HO_&BfoaUNEeIO8^bu*bIVwF~Ha;eg!})HaqN<0OM5p1pp13 zHI?5AEY5mA{rC5>^}Rf>!Fbic{K;zlqz8y$xen0(}z&?rL0w+<@9B^w_ z`Sy{EnO^`1cXM`z3yf=XDGs=*!TBYCzRpjJ;}8LNcEE9d`bB_n_aN;g!hk!^;QTUx z1P->-HPj~dVuSO`020{a0)L?Gt}r;i3}A5K!oZxpCg3<{2QLE{oLD#5ZgaqKx%2A) zx(V^}z@*+BV4Sb+Rj&af%3DKlu02t3`)J~hjNmzgdW!W@2*`y_0%k5Sd?_QiEHFg#d+>mpy}r=NxgQ3G zvOd7~+nLR`bM6N_dBB$PBrh;jcy8Fw*qKHP42|tzfkD5ML~kX1P}T<2-*~4MeV0W8 z{}*;@K^N*~+h#v(Rn4?<58gz{zj?FNY%cOQa1P-O@FtTAx3-cUZn+A#en7aTnHhe@ zfY8e+w4R5YJs|Wl3Oz?@a&AUwY{6u7Kvg@uw2Fn@&FpBGn_XZp%3>zQb`Hne9GuMfd-BU_6_kKLUa^9?O)WJgEu_OE@ ztEsx_1*pJqARB#nd%M(PI7ZV{&h(lZNf2KPPQjG#lsd zMC9)T^`XXBKpnnqWf-6Ktb!K?VU;MCG$~T-GweQ+F62kw)6udU|EXy%-moB`dCL zGQwxX<+h7Y7x2XrEP~^6%CNtE;&3Q?xG^3bT^#|AZswIo*SnXaU=MuK;>t@VV~{)4 z5^sm47|tkj@4!MY4^GhDhR>ok<^8Mt%~e$26yF$hz0bY%f^nli7jSbxUVda>d#va} zaGZltjnP>zM}fxpewOZIwgfg83LLV|1qG?L%`43<%~=NyhUS$Q{XSH>Luga~1o~^3 z=jx|zO~3-~of#ScmKUki+!kOuBzFf7?> zpyC7J9LO!Kge?s_`3!#lN5uTLy2yE5Mi9 z)L#(UT?Cg`{EN#g7D%IZe2)mun(;mIi?lQNTWpyQUJ%PPVx|br+A&jpAw61g`e$OH z9Sax?Q{7)6cEGTBrR}fa4P-02;@X*5qZ$h?uVRhl7t*K?Gd95DaR4mju z)sP0RI~bO1<*(okWUK9bZED9FiQw`o)<}LKjT-SiA~MQU@$5VlxqBjVev0$$hN{8@CxvKJ2NlND;8W{vEcHG1=6S; z-y?#vW_*wQBJB+R7F(u+7sN7+m??s@cFdGtNRRGLk?y@%=*I#E!&LX@i5)O3UTOO) zcmvsruDEt4)~LpU%d1!;`Gqv<&y6$^!C8}kan@u(+8GpM%TzD|u}nK=ir}mrGvyc3 zVzfWfFdcspQNvejI%72ZI$qARYQi8X4l;PNWgNPZ!WYVkcHIBUlD$S=~) z;BT>I>Ucpc)1L!^Z)aF=)@H$3n+4LN5vRWy3$0kdU{oHw9WX4}%3r}7$X0WFZED9F ziQw`o)<}MF8pZcCSa8;i?~z}mox$H?%QW$VSf<8z(z=NV&e}0kejz>Tar&oXVLBEt z7?lS~HGade_!l(fb_Q?2E5P^dOnjDgp9Pm!EV#U4fi!Bz_lV%E8Q&wnNIQeS#g^&d z1+h#cW{Tjf9W&(@(xV!ue=-(ov4Fua)%{Vi1BS&bZGQ!CAY0KD*UrQm)mU(O6>B8F zkVgIRMm)sFg0m(I&YCPpJA-0u89bQZTc*u{smzGrtQ|Au7t*7*BLI92jD<>U84O0{ z!P}wFS3q|zGk62pimteJCf2CIg3GH|Bl(3is>Sz+;H(+nBfm&HgTKX=spADHGksVv z3#nwmS(^oCZ5Bw6c5IAJEOcW5gHd_#cEGS?D}M!Vz$>5z+p4iMJct^Z=sU- z5HNG+5KX=UGgiLR;w$|{a%G0Ebo`YzUupR(9lio1Qs#8|3XH_~N{_F=2!yZn`AT;u zxl-B1X*lDrRQU?Dw0zejUx5~euhjSo)GWSI=POX6_{tPt0Za0gCeJg;N?;@Qo{N{W z7InW`@rypZ+~?kyYVM+*CUvp`x_za33Go|QL1A6FxeKYFALo20BRH%pkHSKzJaEk3 zy!eBR8*%-b;<1m7Ue5?_qp>T={fzs3H1?6tTN%NVg=APTE>5g1z=|m@$KfLIGWY|J z-s<2I8&0MJA7pd=@-ZHfB}>LI%iyKtum-w%mCwI>-BK_@9R*B*ek@}a>oH2w9bE+L;Qu)tj` zpHM9oPc0WtUozLNAFsmj?^-zV6#k`sR?uO@EshATEsk3p`Gs1XMtqM5uCB5UTCp$_3m6Pd)b_0!hQ%ule+6&AE5L`$pgy4= zKh_e#wZ;64Yl~TMZE<`LJ)DvkVMU;OM38X=-W6Mh&JhyJz+M91CGdCBg1-}xzmpDA zaoVS2p%Duh3{wm#qOXe#4gj0??@71zxf;Z0nvUEnDyv2*8(L^2?hKLL?-~imLfglvNao&3(1CSNU~z+k+ajH1 zGFjo)M!1#RL_Csos9Wzfx8h-+L*06xxfPGp9O~Bl&8_Z4wpsH4p7|Y8UbIGK!>0p| zvjI_Cz0XS zC(NyQvh`56K51^H6V0e?n59&<%&qvq6f$sp&IF|$H^{(gyELMUYDgC@_{O#u1b8r) z`KVP6F2prS{iyZnpu<0oD}oEu6GPk!6I>C@q^<~R8LkLCAh;svB(4Zb(A2mcO9NdI zJiiE@^=|Fa&+u&bw?^RP#o<46Kp1RZ!4tvo2r&0X8lMOa>E;Kk&5UERYRXKs1H386 zWTESs@;<)@qo?;m6`*sQu`sqc+5WNrnu_N<=$cn|)H38W4(V{H2)9&NM zOR1WIUpT2;_b@E=RDKYJH{ccELm0A5CDup;(nti-NCeVIPEmB$YPf_MZ~L?gP9mgMd1s_BguHQ^%_^!lzR@ z(bmq>uFJR=<3hV+#dSkQcoWwQ93u=PsX66iVN=itpf=N+3mNA#-WF(lKBIGsp zW#NXb?G{cvfeFNM20VDj0z%b+^O;JJv=~@?xNJ=fC_b(`a=WpX6C>p2lR>3;50^hh z83!Z!p3j(jMq&4+J1z9wIfcTf@SOAF3Vnn!blhXmaTlQLmd&JdF@*!RgI}(?UNlwg zMSbh0vS>*EW(wu~p`+GuijTADx@mVR?P70X|5hTk_I#Zhd;Xs7*T+X4?7ptzg`#^E~-pAMn$^s}jb8s{+n`zx7Bg@+}ma3Cg*KuaRa|NUqF3`)l zv!U+{m|qyocSYg>JgGolB+!MTxZmY1)c7sYh$W`8L9%e70Uc%# zon}D0^mc;dVfp-mUGQ*NJQWrWgw-yo;Rskdqrjd0S}KjlC%)oguLmD|2p#h34tRyL zUFlHQ_tNJG{4B%Ik@7j}sQ2OLX!kkhnD-wGpXJ9Lciac?^FjAH9zGxXFnmrpVZ}uG z*M9vYzPe4cGe*00Rpow@s+^2=%guCF(8-t;cmmG~euK(kBeYSl;K2e_ArYt!i9iFl zT6~WPbdLyhj|gy2hU?X}6|WE%W>g5B1gcWMJ|iI1MhE3)ms^dl9^Ic6?&Yfd5%-cg zDwKII_pbi;&@7x6Sp4?XuMc7|JKTFwxR>?#wL$lC8V2ied0?>~WyhlYOA}=jxjNj; zicBn|wev%vX*vNi0Eas($-D*^E`)?_HavuYUk6&rfH6dQ^kdL-9su+Y`L`S!eptl$ z=JSGAt|UN+XF9~gi9TKu4aF=@be5KPg}XV`9~{p7G)g9VQ02Y=V^uz|5QeA4iAQi; zu$*mpBHPetCl>;+8Gx)ELcmF$x8Yp0;qgF!{~#NNRQutfji?nOV$F})3L`!n?q)TQ zc17p&nC_!E-7AJq_X`Gy5O{gYr+WuX_j8C}woM8Da)^l&e#BNJyc6!`gumA%yo;LQ z$--D^mJgrsZyTUHo|wkwFcL48x5I>g9r1^8!hM6}rvtju*!=!Mh=-GXs4J;IK{B3I zi;6EBUhy{qkS&1__e2b*5XJJ&sCW43m zxDZ;G3j>gC;T}epd@b7_RX-Q;;3b~Gvlq4oXF`bQiVzPgjt?_wkAX~rfRzJ|;ieEFC(Iw6p>B>hI#3UTqYTxmPX!vQ&xdFDm;ZDd#*D9>H5*$)ObXBp#cmbvMq9#gq@a-(V#3fE(S&98a7Rk~B4 znJYsT{3CoW{|Y8yjGnGQaXOhwd%XUL4?1!F?@BuhuC&YgBh_LICsoBQ=fQYlbmH5H zr>9J?j&h2t@Zl*gS9r;kp!zdGb)JOow6NUf^?&05;MowGhv66_Sqj&`N6Q^p356Nv zY2YxfGeQeI-$lL1JrS<#e4I;%%0XS{im<+9v+%_bJ7=LkS)=a@7Y`DXJdE)$zekNl zfnbR*2Rdis!W>I{C4~0NTToOv^=JrO1A> z^_wAbZp_^B(@EG$(?h_MT?b3=G>(?$V4K}R9p){ZcpCrWN(1HxDD0M#I&K*%#L*3L zBTA^;7hk}fSW0iomB1g*D(zW) zb;aMo>%EvEl=|q|O)2x`%Y6gD4I9D!%OP#6|c8GtbuR0i<= ziZJ&Te2<~Rcy%%8Jh2D@!Xrgmv1mW!3Go?}-opW(Md7bm_$&(VW8paz>T(mk!~eJZ)ARV#)$-HlP&$r(dI5#U zCE^!RI*EV!JPI|r>kBBA`KOmqxXArv7fM%Gd_mx*918*#)045@g+>zVlV5sr$Pv8Phi6$X{6WBE2JRS(H+RH~krfK;shjsi+)ng0$;%Q{n9V4lb&&~8CH zJ%r{GTU@v`eUEcmOMKUjWIa=$6G)!i?;qhM{^AP#4_fJsg{YCv-2#GR0dmEO#|~$I zoKNswcjMLiJ@|}a@YyDA+u)30^C3TO=)nya@ecrd^Zt>^qJ1&{X4O|51i>dJM|rpb z&Z59g@<(x)zZ5#m196lO8-3|vCvC05s|V10nTDQWjtk?^&<2P=jerQ$3e>i85gkec zv>kMpxIDzC>M|ywVIMp(4Vy%!QQ*-D{R$)Mprr_IZW2!mByH zf{6`ZQvEJw`1B||cBh|1_j^;Y2Y0{jaNd$1OK&MJrSB`Z;FL)u-0k39Rf98e94tSB zN!?Fo?mZX_gDK;bi9jh6!Bt`o#wml}Ov=XPQg+JzSf^}@NtyH5^G;IsG^T7HNm&O{ zhW6~aVGlq)?v9iUH-R+Z#Keec86VsdXBs zHt2L*2~{ zwDJk3mkVnKRdij&o)6i`Z5J*lZYjT$8onMav9r|hE>%ukLG)Q9g6rD(7izoY7jC;` z87jM3cp>QgxN8>NZaQuVuw{W{w)roOFwjIg=`RM%=Ntz2;Zy4Z`^Glo0BaSdXeZZz zwBwYB;QE(1CGrcT1b6zXEdwuwIJw#I#|guYaeED2lfM87b2QaHemT(2a4DeEgtvC$ z7qOke!3aF}3~g~I#I@GNg~!K9TkHxVx4xt0{Y#^?AbS?tk9O?AR=oW&kkpa!QE2{6 z#IPH14Xmga)~v(h$JiWc>iyEVm?x;%4Jw}HRK#_5I|03)Df5J8yGBjiJ>)KU*?97Xy@q#99em$5szdnBP zIOjQz9(}VxBgbg-D>d$1o3lIYZE4)I6S2W00++RA%@Y%`Hz(q@id&w^&>`NzJ9{F^ zvJ)5^FE>~TW&P}+4=u`I+I)(_PcWM~9m`1;nkQ z2AvZ?>mA6g>x1!qed6!bcky@Xg!#KX=+=8mT~yTKQ{q(;E(|eOUCcwCFK(@IsX_7S z;`!F_+h9XAxhjyjhopsf|B}ts;rGX!(pc_s(yKdxO(7(g0X|baS0_E@m`of z8f_>h6UztGkJs~`YeD_k8EQFwaKH2%IDU5?=Kp|d(8#I=oe{1FTR)8O!v-Ek*nP;W zD?Uyhy1A!`V>mXz*5M?y#?};8wAv}E9z-Mru`_m`68T0 zy`*p;Ej`eeiIGJv?cd%B(!RCt8WvZ8b&ei^57>u4ZeuuANZK6^uNBfVGmMQFf`2W0$ zn*mFSu`VKzE+UXFA_QIRB5E~6%l3k3wNW=@1Ol6~Dp8_jeF=MNoxqI&!re5!c@C%A z#EB7s5+ed7MudRwZjKKkpQc?LpEq$JT*L`3HWw$tA27-!c2Sh>$au2g1epu~{-FdyXPrCGI*dg& z1qIKZhx-_IbTepZp}d02Wc?D7xYT_gEfqnpQFxCH;+}*T;_&Z@_zFI~uyzvs0VP(# zA2@cqjylc@E7)P(!{x7@MqC$kdSE{3L@s*VLpwiUq!(Esagmx%D2%7(B@wF4Q5T=m&WF@(8$0FGE2J z>6JdnuoYkn3YMK;bZc&o-4b-=9CI68ILF}Zb-#R1OZl8*q|^$RQB`WaUGiwoX@2AV-16R_QjhFCnkD6b8{dANZaJpFKEU#QWvm-C&hl}nUZ2{BJ( z-8_3id414?hZ}ZnGZ{IHKnoiLPQ(&79b*}-rjycel9SO=(emhkuv#Y)| zD8~)ITSdv}s-x$*OXfg3z=psccFryL@3KH~c-8W$C6L556kcHoGAURBPKMfT9^Q)q2n+YC_|M z&;xj;`qpbDRs;3)g$Q-@0xIYQ(yo5JA4Z{qY?n+0UEgux;m|A=)z-|cMseG(L9_Z~ zaYTLGa*O*v-diM7Km6;be=-Afem%f<2P{)YA2?^mf4mQLm>|N(`9P07p=*EW@h z^1+vi@wH<3ybC|{cCp*9w0O@w-G(LEvjqE-Xp0iOZtUHmm*_K&AA0YY{GlJ<9HHaO z$N2g&ehz^Ty@kB=Q2ZQ*pTp_%Zv4zWJLbc$|r zP?BA9%tgvI$1G5DJf+*%)fFENx3L&a#zcDUfPho(XcWyoeL!%U0^9!J%#7er`LH#F zD#3MVwvqf~fN)cf7JetM_Q11kcLJwQ*7+d{HWx<0iwX94my0ukbF$h)C+qS6;bgss zlGTVC4iPB-MWFl_f%6|nA!cRwst^Sy3!{)V60_54Q$}!37Q{AWZcPOUC+ppmtXiBb z5hz(AP_je_$+8R9H-#uTSr~=ST)o5X){NksEQoE$WZfAcyu5ulB@4y_QEg?x)m9c< zZDoOy#g#=D!h1p#oGgrDU?IFeBRD539i+&B9fwhFNEIdn%>dzK9p>NCO>6`8Ef@<) zScT2d=kb8!%s*6c5||gz;|73nZH_Q#_jJIqc1r~pl)>g>IPGQvjvtvE5|4E2vp2O2*u2{JWCZ7A zL2N_To^F6}vJR4r>?e?@RPnN1)(HExfa7B3-&9U@0-Tg8k87A>_Ikjvb_Z;Wc0Ua` zE@n$YF|)1N&qHv|k0`h;X1~e^zSa4$W|bcvaEkHW>aBe&#%0DPX??(RlH9A?ZlT=t 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

8#77gDf0=YJ z49A)0Y@f5swKvB{eN4^V#^uK!356!~kHeF3XY_nD8`)*ma2H*>kD8nCsIUJ3JURer zQNoi6{RiU7f#Le$3fbjKM~pH4f7DH)LfYQoWmVe#A7Lg{*aj_JMlX6iFfd9%&G+Rv;XMTOw`@)6AYo#6IwWIwAFADRw|ZF{@qa0f_^5bOv&en zq`%N9nFY4?75@G}sIbqf`^UUdQ{5AWF#D*w-@_rlKMZ+Sa=z$<-#lLc1;gPt4o>{N zIsCR@=8qT)K_D|9ohFM5Zr(=F=Hr9%Un-7Rb%Pja~bS^AV(FCTXZW<>r^fWWp! zwJSc~Pk2!yr9U$a+Kx2~KfU-!=u746nssbMd_&lfJk8SaP zmp|TDC;GjZLVI5c+Dim*uF*3#2kv^fV61V_AF4nZWkErA$;a#4-ogyo0slZ+(7gxX zz+Q%=kG~fVI$T7*U<1GFjpETBKKc(fs#p2r99^*$NctCVRFQN}aacK?Mq>Ca9m(>t z4EmY_QmOVg$4j1>_Xt8`1sQtPe9xI3g_d{9=--2mh)nEp+}~ptc!`L<2*KPh^YM`M z%n5y=!?XK;2c=$AgPcdQXL?MT2nzhgPL}3psYBErzFUS?oK&FUe)&TGf}mw)9byYMR(3b z$vmT=^t872#CDz6x2-^9Ue@x!#*y8^A)n5Xv3bj^<%7K5>l+I^jp&Zpfk;RwTL|S; zLYdKc4@@w8wwcdjuuF+!-t3T#W41ZQXBlc6?Bt(@ZIR+9?qhKujrhc$`=z-J3HGP zKQ=pzNG5sZg`BQ4bH9VInK?Ew#%*W65UgAQIGwN0Ixw3rgt+79AZmVT{JH5U! zzKMm7ZwvU`-;QIhciWuHy58G-eAPQ*^KoP{A7A5qXvQsIWq0UU73+D{f!Ta89anBX zV(tAL7T0E=H|kB1zPQK_gvj@4z%O_oZNP9WC=lRo4w#-nvLfQ@s~Yf24$KD33^KU^ z$J+ZjU}v`51Hykf2%rZ+3v0J~_L14f5#(#{$5xU3{QGTdmsp#e@RaX5*34l?92BxO zi}SToH=pm9YH6(X{a?t}>QCDGL8+E{Yp&dqcMeJ;w0~5p<<3E)^w!*$I2>5Wk8aRa z6CX*4B-xPQ5kxmT21kQZYJ4^~2TP=xPwCTQNv$ii@{nej8$;t7sv=hAbRxiYsyc=9 ziWx^M9b<>Rf`vh|vm)08Hck59XADFixZ zN*9U{Km~*lC2Zg3);I(`Z6K0?AeeO3M2!j6k`7ClF!W26P#>227?nT%-`R%+RQLXd zew6CeIYaW^Fvd&6AtWVb2!_yHHxn6zFPD|Rm7jKhKeO9R!5!mp%)qUs2*Q_pOJ^|b zTj>^QeM*-9+Y{2|ReVFkdBcCnJ~q1(D;asBl9OkY`#PBC>CjR3_dvldmuBMMv64s` zed=Y#ZD`1QvtF^Z(#dLuq`u&i7?+sd7nR!NwJzhRWo-8M$(L7}(1DKI*goKFJZtx5 zZVSieZV|uLJ!C$47U%&QwtOrH#~2i)NA*h-FgM90_D!{AD8WV0UA~i>?HWN z_8*`>xqls)?dBVt;QGh650F!eT1x&Ps)57d){Y@Bj7hJlk3X({)qgr{bm$D%p|`l+sq%l@SLr0;g7LW3`A1B z7^NR$Y+&uNv!zEf8YiI-a+kW^J=lS7I>}=uXaIDg0|VmumBYeU`l^ouRU9wqKo`!# zAkg^9_y@AA>WC_I)mJ;MsIHok_JJ8V!iYXy2$PhY^X2eF$1a!x-vox2;D`-G@h&>rs5iN+tRr$l75WY^p1&#&zDNYrn**H_wa_VW-8SKrDnCDdeHc2qk zmV^oHF{cSe5WOk#qcj3aLMEnVZPyL#Y`lDnjZ3Bvn+8#kD*tZt*3FZJwW2K#t&4h> zXcZfu^$Pg6^>aEJl7j}&%SmK<0UjU()92AF$0tX{ep=_5c|h_M={&Hz^wK5PkgJ`u zaW4KrhfQPb_}c0{HhVlP=G7(9`WP)oa+8U8_Qrd65qyy~$?BxBbMQ~^S&dWh4|*^d ztUQhWG2tsrK;bKFKY3yV#|pP^N-t<95|nf1VIh+5oO$I5K9UD~BsTM!@2mE*%C zPl+eXp+Xx0YE&C8qZJ}i4iJr#+a3JNN?01nimqTfgQ4&9Y{Fs%ki?1Y4C?wgCC>zi zVXE-3_{4Em24$;}@5tKl?tCtT$SWp|)rCzN<7NKg`56K}N>E+7W}9-)4r zdc89o6E}@Q5In2F@Gy%a2ena5PqSbT$TiP}Lc|Y>h=ol;=VT`SL7flfW(Plm5sUl) zKf|&mOTbMig?X6Qi5)kVpusW55-5yt^F?e7dfyt-D`K?KnaPw6JE)4|2W=db4+*ga zh+U#kmN_8PWJ^$@3MoziE4-Km&d0MxU^i@xyg+D+=o^rePlXkHjRP~)4ucADpeNq| z4t4QXUb0mO^2!oOGJgdb^uKkNcCp!RW%Q`>uRS31-hDW#fVdBC6jFSlCpCn;H6dg< z#g++~Na`% zECCX(OoYIu3#*DYbl$H#5cB@4NE`>cI5X0PL=sB=H-y{sGl5}G{2akghzMZfH>7^U zu@gP6p`mRF4N=6i%Q$f8Xa2H;cg*g@Dyn$k^@gXl`iQy(&36f?Q;N^Crw85fma<`!01bpq~`-z@N^%=b#Qzu4Y_dc|@D)NzC*4#5~3QyGL_ zL^*1i7c<6|W=P73$U!V-!cXXJ-MI{yW2CMMb6|aK&@`6ZL^N38V71cQH0Ljs-E43G z#^h`v#8bt#iE5}c#RK#WW01ITJ=St*)0F9GLZz3?hK~+j2;Ot&@4== zjvYV5R7XUbms;$luGCYO>?BpU5-K)EDJ67QeFG^^2zluN1`bd-0&JR}ure1PW zFxk3h7Sn7zyqXY)A%65cBx%?6P{epad=6uZF-i%zFdUyZ@dMqoeDvCIy*d2oV~%-? zYO34qcE5Zk$!9WD*8DJ_kP(H<9xHK#^>p}XLWeUrle@yzhd32MddRPwIh|O;sF2!Y zEY1&^egeB3DG}P-qHU2e%h1^30M_3cx{6*`^yxrTRjN+|SFm-?Ld_nk_VE8Pa;fGC z0KfwY^+34|w5tQdD(}A;K?wz#3Uq%2ic}fPM4lzbu%~<_nn#pSy%UtD6N7K_VHm}9 zEIBNhX*scIz`g^PUXRBeU4Gz=Nv0g32rXcm5OGVZ{VMOL;dwfjcIYHBkeDiuno@BC zAqr-pm8uwqQHQ1x5L2boSX&nVP$Sm?)jg`=J+^k2yxC!!K&EA7=ypS_eWyB-@!muC zQGZ1zk=CT%guw1_a5nHMAevr5)<`qk1J^pCG~Rs0g97iVqT5Js3DVXQq{#w_65L2r zGpYBF&vp|cpEbrSbfG14la4k=62e4Y=2tt}M194f__N*%+rQt6m9caN2O$ax0!HI} zHU)HyH4%l_hplc^zSRH2-kZSNRaN)n_uTtl-U|=)Aqc4;+?Ozf(L@rB7VzCuXya6) zQpH+ZY->wrT5C&NhD(N*2O*Gq;r0EJZgiKucaQ7b-xFCkom}S(^6V9>qJc5~7w`#(M?)Qbuyr%k|8H(x?zE>f;Us zTU2KG3X4jR^5!~@rq}v@mVMLs+lxm<67*E5vF$nTUYRo%R@?(jOo(O;5;c9eEetTt z29?L>*}RDLfIi5{G7==_R3RcXJIP`%de4UH+sL+%elk=?pIlo*^+jx%R;V(nzwFH! zR0eZUDWm!*n_`$n8P^vaACqNf73>kb21rg|&DXseTyF+kuaq-80ceR2!;qb9por{b z>{ZBqs?{wcyDA4zx}XXiGt{dqtJq82J%f`I5k;sqn&--cw&_;2ziG!)-<$8RF(2;J zDh8?nwQ6H2kD-4f&uU`*_DpZl!eS_R!g8rQNMm<^3&3)Wd?iPY>yXJC6T1%l<=6dx zCci*-`E(5*i_xIODj!B@Shm1|NJ43(LLAX+Vemh48i@bAIW%MrbS5^S5CRx)}FfNQ&GUs$&qrgw==Houo%Xn z?N9z}bqpqZV3#yR6Ig!;rk)*~WX3W&R+(XOY+FS`IoGXY;@V+k4@lBEODK`VCr`q;|L5Dsm`fzsPqlxMp6|4IJwVf5V*}xc86WvsE zhWB)d_JoK5Kw>KS=JeVwY<+rdXUJt~`*<*MGgi^a!t~`76Nm8qEhHF)T^r|aJ=Z%r zt#3*Vr|W1s3m!>Y-HZJ->3!FMfI*2l{vj?aIV<|A5(8Fw7sfi?j4OZg!>02Z%r=D( zD$Z;1tg;g)Xu$!M;oRlkstsJ-svvfRzBmi8jB*)@1Tvzzh?`#RO&IFDiSVK^hRl2% zasPxZd2`r2>p54(H&O~M^5!p=T9bU@bf-n?mgbCu^qB<*)l>~JKM|dFV&>$21AXPoI()AO^G}~yjgxnJnW5_KCHHU zZ-f-T2&iv*9RoYz2{1oxC$?$hr#fH2T=R!Iv3SgzF`^^Zl}hVaddpLJrFyd9l{dB7 zn=(~gm|=R}!hF2oU{vedrCJ(gc*g_zT02Cwo-EaJ1^$Aq!2n;K-?2XY%6`D`-dmGT zf=_0p$-I@FiEH@%9+XH z6i=vPfeNAo#b>766=E%WOtHH~>$!xskk*0;KyzkmRFXlCV_ZiNN~+vmh7m8`hIkLGBmQhcrs9Y>2>ys?KB93b?Rc35~gB2XK=urXxjyff@Yd36dK0^@Iu z4A8};sI{Yp@l>I)+T$+-{XUM8T76i5K-&9j@<|e|e+R<6DI&}qmd!EDCH5GNw6jV! z7j-i?vE70oS+-%yWuK4qzXn!@ne1JwVSZ{!rZu_nQ8g{o(dc6AFxf|<$#NgJ@`>C7 z9hg)!)zaHb+ej?4%xh;Y8g?Q;hq}e49?)qDFPnQLs3x4Ypbl=1_)KJ7;ElYfc!cZy z6pQkbu4bXsyDj42%Z1*A*>DE~ABcy1f)}+RBk?*%x}=^%alMv@5>Xw$+s0)GeIiTuVlx}4@ z+j=S+UetFSl!Lds>t6o-2z->4u)8K^((QYr=O)xNO&I>s z+sirRTL`qlgg#u;n(ZDF)kRWv3VVqcxJ=bup-#;*aZwt0{wvSb3z{-4#1a3IuvC6X zW#md6{zvas_~7USEkc-M2ST$sA~a;<=HZobQr7CEO1?5`{M!mf9G2$fx zThiQh1#(NofdM6@C6`0eJT-~4sx9)?Z8f*&QuQkh>{%UW{V6hd&0oC-uL&uXAMI%I4 zn1_Xg084_u#fKA?NIfi>pQXE^|3&ZAcris9-$FO|d)q?XnN@Cm-LEmP|B~0YYY}L^ zO*cK7zps4jh@#x&l}vGVW%hn7xydPw;UKH_r9&pob3o>d9zd5uRVX;#(VbsfABQbQl;RA2|uwdG1d~b0_)9 z((G$cV1DK2wzCR`j;w%k;EQGN>Vk^W#9iLNG`V4#nE1D-y^@Xb-TEYcBZ5DAK&D7) z87!H^I- z{)W&T^2^6V#|SyEoi%7WhXk`i4~-;~5ie*f3R@4h1S!d^iu;rnd3lvg zvS?P?bYk&@{LrjAv!FFyqp2)OG~|?%bb@_29Brplypx-BJ9Q3a1vxRJ9q+mm8$Ej3 zGp!>BZ8A@dH;mELh*r)@I@7(Lmy%9sMu!}h`6%WolaLG7tElT~UeurnCAEW?w4$Oc zHZY1;D_!SQlYqL=%7y8?^8jr6;} z%nM_0h#I}ZE157R>Rr0-i}|6%Sr4u()ynK(x3-PT!+PUql;7tkbWv^qKY5U~z)hJoPQ~ISKtz0f)->Dy|j6BS8>idX}f>vDSO4H)~pNZzu3A z_o4Xuks&-QUi)te}rVGB~}OA)qrluG-+z(Jp|-su~1QqOTh3MFdc6^rT% z+F7r8;WFL4I3^IIUeXAJSf@Hl>KAO&plq2OO=40XE`o$K;y3+)-1*6xevHo0e&yFr zA%w|pJk_vjL{-bj0;?su+W(U{Ys&)CWb_hpe{?2H?bE0iwQ7TwrDjjk%Ju5sRrC#f z8prY?8FOwst8Lo}wQWQ5!c)3D)zv8*dbX`9Z0Q9v)`UntTj_FnBD6i4!3W9Pa-({#E{=HyGjUOHqO%Bq3yOVesi*5vsSB%0 zJr|d{xL68ZO8kN!0@PsWw`1&3(>M-}9tU?D;x*-SgjRtQL9Dvy1+|yB0Ct(R4qCCd zh*ep(2=l%|fR{ZK8kImpxshe>h8$5(*I#I@>Lx@MkL%7KyhDVvX!l*?o!wlM-gtsO z0K47j#NpR@J);So6}B%{l}icfy3WgQMAP21520qUQ8_l!Cl_Q-OAOAYTDiY zKBuN}@6N2>pl&r7;v|}nZZ*NrEp&OWH)&l`VS~6AOK+-2R=9Q;7m}`?) zGOdx4iv+kti}SFTw40K}JfHD_Z}|I%RL7=q+$Z-7 z-r1a};t7Nd9Qv<87Yos19MGVsARVxHZhL-^4s0>80_5+tDRmlo8G1}3FCWeEN2b7U- z`tOj3Wj+L6)jKF~Dl1)c+oRDM!U8E~a(W2FN3|&_tZl5H8B<{dfAT0|jsUIPt4=4J#mI!}) z9n7UggD)cwC6YPav?Nwh7MH4%*|N_qK>K8`XwZgzR5<#Jh(eAAxy%b|PBbzYfjL61 zZO1VKpJbj%*PRrP@^r6nlcc-+6^wF)SF}+gqfA(5{zXIGR3{{c_T zZXTI}DG9GhM@xV|&#T*%0_)rY;LrDpHYEvp*2`hbQ@YTL+mv7tvMDtpp1QiCET<%= z8@4;B{;Wi+3`z{w^#XpPce&3?E7}Qt#(eyWin8pJqjKHWaK5 zgXkjT_4Bo+ARUBv@X=jxzjA&v;3~x0Tr(7iktBv>jqz={L2W2WD zZjjw|UHHF*C5ZeA|2Sjnm>Z8-AZV!UyhO{RB@%r$AH`ciJ+eARJy3`AVJ(bSRHy@) zn1mfs1(p-rSp&AjxN^OgKFcFnIE=*;Ak6Uq1z95Zx50OfwuysSPxgjvBvg%Mn^*BB z^}NQ?>Jo26uRUd7;c%Xwabxfe<53ZhQxq3@s!&9VD$;VgH~f-%TIpb_DtU&N{IQl4 zuOg^bBz2tW1#QBlRwyT;?<5FR+lltDT?Wjdx_)ieQ*x&oep_PYL<0ReE#<1um1WU$ zyt^$U`-NUOkL(@eOUIHNvMYLn&@_O^T>|XK0=62r6DNVPqA9>WfL9n*M1<$IvwFX3 z$oB5)eO%Ssl^p6=vk@aJkL!($LBWcI!&uoe1fUc4eN@wV=t(R<)DxRr!=O%6BQnW* zj>K+h%3?m&BPJ}{8NK5RH5Rnb3NTajrhpL8TMXcAnUQ9KnsXx1E%fRSsir72JmdbO z{{CitPb6QHZsKtvi&3sRXOV8SOdCe4c^*-W2y4<^81rS0r>R-|m*;_<|MM z?Qxkh|DHyzkZl?_M@0d){ka~)0Ms4XVBQ{kYMI})XCeVRnE94?^(%6BDlY>Dl!AB+&1W_$gT0WH6MTnt58SEgMo%#n_JWWC( z*s35jU_UCw`A8P}NPeZH78$(Qcu~SS!HeCga&^!PB8t4o3mQcxN$R9wF78mepOhQZ zp9#H@)S({(LgEI_EwRK6-{M+#GIe2%cc_IAsZsXn6%*(d`1yr_Lf8}_MsaD!%b5U1 z+LdKFZV4Aq_4mVMnA^+32&N%dOmQ{2+lA|Nb|=%P-fpkXHZsgWB$W`!xjzQuGpmby zV3`Ie3&H%9c~o5N1#Pxmd0-VLTvpFdsVZ%-iPiIE6=lhfWL=FfqpK=J)$M#i-dr5G z43>5vtSlLg0JKsQR9N}e&0%yGO)#tF(BS;apqOuq;YuSqP*8|dsdUow1g~K7k7z0J zjy%ze*^cbWoaf~==*DmWQ>Whm-xLKOa*YyPrnzXWGQy|Ho_ku9jkk_894B@sdk3l? zDes3-SZ#^9%oBE#K$8NmrXryK7-aaBXiukmKdL=Z2B^}W#=M{jln`_~LGc_fYyu@| z84`2YMT3(uKw-OtnKE#n`gva2ZerthP$9y^k_sbDC}EtpqJ-|$+ZfrrCC1wcCCkr& zq=+?ng8=*IIpkz)A zLN;e(O;vYNJt_|Qn%mBrGOK^HlS6pE7d5Jb_z04cier-_6=eY=6en*lADhJeNMS}< z+n9P4MLVUUXx8!)c2cRnj(IiP-Miq_QI>0kypItLI|q?E55V};-Z|b@MQRukhlu8y zTREnj=XqtLA6a5$cvpt%EgIE-N0ewRD(Q1ILE*VJakcS3>CU8&PJ8_PGnfZe>C6LA3RNBn(0q_QIw{{=HxAH)XCqys6vCJ>&ywR4(C3K-q`Z@(qdEO9+osPPrGC6aF%|DRExl{QDx z=E9*yimZZ?w}bis877fM^dHqkMTs>Nct!kZxWFp~c8#E|9%Ms2bjQiP+Po$#q{1N@ z4ygpp`<+f-BC8N17_PLw99`q(cfWER?I^Ks` z7!3bT5q=7l(q5Hpk|%p}MyJr6vIvX-wLlH?+SJc!dGGr`vFBThOV&@gssk(^G zF^7}~)Q)G=sU4HsWWEv%x^$z*+;-N`a#cdvXW860&&%1Yw44P}iY6|`KLxsc#d(kZ zY9&KV{V!pHh2sF2c7r(HdD1roBsH{_Nvi;C1k<$a&dMARBP#>x6N=sX3~3nZiMa3Uw~($}bK?JGi~x$SIphDMx7mH$maU3f>9VTW^%Gg#oBg#hq7RV(Q0BuCBjqJ|%44z|w6le}hD>N?oxG6Fm5?ODwF zgn@K9u7aSxAi@aaGDPNfVt=AnDkM9vu*aB}gSR(!BfDh*`8RojW&Lv^xOlB{|M4Ip zC2EiLL7r@8<-#=@l8RDp(AW{Vx$LtuvU4?uhK7&}8~M2qz`Y03VC(&j`|kJF&d73G zSWeqN(}^q=%}vaot@bRQHAGr#aEkd?v@o373mo)_0PmTnG zL=_^9C>{r|4Q0fl$z)MQE2Ze9lPd}dB?J;SKmvi1_+J7Q4E-I2mV4cM6y^5?90Xs% z2SDt_;75gY9|2H%P#B9haJn~eyEd?Qu7NN!o?!{>iBu@Cv90kvj(1<-Et)p77h2?U zDK+xG$Gqh8x*mI?B+5~hjzPK73)_NBRn3QHDr8*76!#FZ4C9phEt>U;bD`tjik=JI zJXRRU28p>{BqZL@krenaHVMU&-+r ztbKgE<}PpDj@R&zarubh-CoWBY2`4AHg<^~HXLn;hxu!qHC&yTC+L9%R4674M*DW7 zx4W;nY2%~GY#1>8XP{H)2Y-^jj8ZD)8(#9X5rzlFGm?$?;lTSmb(_Yl-30DzVasy=4RMM56Tc z+Ld~wUn)Wm#4`>4#ne6do$;sYko@$_rD`eF1=uNCfXBUOixCoGFTJ*Ft#6fTd4`&Y zXes^8ggppw&6+4?7M-mLRV9Tur8O~g0tBj+w>C~F-<`c762WLEYi;b)qrML;gMf>; zlgah8_AzWzdIK$i!>0Il>v`?0DO(y1ZQj%e)F0C{Ez~n5q#0|{mnlBzu6)>;7$Q~I z){%5u=`~exn$MU*n*n(IjZ1|kQu4#%;jW3aN=frW|F4B~L zs^ouUN3$i6*ML_aVGJ-6hp33CXygcvdw2ra7Ab=3;UZ{g9GRf^5jJQZ>(ZnTXk{FO z3ZuaUj{yFIOe)L8Zh$r8nDpHX)2Z_US77g$goq$$olsd4F3F`$0e>GJVJdF+34{BU z+D`N`H0JMY)mq~dUK*&8;=pW>NjBj-y34dt>uyu7yX@Umb}d;Wt&wS{_@r84yM!QY zz!0nr2j(e0-nQldC*fX`ZbV^&CKuo^LT+Th2i zl3m%H#7WB#ISE5yKVw+8tUr;-@{^ZE!hPD&LM-z!+|Zv9ZES`<%D))QYU}~5$W$yy z_%rKdE#AopZNlrKzt`K}w!N&>hWyjjMBAKjLwSa-XQSuixMw~LV(Lp<)oOCJ4`Wy| z3>8wyQH%#9;8e9zG}#qC*|I?a%V0Qy~4xP1~QtH3-?~)=1aTPiix!OvAeBs3Y*tk@f-Fc-_EG7-j<9=W`(y9`te|W z4fJ2E+G5Yl0t=_hD3DJcmfB~>>wltRe zN@MBMv8>LIMgHJe(2I-@_k68mfo3uT(YW#z!ew^9LP-jz+` zd)V-4>_d9g>y}PO{`j@zhprEoe?X^ku|dL*MgKGWpGjPq#x>mP16JrM*hq}|3AA{U z-bsvbgl?A-Zw!lXG+8bs*5Eag6`0gS3|7LMR)BJ0J8Qx~NwO|Av7;jrhbwhLe@5bV zlm#YDfH+Q-oy3Lt`_r)I@{}nfK#Orq#4v$E2aB53qiSSh-kI$oO+UanF?~F&9oQbC z1+1B@5jaEgSSS&d047i*CDNDs;-yO5Ky8sCl)we@BiB_I+VQ2O zj`iq3KlUT^C~nc5Ur~mG@slbjg{X?o;|x(E$n+JC4c+G1W|uX9niJvMS|6L?8xwT$ zARbrOm?_u}Mglg9FSeq*oMyGKAmOS_Neod3=)@NsFjK7T1^jt8ih#5!?#hZ2g+MEN zRskiLdl%ZhBXPNb4K$3vEo=lgAYr}*M5%HliAAaYEO||SRb5{9r;+d#{b@qhNx9)q z&9FG~0^pjHu%EZ!R?W)UI#5%|3}~;#t-64rn;{@f2`Gpr{K+7jY`lXEs{1LL_aqTP zL&zp2D9#(<)e$<)we5)NHVuG{s6-wt9!JfV@7$y0Yn<;*n7F8rfWKXp0dc+KtB8yG zl!yN+?&1~y>NCt49>CD3;3Sp2jDOTEE{>QX56N1P%Ff+HtqLY0VxBB}+^(L_`s)ZF7i zcI0!FLiv;=Or=n;h`h1r^@wzQFA%XuAxGPGs6Dg9;FAEb`q1 zVhY?r2BkcjAIi-nvoy5UOETz}N@L;ul#qu5)t9kkGAMenvA7Jnb;g#u$)I2Mj!bY8 z8oaSWr&2HeD1^aR8A!4@+Je%9o(9E=|6u)Or&Q@d(c;f-XSL(gt3RTc+j}f+Pxawf zMs$i~2$XtP5NZ-3njpmVAV(*W;0=jCEG7WKw4JHTlhM>96-Z8SEs^f5f}xn2k?Fpe zQJ*G!jlKv5+)5$=d<7L=C(1Rxx3M?YZ=16hsh&MG-LNf9t>V$78QU^zpjqJF+HG5X zcxGZ}x^~;hqq(rHgK`U!3<3QfDI)Z$w24$86`i(u3$S*|vt**tvno41LK4zYKgSc^ zDAg=@Q5Ti^)PkE!7mJ-_CBf}hs46E7 z{gFw<6tE?ahKv?lQgf`!3BD{SW~q0)M03vZz0|<}fX?thI==Z?wv2rrzGB;hjBy}h z?nrl8NM?+`;YG9qm^+Rh?avOMcT9-L8=3$U`2;ak@N^~(nLXA@FI(xg28MbO(bvm} zzFvvw6Az{IHW@z5LxcJPc1gmDHtHk6;0{gFg7cibuJCy_#g4nxK)U&HnO6<-vagVs z!`DHMUI-a!Ihzaw4umgH`W>gew==xA&FZ3O>|?d`owdb2NH|e2Tb^^gq4O0lNY!%% z#=XGhT0nhTU+kLb_X4j~(yLz@eAQA;k>GUy3*_h@L5xHs%Ec?$;T08(GV#bxdgqS> zsCWeT7_FqRk;+YjW*;?g84m@#1@TNnTTDgybVS$~+Y(N{j`btW(M|`6>jDH|w z;As)*8);`v8tL1EQVws16|t3f!ve8@ucDgLM7X=`0C6HwJ30s@n)P(70b0Ve<6%EF zMuhu81u9xH7nOR%eTEbRR%w*EY~t}G#GDg}v&*qFk!3e(N_w*h3y8!rg#(ADgT?~& z-BF+ARfg2#i-S13Gzi=l|7r%Y7n(+5$^0OyK~CuaRB22U#yuNyrygm+Hz{QxAtY20 zM0=Gajmt{|M63#njwe9{DJL7fs-hAmRZry_Ku~&;gsC8eMjCwEUgtGUnA@2$A&)jo zUDJ9{6U{|i{!690n#pnwM%z9_Ss}lV9zrn?P2&5KLxfu4uYAyvwk*PbM!X=a8o}|= z-r_ypuV!^ME6ov5j~=4E5bR41$uUUaKuhkUwcr{p-ae!yksumfg9|uuqa%oTj%3|o z-33leAP8u(%OA~Q6Dh!V`Y<(;28T65)$HcU>ZsGRUrZdXCS?eF{$v3*tU~Xff!P6~>4e>B0(UjNtXA5>XE7hc6TeD5H>&B=>z z-{y9;w2pIv{PrXtlD%=ClmxgZt@nU7VV;oB@`H}I(|1aPrgfj&h6pXPAHHHO%d#Jk z*JZ!&a&UG=TSt6E>lr@NpyWAa>F=4+fV;TWXNd*!S>Z<%I7CwQfUbFpV0i0 zUF|y}&mdNT#g?N*RPnl-*CTDo#sV2)rjJ9H% zlz844sUlYlr5kr7FE$1|)RV4z`A4{2TmA=kO-K1BzDT@Te3$NmcGjZ_1Z4NC(s8Q< zfa`aq%AL$CCzP7O9MulCVMno;^3XZavjL=K>OopBkU)TTdpVwjeZd?CMEVUol7yx0 zD}ERoA(nbK#_3B_nKNg;{T;L3 z`L5qR;J}04jnD9KEB!ru4nFwcLk>CQ_y1t_d*t)p_rCXi@0ZU9{!l(2{NM-Yd#W9>cec3Lsqt`pOLpumz4L#n?<56pl7? z;aHM0#qtkq<>o@!aw*PD0_k<<>7G@o4v$dMwk1TnEZ_yEGW+f%dZAC#t}FO2>Do)2 z1-!weIqz%}vC1yf8~G)$3r zEI}ey0rU)-l2^w9+!7VGg9RTR8Kw$QAgT)iX)^Kbufo-~O+ezG033lWfw!I*D**Zj zeX0+!!!mLBeCyI>yBS#O=7?Kn2D!;bcwiKG#b3R_P*a0NDKp>nAuhB>j7z&?7=Mq| zW8ujNIFgk^0DNuhzr*03rs+oj6iixjq|J)`gvI`r3rx$G6q8c~M{t2R&zAs38H6qF z;kGvm5D(#Y1os5lqCVeM4&oD4T4K{7o&~ek@d0>;6Wq_qXv1HA)Pourz1x3{p$Z6e zsC(nlr}aq_BlK=@MU|{<0JF{yI~F~fkq;>4b5x4M<>D|nK-#{7TFHsUxP!Z_0`Azv z{<1hRg=jVvfp7L#0gvdx{R`qzaScADPl^*;8%?Ye5x`YaVR$BX9FE}u*OUMpCa2U% zQ3wSPvB|wd6XdkUCsB;H-8~ye1#(Ms9sXV&%TU*QAJ5l>h_dpG`W%g1Min%VWyyNg z-Vn&jEsRcwAjbCs*(dh_b#Z{1BdRK*l!yhY&jiXJ-?d-BHbnO-zA=eWDteZ)G1JXRUPerZ^Jk7N3)2^ zLT89S6J>@&l9zTOjxK=+H}P9=hJezu(vFF@d2{!vV)0R<7-nbA2pnOIq1P$XGP3QD z23kMl^bSS$OqsM6|6>-@Cig}*sXM$2lf3^3a7EGa1ZCIESu?p$4t>7BX&;Jd_fC$p zDcxOa;!v0z`Y80x4W9D-J5N4^2 z!0@0KG%$pM0=3wH`Sq&e!BECk)!pwa`G{Ar?2aGAKr-acBX!mAHhXm&-XGdLWO%Wm z@!M6!HFBe5lzgh9EH<&IK(ku1?C&4IYNj}K)l)jA^1V{+4|FmvK3h@LjEf~hy@CPrecgch^Qz(spKX#YqM}`p!GferrS*y05`Sc^M-kt zLvXIa7Y5%Ltyee&BaVdAv`$Cq_XMAZNx$#LJTe(I^pzKao@SE=0hlV~>b_U8jFZWH zX8Af#vCe_0(_OxLlEn^S(;08?#Icw9z>Q=7t}H+f?3~AuWIa7RiUZC{Do8iuP+x0| zJa&4JCj?0xH}uaz{=O* z|ETTrN^Q>+Qins~5HeT^JHyfZ0x$j@Me`ZxLb$t~z`c?k?++%Hj$3Nep*qHpIh!x# z`?q09<+V^hJ-f1+#Z&noY*S+g)fci(MeA80e|usMtN4o{d=OCh_fWm{c{a-21NtN< zPoM-&NEhaCjnCoRItSKN4-dW+b}F9(W%!Gz0;8ovt+Nl> z*?6oVeOmv5Ru^7Onmnptoa;Xn&|#F3EmtO;Q&JBSSZo8_ftheMV*EWsr3~;o1%}3!uwaO@1T`r zi!-x+D1fI+DC+|vi&$WY$&HMl59s3Pw5b{%cQhjbpmJg1S_0iBRzIZ?CkG`iYkmVf zt$Nu63R%)zOe}aJ~%PW6k>eUdQGmq2DG8 z2n_7I!{7&{I*d&eqC;O+)>kb0{-{(>Q&?0?!auV+RgH#2+tog?*p!o2o(B z)v*$D+b;$H8eq1k{7z1)hJsx&Q`x;xyCa}3DAj!v`a?NXpG8TT2-w8g0qWlpsL!yr z?YP}oXl9*h79r=*u#C+Pnj&-&Q4Qljkf^hhN}VAeqBf*90ZZF5O;tS3yMnChfs-ld zkd&fP(%4Qb^%5eSDWhQE+=qzUxAE&FaojA2rs)~phTS6b22@O6_*Ss z?l$~$yplCfw=55d#yOvGIdy2>hA+`_+4RQ!z1?hBAOh)m{@yN(;Z9B;*^nn&+edRc z-zyo}LOw?540S)7cGA`P2I5g)RBFH-kL`)Cz>8g^hyEA#@*XvOu$TD}_qLrz!>M7g z3*5q>Tlr1cm`Mk^`BDI>(M^W;wq|wT_gNj=_o$=$UTiC^-LOY8PCw0)UQI2X1zOmS zn_|EX%>}b)r)`EF_{z3voor;!R?BKmQvm$wNs%L2+_oaGR*pX#nJ)!ds&WN# zvBJADa=}2I^tsL5_S=|Ovi(LH!}(}Tn6srbyyT<0ok>{I73b%hj|HohUdfs#jbZas zqn&lOm$c?dSJErGHh+#+vgS!**nCWk&h?Uy=;%pT(#yY^AHC+7@F|abC2O7}rivJy z=Ov986^YIH{@#cYiH-MkfxkCmMByg==`(p+@;ed8F7!%9j8yVE@A`Z#Nq~~;>f%x@ zr$CoEs*;nJG(PVzsHf<|?a{#gU|!i6ub(rvV-M_8^03 zQ~j#mJ#lvM?u#fn?g{Oz!G~432Y@>Deu@`1n~|Kw=r8Xrl(R5Fmz9>{(7tu!3wYw zL8qc)v6y+iRbKBAw|Jq7MWWD3_p$(x9`@bPW@fR6v)oMcSU{NQ)H@5?mh@_Bx%YI5 z_hgCe5n7)iTV_GMg^nGGfzK?g%q%L=_ulDtT%hl##qI?m7d+T)~%&l6npD91q2e%LklhKZswYod><4@ zDJs`WZs;$2TP9>e1E(80JGvk-^kUhngh(eYcds{WyJZ{hmiZ$?xi#G_+Aa5aCEG2O zEGzp3qCiZaMtnJ_-o!6hRB_*Zv+tlfv|V4^2faxXRz;e8X`X7Ss(Z%w%0J|l3ex0^ zdaT=i-AkJ8DbnQfXY=CT>!WFI@=671az=fpsN}<5(wY}(@~o@#&BsQ(Z+NAGGzn2# z331fPH@&=dLYXpMc1gYywHi8HAMr}oiQ1=T)MJVGQ7>uDQ{?oP9`pAmvNBG?-#_l} zO=JanBT{j7eg$=?UTL#eDw+LmneZCaUx+{q>JFK#c_V>lunzhz#?(PVRZitW-D2a? zs|n&n15<&)O0XbyDsINyW_}CFQa; z9<^r@l6pE(5|;9~sF+(Wn!KD1Q1hgSOg z{2uz;wR!FoD{yCerP3a{au)Vb|Np2`QXl?5;Rkf(o}`A48q;VT*L%`J5Ik>7gIz6W zRby&Be0Jmq3f4|$p)2=kSossPaOGrCn*+1}yh+qHkM-KfXjamPb zPa;?yq3VcJ?;NRq>~Zbn_+)M}FPWb#NJf%{$!Kyya$>S5IVoA3oSdAJEU}-Z$*IY* zWO;I0a(c2N8B5McRwidAXEE!t5=w05QmFe$0gX+YKZnIzYctrV=|n$3lPF|b9sbkdTpiK zDMi>cP-N&Ts=N~wDdq1HY$uH-5T@x^tOOJPUJ!F2q*Rmd$Nv&|6BI@J<#%2Vh8!fUduW-MLXD&VW|MzQO8uu ze5<^k^>(uKcKm3bBWx1^VYSz?-WG@H#FFdhyr^|>l5{ZARWiQBYgq@2w1b%?vGP(c zYAo?Y>EJ8h&co|<(F`v0TGqh{VFm|BMb~&yo584baMNx14&vOimwPSiU}5NBIO^aE zFKQi(u&D3&wO+uu_5v1|UR#&g1z=yH_BaI6Wen~Jn5BAK_Y!yi6*YKDfyN8?-*F^G z=5On&Wsn9$wv3bs3cw%{x|g) zvx`I!{gGEQ-1s>ATHLj-=e&~jb(r*3=2k!UlD1$UWAoqWx^aHum8|)XO7r2soukh4 zUecP!X{H=%z2NVSl^j}l|5JZ&OZJh0)>nxyA1ajlxtFsQDZYQv-#@54e@>zPFZ{jr z^Fh1^858aBzuDm*5?6d?zw#Q^;|K6Qowq!Xq4D;3$txM)-d||+*Z$sy@xEfOFM9#& z^*v}{i%8TyKGTT}iDno2J>K72zkiT1>V6pQ1QcS26WITLaZvNTwhihKf?`8~b%3fA zNa}pAWS}^>Fr)?k-iGvhw(>3dEJ(m`0+AfgI?k94Ma2Wo&ul&<}3mR4sv}cUg)4@N4OObd^p#%HrZK%RqBH%yjcD3HYn-FluTbu6FK0dS{T4XYIbO-Yv2UT#bN#(_ zzE5$>o#zFtSMfRj;=KGK#I}_4y^{61XQ9^%{Jr%$74HpCbC=hxCKTwGCQ7t& zda1v+&YOyZ*t;|8>rG&SIn3ZRvwoW#!luLxAEd!)3sZ@q@iw+gx}`xZD?B!v`*v@=wwJQBEpdvQRG$w_-1>DEiq89~x<#We37({UG`gl;6T@nSj5*TI zDw%g^hk>-sD@n|%I=$AEj6_K8!lSXgG6Z4dTBO;KO@Sh2$7SdlBFfV-HX!~Y{VLZa zBRlF6J{NyhIvTzr!iQ&3mcHt%FC z7&kA-&2coLH~7t>*4I#*oKc^pe?lC^D}-O-LP|up_ljMe_ogy#s5h%b&6`iQb)@ck3qD&<#8sZDzIF?Q3IMVq~si}z+G-8WJiVQ*#Z$Tw85o36Jn5AP*Q7fG zDRm5*9BmV0!397VAryd}a?u`819QT|1wM%@)b8bHEw1JDI7wxw4iI^QAu{ID0aee6P*o(1aB~Di`4H#T zJ8IvM&x}x$Ocabqlfx2xG^tt7^5DDRGq0WXpe_}L|LL6}nP(-%lCrB^Lc;Np@P$-N zCCtGp>kcsp7K%(0Xv&}7`2z3U4rDvv&T9a0-IBcmd^{v9M}+%GzB@p0Jc1w*tQ8ZiP>AbZAZ3JeLcgKCyZt`89Af$O@WXNqeIxbu}bV1EKdc}+nBIeQP4 zD`>S`evz0%Ua>h^Bn2Dx--0Mr!2EVLr(MLrrbzKxR$#=NvK5GqDUW&qyFczH&=fJf)-U#QDib`hYWOKvMA(7&S&)=@eoaoII~5%D z_AHi;qKj~G{N_?Ns|T{kD}GCvC)IugnnzOJNnXzO1)_{SFJ?V_m4H1|7YV0_7q`G6 zkE22sN=$O74@e8`Vix97YU-6OQ!q8&DT91gBgm6PT8QF-7WRM^_K+6#C@o~edSweF zBH>oNNnMj`H1Mu?WlNlsj^TIUC6`6poK`#I zB^k~X#b(|ZN1&<)oj{ zZls6`WSq2{H(%B!PvGwBYfeB~&fMH(6 zq-~Va1ZVKu_IzN|ar-mq~`badl7wsSUJ8w-D%2Ewf^roWBPpPj|!_ny)Ao{wRk}*5U z-5ILaL{JssSCjJyuwpJhubtH}E-$nT@SMirx@ZX&cxe?piTeVhTqGRAMp+wibRj~A zl8E7HPIk^Z)~1O4aZ`i3v!Lraap0%(OuR#)}5f+g#+&zpc{ z@1~~u;`192U>6{O9%K^~$gVMC?iPGrPpfK&jkYdA35t7}J~X{H8}@7n7Bp7b-G0L| z6T)vQiYf!kQ}BiDtVzQe%286X0%uO}(r=c9qHq*|P3;ODAV6|C&Ltzizn?*COM+$| zz84dcl*^GbR8wh2r72imh0<-uEgq5VMLvS>s>DkiFNjrCr=hD6FjWdMhFE!jny~&= z9GZ?rVGtrnWs=b1OP0>1KA@otcRThR$>qzuvO(Wi1U>#1C?~?d44U^_%F+x=c#7^q z9ax}>e*2*Bt`*+NJ7t6 zo8mxj3K|FKR6U4&?JFN^x*^&&bX2$22KptL z4_dX>X#YzCK)jjtd;0nRhW=wR6L6Zibqy9+W+D1r00np66HV61rMIjBg&ZOGEgFU3 zbBX&<`6HOP!Td98E7Gul-=MC5rYB^-WyUw!+)OmagsD(5;fLstQaF3t z>2k#7J_B10P~JL#nJqgg*zp2O%J{Dz5C@QwJeW_+1TOb7$am})*;YDOb)D4YA#Xs& zJ3;{*4It>`VmsG|WQHSks!6*h9@%&5>Rj3u(>{=_*5yX+{1RR4t=R-=4#WLY7{YkY z1Ie^{gx_1y5*1RK(2H5SFDtb~^3Wq9*fzha`nt=R93%K=aBqUBxA)65Q`4Tb{HfA46 z>wcglL3+}MT|3TLFd#e$7!qo;3SU#<)(zD!e@mE3Z+7q`Pf8tPD}AIYGq4s|ya=X7 z(~cRcV8QkOMkYa(q1@$l%ymA5%v=p%R^7U+ zBF(9EPQL8j(SERW9NY(NqY?lXfr4>%!(DHno2lmm5lvup}gYc7&C{y zTH|Sb*ngmXeyD~IMQurSpb->$;U6#kQ=_V?q+~T3!G&wI-xzMu-VV-`@Yx=p9d@9< zq=UY?AwqSAl_KYqBpM~;b=I~Fn*?O?$DWPZrCpGQ+MkPz&y<#GBml6dp@s@1-a{q6ZA{4E1{$y6+ zMs1o5HMA@~N;y_)Y&%kU$jO*1J)C^bTuGBsg z+&RsFE8*6iyLonsI(&cWo~qkRt@RRFRJa1Nkoz`r$U;N2JX9N)z(h?l*tunkic+St z`azjq%VnydNIQcbfqyd7yX0D-ge!KiH)J`@Y-K*0 zacI+&@UWTnIT2#xcmrlX)Cc_Tm-tZH6sOk?wRqP|QAQ!9pMmD^4P{z%VN{cxwkOs5 zNT>#jiztnE<6@uSUHxJXP?>hBWmiVxKgc2!X^ohuED~&3;Hf29WT`jVK^7qZ#K~D^ z7t6h}t+aY%W)s+RV)=m33XEI0ka-C@Fm5S=%W|l4Ruzdan;R<)1_DhV)gGKB0S!5N z@>aPK;Ub}4JS~$7T=TP)8$ftF5r_^5S5RdXD;TFI#=JmIF}EP-&+j z`)yOlsayzStNM02*gp zz9^%`+;&#O(1JArw^ErDTo71_hjW4`A}a+3!aV_YSVCPwS_Da2tg+1wQ)@&<&*yuu z-|x*f2Xd;2l+a?*HA?P~h{1Y}&H^8iFFc19VdaNldcYK|1j|hJ&8UL7U^PurCHLV#SS(PF>S?FXJ(ka_Gf5WKsq?AceaV>fot=QXTMBWj z5C2d8VB7pd4Ii>lJPNbva|xEhlqR_`H<8@W3aEAg*ZZs6MR@d z&~5ws(%WGs>|wv!82ibNY4krh8xNe=wAzpw{~mbu=2JXNHn}LS{lj1pMmp4xK~skv zrV!>>xzxM2Ad+EghYoVYY_Un$LMYloZJ-B0DAeIP$0P6yv|!jKijw`fd{A<%V9%_r zlT>l|>Tkf*F^=9ALtc37S|*m7V!pm!2}nd1%|Ywh7)K!1fYof-TjhH`qGA)T`%0go ztvkA|?}{a2@jNWfvXZM>ga0;EYt@>yZE7{4q&x%eX=|9SMwaDph03rduhHoMY+NT= z`k16VTM{a62jU?Pgclazd>@`I0FQWQ(=AQsLN9OAnFZUot`e>FvN~3ntI8ode7R_R@pY$;iN zT$U8(pU@;YAVjD&>1h5w`tV18{tevh-rFVKo1LzkiQdw$jOUMJYNVQ1y3{M#>AD%H z#N{5(&kTRhj&|;4rJDP*yCsFJ5r*6umtIq<#6#^qoXh>a9p;;kyF_yd4{i1`76E#y zj7ET(eFrc(g<%+>qfuYs9o(c*MAI+;@lM*3WOsmbb@8Tc$+YuJEWO#%`{37l+n4Hc zzg60{rNuI{$~sx@W?{LH%){VHZ^qVfKQzPntc#Z9$Y^p`c}-i)eNi*L>#S}VaCNED zKB(lgy2jtzlI$(R5&V2*>ws;B#fX>U^WLy6#a?K*+fr<{RJ~hXiZ6KEwiJ6x+plsd zuJvYYDH!4LN|s`s*R-YB12xmJu4mP+D^=PZm3%3_=222qB)?6n08?ficp(7&8L&WJ%LWym0}RB5YV{*}A~^1**q$TYca20b|R}%mA4a_m%FvJG~iOZp{_2<(+qz*Rd*2*pC-K9#* z9pKA-kH5F&ezPw3QC!(0!fM|~7}Gvn265F=-p}HiO}~06H?qL?1Fa|c8&1ivmYenO z%8q0$$Mb6$FQTmNmez5T&)C*c10G)Gwtd)}v2~;=h(OyC1^tHCv~`rk0MB$yYw*od zB?%eJnBF7)-qw+k%D&Ez`gwV&^n>Zs=0t)FK~b;RP5u0C;cj_bTFVu8?@cv+U@H{^2@R%j*!0t~)xkizDN@A|!O^%KR!_kSmfw_SM$65d6gQ(5c9m4Kws`E6;1+=&GAn<>Ni8OkUU5uNLy`gT z-nClEN4?a$F_{}qIv)6h9G#AT%@S7OLUsMxkC1wV5BMTwVbu_uGc=)yCgMyFbP>1; z94VJscV#_9+<;ZbVbucmLk3xQHX~qdx8}m)qjqqvlV(8R+P-oc> zyn4M3hv_enGZ&S>ju~_dXr<)O^-=ulIc!IZw}s@H+0u5!_g*oitx0#|;-r~R7wy=g z(@AB;RN;LiAZdr@8^iVN2XOAKVf!?wEO*#5n*&5G8wDa0R`bFqo(=7X;VQb$n&wdK z{&XX=qY3bVU2^Fa0*U!hp5<3#ep|cnE3I<}<8}CQGX9mvQ({_g2KvCIOZ$&}n302~ zQ+jYa&-KY@uEHEPsDD;x&4U_{QPT0bnp|7OAK4vX>fAN@-S^1ccGl`5RW;yZ6bM>d zne5X@H}I+?X(8R{U)P=taP#=1;0q4`APOg4F9k@JLk*oWDI$){>7`O)9td}rGl zd~t>Y!nnAf9=?78XyPkJa^1y1b%~!B7AUk*oQBLhBd5T+p8r!CxS_LS%zj zW&T`WdXl~jS&jx8Wyc>8pbI6ykb)^^fHov^qzmGm3tOiSqzgzh3$1a56?*VED)fTP z;mpXl)uMJb_-tFTUXVZ2(Z`Jd5u?&2g};hBilIW>QEe$hoRj5;p^Sl|QR92C+)Fz{#k%EM9 zW)WUeN;XfmXTo-Te))Z}=lEnxn`gn+*gVx~CF;Y!ogZwqy@aa-$Gk-YRXGuGtt8f= z14n%}+I4$#*J=1^x|#;GbT6XpxO`=JH24jl%Qpc{7AA$Y6H9*{Md!A&4)zz6psi+l zZ4!^dOvR$@2~?N1fdR@=7^X8dJeAJNJ#t9gUsXLWhb@AP^5@?jCwTzv*5) zGcXxXcf(VeG@ecdoe9r(<%aTUI~JVao$W2tqxD3f!gi&86Yb)1z+LD zT;vVTlm?lMv8v~jyrA~n%=fHqbNCEY5<`kN(xv;8z14lCd$ot?u1x20#OrHpmek`d z#aa0zmUt^VHX1cDsN`DVw%xJViVkibd)ln%=Ix&9?M{=?G0aS`fY8phOE-dE7nq@{ zx3b(@(b1_5M75vPdgdG%Zy~p4w<^vRVpX2~e%?wG=RRNI-Izuxi3YY%>x@z@Ii-<4 z-nFkYOSP1{b+2`Hsg@kjNJpN}&nv#6@7z)?jXHVynS8An8t0X2iNyf-ALMJrmo{8b zswK+p7HVBoswGx~E!0|7ss+sftK5BrpDWdJ8R~o6^-!-&j;S9_Y^@LHwVmG%8~AOu z0+#a88a}G!LRAqZr6XV2l^1G(wZJ!BxT?77GA+Qd1N(U{Vm}{5(IE73Z|}qK0gK?6 zdi1K_;{a!AKnIl2{GSln59V8b-l^I zT9%6Sdx%dyC5g%CLvi|?=@ge&O(xTzkZZ@MuG=j1_5m7Ee?Myg+FB@ZZ)#M2W6e;rrf@()yZxp90`-A#A3j6#o8muF`rwn5NZ02hwA$8or|%O^u?dvx$Cf z;viIbD=OemY2g6;y`MG!%44`BZpOWs1Ee|O6X@n$D73E@0zFCfu|_Wq6}r; zheaLHFL78tuTd;}Bliy|Q)@pIhSYAlE+|W#`9bO_GnLUgG6FRYYHoXw_lEC_!VsB3 zxx$&tK_cVZ@pzA7hgW%ri~D8u=qU_an#YZHlM2-eQM&x*e5ls;0#cvN=e=>0c&4zi z^!m~KX}z7ITGy6p4N0w29>_}u@$GTfm1?Pwd+lBMT5;Cx>r1s%hF#mWuNzCXRA#-X zYpt6~wNxTq*|pZqrCK6^rZ;z;*R7>mDr^4g&Ti1Sy;MtO&6PLjYsEJbeYsRiWzCH% z^R;4I)19SSDr?@;wbtFGS}JR9=vwP5rCKU$-qy9&y`@?zYp(BF>%LMgl{IhZTI>E& zEtNIDa(^C%G0s0&s^zlgeS~)bfzYNDpagNFCPqaXA8EXSWe@*gLY2|9=#~Vd zkzq}hzz{N9*kHiXV6N42@|;XpSP&{AsDq+7Y=lTH59WsKbjL^}fOs7_bi_Y#)C|W1 z!Qr%6)Hr=Sr30fWomQHX8gJBSD^mg!W!4#*Z)EJVWQ^qb4| z*%UayX2nc&4d$S+*GtGa4J*RRqN$|U{5W7V*C*D>SNdeWs_TE?@`R*P(J_}Z`ca3H1-E7{lD1JxyrgyYiad%;@%85^<2eK1$5hb3>Q zVdn*V96=1;m_Gf~gXVCu^MUD;vZbHq|I~P%wJ-D2=dy1q@nl}d^!ED#n5g2!B=kZb znQeSMGzgH&hH{h^`#<+I9}$&wr?|9pkvH{RpKQ(T2hwNhj1*@u6(UtFUaa!W^ujj) zi+3NLUVW5WC&>OGD9D77XC4FU$FX+)9>h@;{;uKpNq@60ctSI&B)X%Qd>B}S2+bq# z3+(!E{8Gs$TcNNgFi$-tUl2kwVrZzNxj(QE40ZNFUpRlyr7ockA09#5Jt94cF?%*} zv`NldzMerxe6R&DZ} z-wbB9U9I>@#2D6jsxL)T#a0e6JOEBr0LQ#`R>v^05BmgOEvA;-lz<)_gkQvrIECD3 zMa?O3*#4r5LbeU3A%T(8vr=}|Q@o}nT%3T(%%~33NuGx7# zb?mL$;7T105gZqLlUV{DasBiTC?1mOa@2#RQ7`eTHfpRp@KFYY zLCF;p`j6pdBI}BEO=^GMTcr7f)#l|G1S;q*XRTC;nQ+>GG z4=`iDntWtei_%g|Ol{eF?0|FEgtha-N?Rb31S^D~Fi1ot)W|9rkdYKXq0=mG%Qz3} zNIR=(+mbP<*p`{h-NeSEBoIu-cp*X&&t;KwQ$5#51K|;q>4e_*$rFXR_r;~&8L%Y8 z)=kioaEGJ7;pEV4grBE+J6Y~5;uHf1n>>14&+wjC?Fbjgpv!nO<_%r1cmv%&pkyqE zp5uiLCBcF_(B<>JtgR5!;3!e1+`%9>Zb8uI%*>{TJekS>Ji0`RSCv}qW9QRrS0>_y zWM_ zM|vM4M<}?x3ypw9aHRA$imUyK#kwZYeAQDOT;D z&_Jt!RByy{lEem%RU;OJ5;5NOeVF!MiWDj-Av^>TnWR;aIwgl1d^o7$@Fa-CD(_G$W>U64QI=|=Te-> zRb+Af-j}Vv3ikOp>A22{QXQA-k0;J-`MAHNyc??N2l2WL%a!z5 zS!Q=)&H(p)2gF$tAq=*A(l3bqKW0JMUk?||Am3<2Acf2Y^wPjiJdPMLdZVLNMQ zipUk3M1YKDLmd_~n#!nU0}m+94byRp-?WAB#2_UjC&e0fZSI^>bEZyBg9vUOyN=S+mjKN8(y|6g zL+8a@9xW!dKZ_Crf2s*b68e>WhdP#SWg+6*;QOF`r;ZR?Ip?;s_McXrSH!=HsGHhA zD;c=q6F}j?%B1Ll*!{oX|F=K@Y;75k7w8KjmG?z3>R3J!X0O?b;sgs4!!k8XuwW?` zB)`HtX7Te*e%|%2-^J&E0}pyP^DHpU!tD3F_kHjGz#o3_gCCspp$~odBZnUPM<4yz zVITka$N%^f{QSu$Kl!JBcKE08`SZW{OME^ppTGL+zdqt`{`T+i`TKwPM|}PXpCkYI zpZ^7)&wS=zKl|Cw{@cI(`%y>z$AA9U(Z?Kn?6JqSljHF-H<_2rPZlI2$--n*eojbE zjD8j+CnbxMle3>wl2ei;_*t5qYCp@8Wyx~DKbI%^b49WiKUXGKC08fc zB%e>dkX)OrORh`4m|UOSkldJjDY+?GpWK|>lH8iymfW7)k$gGXkldNvWj}W(_u%I% z$ye>?-ee#5?d&&2cXOkZ!KTLjzCo&Yq36B0nJ!12ngGyGJZ!ODR0PoPgPY z=Z(cpEojG0p(yIYCUMMA1Cka_#Y#ZZh+1aH7znMWVfnn-kUmafADAclAOo9?Uyvl0 z;4J<^Sg|2oYd|hjTm2fPgmv;z*sl`NxLlcE?8C8S3@E~Z*Hj={!ppzyb`_`wHYXk0 zk~$?j%Z5ew(Tk|sCuZ^HL}pOxYpT@8sNJ7)u)H0Gk>C?;h~$~PALVCw30Z_jw~3L2 zcbX5-K##(ZC?>+<@>~L|I={S-3=QB*bKoF6LpG;vMw(kKz`KETaI}eE3-HY1EBZzk z@C^!Ybr9-7bATCtA|i0N3Ym7A6RqsAX>)Wkjzf!hyND3~DJRj3#vr&(-iqQc`o+pg zi4$1j1ucPAAs#me4oqszt&naPza?b-Cs^y^p@AV(!cz{P47k5F1rMGBASc3gkrp%= zT!$!_8yu0%{-KG|>JL#IqY%tk$Wh<{*IZpc&*E(l*M%dR$Po=>u8V$=%J)W<@9V&& z7}kf9eVFRf#@{ zcX>(%#O$D3aWsAM2IFn^iITxYhTmatHt1+H&$GoRubpx|ij?&5`Md zXivePtta^WTX+sBP5qD1Gl%h4UM$C+0_fE;9lp~tt>U`Gc4eyHR6N%*txS}?%CYvB z8XY7(k{;;3TAl4F(Yc0;J4!C9eVk*2=$ojfjju=Q-om%e)w%2R@>5Cd^B4gYE93VN z1ds9!(lTeR*bNlZ`wvXsj%5}l9oqu?jF~U7x}*qO;cs}SRs(X){*Phr^2G5YY-g)z z*RJ#V+pa}1?1Y*1os=@&%^`eKhp-hc1c?kI*L(ew)mHQkLPO+KnhxyD<5y~EkjXbe!&_Nk6IOkH{Qf$J5DoN8-jNLyr8&(MR|iFdTJL3TP;9X@sHfTILxn-< zoF&flL4T0}L-JWZV57XBZQ2}~V$!fbkn@i(#yL$KT@#f`W;&?IgYWw%lf?BKP?lP0 zFSY4ogQbwJmRRS!)93XI1$KT6Q;BrS=G4UtUwr_v`SR}OjKAg+BO#j_W|5UfD5Q>p zPnP6|h`(p&HeBvc?m3o@+!Di9np-a`-O6^~JwBmd>F(PIx_caFv48S*a#@57|A>SB zsxIJ0q}^%NTC?P$3gjVW7M^zdETOhs;7xc?7&X$8QIdf7$6mU$uKSq)F44$PE3Tp>R_0w>x$`Cg5e&)c>+3g#*Q<{Djm%I z`P!CcqmRdyMfwes&&)UdaV_LjxC8$LSqwU(KIFnmtCbFNoYZ=xhe`G_bfjbNA`Q(2qdVJR> zWax2o5nUmQ>aM-1+pZn||M{+c#=&r+Vl$?jN9GI+HxdlfYwO6~DM|l;3yOy-N+TVh zob$euoc0D;W@bDXgJzU&5Zk>V@OnXCi1`rKhx$cwdV%eHk&PE*q9FS?3lVp+;6(HRW}}s<`GPRk$2p5IHnCYp zT(|MZ*-({alZ0Rz39SjD+Irk{L19#dvuhH}?rP2s_hOi|t#ijTHv)Yil*rUEn%{v2#YQ;i7n>r@dchlWVLa zAmF6d@dVtZ>;z$0P!V#IJpTAdKhiAlBCpKCX5b!~$Lg18gFKHgH9s|uV1I%bB(VMw zumc^$0@hjWvn6*19`1=%P}&YF14>*hgF@TJw zBKFNeCDB@)Xq7x{0Y#G>Oi{jd3Y)mlrVJY2-&)Ei=gV+o9dl_s4C$5^3h43(2bq&4 zDj8!-=b`PW&*glMyQBm`ux^8x4zaXfry<|xw4Ueco+INJjMnnB;y7Rd>Bj{Wd4QcB zm4Kr+|9VC7wf1#(36ocHpm@xIk^v6p1~@zS-3EK64Hi@?w{~Y1`_gJuAc{jeD=HR^ z`0V0q9q~$ZShe!wR@he_LyK4bB2Er1gvs@{R`JPL<;t%rc5mGZbrZcqR(?2J`ODeT zit@@|!sn-VU-@C3+w#hlzqB}xij}`CDiOhPP4Tt%wXC%AYdKIn4#3H;yksxLgo&~? z*rk;#e`T>RTlrbh!e14YiUxdj@wEtXixzqorBIJ>Iqe*8Y>l}rKyB1Z9XXA;REpc4TZE5h7U zv15G&(Hh&@rao$_?a$O!o7x0!-UGo95F|j9fdmpB1K}kRe1w;zyo?BvDrzjKQPD<4 z3qIiY{jRn4S?BC??@d7ZtN;Ja2kzW+_FjAMwbx#Iz4qD*2`M(A?6AhLDj!w(ipAg` z5aXS+CGw(h(h)9F%91KCTI@AimtLTC>BStH-)5DLpw*2|Zh<#m?w`V+3;L(h=gmJ` zkD)dd4NPHuf{}W2`r%WrTEzN|lr%pMlrm(U2H$;Z-D1hUoiF|sFDBLYp}n_%UkF+n zyZ#-bU;$pm*Tj9xF<@fj0?IJ6N=Kn(W{w+#J$WkTe)5S2q4WEqTl@6))~{t#AM35{ zE3)gpwS8)8l0HSB<3%L$e7DdJYR8>?qwQDQ$3(;5aA+Up z&=8P}IoQvh|D4bNxgg^Fn2-Mn#rN4*+mDjXej95z+CjKn7rfO@1d2Mm6s0Nuh;kHR z_RGo*k6Jfvwbu4S!@xjBviM0<0ujC0*FTM3Lx0P@-kpCf6htCdtbaHb+J4E7epp7N zBiL6)G&>#16D;r#I+A=#zsk2%+m{PHKa~HDibQ>VBL6z->xX*N=~zn2_)uXwo?_oV zh|ce)Xa_}cT1LZk=$Pl>J&>I5d}B#YZ$RfMy5(kSaa1Ilhb8&f+SUg^NkZ47a_U1U z{R4%5ui$Y07X98=`aNpjvlYhs@SMHLcX(yKImLFq$XLFJLVIs57ycsZ?Z zQfQCM>0%D-y%<=uoYwLAdkT0sn~(nn#rL$F&SSy9Znm60l^=7H<#bL|BAUjv(d&pr z&&$7#Nc7$Da=L&WeYcD#yPQVS<+Pp!{-W7(8qc?c35Jm&znm_NibQ=~pMM?o^v!HOxNa%0GYI~%*PjOU7IO)PC2G@1io-) zZ8pB(BOB*aWYU>aSWMR&Fkf-#7WbkNY)xfuAqyfoa0>@@0tTf!%1He|@;anj=^$C; zyZX6&SGDL{==W0l$E}3*7Qm9u&eKlLh5K8#-7oU>oAG*zSRc0X=bM0KNI40Nf}N`p&ODkP#Av7H-%)nu+3v&5 zg+8#EWasbnxTe|}cb|W=sxIF5TfE*ERr322VmEp8>Toa$E{o&40DvLW%daXpH~j%U9uL7gltLS=hG>!Bd1x z0q_%+VXl)72xkERj@ih|AM+&>o^;jvQUHAbP?PIUzRA~2dNQ@2rzLyQdC0C(^M`!J zgeFq{&UP{Q}sj0Lwvf=uBl|Q49C7_{)3i-{be;G2tunova=yApCHE$}g6< z&i4y-4wX9lW+oPjQ;tA(73v%!b+Y6exAUVyotaXnuT49T7V5lokL~=lP-prc$FsXo zr(f!5Dl{eTcsxHZ)X}rw+2t7H?Xf}~9_vnnbEa}lOu?aI@N}hl9yECYiXb%({BX%} zV{#){dF8+qqqU_~l)wpW0KpQnko>7e!i)KG8eVo`frK@%4}z!msZADQBX}k$v7nt_ zlE`okz*GE|yU7Dbr`t6~z>|f+NahmbTg{QySeiz^8Ap)3CEO`fE)pYcNuiEpEvae7 zx#sOGE7XykCAqWJaXTvtb$HYv&*9=aV_xSH<^GbdB*zuwI;VOa!vO=+MQUh?gVlvP zdSFIjD-P6;<;-A>*SSLbrpFI5br`c4E$uVC)@54D4saRq$9_XD39uf*V^udAh3}JZk2M;n!^!hUzzxt#9P{*J4Zg0kaNhLjf zP?gzN8W1W#p8XO7x%IdS=()w&k_}PttsJ}V6LO$6Yg%OPS<*-=m|2MxP>ytAGA++? z;4~hOnK<>2c|{9s<(XDiyd-Y|SiG!$^tlu^HeQafjAm=9Kr3@K@QM)>ZJUG?lH{}NY!xc$TSIDLYq5Dy!W^fkm=s(ZJU3)-MLRCuX1m23TdwpjSIs9| zPS1GGh~>}<<8YuBYc|S>geSG0@BTBEoR@TH?3OQ(o4ghCqA_C($?2%dkdX-!JmHvm zQU)^f zjy`xF&z)Y>4(IXws0@e;1BV7JoJeA9?ZhA7*D~=#{5=nMct&jhUWaW_L@IOg7I*v731H#FCVZY6pQOU_{- zsRC2fA9&#NkQ)$2&s;+z6y(Wc_Rg< zG*Q!qKLqZJX%;Sn%_U{R!f=csjN&=iLtsB>EaoexICQ=62N&AmLS-I4uO9=l1$#sf z*~ignwpM#h<47+GMRlP%t)A&cwGr}Ap#dbEVoS_|B>5@5A$je%abV{-uocY{br~xR ziQdBS2j!eBH!d*fV@fk&RpchXWb@D?ZIpq>a31@JzxS>Ns!eH$(K7!V{n>7!!`iojrEZ{gSCf+Y8gT+zl2cI`J0z?#{A_+ zP%~RehwU12A_yv_9gd1)^)@>MlU>jg%SL3`)!0V@5w_?PbFJ6BUPI(X3B~d(3bm~! z_eO_dlPd@1n}LvpUxW-h=_NnQS|VQ%t*$S669rzlr2<~qI-d}DTTiKENfR(9Etu5i zh)FR&n57M}iBw+gs9V}d>*zA3MiQ2>NWt}PARHQr5<=khw0deTAWhNw0u(WHdxC$~KpnA=lok;=&b)<4YL-<9xz zDv3{3Z{K206R0)&K%=2P!;MJxA?`uEbDb)T=rBxc&ks}EzhY?CD|saNsH0wWw0?Lj zIG^So*ls}@*F~i91{AHksybLuRnrQ#7?DWcBYM=AF^C`la$+zwZb>kBknwk7hDVi& z3~pqUHl`0HL{$a(Ow(WLMU)r(v#(CY_x0!$ibAojOxs_45 zD#WD>n6c4iG(h?-&2=| z%OulpVqqqp4sk+dB>?rqbryU%o)86WE(`tA7`pTa_&(+|#~e6;>5JeonO%%S|VF?e1w3EaL0rQsRLG{L8@##83Z)tN-+N2MUt`RGEf znYN3{AM#I~pfvSQ&dK=S8+_)`5LzNXxdw`2$1*^YlB zKk6o1!bABI3dgp-{%ZZ(gszE>V6I>z(b7tIM(E5mmlz%x|vk|C0I$>hE#1x zxh2`!V3FT%f7($bpAGHskY8U?s|E3uw=%sktblT>2v$`E>ES4^q6;dZWrE0Q zDtR3!kJ05ki4KW^6iGRi;u?Mm)iNy!<+Q5GWlY9D!e1hn@fV~tiLJu!PNHM1IV2|C zx0nG8;V5D^r-1ibmW9Y%%Ui71__)k`&VuF%kVVE{gLE}wQ24V(d!>ZM4^SvUw+{gH z*PxqX$nImAVaSbN=5ly-%wQ=bGGYaMgU&~h5Rc}v%!yQMty5`uJ_H-`Hp+$>rUX8~ zjvx`A3xg8MB8Mwg5iO%7C~@p$k)z7f;3`n5h&_ zM*)PhOdCYnbUbDJ3N{*%T3HHlE8O4nxVSiin}K8Fr&b_+r5H&0O#9j+G9ZMrE)Yz< zua`zJ)4uARJaJzs_YG$H%2Ee6>+6*<+%8Pdh>5ODEkXBAMpo1L8x8$uMiaPttpB5R z-ZlVdPM7Sqxe2@`-;k8V0R#t46w^%DFW^*$A~@J91zcW2x*-ovdH|lERXhlgLLVJK zdZJ^*zDLDe22rS53^Tkj4;V!Xg4Ip=A_D9nET#z-73mMkBvKgok9rfodo=Xp&{M|4 zXitajJDf%7vEO}lxy1?|rfNZ~+?wweO2mg&ZZ4FF#mZX>CE}3s+wvu}!=eD{@YAi7 z!w;uPnhc*z2l9aN9)9&Hw*uoLQ0g}1RuecxjENMvkzyX-^cj7M=YzJ?Zqaf@6r^cX z$_#W{DG@}Oi?~}vj4lx|08)x;z>V4^RC0(7=y%(IA;6jB(AQfR@mQQk?W*4ERZVi( z$Ev~{Dtu6eNK2SVYLtVjSW6Ul`0xQTWXM1fsYn(Hia}jMY<)t2JzOU7WZj>iEGdW> zto)*Tkgd@Fqu_d^6y|_TD8J}-Gy#WeI`ZJYNpLjksb^WiVFT*S!+NL*ta7hf@s{-b z-o7BnDT5{Xh^h0~c7f!y?zf>npYmuog%4SrMG{a3FKE(McjKLzZ0a& zgD*WIP`|M3`|6YcxRQzC9Oll=Hzx(HksfJ;H{mfjp}4qTgr{8F+D4C5#oDF_nQ!AW zP1>Nn9&9zDvvDiwDriqUvgv45T)?O;gVTn=1qiRu_QmjMdwXaonr zM(>zQo_KAIHMHqH z@PHjbI=iBk1v9 zB;q?u8z~s$QqO0E1PVgvC=H0YZgd%>vg zQyFiqgTAvYA$b}|hETcGVk3R3$&7Iy*4TXXbqEu}Js-v#4X{WC z-P9v(Y19QnCkc2maiHo=3TY(M_c-Cj1rE>pP6%n#jrPo>J;H|-R(W%9@AIJrrb&FN zs(W*&=jHm54R+_iq)$Gsi@YDpD>5$SaTu4)Dx<8jiWq=|h%1RDEW+I2Fh8%jqO3EK z?4;I;>J|n!T$E}sDSPH4n;d+>y8G?UXRO_Th0H9;2U-n7+VqA~GLZCsAPI^--~dK` zwqPK4M+}6w4W@bXfvSjAENP?_j8!~OS;e4}Fx(0mWo@6E54BV2YWieX35HBI`?-f;@@BK5X;*t{{ zjdM|Gi3*B|@rE2e;R%8Q(e5s8eis$M^H`18DW3~4@K2SA2RHRFidLBq0+<-V1jC91G3k*E1TslPEuBG#X2PkATCKkyE+KsM=4G7C7(7Hg zLx&!Qs}2r_YY3mAS@^v2h$D`~=crd9#7V9_knpBskIi0rfIAP~n7#Gj#1nb#!8>{J z0q;HdOI&*J*Sz-NJ@0+*d*AndTz7!`4shWCZacs|2d(Mv{)qnm2}Q%95Yo;Z{%_tQ zb!*O1KJ@Qpkl06bozIVW=+Z_C(Rk=b01>GcMcR_E2NLK%YVEmvHFx2FcyH#Aol*Rn zZ!eQZg^wtMeOMpKj*1%aU){z|Adw0Ch~pP5^!NBRkvtB*m25fXv5?QQVQG8AK8Xxl z!XNc_^Z4$ng>KSv@gXvm4lo}*Q%tkP2hp33sH0SzHzw=Zoy( zJTQ~-3m=3WASVt6s>y97dHZ?3{Q%k8#e5r1eqseva(uru`qYAjNjFZWBu^;BEv)l? z*14kz#OwL?eXStAhkb5_6f)F!@tXDf*BV4nq3BDJ%TcWAetO0iR`B-IsRRp75qK^I*3f-asX z3aEOU^zY<_wdzulu*GcrHsa;u$#Fn51m6@A|LO#_;d`JfMWiGhKLItm0w%?xKbw8( zGE{a2qT9fsy)~e+ONp*45Zy(5i`)@PbX_UYb=AMYX?&AFG+cHCs*?nkZwk1KL7q>L zZ)^z?5tkSV$*zkVw>0wx?RmgvSD>{jqCfWy1g|GW^F41s@2Wq{XRqUKSZxSwI<)x~1MNr={7aS+?{+}&Px%D?ZI)76 z?Fa}yhvTgW1a~NcI|72w=G&2gjgAz-9d${#daOV+1a|}kpTSCuT9joSgIvwGh+fn= zD}Y20BSxa@8VHtV;PPhA1A-C0fl)UGx;b?CU7(kA_ahuc^wiS`ewg6#!KH7UC3z+h zhLiw@YLZ1*v^Vl`)fAVr9$ng)2!`8;x4)*pN@T=)(ij_y)2-r8)ff@LsB(#EjBI=a z@{sC=wMaKqA3&@dE_0}+8^XIRgZ5xkY%AaW6Nk?&umG!E4|7uCArg9xX1FHLoP z1$rsN#nY}`HSb=R=Yqi6gdb_R3d4z(L-Z;MyIP?i` z-jskt1&0A2q_5l5B;kEtFaaLZw1WpYlr95+VqI<81d9 z$1R=bm8_-dQYoBvZ#t$=dnIeBzfh?#rVG82wWPT%+P1XbD_Ki8Mv5_ID;37H(JNU? z45!S|aB-e4^Geo|*zdB|5^%@JK60g3vX;a)m#b8mr_El;S`r;SSE(?j>%5Y+BzC)8 zr9w+LcqMB|^!Hq)!kBLIO4bq-uRUS!3tq`uQd?Ta=7sGl!rskZ$y$O_4#77NUAmB$ zWMy*fSgjM%AAVF;E<|ubQnF0vNOP(7EnH(oiToD+ruq$6H*@{Sdupeh%F-Yzia^eN z$Nr>QGO{K$S@L&!7Yo*;C#o&A?aD~_2hD9?C~j2S`00WtoTj`M_Msh-@MczLn6OX6Q|!2j4&Jc(!@j}b%as+U&x%PCTGH?kCOjtM-aML9i?GR(uzQ1|5o1?_>{Ag199qg1Y)+D(UjYcxW3W_y}9 zlCdo^+=cc^#SbB4&uL~t+KVD;g1DLO9v{6UIak>5zH{zxeg)B6`p6sD>*&HkOw`}06L&X%#bMI znUJ=U##KMn)vHoe*ivBP4M)dPyZf?6+M^rwo&*H0r{YN({XPRth+6|$V&}q?jaGT$ zgZz_SLH+?WuFq?DE=J9b3FJW>u8}dVI2z}xXrO` z{9!~UBbgA%!1#RZ-#8iyLnHfz1Y)l(&$U_*@L2~P<(VL5zd%Gyv6PB2MqVjC&h&nK zS@E$y@PTLxyDx%~Yav>ziP0O#U-dxNjrY8Wi=OT9&5cKX&4D6>4VDZHH1GI6*DDxe zkZcTN&3poq~_v=fY;_60GjawS0q7hYnElBV7m0T+0CcPIi#S>Rr3 z$3%p>&>Ig)CXI8lL)||b>V*!;h6*bzYJGP1i@p6s9gWTu))#6CD@)e>C|gUjMR~1@ z3$?_!X`{<71Fy5u>)0*`%WYX%#@EO)n%ic>UeWp+tm0Lr@F}Ms@kGe3qTE9qnz)6T zCmQL`gfD_eqgybJoe|@Z8&U15Lc?&L#A|+a zlS1qr+J3lj_1Y)B@C(JaMO?|mVlPVMhy#yZnFB?V1NGxJc)J3J-UG4?p7qPISO)wG zbI34RuvjNhB5PVi+2?y-Y>k)`cCau57kE*df&HLcW5p6|SithP%!)Z)r;(lMPR}qS zBz^;9OKw|^q%BMoKxYY4Y0#Tfu}z=9Mf8hD$Pi~ap8j-3xY4_9Y)}uVOcO6I*hsX; zIF>{mENnBEIlNnys|ZhOzOA=iwG$4>R;_TAwso#5)KQ+Ye0$9&I_ZyQ`D(9a{7ZRC zR!VO4M3t`hN+u;cQ~65AUN99fj~7AC;747Tn%b!gACWoQ38ariJVFH0aPT7*E)D`+ zh-6CC4IL9T41tys2;$&mETdBi{p1mU3`S~Gu82x4316;BT* zi);mx%TxRrVj-cR1j=27kMq0s;Lket3cmN<+gShLdp#~+y zRI*A@s)0ojT$1NN#6UPLN2gGHIN6+0TmO!?Q@k%JoeGyyw%XTU6~T}pqXo)4-Rs&o zCJE(b?21NUVcMDz{Fx4AjT1cBevW3%H-`Qg>Ed+*!y(Pm_b*;s(sExb(mmJP$&s$= zY9Ksx5*vP?$R4cbrsoU{h0TSfb>2vU3{NFr+f%YTkl_nbB9yD%MaQO!&7*M`d<((n z(PlKLVO-=pvanHIqv*NZ7-!Ve3Rx=~DLg|Ko1RsAp4^tm?Gy@_sb5qaEG*}k((^DU zd>5GGpfXHNYsNqwDiEm$04R{8b*Q0dHZK`=#H7#mP8iMd>?WmuF*5LADqzT|RM01tu}ZIGCn=k||7sq| z?EF1-?aIhA`v)5PhY~)jrFU}6Bzt4l5Pp~qk*6>D;i(3kYkHrh{X_*JR)kbAt2fzUDFsF9&Q_3w#aNh&mRgH}9_N4_LCS%LCTqX( z%h>3+x{;#fGaAx{6N(V~ValM;5OPKF3yD_r#>Zm!mE8GS@WZLR2v)c z);D_VChxN*lT8GPYN%DmC%me0)EQDWIJKyiiI+mSh+MSm}pg>%mX+;$X z0ts%klo0+1jnzm9Ax2{!{*I)S>m8IWGaQ{H7GZZRx2GXr1?@?xy|LmZ?|_jK@=9QW zINO=!5T641f>*OGm_|P(JtIUCq^|0IsPyKIWirQLs2eZimSa%pE#wkvr8}g$y==j$ z_wgw;=+2yuEU5!Td#-gNU0gE}Yy`b8h+x~i!$#6bFoA+d{uXUJcX~ z4Tep9M6l%4`xUQlB*@TaOqTi+2I0wHuX}#1p_1rY1>A`5;O;SK{0hcQRrk89dR4_bqSs3>73*8K0|A zNjGyTmdJn+FHx`|e%Arm5T|e(Pfe&L{w;Dgz5e*@yA*zLh{j!DBaFkLwJ$3=6ttA@ zdkcH5mG3IlQLX%%Wm&EKplGgttL5kHzZY6mW#oV29|V@g z<&wxNRP*tn+bMh~zQD&o=~zC9U4{sQe9oHESx#n}3}acHRfe&A&Ws#9m>&~iBzh33 zC0>>$mk44EX19g#{a7T$AfZ9IzEhn0`q#OjUI`~iFmlGW#+8kiNI`wlGVjM&eO4%JM*GZZOJM7l3|S=*MTD;_Dj z5crU{mBhRKEne9;YJX;iA*v`D*RmVM9bV@?4Mc%tBP}U!^eyF1FZqy`d@<)HwesEN z?;p_j$j~K_Mk9pW?IpjZCB>zgLb}J_e_h|p+3@uJz5f1d`kv>slKa{^iN4~MY!lG% z57oWZf>AKde$6YHX_it^2Wbo8Z6e4cip_*337Qm{2S=;0q=rOp%A#n8gEO`Rw~db&1rZZ-Ea}8S6(RJGu+7(`H<~a&x-Idmtt6OZHmE`mXoFsGLW#WKBA8QRI3_ zBvd@?6;0FMR|uI^WBF>Amo-90eg--mVBYI2Am%4t+7JVAg*X@~6#cIzMWHPTW;#uv zl88il3#uYe;W6}{PP#Y61KcA~)DnV;O;Q)dFutH`QS-{$JAl}nT=kf@ex}M*v;{#3 z*G&y!DDrb&q1%spMH?aQgIReB?pXku$0?wvR(lH8(j#c2VTT<=Z<<@%e(Md`;up~< zr!B{JrY8$^#9fj6^p31rdtkJD8;jG;(^irTMrZR9iz&~NEeE2`5heM+IwNT&f|RvI#F72o@G%zY$-Yy`+&=v1wx!T%{Xr?8{n|YlxFI zaNZ$p19UB^u}Ep4J2s0)lB0!cKNN2?Ks$_@u#c_G;1dy;q~zKPLY5h`*>y~5fUm~N z{oPUoc~4naZX%v635CI3S@j-MnvQ#rYEx>HaYz9R5O)dl`lUH?l#0IS z)JDkD`1r*%mE|KVGdS#7r2!7H+1U7WL@y|w-rp--g{OGRM%;!bHy6kgx_Ws|LoP5j zQ)EDsw39XTN4}P zF7f&|yDl0Ga$#-Eb<>QD6eEKD%SW`)p_rgTM^Un2BCEq`yoXoXwZAt3izfZ#@ypub`WmlP*cL9>_gUN) zT4~kTE@qeTDVN~}w_|kBgF~Pq~jaD`~kPao0+Cv(w^UW^z zW(~%nUYz?%1#5gTIeiEH*H71L5GpAcpll zb~~~iY>5+zoUW@LTM@}<4UgIdF=;J-RP4<-e*|Hlb)+u|oD6bLC=)Ee3LZv`Uf{Ge zwk=gq)ySre`N$QI_8TMO?}lF6}QuFp>XSNrAZWkT>IPmb9$jaYKqVFCv9}twtVhP1A#`(Za|kJMI%fb zIv#BCo61cz^k=J#srWF;bP1N&En3BK=14549VS9?R~zonS%;`LVN(k6Ji;~)kq_z?O zQLuk1@_Agql(Mj1 zX;2n{4J6E8vmr=TaPcqx+*}ry5Sb3}0z{-a{w5hkQ4E1?8|)^wJB1sY$!H*OU}R3a zH+uKX=%hw&w#Rm@d-;B)6N>2|ayNHyVtTD3JP6BBd%oFPsZAC+jouJOj7^ruYs8?$ zIBTRi<}2*Ny%e!o%`RAFvQ0)|bl^>wN!3#z{o-eJEa_f4mLOulW$0T;BUHVh8!sG~ z5>dyUK1`d1PGHK!(b{D6v}6LMz+ryCsq$EDnDP)Bno7tl-bZFpm*-{k!JpBE4SG-U z7_By5eU9z-vi4qcIYSLpfbav~-ke9nv-h02+~CU&2#uIE16aMahSK zqURtiR{$V|nLG^un3jTCL>2&_N#ti1fQH7=^qU7j?ng&c766~|z)!9Ryi7|6mj^(m zNW)4N0H1MT%F zbv@2PvHJHv0)i!RBv*t4moRn?@tAba1m}#L0||#fD49Ywx#CNauvS!G{wuxnk#U{iOLknlTuq=`eN655t6jR|89Qnv1B(@M1L3064!U1z?8cw52q9kikXECCNTcc_};wu;_#NY+hkhHQTXP4k;G-zkSnjM8{ofIFkU#Oc0T zr;r6VUNJthzcrl0$#eQky*rsbu#-fA2n;2roNREFS1|jtMx}`tggmb*NiVqa^QXp| z5W1f4_^&=}kv-3nX|poY>K}N<8%y|5hgCI}H!DgUHyDTIvy%(0BqR+gEk3fFnkTo` z-_L-wm-1>}gr8x6roe8l6gAkfh@Bjc;`PndRD<0T6X=pgTE!-URUq1NLg!5Xv;G4T!dl{ToDEvzUs%Yj+5!$Rkv?FA5;=}hV8 z`7cl&?uuBS^E-G0+lj%Jm%lto`5SB9D^#bi3R;bsPH$IY!+%$izSy`R7ffX)}qh`Q6ksL%Pr z!!6b1bEbMaB0lAaP?z*eF;&8UV0%;wVSvaCC6IYa8xoBoiFKmR$>~2BlzDUyTm^p^ zCz%cyh}(ktgEzc4!mvhBs!K#E8e@3`U0xA?c$HddnYx}Xmx+XkluE*wS&8ZEjY$el z!7s^4F?}*OG;{_V18FC=177S1Fy8q>!I+WjY>rrGn9ZulN!OStrF@m`D_>9+6>R7F zOSyA4Ug)b#-xRn!@L8GgPOVk)4ClIp4rRIMykxu^HTu%#QG$QZ!7><5ANs^9Ag(3U zY5-r!$&Rh`Z)%t&dv3;@En)9;%Zc5UXyt}bhrv&rebA!)JL+>DEBpb((E`Bqu+uHZ4TfFMoI;qs>!N8lDU6T8M)^Gg)yyO+~x5K*8 zVVV7wqKqxO+9VoE!qStA66jy$+t~w?qRskC4$1ZiNIH{nK5d$=)rBw%bk!!w8Wk;+ z%EBbOeor1yQ|PHpVqh$99Ha8x1B(a$rp?$;tFMI#aRjd&x z=!cLo^`Khepb{fjC!e8tJUPAXanfxL)X*p5O!AraS)|X5x^icsmitn_`1=0`M)Ou; z$p8PJL(uvG0_p4{E(1O1q-UKZqE4de^iJ#4kD&4Ynb3a-TH-2@%R_nh5loS<(1{J@+sw0%d5(#l|NBlT|PbcZ%uhk`Hb?J z&{<9lVS(oJRX33T;nSR4h|8s7dU_R-xa4ow3k?_^1giQFvT%&I~&9C|0bDL0fi zqNb!ByF}W+c>xFwHD*@WSRei^5^qkAhq$@`4OLs9V@%d4tsTv;Ozq9 z&7ve`l@68jegT|xt$r@4`P1GUG;)l8!9t3|a+MY~T1^Zhd-ggh$sKYN1PltX<05EC z4@FC(kh>PoCXz-)cEX^gtdWN#d(NS$Pt-RcXIV*GYYhiE68f2h4eAW1*`6 zks?P|ccErIC8G()hk5+ZCq9y$H)W%fo*QBDO0Q*J^7B}W?dwSiZ{R8~`jEQG&y@xq zxi;&DS1H45ZT4E$z}nEjCe_Wn?A2b@S~y2qxTLM4{~E7lEqp4pAiOqiZ?`5rpPf82h+r~nC)@xY{XNDFEQtS<0)>=42TG-mQ zg)LsoT38cWFuB?1;d5TrS~y)=c;d%dEX5f@ZuDB#!s^gM?AE=>i&_JpkOtZ#>GNL8 z8aOR9FdmcA7rd;suu58JkEAbpEo7 zG{`=ema#qP-Xqt4E#Yqzlc0=Z5bqt{+&bkNsGwlQs#)SL@FYEYixn^}QnDA_#fJ@j z$ek)|Mkp^SZco;B!Hj2>u2p-@y{vLl`kZ$lTnk>N%|#PRcjVG8o>QHejWX+ z(lrWR?nM7Lf^Q0OyF~m%UcYE=ao#KUUcFx$lG-2wTf|IwI^X8re`! zcY*sI?w52_ACqAypz-n|9Ko5)a^~mfTtG;dBcl4Y*E~-#@Zlykt-*8LA+1C`9Lj$I@Qp<(j#8USkB+EQkb>~Mc?z% z-%y4ykEJ*NN0zH;;HEe6eXnFqd?45FANYG?YJZzqPN@)`SxyZ75~3alZFoaJbU=oH z_px_peYaije&m&`cke|d(nl;q{n$&|uJIm%Z!bbU>Xi)q-x&CU1oaayYVhY0etQAx zr(Vh6|Fyv{Y^(p}MGZa@jhB;cZMUS|UdiCU8Iox@6jxkRM=D=%%N{7#l`Ps;!8m8^+BLnX(?@|5}MYN_{=pR*-*7*XFU6!?K7O zb0{{UZ)9i3+Ahsgypm!2Pf;ne8#v-m^`a(ky@BxWx-3hEYP$AHtGtrIA2s;%B4nTD zC5>4Agy0`~I14_OsXyVB4E*Z_{85#|BJiudq^->33I6kKSLW$n$-uu3m3(w-{JqiQ zALD&0keHK>T-EEG;dN}95_aU4&t)l5RZ_2XrdP6#)KRG!2mPd%v~i9Q{BLsOR7Zq^ zKg%l__~Q(GfrFmyMGgM3DC(d-(#6^k!*&AA!}`eRW3Y+z(+T(K0u@-B|wRB#-pM%xz1ZKX_Cj2 zgRn?pE|nsYp42h{-bO8fr;;Zj*!8+Eytu#0a0k@mA|J&UW@iiLmg3_`N=>O(I% zTxo7NegluUk^AiasVId7x(hXZzQ-L!M(#%fT5?xgtILI6$>{M2b^%RoQ7tePFh`>~ zzo<|XN21HguRodPBC#g9zEEkFH8&E0-{2*U`iBVq{yHF6!xOh(P3(bm$b8?`ri6roL*=7Py7t2N9<+Q7-0ZbWY2tc4OTa6QX ziyFGSJ1|xcPH-lEv-f38V+t5kntbxh*-cyj_DZ*UCEK)_zgxDqo#;P1w!^;DIG9*4 zxjh3z?F9!ipeOj%xx?D7=^L#!!5#DvG$7(K@qk}D!x+Ul6B#wOc~duOQ@ohbHaG0U zp#k&dkFssi<{0sKK8~_@}j1J?`^L1|M-F0)JcF|F3ybgD>Lc z?gz8|k8LjZdnJQE+2C)D;XmL-4gMq)byR%a-ZW9oN-LM2jNMSc?G&YN*4Oh0kVfy<*oLegf6yo2SF`xhR zP8#!}k(JxdYoGqCVQOqM=$(WDE&s@|tH~#kvwLE_29l0B>5$;hfl}cpdUO;Jq^R-QIUJv(}BLXENk0p(?f}v9 zwrQFM*Ufe6Tj4Sg}h_Le%WECPA~OdMg?<%aAi!DH1emFp$s);N%S!Ud;}~ z^%YIyN~>2*YD=q?k*D(yIF|EWWqg=sJiVus$;NQNE1a{=#7DKBgLTmyP%5oYOT*4< zg*iwo*c`CJA=Mg58fEK;0oe%k4H&L9vDu9^QW$Epqo^tvhJB9NylNrYs7&g))*;BS41q_;k+^jhpW|Xhtvnbe}U4Vjo8-%ji zu1n!zNQ46?rQ|xxd%-)Kc%(y5`WWObD%tujdaeUDYs>*EEJEDF#HOLcOjag|Gvs7@ zm-L#?Eu#~CG{=CGd5)8v}}&YIBToUu$@nALTCutA@%9KJ zkHh71c$qtIHd~0*tkWHQ?&#ZW9z-@BYe@P9qK0Qs0^4vN4zQYK68=;H-2SrD)L$U0 zqy`r|z+%xS&yim9kc6xa>T<})&jiD{l>A7Q$Q5jd!lt%t_(E^k&?Kv5N7Ho6Tw~K9 zl@PFv5o(^{Mz~^O6>f0&mZVtpg#2w+#M3le%22dJ@`5x3;bI43=gg@$Frq@Z3(ges z*NC{W^n43r#&J4a?~JDh3!6hmrV9t)7)Mv-y)Cli%tWQk5x8JZZekB`4tlwF&BjN& zG&e@Zjt*kBi$e{Iv)NFuaCkOUmD?xo8fMA zJp_xRY@CS}i*G};_@*M4XOvM1ES%yoPeP7=`%w+2sDwX3@ifunKin6HRKAqOIA_hk@Od#ldci?_ zoV1|IUJ=bNT^jY>p7%FSnYW~o*02d?4Q9Sm(XRu%-5K4oHl-Q)qH`TmQAcylv#1>i zHF(L&KnpJ#lWh`F&Kk!rYayww6x!FELg`^J9?cBKfZfeECT!31YGo4AT>Zkt>xL9> z++#itONRC`p&dPT#0@2wEjcL7;za!tdHnJ7c_R8!oyH+fw4~6brQ}Cn3$hv+do1Ct z@^){gx*aQ&6#(7V&E&NCJ)gf{I zbav>B59(gZ$sdA^!cIkU14X7Gk+9~9VVL_qs%R{NqBxE>JKMWsc44|l0$M|ZeLM`p zbBxUWkGCX*r1XsDzf#Edd9HWCXd50Ba9rH-6lu2SH!G>KQ;`2a+n6HahYJ793^L40 zo<&CB-lj??7dm`H2Gw53t5HAJdpYZ|s>h%uEJvxqKZrD*NR|ANfP!bdQ#8L;FDbx+ za?Axv>m&6>i3UYV{{guU{t&>E+YA(5U$S5+vg9z40hX*ROzfQpQHH8uOD~)KLl$mG z`z1NRf`5eTHJCr``MC_Z#DBz`pYY}j-m9>AeYI27{| zPzy*t+t!zUrB^aDHIrF#3g(!QN^b~$jz;V7szOCNM7%ef{k<8jnJ>fNU+wSBXe~aC zudWD-AMGYE=z$!((luVm6i(5~*}pxY__|C@-A3uI2NKSpH49@S2ykQQgxNV3Gt3QYMm?Fxipj zJCf716gBaw)%xW#ps6^cv$cDDu-1;$V!l+zY?i-sb0o69AEoz@zca03yCkbHbO5{B zG}#F24>5lAeX^_qUy;|ggUj){c*k7Ph~d7^;ZnR6QEv^*Hqo{`T|oh|J8pKy4_ z^4=@(z~ur5<4(?OAn$=#cCrdzBmGs$7&;eaIV!;pYuJ8c!94;YDT}BCzJct=fmaK7 z=1#!Cv2fEQm|J4^>KWd@e^=JeHnS;0X-}b6MNT|Y3pyNb<`89$rzldq3!@ek4=&Qx(A2v6UlniB33L`d21SuH`A4LzA-DdMRhVTjbLYxf$ax1Y2w3fROXN z+cy1->n5U-L&dEHphs0+m{e9QOpwSgKF7SSMfEkLo~;#F3wVySv-h@FE8Q6YVg`Sa0MQ;R=KH)6WnIMd)`pvXOv$1l95!*=&4)UyYN( zW&X-0E-MSwmO@mRJ9zcWpZP^HsD6Y}!4e0gNW z%+iu{kMSIm5sSQZBH2dO2t|%DJ$JkO&LoxEA-a>j-N_$eo7u%5A?jl{e*}F?QX%LM zY@W@0W!iA6U9;8Hy22LIH*7I|!xqyYY%%@87VSri79Gjob|i1qNH~cp_X0Z$1&)?! z6KOMX*@dkMP!?7FP<9h2+#y^?{~plgs*#KM2zB@Mg;U4L^$a6M3w zjQxVUypn+rLDv@ao5~?-@9@$5uuxNCurIqOJDOOR_)(z}&5v9yu_p9mFKJqYgkW!I zdxrl}uVkY+6yUwjKk@gbTF?%de06C%UHhkA$y5uP1&!_QfmC;A>MFBQ17O~ukt0ka zRuHC1xN!fVH7xbH*`fT*Asek8%%R-;n=JZcMfB%h$?zjaN3^u3+5SbL<_tD>_oLb7 z;=^^16)H_P#Ho?OC+3%4(q>yCvfH0W_?1_((a_`wRtztI3dg!HN9*Ljy_&Vfuomyj z?~hBhj3fv}bsY#i>?i;Ay>+{WF@##a`0D z(`1)y-jHQ@N}rC*C0@zE(_F{i?`a7vE!3nTFKN&4mK7>V05qD58QyX)X=KST<)l5s zTj7;#G?I!gwY9AD_eQI<_U(b;jd>-bRgF5>8(KXzQ&(w~hP9M1O+s$Z@R*po$naJ< zWTREFytQX|r+FpAPhj19n(a>%YKkT9tG~-Kyx1(ex=<-t;=sFMI*v_cr+ayubFs&@ zXM1bBl8q_Y<6_hF8D7%B=Phw(`unDqxKH}~tR=2Jr#s6l6)bVrcfb<2cbCq?y0u>k zAG){cK4t!HxiqOo@WOSGRf*Q-)X^>Um+X8}FI5xgL9*qPG)b-Q#s!bcl12)2oyuzf zO1IGS;M5N{2|#_J4-d(vlkwG$Ar4Wmpy-h32T&+g7~FOM6K1djSW-u=W0tF>0#bi92)LZAP9_sTM7z`fJyzEqvL?@woxL_%Ara}t>h#nX=_+7(J zNRV6T#$gYkPe9X1HpriJZ~%5B8X=~mC}j=1e;lQy6hsIK zhv6k442{KWadSThzb*4E?&TBpoY8W;fuYN8OzX#QM8DdmS?l7xFQBkee+7u*cZYoU zKn+HkdLeIu(44lN3fkRVTI5wJ$#E-} zO6U`UrgA}p$YhUB_aKH!5zC8JP_fnlC+`&0?UfjvgU~(Z%`fx7GxOcRrfg;wC?v!^ ztu4?+M)8H?&#(fg<_W6ns_zL_c5mF#K2iJ?qUqIb0M zb;{fV&QhUvyCE@k9^uLcfhfJeqDAd&0E^6C2Cc#VNVLY3y`+(jr43rgoju$7GdMe2 zq4n3#1g*CG?zd)fzb!-3%>r|Tq(9A&;-||ewl%|j zBV5E7aKAmmeTrJceTvzD`xLVQ_bFxrRi~H@xHrsBBmwtZW87~G4|dyRY!43}w+B0X zc2aU^Ha)=_&!rI?YnL=qoV1x9vG51RwJS3{jV5+{nVyL*Oi$~Bc*@vY{~s*>1!Vb6 z?&svWvDQ1m-O&uoag0IpcVkwhIkAr4CPQ}Pk)3TCj-u3-HBy+SQ#}t+=8t?s zIMOh^E^=!z9B8%5B7&!rn4%&$l+Z)K8)+fYDMOIKKzWA98Xkv@MK)v(Tk27EL;Ofm zliLXSh-aHvs=p%FQBf-6Z?((FZj#o=+K&@ zOVOK-SkPON`pwG&x}ldhJIS#EAHpYn2p6mSM+7D>aJCn?L<`8#Cogc07cdAS3VDHZ z3k6(XynqLq0ynFUv|bo{ev{D?ai}=GSPwDW;RZ3>e=ZlG1M@B9sqN7!5_7VzqClq9 z>3Ba1Da6Q>kHk(ak3^H2jz<=^8Eyux;Sp6hR0J_6wf?FoSkI@1CeVxw=>O3vReMNG z(Wf-ho*G5#!N)+++B5NNzZgw&(N|0hkynxql3~-L>8b9>qf7_()_HVE?5w&XY~h+n z7gmH%?&;nW^U<<$s%(jJhF+PEmIR3PovsKmp75cqaGF4fR0(Y{=_#<0u*ZZoDN7~1 z4BJb1DZ7h_F)esbSQKPiJm{Fwf6nninNL&?I;LvIxn5wCE(%%Cj+XPifGrBzkuptu z+6&mSiq_o)Uceyek;6b1P9omwMPA1=8Ci-kW!02fq@&s3)i$WoD0$uEIo#7P|Tb3 zy@6qh0TqE$qz91#Fpzm*Z9qSF@CN>GVf0|96Ui|_|Kwr`*r0?E{sw2N#rKpgZKU10 zOxHGBq6(LENF*QhF*!LVv&?2{LJNrRLOHd#h<#+dOru@}T}_=bsYJ~Q??|fJKVQHr zylpdcF+y4g&z1(2>HwaE1gnpT?m~##^jz-`%`&w3EZ`&C7+|8IDFl|Gl(M_=2=HM(BeVn*h*!nJ5UqF`>Oc-jF8da;*oPlmE+fIG8 zKwr()S9Tq9X6Uq3sYQ-EBsmc+a`fL$!7WU^3=iWA@*{WwXwsq-jpMA8ufa87ES3GA z$B=|)BR?Zm2eoP;%N2iExW!l#JpxD$#yOISnxULVPIo*Rw^jy|tz+vu#qAkh$IN2R z;V0m_)Au=|N+(Z(C|h3I_-D$}w;827`dXzOzD+^}^@p6mQKWBGydT zTO<+fj|OlcL?xm@OYzHxyrLL%jB{W3=BnfF5!Me!9C%p7&ywFgCF@|6wMR9qLjHW) zLD7O+?H#oRN9`rBGsHaVh0COBF*LhHWyn^zNL|{edXv4RX@?zAXL$QY$gm5`m`z=w z{uHSzXL}u!%p$Sr94}y!S){I<>jj#tE9ZLwlgxarT+My)nQQlA(j6+{!}S7pDbgQN zSE0{T?kg$Yi|`hxtob!*pIqDigN-)PjXcH$gt3AP<(8sC7pZkkj!J%0hFHx=~{^Fi^=5 zq>Jjv(J@)u`>IO}Z6CKVX^bpQ7g;T$*>-GYT_Z)mu@!FC&Q{n1z{3zl6dXX$MN8l+ z9t7T1XtZmNQUyzE#Nh`QdRsU3hzUbCM`aItqbad7D)TnE!8aQ9Z8~gUsuz3nrdY_b z%kiTp%*2y!I+uE-^{Q6LQp{BeE%}oDQYV(|GdofQk@k6_ z*Dy;N3<^P}<-){Fw^);pL~By>n)J~^Mg>GHWN`0^0qyV;CLmhSb<9o9{HlFCF(N!1 zjz~l>L#9f~a22Z9tA5WuD*%}jlA8Fc>y*^E0@NNIC>O$MY7ldq8+^#{J;EuCFcaKF zE&fL`dP=JBPs%#(?@n;(WHNgpk6F-e6{083z4rTe^S|fUy7-uK4hg#}nS2stD!8~8 zqS64qW%+SO6~?|d{o1R}?^U4+ucRY8LplkG-e&~=Q@Hw;UFOb0VpQDIv5u4@awwij z5E>_2*ZD$(tEbcTTGt|Y%PSiXvQ3f`P>xgO?bR%)F82K?AmH{IcxB|-`UjGSsV3Fs zjpFK}K z|4*W{&3ouyj`G#y7CCQCi`C(weuX+0pB$!7AT@E1IccG8O@t<=h6ECKhC>C?4+Rp* z;$;C+2O*IH4hc^dnfjOM+g&BuA{pevj04r=j*`S?^y0xxkW>{GKAL+GyjxA~(sv}v zm*O20t@0g$QL4#3`i@I%I^MxrC-0!!RFnI?UO(P3T@Ds~2LNYCcWnhFQcVtJxHh>6rA3nOKlNy!6x^%O-0M!P^-=fv=*2rA9? zKHQdABApe@8*Ji#7E$rQNq)NTrept1VeGAJrZ#ql@z5<|W9LsXnEru{9TbUO3h_yk zS7cK9P-4?S6&NEZU+sZ1E-7Fqj!PA8Op7u%&X)r`w->_=e~PIU;*O~iufQXy5y{DH zxz?zO(fM#Zqzog5yV^;xEy@0%dxXlu6m7A2JX4ZM)E;Nn~-gxvGr~dd$fp@6$#JF*J--DQ(a!e$7U#+x_BlE-kO9 zj9n#s$`S}Ckv9)h${9h7GnDo6op^o&#Q<4FKx);&B0J7UrI%%o04)xT4-3G@EN1)zF8G(()XZbAe z|8L6EO9-#|BXokRVk5ui%J!W8L@eWAh8#)8RJ-KRaaxFhWz)oUcC>)P%8=n@$?zO& z*2qvwzlx&=ws}<)sd0^cm$DVl_x^rf@y%+26`@K60q2?wLTyc{c}^Hb7TP+8mO0`q zB5DTOY&KwIkEvqc#@IKaDYj-^;1Iu{{o@5w2(IP-Mv>}LB&t!f5=qbKoaz8nDFGhA z`%(ootW1X{dTxbk_7PZF@S)ZZ!QZn4=-N1k#|CfRxE7B-vzyq)nYu%NAfd;?WGZsy zM@;XM7S)mYLvnavcVlV?-5M8y@MIG^VZu^*EY+kYm_lU8RgS=PYC~N5?1QdX^Xnt{ zzgnM#*EB#-w0NCjwvoqdJa;P9;T$HYLgp#AK7$lENNw88HbL^c!UuP!&J0_Y)hWk2 zv7{t>1eFl8NHpm(4@kZavM_soD7Y)^PFvMp{!May8YD1Q3_>ynH#=Ri8>+rBTijy7 zA3#_Sd-525gp;O%u#8NL-$uQ<#1#X+jyL=0Zq?E8$n`|>TZ1WVvu3Q@P)8E4f~3fH z)XnMJq`5uOtTJr#d|aVRp)**tX_y8$Ve0w=B2td(IK0+z zXuN!;Uj7Ons2OI5!o1#zC>PO?*3;^Y2Yg8({@f)o1bYsRr zvRW16mjuhimcl^peb5#-ezNK0g}_h5j+yrbNhQHX(m93TgAgBKu{?pD4!nper2?5H z@7PU_l_zwEsPzgkSgy!G>bH>a8BtfYxYS$uK;r3C_`<!q&K@+ItX<+~!27;|{TKzr(g^Nrgbi8*r=h3FcG@gz(!~`xdR%xQ7LS7Sl-#r8^ zPUb`uxS)Sd)qSILhXX~$GK21pdI>CzZi7OQnSSTg?RrrCOdM{Z`y!|}jvv<2PXgxqR zl=A%GyeFSa1x4Z8TZrdC8e0YF#!9#GhjKfSCxu^;@FfOfLbt%C#Gj9Y(2dh+ZHM>P zVot>UmoiWa%-SKZ^9`@l()-8VGU6`}6{@-a@9VtdC71`QBbB}W2c7h}rBdt)p(6ws zGF=iU)CxgujdLl`LFF;y0%J|;k9$xX1Msj(4%;~w{*?V*r-1W@N6`S6G*YN*H6~3h z#@zd{uc)9zgOdc$>q#knP7^7OZuFT$s7t#}Tp6Cqq_yxfSc2TI&P!YIA~wt*-q3?V|qDGqvRkLViea|bb@ zFyRvfw4PYnh5*iohOh|gsRgKNa(1X$aC%}fE9ZGglfi!3PC2>J;Wj zRtSYN$9@oEBcO2Un9i)#-)T?B@Ewo>45re}s2a5ysX<#fTAD*HBm7DHvt$(V*Z^|z zh4#5ou&BM-vyk%%N0$jXDIc;)2og=653vu}h;5#2){(6byLKv!bY}KJ?tOGh(+J;* zJ{sap7-5hUP05ik62waxmDG@NIgdHRdvC%Bp^zShI>FHeQ9_*)yeCOk7}pWq_Z>v9 zEYYwu>}S-B4RSf0&9=5#Vv&W~Z63r6VRA<@JQwLjJ?H`m^>tE)t%Rg4dWBK|!u-iBQ$RSP4#d@;}X5PL+fzI7KC= zSA#(Zk*eUggO**TY+Mq)>a&cHAr2)k6tPpiZp+RVxIMskTIix&KU^)M2@^eR-PP%o({2WTMAPRQlnwAr;FIdp>=JRUg2AnH$r zn3SJ+dXKrMLib_-w^(hk-Bl6il$q|UBV;Hy0iu)I~a$Fc@RUTv;{cPN5IoWi>qgjKckW{9dH#ic0QIZLu;RdX?xXXYr13TkP z#*+Hy9Fj@uE^^;>IJTzAf3VJ`z1{wvjdIvRmz7KMX{JfQr{(EuuyL9*>(E2t&T?-S zomm-I*617l^o?(N^IP6J`-Hch`1W`F**oXF>(Bq}D;+m_QED)aF!$9CaqeGL4wVX>|#ZEw$Pq|AEb5v z&7R@Tsr1>$?!2@A6Otzo%VlZUxd>Se!xK3n|u#IRp}#ig>62 z0ZDNG1LEuN1)F%fV4+MPyl-lYmm=R|kq-$j-L>-qa~J-^W3ThHHXJGY1T`jgw z7DNNtP^dXKH;{|{y=DCS>)iWG{JmxT`zyRpWvQKDTVm+hL6SupejaF|5__-yW-mdz zLl88`r%0?ql9}0!{X>^}i*{)OuK`FGv$IUBK3NEXe~KjnEy)tPo9#0vzi<+yaA&(i zl!f-XBbOIC@~)^OWKxj+Y>kbpoDHIbO%~ypxM~=PI1c@ogMN6wH_3Lu=kH|ytoBZN zP{NO0=^Ad71-%px-ywz9lyN*$i!M+#5|tWgS~McrC+N<3JDX%Nvl3M{)(6F}fd@4H zaQ9@ox9oDf+6Qc#?b~I*o2C3T4H2MCi9D?vwi1fW*m{h|Axj+xOgZvIK|Cg&{2xdX z2YHs&2G!QpSzjU7c{l8iw6{q&z)bCYKOLVZ^h!&!@d^?|Gr`gjyIl~=UW^;@p}#va z2o5+hu1$I+=TyXrR)9gE!#U1*gLl$6=UdT}1Td5f2{ zjo@_zzy6{uc-3IM(yd;}!2hvpd&JzmW;Nr?qYT@u(ogA*c+p#Mst&e4IfjRW7x6l4!- zfGdU#4jURoHt+CP9g0!tQ5@ygoTvh_&e7d{UdblmNK|SjWPQy`+9Vv2L-PIp-b58f z+B9Q2vFz}G*R(z`n8ye9b$@TuJCu9>pue~2eFfgb8kFu^W|7%x+gC+WF+I$!n{h3) zzs-lqkl*vD@ZcMpez*M5U=jfY6v}S@T~;{^Rgmmp1qvW=k@G<%rBe#XJs}eELW#eD z;gikN2ZUWK1f(@HKs@AQFf~I>!Xk7$E&1P^C*l;Avp#|fnfB)9w{LsXMzI<`qU=EH z=sxOGva?V}P0tuC$V=;yRBO>PYTe>a-~W<2pYr)M1E* z*c4P1!*!wZQ!+!;I*utFEI+$w4zG0{Q+lcV#3@PA<1wWf_{k_D+wMe~6nfiC;uoED zE{R8;LEY=YGvHxdkf;T#Oo$p3aVL-6-cw^mwCE;J{wm9GUl7go&%Bbc0eXd-v7(=Q zNn=HHVkhTamfg)_^81BXGVrto*UGqUh*5NF4C@>T-X-;FTIk1r$3tD501e9 z%1at}`je9lZTI5;_DTkRUjzTr2>jz-(!kTFoLqie7CEq$ zdGA+0oJG#ms83IMB?B)O9;}Q#iqnn7sa?^k!t|Zl+7|nJ+uFo}ok|8v{Jm{$9Yn|P z&d;*UI4|!~uT;p(`%neO?4CUsvtj0)QYw`)CSJ0Eo=A;b+&C?mS=Z?@AtfAD>9dm@ zsyz09#cYN+ZO5MYb2|h12oQg7gRc%TWNLV1$Oi+CI?X{s4>e~}!&-x+B|2EW1p4pP z(+2K2aWD+d>4epi$`*EMeD{D=@w-p&*GhpV(c%>sH6%oR=1(nearrf90Bil|YF9I$)fPOzZ^_gL~0u@>$Upih(wP+Yn4 zj+oT-F|CO*T)cF^&a8_Yi$WGlP{@)T@ZmOrE_kIitea0bBQQGS91tgkHr&o$F;q)- zfDXwnm=!c)%g(tzYP0OXXc2}G3_LBzpfmX$u9Nn0R+vSk2*W2kg*~L#7L#{YGda$GZA^>Mz4@y@xT_VbQUD&_Sac7zqBbwXSSzoAwPzBV{t)+Q87Z>WJ!O1~oDqL5;(d$?$9Y!m3 zQ*MCvPWu3OC9Xe7sgE46dteeU*awFuze|Wa;y2}oN^LTUo_1k!L;4we7s2T%lfi%s zazs9#jN}@fa@bDU#om*za>unbFpfXm1FpiW7b6k?vP($()y0o+Bf0&13O`K#}LK{FNxfJ+k!vCHFOO`EhNw&U#~ z4B)8Bu5!AdxXFmzWz9Gpqa3I72IiIAr|JjyNrBcNg3BOv)FDs!Sy)SHW*fS z{dY7F(J-u`k;%z+EGrX;T;JZriy*Lfuu(d-DDoVy9VtXAtZJmAGEPO4vMK3vROS}l ze71H`{+>$nuSbWCOE3SMweu!1SjWJOSU(0Tu zJ99>uX!ktRJ8Qe=9}8~aj^V-*w~<7QtEpoGxnaQP6=|~Zpt()u^u`&%xq6%V6k~z{ z0p83rpHfoNN*#tF(NI0B)L^DdB9siYE;E=svfM(toPn+NULG>Ngae;6UJDO`z(vAf zFqs_JeVVhX*otKGPkU=NfyXLoJq^5G=r9bgGd@H~D*0bYGo&f2qGWMRyqQlShA+Rm|gS zJ}>i1rs&dc-idt{_n_CPWp-(54XBRv5Q3)X;|rt=jZ{!HH%rkpi(zOvist2H*>PO$ zO&aEDFV_g_l%$Qk86E+6>7^00H{$nv6F2FT#80(`tBR|D>^=4jLdKG?2eM1oDks<> zmefdaz4z%ZJxD{#d>U~ptBk2b*gy0sjb_Jk(&YOg`HWnn{z`HKACN4v-N2pfaXh^` ziv?ztPPDak8(9cWw1N*eOQvz7ch1Ot2-k}P`CuYopA0G7Q$CGa$MRZ8Lc#PCo^^s5 zB*?7!|G=4(?iCBswWBJ$28@Yrr%>*a!FR)uUrm!sRB-@vY@nKGsM4=E4Cd{E{KR|3 z!28vJi*MXp*8{1l24a{(+>lH0SSmZOO>>6$H+d`z^CT7u3nn#2KCPA65mP3w$ zGB7?_etQ;vY>d6nE7^Fa8~oid{I7XYgFis{_qV;-`+l!v@FC&~zP3jAN`s7yR}~KT zKj5HtD%%%rGo6~R`+H;iFF{j|p9lTDv3;DO6{-V`D{|DP@WLR!SG5XeqH&5-O#3>e1QaBLLd(a5KJIJ2!=@`B8Exh9C4_Kpi$9^ii&eol>UC# zT6?c^_c`~yM5(IZAAR$I`|de=Tzjpx*Rp%%hLU-~W@pH_X$c0q3g-P5l|&!fZi<5%Gy&26_?9fcB0ySs0t7Vyz(scY0oS zTI}$9-l1WY9#{w@VHX zkoOURMeCo!oBLz$&?Gj^rH9FFEAk$|yA60h^?G*t7RG8_36v9AJvXy-tG(VLNCqA7qAP1!Iu8R~#+i^n^h6OysZ$XBcC{5IgZM;IJL%M&~`&bz>TUpmwBDiihp3L6%URj z^(%EVtv(2tPMr>`d~34G^w?FBFa4bzD0F!%wo*Z%*qoGD`?(Lyuj4v9rmu-fXXq!? zh2W(!;x3w+Sl4)$zbml{eTD_uGbOPG#Hd=jwLYrS(rxOQlKCp3VhPEDxq`SB!4s}` zUc(*98Zu}jtRaCPI4~(eY~^JpyQ~!(u_dH?Sl4Y>#Tqi%hDxO)*s2<`mO&$qt4Yrd z_g5ygtZO7Y=v{mdk_(hhTCu%r+oReb+g?y$;OaYuZA&@0a_d?8MM{ht^(8)T!vl5t zV|5OdX&)LMs0@>D`iiCC&?`YKrAMcH%k1Kis!X~yjQiXT+bCFwq}h=ntt-{>?d0BG zVCYmg5CS`A5<9tzgu4JbGMBp&#H3LpWXr`Cj3XLmwJu=AIl!&wi5ZgbjSG|5@KY^^ z>Yi55z1hBkEkw5D7%w}_TJvh>Cb`R&wc@yTRVR<(X{Ava9|j|-vgAkS!N6c6AUF9y z4KoKdnB}FxC;~%Tw(Mo(nCiRJFYbWc zNNlT0OL(I>LW=mxR2(sD4daRJPO=VZiwVZFfRK|fBs)&@oz*_lhjfJ)x)fzBQFj^z zqhv_@CTqY!+Kz1(Wi!j1_E42<_;;SD3fI42P(l!{BPU0)U`bZoVfWpc5C|2 za2svMxrO!N zG!=Rk7aK{a!u1SzIrMmpd#fhD%X4WjOz;<1qlX%XzXTUzwLzq_0>=mtGL8`#2mzLG zjKEBQNNgq0ESN?Kmdm_n;~46i72pt<3ZGpShsOm#8+cjLR2fRZSuL^)TR%2`+5N-4 zNW5|-u-WFEvb%CufQ-2-h0{(1cO^CC5-?*G1177`ah4QZ)~YVJjmMkK%qD-IqZlQB zFIE%CCc67(#kijrhP|H#jz86%ss;8yY86v8Fz|d~7g7=Wnlg`e^*-Shm-zV1Hljgi z`-r$v#W1>Q^AWP^)9QbUBohUL8%#CwOiVZ&6n;U)cVR#-l;d~^3uG?&6Rqi z=mWIp-)0kvCRrnnbKAMedG=E_F=@yi2!+TD?EyDd=-MT3(gq)s*@PIfdgwMGiUT6c zg#1x}s4n|Ng#(-bw1IJAsSb9v52|$I-v_Br13GgUqhsBS8ubRKTZ;n@|Tv z{!l`H5~@2XFN-yd{8&SI*-=EgMYiXQZpuhfg9o=d^Kv7tW0gY6!z(A@(l2j=f;g1q zQYwP6RyqgRHPY3Z$6;JLYd2oMW z7kwqk*3=V;aYTgU00WBbIzgoD!Uq9GA<*&Y7vm!dyE+s2Clef@FU}$(Nw?vK6`m}f zODzm`E*h+Y?z>cib4bT>1ZiGv6i#9Y@_aJL@}^JLjFHg}5%rk8#UI?)LL%0xfV+C$ z%9a}QFzt$_8$@IZJ&X9qlRMnZB##Hadz+`A$kB2UlZ-vJ!LDw_`5VR~yA|fRK$H~O zD;FRE828aUTZ+3oZ2);Twp{M22tIg(9}-%^)tGu)PCMa2ba)N(FE%9Mo&+Pp84;sX z$Nq~g$7aM3N~Xl(0VW(0FHhN`L3uJ=5+>ohPm(yz;UvLpdu@ac^-fD3H*yjH*#70}>xIE&txSzZiHh*S@$<+;Yu=qPJ!_vBQq zv4mQQvcnBeZC7p+x!Q+o8y>S+_2IrsIwC@dDkS*6^-6ykZSt#)`fVKDQYv$i22#bi4veM((u_q5p1sNB~`0`Dzn_} zBQ2VCB1fnK%Fa?9H|;#~JEVR+E673c2Z=orcAxS`0yuGdD?Tx%e1Mm@YL-MgP&2k1bv6mEPxOK(cs#m5MiR>6k1pNWP6;4i>> zq-!wNiv4Iz44u5PTrno*Otc5mL3|tqbU6&DfQOW1 zvvIFrvt$jMr3myOB>1rqEyO^jy%{j`Onh}{?#im>*z=|=zyNpoC4BGds!ABca8mBt zigFCo$`3pwsk_A_+2H7hIadZ>QevM&xT&4N0d=FdwKEe)(QCxIsefskmwZHxM0%_- zlvK(h$PzYii&y-VR-B2jGVLT~89Th}Jvtmc+!%a-KJYud;ULpC<}@|%=(v!--Hw-8WYGM>>jn#`oSs4buy3EXpS!NGHXsg@`-`E|>Swe+S?uk~Q5 zmh-gt{kA-pDegq$k%wkttWV$jSrH%Qf8EsF+#RmhwHOS5#ygv_!w_- zEEv1 z%g7`+yw=&0^-WptIeF`0+@=iz^%c3&22jW$D^aiTYlUVov$3;Ls|N(llQu9nwdd8O zp!DBEULo^0zU|Is=ymf4dPo~6{Zor#;0IwE?3imTA zYSjrWMS)4B`|UQbd$QD}ajb)zVp6H<7H_Cc68qx5BHtR4p*UJ>_gbZ6)Ym@;YVTBT zw!oo&*KcsRC0Pv&&MeA$d$*qX(}RD|jP%5|Q2)Wu@0tZp%>xfewm#PmBXOh18g5JU>To*vayM@}4QG65Rmnd^CNr8O|oJY_m94*YF@^pgNj{m8B#D-B@aOE&&;3Al8HZCCWhI8lQUJ&&A~e zGSf>v*8}@Bitr?BVa0Cs9&E*4tSiPaUtieUyx3QjcOIq1UKAEKy)Eo^uVElL5+K3B zfv$GxK7r)jRn=@^Y4rzFhv3aMC@gIBgjFr<2famISPd@5Zea`iEiSBO08f(!eAp}7 zEMBM!+b9UPjn2X?7YHIvX<;8KwL7P@urS`VFD!$4gIP@tm=zApgDL_)ECr{*I<=ZW zFvBId8j&c$Xh?vg#2%l5!d2BthwJAFR~ljpc=S21WOyWpaLW|+MK5T8pLIwS^%Zsw zA*2NPFP9oVybbbF5rMc7^ca6xL)=$tMUqKK(R}0NTlo`SSGRJCA-1k&Bdc83XJgTx z^uBe`)VJu1_7veJVR63FKk!PnXtW{$Dk-)6$P3z{^&Jwm$O%lGIxa2R&r1#Wwk?`e zg#I=8qCH(|Me}EHeWzNq)uZT3t6mqbJGkXB|Qt9f+<)to;M?{{mFx-u)=6dEq z9YK@Fp-H6JuZaX3Mh81JUDaH|^0b+GOi;8XiqJWnE_TirQ8uu;KKc42mj=(Z97X~mA?8bfh6 z7mf^q3S;PudRZrh5iO;IxXK6d6_tC`?l2rf?_~g^V&FI$fKht@$CONGqqp>^wxotz z8GoK=f96t+{(((iS-B6Bu!(R=(=AVRACJDVl|nMo2FHq;s1bwX-HqO!YNE5a(7Fe) z{;&>yq{iqUnHQBb>hL_fP zZ>f%&`hIXjF=N|vlcl@eYnk#ZroME5sk(osSF?G!t?we*`le2fHT9MN_J3jxpTPdz z+9%m2aLIbO(n)Tkz$$lO`uh^5&$EZ|bVOMITGEOYjOpuPMH<8d58&TpXPYsF?1bkM z<@9mMJFvXe9Q?6*P`L}lD>z98Pd_PLta?)@m>Nb_>QT;Ifa7(&ZTnES@OE-z@UjAr z=6Psr1A(zy4lXLkWNpwtnO|5EZGr355&cwPpKENeMXs%Lr6?UogpI_wHgnq06^kd8 z1~Y2Xyad!{)g%{(-7n$V>pFBRTpL}9l0Jm0X7L*q77MPeFnB)Rh%_Dt7zZoH&2~l| z_$3*2;FmOC>bB~f+ z0EhF*8Q}Hao-#lf`iSq93@^Z5_zpiFo*V z)vI3hYJSeZ=QX_0M?TGFGk@Ld&N}<`zlV!`IqGG{ee2zMSAIyN_Zz7(; zsICs+`}ydN`Y4SqUe=238i#(PDq{N+yigi$(@hO^M%MS{mHzF}Nwse(S2LVM9X~!HUr^2}r0%sUjR^sIm@Cc#EnK zGlNjk?Dq{S#F7=LtnY60$_C=I6vPK<9qK~Uud7gZZz#3JjTL zH`>twxCZczB=W%wyi0%cK{suKvOs6X1xn3#?$h;X1({_j+ZU1#;_1!Gp8Zl7vpJSn9`1 z?Veg%>X)WVeRA89eBGO{l{;CN1P&L>WFb}sag~WxMHw5q`qf-F~6*41L|3) z)sKP!0_e?A6~naDt0e||!Eo{E@$Ueu9ERm!|kpTsaW)t06z0-SPlXBE;bvDGAVSg^tLU=>3IW9sX_w_NmJJT z^sav6ohg-0cmpj43uBM&R;if8oEd`Dij3#O-j1P_ zI84In&3UyKsr#<_yvr1UXAgMeZF=D3foBhuYPm6L9nURHp5MDZda(bXv7K3iIZ6%~ z#RyyGY|uzr3D3}z3$tLI@=&xF;LdUNPykmzZdIO%{fVX|3ATb~g3+fCE`g6B+;uUo`%At&8 zqT{=s|9!}N0A-H*)GP4@%$Pg~096j5Zs2K2An;Y*k&-$MD4D~+((*8c-*x<660~tOD6yePOcNs$)r(MH+T~|nbfDvxg;*_ zEndgi)@%)paO;-y=Detjb|;{`*;}gMngNu;H97wjaJPDO1DyM$3nS28b^d8yt{vWl zjzC@0E+Wjw{KY!&Z2L~HWAoSGI2qzpvg-T2vdXIc3OhM&Sm}Of9>UXn%Z8#w?Kug; ze8@X51+~3*;92B})w~m&@@#NQJ=rB$ZD_`V=T=>}uw3Eu9A>ar7cN595+5!C)FeEu zGsAo`VVEbOXgrS(`9?VpBtP$4T=0bPTFh)>oGehdUo)$ku1%MRvfv}GQ+~!n9)?Ue6cs7xSR%b zk(MQ%%W-*)*D+k4tN5r|hRq;ES#jLL&>EOBs1Xc}Ps}2F5VIWj?rfHgL!IS%Z$f9u zoRX3K8uyiJyL^@#ypGKhw-yi@65-t;_M{=VVkdjowce6#oG-!zdZyZ(Zt!ZlIWgyA zadVPAi17i~gRnd4p2Sc^dQrs6MMk92-h^}5pokO7)2lbDo4sR&mWEV0f8+5*r~r&$ zrXZh-Et8ued@2?ASLEhpUK&wY`-(nWGh8uy5w;5Ug~JQMPR9e6^v0T*j(yAdF<-vB zeG;~OGqn{kYcnuCNX?io4Fm$x!1NmYB-;-5B?>a&HAOMxo>HsRv{eZ-j>^HkrDAC$4ET{raPY%uJ9?OOuC(*L9; z9|*u*_#oYd9KVnwWEPYIzXau8IkU?n7%5jj4xi)cfjH@8_#Q^+cYwnI{sv|dSHZa1 zU(T5ERKn`dApFKWW5#%z2xCbrRx#o=<0!5>hWCu@pJHW;c%O=wE4=P&=hl!Wp1IIr z91$~?1iQfe$tM%2`!--87Z#U)8Vy+nQ#H@0POCNEw)*B^I7Lh2(5SIX$xelDIR)Ef zcCJ_GL@Qi(;2gZ$!YVhquq*X(6H|#EZ%oF=$x&ptpn&xV31>crjt3HOBX?}S91l0!S`T{?4@{nmFG%zY@dbx7tXJGLNAar2 zLeIzJbOEmRE|rC{krAe1?G_)Z68%Z&v$#bucICt{kgg`L(q;siuA6rv z15M_9WkQK+D07W%nA(ZyDh%s$rY8XV>~LJ{GaM#OeQ^I` zDyo`k2-!b+V@0E#8F+PIX_oOXd7V=5#{FH8b|yb_1zF_qny8n0%AIlu5V(V7?I(%! zKwK}x{Eq70D~@Ki0+G92L&UDC7%AH*MO%RuCpf1OwL>Js5be-x+zn;&P@QB&uz8g% z-pgBYWTqlf9xdC1S9m$wf+h4^igGXYE+#bqUF^*$C!issxK~k4lITB2lr>(*SQ{i* zmSaw}DszQKg@3)6WUgzpp8Uh|A-OR>652;AK`*D?Vf_vy>&Hc!^e(_y!N4^wFv>HLD@N8!_z4>t3AJ)dlR=Eo~Oi~d0g<>U z@RBd20`FzstO~rRVlu)wivsVdz#Pi7LEz|Aifd?b1)&pzy+$He44w( zNl|1|gOs%2W>L_bi;mqBJ}hMz^ywEF#wXeC3Ca*4o0=p|!5ro@5DiCD>})bg`ueo9 zHn}tyh{YK%3oT5~$NFxsZU*9)RE=OV$@nI3LZ?d?e{s4zpdg-l@AhV|WBd^ZBW&g) zQwhe~y|N0%bol^>6(O;xB0U_V@TJ$rPQAVyqyh@*CPAqOyrON-(N`QMfL(pkE%zhdgia>) z6>}?1T*V*rI<|I)DfrqK;}c%Yl$!x9#@(^w>;#?pR^<|h(x<$+y($s19nA)5M&C|} zvLS)Q-Kz4=1Z(9&g>Pk%{QJKuUP^O#vJ{{7(G^8Z8<=vkT2kk8UZ*5t-oPUYQ{{NA zkEZ{y`<-0FN9xwNN78m?@p4PMBUQunV;B7} zD2eX1xY75{M(?bL`)L`2uJ*156LM(_H1pt&RfO-7OnGO6Me8rxD&a#6A$kVO)Gy7Z znM+odW=JIwS~TVpPF?WtQs$D(_ERO~qW-69kDS5^I2?_=tGv4y+;5C~Q6f}_T*PEo zsaJKiH=`8JTs_52gI1=*$bFgDF$#}<&oqcHv>JI2b{6C%C3S~#W3Z~fnr+XEHJF#UZ3tUD_XIxn)BZz$k<}KZSW~W zWMR4T41CNOvlzSNnH^9POF69gF#pRH!}vymyuoQrCIo$hGyF~~ zYM|~SvzalZ2dsL!9^vd~fF~}+6n@Mjy$dNrkWJG>4+qwKeD$4CJ5_=@#Xf&tqemzN ztu}C9;o_#q_^(H`d9_n5?vVL9ar{BZPUuFw2|uDTaJD{{*)5RsU|mVPEA?R>IY78Q z#=V%EARQgK*;p1A32m)`*X?1fv&a`jdT*!Nh4zzXFBDGYoOQlpcJfxQ5I$8PhVq0g zoZa*5^8x#QjOp6jdE3gI7U-}D?#V)&wt5o^ZrTcp;HI0M4zB{Z-{W-*+~UUy zn4sWxY=CBt`)1{4cw{8%7i^&eO=*mtd#dF4Esz)6I@R(n6lFTG-h>($2LQz!5!Aw4 zB(?7eOmhnKa+J8U9okZAH~4t6##Ze;%JS=J+98TWK340W?-yqUbKDP(RKj2qlc`F7=M^ZOA&7(de z%vI95DIz<79%=^=+R#>nOug8{K6aC)hKLIXDpRxDxC5Q@r}7qW@1x$H9gvjx`bNLA zhmrvEF|T84iFmC*!h?|MrYB;|r@gdoPDf$grxy)M=W@N1i9X`h)S$%Z7hzXLgVN)K zxS9Yo3Ps$wVg$f2nsQ(8oB_$I1#gsDcb;G+gsN0SCOxGK+d$|D3SPo zN{5{;_6kuG0mY*Ke&N;ND@mUvavt|4v`=vtG%K==tM1UE2d(O+jQXhl(UV_!h5>Wp%D?I*!(K2CNOIxvq&00u-(U*nzn??oiTIn@|KgM_$G&ew3-6*_N zi|VDyLUf~0iiD%Zma$w$+DZL8Pyed?t@PTcq^8$@03q<3IMZ;1j&Bs>$L@(ZTwzZ-aE16C@ zdjL0xJxT4QHdqgT%2kjwCN-dsXySFXP0NNJzk4fec1Zr2tXp08c;w@B}+1uJSf)OiaFL)>vX07EJJ6 z^))fTVyub)qliD_CAN^O`f#5CB==rX(w~oKJWtZgfRg%3TyM}LlN-cyp7i5&2A0=l zs6S!3m-&EfQZNzsbDwE+G0{HTrX+@LWB$$hDFHuieBdcG+9U^Y$mI-sZ>Xdo^2OKXo4v3=iQ|`QRY(d zOxTQIcEXgllxn)nb;n_#_nb>eoQ1=9%jAmRFop*}TU;U;?0I}Ls>#e8r@j7*S`i!@Gj zt1Ut{%xNVa631loI%S|Sjq@6u2G&!*U}$=yCvqxUHt<_oXZ$QJ8QsuM1BV(&TEEn8C-~ z(gH6|jZutmpgEw(@R1=bVfeS$9E%Je+gRv?!3jLc5;|#T__TLne@hrXLyoz-1%}U3 zaQi0=|Bm*Kh5pOIQ7S*yOjaxL_`7_CjK^zEugQ4)`$~1hp*Jay-&v}ol5X)Lp>$uk zr&NbBEQ0K17tl>1t#fawj_z5o-FJk+eWg0OXHC}6u2P+Y-LoDj)$~1U3<~Il>f(xu zX&3hqOuK^|xiQ%XL_3>ha%BFMdyA2(MF_Ub-Lh1B-9eAoL`CyUxIMPw=&Dqqs2 z#7(QPm7w+>e(O8Z2XwzkMb%C1aRh$XfIY6lc!+;FW<;%dR_;093W zdbxGY7zj{8X74^hva%+jG~RUcLTTH+RAbK-UA_~7I|KfDFYH0{oKw=FEV z1#B=$UkpQZfG%mpg5S_M8s0$!mCnx`SA zsFBh+7X!l^($B;)Q~i~NP^Kn(1hSSKnrprNV+F5O>vg*bWpi+gPUD~O`lhzhtS6U* zhQ2B+DV1yKm7y@Q&i<`~vBt+EJOi2(hM zHp5>Zgw61n8a^}{DjfyWp;8mmV04Dkjs!|#KMZUeN^>GeEosFHCMhbO(`>tEu4>eC z1bz3+)d1KR7xBKo6GpA_c8$I`W{T};(C}(6X(K>fI80PZGrqE1LzK3tU7sNb597ya4cWaiY33TT$5%!5Dr&*eqAh()QGzC@jyEOJ0r}*%9kL| zGH=b6PPWQ_R(et0%&Pyr!}6?&B|7s<#@mB!|$M{Nv2tt0&2-l zUL=HA(KLlWl<|{5Ip>t&to4ozoGg!$dG{D%ywq)oL?yVRcnF695d?+}qnq3a_Y-f$ zm5eaXo>pIJg*y zTkMIjG+(aXgzau94ILG6gK@TW5M~>kIp5A8V$6EhV1I@OIIxb)f<1Zf3i7-0Y#Cnn zbJ4|~v^m3I&cR@M^NIcoc-=80)nF%wftPJycr?gM`+1k#wmBCy{y@2EqkCt?LePVliQy4pLB*qf8E?ma(cjtX$SO+oH z^$p}LIKL!n=B4QNjTn5NKmfZNW0l@8&_rqg#_id2N*inRNn7g%8MZ2J3Q5u@_e5;N z4ceGYUz4#(uZN{cz&U^+O=qQPTN_A~DV4hE#ET0E$HXFb%Ot0bHP~(m|~IOFia*J`J!C z5}Lna3!{Ry6Pft<<+$)@dz&fgeXP{xDB2{&!IwkVr=}J?(*%c!On8zcQ8<$=(@sP8 zB}_C6i(^mw*;DF=QGp~n-K|YagU)Rnii%pyDgjZ!e~7HWL=*|Tdc?cfuba1K77k>Q z4(an=-nh4WjqA!HwaoL#Be^4Huh+#F{JAdFgE%nJdM#}k~l*mj9v}c zg=5WfLDj4H0Ir|>T^9gD(G~WevLyvl)zuqS0~CPeM<+1Y=ff~#51j&aLH}-`e^;Q$ zE>a{IDj8n4P^2c9_-1ejbO&_(8lNEL@OSwQW4*p0O-eWs0|yK3le~;M8%-_@-rxSF zpv?%^J;;6FaO@|U#dmxbX0Ozfg_GBMvQ&$X03BOb1vkPDfm8PdZX}s+PePrpFn38s zjf)c{F)czA^#$kt6GG#J_V#V=Y!`Fa*&ff?hT|F4v;A3V+_djcRqH^h7VY+3ai!~F zrE%Ni7&MB)O6$cEzvc{ZaL*PLbNU6JfMYEsXM(HRSGuK7+S=!AVY_C#akjA5Pqns7 zE{d{&t*v;qr@)A1rCPN37ub53?R3s|y0G^_Z1gR}4a!c#e2Wb7i(Gg)r-VSiOZd&a z6O94mJk_goacKlJ_)k@9b*Yx7t}R%^EAaoaQY{JoE85;GYOO8RqLsf#FrpXu-xpxi zM;KwJBmTn;4;blvpjQ$Uj9KXo_`i-%5dL=qzoDJ#3*!HE`lPLWVgz^?+ZEb(Zkb9X zSNTwl^`dbRNSLL>d)dfdsO^SXKscjUi2A6xyp<1@dC0ZiMJK;@1q?TpYN?l?;3=u7 z_3lzF^%Kyb!A+wYqi!nIav#BGvx2p}KFWX4wfbuOWRrOcROp9!`Raa=*hK@?h?BV) z0z>B4v9HU13#mWke$ks-hi7coDl4;tN>E5}{WcMCjE9k@mXEd%Z+^ zWy|rBw$LYcf(xO3!JO3fwj(JiS{g~7bg8l_t@d^e*q~t|-2`+lQDj(?hwIod!-%A- zMZ&xp$0p%r`F>c!3~V5(bb4W*?J&2sK87dVy0bmsFUqjY5s~7$3>7hESl`fr^_>Fm za__)G(J5<_aKtqlS+gnQ4NTj~Z1b4;6kWL42BbEmRmWkY_&B7G*lw3|}pODigul6SAIC?qJeDI4s|h_ojaTA= zg%ehMuyWaz-f<5DY2jlh>Lq0`&yz|zb>48r`|Xc8rr`l)dc9R=O!#Di2{^_TvOz@# zL9?0I4SE1a#7r6OreUN@Td^@)*HggB#SAf?y%l$9h>PMRxr+q7H0o#6jse+HXe5hA zpp#%%g&%mew`{Zpl?zs~W5O{-8{Z(BIiA}Rbn23kWW6_H!#kcG+6A)hE-Z#EBX-JN zSPQ`Xn+y>>w&21_0kE;u1GBC`72ZsuH9rS_P@JLWA1tZJV~Hkz)mctD@GUrCQV# z1%)T+>+w=84IP=hudkMBVe6Z+udkPCiDsDJdq**3E4>-=n_kPTcrHh7`0dX)U?)N* zmk`DP=~6v*;;v&j5ZuGze1rPvFux9x#hzq8p#cTApv997=Ywg;Wvh(q2gSLQmb$RY z*cPP)3ov45RqBq8*rl!5!#Y)DK_F=5+=Lk|_j1OJSWd(-ns8M&JvVQFtK`qTc4-LG z75P!Q!ub>!nH#r9?$*}COJf;Fsm|ejRd!fSf7S~lgs3XEF)?PJHW%Fu`=eSzI$@1D zL%oge_!QbB>cjjZIu7>)+FrUaSh$Xm2%*VP-x;D|^0A6Y)>8wo1lPCc9BWY5E5{0O zB>wbft-0Xo0U;3x#MnkYFUv{5ji52YS=K{xfAVR(dz!ZN;%W-%hfRonN4|_^d+|G} z7|vFPP3n%Te1or^IT$IS+LWYQCO@8J8E{h<^FjNGboJgG2k1~=l#I=Axydnfz`w?u zS15$^3^a%Eg_w~p^Z<)UlaVyC{S_@eHWA;)Zt($c3E_JKnF^HOXL_anXTg~dGJQkM zK2QkpQBvhqsUk8?N76xlC^D*Boqly*Ex|(v$U}a_^O1#IJnBdCO0W(ztc&iZA{uY8 z83_%Gt%w2e(84JZ441CRSz<_o`cVuJ?W{q9qB$37LaAfY{7?5#Lw>^Jh@SxRsQips zoJP3on11c>9`jC2B0QQd8f-PBW|I&=FhekDk+${ZQ-Qiil)C4r52AqsNVFy3V7L-+ zA55P`0%o8egTeV0A>=};44jb-UkDgM=kX~r#i4#6VDaE_w-*Z5G$!|RM?S(x7{eYl zN-a<`F!BTx;)V_($}XpasDjeNz)hm|nRWQL<$+Np%@1iz^d<+@_tm%&bI1izuPBk- z;KgnEP+Y^Xu#KZX>)tfAGwV18=Hu6bbJTVSz7}9WD?7yv6dhqr@-ktsSOBoJUdh;q zgmPSK_K+k8+_!VsJ+D{+ue`$D)qOxq-GHYN-KK>?Jq5afgSd>$-ds6FKg9rl7y zSjIpRojivyRaWKbcejt{$2Ae3aW7eivESomZR~^t=&54t(lMYHItKU>NZjYG8Ka?$ z(oc5R54Q(q2TqB@DdLS4nUwsF=icCKM*%yGLVl;YSDQQtQ{Z>ps)XMaJrSj0>@E$% z1(6?S;CCSkxjxE&;9Na5d?qtc?@c5J4r0>0wy}cYsf-%P(?Be*gHX^3)6Q#o7ZOFh z{mAlev#b@H`axpCCIWEhGX$teKPx8e+iAk?WW!Ss`2PWn27!T(21iNsHJLd1xLLC? z`3~Iqu>?+H%}_(W%ry~&mb798gOlWKRK*H{kdS2FcR_ysQW7S`vwoleE!YR15mT#Z zV9=i=5QU}`NF(x2GLmzDj3PM>c1^8&uJ#d`?y0AiVTV?Rq{ap!BKES(h?AorB@2mw z4eE+;8k8D^FU=7>)n-;QEnex}8XzPWoEGmN>gJSWisbbo`12KGi-1jNUu7Pi?UpAX z(GG_ygVaNT7HuX3e2oudvq}o0E=(c#U+cBnQa)b2yQnTaKk4iGQZ1*_ON+tYikt^S zrTY@>6Dke&@~KIat7Imk)I_kP73&v>R;tOazf;*=E*i1&-dq!9noba9MUmw5VDhI` zHRY7cysvLMRaYsYLc$wphVOU`8ft7xTUG`*yvkSxL`T47bV3&b~ideNf#w}}_WlGBIBWC6bflD6$EJWf#FKsW37Fzj%vwnLb#}$8h6RsATX*rH=3~ zmo34c4q$`7-yEQZHmraIPSawc3@7eGvTftJRTXYz0v*2fva)LH_L?X zHY#$6J2={34oD`m?o%*mFQ2)D2#QN|jP-AFkBe@EBuvR0>Rh8RF=Fn_kBp$HCK zT=@~k_>BAKX@#&YkQBJ-5slOGYAe0kr!vvf$fD^^P;gv?)5S z@{tvVpDOGV>F5149v_SXgH3M^aVmZUxlC=r+;UQC0A?-J+IFlNVVUJxbRrFO zi%38tX~cr?1NIXwCX=(^W%HfrSh(ie{t)v1iH^eTH4@rmXFql$jG!TwE{sE&V17aY zj}o?qz6*#H{2N51R9(5uXKRRrWPUsuVf=g_KqPjrc+xg9Uom0?=4dK5KocrwjoNh{Vdy6IvdKpXGQXBPk$ zR`5`ypk>}kk!@8Rk`}J@(R$2N&@SbGOBE6abl^#?YdA!hsSO6Aohb|$TrdKU?^2%E zF`^Dx2D1Fv!Ym7f70G-mS#N18c5Sm1-=B8+Ol_$*&ut>uArA$P%S%1z0+&%w1;!5) zg@|@ginutS>|S|&XD+`ifvCvoQwfT(lA#qVm4%LFt%`CaVz6y&wx|&IRA=7u7;-bn zOL!CwTOu=-d6X3mZ0h*-H3+ehSOYSagXUB#eblzn$d5^NOa&2)8FW82vuYolIo~*C z?o`4!@*^f4@IiB}Riy!Ia?L8iK~d*E7(xy)X~|fECI#jLS?nmENff>g1^1EfG_-#( zJY+3VzmwzxK5|%1o zG9-ZpVOnk)aI~ToJ2m1#70NOYk0zl?&O%-q95J;_8(-=uL2~_Ze9u$>do#1*TK`9ZZ3bA3CpFpRBu} zUfEu*2rXNf?)Uj%HGE5$AH=LGL3v3lc3)(L6?P*Lr*56nY$S33!VX|hm@K?_BAK)p zjC9fv%=1l~OUZYawPKwgXgs2d0Z`TR3#Zt-4dwEoX8~d>eH;-hRET*ipA26_twcauKK9{!v^*OY+&ZB@FN4_X6&e~Z%o#Y{<-LiC6P9SJG+L0RAQmZ zht)ts#~makY~0XCRYF4)r-{U)8D?jOi3-Y58^N|>=E~~0W*>P7LK?tnRGrf$2L>m%K^_J}v{NZ(gPZT?< z4O>-A?yy>;O=}C0R?*k7-h2I^8?6L~95M>W3b%5BAsDcK+d_&hzy1e^IkTRHAf$j< z|L^<%L11bKfdAYiDGcRS1D_y&Zh$$f{d=|dpjr_dnO`6>W$z9&^7Rm1Njzxd`C;#?O|Lo8H z?BD(Qpa1#dfBzrk^A~^dAOF9<#OFW#r*r@FU;Xue`LF!^xBt%1dGh%m`20`({I9?H z+rRtY=bwN6-~S(c{^1`kc;~z1bK!-p%>P}KU6d`!mS)ScovMaL<*+h0#c6D}5wlTXlyDqyv+mzjqy*t~SZOLxT zZpyZ1+p?Rp_hh$Zw`SY3+p_m&JF?reJF+{oyRy5p_hs+Tc4i;Q?#Vuw-J5+VyD$52 zwkx|odmwu-dnkK2`$+cDY?_$J)QkJ`%U(Y{A<-OsxPT8tuL!Dudk@DtdG@K z$-j&1m*C&(`kMNs^~>tx^|keN^~>>Zef)Pt{Yv?_p+13sSJkhsUsK;$zqWo|{rdW* z`VIAW*EiR<)NiccRNq?PR=>Iap875ITkG5Fx7FWU-%-E4en~y;{aI_1X(_Ki9$wzycu^(>LEqsVBpq=sYPK^rW zF}geCAvTzilCO5TcWPT03VYftH2ZEgd%N`I8|;`@`$3PmGInsRJk}5n8A5*)27RFdu#-+5FjnN-fk%rAJwS7oy`2Q z02?`T!M#V{Z|c=|+YlKo&u=b2N53#=_gt_QfyldS7KywMzhf4F1N@=d9zmY$^y^A< zu})+_d+fde`LVaISH{T?Ug#-Hh+!kZnt$)+DsLZ}Cg+p5^KZl4A)HK?BtSRm*og|f zs3_yTQfJ`{rrR+r2uIlBH?qpS9A5})-2{1vv6HrG{hgCW`^ zwavhXRoJV@+Oi|cV-&vx>`14L@24^a z{eeuEV^^P?%SH zIg&lmq0hM5>*X172=kl}BO+(9zX+_L{BlVhW;Zy@9?=M{>)3z3;fuvfdsAoRyS>&| zwbr$)#d+^n9nO2$>}4O-vKys`Yo93ga9ARQZ}D2z!!@CYF;!H&ha0`@W7@;jEb9es z@&aGf0#~&c*y;s7rv)ZLZ|OT#99yH&;hUe8@t*&&e zAJ4g6Vd(c1GFX@f2+mzLaARRE`cx5YnhVs&Jq2_RM5Vu? z{X<9)MOql27vV20GBbb9Tec4#&h-y;u`dI@&lsH9ID8Nq7t|lI3VtucY{v^jLTf{Z zCyZ~0Pr{fuY6NCVNBOMA;m}%Uao>^#FOvovGf(e27f6VC?aNSNUhRaz+47CJ6D6Zp zHF(z;scLrq&ZQWf^Ae19W@9$Uj7RdO+W{6PhQHKCOBi6Z<{{*pHGGpM%(}ZYcodT~ zS?3oTT`g77-g$-gF5$yE2PVh|qHBSq8gQZWGEW3{yo}?uH4y%~hmrTIWPqT&-n={b zcO)s+Sk?IMEsYPwWPBq-=@oVNRhMl{Cm>{pmMcV8vL8N!rFNz<)lYC_EBIn2UW_!R zOK~~Xw_L_MulA~Z##^w0a;M<3`0Tk-P>vZam4~(guo9FauW)KtP zMGzCxJ*$=Bo&qqXm*GkRe9a#`OnVM+`%P8=;;)N8o-Y3QmHt3eQ8oy&0)&G_cnsO# z9DD&HElLgm(-^<8BD?sFjqbFtAOtQWHv=fKg)1Z#-X=B)*JTxK&&dw*8Heyk)nxHY zj1NTvA>&Wj86kB_%1R}yxc8IFK#L-D5EusovU#=Bh)~EJ*`vI$)dNSQ zi&P{yMM~L(XGSD5SM;sCc4dJ4W|E6ow ztDgZ5^}Js62md3h;W?_APO#n1%gW)}pW+Qvhymf@QuZe-D>BK|6!CvNd5=F-$lDGh ztV@m!PC=H;U+KlgVeiX?x3-OaIgl7WHU1?gVC%j*qk5q?x zMuHtd?$37B?pu}Rd$7Ol&qM;0?!IH)jiuGUU8;_vilt~`7&|wmNNMBSXanHuX-Y=8 ze?qZt%XNHu*G?hO)4O)yJD`Z3ayz5;N+icb8TO3D^jO!VK;hQop?a#OvNf~Xl z(!*Up@{!)J6#ImZv;@K*dr1RfEC~>%0g*eFL6%I9QY z)MlE|0{T<$(gfviaBx!y%0Kg3CdPi9wK)Bfp!{<$Yl8CEq=%KiEQV7e4=i+fAJ+k| zWj*W*J#13|>!~j;S}L0VqEz>*(&L?9FUpvyX#UGmt*?Y0O*r<^{mRQerh@h3Eb9fH z_5voFKh|F0*IvLx^Dl?qLLh_T(;`E!D#2XvFP;8xylE58A7#@g0LPV&@9g0gBy`TN zSIS{KV)_Jm-rh_JJZOG_yKgdXU*__H^_6>V+m2C(EZU_b;I>12flPaVxC*AW58qJ= zR1tQJn-w-u2~yJ^V5RnZoG-nGJ>4(jg~~q08fOU6N>bV{%G6XH##=~r?JQ~eMbX-1 z^oJS{sZOiUP;=54x#AbB74{|DkY>F79Dy9#)~MGocCKWq-L3Mz?o+PN)1%vVY|Y7lg1`MAmdW%mrUeqd&NHJMW;?h2LRj5=bzy7 z8Kg`3`Ee=Mn0B%>Ha(!SX| z5Zl$fnPYjF<76H@WRaWAzrvsnjTudbw3RESg8@rQ^_g27lty$IqH5tM<(hQ&P7eGb zT^tbk4&0qUf+NB222TUqh2g4s4@*6O=~2BeBK6&+9v(!g!{H|tYXH5b7vzT_J5EyX z{gw4*0ljwBA%}O<|A_;W?XJ=Wl4ZkRD#H>!PANf0NeBz@cXuleey@%Z-ye`88=T!- z&h6pDTq4SZir$ZNUU-Iw)aY@@gQ-|m@NjI;h_(ww)CM{~z&iI?%Zl~k>4zd5k&@M)`auq1QVMv`fnyXPbpm%Jhc6=fX#luy=h^!+K0evWOv4~+n(UCl@N z>#ho1{6eXvyDM=qb>9DDWj({i8S0B4O5OH2wL8Oo_dtNhIIKGb0g%H4gib-RZC1=| z7=&z;1sk(yPP>?`ZOsOnEPj(tkY;60CS*RSHZ7}GhiT7b`ZSEzZk3>5@*^(zjqDs3 zU5gb!o^0Wh)B^gH!`a9T#W>C|=q@ogLQq2Hu|^NGH~g5*Z??I~XzkcQ^+>74iDwE5 zj(Da}xjHf6jh$oto~E4WlGj2)*?(xYTVDf ztf_I=OAnv>OtFX5qw;gFWj$OMdMNoj4tUweRH?dFdic`DVh^cy{R^*UJ!}j;v{IS- zmtNL-xQ1mNjKA^%rnX((Uf^jjU~1b{EMV5kxbbrpqXp9xbgroP^lNX(7HonIkM9aDNQm5}gFCGyQ3tXvt_WR};CYdk zwJz367ZX<(Ct)}radnB;vK}svJ*2wqQZM^u#ff#&!^4x}#4@jCJ**8ql-TETFKa!F zv#i5>g%>cKxU9XvN-tnIajA^)%AYn|waMouOF8DX%%!y^1J}VyimM4OCUpW`EF-6R zltLwqr)_w2i8o_-Bo*>4n~I&MH%+YeS_Yt1(oGc}t?{z9$YV0S&reLY$d`I8>tSW+ zp@c@4d0FdW1n0_tQl< zs9xqnzuartGB1&3rZlii#G+G3C=O-0a^8YCt~C7V-gctNu2hU7!>KQ4kK#74c54O=A0; zfM^KY{rq~!7k#fj0CX+tcxNavLxwB9ML9c$_BXQqe_;FDb5;y%f}fB%3vdS<&BQBH zCtP<0izKJd-`P3at;-j3O!oJS_!fYcpN=BeI7}{80q+0EC;-1;&3F$7_xBtehu3L5 z-sH93q?w%0mnIbzf_l1FBx;PAVxsL*=d%l%GbW$$LV4{SUgsTtMA!9yONY9y+Toe? zQI5X7zo%pjm@3DBzp0Q;UoT}mkyC#H-X|-FKHX(e?v(J$Toj(%=y2zy}#Mt8^Hbx-jhhEfX!&G zCvN|hJqo}7v-}QPORBAGIw)-=DCHFvIw3<u4vYa>Axb$|Z+Ea6S3qYVALR;awBVqHT7N5( z?xgU+!8e#G>eTnt3P*DU`S5@!sJ2VdTAEd)}4s=GD1MNqL0@eZt8kZrQmmf~m^8=jmzt^1ynPxe-J>5u$ z_#r<3b9AClY?Ucf-|?%!VKBEm6$$R~k$$>1w>Fp^#zurO27Z4poBnseG(^?qKi%}= z(A%G)prpGEgJADq)qtaz888)Jg8RH5<3#_qVzAO+Lh>K>n#PTILuUTeW0Uf*U8P!o zj9NaP`~AH!0^aJmJ*Ov!us0cP(uG%{ObsJ|M7j+<;9Xp#Tj@L6hVY=jH<0`hC$?pM zSTC+#D)>F*l?)nx*w*O7{@&*G_O|yQ@%Ps0+t}$8JHki3mi78p)Z%LGPj-aybVt}- zs`?goIK__eu~Mybq{I33GZOUpxRz2>mTg@H5_!t>_!kP=4{G zXtc*G*@C{opu!FrS^Lfe&Y$%frWY+l4WG{={@&pHd&;Fsfd!xUk{eZxemz>E;0nrP z0KA3_BaljN&dhm5^l9~nG`Y1rJu9?~H;jlQWBd|}zYbgqfSX@GOD<&nI-lh%91VCX z{b}HVYh=dm3D~%(K>*y@2JJ_E@CNNBn$LGms(*gjD;cy$QHgUdIrAU$q6X&Ivi-^R z+sD0mKjH69!aKd~{Wtx+b?^$j4-%e8D9^ei7X&YHw7>w3$N~{nS}<@o zze2m~%P|JZ7$SR-uTzywDC|2va?9HCa)O4{CKxUQX>cEaZZ0im>oX-qVpoH1j?f|^ z@g8yR_75T^j(c+Gmm71NWcQ?ZYCLWp`V1V0fSXV~eMnuSe9}Q#rwGUKVw_|m!SxoD z_OgH`y>!ynIf!z=;rD&Grm~+Z!&Sj5sO&BJ2KCC$sIp(lXQyz0u!Wk+j_^AGF+V~~ z{|Cq{PL^Y+P>UJv2QSeyvKD!B5~_9~kSqMg?KAj2GyXn7n^rj%QYxh3=6BiT@r>$2 zr~CB6+h6K48OOeiejLF`*33hFH%z9jniGOY|cWGteQ# z{*1LSBuSi0&EK$!aXwZ zPRTMHrpq9YdBx{px(xFBX!$);R&Xur;T9Lbd$#ybF6DzGQ9`|yO)2m~M#^J~23vbZ z7hJ@Zb*zV+>?{Vj4k%2;-ldK@C-?!bpcEvr1M6XM+K08{>4Vu#iMQZA647zif%Y$7 z8V%h>`+B=42C!FItQZ!m*v1v5s(Que6x?P*sT%K_$nrnX$u*&{g{CCb~buDwlmN+n15}{p!2u<_=LY*>y>QllJNqr z+lp)vzxSnE*>$C=Jhr*bUFe@$cUMpB?|k;o!fj=_g|vQhfC8 zx{wRqlA#}V*vy%Bkp)i+>v7>Dk30%@oi!SAV)(e@jys;`g-<$}hlNMvxNzybFjmXX zg7%k>f^JEUf}Ta(7|Y}&DEY>Cmc+;`ZN(}k_MXK^XqLn-bdnlT#xum)fREI3y(Ega z=uxP}PT%B7O$wWIye4g5QffPwf@nJAI=CP|q8zugrbE4n4081@o__2Yy3@nZ9k{AZ zS|7sT$$nrqPG!2O5>%s&W>_Yj9-UR8*X-tP{ziBz?DtHx8c3WV}Ri1_Gd{`!?P+*oQ zhMQK--e&87IG<(CX?&zH#$Gwey7 zR_j(lR*r!6q$`^ltMV+W2#BoO=(4K3awm4TulR$voW?g&tkv2Udtg!az&uaVYPb{? zW3eZvp*|8zi&%7yoSNtchW9j&$Gk53lK5F#lztU@CPsamD+`xqGIYvnH z7lgf+;VEyXFEIZ1`s&(7M436iX;O`QhgY(VXr!&t+x@-m7N@rNdY2clUQc1KJNHd$ z2fN#AS+^&*b^AVlZ{41R_dJUYkj<;T0;}=_A$0-)^|S)&bNV2K6z>HYZXff#-nxzX zc#e5;NPWmF*^rNG8}fbr-i9oqvG1YxdjacpE_)rnvbgbzG*?*E2fUK?N>SMxebC=q zuPXMXfI5bN`n8xO_7P6J53x7@jY3XN4nc%Xa7<1TQj#t7_i^vfCcz7srU2b1ypl}< z7Zep5{iMIQN$`%MLV?eC0qb=RdmU>-?Nm_O6&w>B5tXgC!F_j)Cp3zU-rfWGAK zZ7#e{rHwP;*C>rgLOuLCom#k%6fP1A9P3-07O!cmBMMgeK4C(38f^dJ@`NH+rqeiF zc7d{pN^di>f7OOpj!LJ@je+HLVTKqR*rJS){}XjrhPvp;K=JK}@im{f0h90ZRg)sd z*S(Sfvt5GzhQBvpQi3irAN*82q1U`g%;?1<$XQkU13A3xI8?H3NwM^wyfag=G>K}# zfL*Ti?NTKdk-yLb5xM6eL}ZAqashp`t zxtk1E&4Coa#q@GCobljI7(8tDOeR6qIGQbg_Q+-^rjEXR!3qdO^J=~Mi2l)&59=S@ zxW-gob>(yPk1X%kKWfY5MLnOjVwrrf3HRjvvhOlMDiT-Yo+S2t0u<$UTL0LAS5SWB z6-wJd0JyaaC)kc`bdTvDQT9T3rPJ&x6C^P60-6ygGz!&AUhE~!(AbV!m-zcO+?ta} zkgL6%iRFrebA$}V4FsT?Ohih=JWn*)Wlnl1%y*Lp3ZF=p=fR@eD^gM+4tYm_NS6Mt>xJsgwdH|-N7o;0(mikptT{R46f zAnpmLY6JXx9{3|o_sG^~QgE-qqbsky15y`%O8V=0wSFR0L$jDO;i*uqnhsTlZ1&4k znzh5pOhFa%YSUOJ?;7LR1~FZn?Qch=C9T-oRqD{Bbb-wCkhRfAxCoS4T=-bJM#s2RLVjZB z5$PSL8L&uVM#kPnLyY>dH}wqmLJjD{fBj9aG%R&I9gbRkD#IiEK`!GH|MCJnZHSqV zIwq}kbzzLPAqGoJ(jDHRh!}Yy6wB}i*`Tj7r!q}!y>9h85|1cnbmO5IQE8iD@;-X^ zy6{r&BjhGC0?rGq5s_awZhuDYxP1Tno}|WH12QAM51t~8&+#}m&6-SuB&M|(dx7nV z!%`2M;G{uOVDIo=izx-h}ZK7R$f&aM8$@ z-U2r6m5ilOcwm3S$q3haNn^s?(|iW&{JojT0N=v<%l*AECo*vg0Azjh07LxmxMg;R zU(OEBt98Pkk-NvF!hc!4*RGL_wx@C8|yN$+ThHEbJX z4VolCpmh>1F&?H|8B=+(rkpy(zRf#S$>l)`eOM5r@dSZ)H)+}8rpWeq zPz#cbkyQ}k_(=W+Uy`BNPqL;EM2U#T_%|XN?Qb94m=DeZmvkd;*rvdC<$h5L>|AYF zgfzdvVHlt6KnjBiI8ok8a^`at92F26@RtlVrIXb@j1`Jqx(RnqDgB9ogTRRT=;Z%^ zF%UNtUG%a@L;&7a0}#IsEWh{NT>tkXW%ZQteETN;aGQdMOK*5CA;S)`%<) zKhq${C9T+m1!8drA(9w^E#@y=%cux(P7%+RdR=2>+#2)mf3B$2r$;`Pc_m|I*i>Ys zi`z%4!Pt&C%S#oh2>bgL{@yrSyUx4P-y3J6&I`wF;j{yQP37!ckF8 zjdebfHQs`yjXgqJP@uBU_NnTk*uKL9OV~p=v=(Slzu&G25M-w@4c+@&=lwmb?i?uV z*p)^kYFZca%(}$3fy$`M+G-*>O*{w2ofC=|?5^JMdT-bk7#9go8Jcv3*RmC+md|;F zTm^=UX?WH|sUkJ~sREO(D%Iki%#f2bFzIS9X@NRd9td`{IHjAtimf1bs3}5`-s6>Q0jYo)LSh+5 z(@3OSyn+cG-eS9YZ4Kg0*s!=+`A4@c>|Br_Bpa~rSnAmm#~y}m+R~1CSzFqb zK$X_$=8i4_YrbyzPw0uOiR?&U)p1041PY`ljF+}zJI1q*vw~oE9>B&XV3~%wgXciT z^hhTkTExa4-fMB5>A!qF7yU^IPvq-H)F6l!kN^VP-UAbBQ^9ADej zKGOLT+-so^dTU4Qt33(8rC!OVhgzxQZM>=wxP$nUy0%i`6upn&GpMxpvaYHD8&TTX z`s%VK(0A7$-ZPUy-3ywQtZsl>wol`5pU-b)%(kB&FM z@9E0NGj)!6(_6g439@#SwnPMgV30ra=P+B~b2!W#68u8n8ADy9Z$SKfa%cn1d8%;l z?PA`;?&dIxQVc?DNtepKySlW*&Mq;_MTqto%AJfF)UX+$`BcwPIFQb?nxbRl@d4)Z z>DCUo-yrIx3z6dd6Y>H6M2D31d8P-N(s}rT0C2886fvLsbkL!UjqMI{wehh%;Ws3U z=z$zA{0$)_e?mE&+zb;7(HIeb?8XoFj&2>^w>i99x|9?@5J`u^AU;^CNPKh$iX8yQ z`*R$|2+vf*2S|f-Wl~3wz5WFzgw8RfWy!Q|FHK902sSOQcO4)T9HIx5E{OtE?(*uk zS5n5vm*3v79R~Bv)tKO*yxS|;mfmg_c%Q$w4HWmb0}}*alkxBLvdeW@)IKY0Wd}?? zhN7>+*u$N#6gkDb7^IZNqH?|lMTmyr_>~GgFk%rf)l`ud#MbTkSQk*GzO^}QW-M%{ z`Y=54S>Nj;U8N(XSOK}Z3-^C1eJ!E^OEk^JqG{rsKXB^R7#C~-9R{W%#D?k5f<9Ou zt&d`peK9s!Hz9<*G^l?^lFxK-OFWe9pD*U1?N&|#=77>l03q~x2hWmLtZkTdG-~JH zSXIQNqmtEM>Xi(WI66XA1s-pHnU}Pb08}mW`!*ESLuDUcX}MRj=BZQq`xXA)5S4rr zA>uyI@S~qAELIG`H9AJ95yCU5CQSS_99JJE2ih6C#C%BuAx)FQ5QiJl*m92Ga8#cf z+I$<&y4c5OwigB)$|ga@%P<*QRutQ9kfUg9GW$h588(}2)4U(giGMqUF7Xjurbw^a zAQ*NKrD*lhkVL>BNTS9bM~#aZdsI~L*4KFJ7i;U!84xRy@-SV7{=mNIQ<>GyzQ(-) zLpmy9Q?ReKUdgaR+;1_kZ=Jt4tdP4~31x~ufP8|*>%Bt3L{?lTUmvUsI2yRZ3ox5t zEPEmT4#qO9Cedt?6^siu)#6R~xNPy%I;M+9^nvL4ywOM0W+I1FPv#)k};LWXT8 z5>Rw31hO@v2WlLBxYJ;A?n~SFtsu`Za|a_Jdx@mQeVo44;!InPKns3XkbAP8xfC z6d&^U23lO!S1j;hFJQxj=eE$mE`M)kSW({Mes{mWw+_UN`&5M)7PwfDcB@X&Jm`&; zytALFAF}!OlgVx_=G%gzM6Fq+L_ripPsH1cAPQrEd!zy5Mf|cX`NGn<9*c~yhJliJ z4N=%0zyvZkOm+cZIzyxpgueq(iX8;MgOP$Z0lwGGQIS|$^;KQcic=f!7qb+t#b)=D zVY>WVCA7)Cp*M9wX6vhroPne@^+oIo9FH#&yxFI+l0+KOldC3xS&$cK3Ydefg5M2< zqVane@y+}mL2LoP>8%deHZt}^gj*sFyjEr^5_vryrsOh(6~y)zEmsf{VjLpZrr(z( zI<&DYu`bsn{@{Yx4+r^DLk7&(3{z@XSR@N?b{t)%eU-Q$n|G}9)|Y$hCB*-UBYxMY zO2Yd8gIcA}Co~|d6lnlhW|o@>?)*Z76~`I=PT^cYXM(zb%|Z!|%%B6uQ(+gPK~rJ4p0+~HJ4&TysY;BOif+vJGJ zQ|qkt0hn^3;gX79900eYXk8h0>k4lVd?6t*ueK1^odEiLA_tNUHbyViunD_A7*E`C z$VOk95W^^qr1YxK78syt+KhCOEEe zG}7NOWYWF`T<>t((=QBxo^L?F+j(c++HvgzU(IGcECq&O8g8DlOBLHA1-JQoQ&VY?Ij#P@ywwOke8ZAc07&r!`LN#OwTt$c&)-}G zm7aU@O1F3=n+we`{{B{fZ$pBAhI>8qBw_ILF%a=+d!6@s9UBOJFjJgI+~JjMAheB0 zKgpWi?j_AoBZ2C--dUWdGEE=T9bUGQT>PAVRkLXY9UIC;aLP?2af+l!trIHqB7`9wxktHniM(% zw_Rho$~R*#^`f>b(9Fg2^{V>grpyo=!27I479i>^mN;%ck^whxu>WLbQedqqzM#Qc0n5JH15Ov znc5P~VAcsscRU;F7jXC_;IQafP_??_xy-{56)$1&h>C~C6(S=#W4D6A4N~0BnyO-% zJqpJlAPdj0&k=Vhl0u&>im}MDsuFhrArZhOLMcN6u>C+GftoD}bB{dnw;EfpAQ6;S z+JaytMiO(PptPVuP+INfRZwEHV&`IvS+CsUD`*0qA{S9o4T_nG3JO?I)}r<`?k!(Y zj0=Ds65;|V0!dr|@G#ftNIsJ2s%qKWNoKt_U)YWO{T2S+h_gNT`bvLq#3{$82=0Wd zZ}5^voMc_Jesqr(*~NsHGtgT(#i_xYEv88QYyuJwupm|MM)ZC33j z{cZl+9vzN56Fg;OIp|k0}_F;02?kV@Ru)p~?xWo%;_*8^UQL5^&-#wY^ zcj9H+6WsYQ!6)dmq!nuz`sjI)bAdjv3=jnTb3`J8x7!`4JS9tN1ZxpJhQE1&u?y-% zAO40{41YH4enT+h27qZQ1ayZvcGQW+I7)js*8O&%6P^83%#r?wz(@Hu;r$XHsV%%n zYCjn-%0_A4u+?6vAgOUysph-JOFpJsfjF;LTw4?bF(&9FPVSd_C2Jnz7raUL+RMD8 zH7`dLo|-f%*SJ@*<|z(x^ox>#to4%CJcWXM$K?6X*Lf{#pR~mGbvN~iUhXBWeGy2LF?~UpxLLRJCpn||tB|+d^0ZlNg2D>~ojJ)+OISGul&s*m~%?0AY z`SNyN3a>zw2ZXL2L;?xqEj>Ogm1b!rqPVCe;b^_RIHOaIGt(Ce zwp*xA9EzbFfP4`E>Bn4Yal-Z{2Nn;f(%AvBKS@|FV*S@v%?ZGSt5*1(FG#G)<$Rwz6yr} zYRr-vjJy&Bc3utIkXW2(kD_7|sI_AwAguf@9B@ha)nz^_6*S1$WIzRZgBcR!sDVX= zHme4S*&D&rPLc-NuJeA(7~e;EC7fj^45MYf3l?6DnW9OIE+nzSB}Qh(Q+3nmr2c1c zpM?x1El{1;ncM z7;Pw@U6xydJ|LP2LT-s}F&XvasYbJOh&Cxf3F3b=2Ra(5;iC#Ul<|`5 z^SMyPpV#hf09-l{*wYDt%|+3s1&Ih|C$zJq6>Avnum&hV95j?>l-UToKTpi0rvko% ze{gu|}zW(~4>2Jd`qGIOGVih8vKHL|4zXvny!Q`W`a&Yc?JsqRd0Te>JP zDpmn8s-1>I30fX=idlR5k`>I^*=F)u?R^;ahLFl&VC#R5{W21M8z zUD9^%lUwWcjV@m_AP$jsQ~Kpz%*H1XkvFU;svfhF1z7KuY;5fjkyrS8>pL;QZ}0-v zD|z))A(0ba%eo~i_9bZ5hJk|c#jvbnTv+kYP&!o6@PB=N;d1D z;Hj4Mf7yHY0KKXzPxL!qJs~`bcL0H}k|-5GsPK@WC{?F*I(_HPbnNb#W@ftk(yi^~ zPTxDjo#}R%+aQNL3kVP(K!gAV0tt^`kXKa1LQ$ilMn#Q^8e7!Z9W~uzH*MoEzu#JG zKh8eqd{q^q(|_EG@_pYq`?2=gYpuQ3+H0>Jntw2qv=y%GA=w<>8z+@*xrf4ggP*n> zrj}=qM09bYM`RUa;FX*^v+zA71<1%Iuj}`wHGvLn;V)=H=(<5V7aORG!VJ1q_7M-H z-Z?&3c7QRj`3qH5bw%OpsH#f5V^ddmHZ2GVz13|MtPXWewgdkxx)$(>Q;tp#sG9jp zS1lTDk8?v9%H`x5{Lq3TFuh(TL|3Nq_5yHDOi633&uT6>Sz6~dA^BeB0&2E1!}^K! z@=zihdMA&g*l84!djrl_Bsdq{Nq61zJt2b?HBRo1Al9N`DpnT0DV+*-D(HaQSm%TI zgkjP!9}}Sgn-A(P@qBOwzI z3=`~TSc5(!Uz9MU(nm9GOeC}+vE0g!L|vz%EcpsHf%}tKP!M|@;;)n+5iZlP`Bg<| zK{p7TPc2=*Cql_Pv?Mv7T_KTR?$Y9CBL;`Vn-$+R`DSMeXO{~rl zP(x1+O1LyXZ*`7*fd(|G#3W)3uae%SW>ne^v(=WitBvcY`RXvjP0klJCsRfH8}wVx zL>vUc(Cr(D;!Tv%_!GgwO|O30y_KX;4C}F^P~7{XzI}wn8p?q-#)C9Smo*6m@r02{ z^g0S!Uib<|LBo!MIIR*i_=+8{r*KDPAoXvFL!{=b^M6!+0-O_4_;88(Vjv7tFd)QG ze$(P*X5}`VFix=HIFHn4#HY2001*ZyvIMs}Br7s{pblguplP=A!=waV4|Y392d0!2 zP=9@gv5WQuCuiFEkpc!oWaz1H+Z87#;J4&7W+%|kt%j+4WOR6$np zy+ZA3=SO?M2p_FLNJ%aH$Q3|D z0qk*G4V1ZO24RLp#IpKJ=Us%})&Rr?6=l@U2!?i@VD&?xxM7v5!@hu7Wy^|#AzSul zPpmyQyMK^6Z-l^c?lDFXLfnAD_*XtXd-O3;HXn^6JOzVp5ISoUp>ryV1|$E>_C?Nf z38L-+5x-tp|3dh~rtZg0L_OkLJ6W*GU3anLvHD1$b>s7LM?|EKhZ(CsXY&i zj&M5_YsLZcG45$)2IfB5pyP`Z2?8POtOC`cO5Rz`^biO#ZL|85WEpVxJnD^LEzJLA1bO<5BlyCYPx zPRdS{P;xSqwB{uY^66j3&8OPXouQI7Uv{P372cZxcns2Wlh)hgrvQ)im>5}M4HX@j z98c&c~i|+zVgDlkfU;SV>@Lqmu0{TOtLAwh|_KWCrUxFcE6CBtlua)wwYzeh& z5@?-G!x;~UN`@t}8?m&w$`&68g$+@%hrVTZJP#^V0(Kq=m8=J+@2AuJXeepTi-+Z< z8{_6v56ferk~Qx{};eD-#WovjJd06t>zS@bVQl~YH{)3^CO(h&J zrs02;87zJst8lz#V?}1JJ+~rDI#>j~N!;5Z@+U`){5hjIiG^O8wdizENW-$cE?Jh( zB%}Cf&okQ>+OjMM&?MLQ8K5_JNfRVK7fQKx2YdQqt>)(SD4N=w?}^sx+T(Y!^p@6Y z8WE>*VHJ61D>Zl4s1xXZ`j)nfe>r82DF)m&L!HRoaFTEa=x?bsH7WTT^2v{MSw$~Q zR?#(uN6-&+xmzfs!pR`$pZvdU3;+-G!`O*}r2;nmQhbkmSV)e+ zK`?@wnub89_;S{4Exrt=-OKQ8r%~0oDU51wRE-o#>qB#fq$X8ktP!N!LmQD^0nx95 zcmzlq=5z)|y))E^^@=TBqnqvul}z|Jy@C@}6`=169J5N)+@Sm#^a%qVM(MX^oo%xTRag8 z8=_{QS8NTHtOuu8q|^MtP|}*8fnM>UP|2EidPO?T9}Xq0`LbT|WO!ezS9~PAkM)YD zy6P2Ag-R8@;$!=Mi=G+;GzVWrJJelUmzc>K7eA5ahBzI?17P?0!(j;JVd z>do{6Kt?-NoQvHT%C&_bv@Mj!&c-G`KhY+x56#&^$>VNyHu>Vlg>rpp!xl=Oeq)ro zoExP3QaqkP9NZde#4`Dgt_$UcP|3JSWiqF^ZlSy_lsBFd$=uxlzdcm4PMl;;7s@+A zNo$^xIqz$(wV2=0IWBGf-y6D(SAyD(r(B@WxRFG~8C2dw@ z8R%~2-xn%b^KKa!Nv!JoLrH6%%RnIP2f}-k)0Ft({e$7X%`fFVbjox&=CKTkzRI8K zx*WehG+2@0S2KFHK2uI?%~iicO24)RcIVzO&o=Q-c6xYJPmXWP*==0<0pJ@%^M*t; z>kbDu+__Ie(a6LA96N$wX(-|Uy^{BXY$Rmp-S#kToNqOXDehrZ0_A6?eaXB&{6K2y zazx`*g@^sU z&<%73S(2B~F$*uQe!5Hw$#7^}GG@0I0E}}N37Qm~s(m>iqn3&rYMBOuhj-wGK|AeB z)zV@z1Z=OjDxAL`3|1uXDcBZbqh=SJdQP&l{3vF8Y`A^iu2C9#9494`{m_9fs%QvN`K!`mvrqUL}g zaKPAcknA`p>`1$i>^R`rac~u1k{yi+2TDw6f%D)yT)|f2J8p}BBO|`!KCQ*ibF)Gn zf*J-=cBZVjo6@$cng zg8fw7HNZRkgxOO1#fA3{aFYR8|2+Nnayg0Um%HSQyN~I2ct54z%~)6VBQaw+>AM8{ zU8ZDO6FkYvT(vj>g2PML1@yrxvf?leE4TyfBFw1QpR0EG8jcidJ{W;wLp8bAT+-24 zHLh}E=MzD%aq%kHYBxPkS6;^iF74HwVdzf|%1$7aMHu3C1{{65U2Mlo(qv+7ye~9k zTiD!Qu+3=D%e83gwtIkuI>-L+jK)K z^wZr=rkha?JVX^wcMw-KlS~bdtd6NgLgGsxvOv3>)^bedqXCL~_J5*MAh7>E4D*`F zeLGuG2w2tfbS7mLOwWG#)dYsKFk)Y_kl=b=*RRbC zl>9zfNcwCc>E}YyFAE6|0#WGp`GusP3rT;pko1)n5(*YhC1irc#vE=l#mi^g`FC29 zr%De^ko|-txr$ikr&wbPE5-T%b44?{?iftdoV}LPDy#SPe?b!GQ}&k=$!UZa@0iu# zF3nedoMe)lHxH@g7v>XH1EBml59(lV0sJoPl%InPR>UVx zbxMAzbD`x7!`zVdkn+vUfv>hu`Aw)y50xaP0t>Ve$0&h|gUh*0NLZt})GwlRzgSx8 zA7`NKIXVY5J^;IBSMS&D4DjH0zuivpI#fKH7-xpl3-N(%=k@q+!q3--;Tu1njZr$J zZ3F5A=m9i<0DvhpfZsdYSVZ{+Q@$VG;PzVH)Uv@PL=S7RMv;qZT``W2T^ba@_JtfukqcMQ!yVq8+UMZa*EOZN~%JWMu=|-4H+~HDRzEsz3Us3s-jaxC=X*Z z;{_19Hq+b0$DiX&V?S2aMQV$}qBNxS#GPZuM1l4!3;ADS&7B`hFU)=^$PkX7`VxM61Hk82L!V}z9$$>#aA)9J z@tAYB8epDt`y1u~2)j5UjC3kK7zVgYmqyxqVJZ?5_)sWrB!J>=*%(H^853@EMjA;#5983 zI7!4kSWKgNMOwV2{Z>o@8icG;zQX*m#uofH8T7|0gNA9@EBFRMCdx>H@4kc)p9yUl z>8nRoRgn_uljN0Zs5Oj#fz+;XXA_WX5f_2ooXUSb{4Q z_8s1ufVVAxXXKz}s{=2=%%?+fBZq_MBoqHE!K61wXI?HA89xutU|h;H65=rPpR*Q? zuB9X@V@#WnW0ujh__{>=0sMw-Le9MAnEE8U(qMLFGKauToOos>IHs{Yv4J^chRD!ofH!5wLC%RTe&@Uh)ZGS1W zeRnt#BmBthTF`_(!BGy(8UH*#u|d&Cw9rWb-39v@1BMKG=;({$vH^RF+pFZa-Z|r6 zW<@Xzj4%@nkdGCe>1zRy$^oS{|MFEiuG(Y&|G$6E7=Us4g?6h2>(X|Z^Z+894I0sp z1bXfW(cwqHmw41%7@9{PbIh^Fx~s8pGge2EmoIqjYhU-e6Hgo&QM>b$Q)qaedKyg6 zMT<_S?Fq~C?8S@EIp>@=dh_!)-ul+JzU^Q9CjOQzS@K)I^;`ejzm&iK{a^j--(LFm z-}&9&`#1mg_s{=#|NcMx!5{w7|8c<||H(Vv`KRytKQH{h{^Oth-~Z2l`p*~rzyIaG z{`p_L`@dcM-~YeAyyVjNTvlY4XUnqX*@|pswklhlO=MSOS7ujbYqG1eYqD#zwb^yq z_1O*Cy6nd6rtIcyefHk$mYRRJW*f5GvfHyevdQeu?5^y6+1=Sa*}d7uY*Th$c7OIj z_F%R-dnkKeYI*~hYvXU}Ax z$Ud2UO8#xj`0vx%XYAi+vuEw!=Q95LeD($Vw>|r!{rgh(=19W`C7^&;GrTeINgRko^#9erERl`mB1B@|MKD{}IcNuWy^T z5jQ13Pv8B7Xez- z>QESdGJ`C`h$zkWqVW}>@o#J6KVaid{Yh54m7%n)c2b(-<)}AF%Dzt!qVEete33LU zQE382wQ^GO%BGT&^mOr97d-B8wj;@w^lcCM=y!maX9&g%0tQ`QCqp~H!gnz~!u*6) z_v+BuExPJ_Pw{|hF+GrO=R`Lu9S(z9rxI7o;IQ zipb-E_+0_ub5cf6BXT78?aJtRM7I4|-?p4cG`dK!Pu=e`s7^Q7`1h!bY}0z1O6cz~ z^l!Hka3UD~Kg}nfA^<&h^ix!#PZ~&@+A;&y_A_W36~$G&lNIqmAV)FIfff6h6w^ug z9E;(BD+WYasVN7jOoKiAs8rQ?*ukoJz&>>%zQQL@g~m7&R`E&STIk`!(wNT0^Q?*o zRX9Eys4bbXeC9e$#ntwxIa=(r_{K^SOm+3tOx_dvGT7eV6}G<%)Mg{;Crv&eP4b#gc>d=W5zin`*+G4U#CA8zfR|zW7Hs*hY)-xy{wb@*PzP9ka^;&0a~-RasD zY2wAc?pa^SW+tuGzVWO0^LA;K+j^b$o3m5#(evhvS;IjY>#<8K;OjoHc*x-w!y_D% z>xTdv7+=dyH|Qix&lJS^;UbGRunQZ=9@#aMw>TRXj7WJNt%@978E|uQHXKGE$sD1?NwC{(vRBx zlWwV)dvd|4P#rjOdm4Ooo7Sq8_srIx??V-LS-;Fy>c^&ur47UXonDKsH2?Zej zI|%t&3{RAgJNfGxma+a9dxk-T?yUQttn@E!JMV$*hLTL(c4)oqCYefR%lio5RW@H2 z+cNqoKD^Q%g3SPFfS-Pbds*NLH^xo;wK^K(tHbfe${3~Xy%?kNT!ir1Px$>6U{;hS zoZ9At9RG4dm-IPCbP3|dWVd=VOI!{)1bq~wpyWFJ3>_s>?@?C1Oqc(Q^CLyLe1Om1 zqtEuiC?Bqj^3nh%z}3a4n=-IZxa*M$7=JlyFfPvLl0v75p#ScWri#=@`Rw8dY0)%s z*?Nla{~Ovw+0AJV82@+oP`xtBdyHq=KX>p=C#^pm8Z~MC zU!~DVk&p)eON@|c#iUmyS%Nh{N@gfo-L7w5+aL5s-wPXxv4*)3`H;%gRVEE#gw zcJ@`7R}J&HUud?4*|RwPcL6u~&dqubLUh<%4^@XspAMD2qv5}Qib|v(-5?4jKNCt? zs=arjWO)DC@ZJLH-%)!1Yh^nXI|zJ7ZQ-f@X;`?*lbg602MX-~ZUvh#P56V^c; z;KrDG|9?XA`y*881rLoeQjjYXLc_6hCi{Ya%L0Fh0)6@1_u%~iLd)=)F&AUlhvnyD z1S|A)2Br8^6C$K$d%`7#EtlLC1@kDB@+2EsO+d&sF;Q_vj}!GcKg;`Z34y?_?|hB9#pn zCXIeIG-|Tpd}%b24btH6vqA2L0|ByG#SIVnK3m0UN9fTMr+=IFxSK=xH*N^hXNvT1 zgjOcii}iaEGMw;=(MvcZCze2;w))LVtG^qyN(2as|Az4Wj)QMH6n`r;YAAktI$&vV zX@ue-_9Y+=aZdl59sYLo9wE4i5AnO97jsztHhQr}T9vHy->)eS3y5x+Rz9fyGk6fd zDdh)}X7Td`=U)??nTYm(re(T{XdltTa00|^z!V4!zbD|%w#$A~Xu(ARu}+##=I<(X z-lo&JlzVy8OS~&-dopION#b420^=yqhsd4jCEismJ|llLUohUZ?36cBQSPYi#yX6|EbdAxlxM*LWIQ?#54o`1g;&4*C&<7 zzYL9-FpeS zCJf9ZPg(l!t=|9Kobg&Dsw|G`{mwEW&_0QS&aKHW;?RAQd5gjKb_Y=P?!RHw3V44i_YI zcrCk`&u*rlLm@+$@zE}px-)NOBg5(=ZI5r@uM_AZr4vCcZun(!xISCX8%*4jQ3zEY z6T^!hywK-3e49QCJ>)j1Q1*6X8xM)9Jl*xDPSPefVH&m!ctD zP`io_Su8f^t?u+n&@wu$^TWcQCoyj7+`W&#kjjj{U4nxe9&nr(a8E`>l^-y`Wp+0q zESgT>z5w_X8^hr~OlY3~{t-TqgG$u&nEnDBhyWl&%n*1{>PLA7R0lS2DPyjMKrjNQ ze)A;H!1yC<3IS_?NMg?h_)WZY>JaA7QKh>AbjP2J)FLcB68*WA4e*Sg(O=sU7wJ#) z2!4=7G<*$a#`%Fn;U=XWG9&tXyh49I$jpL>KEQ5xifIP)=gV~Gea-%+%%MCTK<)rlQj5~AJ{#&7CK#ku(sJs$`h2KnU4?T*S7ljt+5FaU)*jP;h~MdH zwK9rt@MHHoxuf6r@)FfI~_y(R*9Je7ET64y;IeP)j)>!~E zSqF@7U>^YU^W8H49*->VWYLq`-W4KSc2D`^$|XzEQ4^weU)Wb__3$@JdN+z;R@%3vkH1Nu?() z$z`oKKUl_+9}vccF|HuK!ypf?43g^|Ft_~@F7B_q!bW7jnjP8gSffz0DhQDCV3b_7 z2zW^mz(#NwH^*dq1TY;$EdsbKl_rdl%Pfg={zQQ46l{`+l<^U8Uiq-3dTppf1!6oQo>NX>uwiW)T$U1j^e zmJbo+QkpI&cNU)MOKT!IJzBNNe78JVDas=U)LDf&>#SC56VrmYzSa3fQQvI>6Z&og zl&G+KA)~Tc^`+6L!lg=T9iFj$qCl&HO&AkixUTTDXIvzbA$JZ3aGne;sdhu9nkcdU zTvS7~8!OdBkL}9mH&^NeCAMgLCAMd*9sL6z_8T8IbKSEE*GXQdj_I>7%8aqdYrG;P zOOfKlj5%dS6F1}X!gugpJ@CPJq58`*yJBEvXvpR$VBjkUKwfpb^(Ds2Y`+7GmYoN< z+RH-3e`)KIxkD)qeYg_FD$1Os?6$*>>-+HMOC*;I1DW>cwny*-rtrrNwrTNPTm zBfK||j+!IKpLuRE6uUDNvkv(_|HaMm!asbGM*9s+EfiU&h;2BW(PFrA9c zp`=X(6V(L39t!UbusL(&;u{{*3&pmCV%8zwPcsz{hf0Q&a*n|dg!k6BET^H@M?(SY zRn`(u`j3V87F$8DXsG{qcyAqu^Ja0?1k#&e?w}f+%_4n?E){b43+KP=Pf`r>+E&Zt z##>&X8sYB%`8yD)M-J|Gh4*vGQi0@R+4!ie&~mJTx`z679&)>Ra$JKiwn0vaXtT;UxwHLcYHEak|-e zU8ri=UYTLX6o4>eH-us@^wCduAPHLpCiWgYi}2jCBrv0p8sWNF*XMgfW0ua9`V865 z=`dnpX)vBAs#`;?4GIDiZ_?r@+<^0yr#LQ#pz?`48bd@+Mvlkv1M256lX zB;QqOcRyYrxTy7TCWj4J4@rISDF60f;PCi3AM}fIP=|yELUV=$P1KnVXLBfLB!M<% z+(Htno_84z=?-dbWjG(GwA)u24(lO5s2>h+JwDpRpw~bfo2C19N5V{H_pQaN`N>~a z`0`ijek+GbsEZ@MvZxaj7=Zl$OnCy5oTuO>Vbp1TeXw(Jz?}?WzEep@~cQ-l1tt zXseP!_%m6ww719j4~zF;OaHp<|GbdUz6cOySTIc8>bk7(bxf3^4vS8Trk5E)Vp{PP z-s|>=Jf-_Dp38p}?0+4J`!7axhz*FWE!mFyDDIWBD{Q?h8Jf5P)Bz`JYVrP`r0e*q z!dJ3&obBg3w^T|_gpzL-$wflrf-)G9Q!0P22$fd%NG*~>XkK}>O4J^xbEQ&`E{8Sn zUmH5G<*=)O|3z4E_QKV&yAHq6b+Y;7r}PklceVuOBv8ll!nac>PDBfCzV|W0FFLSa zVCsDG{sZM#XnSR7`|iw8=Wb+ro;eqrwP6t3VI(&CN0?q)a;ie>Z6>!p2|C2YP!|XY zBLKCc@Flko3Q!cCCN<40%_kgf3Q6$wSTxdb&n!CYU!%9r9P^< z@gm5n7((TVDj3(Ml{FFvrCkH(Z>CL#pR)L=c~O(PRp;TIC5;wLm9=;*ssYC@B{zCw!|+VoPwJ6&o*G`9}TtwhLO8(KVDT2z%Mij<@YC6^TF zKA#2e)XW(nff|$Bx>Zv`XY~ePGBQ*!t%x$|HnGKRlm_FiA3=7^DPb{ToT^B<5KGoSjo-hqp8BC7Af8&rmfBZ+x|Ws5S1?&U>jQAIa95ARom z_aD*sLqvL=j=VAyHF|(YOLb%rLfQVjqNXgUBj38fpACZaHLY6auHsi(6Poy@LUwQy zWLJlx1{t?ryJ+v%hYF^>(>x||4<+PtLnwKVY9Ta<1OC>9_Zt*S7{6#Ke+I%`+Op9l zdv5DPy)#9??LSAVz&wV=V#%M6!F<9N&S8U$^R^C%Rit9)q1rk5qs)q`r)b;aWI7H7 zz*bV25gfg9^2b;PA(1RESxxQKZNB~QJq^W!nG8TZse=*AsYY#8{WI&f4XB1mMKKx2*8hX5!-cXbo6>kmX=Y%w5AWy|xZ8=i~uhBm};!@D+^YI1-^C z(4FeFfl5|{(l;w&35f}N|HWI2YikBD4PMuE13%w-^`eBXmleLob&=Ps$xF38*so=y zO6Gh&pcV@d!{V9|ygq?YRv%|s$+}Vj(N{4hRRbV(gDx+8IhzWWlNKp&l2%uS(#Ftg zCv?ClI~E8hQ7P5!{;4t(X9*Lp4sD$xOsslkN0#;-3pmA%ymNJ|%(utfKdc`IgHqj} zV6_>i8xowVl_@^H1|hzz@O2DXs6$bSBL!y93?Xc=EX`NeRD$r{m>+*GwyHb$8c8}A z#&!U7uJk|?E=6(>U#?UqzJj$C^1M0}H1hQ96?LV}Z_e3O>V~~0v|wEc%hk+>xP>QT zMJt+&UXXU1eK&}WNjDx-0y&-#YTPK#d^MA2>_PmU`4ks<@#X1PoIgOuCwq7)soDRc zS2QpF>F3cpgKedrOB0G;UijW_Qw>NkQKR(;CjPvn1`B_;yGqWx6BKYPLG)c-`1d#K z0vd@vFY$IYasy`dme#$<{?y(0AUxVl1V4cCMZ33+`k_UguK z2_zpDX|5v8^Q?0Llk1j2!39OP`77pU67}M<3NzRRlQWXa|7A9zXvFq7NG!D5!tHQk zS2DOxrn7!9b5sR-pk}Ey7d2#e^GLQN6f1~!eq2DFuUJ>{fvhTgt=Gu#*}fbfWWq=e zV6!StO|1PtUR}&+Bor~UaNt4QCFd8G{lvU4E!LSlY|J{49sVLd@8{rFDHSDnQsd%kKj>{J}I}nDQ$U@oPmJ( z$>m)6^Y!*~N`4Z@)qPhLR)0}l+MQY9brvE(gWO~RTlvaHzZ824woCUsRPzTYJA zMYo8eU!9*r_?##C7*<`{XHiHzV5uK+dGVwJ?C%sXbN0*1?fjPb$JK#UuAPQ8;-mWS6HS4-9h4;iNbiA@x=Gg+Hn&)}3X;_AUB^8bKnR*1!dk=(- zS#@mw^QTt#w^s;{FVTU-3^UxZp3D2l(m+~8*a2dNF~qk=64osV!f};zfcn1OVFPEHGp<|Ul&KXQ%v{? zOumLn1053b$4zy;Kv!^fb5gqPu`#BxAx^hx039;d>T;$3T`OKlV zqeYck0sW(JdBUI}u$TvNNRzrd^iJRtRzO~S>);BH2m2HO+^$PIMM~|z4P#H*j1hpa zY$@t4@1Wk3necmm9ajrA_NkiOOm@$?{*AMtUIa~-!z6Q4S$OGjs@cK{VLITK``s(Q?i^Z z=h)VabHL^+LPMVkP7I3%5OcoE`Xq+uUJm$q2fxkEv;+1PUhRN=Lwh;k$7*NTDSQq7 ztethkt$JybIScHB5JK0&=i_-A(iL))3#1B%8bwOx=}QFLZFzdaoCfR{T&M9Yjrd?k zrxSUw-KuYkr78^ZD13uoKKpsY2)(YFXjie=(k@4kv0+3zzG1h{)%T35$nVqu0m~BLO(m zN!wjFz-ejC4=`1WmleLjonb_E9(V!xx*)M<3hZKV%<;zu|5ouL>&6{!0GU|9;BiLQ4+4jnE<^l-pvR`9>okeTHM33TiVRlYg~7>o>5)4^F)Mx zabhoEgWOdxPE!4PG5C8>EEc*)sVcLwV|xB@i$=-P_9FIt!;-Bb7uZkQ)s8D|jm=jE z5UvS_h&ShZxPo9Mfobjy(wa3yXJu9^ngfo|U?d7$Si@Hbfc{Adjg&iMfYc(MtRcT? zRFSoACSp~@MOhKhxnO7_KK-vYdtG!{6PiOYIiKGpiYV_}UIxDnH5WWWZ1gmKak9fY6x;h%_qzLJLZ zio!Q_BOVwpcNNyK{lL!Ti999C_VbQG~^?HyBJ<#8A+-aOgv) zy@ZEi^>W@>dGkk}`1!ZK@(*AAqu+7Sp0enfjqVpco%u*o#vCj*642Ofmuh{2zD9#? zyLf*I8%V+#bbKiAmJK>>w2MLa6opQI!%0YhEr*B1BQi~(#)brZ3Di(G2(0PJiORkd zVhUUpjq)|)K5zZ5c+^G8QqkyvB8kzCz&I!QKyj9^HSVTJKp>`n6gQ+)f)8BlMlU?& z#`{V4Fbg8T;Jysz!|wFI12->h?+o|OqAdz zW-n?cT@Q7lCjY?uRkR57m2~OL3SZk!-uNVEYi1A0-Q6JJoKGwCd=(7sLb0m=2-vUp+j(mxSjSij_Ne_Y#n0FGzN-$B@a=JxZUhe@svxw#XUcjEd^ zWc=XeoyQ$_{P8Drm~X=Jcr->yJ?e&SGH1Sc8M~jgUQtwQNe35E@4(4HrV*0s*O-e9 zi?5#crk`>Xmtso4H1uk9rOkPSgh|es_7vH;I{0sJcuF`{x_5C+Xyl_hi$sCUI`^Ld z6`jLK`zD+!j??W~?t+(O8}1D#Ah(X269gLcaL@S1d5_g`bMh4r{7B+9r6@O=nFvmm zK8_Aj-y&}8JCs4}U#`E=MJ|o13a3IsD<*_^Lm0x^!TBw07jv_}1ft7_L1|Nq%bP+Q zHmkUJoVc6}xWu?RJP zpdE49P<%G5ItsWm6gQ}OsklI0p_Y4U%4R5x{{b?|5pX!@r7Vwgmm#e#j1HU64p#dbf4nR^_ zLIsJod;)&{%YPh*kZ079jSFLyN=A3Ea$L~A6Sn!o0ni&YcQ)IVW!{*BZApHHAQvAE zm42Wr1k-;&s#G0-4(KXxKM@)+6!Fqb2hfN9IbJLp{YKarfs6Own}?xK?QQOAtYYDKf}uH zj=HqR#AqBaXuAOVWLH2Plc#;X8q`d6?QuHP)YbkKq2`&cfHtA#d(EyR&WiqnPIP38 z+lq3`NVd0;yoNTt9N<*vTrL^9J3M+vdj@;M`Ez#QFwfjm813MVd`C6=%c^3V8^Bv+ zz1@!`MQ3m~o+9KLt4aQRwepo|WjF-fX-8&!L^apaC0La-SEHQJrO|Jh5~w8Dp}iXK zV1vGNP3YNp2Qi|y#xtc_#czcKfo`1NSKWxx!0Sfb?dP#7J8DRnY-_RxCf4f?wVHbG z=%Stbb?Nxzu)(t8SqJEQRd~{eUl;5p{Jf^OyE_2PEk4LDCpNab{>;1-N5GDjc>MC> zI})eP)F8xBkIox>E->+ur0i$re*P|U`$6d%aa zHs*(g`%i6zNR1D`4T^TBU(S6CeIUs`)9t~JflPanSbw?m2+*+vpO%K=YlyB(uR(WZ zdZWUsFrt#La;G>?7xpYQoFV^-C_zi?w>npy7k7L|tEzq|#q9%Xc&-~YOnv)*AvJi& z_Bl1UVSyU#>#v6z{D^)v)bOqu$RD!FP(=joa6~YZ)JET+Yuf1)u@lv=VmRsqA;btR z25EIYzW%)H*@O`_M<2ABPks7;L`WbFldEANM-*Sew-gL%C=tU@JkRot#5 z{{2uMS^Z_hg1yr_!`}O(cd8%5p;jyZUZ`b08;(B9|1LZ?R}G)HW2`V^Kbq$Ap8RK_ zy!dPMc`veTc`VY&GRJTNXNf@7@82@}sI}H&YY2}N4-k(c(|2O;viwKdBA;6_aD~k9 z$miw*QOJH6$}#0?-=6n5Jn}jG2RSayl39e`Kmj75$ia9WVwV477$Up` zuAz2}5+>2N4tnwzLwWH8I8;RwC=LL9-k1M4lt*Uoe18MTJ0#qGGereDN%xyK7M@8S zRt<;1h)+U<7r#SKqJM(Q*U1Dn`E~9YTV+yH#?Rw4I_l2Jck?BVNl>ZEH@xtbSlmI^S&=LjTf!Lhgu4i| znzLjo&?f0RKB!^)sy#N_e-K))Z{bh2>Ja{`XO!qH#wn$Phlcdl4!gEP(m?~kDzK=s@(xX>NAbVOiT|)ntSEe?lf;5z%3|#G`3=qiAef9w^MqLC=O7eRej;8@ z&M(2a>QrhhT4;dI-nHn_G-}aW(SPyfR7<`hbZ-kFlMIIikg$xIvxSs$EFh6qx1;ri z=z~yIc5kl=t(tv>)Wp177MEW2L~*OCXRk%NP&T#%sX%z~6t3Bnn;)riZ-d57xlZA# zX^bW2ew@3v$UTgMtnr$=*7|j8E`~hyiFC-<1>kJRM+wSpEU9n(`cT})!r~r7Iw3o0 zGH^zA;f@UXvIp#gA#)78R+keo6pfr?qR5sjL^jIBOyfu4H*y-|7O{9tH&@2Q+h!GW zW55{t6XRq;CS-fYEmLTs+3*1VKZyVDhyU+Cel!|~r0Ye@HtOR2CBrc4u&pVZt0&>D zh&UP@1#r&x3Dp$-D^olt@o?W-K?_ob?9XQR@66GeKA^K-XMeePf!EZCq~x_wxJr_9 zI7#xvmi7hsz!YubPpD^G`ROb>3cmeKU!t+(?*4*Q^SSwH{q0Q<>%f=CI#B4b-a|Yh&%7wnO;|r47Zjq{QqCQ2 z>sF*=e+#I>yu5tp{p^@_JgS(Tzt#Z z$MEfT{l>u!3ONZJFmxh&3r@up^c96~!Y)OfE$DlN@jcCO&j@V947(O?S4;8N0``lp z(<-`W2)1uwF9~JS;9i@w(DoL#^e+=bRRY{J-xgy6EGXbG{2hKcH!vGa)0Yw?P#>_c zOT->f=lGsk`GI9u7rvIIS3Po0z8&Sb?8u2REC<{Z7mFp-yE4?X1JF449S;7e$P~4Z z>j_=>JkTu-tD;232?x6Qq^v7lV=V_=DfD`6rPrY@y)rBS_D;To!_i(3!=nTBNx9b> zl3w#|tdw5{fnp8#Wmqm1g~}S;!{~*scus|}1JE}Hpnt5vFI)lL2{@)u)EIUs3}(=9 z`NcA+Fhu(mr|6T8W_WM;c@mpu^5GaDC*BEAnq21Q0MIT4NLNFwqZnjmTYh~gZi;5< z)H&yu>Ai5&9112S+hVE=v}U<^ArE4$;kFdhGChXfE@-ue29VEepCStfKGjMA#!hKunT??t%jnBxNkU|zwwiOwKaG~7RE@HrOcRy+a>CiN z4vtvxGBKCUNcOB|XU?Oay)E|#guPO&}SbRsAUFKv(UA4J$R zLn!W`#U1iZc3;YIgeQz53@|X&vcfmGJOa38TTAwnJ~exsuc!mK0p~n(v^W6lZvz9` z3H+EX^)v~Ns9@fAG!xA4#Xu&0H3K=aG7#Uf)RzO9*X!t*uY%9)N91MI={4a&v3W`IfJX<9pE=yMfJ)*?lE zCslm&G$-AvP)&2v5hAh2cw5$x*ak}AWMoBf5#q6KUD(`*E^J$mdabYx?IV&tnd{KhsP6#kSBDOU}dG+F{&R# zirsuX^T8bDMbKnyYcnp}%P zmDFN`n#-QKvqSGZBKQI7;P^cJMhqSuTGW2R*lsJ2O$r{Iw#Lv)^U;r~b56?XO(tVJ z*I#P$u5z28C+fMK1VnBi(0?P7PblY(t0zW@X>QW!y-A}WoqX%H8pWqx7&PQG4k(!U z;kNW0g73%JcWNA}ga!=U7bansl9Wc!xw};vElD*}h@45~MhIZX#Ua4!X1Ae)CLat< zzN7~gB>qMwQC8hh^r296xAsnLu`cS5#u8gdH#Qy(Ekv4MT?@J^@DKfaWfMa7oYIm% z$ZC~6%mIS?y?Dcy4;*L4G6al624NTt5@$mqaY*!CPvZFs#>wC##RZjm)Qx0}FRJ%H z^42@({&}w#O_;s-4oI{^&W{_pvPc@?P!Q`Y6&V9bW&(4`Y%GqXUZbBGYBIj7Nli>D_P}GQ3B>=)zh5IE0q5dqRPLo;_>FtmA zgk~>S#hZ}{5R(*{?hG4uWUwO#Sds&CAAmG_*ISD~AzYJ>312GMgvIvnazA~l3$vB^u(!Cfl}3@sRg|`^;@=>TN;KxDPd54S?RRv5M#LT@m2*+{c=aQ$5 ziVykMi%vE;Bn<|6S@y6!P;L`Q5qT^j^Jr}ptuff33^BL%O>-=JN-%4yEO_CJ)x6pIUzRc>XdWLLg&T?@DmG`%X6w5yf5aOGd@dd=?Y zP|2F->0rC9FSI=oidoyFlkonE@ZRo?mAUrH)Rp1A-5bjdz5K5yPlyQUuw>|0g-Vs< z8@FJQN_~veJ0&(H6DmGB1rjI?!$EpySJI3rHPh*A2Gv7#646=>=M`VvC;RtGE9N51 ze<0A~g+MhE094}rd|(W8VXnNuT?5HJ=-{?BmKRFUy2G2LH4cVh zM!leJ3I0<5FV#kjU9&6Mk9yfp;YUKXbylg{)uvIE-c+|bK=K)Nc2k*m+X%Yh(ot)k zCMi#%F{lN{)GsB#9SL|~Hejv*RMY@Hw~h~;Bbn%^D-#wd?cQr_@m7dVE+G+C~DIbcND-Q#a^QTUMZt)ZFgzT>iy+1i9kx5)}ocrCW z%;BCgt6w7(rEjzCnHX3WnlQ{8Lq{8RD^oHQh5|Q-0-Lk|NZG3Ku*qJWfZy5;F4EOdLbW&*=c+s#AZ!F_a`vct z(zPF>s+zeaMw+kk`2dpa4@pLLb&C%*NbwyEk9Rl!ddWPe<^JHf03|nw;i)=Ur}S(N zv9|=mDQ1J^g|A_@j(C$%5C*2$_WE_My6^b3qmgL*I>JyiEilSRDfv;BIZN#)3Ef%0 z+`Lf_mf}P$VRc6LS@}_vNsq%^5rF+-j91A<=QoPRr)rM7$olw8hMc(Ic*U%&dOY(4 ztaiK4z7Ahl^uVxJ> z1o6n6?5|FjiCKpKmnF>wt9={ercfNQ9gq1sDf2NOgP<@>1#Hmym<2%1CASk(&az^g zgZ3A?YHC{*s+PX5ZKs`!(nJ8pr(W8PgH(Sj5ftP6%=rWkczL*>c-Hm$qMV25 z9cz{3I*!A+0()u;EDr^47iVSK!irGfAEE;J))h}Xap!i3R)(UVs_kr5D6mH90ZWV^ zVgWY-NyZAYV48$S+ui2BVFgp)gY>J=@vl;@A-S~cm^;YNx2G? zrGr7I3n-}I@0HH6g@9ke4>(gNU#Xp)-Ln{b6+Lt9K(mW3#i!R*`KpZiddQyURLfoaKdcbQH|SuyRTn@fPL2xL%s4|LY%m-9 z+j9t=AM)g{J9b9^(!1*}FV?x%O&1{loYfw|j^+?=}V zqaxEscSeue`sl9cQLjFFU-U?>0d5W59X&D_?ui~55cfup926U)XAX=_@iT+tzWA8| za)12HAbB8uW}rM6KQmZ1$Il!v55*51H197xG;p?*9vVCkmmV5GA1FOEh#o0DG>{%G zJ#;WVR(k4ydc6G9pn9VG)WF(mPeB+zjb!Ts@%c`#z)oY2taqeWRkB5hb@V{F+U3HF z^hGOsVa1|x2j{ITMDiXHCLG=P^8O%xKIk~E1EY(I+WQ|}8nzF8n ztg#qb@Bw3ZV*y#C^~lnmn~?QZMb?NSYjFixn6C=5{8(aSRgZ%SvL4zS%9^Z0mYGB; zwr~Y|6S^*l(RIF{>wZHGoCGQ}EBwWKULiANPO z^P`IKR#Z=72;M$41H6r+a^*PSrdr&!#a^i3uHB5gb_sW?PE58V+%;%|+J7VNctQuJ_g8ZlH?0Ew#8)Te3oT44F zHSp}9;%+d)9SypQ0S0fS^xud($=VLw4I1vC3a7ZkqYCc)s7ko2=C+&#&mLUG-J`X* zQ~zECcMKD2z}-*@cSDN1p$K+{ZuXfniQ3yi>6YPRh7bY6?}TzVQtZ%ttb?YI4qpHg8E8>MUBG3 zXB7_i<168@NoAQK9&2=#XX^3TptKZSw3ec*wiKqf;4{KwgXW@8G~>~!E``%wiW=pG z&nkHI<16E_L4BDa9&7ZMZS{C;P+*EK8cb1EVG7e>@EPH;L5oo+n(^q=n8N8XMU5iE zXB9m9@s;t|pvue;k2Si?v-NmvP-coQ+DuVaXA0A2@EPH;L8DP9n(^pVn!@Qcy!0Ry zk9=0aqaR-xj}2l%G$M?D^!6rQ4+##5A4p2BnSA1TCi)rwU6KoO(4W=t;GTQmv-sN1EWYK~TxQkJ@EOR2i#^`)}H1dXQ_rwU6KoO+ch=uEXrQ?1tIN1EWYL2a5TPHXh0 zJqQ$+rOVuh~ zn-!|=8dXK53OZGyR5fW;3Q-r_Mru{0SJf+4wVIV5bAsO{)oRB0tW1H-VnsSuy^>X{W%)6u_-#1ufYV8kIQ8NyOA)H)!Vq1nYG;0|?aXw75USaIZdueIY;^-aACn z?p%Ot0a$p~0)%4BZ*>?;iVxI6kO*Kv!>t_gWDbJ$y%H#h=A>nI{vTNeF?kDG5~?@q zqnWw6VVc$u0=3&4$8k7iq1ePB|cSST=)M0oCUsBozKyXc>a& z%AlvuO9aj_)iS37M#NXz-(?clm-8cf$a6G6;bmy@?I_-9{Ymn=(|RlKk9_5o@BGF) z8()3=9hFyGrf>15buG5+uiE0nXfc|k=xcr4WC$ESul0uZV89=7JnV7Y$wu0PV<<6H zE^(YMF_baxv+-@a>s!ey(O6eP${ODagEqdE=*Y&maw4elt&mLl?X5kY*V>>~6(M#1 zg;+Vl4in(|0$yDpi6xL<8qs8s9CeBBUvw;Q!uue-0LnWH86yqegj7j`xWM&x%1YDk zNtoLpOAg~w8@+*rH$3C~RX#A>&R1_aez-@Dh~WTeJKr@R`M`N}jY;t!kn>&dbtQ0y zv#p2T?84o=xObOq{SWuJuW)ZmPJX7K!2zrsGAMuYQP%=aVnP<-CX`ED^tX%xg#f1> zA#$fccp^kkhXi?rLP0dID?FBN7K%GC9M`&!ik~~yQJox2$pO)n^z)o)!%V!C%*1|s zF%!h59d90F+Cj`j-m&|TITys!VZhTp_nm;b*bh(o=H!##`Vr=9-=ONM!VjZ@s=seW z70|R_%kb38L$nPzdO5)n(HY;G8If(H2N#isMz;ePKl52&1!77dV9R~QAsL7jJ$3+U zVTzjf{nPPWW0iLDgYA2u9X(B?G!;l^W#K{Is6o>lolixK4t=^}tb}&F(H&LV&YN|t z#l@AN9S+?e*q8|YRPeql4oHtl6j<+-GvR2e0pZ16W!UK1k72C+pfKLk+C177$!LYVMrwn=MjNH#s8JWs5F2%k z2I}Hh88*(PfJ2A$JR83rBB|Bg-1CsG6HvrYZ%D?}>C-cOe)5+W9`JQ4pOnZzoJQ3` zocu2MUhD;)ov$?-8|hACD?>LG%zutF=HmO?vPJ>p(}Z15ICSfY0Z3JlbiLP$$*ee- z@**@}0vuGZ8$;URW=+u$_yfAF>+DWN5!Zpb+yxTP^_lp%LYa_saPfaJ(1Vn+G_?W} zI5m^l8V820w|Zab5bv;1u3(-MXr<#^_$+1EAhOAt!7{|J?q+azwT3Tm*L|?ipesb} zJo@d+G7&u9vF8I^&jAzm-(*`gX2+JJ-LJ!_@lr zHSX2(Qkde#ogk)|uCD(c{?EgP#1+w;!O}%JY&2RY%)!py%{mq^xlZ^6 zfxWtgLKX)RenHx;F4A88f*?wvXns9&koQQnVObEAtgCM0IZDPKk0pE{WRdci#^woJ zpG+V@Q64shi{h!}*tsOrs5w*#GotO;^5VKa5a!GiiDGa=5s~s%_k+mq4Wzmu87cE; zB%~@_%L!GkWx8}rw#0`rGNEW8Rlc<)Kxsh8obMyb@EQbZS?^e4J%95P&kY%$sQBYs z6aH*<)V&?`eVXv++r{qfV*l2JKi`hIw`2Zo#9B+-+a>;O#9B+;+ok@kvX*0~R0DD* znmhk|RpIg7#9ADxu@=GYsDdy2ta5@+M})N;JEgrUG=a6QuJoF)7R}LFvepNh4I_$6 zP$5$Jny751zR868Bom+tN;3L*4*=8UV=nK80q5fmF1e1!+d&j6AfkLn>pjE|XK19; z&D5z z8cj+n{7}o9(RO!&Ho2|1yuKt%OLQ3_3$F^AKuEgO@~vqxq%P5(gk^=y`PQ_Ugd#1; z1)qvL)Uk)IJYkAv${t9JX65Dy*yOyS011Fe=+`Jy(HEPaFF3xle*14`WPl4 zZ3nQ!g(P(BpyWieH?_}1NOZbJwRMp~J=7Y1hOWj*lwfNR99;FR05m9Z%sOL7A|scFY<3qI`i$t?(N0?tx0DhzYvXy z<%-O|H~Gw`dS@a_PK5Wy%zV!)G<6!+hWBN5W-;ESr^VK1vu5a5<&AhUVaI*pjerl7 z!y%a{JJOR;9yDkC5Lf7sU+<8o8is8CIfgXLIy0RWWcwPsVT_dTb0Uu8);l3 zmHAesGT(ZQ>#X)Bxyo@AQ?+S7-?JK>##weAkA^2u2=ghuM=@xG6NN`bljTVW zg!4(ZBl#{Snrd;7MkYkf zbySI(Z~Y>7R$JWT6fnU(ZVbUCL`a_fD#^31F$CWxiU{8tL-6gWgKAXRfp4QlZm~|5 zQ$+aIJKjwZVIyO{ZnVTDiU{jQ3*1uI@={+nmGldFH!P_KUuG@oe^s=xy_PnJ1n{&1 ztBU}~YYLE%gd494Jihf?G)5b2LuFn!*7EdMs5jT*{{Xk*M_BT!C68#R?HpkbE<789txD5xEQr z$%rHHQGSsLXAp^z1K$p^7~d*^TZoCPJLKLff%9#&CeE!aiT(*!#9bO<5mw!mg$K9Z zp+z6rEIk_6hs>ZU5`n^gGg_hNG}xy*69np|DI`#tL6H!Gw?4oYF^b@gZxwHRYmCB& zf;Tpzc;j2IJ5~e(-=>VRsMR6rsZ)1m%_w{6<#{1N#q>Htq!=t}2}TI;?7ciU^mx`z zCsBPAn9BWv|Dky{cO^q`7WBz(Hu2?;lRd;CYILrEefMRYSVb&uD5Kwf8RI70CGN`% z*>_*Y*_b)5nzX)#?7J`H=!bX9`!f37m+|7(Jc%@{bP=F4xJ*Ty3vnp2(4tvW(bt13 z%uhmJ3xC}bNbgQ2KmtPC#o$=WF^_-dNS`Pdx}DvM4Hd8#TRGL;yQZjo7M;62bl_Pjx_VbOG!tR zZsTq`B!6O(LpDuphyqHdDTw$Lg)g~cKfhZJDT(YxdRZUol$74iZ(8|c zhG-z!&lkF;Lm!e;+65z4w#3t>nMGUdF$in5Q@|}EHjQ{l4Yui6llz{PQK1F{b%di@ z!q59LE6u^8$|!aJ#f%*V*2&y(b_r*T*>|`$^ZMpf^S4-7Ak_+6*6>A=yTy5*k z)kh~)AIaTk<>t?-mO9rS&CZyadS5w2*qchEEXEC*F+)dby)m;qixw-2KZv`m+fLmx zHC`|{L*R4Fi zj%S$ecen7T>l+TP;OGkfcnOr=iz~!hqw{ysH3obh>IBI9>&h_ym|8% zELiZ`*PVFc$ikCOKIQeNo_5;kqSH@5{fsluJoBtKoPGAl+&91Fys_~- z&wt~sZ-b~(({6lEO_sOq3D$p;l5LM>qZPsVQnqxnW?mfURYU&*xA^2czrH(z%G}yW zOM!miw_&N<#fKz`m&h#9b$F7U?18igkhKWN(=Wz{qw8_Nogs{RQR}FAJ^2aC=OM&6<9~~61*6in9WH16 zJV@B-$vewgV(GENJ#yRBd2Lo1kah)*!+im=i>UXNLcrKa~Ce-nvo1d_oH;KL|%Hogt`;F2q@VS$>v~@k-@efbSX-kBU_2k>}Lk#_&vWLa&G0~##j@s6hZ80v@ zWKcVfQ9(_R@OBABLoiAQ_a~Bkcsb32kp$E*Qf9P+OH#giNP@ffhb}&+ z5%y;a?i61*goU$>yM&(rJsXAch|F5@6*o|&*T^oyXwD!SrN9=<)Zq9Tc(#bTKaQlK z0fHOI;SuXUW`~J(P~rDf(=FHI>aj2oQ+G#eaJ97tSK|H@^m$y35m#SHarH##!fdo8dlP14FLOV%_Qh4f9 z{Jl_qYxt>9;s_qpQQ}k>x?y*u2D{s8u)DNMi5C&OUre$4vCxHK_rwZzpO3MNYoZ)> zFREhq8IJFD9=+QHy`SX61p&VVINKAR!PZm_ww6?}bs@3!T#BvF zgf0wQ^D5Zd5o2pfz}AITY&}cF40~)%3AR4ZhqwyZaV`N4*!uk5V5>Lhr8wi?XUn_~ z*d*k)_*(*jD9|R+kF6)6yDxmJTmm2LqsAOYx#r;WQaa8vi=m(MyCm?UQI6 zVZ0(aH{p9{{CO6DE#Btcx>6$U=o{sZPzrejQHnSS;5=V0CBxn;0sHNMLnCV556@LA zUW|62b9?3&qYL~aFJKGK)6|z!s@@s;uz5PPGEXnWRDD69>VoJ?F#K0UAj6^*t2<=+ zUf@HV2XNCzkORJ6*jM=aK^TkSi;)*8zP8ukOSV$W3)00z*OyXs?FwBOx_IkvnXGrl z=sG{3>*6Z5{+fuPM?|r;U9h#A59R2$F5d(=U~BhYVQX_v3e2}oEK)wLU*xUSmhPoW zr)#2s;CyoXk%<)86VP>!>N?_mr*bqwdYt_GLz5aWh8l+8*!@VkF~F=H_cDX1mDNk841+Q>{Hib3x0X~>%m_y(g$>nnpYVI)!UA4 zO4R(emL8QwMr*2&^Li33bXno686lG#P*n4OP{qVKE&T343iA@G!Fjmc2AjRSp@|Mk z?x)C;^W78KJz>c9Tu6G=O)2mf!`eW7b-zK29fN791)%RoNbG?*!w%kaiQFIwa|8OW znj30*1OmM}0RIhLHt6SKZD_B)Rs2+^s0B&@ECe#3c~h}Fu6Y27N}>7dD$Ua|U(-Cq zzw`#1gm0l4mfBfYX@?te>!D4ojx|)B^aPN=}Bc|qPp9lS}$WXI+uXQVy>u`sPgW%Fo*4)k@Rd@#+UKJG`dV_BCF00etm%Z3|xMtL#Fo zIZ8Raq9}JHNw2yyxtH|n2QWLlrq%W}UR4i!^?2m3UPtx|ewM z1DG9N(`o^)%cfhj+hgt@r0kGNS+3Y{nDUTnv$RzYOu#iyv$~WEU8Su%Q>xNdlEpBg z7;(+dL9U-c@Ny%Mv1}@MOQ~f<0;2-dokYiGBny>Bl%UWY=Qbe}1i07Yg>todk-VP= z(}%S>ZHyjOstY!`;!4GW-R6QHR^6-8#`aQXU2W|Ev9qCpYb(_P4SbwC_}vsYQUGS( z&e^HLhS_giXw{(~Cs#H^l)Vo+cnHU*nrC{CSZWxCg`98`9vm0t zrNQpI=$25a%tPNRffU?a*KKr>jQEbIBnxqff>z-0#tC9X=U|2}nb(IO^ZFBA|Ej`6 zVY)u{-21sNGTaa4JRf+^@Bk7lbp|Ad*9n++?!Wivue8Le-5FRlJlGk?r&_sVBh=-EJ!w}ipnqqYEvIilDNp}@V)SSS^^JruAOWS={9ac3y- zkZPBKs_v&~=pIG_8k$*pjTaMIk#VT{olo5Y#`O^m0u+ZCbO`_j4kKIdwhbLt1RS1e%c!kkj!7jw!pix1tMhER3m%?Pkd~)4mNrhW z4e83^ZxQPn2A>yuF5$%0VT7B~X}$&yhRamU+q&F?Ipr1B4Kw+2GLwv&pp5Pvi{;4W zg)e6lsL>T>{7ZbX&4bT6BoT$5@1Isg)Gt2iQwWmtggP-AaS_3s$6{oeCHDvSA8_D- z2OV_K!CaHDGk@4&hhuC0h$FcD z&5`QQo?u;X=SK<{3s8jzb=&z7(!?-++tJ*)$kE|yP=}|i^^L+k+|G}ZDkG?3M^2&w z3}MTU_JGTh$QA+=6fAr)icV12*pi!y5bhbY>NB!_`1gqDv+xjZIMXBAgPj9=^0vzfg2VV95#{yVtaF>S5v_hNwD4Tus6_Eey* z`&0hDyY2ZqR^xP;C4Y$UZYJ~H}%MmL>X#*ZO z8*_kNM-V-hrjiIk+5sJ0>@kO-I{f=s}4A`t`$ z6N?~A3(yJDf;vA&A2B~P^;iV)ynif$?0{P*5<&DhunjMQM8X6SWD+JS009$=Ak!ja zC`^4wM9>?6X=n-=go{P{NzX#e=GaeEm`4gfkEX(?XT40*UXOV!6gNGF4s^E_rpgGG zU%Ea-`J`gvluxP`rhL|_7qf{NXP*tit)^||zpu^QZ`2;+KXBR+j@G_b+p;38p{5Zx~eT$s~XIrk0SqykE#xOFnXNKh4JMj+ie zJFo(W`^K3OncJnaK_(PUwgtxR^oV)N^`9gRSCnM5n%AG7$|yD-*`#Nr&(=qlBPI9e z-_&R@#+B0=>SKd_qLaYA(Vu@yUsFe++Di-CUW3?ZT+hQsm@Jr#EvIP+gXhwcGTe(= zv}~ac&sZ5YKWDT77TK)p!bDZn+n@B!Se*n(ounisL}j~)nvQ&se;U!bKmMpYHq+VK zgw7&YCCQ_z8~O@HX9p{tQ8$dlt!j9TdZb=N@rsG$Jc++DS6O-@eq&~3$(;*o8kKNK zhUtNjV7yAaAIW3mu_k#$3`9@rbeDbH9DqN9z|RA)Br?cs{-oQ3+oDbdPB@BIpz3AaoJ3|>k`rxZBLyl^`z@7l(oH> zbn`9E?5gE0%38 zb&{4+mu^}5#I;DPoI)BU>iml1+@iwk9$SnLm7gds+5o)5_=GFd1H-Niu0ie?dNUIG zL;jg-PcXp_^&;1Bsn}7h?B}uoQ%~Er-rWxXEihNxQc_uZs}pX4pen+PurdG2ovsd3 z{pV@O$+ZEM_v_^WdUy+_zl=#7V>|7KEKM)rhu21NOPE(jch$y!=&Zm)5)grAW{3!< z^mcqNs$<=?+YO3{I4ChQuM1<^q+?} zr@wo9V11}laqix;KNzs-lx@s>Gx-h%MN|s@$e*e<$*zxZsjw+I6$yxG`AYUYy4jAj zBQQ7v13WgU>~|+T+(A)O*=6A!g+q*}C+Q#(+DuU9i910Q3DJ>`!q4O7r|L+I#%JU$ zcqsKdUs3oTO$Hq2bbichK1cyhH<6gktWVZ7w&ion)i;_KFt61#pu%QJ`ch}fb(P*2 zlS^NTP?SWD&DAHu{%*IyPw`EmfzPUw8=gI-Nq>(2&w`jpV?Fn0tQ;a@cp5I9g1PK$#6(^CK#qF3z8W{H)o<_Fblr z2z@NHZJG?t%v33!s_KGUD-}iCOq9r)iXX024EvQ=m31d^J79YxBdIhwW<)Cs-*rVdUD=!r2#ZRe7%OyQHQ;(n&6q%E&c6mu;n&&({n0>~#!M6{Cf@87 z{^VO3G+V=l0m+wd`~BN;$`KwG9uykqm+HA$a)-ntq{(;H`}MQwwp!a`?jO+N@+p`q zEJsbJ@kl(HAS&`m0JWHFsJGY=Q83}4#Hs54I1dDHLaQ9A&vg1Q z9sL?qrO~ZaqbUxX^kHtILP$A%n9eFXr>gp}Dzoai6dlgV?|Oq$mqHO#Zo9=VrPmf7 zNv2_m;IRhP@njxSU+0EU$22VE6kp(`P@r=0&|}>~W--kJYO8lkbFwv=R*K~sU}FAVUifmh@LD;g zaTNhXsMsqUu2a6j*?#Ed&Fp_10}7k5_iR*N*7j%xGT$Aty@j6 zIqo=|Jnsy1kd5)x&Q80PiG4s2+loKaon~G}1% z2q6Q2I-FDO8ef9r{yM9$aeV0A!>#dFr*%lHHNSogmUaM{IX zqr*AQ*sa&uP+8<6YJ?P`ud^MtBk>(4GBHZL6x~k64SwQ?5>!16`f}KaA-pjR>BkBg z8^>mtqrF_58&^|$OafJhX^$}JWXa_f>nX5!0`aO zgGohEj)$>kFu8#Ee(~dS$FbzJkL5(&NH$bP!Y0BVHEAIzYM?05Rx_dQs!K6?+sl9`RBY?fw7%-#5mX zYtFg$BS~90$6d(YYpyw7-}v6&H@dx`(*--t_bhS_=K!V&8kl>-c@*V@H()`}( z9hUKs)?t7VS5FJcgRS8h;A!_kII2lSo1|Qy#Ybs^6VncQ7&{9KjeS+ykli_Jvgb6eYJI42zv* zk_cc&H^FIRoeS{G;&Y^%P&KofZVqL7M~8CA534M)?C|}|1N#GM-41p$ISm^f?A%qV zR8YODyH8;MKT@p=`i)$%s}$$gF!<9I!&8({jW4r)qO zAKs3fH?9uAkBZck;ibK>tBquX>xifJdH1f}*@ii1`@O2`JC-}Uhbw1iR`CuFxq3(6 z*$szT?c$5p<~lxW^q=5SPB6rfmIA(`)f0600Oy9Gv-X^^jq&hYtOG?$=b&wXdF;er z_}#?GSbQV2N3t)TK@r-y9sf3V;xlizU$tvHo`-Z_?n#9E&PtGfXb3ABJqc?8B>mi) zd*OMgDjvEBSJw0=?k^R9Lj@@39-^00imWG-;;=C`lxLZ#$of4pOl(l52s9ALr5gUn z*QQ>#LpzVZ+KoMAtoQ!bG*Pti7i_vb{ar9^I)BAbl8gU5_#q2IIHKwoi zn9)b65|%PKf;qPL1hkz2U^ET%Il^hQ8{7u$T3>kN`Qa_yh*%F;W-8p?*@HLfcm^z| z@F%V6kgH2`NLeA0zhrWenNejfI$>^0LnM!J)=fkBpZOseAfl_rMEs&dysb1uauNS7 z6O0x+?MC+0pr-=l2?C|SWnNLfTHL~?A0H`@ryO{XSS%YNc5QQu>xBd!w!5O38@4zV zbK8R5i-Jy-;GA^fmP@tVw&E?FKO9Y^+_vVocVE{gmc*T31kV`>K@KrHQ=E^TNgH4Q z8KRbERrDufzw6j$COm-~RMl}~H)sXICmROGu=Kl7$89Lu{W3vma}V}Bax|K5OPvG% z;`zN9{K`$$Ei%qDzslQvmB{vgV_t=W3dk8ja1cRft*>BHd0$rLKnjO=OQGvKQrBJz z&Z=t!jmi2fI0a@MvKT)GjUisdFJHH#Fv8o?2)|*IS485G3R}h0lD}TiCy&AiKwzd^ z_Ln7JEg-8x4M9M2 zIgt9PWV3K9fSLy-G%ZAO6g}apTTzCdI9%iGmkrlq%LLcu(ZbgY@LK{c{5DPEU@d8Ic3C9;wR^f*ZJLOd{E~C6nz4T**n3(gP zG)@siHZI(9uGBJN$dgxH;v0n>%>_u~-Wh`n`0Yt zGa$A&NZRC|!{t&C!~~^{Sh0anSE50SD8U+Me>MB4gbirl`_+}ew^X4+T?t12a-Hof zb_Of3?7%P_ScLoD=v`G*C0K;}-c)LtaNzE|Knvsx!bJvz6qEjH$>W7Rrlz&P@edq9 z4h>u_VFSoH>{V1trijc1wZxj0)e`Dmq+RNZ?5CFw)DtL>6l~O-cKEt9l`oi9L2g%- z0Hj2b|H;ENONlxHYzSycn}aFhi3D^G_wfLJD*(jL0@5$tnRX8#nHz6s=h|k?hvIRX zO$dTDg~~7``3elL_JF*w#Be1-an0>EqB%0krC&@};9W7Kx3?ST-VTLDt% zYY23Fg5Ga#Tz%6#3#Hevgcz^KeG6J*dGqW{*Q_mXqb+ZWg0;9(ZLPT{lu|~2vpWV5 zJcn^IBwL-h#0iboGbGk|R#!K~P{ zu#^UTFc=+35AOt{OjPn3W1R+m)yGVc{a2d73(3|%sxpJm0M^L}rU@MIZh;du-FNk# zwibJyiHNspqMcNvkO_xJEs>~Kwwy*EXEHY!LqJRaRSwYD+ikO~gDT|%nb!U&@a1+9E z=pe%K;yP|Bt;1T|Iv`8g71rUT3thsXWGHJzOXbQpusm+^-QUVOoh=Y(HGLI~=fD6IKq5@?B`S+yG zdz=NE^TZrnPeOT3F<|}XBG%7&e`R{sG!_I(k81#L1`!TlOch*kPCe|a!^ODz6yf4$ zHi3f_iBNa6<7Ff?bi0;$MJE#}AVOCE2QW(LvOn5!W& zG?E|a_3d=Kb79Sn%ja@s2ka&aLg`@LkYT=VlJs!haO9yn37oa^5ecYI4B`L7V)7hL z&2%?1nvL@Fwh1s+w4khN!R0@KUPsa67yWz`gSK!ys<+Tm?1rOo=I(~z*%;6zLA65BDwE#tQ`K9@zb6SNfadsxg0z}4| z5{c|fVELGl2&Ru!bnB5uig1~8cy|gneJCv0t!^7BqB_d(?Ynbq}0R=vphD3k2(tXy|u7E|wN6h2kfeXk!Wi|4%!d9nb(zm8b z|2Lbo<=_B#jOSzgDU9biIM)!jFGqJJTe4!FNJz<8wfE1UXF|%$j>?Igsycg<)bQ z60^+c1Q5w@!7pLOGL~X{AN|DJ)HK2NooOW=AmCtYF$4Uw<+Wb;Y7@0t%*~+OIR}%H z@&L{@yM#GGBM#_D4MN@c5?opqr}eJVv`mZ8v}VJ!$PL-sCUFN6mF+oMB&1APeqydC z!m!_)X7f?oZp!XcIl`ed!bfZb#c8V6U^>93RxYY?R!jKBpF#&frRiEN=NW*3qN}Vz z9x>}<+5J`Rq83n60p3`p0;G7*Oo78)+l>vJ!%=4l)-NdwA3_YwWshmDW&q=jgx$Nn zvod=-N1Z}jcAv#YsbPj6tEFk21wVzp#+#&O_$N?S1FU)&*blVmqsVL?tfz;)`MHt)E3`_7`!jjwi&V}bG*P=d9z>?L%k`C*xQHbEqE_z*-Ivs_w`*AM-KFFI$9r6p}=m9NwG9P zv{A?c1Y5$}2l~!}J=y^cuCE7gJvF)lZ{2S=ctTPP66!fM{76D2529+TA=wS{>El}2 zUywy4xtPQXLMpJkYrC<5BW986vEZf4BI~Ryi>%IZQ5JO=Jv1|5nfz>zPrE#lb=Q}` znS=&fb^@nKvT97y11{5Q0{7UKXn`Wcl*gjjxUmFBX9Q6e7T{=X8^ltSg*WwG8b@9d zEil`7WURwPLAdp+Nt|ho$WG9*C|Ar?Q(V?tO3QLq5J|kStRR87tRA6oTi<1Ibz#t3cXkhH0gZ%g?$Zu(G`^M~I|A8pa4J2tbTBI_Dq7Q!S>6+(0cfpbm zw-zW=B_9qa=jY}qi?>WPwLeYl4{J!k1IOI=xI}dGobcRn5c6GtKG0EVzgi{&nyKqhMeKHP+`U2 z&`Ho|5xH;hPRn%r?6FLH4^J(eqC1q=MA8fT&P1a#iI30n*S2W!_8M(q9RLD21Untp zvb@*Fs9QLXK3tI!*6tztX#$IIA?YBS70@4$2gVBJ6az1}lt5&~7cB5nRDcO7hYO=F z_&VulZ|MscJE_yFEBfABcutnJ&|rX?Fq8Rl9Xb_aGuRh}0QOAp_<@s3C~+_IBp*be zTPHKQ{qCXqJNmB6*yw8Q7jYCLY*Dm`yQz#4YPO226v6)X64=dhE`WVO%q;D|JNnL) zkdLgwzi<5{N&A&h19b|Vsk!Zv250aitr+*^VPLsKCJ z7*TO~FuAYq98DoItRzh68AHI71Y7rj>9?4S)Gu!soOBg9DSkplorR8p9|(-dUF_VE zPKu7guMPA>v?xPOj+hV`Pq(+ZeIcwP+Zsopvc_KBk3`5oW=)%vL@fJt69d`dT6+L4 zD}aB1$@+YNP?Lw_#${#7J5m`#6Ys?^8q-|NEBCaU*TL0%+MIr4tbsk(k$>B~g3K)L z>Ar4UxN~3=(uU{sqlwSrrZjMtUDh8763WdE{sUWnjX;xUJ7|{J&W%1onH?MUByj^% zn_W$t)WL0VJZQ$?E8PWDIKeyyN;XY6|` z7iSAl_phe#l~$+EXzJV zm~E9&wiWKE+NXDv=3&BS+5%M^S-49!qWXOFm9s=eBU_=+&zbnF%pf`c=lUvP%|`IdIJlHb*dVe_4~l!lC58`fpco%N8G?zfLB^meOi^Km0r`w`kk-h z11W*4X#MW$#sFVPkS6t++S3%E`E6h}s?mUKSTr#9L{ix!Z?r+~Y_!qvjyWMpGin{%rQ5{NF5 z9={>V@(H5lB^klE2EeE!)gsRXF0SjXrFEIYR=KXt(DdnXGhdR@ji3g>Ih|VqKNxmL z-?HT<*skE~#0%ficL{mllD3A_C29g|E^N)+r6rgwu3Q50;yUyNnj=bHYS0^%Y@cK=UuKIueO(4SFe}({Cimf=n|r)i46zPE$7E&BR4_b#1URQdsAL0emU>w9qY< z`9{ZGZ(67s`ZN|}S}5fdl$V)+0+>Y69NOzsNHG*k3+1{nd~RJr!>vjXHTgh8#l;!xRk_N?&wzAL1#3Wy;&!8@@$JyZij>Uf~kxS~G<84{(T9JUGa;(Bf@t;bs1da#DL zPnajHgP14^Alb6SXMx@N(#_LI*ir@2OWMPm`mT`NH?9zPOa!(x(Q0o{r|Pi@uzx(I ziJ}h{Fq~S>cT%Egoc|}y3^Tpwgc3!I{@Fd<*tv6m)0pUuie#Qw@_;76;1m%MZ?=dm zdgx%z`z=#C(KF(tqagYSW1!PzCyd4=IDAYEIDv%G8@_WAMn7D@>2rzG|DG@!!SY!n zm8UjgG>-l`8~y1@7>)CI*yiyakuVx3eZ(gHR40ta@tqOo5=Ptf&O8&evey2Q~qqu;R^Q9}$f zlAZ=w!}a(bkT@Dw;AGp*uNE?JsY#^W4Jw3r2_PK zQ(oJR4V=SKXMoj_SM`DyyvIu!EjlS_J$fE$7i$(}_I8dsr(54Gefna^M&aXW%f>yc zkSqh|MLBVlsWv9WInT(5^Yawb1tXw7iuK5|+QWmd?>k9L3^g8X)8q)A7z+KD)wE&B zcw#7R&0=C`%y#v(iHzB<%1&Fuw9n=y*nfR$8 zT@L5d5Gp*ReDwsEe_P*~n66MXz`iC<)M+j)YGpszOloWP?Q#U>qqVeA07mo`@4CfqVN-nmq?sLrCbX zq+AA4kraFr@9#Ss%VVg-Lr)s2z(bQVpB+3QDFX@etQvkQBnTkWM_&9^ zL0%}Sb0K*V8@Rk!gpxs6A*kzItx8^4r)7Cz$(==cQAqAIpY*bL)}C&^5iQBHFVXfU zdGd0yK1rUDXel39KaL`R;=mNWzC>GqSJ`&BvG3H`^OEr2lQ=1m;CHVkTc)XnBu>f* zbD#7j+rqRZC3+;+Eq$lWp2M^k5Vy=eYmViTG(}n_n)(O5zBCF_TAGi1arF%Zc4i>2 z$|Ox!()v@|;R3ZOK{IzceM{7gwoWvKG7Ruof~FD>%_U2fiJoDqB2@{R(?Qv&O3>W0 zlmyK8mbaDg%;Hbn~OpM^U^z>uvrN$jJA*?xSjKS z;8kgLJ)Gcy6W`uknWq988z4Z_F~SKFAz^w6C2<^oBL*90w9(TML{6LWiyoL-V97ssHfqvlnl((DFd@A4%Jr3Z5rcf&_z=) znKouNT{%XFy6j=;&SOo)S}c_*nA~b7Ch}P4q`8bt@>dw9JsFvs#ZU^Vm^M{NGi2C435t5|W5B6Gd>TIQ>kl)1W?l)1H#e6+7LEz5Y>D%aIk%&i92ED-=1 z=pNIaq)gA$+#CzMAV)*qB}orkojddjtJ{)O)5<=*xAa|_k&tT#OwOba$dfaR>$|PA zJ`X2Ut#1pod%DCd)c~6U*~FZ!soYW^mWmr?24GaSlwQ=MPT$>kDS3a9wu(MDPtq(d z<(;Lan6$3kDx{+65VSd$KGG-i5T zZ;~eTYEBQinotP}n7XSQyLAFGO?4VL8r?55Ic3GP9@`deQIE^`I`6JbIR;gk0H%Xb za|0?s&EerWW)E4iX5UlMH_~~wlw{3d?*pzOX)_mg0o3|<%)V3rFg->=W6jRM*^e3k z%iK7cYlJ8>&&up2sCH7~9C9G5fFZH2=B{oW&|_5W7fM=oh6hoguK6*y%{($g7{N=t ztU=MAvAdMgwWl<$F{h2jhrn_;3nVaN%>#1FV9X(^j5xj`tBoZlEDH|_V^cUvRNoUy z^i1P|ydeO}(la3rhuZ@z>}U;n=toI#4vhTCPeZBU9KgcCgrsbzMZ7UB;)|vt8G9)$ zLP$R`B+nvourdt|AoYt60@sOpIp~`knV%PzmzX(%}PRhEUl{>a-0aGoIz={0^;h@w_E~zvhvBWj?xTOBsidx!* znG?MQ?@Fa^9x2cj1CgC>s&+RoDmqZ#F^TAij;PQ#hKnExu=%>7B}%_FRYeSOL_9vI zHuLoz-hweZRpM!i~h@z_u- zMdgnXAzTAomp|qJj7EHFX8M?D6~ubH)st1U69){X!>z{>CV?6(+0v&>qeN4up7vh*xV;;|Sp^&NhWCGos2pFtiI z=$RZo9|(2*$l1eW$qkHwq{+QGP0kq=Go4tQQ5c2Ek;NN(`I8W^oM9+3;r z7MxXJU7S&n(wvd{68O@r-ddWKuB!x9_NxvyYvUL28n?g%;&!~YFpJ|g@PW-D@O-DO zNFr99$8*r4v07m@TBh0Jx)zO6#%j7`dqWH&=~pu%_U-<@OQN~ZyKkE3wzO~B zGIR^C9~e~FH+-^vol}3)3O_{S*&hs1%Fn47k*Z; z0?BEl);`+sR|8?YPmU4W&avdb?F!wuso*k+fH=^tOBk>KCJ=$2O{3Xrz=1 zkgJG26#i!KuFS?P-$TaH5aBjs!eOIHt}0*-nb|~vDoq?aQ^~ne!gs2)t^=iYfgY>Z zHPRl+uWO_|tdBkGx})#9=njKoK{xbBZe6SUt&8t$GVOPk+V6<1lDRX3ru~wpxXrLL z3Y&FLX;C2a>O~FrE-L8rJ&U@x@1l&X3c2pn`pb~{YX4z4Fu_Q4-`0)#cu zH|)30kx=|-xO4SkG%(wzGb{w_)a0DcS+Q~8+v>VJ2WzVv1Jm6?3m1S_33#4htCMB1 z2)vwy$dT;3&_@dkCGq&JoW&Kd?z`gEzG4!PL?|jqaj8al{1e8$cv`#N(5*#GuOq2R zt7wPYxIDb#?+oJ|xy+QO49!w6PlcDm1w!MMq)JM07DA3vR3vZc#)bRsK~}8<%|c|h zs@a=L&9uQuxw<*MP};yxFLpT;F%-DDybXNp+hqe$E}Q!-V-9IO+UBr@Y3G0vEo=v0 z<@SJbO!Mh~2hhUX7?;1iZ7en`ZDV|)w2ddjR=!@?tf!2v#DPo8c|U{Hi>LkoFQ4Iz zh4+dMN(};I>Cah?7uHI}+dZsB&NAJXvrIc@VG@?-gwdJmoP~b|&H`OXC`V0*JV+=v zQ+=@+yt@82bG#xSnytP%E$Zgv2tiFDM-O&kl|OQCH?H5WK{GA=NDU1kK442??n}4^ zO?eTLH)SriFAY*e|GbyE$oy_9H7lV1o6`#=eEIu@k{XhXO@9G%P)JiENr*E%Jc7s- zm1n5VtLUZeBZI$DKp=UL$CdI>M4-h*6D@zSj5*{gCNdI}ffMhxSr(Hk4x%$eQ|NJD(DJHUlx74rXz28qf z@prG+D?g2I0v}Nm|MrRS1(X;lKj=*V{1go{`kv*xx3nC7c^SkZ=zJ<3;;j;i*3a!e ztMS@Tvooq)tVxuc@AOOWLHV>-LL(-Ew#HzeK_SN|DyDP@QWwLavqR)UlXj6groFfO z`dzv*9QTbM->{qdSc)p}b@DBLc7C&#rcC`iyLc|smGswcGb^WR0kMyzuGp2|0iZyA z=fEN;AS7VfUc-Wb1S9xiuzVqL^{oOTNL;nWZ3Ofwf^X`l0B(9~fd;);Fr}R!VM_rv zm6a_7qfSN96!jO;i?~AclERB-@eAS|3pfBLb(-zwJl<4BAlySuAO84;yZQ8^Km@!I<}^G1P6VL_ z?!kTWgZE4hUHOjR*>-f~j!$m5=gJ4Rz3F>C{VNY|m~Ri=b7kwFZ@c~W+y6)(+Cx`f z`RXhF?DW6?1m617=I7t~GcWs$z4fEFOx}9dD}LWT-15Wx`3rm)yk{Pc^fc(P4fotL z0dwAM0ZirCzhxJGZNoiq7PPMXzb}8?C4YC>U%liWgm{MLF}3--+s(W0?hAX|1a3Wr zbw1JmRlW%cpS=MzfuC6QO>?fF0Z@@IY%8%h!V(fPh389ev0ykWoG%Es(M z{{h;R6BTz)@sLIzWn^~&>O8dNb}}d2hW|wVFE4|;+AclJx?lbZ0OQxQWXA!V&3KWg z2A)Z(%Z7BvJfg$%`~DDLW-YML`Ysm6oNTHKIOOnK*Un%R1Y4XP@E#uk8_%Tm^6bGg zC<3V7;C+zhz-#a-9f0%;Hrs>IAd?y-@Mr(}MDvP<#Lf&b+>6Oo8Pu(;!Jv82c6^uy zBuDr4+c{-On+-N3rID1IOgC9D*cxu8#mt&m>jtFbdoxXn5pb|g$BCs+%5kXSP|Qx> zgWEqh2%_1FJ-Y!;|1gLT7*^lx&MnxK`F>(*8ltX|tqT36zS&*qJKvqz0}FI_0!w?o z4L_KcmLJhI`>Gu?;4FQ_X7+rR4r=eo+IzF-tNNyqXp?>H!h&CaUAwU>Kl%drQaQRT z{yuuABcIqoK*T8F-qMZa=XOqVi#^qhVD5i8MnH`-F#=$HfPWQQJyncgS(5^`;e8OR zvD4)-0xo!AMqqs}krA-Fg&Dz#Ev-Kz;D`$|f@O_Z$p{F7YDTaKzS!0j@arTPK_tHt zBe-pFNsg>Wk8S{6fHwuZE|9Ax&|edHV}SuEl$VZzGO1RF-d!BeP$skHqm+QjhI80% zosyjSZwlM-mF?T{Z4Ie1@+Hh>J8|3~gNu~akZHZ)9s6nqnPe2~cF^f4JxUFiYP{Je zknePrWBgFY_jCK97QP`>En1j5%c#L`tIFQ=+*6*zB9QQ=E<edyR zq_qT-2n%UJ2G_1$Gl>OlrhZ9fLKYb{N0?VgEoOufHYfT5B#;b)n$WvK#B7)-h!^NK z23C#Zqmylv6E}9_=KPUqn&xza(Q4KY+Ci1SxIwE(5S`jCxN4?UT-+wFf{{zRDj1<# z?Lttdbib05WaaxFk1*TXxkX$BF2D*XcCba4$4Y78(e)@m2nxx)gR8DWn-XDM_Y@Jv z{xE}ljC(2`QDW)eJYh@|@-vGQ#!P`QW-15+IaTZpH8698aX3#H^t%Sas7Q(>M)Ca| zVW@=@MpcWah%nkh`URbJtAfFr=v_%FpMKY*@h?7ATL>z|gKnC)4 zI~i2IzX%z`RV;%HVw(~fypIVWjb$c)BxwOju{ueLLfM)A(&E+vQ9K*3M!WIi#&kw! z;i_HW{7=-x6)6(@%9XYUKNzw1>t0vG`-WDR*Op?mq0d$7lfnY_X3=0&mKqI4_346X zaBnudTm7eRU^#VPkB2Zgt&)F#bpz}9BxDwCPx?e9+_=o{(e1Dkwbn2z`aofelH}m0 zq#Ii$J)U^N!~+dSC6l2!PkM@9o3%@sLmA}4)QBI;Xl5(+W?OQzZ)R9dZuVLdE*S9j zpi5g%e}yd*W3gc=u;kt2g4%nqXYIWvm@#%EJAH3S&dh|iDRz*KTC=cZ7Gvs`wx z$QRN}UCT5X0_N8)h=iNF5%-)H z-$`iQR%(;Xy5AmoYW+J0!t7mm$-fgz4qV*Wnj_RiRPOEBjB>WNw_6PLNyK#UU|W#- z&tF?6>=+5F-RQBaF%;%TO{UWDRsRa?I&Ky;nC#efV}&igt{bO)T^s1j(9LKXA1O$%bSGep2v7a<4OW_bB2pTM66q&nS%Y0e~4Ohdtl)ZDuu;8 zu-RAcLHMeA4{j>$f$5yEiz3{855#Wrd(g~wZ09{DVCh%d7BCwgQNF~-^r?r5+1^~) z%f!li6K1WwaeiI3HwL>_Fa9zHs)$k!c1^`6m@`#`T|fh>4TT8HG_e;g! z?E!XZi9<`0-oj7hc;4YrLrb@m-K+UN^QypZ*gw(r8Y@-__iax z`2Z4EF8-bL{x={!2>O#Dy@)f*AiZK6OU+rB^onhkLVCqEiS%xu+I}jfp2 zFu^#GK}JK~v4jDS_zk#FhJ=E&p=2JSFPm}-C;m(h59H(fg8HD@bA3nBzO_DjYT-kx6>OZ z!HXj8EQ1#n+bo3_727O@7ZuwiUZgCQaLS_B#)oc$!YcY<)+(>x#lfwp$aId^e!f%$ z;(Y}Mq8z~EsR+d5#gYlvc4HGid^yB)(zVUUdER<8ZGU?6HpNHd^rbO7eU7=3(f25$ z&m6f8T)sQWnC=E#+FReN2o>Bto9V!zC&+!*(VE2VVPV$$%vs4ra=_KeHjMsa_a#}m z6-90NW<0VFe-b~3>M+FZNe_ywjg)XGJ1_p7tj!zJJa&zGc$Ix2$iQC;C2|cYoSWtq zU7ehlxz?eQ+usR*`_m@f zXM4(1^U+N<6di8LQ~ytNd_b$tt(*MQ%VB1U-VwzLnbBP%;7EaBbKrtBaAN zi9Oxe?IGJzrtU-Y z^}a9l{s!Y#JO-tiL;|j!boSx@5om?TzS5z^-3~iXF6s!I<4zGu_ZyT>qogQaA9M{L zO-IhbZouTS!#A9!anb_zrv-eWE_Q2aONj$Vw52Q}t~Ao@W+j^w!dhc<4ux4IrJgaad)gc+!eCC?iVthGdb~^|Pt4 zY(rZ39mTm=GaSrYojv%bZ`ALiDj5 z$JzXSA4jT6yU;OhYw9i5@it^xb?6F!2xuT-k{zSKOX~QZV#fdqS+?U#r+;ycr;SlO z^yDy#*zKuh6tUYUg;B)bm&+)=dgJq*Ign8p0h`LTFr$bAo+3sO`+F)Fg$=d{qbSbk zNn#X*xtuyiQR?_qF^WRROJ)@R<6LMIV<()1MTO}*=|5;f@2S^3XqzjW3FYSuRsOTv z%AU`k_5>^copts(=bk$?wf4O8UvR;N-;1B=buYZ=;!7^o&-$5}%U<;27hnF8E3VkE zVOBq#EPLsdS6%h8mv7woidTG}e!l;eul#`@{GlJ(^r~0C`s%A+qn{uCkso>O<{$mh zANvnK{^S4gKmNr3vE?U!>ZkSdGe7&Y|LNzpZv8)h{uh4X7k}}W{;yw-8d>L9y=-;< zR)N|63SRFVYs3uC#+vX zWGL`|i9(A>!VE6|lD+&`gMQ>}T15?+2=a^Y(n6PF^Vc52d8v?8{0llNxwfeW^{l;{ z2b3mT*?+I8Df7;LK6HuLEme8;VR@x+*lPw`>DdoGZpG`Z?C-2Sk1PFL-}W$q)c$Al z?SEG7AGh{QBm0@Y?Z>_SPYHsUm1^>1f{!&qN_19dBq9qV{p46SS_Y$VFWiu@c+@yC20J^SWWi$ZwGxAx?>iiTCVLs7DN^GTWzO{H1`yAi+b)| z-H6U#vm{v#l2>yNWphmo1icENg6+r;hu=>$mbI^>AHLCpoCpY8AZAD2vn@=%cxc;y7qL>@{-`#s4yJBhW7?!{drhlH zWV!iJZd<_%RiXL6C-vtl#t*4Kvqhl!6RQy4yFculNn$vmiYogHfRsN7im?|S0X)W4 zHSd*Ftxad=w9@9i--iwgM|R}*zfRYiP9gxW{8L$npTP+33Vr=VE-$#@b`qrtOm}bkKE#$6>*i_?%y~ccU*JCtXp`{=C*+A%XF){Jw+l zS7iTeNz!^Us}}DD?|@pS?ogI>fUVnO?DntN>Mi$B}y*7A1+#C0uioc+sgKiO;8Qog^-+Ac==6 zNCF3uDoElBsXr%)nWd0Kg%$g|1mSvs&}iZz(ZuiZ;U$SEII)DXzgIxn?4cf_c(5-~ z`~kbY*v1l7e3=hkSVb0JE{qY#fvnt;C9BsXxbx3zvcw@ZJ;|<$veKToAG1u(0A$K0H5R1t*rU;?cs6Eg37m z#%|BcVZ~#7Fja*Wj}^u^l~@5s^)j*IcmlU$#W|+}EB-!p>sZ007g_c$m8riRslW;Z z8Y+0jKcxN~E6!R9R=|N@#EO69#+(_k;)t-~n|ufs9t0>SmayWRg&kY60R1O++sWX{c2@6B-8xFd8NpaTFt<1SghI;szgl**eu5 z*)6k)FqXu}oA?0HfHF$FsW8S#qeOc|R^_c6QKzHYh=6UO;!P8;mvNNz>^CQH|CN~l zRQ@4)5=9B9+2_CFK;OR;PzAN?T2n@7X9D%3H2s}@~^E|U5@Pk6&d-xEwcLM@* zVhMro@xhmk!1uCSW-$Z=zK;)(qhChg`wC;6JObwy@a_b?2kfYFN_m)n&XbY~+Bjhc zAe?bOS94$75Q-3nBNXG~r=5QKGx&1`uj9ad9Q4ZR=XrF?O~NgA_Sxs01GgN1)}BY- z9Gr90)9co~P(K%43=iG<^>EIacW%QhaL7WNodXq)w8I5Q8f>C^=Rk6#9h4*ODCJa# z=!jsZd|x{OqO4IxxZzevUxb`@SxqeytV;z~*F$Az0FYc#b<| zXcORbB7nJW1jSz(KYKBH?qw2F@*!+eS%esJMA88V-Y+`0H|PRmroo(^O`GSzy-Ho= z@yZiM-`k5|ksg5`$Et7J!mjNcNLU4Uwnx_ZXVRf+@WE&vi?zf z#0|}I8HU{p`&q}Tc^qvCQ8PWl)}0CxxHS zPM(yx;>A^3;XV@8KE#fx{BP9Ie6t{$;EX2aRk6cK&00QQ^!Tr1}4Zg-{T0I3V zmE8m_wF-}emO8g=7V*inX^vYg&=5CVqQq58&_Sd&a-h7d^CiY4nop%}9k+N-QPJ{7 zIlwfOlUcRp{X3~Y$1R>uUlg}0Ebk*^=5G36=Z*`xKF5bLf6R5wi6!j%Tw(8*j9m}2 zTb4lz==DWDfW=bAuP+wH;Nr;Ngk1;^<*_0cgINr}0%9PSaGA2>4->>4F;<-l#P~|; z))9l(9u*Pe@e0JKw!i-<_2-CTR@Nd+r^5dJf4DbDZ*s2lxDew{_z*T^U^|>xLX1Bt zY}%4tGJnQyS&bqf#-H;6l98PaQobbu!-#jiXNh^Fbf%jc? zDO^malA0+ct-uE=diYwYhh!n`<)wpzPf9WbY@HX^%+^66Y}M;W@+EH`RMBr5)q}y(;i)n@3atagdT5{MJf0;U&%+K-JX~qW7{iW} zGb)Y4d4c}RN(azeI~bG>`Ti?LiZ z{-GrF2nJY5ifF#?c16!YaR6n7(!qoZR|W6_(;vrG&{pbzi3Lt8LFg7AI;iPOrhb;W z=28DZ{Im=pb<4DWTVVt)jQNO>_LV@M69>v659&rm2DV|5SxNJCotU&z2QY>PJG6qB zXl#htD=!Y_@Fk|KLooDTw&ejyE=nfpnV6K$ zG!`tCS_VBtP>MRnf3&HLuFEa zs4xP7a+0JRI%p5>K-3;JGM!?@6oTbI3=K3|g`rlf<&HrJ;^kb1-I!hYKZxJ6qNg!b z63C6dV#_&wH_d5KUAUJn^^;$=I)TUCf>5w?cLXH^vPaHW5EN*+C2I3Esg0cO;j zc88gLCmI4TaFGu<9iwh6@%&l?P7m(jUFZN<0~of}Mk12e*x zmQ^@0tUQ%rwd9x7pog=sS(*wT;J|=Z!K_A9h8hZ)GE8hFkq-LN{%rcy=%1V#M*;8> z7Re^ylkpAY*x(iVjzDwSgug*wthi1%|CtW)EcQjd>sKGr`MDhTHrn{YAZR0;Tx>3a z_tjJZYM7{r9CQvS?|SDkAWwzGGWwhbdbmIe3|V%jT-_Akj~W5gIsQG&mHXf0L|)th zNr$KC!z_I8K_&3v5DORXxlSz>6{E+Jn@u7kiZ-&*E`8}h&C#8_qO+N;X3|gt-+%X* zQdFNMN|`PQ={?;zbr;e!+i}!Tlbi?FiZnTm$*~3!v;~zNXb)&sa5KPrG(QLdx*oqU z6%sL!-06^1MfIS88F9+YFX zU*eDsoC z=h(^$&7mi*fB_1I+3g9kJ?DTiVX5^Hn&n1!mKxbX;9vu?(dxoLca_?h1sJ?PRc+== zZIaFRyDX40@}$^&BtDQDA^|!@tRr`bbEWI%1EoFZIcpf;dLCn2u=UQN{nm%{juuF7 zE%(dr;36XH`03gvq99_;p=cO76vJi7t?6BB+s+PI^T<5@a(qK`Gxwx zc0@lA6joD#eZ{f&mBxl|7fKI@KZtsAJ4BxcL8j(9$683JSk}a_3K7D}Yv8t5MB$y^ zxJvA~l>*aU+ActO*r7nN`aNTv zwfF^b&Vgk2IE!O~x5}=i9$2p?_Mj=S{wxc>s7p@a96V5}hL!{=Ef#8PQFsY#E+l`` zuB2E8#Bu8X1B3b=Tn^BKKYSkShEkHw$H;DMQ;Ac4l{;mnxLOapITKHrK>@yOY zD6dhz#p8XHr%rRU zJX6dH2{=!j<86MN2CR*KtoFnNqxR%&I!c2T_F-^eDlj-k2%W)Y$L@cODcZPfGW-b@ zf^4tt1&4Sv;R5a{IAKBb@9M^$om(MDXpOVgJ5lK$9eZ!Qk8plaVpMA6Mdf))2;a z>fE%wJ;1QyfWnH~!SkV2;qqv(6>3#j0;#(J>=VYZHctFzzN)Y%c^mQ^F z=_<(O8*+X|)rHJ)FmM|_Am0;|{3X_jBGc0h04h<+4g$Jo2INa*dvOL79%Oqq17~~E zdUE`ZN)Y*7oBOyoyz7^kAux@w^2aeX!KXl(_{pzz?TJ_vWuwAWbLD(Vbn%gY@gE**lAA zPM_d?s8zR&HwyeKdCC(tbkh&sri)GE2%VK4c8JWT-+}S~y&o)F5KEewu)DSF!Y6FaCm($7t8ehrEaQ|jYyY+7tg56YD?zAgv1b?(~YgbT|oq0gI3{WWb)b-$^8_s~h(*a5p_0$kK1 zCxKx|OXP*SxN&=>fPEW81N)lBLsl7|yjwKA)2gG5!5ucLBYm{}+ zJMTyL)J4J34e#4RYpTcO>9KQ&0ArGyP}N8`*+6O_vr3W%WrmqeN1^hpvFs9DWP@*j zr%I?ZKUJ7~aJH?6VNd4z4Eq8%1#qI|-&!RsC>iad=_-c1fLctUAtx5aR@vx8$}9Sh zTc{C)y>pjGL)O&%V29I$dkemTb@ml+A)pX7e+BI=iAKFBHP&ETquZm>1@OVrjFTq& zrRP3Hnrx!gh5mw^_(9RJS@YC*qpT>L9}jkXI5s}*si_z7=w&#J?$zzZlIwY1rMsXRwhFdW^ejt3k-X46N z4+Ik=;E^;4p2H2<0IU&yDM7Qg`Jkt99!46cO7LHd$CNSK@C(WqQ^D-LBpG9b&coY> zgDS;D-0(NzU$L%R5}>zsBOcsn^?x{?u1O)-!K-7SQr^WWOK)pZeFn%d;caHBJcdh4 zIa8>!2RTLh68RhPLZ*>m`|$2VJx7g$YROsKEYrN+n&$Oe!%D??q2~3NX9+Q3MRb4M zAH=xe0+%68)h>hGsHGb z;Pa6Gjcte-Y18-{z7@SQgTIZ3Cs4jEf%2QC-&g`GuX~Dn%nQx<0XD0OZRvw{To4a) z610Pm5TtDr!8po_VYcVdFDv6i#GzEQ^92>G;=gd5F1D&u>rAQo99ORU@RZnndF@vK zb^w>rO&;!O|Vc{?cBh0}NRy7Lj{I`pY9opPd}^cPH>wYR-KJ zh?rH!ePJ2}_o~a^Nbx3hgkYxcS_q9QjuAeLyPiRFPKIzcB3qlErFeNgI_u1Pngc}L zsf`i_@q_VDOx&UFZ_`5=Zto&CB6B39c9L@xz3}fzi1fH25=?PmY}fBAJ`UDTjQtgm z7JmH~@MC<7v*TD76N1QZCmQn5!bTs=PDdFJ)1~ONl~Tu32LCyrhQsN^m*y>(u(U&I zY5!zPW7KI~?LQlHTlxyMx@SvozQZ(kGoG7zG><8X`$k>Ztfu_#g@hA7D~iT}b*UU<)LK#~XR92u7k1 zULO`h`2JW?aBBGSGVGlWfP7R1N+$V@n(KEZ>e@%v%>bU@@_S zX08J!i>d?XYnqK*+i_&jr^d4R1ASrd^pdnNdigl404JvRY%rD}#e~l;2By9>YGMu< zKjA2h-?NGFkAg1%QIb&mOxl|NXrz*LYh!ZZhq8wd@W?5WT^NP9Seg0` z_{M)V`AdI|{7UO;bHh~b!603Oq{or!N7FS(#-!;@;tS;7H2a=2CO;6eNt!`}3^`5` zXC;7P5)Q*O|9xrxe`oXOL6LQ}|LST6a<7zyi~N!%^j(fk1Cs|hnn4+*k*UiD6VyyG z?Mlt+4sX)+(X^;wG75=H*40g=c_1R2=CRGEVUFZ(m=)#Lq3j@Fz0kg48gAvKb-%eZ z9{cK9xBBkcN88r4O8#{igTqnisClI4(@}ilJM%U{f9DZ@>eI$kWy8|j-P<*lVQ@Cb z^Qed&2waL9F}|NK(!pEO+Wx`z)XsRE)LMKEL<1|~$4qqTGktPy?XWEm@`K40Ookt9_|CDRvSDngcDJsC zs2DgYQ2_z5rdA90*@yVJ<()nYC)=@{K2H9}3KBs{cE@Wj5!Tg?)Wsqj0hwCZT#JsH zlFMW{<%Bpgk%g|d{7cvpjetx;c+Bu9XbqmCUWw8TE*#%(W-iMZ5T&iF-E7xJD4m+y za)3grcZ<>K;m|5<^AW#oA_mCzbmL;bVFb$by(Mq+Q4AZm`4N5y+kA{4e4BA?LpdM5 z;XIs_XK8z`cvBY1L@-AH*r`QD4%e>^l`Sb;R4@eSgmLhS$By}hg1+#xGMoXcz)yf5 zu1i~w4d8c&uM?MGf>?q7`|EIHAsU@+XZ(g?e?|!KKyC%f8JPl4&Q3w==3c><&r~Vj z=(J@h##vDC_m_6f()gFC;Gg)e0aZ^e2*T3k0mTllK?0dEc9}ZS&J$1)ce*73;2#Zb z?SKG*=JHp!R_KFCgS>@v;sD_4yLDDd1={dH0n%T9FiZ<0K26=!rC=+c z=LkG7#tPz&_c(xeSGc5aOAB|GH2aTkXo*BO1GMZZg9jo$ zedP>DrSCc^snnQ#y8eSa{N-9cY0OL}guz#>T9w3N$QrYB*ce6&rI%56dFC=!UPcrR zVYCgio$RGAz4A)cU1s6s@B4mMT;7C=%U8eVhkpdP>6X`l6=loo>jgQBI=MJJxiV&R z99+o^4Q745)@bV?KFE7Ic6DPPZa%$MMEKB3Q2sa_*PsXrC^(EsoDZ&4q?-cyN36^F zVwZbLU2+v{%74{yZAbQKZ6`m@a~z~4g+J#9cVrJYc1mb)kRRqCSW<=j1DYSh9k#ue zC7y^)pwpFEeNUKun-nUIs%$phkml>ACQIRlnW_gHD#w5DHI{>;qb_X{f$dAZxe@v5 zp59O9MTqe?5-brTW{$}h=sDfU{eb`gGE$MkYsjl~#fN7oUXJfEF>qyjLlnd>UdAs% zX3F2NtE;Rl+^1o;Gb02!9SV*AnvFYnf&jKdNdg9+CPU?P<9jCO1tbzR>H36<>jO7%&`RH0O7?ooC^bGL7hoM}W}2`YgYi98>Uq0%<_Z z+NC$2TDK}JOyEs8Nr;{L%;+9+T)@JaAOGiUPPbMJ@RAF#6VYZKT|HSVZQ1v)8>n)|HtfCJ}jUYI#bK zs-DrE)qq`vHBxN@ENr>R3DVqf!_wkOL3)!Ot5{PDa0|Yo1huawsCg2TtgPxKFK{MG zMQvq3Vf`r`OGRmENA;eHQV9$?U+h?vwwHA?wbH-0x1%TsykcKJ#s)WZ!>5A8fb&YO;U zfJl&}!^F-?rK3^>-4HeZ0E0d*mE#3fkG1V^onv&V?5}&Yn@$n%Vrmw!vrK_Yb{0J? zNFw65c{__4yX)~(&vQ~em@rj#R&b3}+gaCjx@bx-FB2xCFZR z;=H@TAMv0$Fg%Hhxx^Q7f#%YoEeq2)d>Hn(SY?bd!fulu(1GG<3OF!%rE9E|-2 zW>H2U$>{RhRlOt>JvW3;u!P`XVrrrAxEeNZD#7N$CBcS%ma8~LnxX^|r^GNUpaRpM z4%9Ygi}N1EMKA@-vSV_ze1fxob7}VHEot^?+S!F<#Ml(yI_?lxKx|bi9@Fs_1j}* zN({|jX&G?a zFMSy{|DD^nPvQj8H0O?EN_Ir5E?pn-!~u8^v>dAU=Kj`lu*&gI51(0^V9p#kfzE?5 z8M7g^ocaIqjgyv1G1yV37@-CfkG^bi;Wa-{S~JzfrET5jKxMvlT>21F-nQ zKKV>%ztUnS2k|xxvh0rL&QJtm#hf383t(UpvVnn?4)glK*)FfW48I&2OWFD$=c>2< zLnSa+z;ZESjTlS@2Zp|`_A+udBJvJEW0)X#wB}nI4hd70=g~bdz5p#|6rGeaHj<7I z&yH3D-Q1q1e5F!cV0X;alKYzYv=Q)J3LqC&5`LouNXx-l3Lu?pAErIdsWH2SGm9v0 zq9C#V-%5ksmpjYG)VR>b|4wZ_mfEIPpwUOm{zgH| zre4;0JZaen@>=!pJ{&P(7TPO4x6IQ1G}b`(Pv2ot3V8lA)5Ad@>H;|w7ecg zX_0V^%m~u4G&(D~=kZQ3OwcseK{b;sV_vIsWzs(6l}WmrCb*?W;VeUeE~G6o-bybE zHsACvC|B3uQ-1Y%-77FqY;GjVYG!&%Y4yy4ig{`{umP&Uy=$2Ozr@6O+)ULzo(i>tC99U`suu6Cl1g+1!y9;$&k*bt|~5yunkZ zYsvtHqNR8x^Qa)WTUhh}e9P1=*EWxs9X5d}%kgBqA;?{d4`uZBAV*Lv2=N?pEMi5z zqqGFOE4*R}LKI&DRQD+2%nswEbqas5b0+3zS86XUocVZFVnXQNGI8nerAkU#qlHSy z(6c3k_05Or1?ZWFkG^EOxQ2+(PONIkFX-gLVQZQgXQ@PJVq_!nLC` zmsVN^Oh|jqNmc?`9K@Fg`ffKxXq5CMwBD%(7Djd!roA{!_oWFrOf7EZgK7dZIg3Bf z&RAUpYdl`lB6$d*5azovb?$LPdc&!e@!tcwJQGDbsMsjLMt>Q3LethB*2_q`dAC7M zMYHk5mVI-YnJ*i>5?pPuWpmyz8_CRl_2*;pOWcYcwIhcyu(99)5fH1f=GHV@#~Mo? z@!95(#xN#elVm8lc0`DS{18A!KcGuQkbF7TZ^W9u(>O1_$mARdv4@z zPk3pxvcLaDI!Zl@ZR^7ozg6Ih8D8ylQ+e#eMNGf88=E+$vkB4_P)8dFhcD;fhaKO= zYaWC;wFkViX@{E;SppRxk&Xd*zWh)f(KDp>b(oZinSvztU~{R@(Jlywml<~0Ac~2X zH}7Kd2|2RPWg~1}&n$FHwxKYyo;5UjyTz;s6f5Qx&QJKys$HPT%iFCT2!ZM7H9Z(D z9=(Q73lj`Ou@n*JwQIMy5)!Rujkgcns z05}u*TR8R;%RtP)3H^b8dmc1E#sv_*{y0D2b)qj-YcPgw_~n)W5PS=}dUqYJENVZj zM8v>00K4D)-S`t{)>KK6`~@*>ehaG$8W6ui)i+ugh;NHoMQ%^&pEoP?@{;YwTN0i) z-{Am}??^kVV7Ee$e!~}fqVRV!yL=AVDAyE3N7f?2$Z7#H2{WVu2_Cr8w0hf@2@h>I4GO!0`E0j`=FJ{rJb*rd!qU#fW9B)WilyCCTH2YX zdTF+MIBCqg^DI9^NMI{8-bBLf8@R90M*?vx!B->39%C=fyc&|oREmMsSXGzkVsdE;+k zeGDDw@KgJgt?xah_2E!=!qerikAVLKwWAXvZ?Q3e2lyKf*NVjD;pMlg3q(uX${ zh`Ap~!t-j7e5eGH9_Pk_AaTCE$)uE&WI~1v8*!vYDU6VUON=uaLL&RVV5eqO~Dlh{RsRrgpO29-2 zDG}4+z+^B6BSR_98Li# zlt1sTjc(Ot5JACckCCE1P0%DQvIg5D!f*;59yW8KLmd%fxS*8cH?zBCL7taMR`o!M`S2_HWdi)7fhyb4mZ;hxWRYvJh{qlO3?W?J1a%CFJ8nV zrw1$%)hOe0*bqoUWiq>^;Zn`;VurIB3UiN2onT6nl_$KUadFtG0h-Kf@eR}|GzUOt zkbsU=40Y(#W-`dS+C?xp**Cwzn)bj1iCx(F3xGy2bKc~alW%9Z|z31e` zoCwmC{kyi=<{z_G`5k|Q(kp0;K^oS-qkRlGGK(3TJWTfkFhF!i)S<*1$Oc#sd7wR< z4eV4NJ2UYm_@PomMIs6fkKb7u@z+WX zQ#j(kjXsI|9GslhPQ50$mq=tjK`eA?X}nex!zzRG&I7=)4;$ZIVB=(~oukIav(vfh z*N|y5hv{5w8$NH5Q;HD_r7l9(D)8#v-Poxk6UWDUiC5d7#G|7Xc%)HY2U0&w9s-uV zUZ^vSAz_MV>z!p|Dpf3d>-OvwWZC5KlNva=NsMJ*6Ik}I@7s-x%N)zz7+Cgtv21$Y zCUPvBEd2STRp>8ymc5?5nhamRYD;0+Z%ROV!YI>H2B9Cv)2$$C{w?jd$g*kc$)bgB zl|6HN_AIe%`mvDkC&4sJPEErer98llumRxIirCFM!=_ctGxFrb9xlX-&8R&r^a z?rxGj(|ttd3u`5^XENl(g87D`(vexydP}UEVKuU6=gX85rx{=7pX1z{Mu&f{@|i%T zZV!+dTOszyg`NFU&qS;@$9^~G+3!;M?llFz`>wRR&UYERDwE26={+YEe@}dOGq%6Y zW*ZaVt)dt3T;sbed4aG||*HWC`nPQ)cnn{RD%GW8hd@u$V|8?bdF*!xWGq zy3(K|DeatWZ9Q-SW`36n7c?08PqG1MQH%jl5x*4U!^7Wc;%^*pfV|dM;lY0LLb+}w?j zbh>$gy(hYvc8dVjrrDU6O))-!v@eCYeU3OGyd&yV?H zwp%Z75>2cg^;W4Ek7jeb&Wx!c@D>cK&828VU-U?O6su5Kv4PMZ?JQUqXpieA!C%oG zuBh;Cht;25O9W)V5lnJphLCYikMv5d1)d?TBR7iSBsE9YtAYUm zxNsB|J%wn)sXBN9R!3Aau-N3GajV31qb>-sS#77dRJ5&=tHG8mZD)Rm$_SB(XW*nMTZ!a8?%w!9~VpC ze5BOIawBryq4Gct6Um7GK8?jtC-U06#Ce!b(SEFTE1@(8v0C zV?iFi46k-_$pibDJkTM1Uq!59usN$qHK+Y?r9InU|5exuKmvY^qFi1mh;O`9xQH)2 zCaruL-5%DIZB7AEcCQ3i3ytdVH~rS3Akzf?wnUypJlA#OTE1oaJhK|Gma>`5iOv_Z zBIZ(imuMYR<8f)Y3BF9U@i;diih(pQGju#d3bEe8@D-4*sCG?#;f?l0_jyKzMWuD0j}gD%CW;HCJ5(YIaEi0lL(w>ZUfD10>E zOxpF^OQZ3CY;iQCv=m39#fbhkE^D+qN~1yF>lrP&{IIAvB=+l)#tcorOB$D3vgUfI z2GAfcMdk)Au1f{s#M~By@SSNEZn?6#*6fxmcOT)$IDrC$bK@)y;kTDYyQE?? z3lLt`Xm^!H8ZjNf#+bX00Vi70pgt+9si%4awVwPC*1lZs=? zh*fqBY>g}~$oIuq+`AKSoW*gNzASF8$l~6c+B=IoUu&JKC&!Tg-R{#bK?wkW7mn;f zL}|o$A**oI+GFNahI-i^p}~*O6D#mx6e(Iz+Tyd7_<(1ObH-;Q_<(1KAIm_YbA{Fb zuf{!uL<*|D=hC!6!l%7)5uWH^iHrq)qB0MNGiM6k3BEZ(R*FH`H}li{mJHV2fTj*d z36=sADeuFA@UplTRejtjhasB^n8BZq%rfyrS`O61tvU^cvNxVbB(guh$2-U6qn3;2 zNo({#!wekO8hOB+iuQn3z)w`6;|hRXEcihe{0d43_$BO;kHf?-D#(Kvy4CqOKjLc;4=*@#{dTePu2E1aCR+ z6T%NQTmIPHU^%Z&yrkYzVb3|2Kb8-R#rM%)_ZRe6<`8z;DtS?_iv!PQ-CO_qtIaM{ zEpsG5g##8&`(sn4rr}J`YszB5*E8X3$P#>lk`%s%Q~?e{V+#*pS`!7rohwNEP~gfO zu2lHwQ9+w2yp^Y{8@qAxPB6?n#CwSuPeH970Z(Bb+4&?kx{bK! ziq`&VdXN6c@CI;?8KY~RKZGyfuIzs9*ZvlYp-gT%XAt)VstzdqR9+Ol@Tx=X{}tfi zn44yo6X!uCTmil@=!z8eH0XEWA&0UvDBHwO4#7k2ZXXloSM)w|djcmhS$aB6V zJBMK~%06pRQ-v@bvO{%ElQ(KyUG}hhv?|YvE$51{{33oo`dEv zQa0Oy$DTiu+PEh|2abAtKc@4gaXwmV!+ft%In=@-|CVJ!8*NV_4jnZIx_nyM7jFO1 z*H-Mz&ZK+P?m|~-x&UK3B%upwchE7akYQWt>0U9`(VbF)E8hwT1{Do&kLwnymfWW5Qwo~24AYaPZA^C<$PD(Cw&pWwYn;4?#yaFK;)y}2=kUc% z{cLLa?%bLA9z?Lab<${`Pi;ztuLey z?jx^nEy(M2q{F)h;AWjP(#A^l%X(rSA(c;Q?mw zIFSxGQNqOyvLwT{FLJcXE8a#F{~3jv5ovgGEQ|*mD*U;!y`rsJph42Z5+iS189NrQ zrXvbDU+C6GYp;-)XV?i=6+lHzxS<57bMY253`T??_3>vguow%XNd=hzC4#=ZGo?i6 zPfQNkH4;tF!8bINkVwKj1x7$8*en}}5oTti&|oqpg>RTFqgdg06k7HjKT%jQaOHCc zaG3zaVb)MXu|J=~x$taJSfN>MESYH{hJEuBg#~&8khI^^?IG2^Ci4Kxg1%z`Zv;q2 zK)|woSi>0zHz-&Xl(zX29zm|~vZvKJ>faDR&cUdZ5n*bR2&0A275+x>ibs?NEqDbN zAZO>RNYN?AgcxOD*TcX#yH9GQH!Ow3bL}gwV@en>cj`3MRN~;x5Itffh#?5;amaf_ z+>7GDIySWd=!8?zlnp#pGCtN}L}(S6^PrH6;cA*x))C|krpPh~_+GQ2vzVv1@q`ey zEOWjNG$xs?=AR(Fg^8}0uUiIbVv_Go+u#zGGO5n%?ZCRtpNN$ay1N_a^FCAfVIZ4v;9g8Q%J?^q%is$h6a_jB?ZM!e&FywcAIg}|WWVEnP)Ap)$K<}RNBpcjQ=zF@iw{TFpTAA#zh-2G-HpTO>ld(!kv+Q|NW5_l*uE`b|8agc8ytIGW&PM44gx?nyeHocrnsrMr-1p@ zJr(>@N6V;xa{^-t^*>A0@6Y5Kv*rIl0?#1{G*D2rHNXq2SyNSUQ~H$vraqi-zCa2* zI0PSFB!w*y&XQ#$2ia~+ryrI0<0HsXZRi%Sm&cqO9nV3$3W!WJU~Z({t^6!}33-`) z^P9j!JSI=2SDE{1l^xKA0Y2QxOld7Uiyj#obueu8nfe~cM)F@=8J8Ie4Ya{Q8a>Y4 zHhG5SRPAZHEFBTr_HnC!oQi>0JN#b^!tU=z(E8zj(urL*;RI)yrNUZ(u22z|t{u0QG(TW~=v2&PUxbC+7PiIC)itrbIU) zy#uVXu@PVEj2MoPS);S@^yR4$OxRSQ;wrrCg+G3;K5416w2_$x#SSE?&%}e5vI7=W zVFJ*{YtZZPFAq(?<$#?tcPO+3seuof#HWLU7j~fCLBwJB`ym$RWL#+$k3%XC1ktQ1 ztOvvS|0D|~%dM$PY%)R9W|cTmaoyG1x)Ddc%m;^yS~%tyHD#%{Q_`9zk-pn*Fx3Ll zFjIIo+6gMy>Yj4Md$uX0IbSUZMSOf(oHF_)s>I5I;N2w;>f6)gyqe$@nw(DmV(0?_ z2FG|%m~-&~9`nyZt3Qs9ZSeya7PTTSEDT(^Fkocb0W3!!l2&t1 znxo5r%ZQQ-H@dgfh`H^HG`cS}au3cWY7}r4;4M$@V5!kXY83L(DjU70)Cl=LhL~WY zmh5^~0S@m=ZQKcu1fYPhs2JGRRi0pDs0XCP5RpEEQ*;2sirY0g>`aZt&(Ft0yQV~} z3e)82Pga>Xrp8GBd1I6_Cc}m~1!;1TchHCy<@CECVxkF1i?S8vnNd`089m-t?MkJ&whU{?VTfu<-6yp z>_{=+{o&NeH=NGqMKJ4&sgaMQT%B06ikMXz>1b-?BhgS^1o3}AHS&?nVZ5Me_@&gy zM>3CbK6|}HEq|CA`ABAjnhV=NURu*5sgaK)mvO2Zoz-PE`F#a7`8>ScIgpCjL6w4VKUm+vU%1EwblC(lixX1OVq}n+ z%M*>xFrJeWMpZ{Jx8`E=?7%*5XH_2vUdlJ5KAZMbwDfm(LK}q`a8mK zg&~79P5OxD9Wx%FZ$vO9E#QVU3D*d%F7|Zvmqv|Hs?d}@#{^mbhqa;@ruBP}WtAj# zmTpZRw1q>B|7`RVvAE=wpP)z~MP0c92&W;a1brLq3n%l#>8LZ&o*Y~Bj;v#5N~0&T z4D>N5!8(+6!FaOvo~*r>dA~F}km{1LP99kxuNWf>+=5@&D7>upL2P>Rb%Mvu2_AoJ zp$hgOY`M6>&{xC;Q-rq|HhMWYPfMQTZ4(U$eXR5UXYWnmwW_YO@%v8qUZ;di{cOx| zAtoV14JM}HYtw{#+9oDVTbuT4>}-dmX*#9(+B8iydEs8*GG9iSCz%mN1Ox}X-~@_@ z3JQvNQ9x8wP*gyW|MRT9&RP3C=RJpeh^_s8|J?mk-gm$2oU@*_*Is+=wb$OK>ROW{ z=%rXGb*c6(;Ec9D%+U%?o^tu7{DJ13XHapM6kk8X-ErKsTdQHAVTw1mQ|Yt`z$AmG z&COhyXaXScG*n*G+(ZJ5$^>^CK&EUGupwIzFy&Hpry;+2;)hK6^%cA(Zzj@)V$r&Aia)g#C8GAo%(@f=2+s}vG_j}_970)r=2fKrc-6~LDwM!ljQDB{AQFCE)_`mP6 zPcgL6e2#3TX<~1yv9Da!cLRCYnKBTaM%MFXD5xu6r*lEgPPdSsqs z0C9P{p+01ohn6rcRy!eiW53Zp_-*~FUGO{d)vR}?$wPZ!jYfNMBQ{t~C*%^BOxNB6 z3@%Z^XE(H9Y@)EaPTxM`j2~?ucJ|1c2?J`)Jl;5#ab6XAFrf@&Q8i>r7OX<9WWmj` zRd;#Sol3pxm(fcaQ}Z{91AboO5`e9kS8&FH>$+IhmA3=*>h&)E@qL-$IXiXI4-=95 z0f^mW8*DOk|EF@-~0Q2_{V?x=kNc^5B~4J z{@V}#{YU@tVPzbYYB^&cfIN zG)^Zxy^<52l`+dUp5(2a;f%*EnFbA#iE>GCInJ5J-#fWO3Wj5)96PO5Ek*8+XXf0v z0zATEu&W`g01vop=;L18uqupN(_VDSk8*GEl!K~FtC#^a20tOct|W7*QRIxaXL&)m zX^qxfhgKsL!`-+mv@+k~J9e=~O^aIMYcOftI9S5arlV_%JgJR!0YsXmWy#VHoGjcXWu4b4QCAC{F< zEOi|2Oc{sk$ajn}sPY|55rpzx2!YYhY8QcB+^{-aBVxi{8!ENc+(Zaj2d7TKf#lSg z1cN{jbS*f*eObue2|v1QD>B2y3hWcXSxZn$Tu|k+>$Vz~DDbQN%+?|qTTc=QefXR`rSz7t1>?#U+WgZi*6ak2|Cy6V*WKO{y%I}e zK2H$B!+;un2Bf+j{2BxDgq!&ONPsv8x(|{7CGO3P&wmds4JOr85-jUrV~TW0p`ri$ zL#HBM$1ckGSpQm2MM80_Z|3*w$PuU?zF25ntBUXeQOH8Nbw6*RrLTrH$OXo7Zz2m> zF)+bh3B=^hW_drP9;#fGN0&6y8rjFi#)!^oe;|yAp}-wG!o@2w7N`j4onkNW-Az%^ z{pz~zp*sXc)t0nJFSSQ&4#4-F@SQOhYwqjJ_~U>%CG%<;GNnmhzlr^z*5 zkQTyNX>hg4`GB4^dDzHMI5s_)U<@PKa z*Yaypa$IisYfo|_Q;dMz1NfJ3t<-KdmQ`weKu>Hb!Y#GZO6@4YwV6`8)mTue{e{To zM^0)Qx-qH!S&G!ScJybS)O>wgPsRR|w^npr#+$|q*V;gW!HX*-;q>;@8|LRv;6*l@VykY&|Q$7%zq%ipAz3vDv(wJ zHQC-_hB9hHB3Up$u1&GalgZh zoSy+dMTZ*PK-ToW!5hf0Hu6QIMt<}1kcnDbn-Az&Yxmf^%*$-;ZN`GOHqu{!@Vg1~ z;*3ru_y8QY5wtXyx<~-m54bh=8zgW-^#^F#hc1~fDpXL3xt9IsNPS5PG-HT9jlJG! zXjGtlKxBEqSFLdUA-czwXLY7PA2$|MpuY|lE-8K^RiNiWpo1yURuG0F^anjTU!>LP zB}6CE6+gI}O8w<}B0TdU?@8ldMaTz4A`~x2LmVPbUxYojK-n?-J;s8H(4AQHBaO;& z79p=e=wZzMX^Kg*Z8&U-_{8$>V?9q1qSzy+32slkONai`>0R`_#=1(+ol>NJVTSag zI5z{|Hj!{~dqG@3W`BSn`cpaHx}g0t2^3%Gkq)E;?c1o_Ja4C-az9W0aquL6^*s1e z>kIrLeDze6k5#92d>8&S_TgXxSk0@aGMXpyOhUVx?$52rv=1*D3#!~WP!rhGJQKI? zG&xuurg$!@Bez%h0}t?V5`9Yss+WyvRck)rEj9|*Wy z5Iam-+F&?V!z_m=xVjTa=8&`An5l|sa^y03?;#dO-wQ`yr6MB>7WA{FGKTQDXwNOt zy26iL#p&`G&I??g8RT)}SX$^2sk_b~IPVn_7j@cf{m@CBtyf_#^^h z8XMqVgQU9O$RYq_xP?uSQUySjS>r-Fgf7_E{S);{wI5MzaBwwxuI3au{X$QTHp-y~GrtHy zds^le39NA=pe}H?xE%%fsV|1ma9aU3Yw)B}nO!p#j(H;CX#l~glO?t)ld#S^r?rTG z&b40=&t=LHe&>3#=o{w$%%tVA4D}1AQSr<*t{$E3E{B#CgKh~5glo`PXNbNdoq`WR zIt5Gyw`vEvzp7uoh~`^LqDdlk9~8|SXfG*RF`pJa9cPV`NO_oW!GCd9Wl=Txt^XH& zes*iTi^J`Z~xBkUMAb2(9|i(9Jj_g8Uj-O`2+oU z{=lz5TNsI=QcEr$RR7|J{+vZ(IiV<#XRc7X=+wultW54;aH=(%h9~#x z$7aqc-A;d9SzQ*~X-XNYpN^$ln}KC$eiIWF3Gar z@K`O0b;;oujKqB&HNR_c3$QFe-p^&Dvq!s)Kz)%3k8`k!I6?`VZi1&=(g&B_7zHZ^ zUl7y4J;T2(-}_K5v=rZvuOcRX{Vj;4pKeR$X`^ybfuZ!?A&t@(LuR4x; zqXKWOK*bT^s0H7-e}@Fr2y)o}9O3H=cp;p3R~#T*3|;BVY>_gVZ_*55E^E(Urd9vssTzhUkn*Igtz2I3Tki_*V@pW#&E zzeagS->2TjmJZJG1cYrl#bCb^NI&2};(2hc_xs2B`-|>(p523aYH+sqJ7$h-wy0UL zgC;o7`yFR1y?yrTZF_QPjiVDIJ!?!eh|N7Ph|Vs{kN__SJ1X6gfS#F-EHlk?v@?!o zTEEmY({Ru@%IIy>6X+*j%@bHtjYchX({MT?I7)ZZ`iXJiY8^Ky>2MRBo-P2LYXX3D z;ABXmYb4x2OX7P8ISxgWx;y~iK8=ECoxdAxy@<>8R+FoGSV+*1q!k_@N@=yoHsVkT z!U?SiC7ku<5lWcXi}#n}2%~l$U}Cq0ffa7C3TFK@Ov}Ut?wvMrYVrGkt0`CvRYszJcm<}yO~LKa6-qBV#JJb0 zi7!y|$nl0PY!}3TaHN}<_QR8*dx3?wvFB2KvFVlj<`|!V+J>h*V$=>zzMQ8lGY~i~ zjh?+b7g7%2tteTq03}O*oOa-_-Fiu`vO>ja2(nt`W=ss@n0eOQDF_#<0OZn;mU6p0 zlg`b)o}g}UY7Oy7BnQfbu??GARH0-7F1!94-}bg-fQlO~)%u992|m%0T_}np^pgZs z1|aVJ#(qL5q-%iU+t>gu#daW%NUPLIvBjLH;^sUsFDVm~uGqwcxy$w@UE1Z#YDbAM zQ5+NW@JOU+Vn3)F-ENpmie%sfy@kgZ@&gXx^P^N;WOd4I}Fem?uT&s~Cd{L~ys z^0VhON8N%=``hIKQ2j`ktJOPWT?4tM>>FX4@+V3=kopzne=zBk+Pqb^YEj)=@P6Fi z6h~{TY*>Wq)0dfzD)njP78o57NoE)uL2c(Wgv!S-wtLC0@io}^dZm4ou?rO$WkxwkDsbk=IC<}vKhZ0yUNy+T+S zabowrl-7~N`tP`u55^no#LTH2WTk`2p<%FeD2X)_6gq(bDXt2AdiPB1)RS5?l`gHc z4&+rx4Td7(w$@ZTyb|By&ublYD z`sxQr;pRtsKZIpGchz& zhc{U9T@j3kKBf>}r@_x|7`DE$!Z>}(N5Z7b^@L)FGY`b&rQb6=dIcI7 zfkMId=L{&AUePO=c?SQ&-w`3F);KfB{w2-97fs8_%OJMCC{lso zW!@hhup?bF?1}7_Q7>k<)GrvP>Mb*<2%rp-!;IK59a;QW#t;aRd=u=Z+SSreVBU&B zu{zPUNcAT}9l~v|MsKJ$4 z=kNYcFmmZ`>VKb|LKFCla!N4V`VyA5m$}sNl*u<%162CjGBEsm$TXG(l4AGVOxIQ> z_Q;C?E0L`;#=DJi6+0ggiCsk9-&?8f>psg_5D>^3DjJ?H2fzW6ZKA2hH_@12*^!_e z-xVf}m8XmqP2=Gk9&th~TQSziqFb(!!xY6eJVQ^~m8p@k8Bs*%D=>a=K0h4<3Bqv! z#J40B_b`~_RxuZs{7rnLt@@XSBNy62}J3wxiI~Y7$l<}uPYro zsj-fB$i$~x#y-V%_peKAGkZC44Hm}GWTD*ftk4&Wf(l3M8V&tpv8?tv?5Mi;ExPPA zyG+@`8ro?db=0oWM}4H;qY|PxZrACvdY|@LC+r%1maPBy;v=lYv);7p^jRMi9>d;~ z)?C$rQEW!9lQ(v`XNV8q#yK<3lMDN9*gNCSH(cvFemCF0_0~DvQO`}o({6ZFelF4R zbaEJC*Qp%1;*za`9d?aAi>od*s$RFPhTC=eET(-))*V-7;F=Y#l%=Hc6g}5H5bU=U zJtp|U5R0?d=d9p7aX)2?4p%*}-h)LSB<8u7x{Tv3xY{9ZCo^Er`eMUZVoW*{=q4R5 zKr7}h>VNe|_pt^;M|XE#j=G!8R2UuI#r5nPjr27B7)wNtopY%1pzp)Q!XWyU-b@Gs z6gffz3^%wfNRUpg9S^5&_3ZcrV^8fkFR!)T@V1yHC;r`KZUV*god!~9lBgISg++C9 zgN9kUN%nx6M8(so+GM*7VtIrb>TfQM+!fd z!&+Pz)*?kk@6m(+Bo}ATYGnr2rC^>sU%|II=)&=C$=6{T6DDZEoI*=cvcP#3olMR| zx7}rW#WDnS+@!Ksy%2_65av>5P-qflJqo;bOiUGn*Gyx=Tc6PukCix2MbebqRw-J@3@JIYlO<{73Wyw;H^nq5tcHsmD{@w!NQrrXNSK0Y z$57#NtD(G6`ZiOt#e1g^9dCFo9!@_L3uEaIs8Md5lGxo$>;jY9r^bDal(w4HBxi=~>lwF098r`D#%07H6 z8mC(_UFSi?c+YtxY$h{kI=-CROXm;2VnlbA1$$4BaOXaMfPO(UHB@#)GxMdH9Ro*Q z$^&H5MQ_gC6mOPe)~7ZrHC--yzg&in5nd*fIr@7ZHQvb<(o1FwHe|q3Ra)f)Ww*nF zJwUUv>*)nFOk^V240Nraji%u4JVKchzZbuiJq>qngOjb|E~iDbTON#8^WaQk#{|;e zv2#ZByPNigX)RRnr}zb1CICi+BB3n0RCwbY9WAHiXQtiG`!G%2pU{TL@rrsx{F>(z z*PI3BVA?&cbG^f!^J3zfrqfl4Ad`Q9-6 z`_Qxx)hNWf?@h-eK#-< zNvgx($OMD#Ks#gb9m?Q>!#vj1P4QD1g>WIi@dKW9xXgJWY1Qk388Q@9YC z*xD=~S{twfq~V;_!Z|z2Xw06xFAhz59vW2Mf#Qx+OK;7svDQQBQr z@j(<_;@*7Z+3t~iQZF|{AY;AU^o1YK=M1K1Gz$AJXC?7T!;r*N*&z~7Z8o4S?x|#; z#h%*N&6`-;SA_%%?bOvR-<>PU0@gxyY!2gQdTt(XW@Wgs_JR`#r$8ZVu%)~sbge-> z0nF_}PoT~_44r0O-w4er^(dPMy7d8A3;gN4!o6pQlZvy>W||9_NiiJTVyYH@C*h^B z*RKw$Mpx)-e0c>Aj_xP^9eO&xK(zh1Z-8b2BL;B01LUyRNrc*$!Vw{;t=7pdCbquJ zqrfB8A+CfYjgvQ;MG1NLQ09HGyd55Y*OyXvr{B>GP%UfOqz5iz2XXY0lxMQhFXF~p zdaOP5WRpAA z4Xcw=S!K_tdsHWef!bGh&Yqb#+kcv|lsIjF-|5HI;sA7&_ch30O;_RhmZ^PYN34%f z&%FJKd~GX72Hmh245~&KsMvS`U+3y|k^X)cfv*#F5!y5=Ukml5FYSbO5qzdq&(}pF zPPB{o7Srz{&^W(~&?%BG60ymtGje3Xn;_}s7UK-`SOZ;ky;0h^Uvk{+Ni$EdyZ!ey z^RB$j99{6XH*>_ve|WH$j{cy(cKcw{CkDMPibF^16a^)3k}RLOc}m8_+U)HvbVgy3YfxhuPZa54XQ?$jB}YId<}xQ zeasNyXoqCj&%laxufPnXL4V^v;c=99vo^cgu7Y?A*uBoi5>t+QUEI)u*Vw^R;$(zN z8L0V;CbhB(b8%rZrUygpzN!b9#ETll;dB_~EC+}FT0P*yj8cJf+Hr=!huh5*IDJrY z&M=6D=tavQRVRXQ&$}lAR!JZL?SzYD7U9XAZh5GqbP?;e!Kef)Zl;Tp?_^y6x88t`z-?R6^sAd+!dV}8HH0&i{`JOicX8C`d2#f` zZHaKf^Ewwh3$Q=Uc8ak-r$PS2deUg6nEgYs-c9jE>lXFQXLNyfn%fXGE&D z)A_z;JNbqHHc2t)SmXA&GbxO<&Z0Vr(?`bcVM@Ej6SnWz_3K#x+}yxO(7ZA|aOmW` z@jX2ZP?()P(@z-nE^BZh4tW-oRPzxQ9jtrj2p@P|L#!oS|V z`}Dy(U@w$4u1|jQlUU(OZ~P;%#{Uc(|3LT-aW?ArV~skf8eO9%?jl^{85A`l*lrWM zvdykkdq&1;4Y|ZUcr?PNX|yB5L?Z>t=+r!U#wV~TAohsC_J~QYBYz6FkvTxrksMvbBN1Xce}lF>SX8fKI_YJ4Jva=1~dNc#%cKuzvs zxYRu*08SucS-;rug`Nq1gxy~S|8cp$lSKH8a3GN;=#3`$Sl9%YBG0{cdN$hbs8aaY zIfbYX_b$;Ogo6s(E?oEk``Yo$_)fBWZF27LM?>xaRk-1sf-cnd0J}XH!jjrI#U8WU zxe+{sEF7;AQHQBUt_ZQYefj7k1uh@DTvcwY;mgX3qMMgO6Yl)WAE=Dsys_4ijsrzIZ5) zDRT|QZI5zt0~U^?p|DxYv~h{vI%+6H@3FGlOpRtI4`&Fj(c+H8^~TsePM2L8&+H}V z#UQLON`>HD^sDXF1+5zwF{pY@4~X9 zgmHT(L^}Shl0pIZR&-;4FTlI?hLLUn3{uCr772q)abvYxw(BuM85hrK2d|CBul8;i z=(OHVZxS{?>~n4y_(G{at86Hv1Ikn6DC(HjZL&wG&rNTS+jxN%oz&sDjIR*l_H>@F zh@@eHfd$87!dp8&>OEnLJwe@Z=Sol3ZE5|5qh-Nt{q8nHEejUOcd+1G-UAKw9cH;r zIGV^kLT_7cpj#~KUF|%%ahx+}uNxKzBn!Nb4ipf`dQK4KJ_tCTu&CIGW6`f1#mnBrU@PoTz64vO{UnB|0}?^z95IN^RBXX6nL`)!G@D zizCrQh)u9i8mlC_23f}})eyU{S}Ixz-Z>dci#X6pQCiS#nB7x>J3mBcK;nn=IEFaf zZl=IpT(15M$ccbw$;pDhiGWqI$`4>Yb7GR=%uxweXnMoRmz(T;vEd?CdE8kjEqpYB zPu`>(oji&=(azxNoPZc`JR^Kau~ zbMJ#>>&NCM*gYoyzZ9F>ak`aM_!K9Y^z3BXtz8oZ5$bDq&ki`-_s2q(OL&>fUIjqV@&8zxOGhq+Ry}HMjgF+Q~ojb zG#&LApA>};r~Eu{l`%lTYSGbOKdJ-JKN?NlS(s6bLB{j!As^R9qjHx&;yYi!xuA6h zc{g6n%Whe;D_2-tyVm5Vr?+f-tYzs0WVdW|g|=*Sddo(n*&c$NObUO1VRF}+@U!c* zCY!_!zUGFEtws+yZG&oau{BjideCC|TWS0I&R}&c>G_{o4Rqi;&;gk!xI{J15HLN6 z{`m4wIWFga$=~_jfjP2AK{qM%QAML zV!L&m{Xx~}5_R@ncDZ_xGUOr-8FTe{)Dw4_qW^Ya62|}x)F%Am(s5kp#AE=owdPjF zcQ3&O5et4WMO+)bUi8DXY_Rcn%#B~nM;B`opXd%XQuQ8izNbH6>L8hn6L#2@>M9_O z-PtBU3r$ftUQ2kAlO1HVgOhMV!r>SS&QOy-qZ@Abp5n$b#@nOyBnY_12J*g4hYwep zdEhn97R98>3E5j0NzRKyRyZ#XXF&Dl#e62OjtnAa)zKHZT4z1=uSSp|HtdWslxmzl zMcF_e@m3mZlG7x(q8^cFEFM#egP3gf@pgZ0^}cd{&jpj#X>p4L zoHsF)>C*Zk>H&!m`6RoeO5x*Y93r1-_fqrvv5>oPy!<%0`6zYpXNa%OvBzk9?ZWUe zP`E^VZLX0k!VBZ^HO@7;B_Rp}G{|lcyx;@UgeU8Fj)i)=Fa}V7$_SB;5-ELZnQ^hv zg19Y_bWSFBo^VHl>pwVM0~AxkI9E?^$J!&~Q1U;B~^~tBp|Y`uW03XxC!~y+0nx zU8}CqE`#{xKyyT^q|wmH%p~8ew+9)Wk!!a;H{PwcQ7;ksR2kD7bmyMJ zZxtOusMrMfh~6;N5$$Is>uU%?$5$A4Cb)oyTSt2FA-3DDQ**!wcR0k#L?$!`PZI?_ z-MaRm9N7b0&o;w)9^DrvG+Q=Gd_>!4kJlM*Ngf}DzxzpJTlhO%0hH)9vsTi>-){2p z(m8LjTMJjUUxN!{RT>*5sx2vD?|3Kw@Tz+6HT6t1_#j_Z4@_>3iX*8Lr!9_*`JH`0 z-8wrwY_X1g8dQxg(awzlBGI|I{D5vCH}}=6&8}A0zzqP_^DtkLhzN!R43}8Uiy4Co z^gxa|5JGlONxFCIrTwYVrp!b2X`wQcrT(~Wvv`7ia3@*tB%d+2XqfS-{fZ+(T}UI0 zRQ;k0(nv=dsiNnasc#rhhn`-hoUdT$8Rz<6xD9G*(RXH|Z^321Km$(nu)?xV&$}{+ z9v3>p&ayaak7W?Z1tepSofvy8?SMR_b~Tp##*FDy6OS6xcgKwxm+>{O39jk+_L6mc zh8qb4n;CG1gr@?tV%#WRUdeIQeU0%k$M{gYpnHj!94;vyZd%;h(AwQ_;v76L7TgO5 z4V|}OJ{)_(HTHz=f`o_8IY$-`7)zi=Brln7m+Wzu$OaC_N$5P$)%^@aBzyc^_?jFd@h<*v8ORCOYCNvkH^F@U#UZb?xvdX(nCL( zyQL+N$kV-IJYH+JRUTa~?{fEs74nG|?<>s6!}v9{*c5!&2zZ``oA{Iq0nZo3b^4g( z4imQ&s&fd)mCRyKBQBm@=ZrsR@HcXET+g;J$(qFZ4fxZ@LsN80FOTWPb5a6}oiU5e zn0#gmV03}Xkr%jSg!8#uSbTuYXwgxPp01+>C1}dw8Fv@0W}C%lgsGVnGcwrjpkt%kD{h_vdvxC@zS4xdaY%AztJKe;9k^ox2!%UHXU4lSH6I8qJ@(Tc){AY+a?Ds%Z) zbA9_oRJ&saxDXHH|gNuA1p$a?#2M#}u>;y&)O> zLfvBnW)IK(;-m9qdy3A%+=%A1AQ4)bV&n=1uidP*Bs{{K1D%`Zwm=1iQL&+DYd|%_ zG(&Hv$|8iayQf~0I%Bb|gkh(UxpNjKK?WNb1=$CPEhQEH$s{7O1&QgwZZx-D?hkCdJE}9cw%;!C(_{)OyKn>d_V2dc1-goq6Q1 zWIe)ZW5^UQT*3LIYz?fk6mf_e-)BUiyP#?go_(~(H*jpY8Ray} zpZb*4w+sndh6bgf;jfloC7TIEcBc2y>%yS-ylHz(^*arcs=izDz~~)LcDNkh7ZTzt z1IQj%1q2x-<)m#Qnqc>P-tz1*!HGO}*Rb$NxU-3Zf^qW&C2w{42qjRCB(MyJ{oz!f z_TD&G2!VF|*Zb_2v*1rRFT4P+kU}1EbIaKaF920px-8!}C@TU%!R{e)TIdTPd(J>PN#|ij%`xF~6m%z4Hh-yzF)z6JI^VSLP!lM5w5@!a$zYF@!H4i5 zX>+ztx`tfbZ~@N-yrkGd)|!K>+8m4Q4k=9vhH9QY)1IyE$)HZSUPTRK{6wPt+Q-7P z7y4zj2c2SY=N1h3Zcb*pgRQ!xp0*%Y_5xov^Nhbi&eW2O z;~$PsBz}4fVOJ*ZpzORHH&w<6sY!QGP(8ZQ1i!#;e#{A;fgb1>cx3zb1(V1(gC-Xx zH(zF;QL`tk|+fwPd9P#MM8xctJk^7H5Zh`uRV?0U2puW+R-t&xZ(ZmVV4vyl$o!{;d8hn z4`1<~qRJv2A-r1({22Sh5OJJjW)`YDE?Hg)0*7lSx zM(Nks4E1fr1STxTFuTc7#~mM5uPvlm!`Bet8SEA%ciN`cUx9-|r0ZNwwf&nvaE2FO zgc@x;_=*{Z0pYyrVfo^`;-NpfvfelziP>{uBfC!lhudJCYg{WMmwZuQM&pb>l@Z;o z`ZB6l>-zh+;?FiIxHhJv(%ZAnUx+U7g$nIBKQ>yoS0l=S?(7Bj@Xr^U#b2oD*6va_ z5=Fh-@7d9v=J`FlP6W-#WK2_!dp3GC^1!8E%d633`s+@j1-B{vdU;G{Gy!;Ti~8c6 zLc+`CKLh9@yo0k!8C~(dpTrz1x|fQR_u_kj%F!WAy*R)ngd1I_YfNszy015b#q5$i zz>SeDv^aotjquIyoO$9gz4T|SF31{N-_R!@&n^oSyvU|Wvm`RiQ|Z~IB_|?!41(j) zX9P#^$d%C}@tYviNA`D5Jl}t!d(A460Af-aT8+?pCJA&1-U9`527uBOW|-0^WB3?@ zF}n$;0fja?7Ysv65Q}~xBLeUy-l+}8&musui-#l@PDUm;L)5ASwq!qs&(r8sp6D%K z-0)7v7X50+RupU&4Qj!AiQ1GGwicO*8@#azX3*n`U`E1dJ~QJ}nQ;^HjdeG0nSdwR zlUA2yVo&$7?u!}a;F)_1o>NjBz=DofVzJ6DSzyrs<|33b>g%m*%+mXZmUM*+Sra9vsI9D9Y+2QvjVaC)eS_kCZ{j#c3pFrYL+!3 zOjg<6K}{2N=<}ilnzBh#H;Fw&l|*ge7JgsC(zhJ~q$jNtK2$p{KjRdH%3qjp%&Z}C-ojNMQ5 zjcEtyp*jcS9#gvBtYS2Sv6hO4)A=pFqimerPg{##CFsydwAvDlXLwHZK5jdXy8L3cjw<(3oO~i}Vb^Am0^}?;G$MT%wLTkO(IEP&%`(JdR3mfnU%ZVPO zFE$W|5{vlE$O==kz;a4wx--_9m>6pAWj!Y{xqsohWz>pt$C)yzwfH>lKmrLZ!-dO742UP zp3l!U~6dpS6er=Y1hyGqp7_F<7&B$m$e%;jn@TEHk_$A{d+73E2z?z+*TN(p* zr^vbIo%BnpR2klI)}o%C^udi~T~@M-YV;&kNoHF+sFH91&Y>hc=2kr1+)Bbm^sI7- zJqmK--MC?|9qLqs?rKh{IS1_~I%sKeDVP_Ws~C;Xct(m5*%-2;+YLF(h!$$C-wmop zg!`SV;Y@XWA-B!wYD{{AbFq;;2d#mO`X(*TV7t^=95$M)>&gY8sX+vx#T~QX>{ZU{OEsv@a&dLDlHK>Mn2{Cg>V=Bz~e-n^9_*!ks!qs}w!MvnASJs@1K+IC+y_ zqgyWv4$+3Wj-}cl-0POns6XO#{}8+Cwc8R>ji(h3HbPZwM<|NTcQuNw78R7wbl8yR z##dUfp2z^=vV=b|KXDBf{vZ_7?L|i6$KdL5dFF8|XNUi*;#Se!dlI+W%Wy_xW=>oE zv6QtKPd^+Er|w;I$be;9wQTE-CBP<<-nNB9iTYCKpA&RD>yA+({D_kcWTI3=f5Swn zB5ewn23;72rYz1dr%CQrMof>9Y*j3wvvXBqA@BBT^ib_wFuJwYl1nJuap#`YtF?gd z2+>p$dB`1luP|~&!goaj6d{CTl|taFOJFG7jhP`*7XnkCIcq7VKp2&P@J=5B=Re~6 zHQ^<~7)_a|NxNBD$TXo|Vdg5~;8j(g;^UPP(jL)3gDZHaW;mfS5iy2N+vkup$Wk48 zKQf;D8{(Z1{tbnyIZZw)Dx{e(a+`O7C-^#nb8+Lz#(J*#IBGV?cI{S z(xQubj9qh$!R+p!YIK42OkO~{9}m;D8|5H3Cv=N@h_yI+C@tRw1b0#=%6uhIGsAU3 zONST@mkNRJ?n8K93;PMKf*%zwh2sru?k#+DKN&~lP0H}G;G0nGI6aGdHN%ZR&A4@8 zL^lU=Q98P0;yoblgBpp$VCE&`T)&`u;CYC&UQny{49_4a1l7Y&c)sl1U|2{N5aeQT z(k$z499U5U15?`-#wcr1ANK?-z7Uoct5vsrX-(5(xEoB~%>X3RL}r4H6098V&w(gzLLw zDlg%BO(vBViD#3xRijH(=^1~o=j;qNN>%#Wz1~nmRc30w({p|>1*d()ZVKEzx_^=H zj~7jrcLk}FuGb)0q@~mzGcu!$jT254oac`jRG5Fsfm&kuOgm#w!~^icAn;<{%IPwH z=20l%Q(Wo`aHT}#&;`-Q-1tX0Assu0yjhF`kc;X=A7s5CI*F5k_%OOa$1x02W4@R0 z2FDtjgAI|JFY}KO4g0-zRGbG2PoyN?2pMp}d^sf)M#@1#R-!)`a{%Ue&M3bwo#?;K z64c~Ea_v}hwX&o=6hFt;P^Q#UNKcgW{zB9|p)rCjApxDmch#8?um|#Ll}&h5pfr0J zW|Ig;-Q2jCtmBq&y2&@uIai%Y=ag|XwR@iKsL{Q#?kPu&W_Qo%678Ps(NXvDMz6uu zh*Ggh5H7SX9Tv>D zXh)Mii|<%2$MxFr-o9=d$v@F;Z#p}N+gKb>TQIhMtO0-GLvl|P{Yc$4sV9MP+az~$ zplMTruLokin1Q(L9UIXV+KJuL9D4zyFF5%koF_>}crbhE`(mv)xEkF;ch}b2GYJ(B zy4Hm8E=C_Pb&}TP*yBE%;ivF31+gpIA$JfaCTPd}UHO*KHOd2S^Vg9Um7-8I-DVF%VplrQ=g z*FVmZHG=^(c&Mj;G-YyTgj<*Dm(af%wOIIA(LW3v#_X(GqEP?(<7jtbz)XTiZ@iZ+C>01a``c9G6LiHjt2Zii;zv6#iba*gQ4w6 zo_Z<}6O-%c0_|9Cl_IXd`F~6i-BC!W>$SuCH?vs-#$In4S|-3BytwpqB~l z8)3Iv?z*STDAA4s?Tb=)FyRe-aeZ?cv-ouzDArc=-fkiqIsF^O{dGQTo#RS*Ph1=M zyKaW6D#2^R>1v&8T}!TLJWWgbgC1J-Lu^&HtAC&^M?GwG$UcJNP^^_Dgc7EIVc|T{ z%FzXp`4o*GfWF6moz^Bps?mkoyc$snlZu%1Cl=G4brK1$&dk9HzD^pD=p|J}*x&&J zwE>_J#)NWzuJm>|&T(}dW2DM2T|x1{)PfNy9Z=Ymc=%|nU3`O6K=uXy;uHmhwRUM6 zAa`LKZc~U%AS*+6PHmEVv~%HkNvu~*GEQ{gvx}>EUOPJ`x)XrNGsB))-`SjM_lr!P zbZxgD@043LJzvY|3G?BoBHnB5bThTtU7s19KmK_nru?<>PbX=!PS^oqEaFmKB>Ydnz} z@39E4tliTUG)QV#Y@^J%-oU7~Of*nCt%+=y-S>Ey4l5Xv%Z9EImt^jN!%OJ-2eCYRqg8F~Vf?yw}&oc=HUmE4}6sUBzB{#S`VX zTQk*6J!&-E<#3pWkFqC3TfszZX&S!!bghOq!};{oa!EvGcv#}Y>Fw4YYc~!yQM+Np zh>3GhHM&5>$qQ_3F>vihsYyW5LH03&!fD5qv5lfb?P?W1y-k0ksLWQ*{U*maJ>ec~ z2qS^ttk5o**2Et$I`IG(`M|8rYh8C50Po+E_HBqMDNa}qrTa#YEZECz-?SV+uV22K zZOm4t%ck2>)0?;>WI_!ZmwWV}dKtA7O&ndIP3#;UdI+^6fe1F%a6_um)!K0E&1g91 z;NjqiaGLooHeI+~qYym2(eLl^@pG8nR{J|`kvsT-QEypRVhhsGre81I_IRurZMWB+ z=w^j2lExK2h${iV52k6B#lFf@5{(`Sz&lN}HPu~zrV(x4(}m7Z2f}~R-#<=G;Gc5{ za2P26kU1Fo@A87H%#hW{n1V>is&BLu8h=Fvj{XcUPz5dm+sXmy~&Hrr$BB?ar!T8iJhVRj;913NkZ+Qq^m49CR6q!&~nS9d=&P@=ZLi zH=ckwO3h8``^nSnhC|!}vWw`n^e#%kf*r~o!Q%KyA8_IZX{O!T+n@b;^hqwX`C^7m zu-Qa?nFO;3ony@%bj@5Jf81PqoWAB>Qom1s;k?9!Vt!*6E>AvjLE=JNZavN&eD#eh zx=~XD!@gKeg>X|`oX)VBeaA4|GabDb!A8JA)#wV1%+(wSMuQk?30Dy*at06p)xD`j zLI$#tA88$YKN#$f7kV0^x3^G#`Z0o&dl20@OC)d_cVR+I2I4MwSrZnb>x+-_+80La z+(N2`?l1=yUyqqg;_F3$5}J*0-p25$TZJ)+wpF9&ztA8HqVx*FAdDQw!JCSfVP=iT zVv_Bi-!FQk3;&?HZ_Q{XgjU0tczh5VVvpbA9`9m9ZbFRS$#^%~szJgCnmz7jo^_H7 zoFo3v(L|3n9g0|JD5R_4L8%owujbZVYbi>_%QMy`NHR3@<9j!TpOS-&iw3Yw~hdek@ z^Heu#cmak5gDZAjJ}{i=G+U(a<9#fRuu zaTnaj=8)5;hSnR$jsPvTrQl{14v zh06(uiY)0&{LvlF*CO*o#)YIy^M`*A^Gt#=w_k>q6%z>h`TW{^j`TT6kr*ro6NY|4 zF_>MDrjPohJ0?Yw8R`VgD6+n`?oyW`*gE`x97t{sF(-{JvB~l9Y9x`3E==b_-?%-W zfkv8KKd zq~3AlEy26Lg|;c7ZFrJk;d6z4X#7%}H9cKl9wo@1oUzyB7@YkGkIHR4=UXC>IO;}# zmOj|yj-N19Z^WFA`op|c9xYgIX}k(YQhvFkrRho@O*yos5&yPSB#)2DaUTK^j=BsQ ze{yA?=7patH1xswhoXYag8v|XNY);zXB|*HT+caghAW#9L6; zc#?GvC{c>g3e}}BCwhD}YOCwrDK0Lz3+eap9%V+77#}CvHJWn6T&)TP0ON!mZ6bZ1 zg~+tWGJb(zk?K#AUuwfCjE$5r4wP(aX{HE23`*ulxgVV1nd8L1Ptr010Zw{cze2|s z=`q6{E)ZJgDriV}G(9KQ97)`>T1s!Z=yXBW^~=);cdiLag=-Vgo7r>EeoK2U`fZ;c z^jqjqiiN&4)@?rm(pa};zhb|Y&iVOb{m#k83p*z~HIj*!R;Q1$55)UutcNnIl|8hG zK6bA3(9ahea9XL1ZaAxy|CXUmVWeRobH`fksU2SLA-7`^8taYRk;hh4FL$Yiw47=3hshG1Rxnwx*d zr%J5l%QP@_@?$@2L3XEh(A}aTXOe9nSZf&`**_&g{*q#U)oA=y0#V~nf*)UbB}YZA zk9;;JU*M+lo#UPA(^ZmaR+8a>ao4MYFAr_=*4)s+D_7~TV>4h4XyEa`R=|j4BNvY6 z3B`1`bD!MK73Ror@0&X8T5Z8C9G`$!;zO+Q+E4pkD#M|-)3 z9^i(eOG9^2qO30Il6lR+$x|h1n`ObS?EI?8&7_J`<(->}LF&sLIOe9t$>g9RTR@g! zITBG#5WV*&S1xRQ?+L_2sH~`UrnTs_io=`x)CY%gM~h>$wr7zZ^V3Kf=}L2CquD*H zJtkm@M?O49(vj9h_+0Hw1jvv4eea~y(Sy!--Z zCHf^Z0182Mv72M|#*()C$j!(4QS5t^_{RRuC#X1STf^ii#yP?mI}Bzb#@O(A?4}&JpK1vTDq?8n}n6e?Ukw3#KLJ0MyLcvEv(q4K@-A1nx*? zU+l%Xuh4U(;9!F9QFwwQM+HL$9)b5D1EE@omZHS2cnJpvMMnx}IqMx5jprHsDB|5& zjoR@(*UcHn6P-r)M)1O!B%1$TQId@~JWir{pEur~cdvV%84Za>` z7J->)H&=u2Tp72i#dXy9HCHFDv6=dz%)_{fbwg-Bul>0MelCHZOW@}c__+jrE`gs# z0`N-*GF#te>LVeEZ)b4(k&-Y`2JF!hlm3a-~av#KJbALe&|D3rNS~*pFSVC z@WPLN>|-DMc;CLC_~a))`KeET`j;-c=%UZ`>v!>IKl|CwU2@6ifBBbx`3wE~|L0YAKToQ&6TBrb(Gzn1M30FiXnp!W@*jg=?hDE6hh(P*^BsQDHI4 zlEP9c*A|wcTvxbW%JRYuC@Ts#N?BQ0g|fPElaw`uwJ0|iZjo|p;Wm_Yh1;cc71pC{ zDBL0C&ca>uEG;2y9-ZB=`QR+d8+WVl)Z(0DEkY~NI6h=7Uj9Z^HL5LUO;)V@RF26g~KQ> z7haKar0^=rYlYXP94#C}IbL`}%89~Bls5~fq*RLoQ3e&;q_h_YqYNnymC{ihhBCZ3 zLdwYED3sB~F;Y5Or)u0mN|yh+NM;#!oOi?>L* zwRjuKy5j9px{B*jHWcrWa%b@_l)H=fNZDB2gmQ23J}H}v_oHknJ|Jal@j;Y_iVsWK zR@{#ANbylAJBm9|9xFaBWmoYDl-~BzB+8q`Q&Os>fhdDYZBp7x zgHeW*hDzxu4MQ1T8X;w5X%x!n(ikb7rLidEO5>$WC{09}RJvNqu(5NV&6g7s}nGd!%eEZ9=)Xbf1*XrTbB~ zlpc_>we%p$L#2nMY%6U?d8G8HlpUp=D36sMm$Iw$1j_ExlTx}%dr+P#JuPK#X&=h| z(lb&Hl%7R-uJpW=gQXWxUM#&NvA&Qf@8ZhO(}FyOgf-dXx?2JEYuMz6<5<@;y>E zmN%i?TfR@q=JNe0Tgnee*;;-O<)QM!Qnr=1qdZc6RLYL>PL#*Wk4xEAegb88`AI3= z@l5(hg80F>iD^iY>UqyMX{JNB* zWpm|zlr5D9q-?D`i1JY7VJX`x+fg2=JSt^JWhcsG zmB*#*syuGN!Rp%GkznDB~L^NSW9;3FYd>$x@~?PDPp4I9NF9 zn#Orj<~J@tS=hKp%HqZ)C`%i!m9nhyI+W`hmrJ>!aRthajVqMTls%14p*-EVSIWM|{V2~g9+2{E z<8vs_Hy)JoLgR}lFEt*La=7tjlvf&$NO`sKHI&yIk4ib#cpT-8#uHLbHol2+sjNEy~N9A!k)NGYS5MoSsf)Y&vv%DATSC=;3{N}1GjHOl0s zDN?33O+%U9G(*bFrdcSno90NF+jI@eyr%h57BnrCvZ!fs(-J95o32G!)^wee>zkIN z+|aZ_%8gAcrL1aN&G=zTR?D_nhXI#^waIH4_w$ppCWE zb(x^X8@+-8ebAK#ifaqYd{8{)YiSbH;IS5Tl2y3;^?78qvupe{khv?QpNIYI5n1hvYTR8UhhL9I4=1qJ%xKpLq34GdF! zP``?btCOH^$qDMQOi;HPlL~55CaBwtUO|CAIFtses{tS;`lvRrW_%LXhMcf=Wx~3{ z*i=~KGGX0m^a=~~LA5QVSKUJpV|`egSTiOGYg0~GyE9?kYiug4(V4LBGkS#u`k*5X z))s;o<-^*_nh{A@TXVu1SOY6=10OUt71r=fSPvP!!UBCTI}O%$f*9t*dXzOoldvAm z39GvXR@@5iFg6v|kW5%Rjb34aKIl$^wTmDI`>=MirY#9;cTQMOWx{&W*i=}9GGTQa zy}|;0a3BrV(*!ZlhqaG2r;w2qb8h$Lgta#l)_!ACVZF&DuvCxz8KYNNpbuuZrnJLDsyHgmo|{td1wU+}^_aGm#gJPsMdS6W5DIued-TY)!*;m?)0q%U%8Kn+of-OjxfPy}|;0a3BrVQG$5YhjpAauOwj|&k5^5CagD%O@;Mx zCae=iudqNLbPP_>!czos*oQT+fSQ+*um%ovGlHJZ9G}aCHAwG+ zebAW(YY0KS;KS-*&GSiE9XVmWK1dJ1sNcDU8J~*lxlCNcjb3qqKG-oNrMX5C#j`%H zF|2teiEB(wTrX!fSEsS5u=Z!d8f)|l3-m$9&=gn`2x6ZPYZ7aoPQsd$6V{PTSXUdH z3hSv%Sd)!jVSzsAOoKIzAolpMX0YbTB&-=ZVZD|KYo@WOuy$v{nq~9~3-rO{G+1*9 z;t3ztJk~s(gf%ZGtfQH*<{O&|>#25T`v?DSzRWzC~WSW9!lI-UvZ zT4PgTJ(3A)nb9jO&J zGJ1st`e1e%tjz>*mk(?jN z=Jq74?Kxo$$%OTYv8k}uWx{&Y=oJ>|gYGm~j}gReKCE4=xg`l}S58`ofFpb?#zkgUgJ}7ti|)#@^L-Knj4e2p38}AYG!jiZ)_^86`8OO8oj~-eQ-1l)=LC&gAeO4YpzeiI-C>M z^h{VU8=DI2x=dKF7`?&*eNY{dV&PvSh-E&kqpVq)gmpA0teKgxjv1Q@Ye^=o<3_Kr zKp%9Z!8%D0i#=Gu8XVDwtwwH{w6)5^c@`!?zF7-Wu9A!V#n|eg>?w6HJ=}xF_2u|^ zQ3LgAOrdqrdVxb;yJ$TibJ2Rk41f4^=akuM@gRGI3U_{{aNCStg$w$i<7CPL+YkzG zo+sSa4%W;~inHT1lA>q_c+1v{rueYjnP3KMn6as_=48SeZuANZ^g(ADtWg9p+lMuV zH8Yd2#^i+6w(7$Q5^WsBUl7!3Y$~i7nXtwhy}|;0FgXp@1cI3E!5#R zjo(^{EnLQ?!kUr^YqHTREYJtD(_l>_h{-;z8LXL~cn+j`GCah&fudqNLtVx5loFGQ}uvV~UcoNo%oUk6u zH1IbXn+j`KCajf4udqNLbfv+%i6AO2 zEk>`fKp$*OgSCzz+I?7EtQnMq)s++0BblwW-q=)F12bW5FnWar`e17sth)%J>chH+ zHE-hVuh>G{Jvm`*$TS%njZKAh(w(@Ql0~-3=oJ>|gB@wGHWS1NZWRs}+P1LfcoNo@ zoUpFWRKf?0O@(zV6V_IvS6HAAy3=4iOb|zXSle0iS`yawoUk@$TEa(+O@;MpCagz| zUSWYgIFttKF@iYa!`j7~my@t|<%BgY)600m*i=}DGhyvEdW8l0;Ak4GJp^&chxIgT zUQEJzIw!16nSE=ov8k|L$b_}e=oJ>|gKApd-vNR+=)-!BHP0nsJ(m;KwoD~_-q=)F z&t}3pX!HsT^g%}&td|JlfDh|1YxXB$9nJ~s@k|5%vazYK_GQ9)#po3l=!4EQSg#Sp zULV#`);yJjbu=feF*E#$iF^B~4adifO@*~56V`E~S6HAAW~aeANf6yWtW&JnorHBN zC#;2;CZpOG<;W_mCo*9TG81c*;=EGO@*~R6V@1`S6HAA zHm1QEM-bb5SQA+DP!iUJoUoQ>#xf=vn+of}OjwhQUSWYg*qR1w3PEi3VNGMrmL#lc zIbrR}H1N}nO@(!TCaf7oudqNL>_~$(n;BCyinhi-<%X7lIJrmXq#-_qrp9yP)(JL&_2S?Ljts;mnAJ$E*S(k)$Q%+cmGbbi% zj7^1gTPCcvMz63yA9SQ`o4A!AZuMcUW6jM;SnG1aI+*F|-fnCvthJf2x{O|7fj;O= zgLMZ%tnp#p#hTSgSa;=w)xOF%8Syyb-NvTET9paw9-~)SpbsXe!Mc|qR{F3uvt~sS z*5;hBUde2&`;AS7bwehsEk>`fKp!kmgY_UmEcanO%$nr|$J-)3wotYw+7 zwi~^|0)4P14b~2VxYmdD7;Ba!VLg@;)}vc}C3LU+G7tW7V^d)*&V;qg=oJ>|gNJ2 zjz_NcTPr>s57xU`;`-Q3SVN3nVSzq4ng(kaL3H}CMzCgd64r>Eu;yjL8fk25YmLf; zHOlA}7U+YHYD#uUCqaz#VU1(W@Fc8pIbpqUkKbDH`PO)2Q(+Cugf+qF6&C1&&NNt8 z6GVp(YYJk0v=o6T9^~o6EpqRif7R*GBy>~ zNgh0&x{++L(JL&_2aD2RT}u!r_=2!-ed{{b98bc!E+?#&nI_|UV^d)r%Y?Pu=oJ>| zgXL+kZX}4KKCD%&c`XTRRZduI_xY`LUd+o_ZEPy6S2JPVWb_IP^ud}mST_^I5g*pA zta&*J>(-pGZq011+l)@~l&-Wls#4;h;ZYhNa;hmBrgfj-!g2I~=m*z3dE z!J4O%uy*8xwJvkq+G%VmtUZ~q9y5A{1^S>n4b~F`(e1-}k~O=Nu%65bYiFhsb{m@t z>xoQQdyHOTfj&5p25T=t?DAplXU$_tSo?FrdNLE%GsdRE+L;OKfYB=~&&nBu{|Oc2|ASVvg%P!iUWoUjg` z@=Zpsn8|q6*i={#X2N>S=oJ>|gGFhujuFIGAJ!YJ*^-3yMow7EZ}(xvGt^EPn+ogx zOjsw4USWYgSe^!}%2#o0_F)ZT&Amxjg9hiD9Z$|oL2lE#+3a{zCaiX&S6HAA)}+B2 zN)Q`;Si@LzcM{gHoUpds?nj<}A*O`GjZJN>yE0*oFnWar`k*Tf)@Xvb(}&f`nhi-< zojGCc%`_QfjZKBMJ`>hBqgPm<4>qR3nn(~`KCG)*vn~ni>YT8i&ouCpjZKAhTPCb2 zMz63yAM8kjHJu=C^~+Durpjb34aKIl$^bqztR@nOwp z&FUnq`8i=7%v8b!#-_qrl?iL1(JL&_2M5w%Eg^`NKCEk5vmy!W+MKYCWWrizY$~i9 zGGSe3^a=~~!J#x*HxR^fAJ&bmxh@Io#+jctCBXv8k|@Wx`rz^a=~~!O=8W zYY5_6AJ)yRS(1cxb52;@GkpUe&rrL?*i=}HGhy9o^a=~~K{f5vv)c(`kq>JgtWzD!Gti3s5y`I^(_8FTBYiuU0{YI~_Kp(70 zgY_&ybo#KKXU*s&tmkvWI-J>B2aQdIH7XO<3r4T7Kp%9a!8$|`BYjvevu1b_*2_6z zoyhbuUNJTm*04-iM~q%!fj-!n2J3Z#=|gUM;I#uLO*AJ#~a3-voMz63yA1qIUHHRP$ z`LM2G&5KD`*W`qCU#3qu&)8I0FJ!`+Z}bWa^ud}mSc?eapbu*aYo1HOT9Omi$;{ST zYHTX3XER}4YxD{W^g&k|tm_HlfDh{i*6dHhx*;d5#hJ6?6~?B*+LsCIMx$3)pbs{t z!CFladwp1ISo2g8)|#BK+OP8sd^|&Kt+A=F_GH4k+2|D(=!30kux=xWZXed|tl6D} zb$d=&$M^ZL;w$}K#-_r0A`{knqgPm<4|b%%x|1Mw`LOP0&0|Secjtt4_(305JXiM~ zV^d-6%!IYk=oJ>|gF|Vs?jwjDKCJs$^GFib{W)PBc-)6|ZY&1B#n@C>+cRN3VDt(L z^uf_ISPv1zHXqhD);yGiwJj&Cq5FMUaV6YtY$~h=Ghsbq^a=~~K{f5z;++Js)ra*s zYqlg|J)RTRoT?vCi!a;lGBy>~{h6?yFnWar`k*5XRyRRx_F+B6ntPM5p2`Vp%~Bs$ zJO%k_V^d*m%7nGo=oJ>|gU&Qq&k)2$AJ((1xjPB#*_^NrWll_JjZKBMJ`>i+eXu+Y)(L{R)ra*aYi>@$dNU`i!B_j1Fdip7Wo#;} zwVAN0L!<523JdhXnlxB#O#rdRhc%crtCO$>>y3N5oq9y3^EAZRR9LGrVGT8Ug$4Sc zD-G6gf>`Op8p)a!NmwIu!Wx$eYm~96ux`kNHQMME7U+YGX|To;#Bv|jc-CB(gf%`V ztS2)2)&yfyVJ*vqHPPr57U+W=X|N^}#I-)GsjOL&gf%rMtP`0&;WT4YVJ*&tHQneH z7U+ZSG+46;Vv!GP4r>-9Va>@2Yv@D1$%wnUbB#@fH9r&9HAb(nKpz}RgSCJl=J~J| zv1V=()}oxSj%JQqi;Yc%H766+5~EjGpbw6w!CFQTvwc|Cvu0)z*7Z4IjmR|c%Z*Ki zH6s(&4Mwl9Kp#}o-ubYSAg24UR9Q0(~$$ z4c09LG1-T88*3&dVcnJ!R%e&*>c(@P))|`$Yhos>+l^jffj(H225SRBOz>gd$(nIV zSa;@xH8``i?lLwN*4Ru~cN@LJ0)4PN4b~=t==5RT$C}YeSoh_GwJkHMyV=-OSfesw z-EZ^?3-rO7G+0{+Vx$l2A=V5}!g?qttT~ypgtap#ta~!!gpV1U3TtpCtjCRBVSzr_m++Q39CCNtnI^nlku)t zh-QzmsjvoS!g|W+6&C1&t!c3K5k%F8^$cs?EGE{sp2-R8!OYe=U~DR^lXztM`qr~X zudqNL>_~%kkRVPJz4fgZS#vxI>&2X~#$`HBFBzK(>sThNLq@N#Kp%9c!Fq)tj{2}( zWzB0zSg+=UH6s(&YsRL+dNmW)>qf7zKpz}PgLRxBj`*-nu;%3?tP?q5?a%C6Cyh;o zbvP5&n?|p&Kpz}RgEf#ZkUr$YYGcidNmy+i`If{V&+J?6dN*4Ve<2grV53)9pbw6w z!RjE0gFdX`ta&a8Yj{pr!!x~%5yqyr*0Y(gMjE}s0)0?Tdkxqaf;iyA8q1pfNmyfZ z!WxqaYn-vEu=Zub8gKLp3-m!p8mvhKvDb$+nKe%(VNK2nYgJ|}V~VkxoQQbBtbLfj;O?gEfyJcKNUt zu;#HOtOYq?y>z<|E53DRp|Pp3c4op_Wb_IP^ud8NSW5|FhYxERYaU6$T9y;mqResY zI%88|ZO?>tz0oTy&|gU&Qqy9nY|AJ%Tx+?<59J14B$ zH~FyQTW6j$HWk*|OjzAUudqNLOiqLKG(oKKVeMnh>LjdvIbpq#={)T>HWk*YOjyqt zy}|;0usjXca|E%{hjoxOE0VAd=7crqdcU>eIZrPbn+ofOOjs`(y}|;0uqF-GVS-rh z!+M1^*Ck=Sk`vajOjt*ZO@*~A6V|InudqNLbfv*MN)Xrju#U54NfOraoUpcKI!|vH zn+j`jCae=iudqNLY)pf7iXayGum+xmngvN%1Bd0C9d~B7)*!u`&5q}1!fG>mg$4Rx zYZ|N}1ToKt)xny%Nmv~@VO^aGYnZXAtu-eT)^MX&SfCG%rokFT5VL()V^}jY32RJF zSO+ubTb;(H!kUo@Ypl^LEYJtlVJRmtOdyEqKCDTsnVN((DJQI%nXPrTv8k}8WWt(k z^a=~~K}Q;_X#_FZhc$yWlajDz77tPQqH66V?-%9{jb&rotMP z32T|rD=g3lv(sQLCy0?gtQD*oo`kg`C#)MY`__%drotMQ32UX%D=g3li_&1-L=YW5 zthKBel7zK3C#=nDeCH{?f9qyrQ(+CxgmsJ2D=g3l%hO=3BZzh%Ru^jqC1G{tg!Oc$ z60SEk71qE^SR0I9VSzqalLqT9f~fki?qSWFg~a;SJvm`*%WSQU#-_qLiAScdZ*4Mq zg$4ScD-G6Wf;ds|*0;8>=6Dj;mYlG5Wx{&E*i=}@GGT2sdW8l0U}GArhY8}S4{JMX zUQ5E-o)gx6nUnrUj7^30Y9_2ljb34aKG>QD>oI~j;=|g-n*Wcz_kfeDIP%Bmz1f6T z2$4mwJ-Z@EM3EO8!_IS(Z7{NpZTXyp&-Td~-}&yiJAntq1tAb1V1)=vToD#T7ST%< zAYh3Wc`@Mx#zsU74Cw#;R#m@#^WMztj)Z@A|Ns9t^8xL9(_LLvU0qdOUETdgmaM1h zBx|51SxuWksrDJri z?PteN*CgvGU*5<<`KYTJSu;m~h^LZd&E}gYvSiIRz{5=#f3>FFn&Z*5-g>+ySzW%o zk%jWn{Ay&)B@ruumC?9oKBkM#G@ko-a z1$^^RmaGMJk~Q%N*~o#D$HStuVZsYX^0iCCT_>m0thCrj2jb&@rwH`!b1qYBRTXc}2} z*CgvaU*5<<`KZ4dS-m7;S(2;^`R2|nSr^txR_Wm+S?N6Zi#(b})*Us;y4aUDvQR!+ zR*kGnNyP0*vX=18ty!{`)JfJ!HGAuFkEW4zOHHz_@a2sxl#f!|6; z?9cR;&)<7AjjZcxlGX3a8(AnHt*S=WZ6so8f~;u8(pQ6CcY8BzlPd(#o#llv`;7)~872MJ7qv|5jmFyFqw#kx)t`5HLLLvs=GubwuU5jx zOzRz=&$Wexpa2=@NCV|dG~O2x=Z}0ZyjkhQtm8#uNyqvtd zGQr#8{d{wImYeqv!6xn!HOU(A<&7+qk5*PA>tPacS(2YU zG3T$5h_jMpz0NmhWXXEHPO{Fdnf>>MN7KkUy(U?2`tn8=%15iKk@XIVSd=7dHQy}E zlC`={vRPD+wBn{Q6Yk~P}^*P5ay?bgbgH_^@UXj*U0uSr&y zFK=X_eAHcythprO_#|2L_-0;~ta){k^<>Rm!pC_ujjUs9l6AZ?e`YFi##6nW#M_ewTY3jikeCk#vPGZX_KJRZ)$k zt4YDXCrG-MFa9+{(zSJxbZgDqE0%g3jile!BI!C`+(`N@+}mm--AD@lB|*~7eDRwM zNjKL?(qC(C8~eS-(MUS17D@fSxRG=iqIlIvx{Vb4IziGMeDTW+Nq5vqQt7p%zpm5p zqMxgK9F3%3)FSCFU))Ig1=irJk#r9!_<4e)<$Uqe3`xuDBj(!+I<^kU5o5|4NsjievdBI!|I+(`Nn0+Q88 zT0si_F+tK3d~s-oq$lbm>9(4^^rXkpNSacMq^EpwBWVh}h-xG~OA3CFAn7^2_+Eyj z=jtTs^qOPoj~+)O>AST^dfpc|lD>LlsSuB55mI%R5Cc^r+TLu!%q zx-V`d9fGk`ZS%@oq~PlblHTEquVzSkr%saYtSNYZ^*9vkaPFVV_uwq}jf>ku(wNp&Cg?lY%cKNSezRpUaRmw@#84 z&P|e(KBMATkE8X{XKRr(&lfk6J_{eOTITtDQt+7sNhk6}F+@Z^v|lZf7Wv{v(tZ%UYQ1zO zDfm=^q#nN5H$zfSog{T#k`%o3(V=I19F3%oS|pw0iyKKDAgNkr(fOocp9D$0e6d%C zq~1D7T3&N3E%rDXNqg2J=|W%JNZJ#ES8cuT5>l{7f}~6NVz&%Qm)1$r(wZ9YGLNH? zG@%wrOMG!7X#yq})kwOM6zrNH>1w{%IYZLbb&@ox&ynJHc(O zM$+}9U`J0%s1*!Hy;*6)iO!?uT5&#khH=QeU=JI}D<9elA(hDCQ|s4riU zCbbg;aa})ttc;{|%E6r;Mu9Ku^YLfJb$I(dIsuoF)`r<~? zRtN)BBWVRG*fK%V6MQiyL(&s@n!xz zIz!-pmlG(JL_s8V=F8=UfV0=9uXrR)pKgHP6Z&*qO?`Uhxk-JRPP+S(2W|`-Rf}P- z`r^j0QCI@3#<17Ok@Y>pim&qpp9}dUg|BC*&+5~034Qu>&FjS8@HiStBWjWKrY~+J zjX*rV8cFYvg7p$4t>%m73`wi&B&qg|)bDy6jijbpB)#X08%a%w=T{@?15(iFNs5*^ zu_n)prSQfp|PpCxus>j5v?QFUw_o74MuOc(MB6@vdN~K zZ9Zm;EwN z{c{bSMQ%j@L~AP^$%wAti1u(2Uh{xEn2@HC}Ah8Yo->WuI-OKsypJ_e=b3??-ASfFk4#QE!U`WI=0wFs-+sN51z( z-Fz^;S_-nAMLIgB74j?XM0d4}m(<3bPdoCbloA$z1| zokf{C5P#@z&0Exb#-&g9yGLdps@d*~fLsi^;QJ^h@JtW7R|#BS7&$J^bnHWaN!BB@ zZ(k(6t{rW?Zm0fN>vhQJklj8Oj2i)p!YbYV3H-iZYjFqs)8e~*dwCRW(~Usp`=Y@d zdp6toQg~Rsf4*mq^*(eqAcK)+Nrl1uTSr?Xeva8)srN7R5UuyALu=Q$I8z5FrUt71 zdPYM1HLR2RgVNhBhYyq4y%mM4+LOu3kR3|U5Emz3imh$s=@s|uD!947cIc_Cwjw@ znmZBy=%y(h^G;7;XcY9gZ|S*sn4m|ap10EZk+VF4^K@{K1$|NF!6C@-40%Fm8R`1t&aG`r_|YK+~R3X~OOca8|Q1DQ>TU|&?CLRUo5+3$~l!WKg^;1mm_ zo4>Dc&r~|9fV?F?&bRpBh=lfpQraz->qU#SS#XY1jH0~}tr)YE=olViBwyl6+YngoKiXX$f^#GKVmJ9b8)_7XDJIjT;MTC38 zki)WtSHtXXA!P&^s@tgWcX zEUV(hu&@*KN@bkPKv>F!$6 zun-v&0UJRhu{oj-)jZJ;+Xy!rwZfR?T z)OiE3g$y8AfLaE^xi?T#LmG$}MH@h5Ky?EFocMDs1F^XdAeM{`gz9Nb8L|dK+mFW( z*fWtNxA7WcVHMqxas#3EZ+w1!+CUszim5S%Z=$+!KK0?|QDH{3CYV7(K?S|BDNg(d zYYhwM9C!vhWE6BcH3;<_`>M1Py5%x!fdkG9687&zkI+MEKj>ZydtpB?ISJr*Z3En!jYjClM$u?vfe_;)@Fw@meF6VCIi_`VP7f`kbBxmRoiz}rdv=(7 z6aKK}J8d9n!szFlWD>t(0q@|{%d2t&(PNFr!kvd?2fO9Iz%DQlAgcwn8clV}=qfi5 z97tLi8X5CHGZ4za1Y>D*#Xw;62s=5wXi{=zcFUg=2BI(O5woEJRBiUdnz0}bT_Nr! zcA0jcx7Le&XJoYe-R;ow&FeG|2s{7xd|`8D1v&eO;Xyb?CnqpH@^fn$-S^mIk3IL=d!LSdKl!QsKE3||oy92n z%x6FM`7cbI_{A@M>B|Qmc+gi4p7hnPeeLUq9P*8Ce)C(Czx@y2`R;eW_xtsaAD&Q9ie$*w%<%;o(8i*g?e$zFeBOZw5flNd3FGL2( zR7C7g{QK*wTGC8AFN4S-wGd&X0vT8ykrpDtw_mG*$a8EQDNsb@8UB4RIn*SbyQ@6% z8B>o2c0c>~D}aO&?Cw4Acu;F`IqM-s31Jkex4S$FLG#&-fQ?R){_$p#&)v>a&^oxk z)7BwvDlhjeG2{GYGzGO70!VB!O+AJcLV^%w5dcB^i{#5txW%?|DBP~f;HGI#b>Oxc z`FsF4_<7;;7(RXykDrsrEd=v@@%&jL4rfZni5s_5m8&`mFd8IYF+Xf;ME^DwA7ej7 z?58c+d&~4uyN{_w(dGjE(D8#8RtyrN;VrM@0=lEmOj8kL(f zsO(>_^lU6beiym7pLEKG!Zu+ilY!!1(TMt;Eci(&7)Zf8_+sBgL7A{+WYAF|F@<=n zc(Z)Fr^JFB9c7e2R^hDH7zZ|HqT!S=HkK-nr%fnM_mHeT6J)L1uupf~-JV<<_Is3( zi`c;s8Xg1#tF;+H-{{ArJnx!`TS?Sjc?<-sXaF!HNxuCfX-L4*z&UJYS- z$y{^{9lr*45N7cWk@mpLr1WFjn$+?kM?OZ5t*h~XO8MCcRhlU%aT4O@+`3Z7hWM*= z4_m^l2k&5=-xHk0K~bX61)^kU1R#KEB9Jbr;`^JAaeuF1f4cEL zD4lB~eKj8hK40(;ixKfp4sQPI2lu<=SPL7Z(q6|={b8nyb+L3UM|FwJkoZfYi>LFY zg*H>8diqg1u}+R^&OejG8tZ0e;_^kI9jOOFn@vdr%P3jhj8MvYb%#R3X*uC6j0@3d@pWE*a3*C~PSxx0WYZPVsplyfbPV%w3PW&3 zgvkqxEOcxBnFxhVD=G>_+OO?dnDJ{Dc$S!7D|r-Yhxp`7#ZxjB{ZiR+WB)%DL=8KK z^M&48icl+qteX5G8E*)#@}sfU4Uq$)@zu@sGe*O#AOHBr5oy&=dpjep+ir&sqOSPt zu!DqNchTVMo_pbA(bxSDf0Y32XFmH`L|_qul?d!X2O$K@80^;%`NlWC@y%}`28$r< zcO(q^gDHpp@E?ElqaXj|C;#+MQ>Xs)XFvbNFMsvx!w&n+KgXK2*d1o0v#+MK>u;%D zyYm*E?TeNm9}P~`(m>Ykkx!7`dOE!ngSan{1crYB2un`k$XOYPv4&p&ILMP=4#4>Q z;=Cq&P&@xK!hlQ}5=qyCZ*P>vJn510_0OMtc~o!DoXRvQoF0ru3Jz{o_GJTPR2_;meY z2NRizNJV6{x~aGgUQZF!OCeT_)XJ3tS{|7(>k4b$aSkQ9$U22{JMrT_h58K6i&s@b zq6Yhm(o%xYB90j9vdU^mLslL%g6C!70?)1oR2IGu*slNELzOkgA}!>DpZ_?tc=rr{)P3Ud_54Z3-}RpPA87Xh9Dq!LV^lkf>8u8DO94wt5)ggvpa(9uTgD>e2Ac84awC~L+) zc~u8@b1HDK44q~f1Ot3=kQ+N3V=(N^g_dbj2Zml?6`D9En*EsiP^+~f0Msn3mZhHq z!D`e!0@a$}>E*>6Gj@g`d|T8@3uXitZujKRY>8pT1Tp5c#E z)GOt*4o{O**x-=}Dl#r5CNL4G1avwNFEmvfm#e^A@*2I6(9`L0xx#m>jms|pbb4G$ zbOLJ#4j?+Yz;-o&pd$|W9&W47eifMUiUZPwVPirNRniyy4 zYVT#L?JCvWWQt9t1GOLcI(>@X&Qiw(Dakte0orddC)W6C7il%_goT`|=fF6r7!gq? zRNmwGGc^u`kR90I;ym`kcVLNz1QB%TftnpS=cw4_G$v_OJ;~U#COXE~u@01wI9&{p zQF2J-*>~WvzK(SuH++@{g3|3A=j#}51*wA$EG121y55PIda|`89#&O)<78jWdP4%y zw7(b`vYH@&Bf+{oALYBuy^T{mPbbSQFpMe~xWTmj!<;U%bH>Y^i}64wlhUGhrpLet zW_ljN(Fm7~hDvOLI(88bLT6@DK57y15J#CY8|uFn$cXAe4YZGDVK^U!CUI@fBBm0@ zVV`03xC|>7o1=%}#2~!_J~%6Vg#5W4cZ(WqBuaCfs(3L$6ZCJfHRKSa)_8j zCyEvcVo|WFrP#}t4E3-d;40I1^di=47{sB2JV>_1aA&or!r>F@x$Pv=vt*n@j=hX^ zjkuScZM%dxFa!jzjq6R|GZu#s^MTuhSdYwjX3vzRLxFG20Gx_L@iYPuId;sgBnp>$ zcA6+K)p>ZLu$V0{&N>WHxQt~bF`1%p*heA?S9;t{6f_dEmZESqQIvR#GE_w2TE5i8 zyb7Xl?Jz{)Fo=RsA6O*zmM{o@$60sSnePl!U&Jj&rSjntaCAP7U*=J7w>^mA+wepc& z&)oOCnM8lb$Ok*1x58)Zk9~|$;7=3^ZIW`U5nxNa-D#(t@!18RUF9L;`2j%{!u-CiNQ(1 zg5c!fl;BkPb_d6g+I-M}kL! zM}x%@Zb2Z#P?K5}q1% z;o|T@d@l+w4llvCFT6Co4BsX3 z_ww+H@XGM2@apiI@LGJAhS!DH<9kDRV|Y_|bNKtPKfEQp72n&!+rvBXy)(QkTqfVU z!+XMe<-0t*FT5Y$2jn{t4ulVe4}}khkA#ngkA;80cSZO(zE6ZtGR9=-^GhnE&#z87 z6;HE#af#;7i{rD5;q5-S^<36Cx)E;GQ=v?v$L9z6Q~VlDX|Qrx7?m2}YiV$Azudv_ zx><^cA3T9VQP-?n8RmvpwG@*PS(sVDcJ+;SwD{bwGeQaK@p)N#hIm{lrs3>Xx(DkE zELo{xBu%DS1({~G=Q#;v%e&!Gsd1cr#S@Pd4_Z37}nJSfM z99XDfdx*et7S_Zpgm&Qh5b#$7Q&9+IXF6tcw#VkrIbr34B-AZ>^#UqGE&~F!FIt6I zp35y*QXwA}$6M{j0Gh}Fuv_Z5VceGrQ+>YzQ0Hk5I3dk6%tA%bBvlG{;w7;?E< zUyS05nS61TzWB{F3@5ykMXxLMoo<-)($ zODYerNB5C^z!v%p?ab(XFVh5y>gX*)dxfEmRl^(FMiys~qZgwj_TkAo%>85+URd1} zA*G{YZ@@a0bs?oIm`EUm$jM4*g@h1_8ZsonwI1467*QB`Xx|Lo=1|F|v6I#pJY-3G zakWnB%HV;b#zF0sB67HLBQJ1oQ*_MB)bDjA1@UwbC{7Cr^89MNIVA%VMU^)yDI+ux zd@kOG(I}zvZgLwhtXvAq(=!lRSGcV*g9l^ph{Ae@_EqOA8q_^OSCNFCYHU3>(;$kf z<%YP!ri&J*Ye1_Oe2o@fQfkf;h)f+mNELPLT$nR5q^s8Fo1UqD=9#2*x7j{5!fFh> zK7$jAnp~>e@G$G2>RzTg{P&sa-L7Qs1aiM9)lb38FlrEd;IZaL;)S)60(eITAnSrN z=+51P7~lc{*eC$+CqTTY4Dj9zK-N`&dqOoDh9|n0DSQSp)lYII)vZcuKDy-e{+G~o z(*Ag!$elpskoYR-KFv4t4c&~4JdtS+MNKl;ANk_jtbZI{q6qGQc-709jW73J>vMgAQI_t-%>aJZT=vioxBW*nye8 zz>DpL6-yDYI0KM%6(Bn}Ulf3E3BdIP;4Rbzcu^VPr5S*%s{q;M2Jj65s9k<7F~p0? z0I$jbWL*WwE;oRy1fX{LO$3M+l>uI#0m!-;9{xoDj`SqsMP-2f8Gx*t0Ema-=>m*` zP3gWrmIncUVtZkpDCl%de*lyr@)Ww9s-7$$XHP0`D+c9(Amf^t`n}ah}Eqw;v;I0A88f4`-ko z9ySDI)+~Qx2Ws&t!g`*Fa+b+7L)gxxHgT@oAA7>L-J?7b(DB)j2qLjV7 z*|xPxvkHjTW<=+H%Gy)L?Mz?3;M=mkMA6v!6`LY42>~F-S=~^MxLd@D_{y!LZG!$JaC1qNpE<2oExJjdUfr5x}N^JREw(Lkb9V`q0sbEQTMfiIi%6KZA_HaDrM~ z!};i598zpUK1IxoXy@XXv;v-v7loF2=u#W z3wCEB^{4m-&(Q{#k%qWI3{TR7-NI`}(5V^tcO~Hy=Pnub_mYr1K?vGm#7~ze&fwcS z@Kz&!sw}wu_-y`go3NYu!;xtd$05l+%cErxK7o}aJ62lIOzAMyIlj7$`dfhtT@2Yw zNgawU0)<4@*LhYW8~(mU`2ozKEiwVI^D`}3d32~aG}5YWLafkiZ`Ee|lg+{vf-GG~ zp8lT9rsBPjy5=T~m#F)iSL2h9mg)p*35()K83UPd*Ox&WMcLKP&5r-($hnHJZeW46 zlHe8bc{8q`||>sp}(Qo!_m z$YwuCW2w6J!A-txBThia#AOU>f1nn1G7Kt$;e|Xq_7387wd>fs`E;dVm>f1qi>j8k z7+ch39u2doQomk{3bi8ZQ?|{qqSbX}?A({NFSAy{^nfSS)L|bPmDCICqz(r%@GnWi zC(clZj4M6FUbzuUrx7u`oa?8kJYQLoZSNhDoJ?S)fVGYYz~ z^vK`XBj=+>FqC1T;LQ}@<*W0gleh|=aDATPFX!4X83p;2N6J(RiV}UNAdAnk{@Ly& z4ZiJYlO}tJg=myP&I?>eA?6iE>Q}C0{j=D982gp0`0h-7Cw}ECd~pW+%5$mfPe*I; zc{!bul6d9|^(+6vqKo(jSY}k@pEC5IsFtLaVzL4(%4)(`D6ObxDb3;qiqf-m4DGgN z29peZo0U(khQON{1W?o?fX3fp{gd5G$55aJ8f9_uJr+1g8n6LZODG^XL#i_Lg$T~g z%zK@0sApv1!wl*uDt)WMz&sCey3Zn*;{hhw^L{wu-Up3|vDk5J&Ce)K=e-?XwF4$r-3Mq+aKckq>qQ~$}rJkQRGwoudsAs(Ne7<-ZVRT6=+Vj#ZUihA0 z#3FO7nX;ZgmA}lchQP@g1W?o?0RN(!^=G=5l8vEgfkx?hVeE8ifEDX@CQtV$m>NBb zt)-2|-(8KKk-?)xJV?_ztI;z(Y*VAZ6B385MS(;{^w0J{O${Ci;ZEqataM+*&OD+_ zxUb-=Y4S>B`w~9?S8H(*Mf*Qv$(CaODaBN!En&I;pa@pbXnh&f{=*8YLW5l0#QOhE z_$t%V-oF!`nFcqejJN{6#KChQxSNa z<*+rrq6j>e!Tv{9&_tl2_!8^?(2Iby_d~*SBJd1L94bt-;ygPyB?8a0knD}GAc@aq z&`=0&_ECI+wQ+;GiU6Y{agc-&f)aUv?d0fL7O7jiz2e)qki2`9%7ogNVXL`rCVh9srjIV@Hrc&4}gtCT> zeuF5l6@T9I&DoTJJK5vr%!giU-}rAC@H~vyfhWcqKlzYUV1N5sQt^RrX1-1ZzADX_ zhi_CYPIi1=f`7+Syl^ZpP#V%9a%G0&Sk)|3M@I>#Tt;L(p`AV}c3b8uxi}#h=#`Vp zlPJ;?pE^6Ta`Q7X&3`%7e6rc`JQ72KWV6WZFPTc7!v~(=OK#W!3vuAD%gviOPfAbc zXZz+~&5g|=Jy#C`#`eiN;^VG2YtH7W>F90I47KT58R9b33cQO<<5maFuI-T{Mr5@B zI|eaq8*H!mDWpFViO1x#2P+qD9)v!!Tn-4T!*O^6<2UH_5dN`6c{^JK;(?iHj(ytAD_Wnk45%)_u=HQ7+<$Xwyi-}*&U$Q z=|!B(Uc$);ASn4}f2XO+P7MJbgKk1k!Nqg8dxmh5QL+L=8eF`JJXZmi^D$W`69ib` zX)*5=Con*Mb?(m`>bXR7KO*%JP5y9P*MjuHNeew1c5u?Z(x8j|_C~0IgTi{F2QH91 z*0GV+x@I&s$oG7>eqseodExu(G!NYN4dP$~*2qb*tu+6?`h@tZI9waic2 z8RG{w*aAelmHtYK>`pR{APZfl7wXbsX&JiAH++ohsvSi#Fy0cnN++_W2mBPxo65C| z2ga((ZpiVXy(ELy4k@&fN8`q(lW2ftvF1aM^0~}3;yDf>u8W4b+@ok32G_xtX_#Ji z7f;6cduo_#JQ^mo(Ik`?^(JlLQg)X+OdHX0=QY<{ zgQ@BLRnYpkc{EHyd4HMstxz#o_Kh|&8+iM|x^3X?9=J*97L>jUXx!yX8X7$IB#Fj` zhQ_JK*Nw(958Tk;^}XWf(bcSg&T?PF(Agw~j`IvItlu-Z&jUAf^iUNHlq%>v=xZ1{ zdN8$DBbyp`{&;=e+lMC&|8_+NeAZ#fvN5NwSz@x+$MrM}uRrI;Qf7wo632K2xU=?Y zWSAiIAj>g4rgdAyIF|7xYpkLZkT`frl4RuQWcVM^fGf6|#pICJc74mbtKpUS5jwY| zD92|nLB{6ugfiC(g--5*kg9+uDuYGDI2q=f0K+ySj;R{1fNalW4OS0l#s5peOvV)y z4!vd`XobCv?xM)85a-+s06xLMI%8-d{%gu`fwuzUJTT9N5+}S#E;Mk#l(*T#WP2`j zu~?C{xAI)*f-CH~aApNA@HPzX9aJawJZO(E1fFn#MaTu$f4mA1=ZJv|4Z?*+ash{D z$`P960*(-h5A5TPw?Z?{nYHUOvB|SI9stIW3vw(i{^g+O$>5Cq!U9aeKj_nm_y>o5 z*`ZH%AZDkJC-B-Y9zd3t9qx=d@C_|4wuWooSW9tlyrM}ZT%nJXf#eZlX-D%4V^T3U z+A_q{B4d)kP8F?bid`IEJ7KeveLp^b7& z5~5HhTKfUdjevS%Obp-fgt3OU5lT#Jv7ejzc)(a31R*ugwO;67-ck{}L`huNbAuO`|fXO`rZJu-ZS$Eo%>P9Np! z8K8-YHL(Tq^1H|CPLGvYNghtGtl+;LiAkifu zjZ2V}D_|2O8B+rT8lyJW9z{{Hq>PxVfMzt z?70t*@X`Awc;UndnmxU90w|d^Tb0kAi(a~j4jsn(q85pX^MZ=vss=k39g#>KlaRwU zu!@5eoat&zt#QpP#c(Wkvk_IK6s4Nf81;U+XYo$oniLqT=j+goS>2r;%5!}KrkLoP z?*@R}UJ30>sK9kFKVv3r%Y2;cAsP!>Dqi1!5I9G;y-~D^ECTZw4e`aPn;4Pi7+nSX zTq+IVKtbp{{xFCiaIk0DDe*}~lsSs+1ds9GGzCkQ4?!4GMVvOz>z)9(WO-TAfO{Pc z&c%!azx&Z}qK9g86y9=^n8A?`5=~ARO)e?)MT_03(uhf;J890Tst|1jy)9y$`3UKU z;Z8JpiZ$uo2l9i9GeXCF1nQ zdu~Rw@k|wwRSlKQf!RbQR*{uK77gCHWlFSqJVxgSq6;cH{yo`?<<9XHZN}go|3@0u z;vNlXwstBuJ(Y~t{py9kIGRlE(y?oP!LKT3JkCrhH99d^2{UhlYsQELh%jI?1PlQk z(uShmZ^KT2!jDg>fE2`ITR2?IVIb$-39p3^M{DDuy(!hfb4xK6*1@B3#ytJ~wkEi7 zQS*^)%{czI(EKerZ&X4XU^FyEYtX0EXU((WamY0_eekDRSh9C3y|9CR}ES54~#f|9PIqS%t4(fGxYD3`?e zk#(9U?)+wv6}hX*7dYJ)xIhcYk(j=~nZAHQ5NY!T&h`Z^)$^CVRK3x(7E%><`Y$A` zBd4DVa)$Ho^g}yJOKNvF>A`orNv?|Ab*1EvK|ab|`Eei9OK~}qj4e$VDIHNbqaC+% z#3#}41|`JvGSWHa+2Cs7tphD` z2b2z}=CUEhdqv<9z=Of<5@kb*lPrwW#E{w%Z!r8!ZN!VRwTIL$s3hai%X^)R?>67cdB^F?W?OU_&Z3=B~{Y@MCTb??P*-%R}|!E$qaI+c%eEkOodF zqBQ!!S(6-W5~xw96+=yfG;y4UF`DW_?%33j+X6+4h1h)^XF7~ZatwP3hw@TPFvJ>W zAcVnj2EE9iF`Je_Hcrg}OhRLkgHNw`#QY>S2_5m@#X<$6+d$iZnE;Qt#<}1!+R_3% zuM{J0Isi5*7GNA#ePmlgfH{w6^g1cPj4e=r`(P&4qcp=hH1hJ!a#5yHlc_c29C4Zu zC4vG@=urEiF)7}ugYkg@Bg3(=I1Vq=Tiu$ZV%~?LK*gaEfUR-3w;X6PR?2~^l>V)g z7i1)+ymnWi7vyt1?KkSALvLyX;{l3*dgXi!fOQ6n(}Yl_pB~J49?Y9+VmNcQafoO| z%Dp+?7k^y+aUHY(9fvlcN%^<9%jj_Wx#9_;!=0yBsl#z%j70E}qce^DT|r@8>|3|~ z#@ssY?=aQhy!M7+-(-J#g;k-Kw?hREc5Ehw_dX3u3&P88#T^9+hxlrbMP&uBG*iGU zfCo2$0;vBo#H12f_rIY=zN%^jiiDRd@}n0l+H@Belx>UyYB$HlWLxrFT8rz-on&$t zt=>hp>ja!WyT_h-5gC|dQ{)NR8S?y;hS`rST@r|j!5p!~Wmlvq1mA)lk@MDY;z%3B5XT5(iHXCv+f<0YrsJIw?C zAvXi60CF`)_Z?Bt9FU3+b zS3_w#3GA;#EeKDL9QX&OY7jzX>T&_Ekw4ANyu zy*{{?OQi2GdUOPV|GvJJ-PMJk;6g@p|;vJ{;wriL0$Z$Bx+7Yn6sqD*vk>hAmD{0zFx42jY8Tdt{b$C4cgZt{PM zJkQ%~*SCUvDL4X-gW!*`sF+F>@K++>Q`rw<^@SveqzZ1M(6B4OwF%E5+mq0vknPF% z2Uz!Dh?y|UvzQ(05lDWbN76^7UYa41xgktXQPE(}@YzE3J#s@UFU7(j1*XzTdjc_D z!y+u7dPH=DiPZpbVqN}Av4W=IToNKxXi|~F20+(CWTE6y#AZ|QXNd&*Zkp)?>WU2d zTPJ&{FB)X@*}^P1H@H362E0j5Q_JtENyER^!?*izBsoHQ&CoJ5_1+;bJJ)4ua=k@* z$@dNo6a znL3O)h#WeSGVR=vsiO-V%4kuAnL2l6>d0KCj0acVUhrZOxxYDWg22ThgP2=Xa%(B$ z@G$?Bk6Sf3XpzZ9oOXPVZ+LNX2?GvX?BpfVcgrL-4eMSH>*7FS9J=rTJ!7!S*TfB& z@1f-$fW^gRK32wsw;pzs18mf0q!|}t)mA4L?)MEF7w87cQc2xhc)-IlF6bJ^u(>ec z0c4_sx8~teh85?OaP-#8x%nc|uM%=ukn+wLMJ;y7z>50Mm)oH*tD#JFx@WzdIS+M( zWgt~>ol(PVUKpe%S<~iGNiUL)XCZPuw3?q{M^+P2g|nT+Ku-_a*`*lYqjVCI=4R3} zD3g@Mi=5z7QrzgHq&S1f_;gx`yL^MaIv{k8g`pIS!i3lrF?t<9q1PZ*pjTI}USuEU zEB0a7$uD|RZs$R7$^|_L;#Tj@?o@X&X{R{G^yK(_Ar%LjUWzN&v}%M-;tQBUj$^;G zN8AvDO3ch6XL|^5xJahf8ZG_khjW)NX%k4&0qBS)Y!XkXRo1Yri$C!eQr*T(|C^)V zr4cX)M(JxX7fyF1(5VpfN{`K}Ij331WMz&rioT3R6n*J@wu+@AXN$oL6E9EUJWrw7 zNjxp8!FO3OJ-J?d zdWMNlT&^-cSj@B)$BJl8NpmTv#iR2o;N)qq*uecwRaK@Ax8eRD!}0+1AU_zFjLS*x z6ytG7nnKhYVej>sGKFxQT>6cSDdtPb%`Zrq!sMEsS{1dtI7Jz=Zta#W4vh3|S2Id+ z1!McibsUe8!G+`+4T*C?#Q86if1uWj^r*M;C0*B`v>pqF zXv^9!C!yjG0wvs$3%6H5BHoA^Qer2R5WkNl;5t|d1O>xLPsm`HMO-|V=x_zNj?Nd* zp;iSEY92H}61G7V2Ibs7tSZEVM1B4ADv0xvT&pU}2;u{}FKs zF_&XOg~~U$#u6jVU7PVK6h<^TzzXahK~sBPW}b}kBMJpZLoa~{UMr21Em+L3cdrna zVe=fZQc0%}oTgHtVeHZlITMoBO=e9-SJq_ob9A_iR*V0JR&&a#V$E3nQL6zX8#&Is zzS&EcT^{N6+Ie9-V)LD0{Ke?N$~-?99C;e)DuRAVO3-P8bZ}N}obEpeIQ=ytR*0B|Wo2qR;{Ajce zxGKwTw&o`3Dt6rz6%JBXpm8=R*EpL|<3QbPRlN_Er261v?1NfPLtMf7fECP;Lv=JH z76y3p1#TLJ(8DClYJpQhP%E(t+Cuw~o`CDaG8IG>lT<-miAbs-Q!s^u3K9k5Rgfu| zLP7;W!z5LZ%ost0S3%5>;R~;VumYV_LCktdsvwyRvW8bdnnRudDjG)55uge(4U;GU z1(Q@kvT$6Eg}F^B6~r|Tct`=1i;Mmfdl6<0xTO~Wt}MmDI;tDp5kn|DDGhrYh z$|*}S)>FuCu%$W8eL_c7vJ{nApBGrIaI^EWGEDnV5oSCYgExoO=3SV`xjx=AWZ@E2 zS&ow26g`;}w_pRj;PPuD0XB+Hf|+Mi^tAp=ABFBdGehiW2pgBSc@Mkz02`wSmtSE- zk0_f2B%*A?o&=Po`KZu({x0zR&A9c`DOiIFQ%4K`0jf4e^e34H|U1Ce~fYcu;E> zg_-LCWTG&uxUyee2FewSNyW}86{21w?^JTMupTFgGrI9Ya%VJorn=bNm=YUNIvT&J zEH-h4a;4Lm5F4lrb@#dCM72X(3qj(bRhy@VmAU+|c_wz_^AoUE#zWgg*-+FZNtDW> zcPs024FM%yRS5(^;L))k6+jTMDGA`B4b_z$(#-rWYAH7-AU)7h|NH5QG3@w=IF8{% z9g`aI7nWjSsdvO*a!GQ;yU5#6BmN@a;JS|Zi#@2d8}XNT0GSd0Ms2MxdVl>gz3)SI z#lc*5jl4fKiY06}sB7fZv8%C&gFOi=bFvA63Beh25QDIBZGk*QaJ^FA*EzlemJ(;wDa~swl#~Aa5+%n8L`=jY}q`4cf%b6E(Gpab84vFtI}b zgEmyrfMq zeF3&0(B+JYQGT{K7D@F=)0H)7nCfAgGlW4?_3HNZRB}+xD8)Rp6-=4&)c9`q(htxAT01>pHN`_n_8pU|rw=WCqrywUs$s_zg{! zBkY1muS^H450+)A!7`*DA6Ka1$8XA^!Zi?dZ*2TOGViFO@t;?U5vx~TZd@yQInFn@ zuJUrc2eo$cGT#Hp$je7JI^yV0ZzkE z4&c$HxWRRmfnz+VwUdFl9>CvG1_tVtfw)2q84x$G%Cx_J8Hih~R|eic)+J~zfY(&F9*A44R|X!gnx^Dp!-Wd* znxji`gX=B>F{rhbffztW2HtM0(8%_B+k=hWa(=5L{Ia9zdzG!JU+#D0+nkP-Xm8S$)@v&6Y) zwJ(OijyeQ#SR9t+6+LrC^Cn#81g50A6QR1R{Zwj1aA#r7d1+k1M#LB=^Vxanwh&h= zE83W-I4{LvA%0%EN%_3gh7dMLxgo@1gNbfDL){$D8#?$<$w+nLhCZpl2rA~cnThLI zsUyoRGNuZ6W?ex z@pZ}uc|tK%8sz8sYC{e3USG7{LB4XWf}D$egX=oTFZ7_+ZjfK(0b~aG#kJ?f9Nrkp z2y=1>b4wz3mscOGgQ>yFu1^kD+!~HKF5^9-#v%T=cG+gV60PJLy*D{=s+X)XJaU=~ zFiVWa(pM^26pUsc8mXLm-BpSawG2~T<$?zrFFHYu+oDt1D%T$_c4*Mu)qMs-PkD~< z4Gu#b>dP=?Bvv?dQ?El!IHY;;m6l%O8n2%-%o@7DzO)q+UtTb8YN4+seMR9e3J!7wlTAE}<`^B$PX}iUYYgd3LhqrcP@C`*O_g%c6=C0>mVm&Pin!C%eY~F~yAhHug&J-btoecyxTo z2b@KA%fLXc!qT~P5%S&8DRNpQbrlkze5Vws)aY?<)mr3_IO8B)rvEGqax>(T(nzhnO{D2P6AclPjedH%L={kY~|cXcFWo8_avcvq0Yg z&$`*US<^XM3@lfExe(kEJ*5d6?$95FD93MbPC$-ofI)qBJlb3{cH1xTz0;-ZNt%U% zX&{s;R*z-hfT>$qNj7!MRB%v4oH>thOHj@eU^iLnww@ms*&(wPyGaBsM<5g^(}yvR z7kV7e)2RiQiDi3a)jAjZI_BNz8k=sZ({>bBzu486sl%j~+8)tmnL2U^K}>q3)rHG_ zolFMHBlP8mcXAdqZUGvXL2yo86Ca*0V`s|%|0?-WD^vQF>A7*Lr|hmtE^$uKGg!D* zV|lvcGHaeOMDyo$TFN9(tPxQbCEt^OOrW}Q>pt?+glG&lB65cV)X5lR&EcRCEG993 zp}{TlG+-Yow);a$WSPfx14FhUgI}?X9_zsy^&{oTFguEpXH4dz7MDcUCs!3#gLPshSRjfZEN!!o zV~^TIM}qM-J-E9)AfuTp+0|)IL;!H2o+BDn*k?j_im9jh2A)W+Mk^z^Tt|H#HwY~( z@eAg$%h2kJRgTx*v5jUxXW67wL zT&IfdaQjDiI;d?Xsho;jzBw*hl07%-ERRXXd0)99Ms+<2kHh!7SQ46G{~SIpIZ}=w zv6Fs~evAWRafkqq`$6V04u|DQ0$YC!2gLG(*mgN1c6)GK^+a(@HXq{El&at+>0-Cb zhZvvlN#{RIFU3`CG_VQ_A{%xm31zKWv%w4uZ-_CE{-H~RBkG=i)pdx3i|*apI?h~+ z9{tsix>>%RlT`jlNWAGxY*!(k9!OfN`5Zh7g&vlOb_VVo57%a)+X`G@RY6&>MT{21 zm6-QDZEM4lkP+`v8Y6P;XCd5=xG0`h?a*g&g^Y)`X;P;eI zV>5j6%8&iTP4`Ikq-O+oEsXl_*jh40ndjLCzR^K0*MI3AS1)fdhnyMO?h1J);J*rn z=U!%0+X)_fI~qj~<~NL`m!%zL0VK16Cs@WHlH)}y>bXcSW$}Wwz&CkbAiHI`7d#L5 z1PTqlHym*K@S*r^^uD+aCoh&EeR5j22W4XcK4ue&PAD`uUtc!u)E0lIBOyZx>>=D4 zcWIGt@MP_5M&goElsGHg_bj)((05Ju>=_=M;jia(4b`)3Qgm$pN_Vz|XjwJP{!n4F z`8bgvDs`uC+v)L*n|kN@MLc7oT>Q@V~*^jnZ4?&-XaIt1?69UBvsagmeRYmwEy~@l=NW>R5wbwOLJH)E58k zrL)(!^py7SXofC*Crfj_{6)U}JGv`W_hOZJHn-4*Jqr7W8QlcsL?tF zxC^#9MoJ!b(4$oPB0Nc+PlN0>!ybz~T@{{y!GVGmhv=jkrIsTLjkDUY?}TSbHADeV z^o!38lV&;YN2fZ7r!a_%qb0C~FlL76oS}zVESI!ALn*c!d^4ulbiR_X z9z(*oDFefAKsyohk-9e4u1fh9)i&0~<%~O-jkRMqSrETEah!&1uI(EO?`!SPdJ8-M z-}Qwz_+XH;k4z3ZKh&5or-j%KD|^#yJ1lp@$^`Q^v+0TFR%U}H(qrp7X{t79(Z>7ZOHz;20_b%$Pw2L~U6jw2c z`i(CCERz&n_^3DuUo#^&p_!I5uMVR^=XoA5-`oOHl=}~Ut#1d?P0Y zM)ZntF3JANHJ}sb0i1RNKTLhG69N?YMFK*coXJoVJ+)s*ure%C$NY?5n{FH4ULN_Z z`v@2{{3#l8d-gaTo9bw=O?w3K6R9F@A2$yEBrc*GhgsxDETS8SX-n-I-hn{3?XkoU zg=2UF54lZIJCv1l>o9jbA1bKm6~+vQPKn#WG~cRx-$9Wb$%Ko`azooZOe68VxKdo= zJ1n8QhlxI}&t>10VWL;p;#K+nVL3=_vaHP^skOn9TKjW=@~wEyutATq{{}iF-a?EC zE;sB-;PqH`*EiTG{a@HtPIIT?A9dj=MSA`iI=H!b4}pIjg%RA~T-1V^{S{qVD`OG0 znq_Ljfe_O|O9+_QkUxj#OIwu>JA2VjT{Q7!+$$) ziX+NO@bVZI_==E^cpl~oJk4xU0R@=N>moh8AV_yeqPendU-{Jeh!6O|WZNST5^niP z0PqmZrTH#4f1orEe&gIN62t$wvr)J!6Rrv7qYaA8{^2&_Ls3K$?phj;$1-?)IfVy1 zcnLwNP4zy>3SZU2F<+`sb&9!UoM@6M5FVV9CIr|CIv(Pa8His@KqR?S7~g)H!Zp#9 z!z+CFJc{w>#g0_-X{V%|oM(Ik7QAQ8Wbl5F;69gx{TZq#0x#oZuxGeUs!N~uz-?Y9 zRmbDnDAz4Ae@<|s$3Vv?Dsi@(-buSM12;->r6=G`w$Kl9nBFYPN+)H7=dYz^7Jv4@ z%uaNw3SKI=-IN97W)KkWNv+abZ+cKqs@uMQ0xxy5L64HF2d%tA?ta=q6uXlS^1bb$ znpEvq6)G`>?ti` zj=)F~Ew2FIL&awj^{KS0K0+a6q0TLb9iA5FqfQK&CS%|VyGx8loPJf2&QTs=WAIG2p30z z(nPXMPELdg5>rI42Ue$17j$7$X=23cEGHuww&VIhCl^J<>flZyTQYlq1-2D*fWSmx zg;j#dFiMSLbxfaj!|LQkM$xXRX_bbCl!`jVV{P)uh#Xa$ARs+0f6Kz9lUgNbVj&b$ zbRTiz60CRtFhycnWmAhYgNG-rpny+wTiODhmBFbUu;aFYQ&kIewy$dAN27G!h_Y%u z7U;YTM7_&XA(B;Mfi55qK4DhkN=!;K!4DR>Q+c{z~bkhDaooUuf=dXR?bhE+kDCAx!%G7V24%HT|!%-cOwLzMBbYKY1p@1PmEo1kU2o5*%K z--${xWkzf_f4n?+mv7OeSXUntW<-EntZQ;bGjcDRAJJMop8sm}3rR5gsHc#`j~YAr z=*)WD(u&xxlT!3eFU56Ua?w_nYeD`SgrWhRp?e)e*^Nyx z5WbJ+n1jI&^DyE>j5q}Y%~lb`_fw+Ce2F*%1HKyhGJzsyH{b9%opmv@6hkqiu)Z1v zp1`#U4}a35=5+rqms%lU0ys6#!L^zW9Rq{}1}SKO?ED*`!%&kcstGA5^D|H|B@i&l z6T$RE?Fj(v&XU3wy9*FxDZH%Q@jf9IJ+%Tqs6Iu^=(rkvb9;zfE zhqflnI9O9nXd;jq!CT}ZzpIc{+B+by5INQH8kw#{42qzngSu8FRBCT*h19O?K7g<@ z`Gs7!L#}0aEqBCNHj(U1clQw>hoHJ_moBDt^cV4Q#n!9Y-Evcrn!(8vRUXgkhGdr)LLIEC@CM6Os9LlPqRwaSQbnIeQDMrHXq9h#GAEpm9`rq2Xn?i2GTuv63xj+lrQ|;iEK*vREM;CIv zmqy(PH4!Uno8LfD1DayP8IEHP{`T0+tBQ@T?`kWoJ5EL??FaW*&^R&ckH-%1SEspA zUJ9qI=X_6uc|NS@dVxlY*Dr7@h67BCtjz4L!OWAYqOTqzybijrX1WRlNsa)dSsW1; z{Oviipejh7;59xEAdb^t^ETG@aX6e;*1-AHstqJv0f%#~jzud~JGQ%OE9!HmJC;fm z>Rk9w6-dvL)C|$FxQ@_Cr*$kVx{h^D2*)@R{Vd&!!_6u7s>2Q4R0^vPqqC~gmv%BZ zJm8^d&jV!Dp2uZ@LQ8gJ(uE*|ghS%+j~$P*Jts{6>yebATVjq>*D|m6Qcq=-FrUx2XcI+(Jy&aXvpC z3&-7%uEVYNKP76jL2+5AII%z~C>QWI7Dh!5GVspu@NBBZqRy^3-CsiG^jzz3h1i|O z5O+^H3=QHxrXZF<0>)(la6BJweicnPRA$c9cyhMIi+p<0Gp@6I%QoZsp|o5!DL z)qd4`EyJgCJnTQIQ~iS!RYY}C6`q`%sm&E+$7S}~B+4y!o?zuzdTl)Z#*%U6Uc11< zGaj?3gSR%l)|-L&4=IR$uU=d1Tee=~GI(m9JY=uo3_no}T#Nsv41LXF;N~h>^_G#3 zD7{2BxXyn_Jm8aWzs|QdwoSe&OUZD@e@2on_w>G^k~AsBX-ZN(Bkqa}#Dh~1|6YA} zrEl5#?kkDDqc_dWxPwfjdBpjb@w;l*lv=#TgEEn3(RC5&YcmjaecLPAzZYAU`j(9? zUreyYrh3B=>CI^yCHv#^5KEUmBGwE`+{#9Hr=9!@h6{hun%zzl^;!NNmr!@nPc3ft z2wKGXGlHP{;!b}+o5lR6uZo~D#WHR!4fXdKs8Iqct4$()w-LXh!!K6;Heu6Qv`6(8 z57hknP64W644JeGKw0N@gFHcjn`7}O%Ursj2z*+guoG(A@ZpT};gr$7ND2L2o;VYF zUD@^`TCXlxmVvmh5b7cRy@dX5-?9lk*UptS{8z1TEyHVUTxYdA95|RlaZy8ZjBs0< z$~0$WDkr+u>oV%!roikDiEZE*LuvlofjlI)&byigc0++i>>I=H*fPm06J@0s$w>T{ z$w-Zsj3j9k*bR)aWP4b#I02`V>)ccE4-(W5;}fdoQWEo!=dz7lF41$#EdDn!PGp)w zj@xLqp^JD{JeoOK$AWZ;qnT^g=~f=jw6crzr9zaZIFjEY*}6iH*3%<7z2fkw2WlgE zCjpum$pUakG6v~Uzzca^{Bw%@2|8r!oq2?i=-4|1Udf*TaY$$J4;~v6*Bt~K6;shG zZ<0Jo3!t-U5yI#Aa-8&?A(>|06CSedLfbyUJg1tH-H}qRBsUH8$qdl#5fA)7~2G`f4Cp8arRI zFLTISEZ-&ZqHob=oD9oqcjwx=pSd$~es&dxEq5HL?{X2j?$e7UQm? z57G^EWg2iR#r5{V(H@fZfd*ww%cBowkn{$M-_U&!m#HxhHG2BQ`iP#68peuk*je8f z(aBwMIk&Tx2gBjR6a#Fl-IyP{om+R*VnglNZ9tlZ4_8#!snF$uH5NalSt+h?@k8I~ z(@Sy5*LBm@wkV11&}yO!ZkSExOY9MVM8d=9k%5Q-!*_7DsBbzU%1!vM8UMB5zx5<% z0mdf8+9aSgQL@qDO?F5|3p$9WfP}EXbO}bN%YsxfTsJK#ZA{Y_gG6@CM zZ#m5Y=9X@iBtqlfNP1b=yN&F(2DE4AIk%0(+mVvrJfdxVU^c4AeYt9skOe5d$YgaA zdt}9f-k`XUQ`Cj*3gGq0K!n$af06gJo*W0GCx@)!?o+q>P!2;^HI1#{A%4*;M=(E| z2S8v`+t%kliv!{*OMB7*H4&Pm_)JuEmH?eX2nM1$>1i#DDvS^Xz%_IpL^7f<>WC@}ru6iXc5rs*%b)svTj>-%&^SpQV-k5GHTaejT_ zd>&0Qk8PB(dmNsz{HW~aECBL?TcAaV8Ox`XbP3x>CD~4v39c=&vi^k;hw z1=|uTC22=F%wp+JZv?;4<85x7o(Y4oShdc@nL3&fr|zCwc}Oj!UEG zuY57!UaUx$7%VRl4gRt0D2%~VbZ5M%4>k?}B7t6l=6XihSr`)pO^i*BB+)mjk!et4 zub6XKriJaQM6Jd#WZ?HQ;ddDI9Haa4I#6O4UjieJMeLT5B{<-W5T$PU>$v5mD8mP7 znw`oD{dmc)H8?By+L@w3KBxwSJXA8!WgIpgX$i*#Eq4V+Zsu!)7h; zB>C@X`)zOhhLB83^YZ8+#$=*1ZuXJ$ZZ=*2oZ4GN8Q z*?5y?qpKcu$1$S8NY5ma=`VY=--)oyQxn_Z#-Z#v3tUZDzQ~pANCt>e|RodJpP#XDx4{f1+%$FBQbnDtg}5Vy}rC1v#~W$!UTe2UIfP-vk?uxIVM&4 zLSNa`hh{5!&Xa{pA(~PDD;uUNUzDkwboZ%yN~QT?X;b5v6FE8CP_)uwv>?-{rN9_} z7yR|nEz^{ew=Yt(uA`_%|AQMJtsd0co$!5|2aq`=@VWrgJh$mYr)ijk<#Px=fHi zp8aVpqTKQ*S{yCYr?C=1gNp{IE~Un%n>9ea`!%-6CT#gnjpX2L*Wn4xRN=aMIbr9; zj|27pv*%3@cOF}RIWWB|$l;R+`nrHG4pGF1m$=I@IXof<=O{|l7pLR6vvGJT&ICCZ z2brmR?uF0ZJQ!zRITvTY{XYF^oQ-opr#l^IA`(^OOjR6-gEMiyCF!Z({oeP!$F#NT zxu^?Lv*#)7{X{Nmg@YO6DmIf~6*-s@y^pE2Y+?HWRhPWuEBaAb+2(zurR2 z2p$h#38P<4ivs4)@Ls_0${WoHW9-ikUzsl=sTm?gNsj%tCf~{FI+F=yj01u5SMaz6 zC*7Q%;@}lLZYihH5F&HVfMXd%X0jjRP-mzZnv3HZ!BZ&-#Vc)Nh9YMi;v{SwG|l}7 zJb49-t2oU>*k)=0$7%C~T8W5{MhIFXA#L!w+ASEdWM9mKG*)utVpua4WabZu9JrsfW zw(nJpTgK{M>{(_^j+DumQIAIIN&~{4bZiJePYHo;#|e}o0;GxwSi&9tMh1}@mCP~1 z98T@&;O~!uBBxj?DqDX>Lm~o{RTrG3SE{ox3E)SAv(yfF$76}d+d{dT+Ev-{;J_2t zTxV%G+&MJ`*&P_}M+~(jhHFc4PrPGd7GGh_qJTl++rP@%k3$N1Qm@NGP90!PKuBjs zR7@H@7bV#PyVet9ozS73fB@}iu6HFmp+OkU(+jl|D6KqHB<=*K7W7<-G3^+dBJYfz z?J1pr=BK1E(nzod_FQ;y=uWuN<87V5`w`s4G(9yKvJ>_PhRnB0c7mLD#Ta76Ug%Hv z0*XyRN8~Ajx;W=LgL|%u8bJi@=wQj6!dbw`3CqN~?(l?}B0;_t15&!gDae@EiYHoV zIFcB4$6*Kxv+88u%XfL8rg)iNg(NQaC|n;=x`I$A&!xPLX#zX7$}rxM{aan{-RB`E zLvxk&-XnyIKwDPvJpQI5X zbf#d3qyGNF>f1mpO#eaov4=5=D(gT-BdMpzF`ilirIS+dmLLTr^eA0XOC?N)K=w;) z4U5df$M26?BgU^T{mej8nQBN2%?rM3O*JsNio!6oY7jcPzB{CDc#$;daxauaX9}ma zQw}eC%uP9HIA|?3^q+{L98sK5(SPPk?iA%pZn=W~vo#+pXq4%!tQtyG4Z;G(QEGO_ zDo>Pk2a}`F9bnr~=2FJNM#=7|W-ld)E?$0}2%KCOcjRY94h|?0{QOXzXDvdtyca6lHBUF)(KFC8yyPdt#PhkQ^J6 zDvu2@o5F>_j-}{n#58-jC!=5*yJ=27@jO=7ZkZHUC7RHknom+rixc9-SP7V$@de8) zh=s{VYBDgR6azA&DCbk7pe)H2^coDhr<^OAC{K(^!3@qodBnVBCE#6Xw*+vWDbY8X z*U8OfBB)?;W5 z%p#dhfTVCCL|4{$rmM&>Ag7pgyoYQ|Vs-K02&I!Q50DYSaSomQg11tVftdsac#I>q z@^_1_wsO(PrlNNKiCMY{m8QF?i!KIExFsD~UEmSV#IVjC&h<5r%*`p7LBPxcd~i0g zU06rvRu6Zao)S-{kR-z$nJu={OK}zBF{{X6#jH{;aglj4^cR*@&Rd3OE+FQ@g1)eZl z_S8}0RyyI+_eE|ER8}r9NALrohY!ZA%7Gsf6IlbXzhy*~#qO)K!qMV8MaFh?&Z~|r zvO;r@JXNQ7s%*iNy%Og}2~lqGvwos9SN7TUU`B>_$5hx^`-`Exb8;Z_`sDb8@sV-V z)UE);k>dWy7$lHn(}8+YBb-ipaam{#hS|{#GP$znf=rQ==Obag0;y5YYgiz1J`}BS*WDKpyAwx?J0^p&4%rP_z$sAnw zd#oWn_KQ5PuGJNOO_Suv<$O~lUh;U+7St*mvV0*K&v+{>l)q-0v5^wh(;m1 z88q{_7Wns=aW=|5d9v962ZH??xIr(KKoivh^KG4)qB1}44L52jLg`U^rYFKOF$q>w zqS3(6E)bHmSBqBdmiskX)F>%1Ou2-6Lo7wiw#PG0WkDisKKkcry!H`s6<$y|ikCm) zqVP!W(2v7E^de zaF|8L(*TS{qKGMe)UzOc@6cQi$uzhQ6lJ?p&C)Aurm3T%e>P)i*%#B$TFUU~T_kWDUF^8}Zx z%orD^#sVWkkZm*AHWuvYFsi@ASl~jU?QfeR^E~jc5$~9sPZ+hw$LvzvwDmRZMl6&c z+4wl~&(7E7_(&&x&hc2-_|VhG)@FQkd077sd+!2gS5f4T&$%;6CK;5-vKZy3-XsD8 zs5=N^6d!Z1q7h%{`pCLIvbt*A^$}NHqXxJnlQ4M@CLtt~5MV$c!y_03Aqc{NfKfri zOQWKWh-*}I`z1^$9EWp%(}!ZPK|0Bhf5%9;S6Sf=!a0uz)eYXhWl$rNhq$&>_Q zHjYoGtPgFDC{s3AIVV%-gK;wDiV9?ki%V(k&Pxr*jLD`s%SFVMk%*uqwGb6f*iJY1 zsTm`XEZ!$%Y&i^CY^l~`6_!u zar2{TaZ^pYm#7E()a=824Afs~wbSg1TwFVYtlmx*=DJ6g*QvvFb%KP3SBs}q<7W6( zd^GAmW!wnhmpMSyJ>)_H3caC4v^y){VYF)wwvK4m7m6G0wD{O)x2}|SdXs<-n9`1G zJRGt#&QQ-eo$QSGw@U?LPyL1jIo;Bm144Gg=h4C?^Gwv|E%q4&NGImM^QNG26S!fp zHwB2Rbv++PNV{e6R)A*OJlK0!=7LGPPtjwEd};B@GIadOkYzSNaD&-& z0lGbK=41)QdNF=wZUd2J3zQJ^MPkm&-xkx9kt4n>ravHJx5ZE|BVPdhrug?{A*!Q> zy8Y%Oz=cQYBWb$=>S-+r-^J+PvfhGE(}Q7IIG51q>^#|Y$$Hy{Iue6em;;EEnjzG=0Tor z4M0rh6di=3=RH9mcg)R=E^xX$Kzmfh_ftD^J{xr}2UScT4s%snw97)>BB~vOSE?8n zlF$L!s|~#Ky_aD1nh2|F16IaCO^1?XED=2?dvFWQkG`E7R?bJeBkW$`FdQGuoAg+r z+hmMBLa>9+_rh%}Jo_X5o$!9_y(aGqiFZAAgihJIUa$Yz7hlK?0hX=nbypzFhGuQ& zy6;^bUkm_DyXcXj=EdFiR4d<&FsZNT!RN1&C}<^5K3q4*>C^Y@7gc*5EU7P4?k(KQ=DNevaIX z{oG^abKLWefBy4%HTIkryih(Tya?xja0&>=fN%~7A6%4uBCpEEhl%T7jnwtXU5|UR z{VmyYLH6Ij{q4LS+tSv*?|tuoKQ73|hj(Ou2)AT^r|FMsK{1cz}*H13`)TckQ z_>@ylJ*|B@GYSYzqO+l7P@fMNX-gvz{wllnzm6H)(7eg~ztV@u`JptS0x_fs42?0lpL$ptj z>T)>t%Oj&?1-%`3#A#-rf~|8LckaLfIWM$Lse}fXg$Dnq=A(?1!XPZ@^ZaRDIdE+) zxZ~7GgTS}XMN0q`;@=JG5*7LSN4a zO%7^bx3EcXaLdrP&uXP{Dd)wORbaoJo2g1<8{8&>k%g2Q^3ZNehovmH*~$&Ha_qO( zx?H#cUvQz(TCYe>tN+SSdJ{|IbdI$1JHF|c`bau4DdONW1KP&HD9Y#*mStchAmh&Y zHcK|c^$-(tY$Uw+xYhau7K#zluDI0=MJ4kVuo#=Wc!o?;f6xMEc8?9xtXiCMlx95| zs5FO#Y&O`=t;)kjXDc4Pl{&*YbxFq4N_da8Kx^HCKhX-`t}E)?1qsS1R@k`!0&&lu;ul(k!N#Evs_GCF}sRfs5P3+B^9h>tuVeIcq%k%jzT zHoAn>@XjX`WXk6$II<`Q1-rXiT;;owm5DvQBcXe;OrF z-=rHNopzDPi`eJN;#rdn*pCTpkpK%6)NM7bIbG4v2lg2?rHeme&3{GB11#L=2Ym4f zyqHuy;1uZ7Y1ISJKlF7fo*BJ_{((NiUf&`vA7@#J2e8|Ntot!MgAWI$;Xp2ZG#@21 zL0eFtGjZf&!V^qHQEku3WXnup^7mmv{-{AFCx4fq7ZNml{mfD|HCLA}z;38ZBv|z$ zEJgV8MbMfHnS%8-+o9SHB=E0=w5}vor~+))`!IXj%*tGerBtn-K!Nuxw~T{ z)Ti{nnU{@*2It|lYFnIhC=L1VW7*6Oq2)g* zsY#G85Xpa1f;3`+@P!hDMbBr^4+uqYz+w;bA<|A#@R-!?wFV2kUr-r{Wz)|C&Zg@Y zP&93;Z%4m5#|7g7Y8?t@{4i)gaJ<<{WOwXv&m@%kIxON?Tr1n^{|E0U*?0Ob+BCBk zC~Pk~NnuQ2J1AK5>)l@lT+eHt%}6WPDZvgj4%pH4)_RKfHA0ESfu9lmQ;Z5|ifA&*EoMfT#5UlTqp+G}0tYmOd95Ae*M6OAl!{iAJw~S8>Qug) zRqNmM{Je zFD6I!%<9wQg%+;|@^g;t&=PsR`a%`+d@*@L97!>}A=v_37b=>AglQdOjMj%z#_Mk; zbj3pER)W!nP{lBMQxQg~`)^aIXc)b*0Hbq5DZ}UuqhWMjsA3o~g~OEUBiwf=R) z5K5bDlh<*(xDd%JF23-Sg~fHUKr#{5)g0K@0v6UO9Qkd0evLc}4_(IRSIe{V&{n=U ziH&nIMBH$3K-+qH(r7)sG*q#kzKXyjuh(!&`@vArX#dI*tS%2F4Xam-hSim!ieYtP z3Gk~zNdx}!(SUCcRSfvc3c9>E?egbCMeA~HY!$CfDl#3!$dlr_P{*)*aY184DV94z zMZ@w0R;)TP4x2{B_%1VhM2rvF1I0M_+9_UDhGUiGH-)AjP+89Fb&zCHWcg%%&B^k< zX)3pe<(AiS6A8bI8bJ9bIX+3``0bn!&qog@(*}gif{s)t=LPu=?HYeH+s*_zi>e@p z(Vr9KHxT6U9ko07@AISw-qc0PTNCfQ`Rj3Lcp8K@ZLkOU0{Lo{fCf8HTqoY|VL>Kv zaN_-&d~uA7k|TAI%?<4mE5~RMPrHQu;RA*gWQaoy7j0^%bdz+POJL^ z5NrKe1+DK&8S>kqqP2dMbQSFz3z}J7)aUPn%GN3~nT|YlzL(UI9rcJ#1ykqyp`u|b z+uO`~59;V#h>f!0P{)o#=#F*HBD19S!RC1=)VZ`xj9A8kHJ@IO?WBi89U}xcl4ZH& zaf|EhN$SWxu1~TLg1fZ(-m3jYsAK)%;ik-=+h!ez60{lm^UF}j`h&p%F`{b^P8j&!jaI9+h`>N(a{m1_n)EKbhm=8j{l+KQ*snTa44JgYGIJ<&p73wj5}+c_%q#u9G` z8g$vlW989NTar|kW6&cSZ9PdHJqDy3lxpa?cmY|76r_q=9$;LY$vg-W7HBU~+OvC4vB;dT_rom|JEX_DLf1ZbielXSU8$sccY?4r%AC zr7B`pF^h_bg9y(|fG{?ZP#8uSPo1+u>F?{36UQ1=65_0!9EM}Appt;awV}2l90C@x ze3X)jw(`1{TMvD?6-{4$kR5s z`03zh3*9^y)>Ch^_Na6z4BEy_1w=n@0&vI0qm z!4eN0UF0IaK*fk*E(*1c{yd~&Bdx|42OWV|wN5}`u89=LB?%B7mn;I}2T+00fllC> zdm-MCqnr@gh9A%s@1^0Dw2*|@YGKG(ewziGEsd;4m+NpE(Q-q|FKlwOI@UiF9btyD zY4nD-;y=X1@~)g#V=TsWQ7obYyq#`P@#CRAaQ>lJI(~lnEF9r{fD+BB(ydlFev$rY zY))3tHw03e{_r845`vkWZ2MBEP!iI4kcD&(Y|4dnjwu}f<^bD}3BvbAp2-|d_(HTk zlaf_aLsaq~O%q|k^dU{eYq^sg%!Wqe_DFt8j))mSes*cd{8PA8ru?La#IRK(K3^UH z8J}A@Fo^|PR`C^$iyrU{r2O47K#&|J5EQvU6KRhoT~WBp$MH3mu;q zWFpnjawl%RF@r=n*-Y0NMP9y$dHYi4JwNnsY|ML6s8GVZE*^P9J|1~Y%=_5@J7L}j z_9bHinE3?>Gpo6PQz7mnF~=_G1lF0mTMS%TVj=8|IGpOLmU8%$#3bMme~G0pVsQ`2 zSX@u;H}f?&18LiGj(|D3lAzBOjTj6<^@N`x0G-TL-6$;OmZO2CIEAXMr{)>UNz*Pn zI(;bH?}DmaO0HEEYFe|1_bPSnLgN%0HItmbXnVvwig+n4}Q zC00zOO$DXJL}Gh%bt}c%0>#va%t_cpG4WB)LDs{O$u-FlDVP_R67GcBzup2d{g?GU|w0P9=&8%Mp80@6ARS=-5-SJry#a3;5f- z)-@2QTC5?j2^CDpXr3N5kn)EfZW_0cxi-KyWOP{+g{7uRm##}H7KIWHq}|_u?WeYFazu)i}zz%7J%Yh zfbe*zKQ8VQDjb5hX4vBpd7GtK;6X@}dh;lHaPC}f)01J&wc|&cy!9Jy$%lNoWC^wt z%X7B0-e_c^{yckxl_=okG1whvG<>&q=Z)$)YE+8Lu2a8b0&l}UluY|Js$9<0kSSZ2 z|8PIRwD9W)u%7owgbmQp{HoCW1`Ri(;VsD1rU&(?2W*0OM-%+aP}%f=PVjC)QKl%r z@+^g0PH{1a*)BrMS>t>2qUy0=Jk)j;hNQ!Gitt#M;6XDFTILu=sBs zNuB+=rXUx&iw(J5IBq;5qi86dup0vcd84S{bk?R&vcwvCvYGNX-DjpeSBoO`M$AO9 zIRH*fq4#FlY4od9y7>n&fbdzab4q6Wu4uMbs3J6e5<@!!yl*o}EXZ2RftsS~hKg?{ zf8rd?wZo)>l7!$XZ}k4CQHE{Ts$mTsa)UU8lA?P{7YMO(^&~t(4>;?3f_b})+CWSievph z$bTZpFLIxG`;fSgo-d~SlGDux@WZ^myTdK*UKiP?|R-;DX%Q&*W*b5{B6w zjolFiW5-!Yt7t~GQa?xnl9>6Q9(lWzfH~n0lgEQ(lwX8rJ60B(H!B*xMH}U3=ByY! zSbH0TgJ$Qf8y7GtKZtW4CM;YDF5r>*-)E}P9COv$q&-B488^YZAi0@%@(au&ZVt2l zf~?;V0DMjTXL=UfF^QTfrA#7R8F6}l0BJPPV_uHaY0!0-L#)*GlE9vt=8h7Hg>h#=oP{m=0MeU0T&NLy%C-v!Sh}Vz#&{v}i-12cFyzj9u6SPPsb3w1euJP)4y& z7IL2t#SMj~{4=^lDLv$Wt<_Es`D-dPZ4`Hg(3Yd4T8>f6SSx4w?V{@f9)>pU5l8d{ z?dwBvLtBeO#)g&EKqfLnd~FaOfkro!qOFOp#yqPc#Xfva;;OqbAevu@6e#vDg_0#J z5aisHW7mV4iBrRhkzZqU-F|a`J;DlPC|!Zvnp7-WffQ7{J*gO0Agd3Avf4kXC@bCJ z4~lB8=qXwXFcp|y79VOVeC!5W-JWrJiud~PW*@!ImiO7}sh(N0!F(mU>cL1?QLWYX z=u$?+SR;d_F$?mM-bTtXQ$hufGwn}64ArNS4 ztON++m(3&OmJC83;?SZhmKqw_O8jdl{P|vXrFk?pC;h4LpQajiQAEs*N%PcZNWdtR zY7jvUJil!&3C%vw`ih%h@shu8qP!1750O?I6Xh0IjBaZ z;*?*S(if+~5(rV`@j=3JiL3|D0r%LkPf8yth~L11Y62ZPv*HKR#+SGGU`x-xcH_(U zve1vlm)hM{`|bkLl$B_B}eLs)pU_4}5GJ zKlF>5Yq5ALT@^qzsZ+-baP`@~Av}Ga(K!CjcPCCz@m^q)$~i*S8K&GBWB-NFJ>xa`0S<2H{q;(%DvLZNEp!+WvvH-5zCe?MQPL zXpkF2zf5P*`4Id53M$^5RP?^Td3h_~)=;iE5!QT?4r61a<8Yl!1d{Ew+X5t0-Fk>b z>ssPS_?F^CSaK+ZTX(9;=VNla?{GbhuGa4e?HY;N2#m4~xCf#26)WeCY{?m!%-t`* zrQ`nB#^NS;q0`4u$^58V#`=+qN4M#L1S=9Ffd~nntJRzJW>Xic24+^sWXEqf(!z(M zcx`tUmiv42TKE{uTP_VjnBgqa9LpOXmQ7h|bQZ+G7wvqc#WS~afkxFyc_@aIu@tsx z!A%hl(}d%5fD&sra>X2Ukr7} z7fL}e37NXP+6MUsOMyoKp^vfIJxLTMRVXC_ri}@Pz*Cz;i?&+Q<)h6PVM4lLaYq-S zV9&6N(}_MpoNgUv;%K}UI+v(nEiFHWX19c9?^9V#tzI8mp7ZJwYUFg$#{lNM0A`gY ztWq`ZL_SaheHMZet+gtsLhWhjM+jXIAl9TWsx%$f@YuBae7;!HZI&K=3bksJ+H;94syov7VPrTMZGDO;z3z)qLP|u(^c5 z(OoxCR?wA8@?_M-TIGpUS!jaYsMDN+YcR-OPy+V7d_Z4~Gjbb(+%-R;H zXaS33)KS|*#r(36s6xdAKD{QCE7nm9Y`k+iYHp#9x;8*6*HLp*9mTM$prRIl!<>qO zLK|I0T_2i_RTNMU9lgQIITdw0n$1i@^)rfOWDSM2-&0!nvG6=`RMJx^ss@v{WHI+} zq(-PC{M|R02$8N>((n~bSC{~2_*17%N%|oz;!>uP?sSH(E)PI#X6wbv(afehQBu4C z2u+Y=+14B27&6$j;Ib_ZU|UsGloK7LkuR~#C{Zj)p#B_QU-12)CM56fzI}s*{TGg7D|-J7=TwrPw$*`d&i`vh%nlS9h2f^AINEKMo6hf;n&KeS@}UKB@D;1RemsaPcYx2G*$oKy@mY`-V{ z-W$ytu|;x+04#`A+{)a+78|2DgqU_DY_l+yy$uh&*p94*aq`ou(2iUYAeGyZV5QjC zG2x`&z5_P)-qiurLr2#bdd`l_C;c8~n)cG1_6La6qXEgCgL2{aXf#Z;Z$=PqOB=p| z3AZV_=I@LTTk!H2jpL?_j3(n50gPR5NEE$$3hN+_`3(HyE9=4!k8>hey#bcxmY_qx zZFIV}Er#6-21}`pXM|+B@VvsAj20uid1YwPh(I5$8MeC6bbFpIctY$yXAFw{$CkAx z1+8ir#Om@9RvicJHdPi0;)4PXCF_F6qCsX*QttYK874nD4dr|kh*ob%AexI>6VqK{ zzMLbp@Zy0YX}YZ8o43OnjAap6VaSydg)j>|lxGBxHfwdr-I`---9-)EH@>K$-T*kU zL4L*27&#~fudLzKQs8dBX!Te&hfL zj_-o{SMN!=e8pS~VrOLlIA-}Oi|53byedE{m#@=P`PzI5Q5Edr*69$&qp#D~gl0#S zuYFd|$ybW?%+~3*c9hE3yoI?h-@zv*l21%L+ts0R#{&GwymAo1M>uxJY~Av~o-PjE z@zfoh%GlL)Ugg8ed8=_HQ@z$&rk~r+ShpvP7KHTI;%s6Vi-CLXX=9fPyAyM)$MoCRA; z3@tKJKBc3^&0x4x-El{|??BXCG^@`~x}vUFvFhcF8%M{^7{(&u!lbgEF*G_n;qI4g)^jRG?>>XjpSo< z0Gj++PQzq5v9=&I$Imnqd16r)XwRDiE+&)X!vRQ(EulHT`(p0++?WLKEdjP+QM9Pp zm99;0O)3^GY6@0Ew-3V;R#JH8qX5^PhO&zIyChAGf+ zJ9q?okedSpYDvVuKyihRE&=Nc@vPUlK11O0wssG{uw{-g9p&BF4iEY$fY$t|<^IsJWfYs*QJV<>TpZ>5(NsSlZ4=14Il!{j$rOdf1rM5z z5}qimS!C|z#sY8&%x!3=q7^9-@j zG|mu_mL(Q%Z!|L~YMWC7_+v4g7_#pLL@~SvhAy)56NkgckW*?4l@=yY3yh>+mM-(tB+r?2$K+(L!eAImctB^?)S|t_aGiwsXbn-SI|L$ve(8hym zj&zEsngdZ)n+0gFNB~@b&6YX+%fC*-rVTD17cAh*2)}H`V)7*f) zI8$I)@8Y6y!Hj$4&Y=)>b4vn@>tv8ayNQICf*B-kr9RnrQ;dm}W&;T@N@@=bG^3a) zIy_nw|8#MHR^nYa*zBX*ug=*=Fo8#3m|hZK+pG%K%IQ<~dBKSpbJSR7jIAj_jS~6X z7tIXigoq3Q#wlqlf*9EP1X$A)R zG6kmzFwUBiDYzv8)-(k{@ZBt#f)^*iCNc#F z1GJJU=$0s}ZyfIwyez;@rr;Hf%^2CoSLx3GVd6c#Y2rzYzFw9o5rGHt07}VZTOUm} z#_5h=3>oV;8$+_zC8wvxkOyy*4cwkLhGsCJpSygojj4`NHNlCaVb2rMA^M8ND{}T1u6;{dqYFL^~ToTh2Ngfh)gLiT-pz}vY8sUtF2XE}l z7+kU@=88qy;VW(r;M;E8ZAa%X;!G=ctd>U~EI>6r=DjL`je3M4UPcLb=U43ZON(|v z!O40R=^b>Rnfr1ce?OTQl*(H~t7^RSJpW4586qs8T9v5PPW+?Wq4nV#G?QSMPiq5S z#?1LBR;GPu!IZT4Y;F4#nleBFrVB7Rg-d8zR8Gg*yj21`sX-(`VwykX?9iUkSg*6K zqVs9k)`o)8xnN5R+>&*?$SHIcC^4%Fuxi8bO6)36XId<#s3+uUi()V@w07Kzgi35i zyozRiFdn@GD73cfvAuU3;Q>Y4z-7%qQ2Q`!Gy57K8C_nJuNi%dY{Mlb<~gb}t)tf3Ld zxRug4f!BG^Ip8?q#dwB$DB^@KB?A}6gDa`R@gTa?T;PBr`p2%=#>T`IdrP2-33v58 z>6UhZNA}C1f{`)y$hw?R59QOf%oxjxiRa(5;b!y4z& zN{N95oimoS2wNhRA!!kEQ6=5zp!_STKXti=fY6?Hz& zwMbS3O9)Eat;BvEhz5iHS)@t{3Vc3BgL0deAyzaZ)#uxm8}+$N3%D_5E72)=tXAs1 z%dqz+f|%KEsF=B$;LL>GDbv)HXH& zyK##U*OCA^4N}9Gpeg#SMtXugj&BifvHGl=(>C}1z%unp34c#HB96V*fM?wTAdjlCc{k$B6G}Uj|3#yPH?eM!;e*+fZBGR+u z@xr_~awdxMEVu@>KOk%Bx9Fn#f{L4yiV{s%U_ERJCCz$>qoG_n)X%$gs9Xn(?yNj7 z05;r%BLD9HyQ5%9!W28O#l@HF!Nd`k3Rgz* zR+b8n=~97%+9%99ARF}D_?P_;{UK)wpkTkdz}_r=yU;$^BTE~;tzWiC06B5@Po>1=YXK}(>S|c}AfSZ?2x}Eq)aa&dbu35f7x%k*R1f|J>(T|UU+1k3G`n06!0UR8 z+3CI19kvIO%i%=((pJwN*qH&?6`635+Ed^-gVk*IIZ5sTtO)=TyXmfjFt^$#e1QiS zLu38JOnpZSKXRIwX{01!w`@`&=^>^XJ`6ezA;+5WQ2h8$f5tPOQLR>IBIzOThCl4E z!w*0Fh$A{XJC8hyH^e`Ocf?~VsEYu5?5}MOXJ|CGM^pb;l& zG)q5+Z}q+KVVD1hbtCkXt)0GuoI#XZgqD_7YYz~UrtQ(*^6xmYA+N!3xwhg0g2D5CrwYa z_S!Xd3nUE-1`xYU=ovQ+Y;$5TR&X~3P{v$(Ty;5i>LJBL=gL4pC3G6sYuTLJ#BV^mNZdPu1-g;>b_OzT-A) zy$4&j;uD}>O@Qj{H3^^=TpHN!fE_^j#`cW$JV}Qfw-`y2>GO@yo{^M>o%gTGCQ_cH zXj1z%lQs=+T*K}VFHW0_f8e-WB>Q}MYvrEMf{_W*kLQ^i6;TGFyqgTJ`>aMPeP{@V zi8Hc2;~dK{XNd89E6r(w$3^zYnSw{%F0vzS&PN@D@BN_<-^(W=*u``%pcYIYzq;%% z%-mA29QjrNYRi$lnaI6fOnq67m_X3w2&}Ks9Y5a=u+4xG-xHZ0c4q-H-wPE=Tu}Rt z%!2`TVom+ezGwdr){{DwTUvNl)^d5}l6m3e)l-;Fsbml2+Q_=$2KWf)XO}d51!HI3 zG3PSf^eOmBe5_4O-DCAqrq(o&?P@L22(fF@=4iA514b>)jbTNiU@VoFms#Br_NxQ-yL9sL;D!e(+Gd8#;yD%yp-+Glr-I_a z3fl-k8T7eDu9V}JH}VZIa3FNG&zg0iO`%KDVrS@yKbDa@uxaAO9TbKS0V9I@XR(4o zbb$7-=&Y4U@lGqvwGEN9-qwfje5%&;3zf42Z7$K3j>guzT7;mhBcWFTgmV%ISW8eu zG-W>+P8}B;Lq(g_vLcTv?n*0eN-7rZXAh+n&rK>8xk|RD70*j523N^%$8~1n$rLj7 zfvj;}6GoDj$(J3Ge4&xhBwzG$K*sSQ9-^Gfc!8n?`lXv#z7dm2PvAv!oWb0?n#J2a za7iz&=AxbMZk6L|Bp2}~uD^PtUHs(SumvCBZp%kuJjp7Jp{3*{hzWrlabjP?<6sE^ zSRrrYVunc^m8i=AqA1T2bGY_s1BH{M5QKMdh_^wxzR)>4&N;R|^vvd15!>xe*=|Fq znCQKG$#!EoSOMLJ6X~+>XW|>ndQ;ABH%075^Ra;4xPu99DrYxx0JrxF2fL@?oB562 zPr{OJu#?5;@=)BHfH1&iU$v^2zkwIIB%46;Fd5U?PJa2-+i7#m=Vo%;XQ5#TS5=poN&K`Fvy%h{$VU{}} zh4?d;a}=gus-0sN*y0+t70XXvwr(AKKWFD9JNJkdUs~=PPDMiBeI+9M>CxMhupY^vD_FM zH9@7W3XD4%odstZYl1_Z)5u0MK-d%@Sk{$%WTu>wtpWo(0n-6a^O)G^}a(itSUhBqPU&dsps13pdL@%(GT(mCBJH-+6s5EOlEr7zf z@v$#v;R{1A?o!)dtkV*v%7HM(T5kZ0Ig31rj^{grTY)3yo@%pWS4MrM6Tgt9*}CUT zvUOE%RfE;#0)*Y6ak)qmXT@=mq**z|_z_|(526AUkM_%e%IMOkg9I#_PF|8Bp&`i0-Z=!Tni>AAv2TqmDZI=x06a*|v}L++&Y>9t2y7 ztL1h#wJf8}^HJ1iRS@2!3c_;bNwNqz5`yG-ND@YM%0=GKXk9?9(veerCsKHcW(5G)!EM#v#L(gxWShhocY%NG{x_7>x#K zYbmV`lV%xA%jPjqu)5SX*;N>|V5dn&DpNrKDoDm{C!TDo)Rn}X3^R?y+_-s$8e|L1 za(S-20ydJN1XG1%=S!ST(%Iq3emvgN>Ky;K*rQ6ccW|_$D_Wb;oPGn(FS*Lz{~}gesYfRc_q3@>UF<(95fy zT>*;CNx1a5b2lKXaZL`~q^$0>8mY3-q9-{_8AP|o)UWLGNR zs1ds#`R0Mpgz=5WDCu0}`drR{G7+p}ijicwD>DM)=s}AgPJ^L1-h&pE?(zJ=AUvr> zKlE>lYg>JdI4~@+MUt)sdA9LEPD42<%yfp{B*d+%a;Yj}i#iz@Q(^+{bgJ1*z@t&L z)|8$?48RZKoFE)0^^7MCXvZ-y$EDmm0M9TOI8Wk3oGTi>0b^O>f^y*6c2Ro-)~O@3 zi__Lds3^5a#i9UiC6_X0M+E6~{J(y%7^w7;Ab1DQA6~4e($?W|X4BJj>d)>_t49td zAHx2ykZNze{+EYEpuLG_oXBEB(jUF3Rf2+{-C^^JQwW!}R_dCTPfRSHLk2jc^>EHK z+EaFi9o}Z{lGrL&bU4-q34gdTHM{HPDQC|v5ctV~aZ-weH7B?hVXmy@2r&0VO zRMl{hZX=}srzVGlr%A(rZ8?uCs%naO){2b8)npDW}&kJS8&ku1Mx_ ztlhG=+7y@Tx3FLm+V`O0mNq<~D|N58DO3lF*wUE}U$1Eea_*9xr%z6`X-PFuWqI8W z9^{5!|8YL`AbSn)Jw=>R$yMXZUGM6oo9-QHazf0#^+A@mf8s