From 97b01db23e6c19c3cac03072d9a0af062eb93012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 13 Dec 2022 17:42:11 +0000 Subject: [PATCH 01/21] Chore/more error macros (#2686) * cleaned up MixProcessingError * Added Error impl to (hopefully) all error enums in the codebase * Replaced all occurences of error("{0}") with error(transparent) * Changelog entry --- CHANGELOG.md | 7 + Cargo.lock | 24 +-- clients/client-core/src/client/mix_traffic.rs | 4 +- .../real_traffic_stream.rs | 2 +- clients/client-core/src/init/mod.rs | 4 +- clients/native/src/commands/run.rs | 2 +- clients/native/src/commands/upgrade.rs | 6 +- clients/native/src/websocket/handler.rs | 8 +- clients/native/src/websocket/listener.rs | 6 +- .../native/websocket-requests/src/requests.rs | 4 +- .../websocket-requests/src/responses.rs | 4 +- clients/socks5/src/commands/run.rs | 2 +- clients/socks5/src/commands/upgrade.rs | 6 +- clients/socks5/src/socks/client.rs | 2 +- clients/socks5/src/socks/mixnet_responses.rs | 6 +- clients/socks5/src/socks/server.rs | 2 +- clients/socks5/src/socks/types.rs | 2 +- .../client-libs/gateway-client/src/client.rs | 4 +- .../gateway-client/src/packet_router.rs | 6 +- .../gateway-client/src/socket_state.rs | 2 +- .../client-libs/mixnet-client/src/client.rs | 2 +- .../mixnet-client/src/forwarder.rs | 2 +- common/commands/src/context/errors.rs | 4 +- common/commands/src/context/mod.rs | 8 +- .../src/validator/signature/errors.rs | 2 +- common/credential-storage/src/lib.rs | 6 +- common/crypto/Cargo.toml | 1 + .../crypto/src/asymmetric/encryption/mod.rs | 59 ++++---- common/crypto/src/asymmetric/identity/mod.rs | 58 ++++---- common/mixnode-common/Cargo.toml | 1 + .../src/packet_processor/error.rs | 69 ++------- .../src/packet_processor/processor.rs | 2 +- common/mixnode-common/src/verloc/error.rs | 6 +- common/mixnode-common/src/verloc/listener.rs | 6 +- common/nymsphinx/acknowledgements/Cargo.toml | 1 + .../acknowledgements/src/surb_ack.rs | 34 +++-- common/nymsphinx/framing/Cargo.toml | 1 + common/nymsphinx/framing/src/codec.rs | 63 +++----- common/nymsphinx/params/Cargo.toml | 2 + common/nymsphinx/params/src/packet_modes.rs | 14 +- common/nymsphinx/params/src/packet_sizes.rs | 27 ++-- common/socks5/ordered-buffer/Cargo.toml | 1 + common/socks5/ordered-buffer/src/message.rs | 26 +++- .../src/connection_controller.rs | 8 +- .../proxy-helpers/src/proxy_runner/inbound.rs | 2 +- .../src/proxy_runner/outbound.rs | 2 +- common/socks5/requests/src/msg.rs | 4 +- common/task/src/shutdown.rs | 2 +- common/topology/src/gateway.rs | 80 ++++------ common/topology/src/lib.rs | 4 +- common/topology/src/mix.rs | 79 +++------- contracts/coconut-bandwidth/src/error.rs | 4 +- contracts/coconut-dkg/src/error.rs | 4 +- .../multisig/cw3-flex-multisig/src/error.rs | 4 +- contracts/multisig/cw4-group/src/error.rs | 6 +- explorer-api/src/tasks.rs | 12 +- .../src/registration/handshake/shared_key.rs | 50 ++----- gateway/gateway-requests/src/types.rs | 2 +- gateway/src/commands/mod.rs | 4 +- gateway/src/commands/sign.rs | 2 +- gateway/src/commands/upgrade.rs | 6 +- .../connection_handler/authenticated.rs | 11 +- .../websocket/connection_handler/fresh.rs | 6 +- .../client_handling/websocket/listener.rs | 4 +- .../receiver/connection_handler.rs | 6 +- .../node/mixnet_handling/receiver/listener.rs | 4 +- .../receiver/packet_processing.rs | 16 +- gateway/src/node/mod.rs | 4 +- gateway/src/node/storage/mod.rs | 4 +- mixnode/src/commands/describe.rs | 2 +- mixnode/src/commands/mod.rs | 4 +- mixnode/src/commands/upgrade.rs | 6 +- .../node/listener/connection_handler/mod.rs | 2 +- mixnode/src/node/listener/mod.rs | 4 +- nym-connect/Cargo.lock | 11 +- nym-connect/src-tauri/src/state.rs | 2 +- nym-connect/src-tauri/src/tasks.rs | 4 +- nym-wallet/Cargo.lock | 2 +- .../nym-wallet-recovery-cli/src/main.rs | 14 +- nym-wallet/src-tauri/src/config/mod.rs | 4 +- nym-wallet/src-tauri/src/error.rs | 2 +- .../src-tauri/src/operations/help/log.rs | 12 +- .../network-requester/src/allowed_hosts.rs | 2 +- .../network-requester/src/core.rs | 2 +- .../network-statistics/src/api/error.rs | 4 +- validator-api/src/coconut/deposit.rs | 40 ++--- validator-api/src/coconut/error.rs | 8 +- validator-api/src/contract_cache/mod.rs | 4 +- validator-api/src/epoch_operations/mod.rs | 12 +- validator-api/src/main.rs | 4 +- .../src/network_monitor/monitor/processor.rs | 65 ++++----- .../src/network_monitor/test_packet.rs | 36 +++-- validator-api/src/node_status_api/models.rs | 85 +++++------ validator-api/src/storage/mod.rs | 138 +++++++----------- 94 files changed, 583 insertions(+), 714 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddb76af927..0b66b2305c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ## [Unreleased] +### Changed + +- all-binaries: improved error logging ([#2686]) + +[#2686]: https://github.com/nymtech/nym/pull/2686 + + ## [v1.1.3] (2022-12-13) ### Changed diff --git a/Cargo.lock b/Cargo.lock index 822fa26726..7ce237d55d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -586,7 +586,7 @@ dependencies = [ [[package]] name = "client-core" -version = "1.1.2" +version = "1.1.3" dependencies = [ "async-trait", "client-connections", @@ -1116,6 +1116,7 @@ dependencies = [ "serde", "serde_bytes", "subtle-encoding", + "thiserror", "x25519-dalek", ] @@ -2934,6 +2935,7 @@ dependencies = [ "rand 0.8.5", "serde", "task", + "thiserror", "tokio", "tokio-util 0.7.3", "url", @@ -3106,7 +3108,7 @@ dependencies = [ [[package]] name = "nym-cli" -version = "1.1.2" +version = "1.1.3" dependencies = [ "anyhow", "base64", @@ -3160,7 +3162,7 @@ dependencies = [ [[package]] name = "nym-client" -version = "1.1.2" +version = "1.1.3" dependencies = [ "clap 3.2.8", "client-connections", @@ -3199,7 +3201,7 @@ dependencies = [ [[package]] name = "nym-gateway" -version = "1.1.2" +version = "1.1.3" dependencies = [ "anyhow", "async-trait", @@ -3246,7 +3248,7 @@ dependencies = [ [[package]] name = "nym-mixnode" -version = "1.1.2" +version = "1.1.3" dependencies = [ "anyhow", "bs58", @@ -3288,7 +3290,7 @@ dependencies = [ [[package]] name = "nym-network-requester" -version = "1.1.2" +version = "1.1.3" dependencies = [ "async-trait", "clap 3.2.8", @@ -3320,7 +3322,7 @@ dependencies = [ [[package]] name = "nym-network-statistics" -version = "1.1.2" +version = "1.1.3" dependencies = [ "dirs", "log", @@ -3336,7 +3338,7 @@ dependencies = [ [[package]] name = "nym-socks5-client" -version = "1.1.2" +version = "1.1.3" dependencies = [ "clap 3.2.8", "client-connections", @@ -3403,7 +3405,7 @@ dependencies = [ [[package]] name = "nym-validator-api" -version = "1.1.2" +version = "1.1.3" dependencies = [ "anyhow", "async-trait", @@ -3541,6 +3543,7 @@ dependencies = [ "nymsphinx-types", "pemstore", "rand 0.7.3", + "thiserror", "topology", ] @@ -3615,6 +3618,7 @@ dependencies = [ "bytes", "nymsphinx-params", "nymsphinx-types", + "thiserror", "tokio-util 0.7.3", ] @@ -3624,6 +3628,7 @@ version = "0.1.0" dependencies = [ "crypto", "nymsphinx-types", + "thiserror", ] [[package]] @@ -3707,6 +3712,7 @@ name = "ordered-buffer" version = "0.1.0" dependencies = [ "log", + "thiserror", ] [[package]] diff --git a/clients/client-core/src/client/mix_traffic.rs b/clients/client-core/src/client/mix_traffic.rs index f61a83af95..ccba8f86ca 100644 --- a/clients/client-core/src/client/mix_traffic.rs +++ b/clients/client-core/src/client/mix_traffic.rs @@ -51,8 +51,8 @@ impl MixTrafficController { }; match result { - Err(e) => { - error!("Failed to send sphinx packet(s) to the gateway! - {:?}", e); + Err(err) => { + error!("Failed to send sphinx packet(s) to the gateway! - {err}"); self.consecutive_gateway_failure_count += 1; if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT { // todo: in the future this should initiate a 'graceful' shutdown or try diff --git a/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs b/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs index 9b75669960..ef1c03046d 100644 --- a/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs +++ b/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs @@ -264,7 +264,7 @@ where }; if let Err(err) = self.mix_tx.send(vec![next_message]).await { - log::error!("Failed to send: {}", err); + log::error!("Failed to send: {err}"); } // notify ack controller about sending our message only after we actually managed to push it diff --git a/clients/client-core/src/init/mod.rs b/clients/client-core/src/init/mod.rs index cdf210a27e..f01bc74dcd 100644 --- a/clients/client-core/src/init/mod.rs +++ b/clients/client-core/src/init/mod.rs @@ -209,8 +209,8 @@ pub fn output_to_json(init_results: &T, output_file: &str) { match std::fs::File::create(output_file) { Ok(file) => match serde_json::to_writer_pretty(file, init_results) { Ok(_) => println!("Saved: {}", output_file), - Err(err) => eprintln!("Could not save {}: {}", output_file, err), + Err(err) => eprintln!("Could not save {}: {err}", output_file), }, - Err(err) => eprintln!("Could not save {}: {}", output_file, err), + Err(err) => eprintln!("Could not save {}: {err}", output_file), } } diff --git a/clients/native/src/commands/run.rs b/clients/native/src/commands/run.rs index 4267fcbac5..d5c7eccbdb 100644 --- a/clients/native/src/commands/run.rs +++ b/clients/native/src/commands/run.rs @@ -95,7 +95,7 @@ pub(crate) async fn execute(args: &Run) -> Result<(), ClientError> { let mut config = match Config::load_from_file(Some(id)) { Ok(cfg) => cfg, Err(err) => { - error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {})", id, err); + error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id); return Err(ClientError::FailedToLoadConfig(id.to_string())); } }; diff --git a/clients/native/src/commands/upgrade.rs b/clients/native/src/commands/upgrade.rs index c84073200c..6aaa732624 100644 --- a/clients/native/src/commands/upgrade.rs +++ b/clients/native/src/commands/upgrade.rs @@ -59,7 +59,7 @@ pub(crate) struct Upgrade { fn parse_config_version(config: &Config) -> Version { let version = Version::parse(config.get_base().get_version()).unwrap_or_else(|err| { - eprintln!("failed to parse client version! - {:?}", err); + eprintln!("failed to parse client version! - {err}"); process::exit(1) }); @@ -110,7 +110,7 @@ fn minor_0_12_upgrade( .set_custom_version(to_version.to_string().as_ref()); config.save_to_file(None).unwrap_or_else(|err| { - eprintln!("failed to overwrite config file! - {:?}", err); + eprintln!("failed to overwrite config file! - {err}"); print_failed_upgrade(config_version, &to_version); process::exit(1); }); @@ -146,7 +146,7 @@ pub(crate) fn execute(args: &Upgrade) { let id = &args.id; let existing_config = Config::load_from_file(Some(id)).unwrap_or_else(|err| { - eprintln!("failed to load existing config file! - {:?}", err); + eprintln!("failed to load existing config file! - {err}"); process::exit(1) }); diff --git a/clients/native/src/websocket/handler.rs b/clients/native/src/websocket/handler.rs index 7d8d16e97f..476eb0a567 100644 --- a/clients/native/src/websocket/handler.rs +++ b/clients/native/src/websocket/handler.rs @@ -373,7 +373,7 @@ impl Handler { let socket_msg = match socket_msg.unwrap() { Ok(socket_msg) => socket_msg, Err(err) => { - warn!("failed to obtain message from websocket stream! stopping connection handler: {}", err); + warn!("failed to obtain message from websocket stream! stopping connection handler: {err}"); break; } }; @@ -397,8 +397,8 @@ impl Handler { error!("mix messages sender was unexpectedly closed! this shouldn't have ever happened! (unless we're shutting down - TODO: implement proper graceful shutdown handler)"); return }; - if let Err(e) = self.push_websocket_received_plaintexts(mix_messages).await { - warn!("failed to send sphinx packets back to the client - {:?}, assuming the connection is dead", e); + if let Err(err) = self.push_websocket_received_plaintexts(mix_messages).await { + warn!("failed to send sphinx packets back to the client - {err}, assuming the connection is dead"); break; } } @@ -411,7 +411,7 @@ impl Handler { let ws_stream = match accept_async(socket).await { Ok(ws_stream) => ws_stream, Err(err) => { - warn!("error while performing the websocket handshake - {:?}", err); + warn!("error while performing the websocket handshake - {err}"); return; } }; diff --git a/clients/native/src/websocket/listener.rs b/clients/native/src/websocket/listener.rs index c7825fb345..cf9c7cfa65 100644 --- a/clients/native/src/websocket/listener.rs +++ b/clients/native/src/websocket/listener.rs @@ -36,7 +36,7 @@ impl Listener { let tcp_listener = match tokio::net::TcpListener::bind(self.address).await { Ok(listener) => listener, Err(err) => { - error!("Failed to bind to {} - {}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address, err); + error!("Failed to bind to {} - {err}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address); process::exit(1); } }; @@ -63,7 +63,7 @@ impl Listener { Ok(_) => trace!( "closed the connection between attempting websocket handshake" ), - Err(e) => warn!("failed to cleanly close the connection - {:?}", e), + Err(err) => warn!("failed to cleanly close the connection - {err}"), }; } else { // even though we're spawning a new task with the handler here, we will only ever spawn a single one. @@ -78,7 +78,7 @@ impl Listener { self.state = State::Connected; } } - Err(e) => warn!("failed to get client: {:?}", e), + Err(err) => warn!("failed to get client: {err}"), } } } diff --git a/clients/native/websocket-requests/src/requests.rs b/clients/native/websocket-requests/src/requests.rs index f50364a3cf..637db0daba 100644 --- a/clients/native/websocket-requests/src/requests.rs +++ b/clients/native/websocket-requests/src/requests.rs @@ -132,7 +132,7 @@ impl ClientRequest { Err(err) => { return Err(error::Error::new( ErrorKind::MalformedRequest, - format!("malformed recipient: {:?}", err), + format!("malformed recipient: {err}"), )) } }; @@ -210,7 +210,7 @@ impl ClientRequest { Err(err) => { return Err(error::Error::new( ErrorKind::MalformedRequest, - format!("malformed recipient: {:?}", err), + format!("malformed recipient: {err}"), )) } }; diff --git a/clients/native/websocket-requests/src/responses.rs b/clients/native/websocket-requests/src/responses.rs index cbefe54242..8b4e60963a 100644 --- a/clients/native/websocket-requests/src/responses.rs +++ b/clients/native/websocket-requests/src/responses.rs @@ -173,7 +173,7 @@ impl ServerResponse { Err(err) => { return Err(error::Error::new( ErrorKind::MalformedResponse, - format!("malformed Recipient: {:?}", err), + format!("malformed Recipient: {err}"), )) } }; @@ -249,7 +249,7 @@ impl ServerResponse { Err(err) => { return Err(error::Error::new( ErrorKind::MalformedResponse, - format!("malformed error message: {:?}", err), + format!("malformed error message: {err}"), )) } }; diff --git a/clients/socks5/src/commands/run.rs b/clients/socks5/src/commands/run.rs index 612ecc02c2..10d2d60ea6 100644 --- a/clients/socks5/src/commands/run.rs +++ b/clients/socks5/src/commands/run.rs @@ -110,7 +110,7 @@ pub(crate) async fn execute(args: &Run) -> Result<(), Box cfg, Err(err) => { - error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {})", id, err); + error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id); return Err(Box::new(Socks5ClientError::FailedToLoadConfig( id.to_string(), ))); diff --git a/clients/socks5/src/commands/upgrade.rs b/clients/socks5/src/commands/upgrade.rs index ff41f3ce6e..db77167f34 100644 --- a/clients/socks5/src/commands/upgrade.rs +++ b/clients/socks5/src/commands/upgrade.rs @@ -58,7 +58,7 @@ pub(crate) struct Upgrade { fn parse_config_version(config: &Config) -> Version { let version = Version::parse(config.get_base().get_version()).unwrap_or_else(|err| { - eprintln!("failed to parse client version! - {:?}", err); + eprintln!("failed to parse client version! - {err}"); process::exit(1) }); @@ -109,7 +109,7 @@ fn minor_0_12_upgrade( .set_custom_version(to_version.to_string().as_ref()); config.save_to_file(None).unwrap_or_else(|err| { - eprintln!("failed to overwrite config file! - {:?}", err); + eprintln!("failed to overwrite config file! - {err}"); print_failed_upgrade(config_version, &to_version); process::exit(1); }); @@ -145,7 +145,7 @@ pub(crate) fn execute(args: &Upgrade) { let id = &args.id; let existing_config = Config::load_from_file(Some(id)).unwrap_or_else(|err| { - eprintln!("failed to load existing config file! - {:?}", err); + eprintln!("failed to load existing config file! - {err}"); process::exit(1) }); diff --git a/clients/socks5/src/socks/client.rs b/clients/socks5/src/socks/client.rs index 3b35a4caf9..e5a8fc9d56 100644 --- a/clients/socks5/src/socks/client.rs +++ b/clients/socks5/src/socks/client.rs @@ -220,7 +220,7 @@ impl SocksClient { } pub async fn send_error(&mut self, err: SocksProxyError) -> Result<(), SocksProxyError> { - let error_text = format!("{}", err); + let error_text = format!("{err}"); let Some(ref version) = self.socks_version else { log::error!("Trying to send error without knowing the version"); return Ok(()); diff --git a/clients/socks5/src/socks/mixnet_responses.rs b/clients/socks5/src/socks/mixnet_responses.rs index 7613a32019..d4fb8fd544 100644 --- a/clients/socks5/src/socks/mixnet_responses.rs +++ b/clients/socks5/src/socks/mixnet_responses.rs @@ -25,9 +25,9 @@ impl Drop for MixnetResponseListener { .unbounded_send(ReceivedBufferMessage::ReceiverDisconnect) { if self.shutdown.is_shutdown_poll() { - log::debug!("The buffer request failed: {}", err); + log::debug!("The buffer request failed: {err}"); } else { - log::error!("The buffer request failed: {}", err); + log::error!("The buffer request failed: {err}"); } } } @@ -60,7 +60,7 @@ impl MixnetResponseListener { let response = match Message::try_from_bytes(&raw_message) { Err(err) => { - warn!("failed to parse received response - {:?}", err); + warn!("failed to parse received response - {err}"); return; } Ok(Message::Request(_)) => { diff --git a/clients/socks5/src/socks/server.rs b/clients/socks5/src/socks/server.rs index 0bba59ee0b..a7e0a3c0e3 100644 --- a/clients/socks5/src/socks/server.rs +++ b/clients/socks5/src/socks/server.rs @@ -103,7 +103,7 @@ impl SphinxSocksServer { tokio::spawn(async move { if let Err(err) = client.run().await { - error!("Error! {}", err); + error!("Error! {err}"); if client.send_error(err).await.is_err() { warn!("Failed to send error code"); }; diff --git a/clients/socks5/src/socks/types.rs b/clients/socks5/src/socks/types.rs index 669a6b1093..e561d0025d 100644 --- a/clients/socks5/src/socks/types.rs +++ b/clients/socks5/src/socks/types.rs @@ -40,7 +40,7 @@ pub enum SocksProxyError { impl std::fmt::Display for SocksProxyError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - SocksProxyError::GenericError(err) => write!(f, "GenericError - {}", err), + SocksProxyError::GenericError(err) => write!(f, "GenericError - {err}"), SocksProxyError::UnsupportedProxyVersion(version) => { write!(f, "Unsupported proxy version {}", version) } diff --git a/common/client-libs/gateway-client/src/client.rs b/common/client-libs/gateway-client/src/client.rs index e1c2654b80..bb6fe0bbd1 100644 --- a/common/client-libs/gateway-client/src/client.rs +++ b/common/client-libs/gateway-client/src/client.rs @@ -305,11 +305,11 @@ impl GatewayClient { if let Some(shared_keys) = &self.shared_key { if let Some(plaintext) = try_decrypt_binary_message(bin_msg, shared_keys) { if let Err(err) = self.packet_router.route_received(vec![plaintext]) { - log::warn!("Route received failed: {:?}", err); + log::warn!("Route received failed: {err}"); } } } else if let Err(err) = self.packet_router.route_received(vec![bin_msg]) { - log::warn!("Route received failed: {:?}", err); + log::warn!("Route received failed: {err}"); } } Message::Text(txt_msg) => { diff --git a/common/client-libs/gateway-client/src/packet_router.rs b/common/client-libs/gateway-client/src/packet_router.rs index fd63077ee6..c64fbf92f8 100644 --- a/common/client-libs/gateway-client/src/packet_router.rs +++ b/common/client-libs/gateway-client/src/packet_router.rs @@ -89,14 +89,14 @@ impl PacketRouter { } // This should never happen during ordinary operation the way it's currently used. // Abort to be on the safe side - panic!("Failed to send mixnet message: {:?}", err); + panic!("Failed to send mixnet message: {err}"); } } if !received_acks.is_empty() { trace!("routing acks"); - if let Err(e) = self.ack_sender.unbounded_send(received_acks) { - error!("failed to send ack: {:?}", e); + if let Err(err) = self.ack_sender.unbounded_send(received_acks) { + error!("failed to send ack: {err}"); }; } Ok(()) diff --git a/common/client-libs/gateway-client/src/socket_state.rs b/common/client-libs/gateway-client/src/socket_state.rs index aa96b9a4fa..8c66b20906 100644 --- a/common/client-libs/gateway-client/src/socket_state.rs +++ b/common/client-libs/gateway-client/src/socket_state.rs @@ -115,7 +115,7 @@ impl PartiallyDelegated { }; if let Err(err) = Self::route_socket_messages(ws_msgs, &mut packet_router, shared_key.as_ref()) { - log::warn!("Route socket messages failed: {:?}", err); + log::warn!("Route socket messages failed: {err}"); } } }; diff --git a/common/client-libs/mixnet-client/src/client.rs b/common/client-libs/mixnet-client/src/client.rs index 600268b69b..f3a04f1099 100644 --- a/common/client-libs/mixnet-client/src/client.rs +++ b/common/client-libs/mixnet-client/src/client.rs @@ -122,7 +122,7 @@ impl Client { // We could have as well used conn.send_all(receiver.map(Ok)), but considering we don't care // about neither receiver nor the connection, it doesn't matter which one gets consumed if let Err(err) = receiver.map(Ok).forward(conn).await { - warn!("Failed to forward packets to {} - {:?}", address, err); + warn!("Failed to forward packets to {} - {err}", address); } debug!( diff --git a/common/client-libs/mixnet-client/src/forwarder.rs b/common/client-libs/mixnet-client/src/forwarder.rs index d92f6ad790..1aa68be8da 100644 --- a/common/client-libs/mixnet-client/src/forwarder.rs +++ b/common/client-libs/mixnet-client/src/forwarder.rs @@ -59,7 +59,7 @@ impl PacketForwarder { self.mixnet_client .send_without_response(next_hop, sphinx_packet, packet_mode) { - debug!("failed to forward the packet - {}", err) + debug!("failed to forward the packet - {err}") } } } diff --git a/common/commands/src/context/errors.rs b/common/commands/src/context/errors.rs index 44a99f49ed..7be8f6d8ef 100644 --- a/common/commands/src/context/errors.rs +++ b/common/commands/src/context/errors.rs @@ -16,9 +16,9 @@ pub enum ContextError { #[error("failed to create client - {0}")] NymdError(String), - #[error("{0}")] + #[error(transparent)] NymdErrorPassthrough(#[from] validator_client::nymd::error::NymdError), - #[error("{0}")] + #[error(transparent)] ValidatorClientError(#[from] validator_client::ValidatorClientError), } diff --git a/common/commands/src/context/mod.rs b/common/commands/src/context/mod.rs index 4f55aa1847..98709d6d98 100644 --- a/common/commands/src/context/mod.rs +++ b/common/commands/src/context/mod.rs @@ -59,7 +59,7 @@ pub fn create_signing_client( network_details: &NymNetworkDetails, ) -> Result { let client_config = nymd::Config::try_from_nym_network_details(network_details) - .tap_err(|e| log::error!("Failed to get client config - {:?}", e))?; + .tap_err(|err| log::error!("Failed to get client config - {err}"))?; // get mnemonic let mnemonic = match std::env::var("MNEMONIC") { @@ -88,7 +88,7 @@ pub fn create_query_client( network_details: &NymNetworkDetails, ) -> Result { let client_config = nymd::Config::try_from_nym_network_details(network_details) - .tap_err(|e| log::error!("Failed to get client config - {:?}", e))?; + .tap_err(|err| log::error!("Failed to get client config - {err}"))?; let nymd_url = network_details .endpoints @@ -108,7 +108,7 @@ pub fn create_signing_client_with_validator_api( network_details: &NymNetworkDetails, ) -> Result { let client_config = validator_client::Config::try_from_nym_network_details(network_details) - .tap_err(|e| log::error!("Failed to get client config - {:?}", e))?; + .tap_err(|err| log::error!("Failed to get client config - {err}"))?; // get mnemonic let mnemonic = match std::env::var("MNEMONIC") { @@ -130,7 +130,7 @@ pub fn create_query_client_with_validator_api( network_details: &NymNetworkDetails, ) -> Result { let client_config = validator_client::Config::try_from_nym_network_details(network_details) - .tap_err(|e| log::error!("Failed to get client config - {:?}", e))?; + .tap_err(|err| log::error!("Failed to get client config - {err}"))?; match validator_client::client::Client::new_query(client_config) { Ok(client) => Ok(client), diff --git a/common/commands/src/validator/signature/errors.rs b/common/commands/src/validator/signature/errors.rs index 2369e06d66..d67c3d387b 100644 --- a/common/commands/src/validator/signature/errors.rs +++ b/common/commands/src/validator/signature/errors.rs @@ -11,6 +11,6 @@ pub enum Errors { #[error("signature error - {0}")] SignatureError(#[from] k256::ecdsa::signature::Error), - #[error("{0}")] + #[error(transparent)] CosmrsError(#[from] cosmrs::ErrorReport), } diff --git a/common/credential-storage/src/lib.rs b/common/credential-storage/src/lib.rs index 3b683026ce..d0a0992894 100644 --- a/common/credential-storage/src/lib.rs +++ b/common/credential-storage/src/lib.rs @@ -45,13 +45,13 @@ impl PersistentStorage { let connection_pool = match sqlx::SqlitePool::connect_with(opts).await { Ok(db) => db, Err(err) => { - error!("Failed to connect to SQLx database: {}", err); + error!("Failed to connect to SQLx database: {err}"); return Err(err.into()); } }; if let Err(err) = sqlx::migrate!("./migrations").run(&connection_pool).await { - error!("Failed to perform migration on the SQLx database: {}", err); + error!("Failed to perform migration on the SQLx database: {err}"); return Err(err.into()); } @@ -104,7 +104,7 @@ impl Storage for PersistentStorage { pub async fn initialise_storage(path: PathBuf) -> PersistentStorage { match PersistentStorage::init(path).await { - Err(err) => panic!("failed to initialise credential storage - {}", err), + Err(err) => panic!("failed to initialise credential storage - {err}"), Ok(storage) => storage, } } diff --git a/common/crypto/Cargo.toml b/common/crypto/Cargo.toml index a8e749f2e0..94d3d2820b 100644 --- a/common/crypto/Cargo.toml +++ b/common/crypto/Cargo.toml @@ -22,6 +22,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, package = "serde" } subtle-encoding = { version = "0.5", features = ["bech32-preview"]} +thiserror = "1.0.37" # internal nymsphinx-types = { path = "../nymsphinx/types" } diff --git a/common/crypto/src/asymmetric/encryption/mod.rs b/common/crypto/src/asymmetric/encryption/mod.rs index 5c7b5398ad..28ff92c07e 100644 --- a/common/crypto/src/asymmetric/encryption/mod.rs +++ b/common/crypto/src/asymmetric/encryption/mod.rs @@ -2,11 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 use pemstore::traits::{PemStorableKey, PemStorableKeyPair}; +use std::fmt::{self, Display, Formatter}; +use thiserror::Error; + #[cfg(feature = "rand")] use rand::{CryptoRng, RngCore}; #[cfg(feature = "serde")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use std::fmt::{self, Display, Formatter}; /// Size of a X25519 private key pub const PRIVATE_KEY_SIZE: usize = 32; @@ -17,31 +19,26 @@ pub const PUBLIC_KEY_SIZE: usize = 32; /// Size of a X25519 shared secret pub const SHARED_SECRET_SIZE: usize = 32; -#[derive(Clone, Copy, Eq, PartialEq, Debug)] +#[derive(Clone, Eq, PartialEq, Debug, Error)] pub enum KeyRecoveryError { - InvalidPublicKeyBytes, - InvalidPrivateKeyBytes, - MalformedString(bs58::decode::Error), -} + #[error("received public key of invalid size. Got: {received}, expected: {expected}")] + InvalidSizePublicKey { received: usize, expected: usize }, -impl From for KeyRecoveryError { - fn from(err: bs58::decode::Error) -> Self { - KeyRecoveryError::MalformedString(err) - } -} + #[error("received private key of invalid size. Got: {received}, expected: {expected}")] + InvalidSizePrivateKey { received: usize, expected: usize }, -// required for std::error::Error -impl Display for KeyRecoveryError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - KeyRecoveryError::InvalidPrivateKeyBytes => write!(f, "Invalid private key bytes"), - KeyRecoveryError::InvalidPublicKeyBytes => write!(f, "Invalid public key bytes"), - KeyRecoveryError::MalformedString(err) => write!(f, "malformed string - {}", err), - } - } -} + #[error("the base58 representation of the public key was malformed - {source}")] + MalformedPublicKeyString { + #[source] + source: bs58::decode::Error, + }, -impl std::error::Error for KeyRecoveryError {} + #[error("the base58 representation of the private key was malformed - {source}")] + MalformedPrivateKeyString { + #[source] + source: bs58::decode::Error, + }, +} pub struct KeyPair { pub(crate) private_key: PrivateKey, @@ -112,7 +109,10 @@ impl PublicKey { pub fn from_bytes(b: &[u8]) -> Result { if b.len() != PUBLIC_KEY_SIZE { - return Err(KeyRecoveryError::InvalidPublicKeyBytes); + return Err(KeyRecoveryError::InvalidSizePublicKey { + received: b.len(), + expected: PUBLIC_KEY_SIZE, + }); } let mut bytes = [0; PUBLIC_KEY_SIZE]; bytes.copy_from_slice(&b[..PUBLIC_KEY_SIZE]); @@ -124,7 +124,9 @@ impl PublicKey { } pub fn from_base58_string>(val: I) -> Result { - let bytes = bs58::decode(val).into_vec()?; + let bytes = bs58::decode(val) + .into_vec() + .map_err(|source| KeyRecoveryError::MalformedPublicKeyString { source })?; Self::from_bytes(&bytes) } } @@ -188,7 +190,10 @@ impl PrivateKey { pub fn from_bytes(b: &[u8]) -> Result { if b.len() != PRIVATE_KEY_SIZE { - return Err(KeyRecoveryError::InvalidPrivateKeyBytes); + return Err(KeyRecoveryError::InvalidSizePrivateKey { + received: b.len(), + expected: PRIVATE_KEY_SIZE, + }); } let mut bytes = [0; 32]; bytes.copy_from_slice(&b[..PRIVATE_KEY_SIZE]); @@ -200,7 +205,9 @@ impl PrivateKey { } pub fn from_base58_string>(val: I) -> Result { - let bytes = bs58::decode(val).into_vec()?; + let bytes = bs58::decode(val) + .into_vec() + .map_err(|source| KeyRecoveryError::MalformedPrivateKeyString { source })?; Self::from_bytes(&bytes) } diff --git a/common/crypto/src/asymmetric/identity/mod.rs b/common/crypto/src/asymmetric/identity/mod.rs index 8ba1de8ec6..836f6c70e0 100644 --- a/common/crypto/src/asymmetric/identity/mod.rs +++ b/common/crypto/src/asymmetric/identity/mod.rs @@ -6,10 +6,11 @@ pub use ed25519_dalek::SignatureError; pub use ed25519_dalek::{Verifier, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATURE_LENGTH}; use nymsphinx_types::{DestinationAddressBytes, DESTINATION_ADDRESS_LENGTH}; use pemstore::traits::{PemStorableKey, PemStorableKeyPair}; +use std::fmt::{self, Display, Formatter}; +use thiserror::Error; + #[cfg(feature = "rand")] use rand::{CryptoRng, RngCore}; -use std::fmt::{self, Display, Formatter}; - #[cfg(feature = "serde")] use serde::de::Error as SerdeError; #[cfg(feature = "serde")] @@ -17,35 +18,30 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "serde")] use serde_bytes::{ByteBuf as SerdeByteBuf, Bytes as SerdeBytes}; -#[derive(Debug)] +#[derive(Debug, Error)] pub enum Ed25519RecoveryError { - MalformedBytes(SignatureError), - MalformedString(bs58::decode::Error), -} + #[error(transparent)] + MalformedBytes(#[from] SignatureError), -impl From for Ed25519RecoveryError { - fn from(err: SignatureError) -> Self { - Ed25519RecoveryError::MalformedBytes(err) - } -} + #[error("the base58 representation of the public key was malformed - {source}")] + MalformedPublicKeyString { + #[source] + source: bs58::decode::Error, + }, -impl From for Ed25519RecoveryError { - fn from(err: bs58::decode::Error) -> Self { - Ed25519RecoveryError::MalformedString(err) - } -} + #[error("the base58 representation of the private key was malformed - {source}")] + MalformedPrivateKeyString { + #[source] + source: bs58::decode::Error, + }, -impl fmt::Display for Ed25519RecoveryError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - Ed25519RecoveryError::MalformedBytes(err) => write!(f, "malformed bytes - {}", err), - Ed25519RecoveryError::MalformedString(err) => write!(f, "malformed string - {}", err), - } - } + #[error("the base58 representation of the signature was malformed - {source}")] + MalformedSignatureString { + #[source] + source: bs58::decode::Error, + }, } -impl std::error::Error for Ed25519RecoveryError {} - /// Keypair for usage in ed25519 EdDSA. #[derive(Debug)] pub struct KeyPair { @@ -134,7 +130,9 @@ impl PublicKey { } pub fn from_base58_string>(val: I) -> Result { - let bytes = bs58::decode(val).into_vec()?; + let bytes = bs58::decode(val) + .into_vec() + .map_err(|source| Ed25519RecoveryError::MalformedPublicKeyString { source })?; Self::from_bytes(&bytes) } @@ -211,7 +209,9 @@ impl PrivateKey { } pub fn from_base58_string>(val: I) -> Result { - let bytes = bs58::decode(val).into_vec()?; + let bytes = bs58::decode(val) + .into_vec() + .map_err(|source| Ed25519RecoveryError::MalformedPrivateKeyString { source })?; Self::from_bytes(&bytes) } @@ -277,7 +277,9 @@ impl Signature { } pub fn from_base58_string>(val: I) -> Result { - let bytes = bs58::decode(val).into_vec()?; + let bytes = bs58::decode(val) + .into_vec() + .map_err(|source| Ed25519RecoveryError::MalformedSignatureString { source })?; Self::from_bytes(&bytes) } diff --git a/common/mixnode-common/Cargo.toml b/common/mixnode-common/Cargo.toml index 53676023af..e4d68165b9 100644 --- a/common/mixnode-common/Cargo.toml +++ b/common/mixnode-common/Cargo.toml @@ -16,6 +16,7 @@ serde = { version = "1.0", features = ["derive"] } tokio = { version = "1.21.2", features = ["time", "macros", "rt", "net", "io-util"] } tokio-util = { version = "0.7.3", features = ["codec"] } url = "2.2" +thiserror = "1.0.37" crypto = { path = "../crypto" } nymsphinx-acknowledgements = { path = "../nymsphinx/acknowledgements" } diff --git a/common/mixnode-common/src/packet_processor/error.rs b/common/mixnode-common/src/packet_processor/error.rs index 38be92079d..084ce708a8 100644 --- a/common/mixnode-common/src/packet_processor/error.rs +++ b/common/mixnode-common/src/packet_processor/error.rs @@ -4,63 +4,22 @@ use nymsphinx_acknowledgements::surb_ack::SurbAckRecoveryError; use nymsphinx_addressing::nodes::NymNodeRoutingAddressError; use nymsphinx_types::Error as SphinxError; -use std::fmt::{self, Display, Formatter}; +use thiserror::Error; -#[derive(Debug)] +#[derive(Error, Debug)] pub enum MixProcessingError { - SphinxProcessingError(SphinxError), - InvalidHopAddress(NymNodeRoutingAddressError), - NoSurbAckInFinalHop, - MalformedSurbAck(SurbAckRecoveryError), + #[error("failed to process received packet: {0}")] + SphinxProcessingError(#[from] SphinxError), + #[error("the forward hop address was malformed: {0}")] + InvalidForwardHopAddress(#[from] NymNodeRoutingAddressError), + + #[error("the final hop did not contain a SURB-Ack")] + NoSurbAckInFinalHop, + + #[error("failed to recover the expected SURB-Ack packet: {0}")] + MalformedSurbAck(#[from] SurbAckRecoveryError), + + #[error("the received packet was set to use the very old and very much deprecated 'VPN' mode")] ReceivedOldTypeVpnPacket, } - -impl From for MixProcessingError { - // for the time being just have a single error instance for all possible results of SphinxError - fn from(err: SphinxError) -> Self { - use MixProcessingError::*; - - SphinxProcessingError(err) - } -} - -impl From for MixProcessingError { - fn from(err: NymNodeRoutingAddressError) -> Self { - use MixProcessingError::*; - - InvalidHopAddress(err) - } -} - -impl From for MixProcessingError { - fn from(err: SurbAckRecoveryError) -> Self { - use MixProcessingError::*; - - MalformedSurbAck(err) - } -} - -impl Display for MixProcessingError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - MixProcessingError::SphinxProcessingError(sphinx_err) => { - write!(f, "Sphinx Processing Error - {}", sphinx_err) - } - MixProcessingError::InvalidHopAddress(address_err) => { - write!(f, "Invalid Hop Address - {:?}", address_err) - } - MixProcessingError::NoSurbAckInFinalHop => { - write!(f, "No SURBAck present in the final hop data") - } - MixProcessingError::MalformedSurbAck(surb_ack_err) => { - write!(f, "Malformed SURBAck - {:?}", surb_ack_err) - } - MixProcessingError::ReceivedOldTypeVpnPacket => { - write!(f, "Received an old-type unsafe 'VPN' mode packet") - } - } - } -} - -impl std::error::Error for MixProcessingError {} diff --git a/common/mixnode-common/src/packet_processor/processor.rs b/common/mixnode-common/src/packet_processor/processor.rs index aaadfe0171..84e543d8bd 100644 --- a/common/mixnode-common/src/packet_processor/processor.rs +++ b/common/mixnode-common/src/packet_processor/processor.rs @@ -51,7 +51,7 @@ impl SphinxPacketProcessor { packet: SphinxPacket, ) -> Result { packet.process(&self.sphinx_key).map_err(|err| { - debug!("Failed to unwrap Sphinx packet: {:?}", err); + debug!("Failed to unwrap Sphinx packet: {err}"); MixProcessingError::SphinxProcessingError(err) }) } diff --git a/common/mixnode-common/src/verloc/error.rs b/common/mixnode-common/src/verloc/error.rs index 44a408c77a..0268059d7c 100644 --- a/common/mixnode-common/src/verloc/error.rs +++ b/common/mixnode-common/src/verloc/error.rs @@ -53,13 +53,13 @@ impl Display for RttError { write!(f, "The received reply packet had invalid signature") } RttError::UnreachableNode(id, err) => { - write!(f, "Could not establish connection to {} - {}", id, err) + write!(f, "Could not establish connection to {} - {err}", id) } RttError::UnexpectedConnectionFailureWrite(id, err) => { - write!(f, "Failed to write echo packet to {} - {}", id, err) + write!(f, "Failed to write echo packet to {} - {err}", id) } RttError::UnexpectedConnectionFailureRead(id, err) => { - write!(f, "Failed to read reply packet from {} - {}", id, err) + write!(f, "Failed to read reply packet from {} - {err}", id) } RttError::ConnectionReadTimeout(id) => { write!(f, "Timed out while trying to read reply packet from {}", id) diff --git a/common/mixnode-common/src/verloc/listener.rs b/common/mixnode-common/src/verloc/listener.rs index 8f49779130..537ec3aad5 100644 --- a/common/mixnode-common/src/verloc/listener.rs +++ b/common/mixnode-common/src/verloc/listener.rs @@ -66,7 +66,7 @@ impl PacketListener { tokio::spawn(connection_handler.handle_connection(socket, remote_addr, handler_shutdown_listener)); } - Err(err) => warn!("Failed to accept incoming connection - {:?}", err), + Err(err) => warn!("Failed to accept incoming connection - {err}"), } }, _ = shutdown_listener.recv() => { @@ -141,9 +141,9 @@ enum EchoPacketCodecError { impl Display for EchoPacketCodecError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - EchoPacketCodecError::IoError(err) => write!(f, "encountered io error - {}", err), + EchoPacketCodecError::IoError(err) => write!(f, "encountered io error - {err}"), EchoPacketCodecError::PacketRecoveryError(err) => { - write!(f, "failed to correctly decode an echo packet - {}", err) + write!(f, "failed to correctly decode an echo packet - {err}") } } } diff --git a/common/nymsphinx/acknowledgements/Cargo.toml b/common/nymsphinx/acknowledgements/Cargo.toml index f105e0c544..c05976ade7 100644 --- a/common/nymsphinx/acknowledgements/Cargo.toml +++ b/common/nymsphinx/acknowledgements/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] rand = { version = "0.7.3", features = ["wasm-bindgen"] } +thiserror = "1.0.37" crypto = { path = "../../crypto", features = ["symmetric", "rand"] } nymsphinx-addressing = { path = "../addressing" } diff --git a/common/nymsphinx/acknowledgements/src/surb_ack.rs b/common/nymsphinx/acknowledgements/src/surb_ack.rs index 67e863d1f6..912ed4bc32 100644 --- a/common/nymsphinx/acknowledgements/src/surb_ack.rs +++ b/common/nymsphinx/acknowledgements/src/surb_ack.rs @@ -4,10 +4,13 @@ use crate::identifier::prepare_identifier; use crate::AckKey; use nymsphinx_addressing::clients::Recipient; -use nymsphinx_addressing::nodes::{NymNodeRoutingAddress, MAX_NODE_ADDRESS_UNPADDED_LEN}; +use nymsphinx_addressing::nodes::{ + NymNodeRoutingAddress, NymNodeRoutingAddressError, MAX_NODE_ADDRESS_UNPADDED_LEN, +}; use nymsphinx_params::packet_sizes::PacketSize; use nymsphinx_params::DEFAULT_NUM_MIX_HOPS; use nymsphinx_types::builder::SphinxPacketBuilder; +use nymsphinx_types::Error as SphinxError; use nymsphinx_types::{ delays::{self, Delay}, SphinxPacket, @@ -15,6 +18,7 @@ use nymsphinx_types::{ use rand::{CryptoRng, RngCore}; use std::convert::TryFrom; use std::time; +use thiserror::Error; use topology::{NymTopology, NymTopologyError}; pub struct SurbAck { @@ -23,11 +27,16 @@ pub struct SurbAck { expected_total_delay: Delay, } -#[derive(Debug)] +#[derive(Debug, Error)] pub enum SurbAckRecoveryError { - InvalidPacketSize, - InvalidAddress, - InvalidSphinxPacket, + #[error("received an invalid number of bytes to deserialize the SURB-Ack. Got {received}, expected {expected}")] + InvalidPacketSize { received: usize, expected: usize }, + + #[error("could not extract first hop address information - {0}")] + InvalidAddress(#[from] NymNodeRoutingAddressError), + + #[error("the contained sphinx packet was not correctly formed - {0}")] + InvalidSphinxPacket(#[from] SphinxError), } impl SurbAck { @@ -92,20 +101,17 @@ impl SurbAck { b: &[u8], ) -> Result<(NymNodeRoutingAddress, SphinxPacket), SurbAckRecoveryError> { if b.len() != Self::len() { - Err(SurbAckRecoveryError::InvalidPacketSize) + Err(SurbAckRecoveryError::InvalidPacketSize { + received: b.len(), + expected: Self::len(), + }) } else { - let address = match NymNodeRoutingAddress::try_from_bytes(b) { - Ok(address) => address, - Err(_) => return Err(SurbAckRecoveryError::InvalidAddress), - }; + let address = NymNodeRoutingAddress::try_from_bytes(b)?; // TODO: this will be variable once/if we decide to introduce optimization described // in common/nymsphinx/chunking/src/lib.rs:available_plaintext_size() let address_offset = MAX_NODE_ADDRESS_UNPADDED_LEN; - let packet = match SphinxPacket::from_bytes(&b[address_offset..]) { - Ok(packet) => packet, - Err(_) => return Err(SurbAckRecoveryError::InvalidSphinxPacket), - }; + let packet = SphinxPacket::from_bytes(&b[address_offset..])?; Ok((address, packet)) } diff --git a/common/nymsphinx/framing/Cargo.toml b/common/nymsphinx/framing/Cargo.toml index 6921a8cf69..fc46ece44a 100644 --- a/common/nymsphinx/framing/Cargo.toml +++ b/common/nymsphinx/framing/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" [dependencies] bytes = "1.0" tokio-util = { version = "0.7.3", features = ["codec"] } +thiserror = "1.0.37" nymsphinx-types = { path = "../types" } nymsphinx-params = { path = "../params" } diff --git a/common/nymsphinx/framing/src/codec.rs b/common/nymsphinx/framing/src/codec.rs index 5794a88544..f3986d2ece 100644 --- a/common/nymsphinx/framing/src/codec.rs +++ b/common/nymsphinx/framing/src/codec.rs @@ -1,57 +1,48 @@ -// Copyright 2021 - Nym Technologies SA +// Copyright 2021-2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 use crate::packet::{FramedSphinxPacket, Header}; use bytes::{Buf, BufMut, BytesMut}; use nymsphinx_params::packet_modes::InvalidPacketMode; use nymsphinx_params::packet_sizes::{InvalidPacketSize, PacketSize}; +use nymsphinx_types::Error as SphinxError; use nymsphinx_types::SphinxPacket; use std::io; +use thiserror::Error; use tokio_util::codec::{Decoder, Encoder}; -#[derive(Debug)] +#[derive(Error, Debug)] pub enum SphinxCodecError { - InvalidPacketSize, - InvalidPacketMode, - MalformedSphinxPacket, - IoError(io::Error), -} + #[error("the packet size information was malformed - {0}")] + InvalidPacketSize(#[from] InvalidPacketSize), -impl From for SphinxCodecError { - fn from(err: io::Error) -> Self { - SphinxCodecError::IoError(err) - } + #[error("the packet mode information was malformed - {0}")] + InvalidPacketMode(#[from] InvalidPacketMode), + + #[error("the actual sphinx packet was malformed - {0}")] + MalformedSphinxPacket(#[from] SphinxError), + + #[error("encountered an IO error - {0}")] + IoError(#[from] io::Error), } impl From for io::Error { fn from(err: SphinxCodecError) -> Self { match err { - SphinxCodecError::InvalidPacketSize => { - io::Error::new(io::ErrorKind::InvalidInput, "invalid packet size") + SphinxCodecError::InvalidPacketSize(source) => { + io::Error::new(io::ErrorKind::InvalidInput, source) } - SphinxCodecError::InvalidPacketMode => { - io::Error::new(io::ErrorKind::InvalidInput, "invalid packet mode") + SphinxCodecError::InvalidPacketMode(source) => { + io::Error::new(io::ErrorKind::InvalidInput, source) } - SphinxCodecError::MalformedSphinxPacket => { - io::Error::new(io::ErrorKind::InvalidData, "malformed packet") + SphinxCodecError::MalformedSphinxPacket(source) => { + io::Error::new(io::ErrorKind::InvalidData, source) } SphinxCodecError::IoError(err) => err, } } } -impl From for SphinxCodecError { - fn from(_: InvalidPacketSize) -> Self { - SphinxCodecError::InvalidPacketSize - } -} - -impl From for SphinxCodecError { - fn from(_: InvalidPacketMode) -> Self { - SphinxCodecError::InvalidPacketMode - } -} - // TODO: in the future it could be extended to have state containing symmetric encryption key // so that all data could be encrypted easily (alternatively we could just slap TLS) pub struct SphinxCodec; @@ -97,17 +88,11 @@ impl Decoder for SphinxCodec { // advance buffer past the header - at this point we have enough bytes src.advance(header.size()); let sphinx_packet_bytes = src.split_to(sphinx_packet_size); - let sphinx_packet = match SphinxPacket::from_bytes(&sphinx_packet_bytes) { - Ok(sphinx_packet) => sphinx_packet, - // here it could be debatable whether stream is corrupt or not, - // but let's go with the safer approach and assume it is. - Err(_) => return Err(SphinxCodecError::MalformedSphinxPacket), - }; - let nymsphinx_packet = FramedSphinxPacket { - header, - packet: sphinx_packet, - }; + // here it could be debatable whether stream is corrupt or not, + // but let's go with the safer approach and assume it is. + let packet = SphinxPacket::from_bytes(&sphinx_packet_bytes)?; + let nymsphinx_packet = FramedSphinxPacket { header, packet }; // As per docs: // Before returning from the function, implementations should ensure that the buffer diff --git a/common/nymsphinx/params/Cargo.toml b/common/nymsphinx/params/Cargo.toml index a06f897f22..ebca914742 100644 --- a/common/nymsphinx/params/Cargo.toml +++ b/common/nymsphinx/params/Cargo.toml @@ -7,5 +7,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +thiserror = "1.0.37" + crypto = { path = "../../crypto", features = ["hashing", "symmetric"] } nymsphinx-types = { path = "../types" } diff --git a/common/nymsphinx/params/src/packet_modes.rs b/common/nymsphinx/params/src/packet_modes.rs index 819b32b3af..3fb7ac6358 100644 --- a/common/nymsphinx/params/src/packet_modes.rs +++ b/common/nymsphinx/params/src/packet_modes.rs @@ -1,10 +1,14 @@ -// Copyright 2021 - Nym Technologies SA +// Copyright 2021-2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 use std::convert::TryFrom; +use thiserror::Error; -#[derive(Debug)] -pub struct InvalidPacketMode; +#[derive(Error, Debug)] +#[error("{received} is not a valid packet mode tag")] +pub struct InvalidPacketMode { + received: u8, +} #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -31,11 +35,11 @@ impl PacketMode { impl TryFrom for PacketMode { type Error = InvalidPacketMode; - fn try_from(value: u8) -> std::result::Result { + fn try_from(value: u8) -> Result { match value { _ if value == (PacketMode::Mix as u8) => Ok(Self::Mix), _ if value == (PacketMode::Vpn as u8) => Ok(Self::Vpn), - _ => Err(InvalidPacketMode), + v => Err(InvalidPacketMode { received: v }), } } } diff --git a/common/nymsphinx/params/src/packet_sizes.rs b/common/nymsphinx/params/src/packet_sizes.rs index aa573ffe11..ef9976bd92 100644 --- a/common/nymsphinx/params/src/packet_sizes.rs +++ b/common/nymsphinx/params/src/packet_sizes.rs @@ -6,6 +6,7 @@ use nymsphinx_types::header::HEADER_SIZE; use nymsphinx_types::PAYLOAD_OVERHEAD_SIZE; use std::convert::TryFrom; use std::str::FromStr; +use thiserror::Error; // it's up to the smart people to figure those values out : ) const REGULAR_PACKET_SIZE: usize = HEADER_SIZE + PAYLOAD_OVERHEAD_SIZE + 2 * 1024; @@ -20,11 +21,17 @@ const EXTENDED_PACKET_SIZE_8: usize = HEADER_SIZE + PAYLOAD_OVERHEAD_SIZE + 8 * const EXTENDED_PACKET_SIZE_16: usize = HEADER_SIZE + PAYLOAD_OVERHEAD_SIZE + 16 * 1024; const EXTENDED_PACKET_SIZE_32: usize = HEADER_SIZE + PAYLOAD_OVERHEAD_SIZE + 32 * 1024; -#[derive(Debug)] -pub struct InvalidPacketSize; +#[derive(Debug, Error)] +pub enum InvalidPacketSize { + #[error("{received} is not a valid packet size tag")] + UnknownPacketTag { received: u8 }, -#[derive(Debug)] -pub struct InvalidExtendedPacketSize; + #[error("{received} is not a valid extended packet size variant")] + UnknownExtendedPacketVariant { received: String }, + + #[error("{received} does not correspond with any known packet size")] + UnknownPacketSize { received: usize }, +} #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -55,7 +62,9 @@ impl FromStr for PacketSize { "extended8" => Ok(Self::ExtendedPacket8), "extended16" => Ok(Self::ExtendedPacket16), "extended32" => Ok(Self::ExtendedPacket32), - _ => Err(InvalidPacketSize), + s => Err(InvalidPacketSize::UnknownExtendedPacketVariant { + received: s.to_string(), + }), } } } @@ -63,14 +72,14 @@ impl FromStr for PacketSize { impl TryFrom for PacketSize { type Error = InvalidPacketSize; - fn try_from(value: u8) -> std::result::Result { + fn try_from(value: u8) -> Result { match value { _ if value == (PacketSize::RegularPacket as u8) => Ok(Self::RegularPacket), _ if value == (PacketSize::AckPacket as u8) => Ok(Self::AckPacket), _ if value == (PacketSize::ExtendedPacket8 as u8) => Ok(Self::ExtendedPacket8), _ if value == (PacketSize::ExtendedPacket16 as u8) => Ok(Self::ExtendedPacket16), _ if value == (PacketSize::ExtendedPacket32 as u8) => Ok(Self::ExtendedPacket32), - _ => Err(InvalidPacketSize), + v => Err(InvalidPacketSize::UnknownPacketTag { received: v }), } } } @@ -94,7 +103,7 @@ impl PacketSize { self.size() - HEADER_SIZE } - pub fn get_type(size: usize) -> std::result::Result { + pub fn get_type(size: usize) -> Result { if PacketSize::RegularPacket.size() == size { Ok(PacketSize::RegularPacket) } else if PacketSize::AckPacket.size() == size { @@ -106,7 +115,7 @@ impl PacketSize { } else if PacketSize::ExtendedPacket32.size() == size { Ok(PacketSize::ExtendedPacket32) } else { - Err(InvalidPacketSize) + Err(InvalidPacketSize::UnknownPacketSize { received: size }) } } diff --git a/common/socks5/ordered-buffer/Cargo.toml b/common/socks5/ordered-buffer/Cargo.toml index f5ea5545d8..58dd09b263 100644 --- a/common/socks5/ordered-buffer/Cargo.toml +++ b/common/socks5/ordered-buffer/Cargo.toml @@ -8,3 +8,4 @@ edition = "2021" [dependencies] log = "0.4" +thiserror = "1.0.37" \ No newline at end of file diff --git a/common/socks5/ordered-buffer/src/message.rs b/common/socks5/ordered-buffer/src/message.rs index f5f28f53b1..15627d7fe0 100644 --- a/common/socks5/ordered-buffer/src/message.rs +++ b/common/socks5/ordered-buffer/src/message.rs @@ -1,9 +1,16 @@ -use std::cmp::Ordering; +// Copyright 2020-2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 -#[derive(Debug, PartialEq, Eq)] +use std::cmp::Ordering; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq, Eq)] pub enum MessageError { + #[error("the received message was empty")] NoData, - IndexTooShort, + + #[error("could not extract message index. Received {received} bytes, but expected {expected}")] + IndexTooShort { received: usize, expected: usize }, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -32,7 +39,10 @@ impl OrderedMessage { } if data.len() < 8 { - return Err(MessageError::IndexTooShort); + return Err(MessageError::IndexTooShort { + received: data.len(), + expected: 8, + }); } let index = u64::from_be_bytes([ data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], @@ -81,7 +91,13 @@ mod ordered_message_from_bytes { #[test] fn fails_when_data_is_too_short() { let result = OrderedMessage::try_from_bytes(vec![1, 2, 3]); - assert_eq!(Err(MessageError::IndexTooShort), result); + assert_eq!( + Err(MessageError::IndexTooShort { + received: 3, + expected: 8 + }), + result + ); } #[test] diff --git a/common/socks5/proxy-helpers/src/connection_controller.rs b/common/socks5/proxy-helpers/src/connection_controller.rs index 97c4487af6..d7e2645190 100644 --- a/common/socks5/proxy-helpers/src/connection_controller.rs +++ b/common/socks5/proxy-helpers/src/connection_controller.rs @@ -53,7 +53,7 @@ impl ActiveConnection { let ordered_message = match OrderedMessage::try_from_bytes(payload) { Ok(msg) => msg, Err(err) => { - error!("Malformed ordered message - {:?}", err); + error!("Malformed ordered message - {err}"); return; } }; @@ -158,9 +158,9 @@ impl Controller { .unbounded_send(ConnectionCommand::Close(conn_id)) { if self.shutdown.is_shutdown_poll() { - log::debug!("Failed to send: {}", err); + log::debug!("Failed to send: {err}"); } else { - log::error!("Failed to send: {}", err); + log::error!("Failed to send: {err}"); } } } @@ -197,7 +197,7 @@ impl Controller { socket_closed: active_connection.is_closed, }) { - error!("WTF IS THIS: {:?}", err); + error!("WTF IS THIS: {err}"); } // TODO: ABOVE UNWRAP CAUSED A CRASH IN A NORMAL USE!!!! diff --git a/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs b/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs index 37403c33ad..b6688657de 100644 --- a/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs +++ b/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs @@ -54,7 +54,7 @@ where Some(data) => match data { Ok(data) => (data, false), Err(err) => { - error!(target: &*format!("({}) socks5 inbound", connection_id), "failed to read request from the socket - {}", err); + error!(target: &*format!("({}) socks5 inbound", connection_id), "failed to read request from the socket - {err}"); (Default::default(), true) } }, diff --git a/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs b/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs index 78db73afb6..f6c713e948 100644 --- a/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs +++ b/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs @@ -33,7 +33,7 @@ async fn deal_with_message( if let Err(err) = writer.write_all(&connection_message.payload).await { // the other half is probably going to blow up too (if not, this task also needs to notify the other one!!) - error!(target: &*format!("({}) socks5 outbound", connection_id), "failed to write response back to the socket - {}", err); + error!(target: &*format!("({}) socks5 outbound", connection_id), "failed to write response back to the socket - {err}"); return true; } if connection_message.socket_closed { diff --git a/common/socks5/requests/src/msg.rs b/common/socks5/requests/src/msg.rs index 2b688d8214..906c643524 100644 --- a/common/socks5/requests/src/msg.rs +++ b/common/socks5/requests/src/msg.rs @@ -9,13 +9,13 @@ use crate::response::{Response, ResponseError}; #[derive(Debug, Error)] pub enum MessageError { - #[error("{0}")] + #[error(transparent)] Request(RequestError), #[error("{0:?}")] Response(ResponseError), - #[error("{0}")] + #[error(transparent)] NetworkRequesterResponseError(NrError), #[error("no data")] diff --git a/common/task/src/shutdown.rs b/common/task/src/shutdown.rs index 09e8abcb50..4fe7a22bdd 100644 --- a/common/task/src/shutdown.rs +++ b/common/task/src/shutdown.rs @@ -299,7 +299,7 @@ impl ShutdownListener { if self.mode.is_dummy() { return; } - log::trace!("Notifying we stopped: {:?}", err); + log::trace!("Notifying we stopped: {err}"); if self.return_error.send(err).is_err() { log::error!("Failed to send back error message"); } diff --git a/common/topology/src/gateway.rs b/common/topology/src/gateway.rs index 57b34146e6..9df2156b32 100644 --- a/common/topology/src/gateway.rs +++ b/common/topology/src/gateway.rs @@ -7,63 +7,25 @@ use mixnet_contract_common::GatewayBond; use nymsphinx_addressing::nodes::{NodeIdentity, NymNodeRoutingAddress}; use nymsphinx_types::Node as SphinxNode; use std::convert::{TryFrom, TryInto}; -use std::fmt::{self, Display, Formatter}; +use std::fmt; use std::io; use std::net::SocketAddr; +use thiserror::Error; -#[derive(Debug)] +#[derive(Error, Debug)] pub enum GatewayConversionError { - InvalidIdentityKey(identity::Ed25519RecoveryError), - InvalidSphinxKey(encryption::KeyRecoveryError), - InvalidAddress(String, io::Error), - InvalidStake, - Other(Box), -} + #[error("gateway identity key was malformed - {0}")] + InvalidIdentityKey(#[from] identity::Ed25519RecoveryError), -impl From for GatewayConversionError { - fn from(err: encryption::KeyRecoveryError) -> Self { - GatewayConversionError::InvalidSphinxKey(err) - } -} + #[error("gateway sphinx key was malformed - {0}")] + InvalidSphinxKey(#[from] encryption::KeyRecoveryError), -impl From for GatewayConversionError { - fn from(err: identity::Ed25519RecoveryError) -> Self { - GatewayConversionError::InvalidIdentityKey(err) - } -} - -impl Display for GatewayConversionError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - GatewayConversionError::InvalidIdentityKey(err) => write!( - f, - "failed to convert gateway due to invalid identity key - {}", - err - ), - GatewayConversionError::InvalidSphinxKey(err) => write!( - f, - "failed to convert gateway due to invalid sphinx key - {}", - err - ), - GatewayConversionError::InvalidAddress(address, err) => { - write!( - f, - "failed to convert gateway due to invalid address {} - {}", - address, err - ) - } - GatewayConversionError::InvalidStake => { - write!(f, "failed to convert gateway due to invalid stake") - } - GatewayConversionError::Other(err) => { - write!( - f, - "failed to convert gateway due to another error - {}", - err - ) - } - } - } + #[error("'{value}' is not a valid gateway address - {source}")] + InvalidAddress { + value: String, + #[source] + source: io::Error, + }, } #[derive(Debug, Clone)] @@ -123,14 +85,22 @@ impl<'a> TryFrom<&'a GatewayBond> for Node { type Error = GatewayConversionError; fn try_from(bond: &'a GatewayBond) -> Result { - let host: NetworkAddress = bond.gateway.host.parse().map_err(|err| { - GatewayConversionError::InvalidAddress(bond.gateway.host.clone(), err) - })?; + let host: NetworkAddress = + bond.gateway + .host + .parse() + .map_err(|err| GatewayConversionError::InvalidAddress { + value: bond.gateway.host.clone(), + source: err, + })?; // try to completely resolve the host in the mix situation to avoid doing it every // single time we want to construct a path let mix_host = host.to_socket_addrs(bond.gateway.mix_port).map_err(|err| { - GatewayConversionError::InvalidAddress(bond.gateway.host.clone(), err) + GatewayConversionError::InvalidAddress { + value: bond.gateway.host.clone(), + source: err, + } })?[0]; Ok(Node { diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index ff3ba55c83..527176339d 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -276,7 +276,7 @@ pub fn nym_topology_from_detailed( match bond.try_into() { Ok(mix) => layer_entry.push(mix), Err(err) => { - warn!("Mix {} / {} is malformed - {}", mix_id, mix_identity, err); + warn!("Mix {} / {} is malformed - {err}", mix_id, mix_identity); continue; } } @@ -288,7 +288,7 @@ pub fn nym_topology_from_detailed( match bond.try_into() { Ok(gate) => gateways.push(gate), Err(err) => { - warn!("Gateway {} is malformed - {}", gate_id, err); + warn!("Gateway {} is malformed - {err}", gate_id); continue; } } diff --git a/common/topology/src/mix.rs b/common/topology/src/mix.rs index 81e0308b2f..08d7f5c0b7 100644 --- a/common/topology/src/mix.rs +++ b/common/topology/src/mix.rs @@ -7,63 +7,24 @@ use mixnet_contract_common::{Layer, MixId, MixNodeBond}; use nymsphinx_addressing::nodes::NymNodeRoutingAddress; use nymsphinx_types::Node as SphinxNode; use std::convert::{TryFrom, TryInto}; -use std::fmt::{self, Display, Formatter}; use std::io; use std::net::SocketAddr; +use thiserror::Error; -#[derive(Debug)] +#[derive(Error, Debug)] pub enum MixnodeConversionError { - InvalidIdentityKey(identity::Ed25519RecoveryError), - InvalidSphinxKey(encryption::KeyRecoveryError), - InvalidAddress(String, io::Error), - InvalidStake, - Other(Box), -} + #[error("mixnode identity key was malformed - {0}")] + InvalidIdentityKey(#[from] identity::Ed25519RecoveryError), -impl From for MixnodeConversionError { - fn from(err: encryption::KeyRecoveryError) -> Self { - MixnodeConversionError::InvalidSphinxKey(err) - } -} + #[error("mixnode sphinx key was malformed - {0}")] + InvalidSphinxKey(#[from] encryption::KeyRecoveryError), -impl From for MixnodeConversionError { - fn from(err: identity::Ed25519RecoveryError) -> Self { - MixnodeConversionError::InvalidIdentityKey(err) - } -} - -impl Display for MixnodeConversionError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - MixnodeConversionError::InvalidIdentityKey(err) => write!( - f, - "failed to convert mixnode due to invalid identity key - {}", - err - ), - MixnodeConversionError::InvalidSphinxKey(err) => write!( - f, - "failed to convert mixnode due to invalid sphinx key - {}", - err - ), - MixnodeConversionError::InvalidAddress(address, err) => { - write!( - f, - "failed to convert mixnode due to invalid address {} - {}", - address, err - ) - } - MixnodeConversionError::InvalidStake => { - write!(f, "failed to convert mixnode due to invalid stake") - } - MixnodeConversionError::Other(err) => { - write!( - f, - "failed to convert mixnode due to another error - {}", - err - ) - } - } - } + #[error("'{value}' is not a valid mixnode address - {source}")] + InvalidAddress { + value: String, + #[source] + source: io::Error, + }, } #[derive(Debug, Clone)] @@ -100,16 +61,22 @@ impl<'a> TryFrom<&'a MixNodeBond> for Node { type Error = MixnodeConversionError; fn try_from(bond: &'a MixNodeBond) -> Result { - let host: NetworkAddress = bond.mix_node.host.parse().map_err(|err| { - MixnodeConversionError::InvalidAddress(bond.mix_node.host.clone(), err) - })?; + let host: NetworkAddress = + bond.mix_node + .host + .parse() + .map_err(|err| MixnodeConversionError::InvalidAddress { + value: bond.mix_node.host.clone(), + source: err, + })?; // try to completely resolve the host in the mix situation to avoid doing it every // single time we want to construct a path let mix_host = host .to_socket_addrs(bond.mix_node.mix_port) - .map_err(|err| { - MixnodeConversionError::InvalidAddress(bond.mix_node.host.clone(), err) + .map_err(|err| MixnodeConversionError::InvalidAddress { + value: bond.mix_node.host.clone(), + source: err, })?[0]; Ok(Node { diff --git a/contracts/coconut-bandwidth/src/error.rs b/contracts/coconut-bandwidth/src/error.rs index 7bc8b11d4a..9f4aed6224 100644 --- a/contracts/coconut-bandwidth/src/error.rs +++ b/contracts/coconut-bandwidth/src/error.rs @@ -11,7 +11,7 @@ use thiserror::Error; /// Look at https://docs.rs/thiserror/1.0.21/thiserror/ for details. #[derive(Error, Debug, PartialEq)] pub enum ContractError { - #[error("{0}")] + #[error(transparent)] Std(#[from] StdError), #[error("Received multiple coin types")] @@ -29,6 +29,6 @@ pub enum ContractError { #[error("Credential already spent or in process of spending")] DuplicateBlindedSerialNumber, - #[error("{0}")] + #[error(transparent)] Admin(#[from] AdminError), } diff --git a/contracts/coconut-dkg/src/error.rs b/contracts/coconut-dkg/src/error.rs index 089a8b9f27..cd359579d0 100644 --- a/contracts/coconut-dkg/src/error.rs +++ b/contracts/coconut-dkg/src/error.rs @@ -8,10 +8,10 @@ use thiserror::Error; /// Custom errors for contract failure conditions. #[derive(Error, Debug, PartialEq)] pub enum ContractError { - #[error("{0}")] + #[error(transparent)] Std(#[from] StdError), - #[error("{0}")] + #[error(transparent)] Admin(#[from] AdminError), #[error("Group contract invalid address '{addr}'")] diff --git a/contracts/multisig/cw3-flex-multisig/src/error.rs b/contracts/multisig/cw3-flex-multisig/src/error.rs index f7addae37b..75a546ca0e 100644 --- a/contracts/multisig/cw3-flex-multisig/src/error.rs +++ b/contracts/multisig/cw3-flex-multisig/src/error.rs @@ -5,10 +5,10 @@ use thiserror::Error; #[derive(Error, Debug, PartialEq)] pub enum ContractError { - #[error("{0}")] + #[error(transparent)] Std(#[from] StdError), - #[error("{0}")] + #[error(transparent)] Threshold(#[from] ThresholdError), #[error("Group contract invalid address '{addr}'")] diff --git a/contracts/multisig/cw4-group/src/error.rs b/contracts/multisig/cw4-group/src/error.rs index 82a84fe833..8c88fb2255 100644 --- a/contracts/multisig/cw4-group/src/error.rs +++ b/contracts/multisig/cw4-group/src/error.rs @@ -5,13 +5,13 @@ use cw_controllers::{AdminError, HookError}; #[derive(Error, Debug, PartialEq)] pub enum ContractError { - #[error("{0}")] + #[error(transparent)] Std(#[from] StdError), - #[error("{0}")] + #[error(transparent)] Hook(#[from] HookError), - #[error("{0}")] + #[error(transparent)] Admin(#[from] AdminError), #[error("Unauthorized")] diff --git a/explorer-api/src/tasks.rs b/explorer-api/src/tasks.rs index 08d43fb805..bab29b798e 100644 --- a/explorer-api/src/tasks.rs +++ b/explorer-api/src/tasks.rs @@ -31,8 +31,8 @@ impl ExplorerApiTasks { { let bonds = match f(&self.state.inner.validator_client.0).await { Ok(result) => result, - Err(e) => { - error!("Unable to retrieve mixnode bonds: {:?}", e); + Err(err) => { + error!("Unable to retrieve mixnode bonds: {err}"); vec![] } }; @@ -115,8 +115,8 @@ impl ExplorerApiTasks { async fn update_validators_cache(&self) { match self.retrieve_all_validators().await { Ok(response) => self.state.inner.validators.update_cache(response).await, - Err(e) => { - error!("Failed to get validators: {:?}", e) + Err(err) => { + error!("Failed to get validators: {err}") } } } @@ -124,8 +124,8 @@ impl ExplorerApiTasks { async fn update_gateways_cache(&self) { match self.retrieve_all_gateways().await { Ok(response) => self.state.inner.gateways.update_cache(response).await, - Err(e) => { - error!("Failed to get gateways: {:?}", e) + Err(err) => { + error!("Failed to get gateways: {err}") } } } diff --git a/gateway/gateway-requests/src/registration/handshake/shared_key.rs b/gateway/gateway-requests/src/registration/handshake/shared_key.rs index 3fc014db51..b030bfb67e 100644 --- a/gateway/gateway-requests/src/registration/handshake/shared_key.rs +++ b/gateway/gateway-requests/src/registration/handshake/shared_key.rs @@ -1,4 +1,4 @@ -// Copyright 2020 - Nym Technologies SA +// Copyright 2020-2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 use crate::{GatewayMacSize, GatewayRequestsError}; @@ -10,7 +10,7 @@ use crypto::hmac::{compute_keyed_hmac, recompute_keyed_hmac_and_verify_tag}; use crypto::symmetric::stream_cipher::{self, CipherKey, KeySizeUser, IV}; use nymsphinx::params::{GatewayEncryptionAlgorithm, GatewayIntegrityHmacAlgorithm}; use pemstore::traits::PemStorableKey; -use std::fmt::{self, Display, Formatter}; +use thiserror::Error; // shared key is as long as the encryption key and the MAC key combined. pub type SharedKeySize = Sum; @@ -28,37 +28,23 @@ pub struct SharedKeys { mac_key: MacKey, } -#[derive(Debug)] +#[derive(Debug, Error)] pub enum SharedKeyConversionError { - DecodeError(bs58::decode::Error), - BytesOfInvalidLengthError, - StringOfInvalidLengthError, + #[error("the string representation of the shared keys was malformed - {0}")] + DecodeError(#[from] bs58::decode::Error), + #[error( + "the received shared keys had invalid size. Got: {received}, but expected: {expected}" + )] + InvalidSharedKeysSize { received: usize, expected: usize }, } -impl Display for SharedKeyConversionError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - SharedKeyConversionError::DecodeError(err) => write!( - f, - "encountered error while decoding the byte sequence: {}", - err - ), - SharedKeyConversionError::BytesOfInvalidLengthError => { - write!(f, "provided bytes have invalid length") - } - SharedKeyConversionError::StringOfInvalidLengthError => { - write!(f, "provided string has invalid length") - } - } - } -} - -impl std::error::Error for SharedKeyConversionError {} - impl SharedKeys { pub fn try_from_bytes(bytes: &[u8]) -> Result { if bytes.len() != SharedKeySize::to_usize() { - return Err(SharedKeyConversionError::BytesOfInvalidLengthError); + return Err(SharedKeyConversionError::InvalidSharedKeysSize { + received: bytes.len(), + expected: SharedKeySize::to_usize(), + }); } let encryption_key = @@ -157,15 +143,7 @@ impl SharedKeys { pub fn try_from_base58_string>( val: S, ) -> Result { - let decoded = match bs58::decode(val.into()).into_vec() { - Ok(decoded) => decoded, - Err(err) => return Err(SharedKeyConversionError::DecodeError(err)), - }; - - if decoded.len() != SharedKeySize::to_usize() { - return Err(SharedKeyConversionError::StringOfInvalidLengthError); - } - + let decoded = bs58::decode(val.into()).into_vec()?; SharedKeys::try_from_bytes(&decoded) } diff --git a/gateway/gateway-requests/src/types.rs b/gateway/gateway-requests/src/types.rs index f73f85bca5..3d93800c73 100644 --- a/gateway/gateway-requests/src/types.rs +++ b/gateway/gateway-requests/src/types.rs @@ -99,7 +99,7 @@ impl fmt::Display for GatewayRequestsError { MalformedSphinxPacket => write!(f, "received sphinx packet was malformed"), MalformedEncryption => write!(f, "the received encrypted data was malformed"), InvalidPacketMode => write!(f, "provided packet mode is invalid"), - InvalidMixPacket(err) => write!(f, "provided mix packet was malformed - {}", err) + InvalidMixPacket(err) => write!(f, "provided mix packet was malformed - {err}") } } } diff --git a/gateway/src/commands/mod.rs b/gateway/src/commands/mod.rs index 02dec84802..ef2ec235e8 100644 --- a/gateway/src/commands/mod.rs +++ b/gateway/src/commands/mod.rs @@ -165,7 +165,7 @@ pub(crate) fn validate_bech32_address_or_exit(address: &str) { if let Err(bech32_address_validation::Bech32Error::DecodeFailed(err)) = bech32_address_validation::try_bech32_decode(address) { - let error_message = format!("Error: wallet address decoding failed: {}", err).red(); + let error_message = format!("Error: wallet address decoding failed: {err}").red(); println!("{}", error_message); println!("Exiting..."); process::exit(1); @@ -174,7 +174,7 @@ pub(crate) fn validate_bech32_address_or_exit(address: &str) { if let Err(bech32_address_validation::Bech32Error::WrongPrefix(err)) = bech32_address_validation::validate_bech32_prefix(&prefix, address) { - let error_message = format!("Error: wallet address type is wrong, {}", err).red(); + let error_message = format!("Error: wallet address type is wrong, {err}").red(); println!("{}", error_message); println!("Exiting..."); process::exit(1); diff --git a/gateway/src/commands/sign.rs b/gateway/src/commands/sign.rs index 17d6eebfd4..61e9495f09 100644 --- a/gateway/src/commands/sign.rs +++ b/gateway/src/commands/sign.rs @@ -104,7 +104,7 @@ pub fn execute(args: &Sign) { let signed_target = match SignedTarget::try_from(args.clone()) { Ok(s) => s, Err(err) => { - error!("{}", err); + error!("{err}"); return; } }; diff --git a/gateway/src/commands/upgrade.rs b/gateway/src/commands/upgrade.rs index 7d8e5481a6..de3549b4f1 100644 --- a/gateway/src/commands/upgrade.rs +++ b/gateway/src/commands/upgrade.rs @@ -57,7 +57,7 @@ fn unsupported_upgrade(current_version: &Version, config_version: &Version) -> ! fn parse_config_version(config: &Config) -> Version { let version = Version::parse(config.get_version()).unwrap_or_else(|err| { - eprintln!("failed to parse client version! - {:?}", err); + eprintln!("failed to parse client version! - {err}"); process::exit(1) }); @@ -106,7 +106,7 @@ fn minor_0_12_upgrade( let upgraded_config = config.with_custom_version(to_version.to_string().as_ref()); upgraded_config.save_to_file(None).unwrap_or_else(|err| { - eprintln!("failed to overwrite config file! - {:?}", err); + eprintln!("failed to overwrite config file! - {err}"); print_failed_upgrade(config_version, &to_version); process::exit(1); }); @@ -140,7 +140,7 @@ pub async fn execute(args: &Upgrade) { let package_version = parse_package_version(); let existing_config = Config::load_from_file(Some(&args.id)).unwrap_or_else(|err| { - eprintln!("failed to load existing config file! - {:?}", err); + eprintln!("failed to load existing config file! - {err}"); process::exit(1) }); diff --git a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs index cb2d85b5a9..e7c2658daa 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs @@ -182,7 +182,7 @@ where /// * `mix_packet`: packet received from the client that should get forwarded into the network. fn forward_packet(&self, mix_packet: MixPacket) { if let Err(err) = self.inner.outbound_mix_sender.unbounded_send(mix_packet) { - error!("We failed to forward requested mix packet - {}. Presumably our mix forwarder has crashed. We cannot continue.", err); + error!("We failed to forward requested mix packet - {err}. Presumably our mix forwarder has crashed. We cannot continue."); process::exit(1); } } @@ -426,7 +426,7 @@ where None => break, Some(Ok(socket_msg)) => socket_msg, Some(Err(err)) => { - error!("failed to obtain message from websocket stream! stopping connection handler: {}", err); + error!("failed to obtain message from websocket stream! stopping connection handler: {err}"); break; } }; @@ -438,8 +438,7 @@ where if let Some(response) = self.handle_request(socket_msg).await { if let Err(err) = self.inner.send_websocket_message(response).await { warn!( - "Failed to send message over websocket: {}. Assuming the connection is dead.", - err + "Failed to send message over websocket: {err}. Assuming the connection is dead.", ); break; } @@ -447,8 +446,8 @@ where }, mix_messages = self.mix_receiver.next() => { let mix_messages = mix_messages.expect("sender was unexpectedly closed! this shouldn't have ever happened!"); - if let Err(e) = self.inner.push_packets_to_client(self.client.shared_keys, mix_messages).await { - warn!("failed to send the unwrapped sphinx packets back to the client - {:?}, assuming the connection is dead", e); + if let Err(err) = self.inner.push_packets_to_client(self.client.shared_keys, mix_messages).await { + warn!("failed to send the unwrapped sphinx packets back to the client - {err}, assuming the connection is dead"); break; } } diff --git a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs index 9e13fd2e69..9dd99eb23b 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs @@ -586,7 +586,7 @@ where let msg = match msg { Ok(msg) => msg, Err(err) => { - error!("failed to obtain message from websocket stream! stopping connection handler: {}", err); + error!("failed to obtain message from websocket stream! stopping connection handler: {err}"); break; } }; @@ -605,7 +605,7 @@ where if let Err(err) = self.send_websocket_message(err.into_error_message()).await { - debug!("Failed to send authentication error response - {}", err); + debug!("Failed to send authentication error response - {err}"); return None; } } @@ -614,7 +614,7 @@ where .send_websocket_message(auth_result.server_response.into()) .await { - debug!("Failed to send authentication response - {}", err); + debug!("Failed to send authentication response - {err}"); return None; } diff --git a/gateway/src/node/client_handling/websocket/listener.rs b/gateway/src/node/client_handling/websocket/listener.rs index ee76f0213a..580ec61750 100644 --- a/gateway/src/node/client_handling/websocket/listener.rs +++ b/gateway/src/node/client_handling/websocket/listener.rs @@ -55,7 +55,7 @@ impl Listener { let tcp_listener = match tokio::net::TcpListener::bind(self.address).await { Ok(listener) => listener, Err(err) => { - error!("Failed to bind the websocket to {} - {}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address, err); + error!("Failed to bind the websocket to {} - {err}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address); process::exit(1); } }; @@ -79,7 +79,7 @@ impl Listener { ); tokio::spawn(async move { handle.start_handling().await }); } - Err(e) => warn!("failed to get client: {:?}", e), + Err(err) => warn!("failed to get client: {err}"), } } } diff --git a/gateway/src/node/mixnet_handling/receiver/connection_handler.rs b/gateway/src/node/mixnet_handling/receiver/connection_handler.rs index 8dd85d9ded..5db66bd7cc 100644 --- a/gateway/src/node/mixnet_handling/receiver/connection_handler.rs +++ b/gateway/src/node/mixnet_handling/receiver/connection_handler.rs @@ -142,7 +142,7 @@ impl ConnectionHandler { .store_processed_packet_payload(client_address, unsent_plaintext) .await { - Err(err) => error!("Failed to store client data - {}", err), + Err(err) => error!("Failed to store client data - {err}"), Ok(_) => trace!("Stored packet for {}", client_address), }, Ok(_) => trace!("Pushed received packet to {}", client_address), @@ -163,8 +163,8 @@ impl ConnectionHandler { let processed_final_hop = match self.packet_processor.process_received(framed_sphinx_packet) { - Err(e) => { - debug!("We failed to process received sphinx packet - {:?}", e); + Err(err) => { + debug!("We failed to process received sphinx packet - {err}"); return; } Ok(processed_final_hop) => processed_final_hop, diff --git a/gateway/src/node/mixnet_handling/receiver/listener.rs b/gateway/src/node/mixnet_handling/receiver/listener.rs index 1cb1f2850e..d301dc692b 100644 --- a/gateway/src/node/mixnet_handling/receiver/listener.rs +++ b/gateway/src/node/mixnet_handling/receiver/listener.rs @@ -26,7 +26,7 @@ impl Listener { let tcp_listener = match tokio::net::TcpListener::bind(self.address).await { Ok(listener) => listener, Err(err) => { - error!("Failed to bind to {} - {}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address, err); + error!("Failed to bind to {} - {err}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address); process::exit(1); } }; @@ -37,7 +37,7 @@ impl Listener { let handler = connection_handler.clone(); tokio::spawn(handler.handle_connection(socket, remote_addr)); } - Err(e) => warn!("failed to get client: {:?}", e), + Err(err) => warn!("failed to get client: {err}"), } } } diff --git a/gateway/src/node/mixnet_handling/receiver/packet_processing.rs b/gateway/src/node/mixnet_handling/receiver/packet_processing.rs index af9970cb47..a344f475f1 100644 --- a/gateway/src/node/mixnet_handling/receiver/packet_processing.rs +++ b/gateway/src/node/mixnet_handling/receiver/packet_processing.rs @@ -6,21 +6,17 @@ use mixnode_common::packet_processor::error::MixProcessingError; pub use mixnode_common::packet_processor::processor::MixProcessingResult; use mixnode_common::packet_processor::processor::{ProcessedFinalHop, SphinxPacketProcessor}; use nymsphinx::framing::packet::FramedSphinxPacket; +use thiserror::Error; -#[derive(Debug)] +#[derive(Error, Debug)] pub enum GatewayProcessingError { - PacketProcessingError(MixProcessingError), + #[error("failed to process received mix packet - {0}")] + PacketProcessingError(#[from] MixProcessingError), + + #[error("received a forward hop mix packet")] ForwardHopReceivedError, } -impl From for GatewayProcessingError { - fn from(e: MixProcessingError) -> Self { - use GatewayProcessingError::*; - - PacketProcessingError(e) - } -} - // PacketProcessor contains all data required to correctly unwrap and store sphinx packets #[derive(Clone)] pub struct PacketProcessor { diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 1d23068db7..c04091ffdc 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -46,7 +46,7 @@ async fn initialise_storage(config: &Config) -> PersistentStorage { let path = config.get_persistent_store_path(); let retrieval_limit = config.get_message_retrieval_limit(); match PersistentStorage::init(path, retrieval_limit).await { - Err(err) => panic!("failed to initialise gateway storage - {}", err), + Err(err) => panic!("failed to initialise gateway storage - {err}"), Ok(storage) => storage, } } @@ -269,7 +269,7 @@ where let existing_gateways = match validator_client.get_cached_gateways().await { Ok(gateways) => gateways, Err(err) => { - error!("failed to grab initial network gateways - {}\n Please try to startup again in few minutes", err); + error!("failed to grab initial network gateways - {err}\n Please try to startup again in few minutes"); process::exit(1); } }; diff --git a/gateway/src/node/storage/mod.rs b/gateway/src/node/storage/mod.rs index aeed709455..cbb7c27f90 100644 --- a/gateway/src/node/storage/mod.rs +++ b/gateway/src/node/storage/mod.rs @@ -173,13 +173,13 @@ impl PersistentStorage { let connection_pool = match sqlx::SqlitePool::connect_with(opts).await { Ok(db) => db, Err(err) => { - error!("Failed to connect to SQLx database: {}", err); + error!("Failed to connect to SQLx database: {err}"); return Err(err.into()); } }; if let Err(err) = sqlx::migrate!("./migrations").run(&connection_pool).await { - error!("Failed to perform migration on the SQLx database: {}", err); + error!("Failed to perform migration on the SQLx database: {err}"); return Err(err.into()); } diff --git a/mixnode/src/commands/describe.rs b/mixnode/src/commands/describe.rs index 2bab09b8c9..07b2d420c8 100644 --- a/mixnode/src/commands/describe.rs +++ b/mixnode/src/commands/describe.rs @@ -18,7 +18,7 @@ pub(crate) fn execute(args: &Describe) { match Config::load_from_file(Some(&args.id)) { Ok(cfg) => cfg, Err(err) => { - error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {})", &args.id, err); + error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", &args.id); return; } }; diff --git a/mixnode/src/commands/mod.rs b/mixnode/src/commands/mod.rs index f716953c11..6ec353e76b 100644 --- a/mixnode/src/commands/mod.rs +++ b/mixnode/src/commands/mod.rs @@ -125,7 +125,7 @@ pub(crate) fn validate_bech32_address_or_exit(address: &str) { if let Err(bech32_address_validation::Bech32Error::DecodeFailed(err)) = bech32_address_validation::try_bech32_decode(address) { - let error_message = format!("Error: wallet address decoding failed: {}", err).red(); + let error_message = format!("Error: wallet address decoding failed: {err}").red(); println!("{}", error_message); println!("Exiting..."); process::exit(1); @@ -134,7 +134,7 @@ pub(crate) fn validate_bech32_address_or_exit(address: &str) { if let Err(bech32_address_validation::Bech32Error::WrongPrefix(err)) = bech32_address_validation::validate_bech32_prefix(&prefix, address) { - let error_message = format!("Error: wallet address type is wrong, {}", err).red(); + let error_message = format!("Error: wallet address type is wrong, {err}").red(); println!("{}", error_message); println!("Exiting..."); process::exit(1); diff --git a/mixnode/src/commands/upgrade.rs b/mixnode/src/commands/upgrade.rs index d104d47988..d11996830a 100644 --- a/mixnode/src/commands/upgrade.rs +++ b/mixnode/src/commands/upgrade.rs @@ -57,7 +57,7 @@ fn unsupported_upgrade(config_version: &Version, package_version: &Version) -> ! fn parse_config_version(config: &Config) -> Version { let version = Version::parse(config.get_version()).unwrap_or_else(|err| { - eprintln!("failed to parse client version! - {:?}", err); + eprintln!("failed to parse client version! - {err}"); process::exit(1) }); @@ -106,7 +106,7 @@ fn minor_0_12_upgrade( let upgraded_config = config.with_custom_version(to_version.to_string().as_ref()); upgraded_config.save_to_file(None).unwrap_or_else(|err| { - eprintln!("failed to overwrite config file! - {:?}", err); + eprintln!("failed to overwrite config file! - {err}"); print_failed_upgrade(config_version, &to_version); process::exit(1); }); @@ -140,7 +140,7 @@ pub(crate) fn execute(args: &Upgrade) { let package_version = parse_package_version(); let existing_config = Config::load_from_file(Some(&args.id)).unwrap_or_else(|err| { - eprintln!("failed to load existing config file! - {:?}", err); + eprintln!("failed to load existing config file! - {err}"); process::exit(1) }); diff --git a/mixnode/src/node/listener/connection_handler/mod.rs b/mixnode/src/node/listener/connection_handler/mod.rs index c9baaecacf..08e8395917 100644 --- a/mixnode/src/node/listener/connection_handler/mod.rs +++ b/mixnode/src/node/listener/connection_handler/mod.rs @@ -58,7 +58,7 @@ impl ConnectionHandler { // all processing such, key caching, etc. was done. // however, if it was a forward hop, we still need to delay it match self.packet_processor.process_received(framed_sphinx_packet) { - Err(e) => debug!("We failed to process received sphinx packet - {:?}", e), + Err(err) => debug!("We failed to process received sphinx packet - {err}"), Ok(res) => match res { MixProcessingResult::ForwardHop(forward_packet, delay) => { self.delay_and_forward_packet(forward_packet, delay) diff --git a/mixnode/src/node/listener/mod.rs b/mixnode/src/node/listener/mod.rs index a1542fba79..6b8ddbee1a 100644 --- a/mixnode/src/node/listener/mod.rs +++ b/mixnode/src/node/listener/mod.rs @@ -27,7 +27,7 @@ impl Listener { let listener = match TcpListener::bind(self.address).await { Ok(listener) => listener, Err(err) => { - error!("Failed to bind to {} - {}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address, err); + error!("Failed to bind to {} - {err}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address); process::exit(1); } }; @@ -40,7 +40,7 @@ impl Listener { let handler = connection_handler.clone(); tokio::spawn(handler.handle_connection(socket, remote_addr, self.shutdown.clone())); } - Err(err) => warn!("Failed to accept incoming connection - {:?}", err), + Err(err) => warn!("Failed to accept incoming connection - {err}"), } }, _ = self.shutdown.recv() => { diff --git a/nym-connect/Cargo.lock b/nym-connect/Cargo.lock index 711edb17af..5a07436347 100644 --- a/nym-connect/Cargo.lock +++ b/nym-connect/Cargo.lock @@ -639,7 +639,7 @@ dependencies = [ [[package]] name = "client-core" -version = "1.1.2" +version = "1.1.3" dependencies = [ "async-trait", "client-connections", @@ -1063,6 +1063,7 @@ dependencies = [ "pemstore", "rand 0.7.3", "subtle-encoding", + "thiserror", "x25519-dalek", ] @@ -3340,7 +3341,7 @@ dependencies = [ [[package]] name = "nym-connect" -version = "1.1.2" +version = "1.1.3" dependencies = [ "bip39", "client-core", @@ -3374,7 +3375,7 @@ dependencies = [ [[package]] name = "nym-socks5-client" -version = "1.1.2" +version = "1.1.3" dependencies = [ "clap", "client-connections", @@ -3462,6 +3463,7 @@ dependencies = [ "nymsphinx-types", "pemstore", "rand 0.7.3", + "thiserror", "topology", ] @@ -3535,6 +3537,7 @@ dependencies = [ "bytes", "nymsphinx-params", "nymsphinx-types", + "thiserror", "tokio-util", ] @@ -3544,6 +3547,7 @@ version = "0.1.0" dependencies = [ "crypto", "nymsphinx-types", + "thiserror", ] [[package]] @@ -3670,6 +3674,7 @@ name = "ordered-buffer" version = "0.1.0" dependencies = [ "log", + "thiserror", ] [[package]] diff --git a/nym-connect/src-tauri/src/state.rs b/nym-connect/src-tauri/src/state.rs index 3a98aa3747..97ddc43568 100644 --- a/nym-connect/src-tauri/src/state.rs +++ b/nym-connect/src-tauri/src/state.rs @@ -101,7 +101,7 @@ impl State { // Setup configuration by writing to file if let Err(err) = self.init_config().await { - log::error!("Failed to initialize: {}", err); + log::error!("Failed to initialize: {err}"); // Wait a little to give the user some rudimentary feedback that the click actually // registered. diff --git a/nym-connect/src-tauri/src/tasks.rs b/nym-connect/src-tauri/src/tasks.rs index ef54fddcaa..ea3c1b1fd9 100644 --- a/nym-connect/src-tauri/src/tasks.rs +++ b/nym-connect/src-tauri/src/tasks.rs @@ -134,13 +134,13 @@ pub fn start_disconnect_listener( .unwrap(); } Ok(Socks5ExitStatusMessage::Failed(err)) => { - log::info!("SOCKS5 task reported error: {}", err); + log::info!("SOCKS5 task reported error: {err}"); window .emit( "socks5-event", Payload { title: "SOCKS5 error".into(), - message: format!("SOCKS5 failed: {}", err), + message: format!("SOCKS5 failed: {err}"), }, ) .unwrap(); diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 3b99531457..200fc3a81c 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -2937,7 +2937,7 @@ dependencies = [ [[package]] name = "nym_wallet" -version = "1.1.2" +version = "1.1.3" dependencies = [ "aes-gcm", "argon2 0.3.4", diff --git a/nym-wallet/nym-wallet-recovery-cli/src/main.rs b/nym-wallet/nym-wallet-recovery-cli/src/main.rs index 7cb2c3e0d7..9798308fac 100644 --- a/nym-wallet/nym-wallet-recovery-cli/src/main.rs +++ b/nym-wallet/nym-wallet-recovery-cli/src/main.rs @@ -82,7 +82,7 @@ fn decrypt_file(file: File, passwords: &[String], parse: &ParseMode) -> Result<( match decrypt_login(login, passwords, parse) { Ok(is_success) if is_success => successes += 1, Ok(_) => println!("None of the provided passwords succeeded"), - Err(err) => println!("Failed: {}", err), + Err(err) => println!("Failed: {err}"), } } @@ -133,9 +133,9 @@ fn decrypt_login(login: &Value, passwords: &[String], parse: &ParseMode) -> Resu } return Ok(true); } - Err(err) => println!(" failed to parse\n{}", err), + Err(err) => println!(" failed to parse\n{err}"), }, - Err(err) => println!(" failed\n{}", err), + Err(err) => println!(" failed\n{err}"), } } @@ -160,10 +160,10 @@ fn get_login_entry(login: &Value) -> Result<(&str, &str, &str)> { fn base64_decode(ciphertext: &str, iv: &str, salt: &str) -> Result<(Vec, Vec, Vec)> { let ciphertext = base64::decode(ciphertext) - .map_err(|err| anyhow!("Unable to base64 decode ciphertext: {}", err))?; - let iv = base64::decode(iv).map_err(|err| anyhow!("Unable to base64 decode iv: {}", err))?; + .map_err(|err| anyhow!("Unable to base64 decode ciphertext: {err}"))?; + let iv = base64::decode(iv).map_err(|err| anyhow!("Unable to base64 decode iv: {err}"))?; let salt = - base64::decode(salt).map_err(|err| anyhow!("Unable to base64 decode salt: {}", err))?; + base64::decode(salt).map_err(|err| anyhow!("Unable to base64 decode salt: {err}"))?; Ok((ciphertext, iv, salt)) } @@ -186,7 +186,7 @@ fn decrypt_password( let mut key = Key::default(); argon2 .hash_password_into(password.as_bytes(), salt, &mut key) - .map_err(|err| anyhow!("Unable to hash password: {}", err))?; + .map_err(|err| anyhow!("Unable to hash password: {err}"))?; // Create the Cipher let cipher = Aes256Gcm::new(&key); diff --git a/nym-wallet/src-tauri/src/config/mod.rs b/nym-wallet/src-tauri/src/config/mod.rs index 9da3a1b73e..ee0bba8963 100644 --- a/nym-wallet/src-tauri/src/config/mod.rs +++ b/nym-wallet/src-tauri/src/config/mod.rs @@ -167,7 +167,7 @@ impl Config { Some(global) } Err(err) => { - log::trace!("Not loading {:#?}: {}", file, err); + log::trace!("Not loading {:#?}: {err}", file); None } } @@ -182,7 +182,7 @@ impl Config { log::trace!("Loaded from file {:#?}", file); networks.insert(network.as_key(), config); } - Err(err) => log::trace!("Not loading {:#?}: {}", file, err), + Err(err) => log::trace!("Not loading {:#?}: {err}", file), }; } diff --git a/nym-wallet/src-tauri/src/error.rs b/nym-wallet/src-tauri/src/error.rs index 46d8840947..bceff50f54 100644 --- a/nym-wallet/src-tauri/src/error.rs +++ b/nym-wallet/src-tauri/src/error.rs @@ -110,7 +110,7 @@ pub enum BackendError { WalletUnexpectedMnemonicAccount, #[error("Failed to derive address from mnemonic")] FailedToDeriveAddress, - #[error("{0}")] + #[error(transparent)] ValueParseError(#[from] ParseIntError), #[error("The provided coin has an unknown denomination - {0}")] UnknownCoinDenom(String), diff --git a/nym-wallet/src-tauri/src/operations/help/log.rs b/nym-wallet/src-tauri/src/operations/help/log.rs index c8ff873f6a..c4c2357304 100644 --- a/nym-wallet/src-tauri/src/operations/help/log.rs +++ b/nym-wallet/src-tauri/src/operations/help/log.rs @@ -5,8 +5,8 @@ use tauri::Manager; pub fn help_log_toggle_window(app_handle: tauri::AppHandle) -> Result<(), BackendError> { if let Some(current_log_window) = app_handle.windows().get("log") { log::info!("Closing log window..."); - if let Err(e) = current_log_window.close() { - log::error!("Unable to close log window: {:?}", e); + if let Err(err) = current_log_window.close() { + log::error!("Unable to close log window: {err}"); } return Ok(()); } @@ -17,13 +17,13 @@ pub fn help_log_toggle_window(app_handle: tauri::AppHandle) -> Result<(), Backen .build() { Ok(window) => { - if let Err(e) = window.set_focus() { - log::error!("Unable to focus log window: {:?}", e); + if let Err(err) = window.set_focus() { + log::error!("Unable to focus log window: {err}"); } Ok(()) } - Err(e) => { - log::error!("Unable to create log window: {:?}", e); + Err(err) => { + log::error!("Unable to create log window: {err}"); Err(BackendError::NewWindowError) } } diff --git a/service-providers/network-requester/src/allowed_hosts.rs b/service-providers/network-requester/src/allowed_hosts.rs index 3746d9a706..0350ab1f7c 100644 --- a/service-providers/network-requester/src/allowed_hosts.rs +++ b/service-providers/network-requester/src/allowed_hosts.rs @@ -39,7 +39,7 @@ impl OutboundRequestFilter { ) -> OutboundRequestFilter { let domain_list = match Self::fetch_domain_list() { Ok(list) => list, - Err(e) => panic!("Couldn't fetch domain list for request filtering, do you have an internet connection?: {:?}", e), + Err(err) => panic!("Couldn't fetch domain list for request filtering, do you have an internet connection?: {err}"), }; OutboundRequestFilter { allowed_hosts, diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index 34fb42e7c0..202ac3d1c1 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -234,7 +234,7 @@ impl ServiceProvider { continue; } ServerResponse::Error(err) => { - panic!("received error from native client! - {}", err) + panic!("received error from native client! - {err}") } _ => unimplemented!("probably should never be reached?"), }; diff --git a/service-providers/network-statistics/src/api/error.rs b/service-providers/network-statistics/src/api/error.rs index d2b190840e..bebafc2fde 100644 --- a/service-providers/network-statistics/src/api/error.rs +++ b/service-providers/network-statistics/src/api/error.rs @@ -12,10 +12,10 @@ pub type Result = std::result::Result; #[derive(Debug, thiserror::Error)] pub enum NetworkStatisticsAPIError { - #[error("{0}")] + #[error(transparent)] RocketError(#[from] Box), - #[error("{0}")] + #[error(transparent)] StorageError(#[from] NetworkStatisticsStorageError), } diff --git a/validator-api/src/coconut/deposit.rs b/validator-api/src/coconut/deposit.rs index 8dba92a705..2112b3d76a 100644 --- a/validator-api/src/coconut/deposit.rs +++ b/validator-api/src/coconut/deposit.rs @@ -164,17 +164,13 @@ mod test { let err = extract_encryption_key(&req, tx_entry.clone()) .await .unwrap_err(); - assert_eq!( - err.to_string(), + + assert!(matches!( + err, CoconutError::Ed25519ParseError( - // this is really just a useless, dummy error value needed to generate the error type - // and get its string representation - crypto::asymmetric::identity::Ed25519RecoveryError::MalformedBytes( - crypto::asymmetric::identity::SignatureError::new(), - ), + crypto::asymmetric::identity::Ed25519RecoveryError::MalformedSignatureString { .. } ) - .to_string() - ); + )); let correct_request = BlindSignRequestBody::new( &blind_sign_req, @@ -279,17 +275,13 @@ mod test { let err = extract_encryption_key(&correct_request, tx_entry.clone()) .await .unwrap_err(); - assert_eq!( - err.to_string(), + + assert!(matches!( + err, CoconutError::Ed25519ParseError( - // this is really just a useless, dummy error value needed to generate the error type - // and get its string representation - crypto::asymmetric::identity::Ed25519RecoveryError::MalformedBytes( - crypto::asymmetric::identity::SignatureError::new(), - ), + crypto::asymmetric::identity::Ed25519RecoveryError::MalformedPublicKeyString { .. } ) - .to_string(), - ); + )); tx_entry.tx_result.events.get_mut(0).unwrap().attributes = vec![ Tag { @@ -338,15 +330,13 @@ mod test { let err = extract_encryption_key(&correct_request, tx_entry.clone()) .await .unwrap_err(); - assert_eq!( - err.to_string(), + + assert!(matches!( + err, CoconutError::X25519ParseError( - // this is really just a useless, dummy error value needed to generate the error type - // and get its string representation - crypto::asymmetric::encryption::KeyRecoveryError::InvalidPublicKeyBytes, + crypto::asymmetric::encryption::KeyRecoveryError::MalformedPublicKeyString { .. } ) - .to_string(), - ); + )); let expected_encryption_key = "HxnTpWTkgigSTAysVKLE8pEiUULHdTT1BxFfzfJvQRi6"; tx_entry.tx_result.events.get_mut(0).unwrap().attributes = vec![ diff --git a/validator-api/src/coconut/error.rs b/validator-api/src/coconut/error.rs index 234d1cb96c..00c7d9c7a0 100644 --- a/validator-api/src/coconut/error.rs +++ b/validator-api/src/coconut/error.rs @@ -20,16 +20,16 @@ pub type Result = std::result::Result; #[derive(Debug, Error)] pub enum CoconutError { - #[error("{0}")] + #[error(transparent)] IOError(#[from] std::io::Error), - #[error("{0}")] + #[error(transparent)] SerdeJsonError(#[from] serde_json::Error), - #[error("Could not parse Ed25519 data")] + #[error("Could not parse Ed25519 data - {0}")] Ed25519ParseError(#[from] Ed25519RecoveryError), - #[error("Could not parse X25519 data")] + #[error("Could not parse X25519 data - {0}")] X25519ParseError(#[from] KeyRecoveryError), #[error("Could not parse tx hash in request body")] diff --git a/validator-api/src/contract_cache/mod.rs b/validator-api/src/contract_cache/mod.rs index f635933ae6..b4619214b8 100644 --- a/validator-api/src/contract_cache/mod.rs +++ b/validator-api/src/contract_cache/mod.rs @@ -192,7 +192,7 @@ impl ValidatorCacheRefresher { .await; if let Err(err) = self.update_notifier.send(CacheNotification::Updated) { - warn!("Failed to notify validator cache refresh: {}", err); + warn!("Failed to notify validator cache refresh: {err}"); } Ok(()) @@ -213,7 +213,7 @@ impl ValidatorCacheRefresher { } ret = self.refresh_cache() => { if let Err(err) = ret { - error!("Failed to refresh validator cache - {}", err); + error!("Failed to refresh validator cache - {err}"); } else { // relaxed memory ordering is fine here. worst case scenario network monitor // will just have to wait for an additional backoff to see the change. diff --git a/validator-api/src/epoch_operations/mod.rs b/validator-api/src/epoch_operations/mod.rs index 8615393779..ec7bfbfaf4 100644 --- a/validator-api/src/epoch_operations/mod.rs +++ b/validator-api/src/epoch_operations/mod.rs @@ -208,7 +208,7 @@ impl RewardedSetUpdater { let rewarded_set: Vec = match self.nymd_client.get_rewarded_set_mixnodes().await { Ok(nodes) => nodes.into_iter().map(|(id, _)| id).collect::>(), Err(err) => { - warn!("failed to obtain the current rewarded set - {}. falling back to the cached version", err); + warn!("failed to obtain the current rewarded set - {err}. falling back to the cached version"); self.validator_cache .rewarded_set() .await @@ -285,7 +285,7 @@ impl RewardedSetUpdater { // Reward all the nodes in the still current, soon to be previous rewarded set log::info!("Rewarding the current rewarded set..."); if let Err(err) = self.reward_current_rewarded_set(interval).await { - log::error!("FAILED to reward rewarded set - {}", err); + log::error!("FAILED to reward rewarded set - {err}"); // since we haven't advanced the epoch yet, we will attempt to reward those nodes again // next time we enter this function (i.e. within 2min or so) // @@ -303,7 +303,7 @@ impl RewardedSetUpdater { log::info!("Reconciling all pending epoch events..."); if let Err(err) = self.nymd_client.reconcile_epoch_events().await { - log::error!("FAILED to reconcile epoch events... - {}", err); + log::error!("FAILED to reconcile epoch events... - {err}"); return Err(err.into()); } else { log::info!("Reconciled all pending epoch events... SUCCESS"); @@ -314,7 +314,7 @@ impl RewardedSetUpdater { .update_rewarded_set_and_advance_epoch(&all_mixnodes) .await { - log::error!("FAILED to advance the current epoch... - {}", err); + log::error!("FAILED to advance the current epoch... - {err}"); return Err(err); } else { log::info!("Advanced the epoch and updated the rewarded set... SUCCESS"); @@ -434,11 +434,11 @@ impl RewardedSetUpdater { Some(interval) => interval, }; if let Err(err) = self.update_blacklist(&interval_details).await { - error!("failed to update the node blacklist - {}", err); + error!("failed to update the node blacklist - {err}"); continue; } if let Err(err) = self.perform_epoch_operations(interval_details).await { - error!("failed to perform epoch operations - {}", err); + error!("failed to perform epoch operations - {err}"); sleep(Duration::from_secs(30)).await; } } diff --git a/validator-api/src/main.rs b/validator-api/src/main.rs index 3055d57f88..e3411b1b7f 100644 --- a/validator-api/src/main.rs +++ b/validator-api/src/main.rs @@ -278,7 +278,7 @@ fn override_config(mut config: Config, matches: &ArgMatches) -> Config { if let Some(raw_validator) = matches.value_of(NYMD_VALIDATOR_ARG) { let parsed = match raw_validator.parse() { Err(err) => { - error!("Passed validator argument is invalid - {}", err); + error!("Passed validator argument is invalid - {err}"); process::exit(1) } Ok(url) => url, @@ -336,7 +336,7 @@ fn override_config(mut config: Config, matches: &ArgMatches) -> Config { if matches.is_present(WRITE_CONFIG_ARG) { info!("Saving the configuration to a file"); if let Err(err) = config.save_to_file(None) { - error!("Failed to write config to a file - {}", err); + error!("Failed to write config to a file - {err}"); process::exit(1) } } diff --git a/validator-api/src/network_monitor/monitor/processor.rs b/validator-api/src/network_monitor/monitor/processor.rs index 7b0649a49d..4a86c52612 100644 --- a/validator-api/src/network_monitor/monitor/processor.rs +++ b/validator-api/src/network_monitor/monitor/processor.rs @@ -2,45 +2,39 @@ // SPDX-License-Identifier: Apache-2.0 use crate::network_monitor::gateways_reader::GatewayMessages; -use crate::network_monitor::test_packet::TestPacket; +use crate::network_monitor::test_packet::{TestPacket, TestPacketError}; use crate::network_monitor::ROUTE_TESTING_TEST_NONCE; use crypto::asymmetric::encryption; use futures::channel::mpsc; use futures::lock::{Mutex, MutexGuard}; use futures::{SinkExt, StreamExt}; use log::warn; -use nymsphinx::receiver::MessageReceiver; -use std::fmt::{self, Display, Formatter}; +use nymsphinx::receiver::{MessageReceiver, MessageRecoveryError}; use std::mem; use std::sync::Arc; +use thiserror::Error; pub(crate) type ReceivedProcessorSender = mpsc::UnboundedSender; pub(crate) type ReceivedProcessorReceiver = mpsc::UnboundedReceiver; -#[derive(Debug)] +#[derive(Error, Debug)] enum ProcessingError { - MalformedPacketReceived, - NonTestPacketReceived, - NonMatchingNonce(u64), - ReceivedOutsideTestRun, -} + #[error( + "could not recover underlying data from the received packet since it was malformed - {0}" + )] + MalformedPacketReceived(#[from] MessageRecoveryError), -impl Display for ProcessingError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - ProcessingError::MalformedPacketReceived => write!(f, "received malformed packet"), - ProcessingError::NonTestPacketReceived => write!(f, "received a non-test packet"), - ProcessingError::NonMatchingNonce(nonce) => write!( - f, - "received packet with nonce {} which is different than the expected", - nonce - ), - ProcessingError::ReceivedOutsideTestRun => write!( - f, - "received packet while the test is currently not in progress" - ), - } - } + #[error("received a mix packet that was NOT a proper network monitor test packet")] + NonTestPacketReceived, + + #[error("the received test packet was malformed - {0}")] + MalformedTestPacket(#[from] TestPacketError), + + #[error("received packet with an unexpected nonce. Got: {received}, expected: {expected}")] + NonMatchingNonce { received: u64, expected: u64 }, + + #[error("received a mix packet while no test run is currently in progress")] + ReceivedOutsideTestRun, } // we can't use Notify due to possible edge case where both notification are consumed at once @@ -80,23 +74,20 @@ impl ReceivedProcessorInner { .recover_plaintext_from_regular_packet( self.client_encryption_keypair.private_key(), &mut message, - ) - .map_err(|_| ProcessingError::MalformedPacketReceived)?; - let fragment = self - .message_receiver - .recover_fragment(plaintext) - .map_err(|_| ProcessingError::MalformedPacketReceived)?; + )?; + let fragment = self.message_receiver.recover_fragment(plaintext)?; let (recovered, _) = self .message_receiver - .insert_new_fragment(fragment) - .map_err(|_| ProcessingError::MalformedPacketReceived)? + .insert_new_fragment(fragment)? .ok_or(ProcessingError::NonTestPacketReceived)?; // if it's a test packet it MUST BE reconstructed with single fragment - let test_packet = TestPacket::try_from_bytes(&recovered.into_inner_data()) - .map_err(|_| ProcessingError::MalformedPacketReceived)?; + let test_packet = TestPacket::try_from_bytes(&recovered.into_inner_data())?; // we know nonce is NOT none if test_packet.test_nonce() != self.test_nonce.unwrap() { - return Err(ProcessingError::NonMatchingNonce(test_packet.test_nonce())); + return Err(ProcessingError::NonMatchingNonce { + received: test_packet.test_nonce(), + expected: self.test_nonce.unwrap(), + }); } self.received_packets.push(test_packet); @@ -162,7 +153,7 @@ impl ReceivedProcessor { Some(messages) => { for message in messages { if let Err(err) = inner.on_message(message) { - warn!(target: "Monitor", "failed to process received gateway message - {}", err) + warn!(target: "Monitor", "failed to process received gateway message - {err}") } } } diff --git a/validator-api/src/network_monitor/test_packet.rs b/validator-api/src/network_monitor/test_packet.rs index 8f5e0bde5e..4806c3efe4 100644 --- a/validator-api/src/network_monitor/test_packet.rs +++ b/validator-api/src/network_monitor/test_packet.rs @@ -3,12 +3,14 @@ use crate::network_monitor::monitor::preparer::TestedNode; use crypto::asymmetric::identity; +use crypto::asymmetric::identity::Ed25519RecoveryError; use mixnet_contract_common::MixId; use std::convert::TryInto; use std::fmt::{self, Display, Formatter}; use std::hash::{Hash, Hasher}; use std::mem; use std::str::Utf8Error; +use thiserror::Error; use topology::{gateway, mix}; const MIXNODE_TYPE: u8 = 0; @@ -67,24 +69,25 @@ impl NodeType { } } -#[derive(Debug)] +#[derive(Debug, Error)] pub(crate) enum TestPacketError { - IncompletePacket, + #[error( + "the received packet was incomplete. Got {received} bytes but expected at least {min_expected}" + )] + IncompletePacket { + received: usize, + min_expected: usize, + }, + + // TODO: ideally this should contain more information but that'd require more refactoring than I'm willing to commit to now + #[error("the received packet did not contain a valid node type")] InvalidNodeType, - InvalidNodeKey, - InvalidOwner(Utf8Error), -} -impl From for TestPacketError { - fn from(_: identity::Ed25519RecoveryError) -> Self { - TestPacketError::InvalidNodeKey - } -} + #[error("the received node identity key was malformed - {0}")] + InvalidNodeKey(#[from] Ed25519RecoveryError), -impl From for TestPacketError { - fn from(err: Utf8Error) -> Self { - TestPacketError::InvalidOwner(err) - } + #[error("the received packet contained malformed owner data - {0}")] + InvalidOwner(#[from] Utf8Error), } #[derive(Eq, Clone, Debug)] @@ -184,7 +187,10 @@ impl TestPacket { let n = mem::size_of::(); if b.len() < 2 * n + 1 + identity::PUBLIC_KEY_LENGTH { - return Err(TestPacketError::IncompletePacket); + return Err(TestPacketError::IncompletePacket { + received: b.len(), + min_expected: 2 * n + 1 + identity::PUBLIC_KEY_LENGTH, + }); } // those unwraps can't fail as we've already checked for the size diff --git a/validator-api/src/node_status_api/models.rs b/validator-api/src/node_status_api/models.rs index ae9661bf23..329f9f7122 100644 --- a/validator-api/src/node_status_api/models.rs +++ b/validator-api/src/node_status_api/models.rs @@ -17,18 +17,19 @@ use schemars::gen::SchemaGenerator; use schemars::schema::{InstanceType, Schema}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use sqlx::Error; use std::convert::TryFrom; -use std::fmt::{self, Display, Formatter}; +use thiserror::Error; use time::OffsetDateTime; use validator_api_requests::models::{ GatewayStatusReportResponse, GatewayUptimeHistoryResponse, HistoricalUptimeResponse, MixnodeStatusReportResponse, MixnodeUptimeHistoryResponse, RequestError, }; -// todo: put into some error enum -#[derive(Debug)] -pub struct InvalidUptime; +#[derive(Error, Debug)] +#[error("Received uptime value was within 0-100 range (got {received})")] +pub struct InvalidUptime { + received: isize, +} // value in range 0-100 #[derive(Clone, Copy, Serialize, Deserialize, Debug, Default, JsonSchema)] @@ -56,7 +57,9 @@ impl Uptime { let uptime = ((numerator as f32 / denominator as f32) * 100.0).round() as u8; if uptime > 100 { - Err(InvalidUptime) + Err(InvalidUptime { + received: uptime as isize, + }) } else { Ok(Uptime(uptime)) } @@ -70,7 +73,9 @@ impl Uptime { let uptime = (running_sum / count as f32).round() as u8; if uptime > 100 { - Err(InvalidUptime) + Err(InvalidUptime { + received: uptime as isize, + }) } else { Ok(Uptime(uptime)) } @@ -92,7 +97,9 @@ impl TryFrom for Uptime { fn try_from(value: u8) -> Result { if value > 100 { - Err(InvalidUptime) + Err(InvalidUptime { + received: value as isize, + }) } else { Ok(Uptime(value)) } @@ -104,7 +111,9 @@ impl TryFrom for Uptime { fn try_from(value: i64) -> Result { if !(0..=100).contains(&value) { - Err(InvalidUptime) + Err(InvalidUptime { + received: value as isize, + }) } else { Ok(Uptime(value as u8)) } @@ -365,47 +374,27 @@ impl OpenApiResponderInner for ErrorResponse { #[derive(Debug, thiserror::Error)] pub enum ValidatorApiStorageError { - MixnodeReportNotFound(MixId), - GatewayReportNotFound(String), - MixnodeUptimeHistoryNotFound(MixId), - GatewayUptimeHistoryNotFound(String), + #[error("could not find status report associated with mixnode {mix_id}")] + MixnodeReportNotFound { mix_id: MixId }, + + #[error("Could not find status report associated with gateway {identity}")] + GatewayReportNotFound { identity: IdentityKey }, + + #[error("could not find uptime history associated with mixnode {mix_id}")] + MixnodeUptimeHistoryNotFound { mix_id: MixId }, + + #[error("could not find uptime history associated with gateway {identity}")] + GatewayUptimeHistoryNotFound { identity: IdentityKey }, // I don't think we want to expose errors to the user about what really happened - InternalDatabaseError(String), -} + #[error("experienced internal database error")] + InternalDatabaseError(#[from] sqlx::Error), -impl From for ValidatorApiStorageError { - fn from(err: Error) -> Self { - ValidatorApiStorageError::InternalDatabaseError(err.to_string()) - } -} + // the same is true here (also note that the message is subtly different so we would be able to distinguish them) + #[error("experienced internal storage error")] + DatabaseInconsistency { reason: String }, -impl Display for ValidatorApiStorageError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - ValidatorApiStorageError::MixnodeReportNotFound(mix_id) => write!( - f, - "Could not find status report associated with mixnode {}", - mix_id - ), - ValidatorApiStorageError::GatewayReportNotFound(identity) => write!( - f, - "Could not find status report associated with gateway {}", - identity - ), - ValidatorApiStorageError::MixnodeUptimeHistoryNotFound(mix_id) => write!( - f, - "Could not find uptime history associated with mixnode {}", - mix_id - ), - ValidatorApiStorageError::GatewayUptimeHistoryNotFound(identity) => write!( - f, - "Could not find uptime history associated with gateway {}", - identity - ), - ValidatorApiStorageError::InternalDatabaseError(err) => { - write!(f, "The internal database has experienced an issue: {err}") - } - } - } + // this one would never be returned to users since it's only possible on startup + #[error("failed to perform startup SQL migration - {0}")] + StartupMigrationFailure(#[from] sqlx::migrate::MigrateError), } diff --git a/validator-api/src/storage/mod.rs b/validator-api/src/storage/mod.rs index 21a5b2ca23..04186b7b57 100644 --- a/validator-api/src/storage/mod.rs +++ b/validator-api/src/storage/mod.rs @@ -41,19 +41,15 @@ impl ValidatorApiStorage { let connection_pool = match sqlx::SqlitePool::connect_with(opts).await { Ok(db) => db, - Err(e) => { - error!("Failed to connect to SQLx database: {}", e); - return Err(ValidatorApiStorageError::InternalDatabaseError( - e.to_string(), - )); + Err(err) => { + error!("Failed to connect to SQLx database: {err}"); + return Err(err.into()); } }; - if let Err(e) = sqlx::migrate!("./migrations").run(&connection_pool).await { - error!("Failed to initialize SQLx database: {}", e); - return Err(ValidatorApiStorageError::InternalDatabaseError( - e.to_string(), - )); + if let Err(err) = sqlx::migrate!("./migrations").run(&connection_pool).await { + error!("Failed to initialize SQLx database: {err}"); + return Err(err.into()); } info!("Database migration finished!"); @@ -175,7 +171,7 @@ impl ValidatorApiStorage { // if we have no statuses, the node doesn't exist (or monitor is down), but either way, we can't make a report if statuses.is_empty() { - return Err(ValidatorApiStorageError::MixnodeReportNotFound(mix_id)); + return Err(ValidatorApiStorageError::MixnodeReportNotFound { mix_id }); } // determine the number of runs the mixnode should have been online for @@ -219,9 +215,9 @@ impl ValidatorApiStorage { // if we have no statuses, the node doesn't exist (or monitor is down), but either way, we can't make a report if statuses.is_empty() { - return Err(ValidatorApiStorageError::GatewayReportNotFound( - identity.to_owned(), - )); + return Err(ValidatorApiStorageError::GatewayReportNotFound { + identity: identity.to_owned(), + }); } // determine the number of runs the gateway should have been online for @@ -253,9 +249,7 @@ impl ValidatorApiStorage { let history = self.manager.get_mixnode_historical_uptimes(mix_id).await?; if history.is_empty() { - return Err(ValidatorApiStorageError::MixnodeUptimeHistoryNotFound( - mix_id, - )); + return Err(ValidatorApiStorageError::MixnodeUptimeHistoryNotFound { mix_id }); } let mixnode_owner = @@ -286,9 +280,9 @@ impl ValidatorApiStorage { .await?; if history.is_empty() { - return Err(ValidatorApiStorageError::GatewayUptimeHistoryNotFound( - identity.to_owned(), - )); + return Err(ValidatorApiStorageError::GatewayUptimeHistoryNotFound { + identity: identity.to_owned(), + }); } let gateway_owner = @@ -447,30 +441,36 @@ impl ValidatorApiStorage { let layer1_mix_db_id = self .manager .get_mixnode_database_id(test_route.layer_one_mix().mix_id) - .await - .map_err(|_| ValidatorApiStorageError::InternalDatabaseError("".to_string()))? - .ok_or_else(|| ValidatorApiStorageError::InternalDatabaseError("".to_string()))?; + .await? + .ok_or_else(|| ValidatorApiStorageError::DatabaseInconsistency { + reason: format!("could not get db id for layer1 mixnode from network monitor run {monitor_run_db_id}"), + })?; let layer2_mix_db_id = self .manager .get_mixnode_database_id(test_route.layer_two_mix().mix_id) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))? - .ok_or_else(|| ValidatorApiStorageError::InternalDatabaseError("".to_string()))?; + .await? + .ok_or_else(|| ValidatorApiStorageError::DatabaseInconsistency { + reason: format!("could not get db id for layer2 mixnode from network monitor run {monitor_run_db_id}"), + })?; let layer3_mix_db_id = self .manager .get_mixnode_database_id(test_route.layer_three_mix().mix_id) - .await - .map_err(|_| ValidatorApiStorageError::InternalDatabaseError("".to_string()))? - .ok_or_else(|| ValidatorApiStorageError::InternalDatabaseError("".to_string()))?; + .await? + .ok_or_else(|| ValidatorApiStorageError::DatabaseInconsistency { + reason: format!("could not get db id for layer3 mixnode from network monitor run {monitor_run_db_id}"), + })?; let gateway_db_id = self .manager .get_gateway_id(&test_route.gateway().identity_key.to_base58_string()) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))? - .ok_or_else(|| ValidatorApiStorageError::InternalDatabaseError("".to_string()))?; + .await? + .ok_or_else(|| ValidatorApiStorageError::DatabaseInconsistency { + reason: format!( + "could not get db id for gateway from network monitor run {monitor_run_db_id}" + ), + })?; self.manager .submit_testing_route_used(TestingRoute { @@ -480,8 +480,7 @@ impl ValidatorApiStorage { layer3_mix_db_id, monitor_run_db_id, }) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))?; + .await?; Ok(()) } @@ -498,11 +497,7 @@ impl ValidatorApiStorage { mix_id: MixId, since: Option, ) -> Result { - let db_id = self - .manager - .get_mixnode_database_id(mix_id) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))?; + let db_id = self.manager.get_mixnode_database_id(mix_id).await?; if let Some(node_id) = db_id { let since = since @@ -511,7 +506,7 @@ impl ValidatorApiStorage { self.manager .get_mixnode_testing_route_presence_count_since(node_id, since) .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string())) + .map_err(|err| err.into()) } else { Ok(0) } @@ -530,11 +525,7 @@ impl ValidatorApiStorage { identity: &str, since: Option, ) -> Result { - let node_id = self - .manager - .get_gateway_id(identity) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))?; + let node_id = self.manager.get_gateway_id(identity).await?; if let Some(node_id) = node_id { let since = since @@ -543,7 +534,7 @@ impl ValidatorApiStorage { self.manager .get_gateway_testing_route_presence_count_since(node_id, since) .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string())) + .map_err(|err| err.into()) } else { Ok(0) } @@ -567,21 +558,15 @@ impl ValidatorApiStorage { let now = OffsetDateTime::now_utc().unix_timestamp(); - let monitor_run_id = self - .manager - .insert_monitor_run(now) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))?; + let monitor_run_id = self.manager.insert_monitor_run(now).await?; self.manager .submit_mixnode_statuses(now, mixnode_results) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))?; + .await?; self.manager .submit_gateway_statuses(now, gateway_results) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))?; + .await?; for test_route in test_routes { self.insert_test_route(monitor_run_id, test_route).await?; @@ -605,9 +590,9 @@ impl ValidatorApiStorage { if run_count < 0 { // I don't think it's ever possible for SQL to return a negative value from COUNT? - return Err(ValidatorApiStorageError::InternalDatabaseError( - "Negative run count".to_string(), - )); + return Err(ValidatorApiStorageError::DatabaseInconsistency { + reason: "Negative run count".to_string(), + }); } Ok(run_count as usize) } @@ -629,12 +614,7 @@ impl ValidatorApiStorage { for report in mixnode_reports { // if this ever fails, we have a super weird error because we just constructed report for that node // and we never delete node data! - let node_id = match self - .manager - .get_mixnode_database_id(report.mix_id) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))? - { + let node_id = match self.manager.get_mixnode_database_id(report.mix_id).await? { Some(node_id) => node_id, None => { error!( @@ -647,19 +627,13 @@ impl ValidatorApiStorage { self.manager .insert_mixnode_historical_uptime(node_id, today_iso_8601, report.last_day.u8()) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))?; + .await?; } for report in gateway_reports { // if this ever fails, we have a super weird error because we just constructed report for that node // and we never delete node data! - let node_id = match self - .manager - .get_gateway_id(&report.identity) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))? - { + let node_id = match self.manager.get_gateway_id(&report.identity).await? { Some(node_id) => node_id, None => { error!( @@ -672,8 +646,7 @@ impl ValidatorApiStorage { self.manager .insert_gateway_historical_uptime(node_id, today_iso_8601, report.last_day.u8()) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))?; + .await?; } Ok(()) @@ -686,7 +659,7 @@ impl ValidatorApiStorage { self.manager .check_for_historical_uptime_existence(date_iso_8601) .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string())) + .map_err(|err| err.into()) } /// Removes all ipv4 and ipv6 statuses for all mixnodes and gateways that are older than the @@ -699,14 +672,11 @@ impl ValidatorApiStorage { &self, until: i64, ) -> Result<(), ValidatorApiStorageError> { - self.manager - .purge_old_mixnode_statuses(until) - .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string()))?; + self.manager.purge_old_mixnode_statuses(until).await?; self.manager .purge_old_gateway_statuses(until) .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string())) + .map_err(|err| err.into()) } pub(crate) async fn insert_rewarding_report( @@ -716,7 +686,7 @@ impl ValidatorApiStorage { self.manager .insert_rewarding_report(report) .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string())) + .map_err(|err| err.into()) } pub(crate) async fn get_rewarding_report( @@ -726,7 +696,7 @@ impl ValidatorApiStorage { self.manager .get_rewarding_report(absolute_epoch_id) .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string())) + .map_err(|err| err.into()) } #[cfg(feature = "coconut")] @@ -737,7 +707,7 @@ impl ValidatorApiStorage { self.manager .get_blinded_signature_response(tx_hash) .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string())) + .map_err(|err| err.into()) } #[cfg(feature = "coconut")] @@ -749,6 +719,6 @@ impl ValidatorApiStorage { self.manager .insert_blinded_signature_response(tx_hash, blinded_signature_response) .await - .map_err(|e| ValidatorApiStorageError::InternalDatabaseError(e.to_string())) + .map_err(|err| err.into()) } } From 3ebb24b2c822a586e6e7f2493e494379c7a3248e Mon Sep 17 00:00:00 2001 From: Fouad Date: Wed, 14 Dec 2022 12:12:34 +0000 Subject: [PATCH 02/21] get version number from tauri and display (#2684) * get version number from tauri and display * update internal version numbers --- nym-connect/Cargo.lock | 2 +- nym-connect/src-tauri/Cargo.toml | 2 +- nym-connect/src-tauri/tauri.conf.json | 2 +- nym-connect/src/components/AppVersion.tsx | 13 +++++++++++++ nym-connect/src/components/AppWindowFrame.tsx | 6 +++++- nym-connect/src/context/main.tsx | 11 +++++++++++ nym-connect/src/context/mocks/main.tsx | 1 + 7 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 nym-connect/src/components/AppVersion.tsx diff --git a/nym-connect/Cargo.lock b/nym-connect/Cargo.lock index 5a07436347..3ba62ad4f0 100644 --- a/nym-connect/Cargo.lock +++ b/nym-connect/Cargo.lock @@ -3341,7 +3341,7 @@ dependencies = [ [[package]] name = "nym-connect" -version = "1.1.3" +version = "1.1.4" dependencies = [ "bip39", "client-core", diff --git a/nym-connect/src-tauri/Cargo.toml b/nym-connect/src-tauri/Cargo.toml index 46c2278178..66cab35d7a 100644 --- a/nym-connect/src-tauri/Cargo.toml +++ b/nym-connect/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-connect" -version = "1.1.3" +version = "1.1.4" description = "nym-connect" authors = ["Nym Technologies SA"] license = "" diff --git a/nym-connect/src-tauri/tauri.conf.json b/nym-connect/src-tauri/tauri.conf.json index 8c0597d17e..3d435986ed 100644 --- a/nym-connect/src-tauri/tauri.conf.json +++ b/nym-connect/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "package": { "productName": "nym-connect", - "version": "1.1.3" + "version": "1.1.4" }, "build": { "distDir": "../dist", diff --git a/nym-connect/src/components/AppVersion.tsx b/nym-connect/src/components/AppVersion.tsx new file mode 100644 index 0000000000..06c63079d6 --- /dev/null +++ b/nym-connect/src/components/AppVersion.tsx @@ -0,0 +1,13 @@ +import { Typography } from '@mui/material'; +import React from 'react'; +import { useClientContext } from 'src/context/main'; + +export const AppVersion = () => { + const { appVersion } = useClientContext(); + + return ( + + Version {appVersion} + + ); +}; diff --git a/nym-connect/src/components/AppWindowFrame.tsx b/nym-connect/src/components/AppWindowFrame.tsx index 5fc3d60ff6..9420a57f07 100644 --- a/nym-connect/src/components/AppWindowFrame.tsx +++ b/nym-connect/src/components/AppWindowFrame.tsx @@ -1,18 +1,22 @@ import React from 'react'; import { Box } from '@mui/material'; import { CustomTitleBar } from './CustomTitleBar'; +import { AppVersion } from './AppVersion'; export const AppWindowFrame: React.FC = ({ children }) => ( {children} + ); diff --git a/nym-connect/src/context/main.tsx b/nym-connect/src/context/main.tsx index 5d2b049bf9..d33af4e0b6 100644 --- a/nym-connect/src/context/main.tsx +++ b/nym-connect/src/context/main.tsx @@ -9,6 +9,7 @@ import { ConnectionStatsItem } from '../components/ConnectionStats'; import { ServiceProvider, Services } from '../types/directory'; import { Error } from 'src/types/error'; import { TauriEvent } from 'src/types/event'; +import { getVersion } from '@tauri-apps/api/app'; const TAURI_EVENT_STATUS_CHANGED = 'app:connection-status-changed'; @@ -16,6 +17,7 @@ type ModeType = 'light' | 'dark'; export type TClientContext = { mode: ModeType; + appVersion?: string; connectionStatus: ConnectionStatusKind; connectionStats?: ConnectionStatsItem[]; connectedSince?: DateTime; @@ -47,11 +49,13 @@ export const ClientContextProvider = ({ children }: { children: React.ReactNode const [serviceProvider, setRawServiceProvider] = React.useState(); const [showHelp, setShowHelp] = useState(false); const [error, setError] = useState(); + const [appVersion, setAppVersion] = useState(); useEffect(() => { invoke('get_services').then((result) => { setServices(result as Services); }); + getAppVersion(); }, []); useEffect(() => { @@ -122,6 +126,11 @@ export const ClientContextProvider = ({ children }: { children: React.ReactNode } }; + const getAppVersion = async () => { + const version = await getVersion(); + setAppVersion(version); + }; + const handleShowHelp = () => setShowHelp((show) => !show); const clearError = () => setError(undefined); @@ -149,6 +158,7 @@ export const ClientContextProvider = ({ children }: { children: React.ReactNode const contextValue = useMemo( () => ({ mode, + appVersion, setMode, error, clearError, @@ -168,6 +178,7 @@ export const ClientContextProvider = ({ children }: { children: React.ReactNode }), [ mode, + appVersion, error, connectedSince, showHelp, diff --git a/nym-connect/src/context/mocks/main.tsx b/nym-connect/src/context/mocks/main.tsx index e2974413eb..496d9c4c2d 100644 --- a/nym-connect/src/context/mocks/main.tsx +++ b/nym-connect/src/context/mocks/main.tsx @@ -4,6 +4,7 @@ import { ClientContext, TClientContext } from '../main'; const mockValues: TClientContext = { mode: 'dark', + appVersion: '1.1.1', connectionStatus: ConnectionStatusKind.disconnected, services: [], showHelp: false, From bb557985c062a771699b6b2487930e9563e6373d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Wed, 14 Dec 2022 14:47:59 +0200 Subject: [PATCH 03/21] DKG resharing unit test (#2668) --- common/crypto/dkg/src/dealing.rs | 5 - common/crypto/dkg/tests/integration.rs | 122 +++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 5 deletions(-) diff --git a/common/crypto/dkg/src/dealing.rs b/common/crypto/dkg/src/dealing.rs index b3633ec82d..d92a9ba6b4 100644 --- a/common/crypto/dkg/src/dealing.rs +++ b/common/crypto/dkg/src/dealing.rs @@ -326,11 +326,6 @@ pub fn try_recover_verification_keys( return Err(DkgError::MismatchedDealings); } - // currently we expect every dealer to also be a receiver. This restriction might be relaxed in the future - if dealings.len() != receivers.len() { - return Err(DkgError::MismatchedDealings); - } - let indices = receivers.keys().collect::>(); // Compute A0, ..., A_{t-1} diff --git a/common/crypto/dkg/tests/integration.rs b/common/crypto/dkg/tests/integration.rs index 2d25c31d40..4ac55df1c7 100644 --- a/common/crypto/dkg/tests/integration.rs +++ b/common/crypto/dkg/tests/integration.rs @@ -254,3 +254,125 @@ fn full_threshold_secret_resharing() { assert_ne!(derived_secrets, reshared_secrets); assert_ne!(recovered_partials, reshared_partials); } + +#[test] +#[ignore] // expensive test +fn full_threshold_secret_resharing_left_party() { + let dummy_seed = [42u8; 32]; + let mut rng = rand_chacha::ChaCha20Rng::from_seed(dummy_seed); + let params = setup(); + + // the simplest possible case + let threshold = 2; + + // the indices are going to get assigned externally, so for test sake, use non-consecutive ones + let mut node_indices = vec![15u64, 248, 33521]; + + let mut receivers = BTreeMap::new(); + let mut full_keys = Vec::new(); + for index in &node_indices { + let (dk, pk) = keygen(¶ms, &mut rng); + receivers.insert(*index, *pk.public_key()); + full_keys.push((dk, pk)) + } + + let first_dealings = node_indices + .iter() + .map(|&dealer_index| { + Dealing::create(&mut rng, ¶ms, dealer_index, threshold, &receivers, None).0 + }) + .collect::>(); + + // recover verification keys + let RecoveredVerificationKeys { + recovered_master: public_original_master, + recovered_partials, + } = try_recover_verification_keys(&first_dealings, threshold, &receivers).unwrap(); + + let mut derived_secrets = Vec::new(); + for (i, (ref mut dk, _)) in full_keys.iter_mut().enumerate() { + let shares = first_dealings + .iter() + .map(|dealing| decrypt_share(dk, i, &dealing.ciphertexts, None).unwrap()) + .collect(); + + let recovered_secret = + combine_shares(shares, &receivers.keys().copied().collect::>()).unwrap(); + + derived_secrets.push(recovered_secret) + } + + let original_master = perform_lagrangian_interpolation_at_origin(&[ + (Scalar::from(node_indices[0]), derived_secrets[0]), + (Scalar::from(node_indices[1]), derived_secrets[1]), + ]) + .unwrap(); + + // one party leaves the process + let left_party_index = node_indices.pop().unwrap(); + receivers.remove(&left_party_index); + full_keys.pop(); + // and another one joins, but we're still over the threshold value of initial parties + let join_party_index = 100000; + let (dk, pk) = keygen(¶ms, &mut rng); + receivers.insert(join_party_index, *pk.public_key()); + full_keys.push((dk, pk)); + + // only initial parties attempt to create resharing dealings! + let resharing_dealings = node_indices + .iter() + .zip(derived_secrets.iter().take(2)) + .map(|(&dealer_index, prior_secret)| { + Dealing::create( + &mut rng, + ¶ms, + dealer_index, + threshold, + &receivers, + Some(*prior_secret), + ) + .0 + }) + .collect::>(); + + for (reshared_dealing, prior_vk) in resharing_dealings + .iter() + .zip(recovered_partials.iter().take(2)) + { + reshared_dealing + .verify(¶ms, threshold, &receivers, Some(*prior_vk)) + .unwrap(); + } + + // recover verification keys + let RecoveredVerificationKeys { + recovered_master: public_reshared_master, + recovered_partials: reshared_partials, + } = try_recover_verification_keys(&resharing_dealings, threshold, &receivers).unwrap(); + + let mut reshared_secrets = Vec::new(); + for (i, (ref mut dk, _)) in full_keys.iter_mut().enumerate() { + let shares = resharing_dealings + .iter() + .map(|dealing| decrypt_share(dk, i, &dealing.ciphertexts, None).unwrap()) + .collect(); + + let recovered_secret = combine_shares(shares, &node_indices).unwrap(); + + reshared_secrets.push(recovered_secret) + } + + let reshared_master = perform_lagrangian_interpolation_at_origin(&[ + (Scalar::from(node_indices[0]), reshared_secrets[0]), + (Scalar::from(join_party_index), reshared_secrets[2]), + ]) + .unwrap(); + + // the master secret and public values didn't change + assert_eq!(original_master, reshared_master); + assert_eq!(public_original_master, public_reshared_master); + + // but partials did + assert_ne!(derived_secrets, reshared_secrets); + assert_ne!(recovered_partials, reshared_partials); +} From 4ece8b7e8f29049b4aecf028a831b85d54f81a1d Mon Sep 17 00:00:00 2001 From: Fouad Date: Wed, 14 Dec 2022 13:04:54 +0000 Subject: [PATCH 04/21] Feature/nym connect experimental software text (#2692) * use experimental text --- nym-connect/src-tauri/tauri.conf.json | 2 +- nym-connect/src/components/AppVersion.tsx | 6 +++++- nym-connect/src/components/AppWindowFrame.tsx | 3 +-- nym-connect/src/components/ConnectionButton.tsx | 6 +++--- nym-connect/src/layouts/DefaultLayout.tsx | 11 ++++++++--- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/nym-connect/src-tauri/tauri.conf.json b/nym-connect/src-tauri/tauri.conf.json index 3d435986ed..65b9393ac9 100644 --- a/nym-connect/src-tauri/tauri.conf.json +++ b/nym-connect/src-tauri/tauri.conf.json @@ -65,7 +65,7 @@ { "title": "NymConnect", "width": 240, - "height": 540, + "height": 575, "resizable": false, "decorations": false, "transparent": true diff --git a/nym-connect/src/components/AppVersion.tsx b/nym-connect/src/components/AppVersion.tsx index 06c63079d6..f351ebc410 100644 --- a/nym-connect/src/components/AppVersion.tsx +++ b/nym-connect/src/components/AppVersion.tsx @@ -6,7 +6,11 @@ export const AppVersion = () => { const { appVersion } = useClientContext(); return ( - + Version {appVersion} ); diff --git a/nym-connect/src/components/AppWindowFrame.tsx b/nym-connect/src/components/AppWindowFrame.tsx index 9420a57f07..abd54ec49e 100644 --- a/nym-connect/src/components/AppWindowFrame.tsx +++ b/nym-connect/src/components/AppWindowFrame.tsx @@ -9,10 +9,9 @@ export const AppWindowFrame: React.FC = ({ children }) => ( display: 'grid', borderRadius: '12px', // screen height is 540px - These should add up to that - gridTemplateRows: '40px 470px 30px', + gridTemplateRows: '40px 1fr 30px', bgcolor: 'nym.background.dark', height: '100vh', - gridtemplateAreas: '"." "." "."', }} > diff --git a/nym-connect/src/components/ConnectionButton.tsx b/nym-connect/src/components/ConnectionButton.tsx index 42903a80ea..6d8a592681 100644 --- a/nym-connect/src/components/ConnectionButton.tsx +++ b/nym-connect/src/components/ConnectionButton.tsx @@ -76,9 +76,9 @@ export const ConnectionButton: React.FC<{ return ( diff --git a/nym-connect/src/layouts/DefaultLayout.tsx b/nym-connect/src/layouts/DefaultLayout.tsx index ed42aad5fe..046f69d9ec 100644 --- a/nym-connect/src/layouts/DefaultLayout.tsx +++ b/nym-connect/src/layouts/DefaultLayout.tsx @@ -31,9 +31,14 @@ export const DefaultLayout: React.FC<{ {error && } - - Connect to the Nym
mixnet for privacy. -
+ + + Connect to the Nym mixnet + + + This is experimental software. Do not rely on it for strong anonymity (yet). + + Date: Wed, 14 Dec 2022 15:05:01 +0000 Subject: [PATCH 05/21] Renaming validator-api to nym-api (#1863) * Renaming validator-api to nym-api * nym-api: simplified crate name * Added nym-api rename to changelog * Changed some output messages * Renamed validator-api-requests to nym-api requests * Removing more references to validator-api-requests * Additional lockfile name changes after full build * Removing mistakenly added merge files * ibid * ibid * Getting rid of ref to validator_api deep inside validator-client * Fixing file storage paths * Renaming struct function names referring to validator_api * Simplifying struct init * Fixed up all other instances of nym_api. * Renaming validatorApi to nymApi in TypeScript client for consistency v * Found a few more Rust instances * Changed examples in TypeScript SDK * Found one more instance of the use of validator instead of nym apis * Aliasing config key name for deserialization to preserve compatibility with old configs --- Cargo.lock | 40 +++--- Cargo.toml | 6 +- .../client-core/src/client/base_client/mod.rs | 14 +- .../src/client/topology_control.rs | 32 ++--- clients/client-core/src/config/mod.rs | 13 +- clients/client-core/src/error.rs | 4 +- clients/client-core/src/init/helpers.rs | 8 +- clients/client-core/src/init/mod.rs | 9 +- clients/native/src/client/config/template.rs | 4 +- clients/native/src/client/mod.rs | 2 +- clients/native/src/commands/mod.rs | 4 +- clients/socks5/src/client/config/template.rs | 4 +- clients/socks5/src/client/mod.rs | 2 +- clients/socks5/src/commands/mod.rs | 4 +- clients/socks5/src/commands/run.rs | 6 +- clients/validator/src/index.ts | 8 +- ...ator-api-querier.ts => nym-api-querier.ts} | 36 ++--- clients/validator/src/query-client.ts | 22 +-- clients/validator/src/signing-client.ts | 20 +-- clients/validator/tests/query/balance.test.ts | 2 +- clients/webassembly/src/client/config.rs | 4 +- clients/webassembly/src/client/mod.rs | 2 +- .../client-libs/validator-client/Cargo.toml | 2 +- .../validator-client/src/client.rs | 76 +++++------ .../client-libs/validator-client/src/error.rs | 6 +- .../client-libs/validator-client/src/lib.rs | 4 +- .../src/{validator_api => nym_api}/error.rs | 6 +- .../src/{validator_api => nym_api}/mod.rs | 126 +++++++++--------- .../src/{validator_api => nym_api}/routes.rs | 4 +- common/commands/src/context/mod.rs | 20 +-- .../delegators/query_for_delegations.rs | 13 +- .../mixnet/query/query_all_gateways.rs | 6 +- .../mixnet/query/query_all_mixnodes.rs | 6 +- common/credentials/Cargo.toml | 2 +- common/credentials/src/coconut/params.rs | 4 +- common/credentials/src/coconut/utils.rs | 14 +- common/mixnode-common/src/verloc/mod.rs | 29 ++-- common/network-defaults/src/lib.rs | 8 +- common/types/src/error.rs | 14 +- contracts/mixnet/src/rewards/transactions.rs | 2 +- explorer-api/src/client.rs | 2 +- explorer-api/src/main.rs | 4 +- explorer-api/src/mix_node/econ_stats.rs | 13 +- explorer/.env.prod | 2 +- explorer/.env.qa | 2 +- explorer/src/api/constants.ts | 10 +- gateway/Cargo.toml | 4 +- gateway/src/commands/init.rs | 8 +- gateway/src/commands/mod.rs | 8 +- gateway/src/commands/run.rs | 6 +- gateway/src/config/mod.rs | 14 +- gateway/src/config/template.rs | 4 +- .../connection_handler/authenticated.rs | 4 +- .../websocket/connection_handler/coconut.rs | 12 +- gateway/src/node/mod.rs | 6 +- mixnode/src/commands/mod.rs | 4 +- mixnode/src/config/mod.rs | 14 +- mixnode/src/config/template.rs | 4 +- mixnode/src/node/mod.rs | 8 +- {validator-api => nym-api}/Cargo.toml | 4 +- {validator-api => nym-api}/README.md | 0 {validator-api => nym-api}/Rocket.toml | 0 {validator-api => nym-api}/build.rs | 2 +- .../20210722120000_create_initial_tables.sql | 0 .../20210819120000_monitor_runs.sql | 0 .../20210824120000_rewarding_data.sql | 0 .../20211018120000_core_nodes_testing.sql | 0 .../20211101110000_no_gateway_rewarding.sql | 0 ...20220121120000_epoch_interval_renaming.sql | 0 ...23120000_drop_foreign_keys_constraints.sql | 0 .../20220325120000_signed_deposits.sql | 0 .../20220410222400_add_timestamp_indexes.sql | 0 .../20220804120000_mixnet_contract_v2.sql | 0 .../nym-api-requests}/Cargo.toml | 2 +- .../nym-api-requests}/src/coconut.rs | 0 .../nym-api-requests}/src/lib.rs | 0 .../nym-api-requests}/src/models.rs | 0 .../src/coconut/client.rs | 0 .../src/coconut/comm.rs | 0 .../src/coconut/deposit.rs | 2 +- .../src/coconut/dkg/client.rs | 0 .../src/coconut/dkg/complaints.rs | 0 .../src/coconut/dkg/controller.rs | 0 .../src/coconut/dkg/dealing.rs | 0 .../src/coconut/dkg/mod.rs | 0 .../src/coconut/dkg/public_key.rs | 0 .../src/coconut/dkg/state.rs | 0 .../src/coconut/dkg/verification_key.rs | 0 .../src/coconut/error.rs | 4 +- .../src/coconut/keypair.rs | 0 {validator-api => nym-api}/src/coconut/mod.rs | 29 ++-- .../src/coconut/tests.rs | 34 ++--- {validator-api => nym-api}/src/config/mod.rs | 10 +- .../src/config/template.rs | 4 +- .../src/contract_cache/mod.rs | 2 +- .../src/contract_cache/routes.rs | 2 +- .../src/epoch_operations/error.rs | 8 +- .../src/epoch_operations/helpers.rs | 0 .../src/epoch_operations/mod.rs | 6 +- {validator-api => nym-api}/src/main.rs | 40 +++--- .../src/network_monitor/chunker.rs | 0 .../src/network_monitor/gateways_reader.rs | 0 .../src/network_monitor/mod.rs | 6 +- .../monitor/gateway_clients_cache.rs | 0 .../monitor/gateways_pinger.rs | 0 .../src/network_monitor/monitor/mod.rs | 6 +- .../src/network_monitor/monitor/preparer.rs | 0 .../src/network_monitor/monitor/processor.rs | 0 .../src/network_monitor/monitor/receiver.rs | 0 .../src/network_monitor/monitor/sender.rs | 0 .../monitor/summary_producer.rs | 0 .../src/network_monitor/test_packet.rs | 0 .../src/network_monitor/test_route/mod.rs | 0 .../src/node_status_api/cache.rs | 10 +- .../cache/inclusion_probabilities.rs | 2 +- .../src/node_status_api/helpers.rs | 18 +-- .../src/node_status_api/local_guard.rs | 0 .../src/node_status_api/mod.rs | 0 .../src/node_status_api/models.rs | 10 +- .../src/node_status_api/reward_estimate.rs | 0 .../src/node_status_api/routes.rs | 26 ++-- .../src/node_status_api/uptime_updater.rs | 13 +- .../src/node_status_api/utils.rs | 0 {validator-api => nym-api}/src/nymd_client.rs | 6 +- .../src/storage/manager.rs | 0 {validator-api => nym-api}/src/storage/mod.rs | 89 ++++++------- .../src/storage/models.rs | 0 {validator-api => nym-api}/src/swagger.rs | 0 {validator-api => nym-api}/tests/README.md | 0 .../status/status-mixnode.test.ts | 0 .../tests/jest.config.js | 0 {validator-api => nym-api}/tests/package.json | 0 .../tests/src/config/config.yaml | 0 .../tests/src/config/configHandler.ts | 0 .../tests/src/endpoints/Status.ts | 0 .../src/endpoints/abstracts/APIClient.ts | 0 .../tests/src/interfaces/StatusInterfaces.ts | 0 .../tests/src/restClient/RestClient.ts | 0 .../tests/tsconfig.eslint.json | 0 .../tests/tsconfig.json | 0 {validator-api => nym-api}/tests/yarn.lock | 0 nym-connect/Cargo.lock | 32 ++--- nym-connect/src-tauri/src/config/mod.rs | 2 +- nym-wallet/Cargo.lock | 30 ++--- nym-wallet/src-tauri/src/config/mod.rs | 4 +- nym-wallet/src-tauri/src/error.rs | 12 +- nym-wallet/src-tauri/src/main.rs | 20 +-- nym-wallet/src-tauri/src/network_config.rs | 6 +- .../src/operations/mixnet/account.rs | 4 +- .../src-tauri/src/operations/mixnet/bond.rs | 2 +- .../src/operations/mixnet/delegate.rs | 2 +- nym-wallet/src-tauri/src/operations/mod.rs | 2 +- .../{validator_api => nym_api}/mod.rs | 0 .../{validator_api => nym_api}/status.rs | 0 nym-wallet/src-tauri/src/state.rs | 14 +- .../examples/plain-html/src/index.ts | 6 +- .../src/App.tsx | 6 +- sdk/typescript/packages/sdk/README.md | 4 +- .../packages/sdk/src/mixnet/wasm/types.ts | 4 +- .../packages/sdk/src/mixnet/wasm/worker.ts | 10 +- tools/nym-cli/src/main.rs | 4 +- .../src/validator/mixnet/delegators/mod.rs | 4 +- .../nym-cli/src/validator/mixnet/query/mod.rs | 6 +- tools/ts-rs-cli/Cargo.toml | 2 +- tools/ts-rs-cli/src/main.rs | 12 +- 165 files changed, 600 insertions(+), 640 deletions(-) rename clients/validator/src/{validator-api-querier.ts => nym-api-querier.ts} (58%) rename common/client-libs/validator-client/src/{validator_api => nym_api}/error.rs (60%) rename common/client-libs/validator-client/src/{validator_api => nym_api}/mod.rs (82%) rename common/client-libs/validator-client/src/{validator_api => nym_api}/routes.rs (92%) rename {validator-api => nym-api}/Cargo.toml (97%) rename {validator-api => nym-api}/README.md (100%) rename {validator-api => nym-api}/Rocket.toml (100%) rename {validator-api => nym-api}/build.rs (92%) rename {validator-api => nym-api}/migrations/20210722120000_create_initial_tables.sql (100%) rename {validator-api => nym-api}/migrations/20210819120000_monitor_runs.sql (100%) rename {validator-api => nym-api}/migrations/20210824120000_rewarding_data.sql (100%) rename {validator-api => nym-api}/migrations/20211018120000_core_nodes_testing.sql (100%) rename {validator-api => nym-api}/migrations/20211101110000_no_gateway_rewarding.sql (100%) rename {validator-api => nym-api}/migrations/20220121120000_epoch_interval_renaming.sql (100%) rename {validator-api => nym-api}/migrations/20220323120000_drop_foreign_keys_constraints.sql (100%) rename {validator-api => nym-api}/migrations/20220325120000_signed_deposits.sql (100%) rename {validator-api => nym-api}/migrations/20220410222400_add_timestamp_indexes.sql (100%) rename {validator-api => nym-api}/migrations/20220804120000_mixnet_contract_v2.sql (100%) rename {validator-api/validator-api-requests => nym-api/nym-api-requests}/Cargo.toml (95%) rename {validator-api/validator-api-requests => nym-api/nym-api-requests}/src/coconut.rs (100%) rename {validator-api/validator-api-requests => nym-api/nym-api-requests}/src/lib.rs (100%) rename {validator-api/validator-api-requests => nym-api/nym-api-requests}/src/models.rs (100%) rename {validator-api => nym-api}/src/coconut/client.rs (100%) rename {validator-api => nym-api}/src/coconut/comm.rs (100%) rename {validator-api => nym-api}/src/coconut/deposit.rs (99%) rename {validator-api => nym-api}/src/coconut/dkg/client.rs (100%) rename {validator-api => nym-api}/src/coconut/dkg/complaints.rs (100%) rename {validator-api => nym-api}/src/coconut/dkg/controller.rs (100%) rename {validator-api => nym-api}/src/coconut/dkg/dealing.rs (100%) rename {validator-api => nym-api}/src/coconut/dkg/mod.rs (100%) rename {validator-api => nym-api}/src/coconut/dkg/public_key.rs (100%) rename {validator-api => nym-api}/src/coconut/dkg/state.rs (100%) rename {validator-api => nym-api}/src/coconut/dkg/verification_key.rs (100%) rename {validator-api => nym-api}/src/coconut/error.rs (96%) rename {validator-api => nym-api}/src/coconut/keypair.rs (100%) rename {validator-api => nym-api}/src/coconut/mod.rs (91%) rename {validator-api => nym-api}/src/coconut/tests.rs (97%) rename {validator-api => nym-api}/src/config/mod.rs (98%) rename {validator-api => nym-api}/src/config/template.rs (97%) rename {validator-api => nym-api}/src/contract_cache/mod.rs (99%) rename {validator-api => nym-api}/src/contract_cache/routes.rs (98%) rename {validator-api => nym-api}/src/epoch_operations/error.rs (85%) rename {validator-api => nym-api}/src/epoch_operations/helpers.rs (100%) rename {validator-api => nym-api}/src/epoch_operations/mod.rs (99%) rename {validator-api => nym-api}/src/main.rs (93%) rename {validator-api => nym-api}/src/network_monitor/chunker.rs (100%) rename {validator-api => nym-api}/src/network_monitor/gateways_reader.rs (100%) rename {validator-api => nym-api}/src/network_monitor/mod.rs (98%) rename {validator-api => nym-api}/src/network_monitor/monitor/gateway_clients_cache.rs (100%) rename {validator-api => nym-api}/src/network_monitor/monitor/gateways_pinger.rs (100%) rename {validator-api => nym-api}/src/network_monitor/monitor/mod.rs (98%) rename {validator-api => nym-api}/src/network_monitor/monitor/preparer.rs (100%) rename {validator-api => nym-api}/src/network_monitor/monitor/processor.rs (100%) rename {validator-api => nym-api}/src/network_monitor/monitor/receiver.rs (100%) rename {validator-api => nym-api}/src/network_monitor/monitor/sender.rs (100%) rename {validator-api => nym-api}/src/network_monitor/monitor/summary_producer.rs (100%) rename {validator-api => nym-api}/src/network_monitor/test_packet.rs (100%) rename {validator-api => nym-api}/src/network_monitor/test_route/mod.rs (100%) rename {validator-api => nym-api}/src/node_status_api/cache.rs (98%) rename {validator-api => nym-api}/src/node_status_api/cache/inclusion_probabilities.rs (98%) rename {validator-api => nym-api}/src/node_status_api/helpers.rs (97%) rename {validator-api => nym-api}/src/node_status_api/local_guard.rs (100%) rename {validator-api => nym-api}/src/node_status_api/mod.rs (100%) rename {validator-api => nym-api}/src/node_status_api/models.rs (99%) rename {validator-api => nym-api}/src/node_status_api/reward_estimate.rs (100%) rename {validator-api => nym-api}/src/node_status_api/routes.rs (94%) rename {validator-api => nym-api}/src/node_status_api/uptime_updater.rs (92%) rename {validator-api => nym-api}/src/node_status_api/utils.rs (100%) rename {validator-api => nym-api}/src/nymd_client.rs (98%) rename {validator-api => nym-api}/src/storage/manager.rs (100%) rename {validator-api => nym-api}/src/storage/mod.rs (89%) rename {validator-api => nym-api}/src/storage/models.rs (100%) rename {validator-api => nym-api}/src/swagger.rs (100%) rename {validator-api => nym-api}/tests/README.md (100%) rename {validator-api => nym-api}/tests/functional_test/validator-api/status/status-mixnode.test.ts (100%) rename {validator-api => nym-api}/tests/jest.config.js (100%) rename {validator-api => nym-api}/tests/package.json (100%) rename {validator-api => nym-api}/tests/src/config/config.yaml (100%) rename {validator-api => nym-api}/tests/src/config/configHandler.ts (100%) rename {validator-api => nym-api}/tests/src/endpoints/Status.ts (100%) rename {validator-api => nym-api}/tests/src/endpoints/abstracts/APIClient.ts (100%) rename {validator-api => nym-api}/tests/src/interfaces/StatusInterfaces.ts (100%) rename {validator-api => nym-api}/tests/src/restClient/RestClient.ts (100%) rename {validator-api => nym-api}/tests/tsconfig.eslint.json (100%) rename {validator-api => nym-api}/tests/tsconfig.json (100%) rename {validator-api => nym-api}/tests/yarn.lock (100%) rename nym-wallet/src-tauri/src/operations/{validator_api => nym_api}/mod.rs (100%) rename nym-wallet/src-tauri/src/operations/{validator_api => nym_api}/status.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 7ce237d55d..a8c9f07c74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -967,9 +967,9 @@ dependencies = [ "coconut-interface", "cosmrs", "crypto", + "nym-api-requests", "rand 0.7.3", "thiserror", - "validator-api-requests", "validator-client", ] @@ -3091,6 +3091,21 @@ dependencies = [ "libc", ] +[[package]] +name = "nym-api-requests" +version = "0.1.0" +dependencies = [ + "bs58", + "coconut-interface", + "cosmrs", + "cosmwasm-std", + "getset", + "mixnet-contract-common", + "schemars", + "serde", + "ts-rs", +] + [[package]] name = "nym-bity-integration" version = "0.1.0" @@ -3225,6 +3240,7 @@ dependencies = [ "mixnet-client", "mixnode-common", "network-defaults", + "nym-api-requests", "nymsphinx", "once_cell", "pemstore", @@ -3240,7 +3256,6 @@ dependencies = [ "tokio-tungstenite 0.14.0", "tokio-util 0.7.3", "url", - "validator-api-requests", "validator-client", "vergen 5.1.17", "version-checker", @@ -3436,6 +3451,7 @@ dependencies = [ "logging", "mixnet-contract-common", "multisig-contract-common", + "nym-api-requests", "nymcoconut", "nymsphinx", "okapi", @@ -3461,7 +3477,6 @@ dependencies = [ "topology", "ts-rs", "url", - "validator-api-requests", "validator-client", "vergen 7.2.1", "version-checker", @@ -6195,10 +6210,10 @@ version = "0.1.0" dependencies = [ "anyhow", "mixnet-contract-common", + "nym-api-requests", "nym-types", "nym-wallet-types", "ts-rs", - "validator-api-requests", "validator-client", "vesting-contract-common", "walkdir", @@ -6404,21 +6419,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -[[package]] -name = "validator-api-requests" -version = "0.1.0" -dependencies = [ - "bs58", - "coconut-interface", - "cosmrs", - "cosmwasm-std", - "getset", - "mixnet-contract-common", - "schemars", - "serde", - "ts-rs", -] - [[package]] name = "validator-client" version = "0.1.0" @@ -6443,6 +6443,7 @@ dependencies = [ "mixnet-contract-common", "multisig-contract-common", "network-defaults", + "nym-api-requests", "prost 0.10.3", "reqwest", "serde", @@ -6452,7 +6453,6 @@ dependencies = [ "tokio", "ts-rs", "url", - "validator-api-requests", "vesting-contract", "vesting-contract-common", ] diff --git a/Cargo.toml b/Cargo.toml index e03bd46aeb..faaa945330 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,8 +74,8 @@ members = [ "mixnode", "service-providers/network-requester", "service-providers/network-statistics", - "validator-api", - "validator-api/validator-api-requests", + "nym-api", + "nym-api/nym-api-requests", "tools/nym-cli", "tools/ts-rs-cli" ] @@ -87,7 +87,7 @@ default-members = [ "service-providers/network-requester", "service-providers/network-statistics", "mixnode", - "validator-api", + "nym-api", "explorer-api", ] diff --git a/clients/client-core/src/client/base_client/mod.rs b/clients/client-core/src/client/base_client/mod.rs index 932fb77b31..6db0280019 100644 --- a/clients/client-core/src/client/base_client/mod.rs +++ b/clients/client-core/src/client/base_client/mod.rs @@ -85,7 +85,7 @@ pub struct BaseClientBuilder<'a, B> { gateway_config: &'a GatewayEndpointConfig, debug_config: &'a DebugConfig, disabled_credentials: bool, - validator_api_endpoints: Vec, + nym_api_endpoints: Vec, reply_storage_backend: B, bandwidth_controller: Option, @@ -106,7 +106,7 @@ where gateway_config: base_config.get_gateway_endpoint_config(), debug_config: base_config.get_debug_config(), disabled_credentials: base_config.get_disabled_credentials_mode(), - validator_api_endpoints: base_config.get_validator_api_endpoints(), + nym_api_endpoints: base_config.get_nym_api_endpoints(), bandwidth_controller, reply_storage_backend, key_manager, @@ -120,13 +120,13 @@ where bandwidth_controller: Option, reply_storage_backend: B, disabled_credentials: bool, - validator_api_endpoints: Vec, + nym_api_endpoints: Vec, ) -> BaseClientBuilder<'a, B> { BaseClientBuilder { gateway_config, debug_config, disabled_credentials, - validator_api_endpoints, + nym_api_endpoints, bandwidth_controller, reply_storage_backend, key_manager, @@ -281,13 +281,13 @@ where // future responsible for periodically polling directory server and updating // the current global view of topology async fn start_topology_refresher( - validator_api_urls: Vec, + nym_api_urls: Vec, refresh_rate: Duration, topology_accessor: TopologyAccessor, shutdown: ShutdownListener, ) -> Result<(), ClientCoreError> { let topology_refresher_config = TopologyRefresherConfig::new( - validator_api_urls, + nym_api_urls, refresh_rate, env!("CARGO_PKG_VERSION").to_string(), ); @@ -386,7 +386,7 @@ where .await?; Self::start_topology_refresher( - self.validator_api_endpoints.clone(), + self.nym_api_endpoints.clone(), self.debug_config.topology_refresh_rate, shared_topology_accessor.clone(), shutdown.subscribe(), diff --git a/clients/client-core/src/client/topology_control.rs b/clients/client-core/src/client/topology_control.rs index ad9e4a4ce6..897d6a0e3b 100644 --- a/clients/client-core/src/client/topology_control.rs +++ b/clients/client-core/src/client/topology_control.rs @@ -136,19 +136,15 @@ impl Default for TopologyAccessor { } pub struct TopologyRefresherConfig { - validator_api_urls: Vec, + nym_api_urls: Vec, refresh_rate: Duration, client_version: String, } impl TopologyRefresherConfig { - pub fn new( - validator_api_urls: Vec, - refresh_rate: Duration, - client_version: String, - ) -> Self { + pub fn new(nym_api_urls: Vec, refresh_rate: Duration, client_version: String) -> Self { TopologyRefresherConfig { - validator_api_urls, + nym_api_urls, refresh_rate, client_version, } @@ -159,7 +155,7 @@ pub struct TopologyRefresher { validator_client: validator_client::client::ApiClient, client_version: String, - validator_api_urls: Vec, + nym_api_urls: Vec, topology_accessor: TopologyAccessor, refresh_rate: Duration, @@ -169,14 +165,12 @@ pub struct TopologyRefresher { impl TopologyRefresher { pub fn new(mut cfg: TopologyRefresherConfig, topology_accessor: TopologyAccessor) -> Self { - cfg.validator_api_urls.shuffle(&mut thread_rng()); + cfg.nym_api_urls.shuffle(&mut thread_rng()); TopologyRefresher { - validator_client: validator_client::client::ApiClient::new( - cfg.validator_api_urls[0].clone(), - ), + validator_client: validator_client::client::ApiClient::new(cfg.nym_api_urls[0].clone()), client_version: cfg.client_version, - validator_api_urls: cfg.validator_api_urls, + nym_api_urls: cfg.nym_api_urls, topology_accessor, refresh_rate: cfg.refresh_rate, currently_used_api: 0, @@ -184,15 +178,15 @@ impl TopologyRefresher { } } - fn use_next_validator_api(&mut self) { - if self.validator_api_urls.len() == 1 { - warn!("There's only a single validator API available - it won't be possible to use a different one"); + fn use_next_nym_api(&mut self) { + if self.nym_api_urls.len() == 1 { + warn!("There's only a single nym API available - it won't be possible to use a different one"); return; } - self.currently_used_api = (self.currently_used_api + 1) % self.validator_api_urls.len(); + self.currently_used_api = (self.currently_used_api + 1) % self.nym_api_urls.len(); self.validator_client - .change_validator_api(self.validator_api_urls[self.currently_used_api].clone()) + .change_nym_api(self.nym_api_urls[self.currently_used_api].clone()) } /// Verifies whether nodes a reasonably distributed among all mix layers. @@ -288,7 +282,7 @@ impl TopologyRefresher { let new_topology = self.get_current_compatible_topology().await; if new_topology.is_none() { - self.use_next_validator_api(); + self.use_next_nym_api(); } if new_topology.is_none() && self.was_latest_valid { diff --git a/clients/client-core/src/config/mod.rs b/clients/client-core/src/config/mod.rs index 0ce94ba646..a6c53db51e 100644 --- a/clients/client-core/src/config/mod.rs +++ b/clients/client-core/src/config/mod.rs @@ -160,8 +160,8 @@ impl Config { self.client.validator_urls = validator_urls; } - pub fn set_custom_validator_apis(&mut self, validator_api_urls: Vec) { - self.client.validator_api_urls = validator_api_urls; + pub fn set_custom_nym_apis(&mut self, nym_api_urls: Vec) { + self.client.nym_api_urls = nym_api_urls; } pub fn set_high_default_traffic_volume(&mut self) { @@ -221,8 +221,8 @@ impl Config { self.client.validator_urls.clone() } - pub fn get_validator_api_endpoints(&self) -> Vec { - self.client.validator_api_urls.clone() + pub fn get_nym_api_endpoints(&self) -> Vec { + self.client.nym_api_urls.clone() } pub fn get_gateway_id(&self) -> String { @@ -409,7 +409,8 @@ pub struct Client { validator_urls: Vec, /// Addresses to APIs running on validator from which the client gets the view of the network. - validator_api_urls: Vec, + #[serde(alias = "validator_api_urls")] + nym_api_urls: Vec, /// Path to file containing private identity key. private_identity_key_file: PathBuf, @@ -456,7 +457,7 @@ impl Default for Client { id: "".to_string(), disabled_credentials_mode: true, validator_urls: vec![], - validator_api_urls: vec![], + nym_api_urls: vec![], private_identity_key_file: Default::default(), public_identity_key_file: Default::default(), private_encryption_key_file: Default::default(), diff --git a/clients/client-core/src/error.rs b/clients/client-core/src/error.rs index 3b179567d1..44973c5f30 100644 --- a/clients/client-core/src/error.rs +++ b/clients/client-core/src/error.rs @@ -30,8 +30,8 @@ pub enum ClientCoreError { #[error("Failed to setup gateway")] FailedToSetupGateway, - #[error("List of validator apis is empty")] - ListOfValidatorApisIsEmpty, + #[error("List of nym apis is empty")] + ListOfNymApisIsEmpty, #[error("Could not load existing gateway configuration: {0}")] CouldNotLoadExistingGatewayConfiguration(std::io::Error), diff --git a/clients/client-core/src/init/helpers.rs b/clients/client-core/src/init/helpers.rs index 7947d614a1..31d76e86da 100644 --- a/clients/client-core/src/init/helpers.rs +++ b/clients/client-core/src/init/helpers.rs @@ -24,12 +24,12 @@ pub(super) async fn query_gateway_details( where B: ReplyStorageBackend, { - let validator_api = validator_servers + let nym_api = validator_servers .choose(&mut thread_rng()) - .ok_or(ClientCoreError::ListOfValidatorApisIsEmpty)?; - let validator_client = validator_client::client::ApiClient::new(validator_api.clone()); + .ok_or(ClientCoreError::ListOfNymApisIsEmpty)?; + let validator_client = validator_client::client::ApiClient::new(nym_api.clone()); - log::trace!("Fetching list of gateways from: {}", validator_api); + log::trace!("Fetching list of gateways from: {}", nym_api); let gateways = validator_client.get_cached_gateways().await?; let valid_gateways = gateways .into_iter() diff --git a/clients/client-core/src/init/mod.rs b/clients/client-core/src/init/mod.rs index f01bc74dcd..fa6c62c097 100644 --- a/clients/client-core/src/init/mod.rs +++ b/clients/client-core/src/init/mod.rs @@ -96,7 +96,7 @@ where { println!("Configuring gateway"); let gateway = - query_gateway_details(config.get_validator_api_endpoints(), user_chosen_gateway_id).await?; + query_gateway_details(config.get_nym_api_endpoints(), user_chosen_gateway_id).await?; log::debug!("Querying gateway gives: {}", gateway); // Registering with gateway by setting up and writing shared keys to disk @@ -120,11 +120,8 @@ where T: NymConfig, { println!("Using gateway provided by user, keeping existing keys"); - let gateway = query_gateway_details( - config.get_validator_api_endpoints(), - Some(user_chosen_gateway_id), - ) - .await?; + let gateway = + query_gateway_details(config.get_nym_api_endpoints(), Some(user_chosen_gateway_id)).await?; log::debug!("Querying gateway gives: {}", gateway); Ok(gateway.into()) } diff --git a/clients/native/src/client/config/template.rs b/clients/native/src/client/config/template.rs index 31ca091282..54d4032799 100644 --- a/clients/native/src/client/config/template.rs +++ b/clients/native/src/client/config/template.rs @@ -31,8 +31,8 @@ validator_urls = [ ] # Addresses to APIs running on validator from which the client gets the view of the network. -validator_api_urls = [ - {{#each client.validator_api_urls }} +nym_api_urls = [ + {{#each client.nym_api_urls }} '{{this}}', {{/each}} ] diff --git a/clients/native/src/client/mod.rs b/clients/native/src/client/mod.rs index cabe049c45..0d61b502ab 100644 --- a/clients/native/src/client/mod.rs +++ b/clients/native/src/client/mod.rs @@ -56,7 +56,7 @@ impl SocketClient { .expect("No nymd validator endpoint provided"); let api_url = config .get_base() - .get_validator_api_endpoints() + .get_nym_api_endpoints() .pop() .expect("No validator api endpoint provided"); // overwrite env configuration with config URLs diff --git a/clients/native/src/commands/mod.rs b/clients/native/src/commands/mod.rs index 9dc6a2ac33..4ad9d414dc 100644 --- a/clients/native/src/commands/mod.rs +++ b/clients/native/src/commands/mod.rs @@ -114,13 +114,13 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi if let Some(raw_validators) = args.api_validators { config .get_base_mut() - .set_custom_validator_apis(config::parse_validators(&raw_validators)); + .set_custom_nym_apis(config::parse_validators(&raw_validators)); } else if std::env::var(network_defaults::var_names::CONFIGURED).is_ok() { let raw_validators = std::env::var(network_defaults::var_names::API_VALIDATOR) .expect("api validator not set"); config .get_base_mut() - .set_custom_validator_apis(config::parse_validators(&raw_validators)); + .set_custom_nym_apis(config::parse_validators(&raw_validators)); } if args.disable_socket { diff --git a/clients/socks5/src/client/config/template.rs b/clients/socks5/src/client/config/template.rs index 527da38274..90029fb5fd 100644 --- a/clients/socks5/src/client/config/template.rs +++ b/clients/socks5/src/client/config/template.rs @@ -31,8 +31,8 @@ validator_urls = [ ] # Addresses to APIs running on validator from which the client gets the view of the network. -validator_api_urls = [ - {{#each client.validator_api_urls }} +nym_api_urls = [ + {{#each client.nym_api_urls }} '{{this}}', {{/each}} ] diff --git a/clients/socks5/src/client/mod.rs b/clients/socks5/src/client/mod.rs index 2b4bff7852..45c9ffad7f 100644 --- a/clients/socks5/src/client/mod.rs +++ b/clients/socks5/src/client/mod.rs @@ -67,7 +67,7 @@ impl NymClient { .expect("No nymd validator endpoint provided"); let api_url = config .get_base() - .get_validator_api_endpoints() + .get_nym_api_endpoints() .pop() .expect("No validator api endpoint provided"); // overwrite env configuration with config URLs diff --git a/clients/socks5/src/commands/mod.rs b/clients/socks5/src/commands/mod.rs index 5f5bfda1de..4d4345f1ce 100644 --- a/clients/socks5/src/commands/mod.rs +++ b/clients/socks5/src/commands/mod.rs @@ -116,11 +116,11 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi if let Some(raw_validators) = args.api_validators { config .get_base_mut() - .set_custom_validator_apis(parse_validators(&raw_validators)); + .set_custom_nym_apis(parse_validators(&raw_validators)); } else if let Ok(raw_validators) = std::env::var(network_defaults::var_names::API_VALIDATOR) { config .get_base_mut() - .set_custom_validator_apis(parse_validators(&raw_validators)); + .set_custom_nym_apis(parse_validators(&raw_validators)); } if args.use_anonymous_sender_tag { diff --git a/clients/socks5/src/commands/run.rs b/clients/socks5/src/commands/run.rs index 10d2d60ea6..ddcd068a76 100644 --- a/clients/socks5/src/commands/run.rs +++ b/clients/socks5/src/commands/run.rs @@ -43,9 +43,9 @@ pub(crate) struct Run { #[clap(long)] nymd_validators: Option, - /// Comma separated list of rest endpoints of the API validators + /// Comma separated list of rest endpoints of the Nym APIs #[clap(long)] - api_validators: Option, + nym_apis: Option, /// Port for the socket to listen on #[clap(short, long)] @@ -71,7 +71,7 @@ impl From for OverrideConfig { fn from(run_config: Run) -> Self { OverrideConfig { nymd_validators: run_config.nymd_validators, - api_validators: run_config.api_validators, + api_validators: run_config.nym_apis, port: run_config.port, use_anonymous_sender_tag: run_config.use_anonymous_sender_tag, fastmode: run_config.fastmode, diff --git a/clients/validator/src/index.ts b/clients/validator/src/index.ts index 642fc2b077..cfbc862a9e 100644 --- a/clients/validator/src/index.ts +++ b/clients/validator/src/index.ts @@ -86,7 +86,7 @@ export default class ValidatorClient implements INymClient { static async connect( mnemonic: string, nymdUrl: string, - validatorApiUrl: string, + nymApiUrl: string, prefix: string, mixnetContract: string, vestingContract: string, @@ -94,19 +94,19 @@ export default class ValidatorClient implements INymClient { ): Promise { const wallet = await ValidatorClient.buildWallet(mnemonic, prefix); - const signingClient = await SigningClient.connectWithNymSigner(wallet, nymdUrl, validatorApiUrl, prefix, denom); + const signingClient = await SigningClient.connectWithNymSigner(wallet, nymdUrl, nymApiUrl, prefix, denom); return new ValidatorClient(signingClient, prefix, mixnetContract, vestingContract, denom); } static async connectForQuery( nymdUrl: string, - validatorApiUrl: string, + nymApiUrl: string, prefix: string, mixnetContract: string, vestingContract: string, denom: string, ): Promise { - const queryClient = await QueryClient.connectWithNym(nymdUrl, validatorApiUrl); + const queryClient = await QueryClient.connectWithNym(nymdUrl, nymApiUrl); return new ValidatorClient(queryClient, prefix, mixnetContract, vestingContract, denom); } diff --git a/clients/validator/src/validator-api-querier.ts b/clients/validator/src/nym-api-querier.ts similarity index 58% rename from clients/validator/src/validator-api-querier.ts rename to clients/validator/src/nym-api-querier.ts index 7c61f91bd7..3fa0471804 100644 --- a/clients/validator/src/validator-api-querier.ts +++ b/clients/validator/src/nym-api-querier.ts @@ -6,13 +6,13 @@ import axios from 'axios'; import { GatewayBond, MixNodeBond } from './types'; -export const VALIDATOR_API_VERSION = '/v1'; -export const VALIDATOR_API_GATEWAYS_PATH = `${VALIDATOR_API_VERSION}/gateways`; -export const VALIDATOR_API_MIXNODES_PATH = `${VALIDATOR_API_VERSION}/mixnodes`; -export const VALIDATOR_API_ACTIVE_MIXNODES_PATH = `${VALIDATOR_API_VERSION}/mixnodes/active`; -export const VALIDATOR_API_REWARDED_MIXNODES_PATH = `${VALIDATOR_API_VERSION}/mixnodes/rewarded`; +export const NYM_API_VERSION = '/v1'; +export const NYM_API_GATEWAYS_PATH = `${NYM_API_VERSION}/gateways`; +export const NYM_API_MIXNODES_PATH = `${NYM_API_VERSION}/mixnodes`; +export const NYM_API_ACTIVE_MIXNODES_PATH = `${NYM_API_VERSION}/mixnodes/active`; +export const NYM_API_REWARDED_MIXNODES_PATH = `${NYM_API_VERSION}/mixnodes/rewarded`; -export interface IValidatorApiQuery { +export interface INymApiQuery { getCachedMixnodes(): Promise; getCachedGateways(): Promise; @@ -22,16 +22,16 @@ export interface IValidatorApiQuery { getRewardedMixnodes(): Promise; } -export default class ValidatorApiQuerier implements IValidatorApiQuery { - validatorApiUrl: string; +export default class NymApiQuerier implements INymApiQuery { + nymApiUrl: string; - constructor(validatorApiUrl: string) { - this.validatorApiUrl = validatorApiUrl; + constructor(nymApiUrl: string) { + this.nymApiUrl = nymApiUrl; } async getCachedMixnodes(): Promise { - const url = new URL(this.validatorApiUrl); - url.pathname += VALIDATOR_API_MIXNODES_PATH; + const url = new URL(this.nymApiUrl); + url.pathname += NYM_API_MIXNODES_PATH; const response = await axios.get(url.toString()); if (response.status === 200) { @@ -41,8 +41,8 @@ export default class ValidatorApiQuerier implements IValidatorApiQuery { } async getCachedGateways(): Promise { - const url = new URL(this.validatorApiUrl); - url.pathname += VALIDATOR_API_GATEWAYS_PATH; + const url = new URL(this.nymApiUrl); + url.pathname += NYM_API_GATEWAYS_PATH; const response = await axios.get(url.toString()); if (response.status === 200) { @@ -52,8 +52,8 @@ export default class ValidatorApiQuerier implements IValidatorApiQuery { } async getActiveMixnodes(): Promise { - const url = new URL(this.validatorApiUrl); - url.pathname += VALIDATOR_API_ACTIVE_MIXNODES_PATH; + const url = new URL(this.nymApiUrl); + url.pathname += NYM_API_ACTIVE_MIXNODES_PATH; const response = await axios.get(url.toString()); if (response.status === 200) { @@ -63,8 +63,8 @@ export default class ValidatorApiQuerier implements IValidatorApiQuery { } async getRewardedMixnodes(): Promise { - const url = new URL(this.validatorApiUrl); - url.pathname += VALIDATOR_API_REWARDED_MIXNODES_PATH; + const url = new URL(this.nymApiUrl); + url.pathname += NYM_API_REWARDED_MIXNODES_PATH; const response = await axios.get(url.toString()); if (response.status === 200) { diff --git a/clients/validator/src/query-client.ts b/clients/validator/src/query-client.ts index 9e3937a89e..de477f7fd9 100644 --- a/clients/validator/src/query-client.ts +++ b/clients/validator/src/query-client.ts @@ -29,7 +29,7 @@ import { PagedMixnodeResponse, RewardingStatus, } from './types'; -import ValidatorApiQuerier, { IValidatorApiQuery } from './validator-api-querier'; +import NymApiQuerier, { INymApiQuery as INymApiQuery } from './nym-api-querier'; export interface ICosmWasmQuery { // methods exposed by `CosmWasmClient` @@ -93,22 +93,22 @@ export interface INymdQuery { ): Promise; } -export interface IQueryClient extends ICosmWasmQuery, INymdQuery, IValidatorApiQuery {} +export interface IQueryClient extends ICosmWasmQuery, INymdQuery, INymApiQuery { } export default class QueryClient extends CosmWasmClient implements IQueryClient { private nymdQuerier: NymdQuerier; - private validatorApiQuerier: ValidatorApiQuerier; + private nymApiQuerier: NymApiQuerier; - private constructor(tmClient: Tendermint34Client, validatorApiUrl: string) { + private constructor(tmClient: Tendermint34Client, nymApiUrl: string) { super(tmClient); this.nymdQuerier = new NymdQuerier(this); - this.validatorApiQuerier = new ValidatorApiQuerier(validatorApiUrl); + this.nymApiQuerier = new NymApiQuerier(nymApiUrl); } - public static async connectWithNym(nymdUrl: string, validatorApiUrl: string): Promise { + public static async connectWithNym(nymdUrl: string, nymApiUrl: string): Promise { const tmClient = await Tendermint34Client.connect(nymdUrl); - return new QueryClient(tmClient, validatorApiUrl); + return new QueryClient(tmClient, nymApiUrl); } getContractVersion(mixnetContractAddress: string): Promise { @@ -194,18 +194,18 @@ export default class QueryClient extends CosmWasmClient implements IQueryClient } getCachedGateways(): Promise { - return this.validatorApiQuerier.getCachedGateways(); + return this.nymApiQuerier.getCachedGateways(); } getCachedMixnodes(): Promise { - return this.validatorApiQuerier.getCachedMixnodes(); + return this.nymApiQuerier.getCachedMixnodes(); } getActiveMixnodes(): Promise { - return this.validatorApiQuerier.getActiveMixnodes(); + return this.nymApiQuerier.getActiveMixnodes(); } getRewardedMixnodes(): Promise { - return this.validatorApiQuerier.getRewardedMixnodes(); + return this.nymApiQuerier.getRewardedMixnodes(); } } diff --git a/clients/validator/src/signing-client.ts b/clients/validator/src/signing-client.ts index ef8913243d..382077f0a9 100644 --- a/clients/validator/src/signing-client.ts +++ b/clients/validator/src/signing-client.ts @@ -33,7 +33,7 @@ import { PagedMixnodeResponse, RewardingStatus, } from './types'; -import ValidatorApiQuerier from './validator-api-querier'; +import NymApiQuerier from './nym-api-querier'; // methods exposed by `SigningCosmWasmClient` export interface ICosmWasmSigning { @@ -199,13 +199,13 @@ export interface ISigningClient extends IQueryClient, ICosmWasmSigning, INymSign export default class SigningClient extends SigningCosmWasmClient implements ISigningClient { private nymdQuerier: NymdQuerier; - private validatorApiQuerier: ValidatorApiQuerier; + private nymApiQuerier: NymApiQuerier; clientAddress: string; private constructor( clientAddress: string, - validatorApiUrl: string, + nymApiUrl: string, tmClient: Tendermint34Client, wallet: DirectSecp256k1HdWallet, signerOptions: SigningCosmWasmClientOptions, @@ -213,13 +213,13 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig super(tmClient, wallet, signerOptions); this.clientAddress = clientAddress; this.nymdQuerier = new NymdQuerier(this); - this.validatorApiQuerier = new ValidatorApiQuerier(validatorApiUrl); + this.nymApiQuerier = new NymApiQuerier(nymApiUrl); } public static async connectWithNymSigner( wallet: DirectSecp256k1HdWallet, nymdUrl: string, - validatorApiUrl: string, + nymApiUrl: string, prefix: string, denom: string, ): Promise { @@ -229,7 +229,7 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig gasPrice: nymGasPrice(denom), }; const tmClient = await Tendermint34Client.connect(nymdUrl); - return new SigningClient(address, validatorApiUrl, tmClient, wallet, signerOptions); + return new SigningClient(address, nymApiUrl, tmClient, wallet, signerOptions); } // query related: @@ -317,19 +317,19 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig } getCachedGateways(): Promise { - return this.validatorApiQuerier.getCachedGateways(); + return this.nymApiQuerier.getCachedGateways(); } getCachedMixnodes(): Promise { - return this.validatorApiQuerier.getCachedMixnodes(); + return this.nymApiQuerier.getCachedMixnodes(); } getActiveMixnodes(): Promise { - return this.validatorApiQuerier.getActiveMixnodes(); + return this.nymApiQuerier.getActiveMixnodes(); } getRewardedMixnodes(): Promise { - return this.validatorApiQuerier.getRewardedMixnodes(); + return this.nymApiQuerier.getRewardedMixnodes(); } // signing related: diff --git a/clients/validator/tests/query/balance.test.ts b/clients/validator/tests/query/balance.test.ts index 254e54a745..97be47c2ce 100644 --- a/clients/validator/tests/query/balance.test.ts +++ b/clients/validator/tests/query/balance.test.ts @@ -1,4 +1,4 @@ -import ValidatorClient from '../../dist'; +import ValidatorClient from '../../validator/index'; import expect from 'expect'; describe('Query: balances', () => { diff --git a/clients/webassembly/src/client/config.rs b/clients/webassembly/src/client/config.rs index 4740a02b2a..4efefeba21 100644 --- a/clients/webassembly/src/client/config.rs +++ b/clients/webassembly/src/client/config.rs @@ -17,7 +17,7 @@ pub struct Config { /// ID specifies the human readable ID of this particular client. pub(crate) id: String, - pub(crate) validator_api_url: Url, + pub(crate) nym_api_url: Url, pub(crate) disabled_credentials_mode: bool, @@ -38,7 +38,7 @@ impl Config { ) -> Self { Config { id, - validator_api_url: validator_server + nym_api_url: validator_server .parse() .expect("provided url was malformed"), disabled_credentials_mode: true, diff --git a/clients/webassembly/src/client/mod.rs b/clients/webassembly/src/client/mod.rs index 9c3aefe8c6..9c9f20b2c6 100644 --- a/clients/webassembly/src/client/mod.rs +++ b/clients/webassembly/src/client/mod.rs @@ -99,7 +99,7 @@ impl NymClientBuilder { self.bandwidth_controller, self.reply_surb_storage_backend, self.disabled_credentials, - vec![self.config.validator_api_url.clone()], + vec![self.config.nym_api_url.clone()], ); let self_address = base_builder.as_mix_recipient().to_string(); diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index ec842828e7..18096c3db0 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -29,7 +29,7 @@ futures = "0.3" coconut-interface = { path = "../../coconut-interface" } network-defaults = { path = "../../network-defaults" } -validator-api-requests = { path = "../../../validator-api/validator-api-requests", features = ["coconut"] } +nym-api-requests = { path = "../../../nym-api/nym-api-requests", features = ["coconut"] } # required for nymd-client # at some point it might be possible to make it wasm-compatible diff --git a/common/client-libs/validator-client/src/client.rs b/common/client-libs/validator-client/src/client.rs index b5746ea06c..396efb4c3c 100644 --- a/common/client-libs/validator-client/src/client.rs +++ b/common/client-libs/validator-client/src/client.rs @@ -1,16 +1,16 @@ // Copyright 2021-2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::{validator_api, ValidatorClientError}; +use crate::{nym_api, ValidatorClientError}; use coconut_dkg_common::types::NodeIndex; use coconut_interface::VerificationKey; use mixnet_contract_common::mixnode::MixNodeDetails; use mixnet_contract_common::MixId; use mixnet_contract_common::{GatewayBond, IdentityKeyRef}; -use validator_api_requests::coconut::{ +use nym_api_requests::coconut::{ BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse, }; -use validator_api_requests::models::{ +use nym_api_requests::models::{ GatewayCoreStatusResponse, MixnodeCoreStatusResponse, MixnodeStatusResponse, RewardEstimationResponse, StakeSaturationResponse, }; @@ -37,10 +37,10 @@ use mixnet_contract_common::{ #[cfg(feature = "nymd-client")] use network_defaults::NymNetworkDetails; #[cfg(feature = "nymd-client")] +use nym_api_requests::models::MixNodeBondAnnotated; +#[cfg(feature = "nymd-client")] use std::str::FromStr; use url::Url; -#[cfg(feature = "nymd-client")] -use validator_api_requests::models::MixNodeBondAnnotated; #[cfg(feature = "nymd-client")] #[must_use] @@ -142,7 +142,7 @@ pub struct Client { proposals_page_limit: Option, // ideally they would have been read-only, but unfortunately rust doesn't have such features - pub validator_api: validator_api::Client, + pub nym_api: nym_api::Client, pub nymd: NymdClient, } @@ -152,7 +152,7 @@ impl Client { config: Config, mnemonic: bip39::Mnemonic, ) -> Result, ValidatorClientError> { - let validator_api_client = validator_api::Client::new(config.api_url.clone()); + let nym_api_client = nym_api::Client::new(config.api_url.clone()); let nymd_client = NymdClient::connect_with_mnemonic( config.nymd_config.clone(), config.nymd_url.as_str(), @@ -169,7 +169,7 @@ impl Client { dealers_page_limit: config.dealers_page_limit, verification_key_page_limit: config.verification_key_page_limit, proposals_page_limit: config.proposals_page_limit, - validator_api: validator_api_client, + nym_api: nym_api_client, nymd: nymd_client, }) } @@ -192,7 +192,7 @@ impl Client { #[cfg(feature = "nymd-client")] impl Client { pub fn new_query(config: Config) -> Result, ValidatorClientError> { - let validator_api_client = validator_api::Client::new(config.api_url.clone()); + let nym_api_client = nym_api::Client::new(config.api_url.clone()); let nymd_client = NymdClient::connect(config.nymd_config.clone(), config.nymd_url.as_str())?; @@ -205,7 +205,7 @@ impl Client { dealers_page_limit: config.dealers_page_limit, verification_key_page_limit: config.verification_key_page_limit, proposals_page_limit: config.proposals_page_limit, - validator_api: validator_api_client, + nym_api: nym_api_client, nymd: nymd_client, }) } @@ -731,53 +731,53 @@ impl Client { // validator-api wrappers #[cfg(feature = "nymd-client")] impl Client { - pub fn change_validator_api(&mut self, new_endpoint: Url) { - self.validator_api.change_url(new_endpoint) + pub fn change_nym_api(&mut self, new_endpoint: Url) { + self.nym_api.change_url(new_endpoint) } pub async fn get_cached_mixnodes(&self) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_mixnodes().await?) + Ok(self.nym_api.get_mixnodes().await?) } pub async fn get_cached_mixnodes_detailed( &self, ) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_mixnodes_detailed().await?) + Ok(self.nym_api.get_mixnodes_detailed().await?) } pub async fn get_cached_rewarded_mixnodes( &self, ) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_rewarded_mixnodes().await?) + Ok(self.nym_api.get_rewarded_mixnodes().await?) } pub async fn get_cached_rewarded_mixnodes_detailed( &self, ) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_rewarded_mixnodes_detailed().await?) + Ok(self.nym_api.get_rewarded_mixnodes_detailed().await?) } pub async fn get_cached_active_mixnodes( &self, ) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_active_mixnodes().await?) + Ok(self.nym_api.get_active_mixnodes().await?) } pub async fn get_cached_active_mixnodes_detailed( &self, ) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_active_mixnodes_detailed().await?) + Ok(self.nym_api.get_active_mixnodes_detailed().await?) } pub async fn get_cached_gateways(&self) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_gateways().await?) + Ok(self.nym_api.get_gateways().await?) } pub async fn blind_sign( &self, request_body: &BlindSignRequestBody, ) -> Result { - Ok(self.validator_api.blind_sign(request_body).await?) + Ok(self.nym_api.blind_sign(request_body).await?) } } @@ -827,42 +827,40 @@ impl CoconutApiClient { #[derive(Clone)] pub struct ApiClient { - pub validator_api: validator_api::Client, + pub nym_api_client: nym_api::Client, // TODO: perhaps if we really need it at some (currently I don't see any reasons for it) // we could re-implement the communication with the REST API on port 1317 } impl ApiClient { pub fn new(api_url: Url) -> Self { - let validator_api_client = validator_api::Client::new(api_url); + let nym_api_client = nym_api::Client::new(api_url); - ApiClient { - validator_api: validator_api_client, - } + ApiClient { nym_api_client } } - pub fn change_validator_api(&mut self, new_endpoint: Url) { - self.validator_api.change_url(new_endpoint); + pub fn change_nym_api(&mut self, new_endpoint: Url) { + self.nym_api_client.change_url(new_endpoint); } pub async fn get_cached_active_mixnodes( &self, ) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_active_mixnodes().await?) + Ok(self.nym_api_client.get_active_mixnodes().await?) } pub async fn get_cached_rewarded_mixnodes( &self, ) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_rewarded_mixnodes().await?) + Ok(self.nym_api_client.get_rewarded_mixnodes().await?) } pub async fn get_cached_mixnodes(&self) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_mixnodes().await?) + Ok(self.nym_api_client.get_mixnodes().await?) } pub async fn get_cached_gateways(&self) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_gateways().await?) + Ok(self.nym_api_client.get_gateways().await?) } pub async fn get_gateway_core_status_count( @@ -871,7 +869,7 @@ impl ApiClient { since: Option, ) -> Result { Ok(self - .validator_api + .nym_api_client .get_gateway_core_status_count(identity, since) .await?) } @@ -882,7 +880,7 @@ impl ApiClient { since: Option, ) -> Result { Ok(self - .validator_api + .nym_api_client .get_mixnode_core_status_count(mix_id, since) .await?) } @@ -891,7 +889,7 @@ impl ApiClient { &self, mix_id: MixId, ) -> Result { - Ok(self.validator_api.get_mixnode_status(mix_id).await?) + Ok(self.nym_api_client.get_mixnode_status(mix_id).await?) } pub async fn get_mixnode_reward_estimation( @@ -899,7 +897,7 @@ impl ApiClient { mix_id: MixId, ) -> Result { Ok(self - .validator_api + .nym_api_client .get_mixnode_reward_estimation(mix_id) .await?) } @@ -909,7 +907,7 @@ impl ApiClient { mix_id: MixId, ) -> Result { Ok(self - .validator_api + .nym_api_client .get_mixnode_stake_saturation(mix_id) .await?) } @@ -918,7 +916,7 @@ impl ApiClient { &self, request_body: &BlindSignRequestBody, ) -> Result { - Ok(self.validator_api.blind_sign(request_body).await?) + Ok(self.nym_api_client.blind_sign(request_body).await?) } pub async fn partial_bandwidth_credential( @@ -926,7 +924,7 @@ impl ApiClient { request_body: &str, ) -> Result { Ok(self - .validator_api + .nym_api_client .partial_bandwidth_credential(request_body) .await?) } @@ -936,7 +934,7 @@ impl ApiClient { request_body: &VerifyCredentialBody, ) -> Result { Ok(self - .validator_api + .nym_api_client .verify_bandwidth_credential(request_body) .await?) } diff --git a/common/client-libs/validator-client/src/error.rs b/common/client-libs/validator-client/src/error.rs index e832b12618..70ac98b30d 100644 --- a/common/client-libs/validator-client/src/error.rs +++ b/common/client-libs/validator-client/src/error.rs @@ -1,15 +1,15 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::validator_api; +use crate::nym_api; use thiserror::Error; #[derive(Error, Debug)] pub enum ValidatorClientError { #[error("There was an issue with the validator api request - {source}")] - ValidatorAPIError { + NymAPIError { #[from] - source: validator_api::error::ValidatorAPIError, + source: nym_api::error::NymAPIError, }, #[error("One of the provided URLs was malformed - {0}")] diff --git a/common/client-libs/validator-client/src/lib.rs b/common/client-libs/validator-client/src/lib.rs index 2a5e010338..5cf81f09d7 100644 --- a/common/client-libs/validator-client/src/lib.rs +++ b/common/client-libs/validator-client/src/lib.rs @@ -5,14 +5,14 @@ pub mod client; #[cfg(feature = "nymd-client")] pub mod connection_tester; mod error; +pub mod nym_api; #[cfg(feature = "nymd-client")] pub mod nymd; -pub mod validator_api; #[cfg(feature = "nymd-client")] pub use crate::client::{ApiClient, CoconutApiClient}; pub use crate::error::ValidatorClientError; -pub use validator_api_requests::*; +pub use nym_api_requests::*; #[cfg(feature = "nymd-client")] pub use client::{Client, Config}; diff --git a/common/client-libs/validator-client/src/validator_api/error.rs b/common/client-libs/validator-client/src/nym_api/error.rs similarity index 60% rename from common/client-libs/validator-client/src/validator_api/error.rs rename to common/client-libs/validator-client/src/nym_api/error.rs index 9d7cd1d50d..1c3f7b11a4 100644 --- a/common/client-libs/validator-client/src/validator_api/error.rs +++ b/common/client-libs/validator-client/src/nym_api/error.rs @@ -1,8 +1,8 @@ +use nym_api_requests::models::RequestError; use thiserror::Error; -use validator_api_requests::models::RequestError; #[derive(Error, Debug)] -pub enum ValidatorAPIError { +pub enum NymAPIError { #[error("There was an issue with the REST request - {source}")] ReqwestClientError { #[from] @@ -12,6 +12,6 @@ pub enum ValidatorAPIError { #[error("Request failed with error message - {0}")] GenericRequestFailure(String), - #[error("The validator API has failed to resolve our request. It returned status code {status} and additional error message: {}", error.message())] + #[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 }, } diff --git a/common/client-libs/validator-client/src/validator_api/mod.rs b/common/client-libs/validator-client/src/nym_api/mod.rs similarity index 82% rename from common/client-libs/validator-client/src/validator_api/mod.rs rename to common/client-libs/validator-client/src/nym_api/mod.rs index 3cb7ae2ce9..00fd839d4e 100644 --- a/common/client-libs/validator-client/src/validator_api/mod.rs +++ b/common/client-libs/validator-client/src/nym_api/mod.rs @@ -1,22 +1,22 @@ // Copyright 2021-2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::validator_api::error::ValidatorAPIError; -use crate::validator_api::routes::{CORE_STATUS_COUNT, SINCE_ARG}; +use crate::nym_api::error::NymAPIError; +use crate::nym_api::routes::{CORE_STATUS_COUNT, SINCE_ARG}; use mixnet_contract_common::mixnode::MixNodeDetails; use mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId}; -use reqwest::Response; -use serde::{Deserialize, Serialize}; -use url::Url; -use validator_api_requests::coconut::{ +use nym_api_requests::coconut::{ BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse, }; -use validator_api_requests::models::{ +use nym_api_requests::models::{ GatewayCoreStatusResponse, GatewayStatusReportResponse, GatewayUptimeHistoryResponse, InclusionProbabilityResponse, MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse, MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RequestError, RewardEstimationResponse, StakeSaturationResponse, UptimeResponse, }; +use reqwest::Response; +use serde::{Deserialize, Serialize}; +use url::Url; pub mod error; pub mod routes; @@ -53,7 +53,7 @@ impl Client { &self, path: PathSegments<'_>, params: Params<'_, K, V>, - ) -> Result + ) -> Result where K: AsRef, V: AsRef, @@ -62,11 +62,11 @@ impl Client { Ok(self.reqwest_client.get(url).send().await?) } - async fn query_validator_api( + async fn query_nym_api( &self, path: PathSegments<'_>, params: Params<'_, K, V>, - ) -> Result + ) -> Result where for<'a> T: Deserialize<'a>, K: AsRef, @@ -76,16 +76,16 @@ impl Client { if res.status().is_success() { Ok(res.json().await?) } else { - Err(ValidatorAPIError::GenericRequestFailure(res.text().await?)) + Err(NymAPIError::GenericRequestFailure(res.text().await?)) } } // This works for endpoints returning Result, ErrorResponse> - async fn query_validator_api_fallible( + async fn query_nym_api_fallible( &self, path: PathSegments<'_>, params: Params<'_, K, V>, - ) -> Result + ) -> Result where for<'a> T: Deserialize<'a>, K: AsRef, @@ -97,19 +97,19 @@ impl Client { Ok(res.json().await?) } else { let request_error: RequestError = res.json().await?; - Err(ValidatorAPIError::ApiRequestFailure { + Err(NymAPIError::ApiRequestFailure { status: status.as_u16(), error: request_error, }) } } - async fn post_validator_api( + async fn post_nym_api( &self, path: PathSegments<'_>, params: Params<'_, K, V>, json_body: &B, - ) -> Result + ) -> Result where B: Serialize + ?Sized, for<'a> T: Deserialize<'a>, @@ -121,21 +121,17 @@ impl Client { if response.status().is_success() { Ok(response.json().await?) } else { - Err(ValidatorAPIError::GenericRequestFailure( - response.text().await?, - )) + Err(NymAPIError::GenericRequestFailure(response.text().await?)) } } - pub async fn get_mixnodes(&self) -> Result, ValidatorAPIError> { - self.query_validator_api(&[routes::API_VERSION, routes::MIXNODES], NO_PARAMS) + pub async fn get_mixnodes(&self) -> Result, NymAPIError> { + self.query_nym_api(&[routes::API_VERSION, routes::MIXNODES], NO_PARAMS) .await } - pub async fn get_mixnodes_detailed( - &self, - ) -> Result, ValidatorAPIError> { - self.query_validator_api( + pub async fn get_mixnodes_detailed(&self) -> Result, NymAPIError> { + self.query_nym_api( &[ routes::API_VERSION, routes::STATUS, @@ -147,13 +143,13 @@ impl Client { .await } - pub async fn get_gateways(&self) -> Result, ValidatorAPIError> { - self.query_validator_api(&[routes::API_VERSION, routes::GATEWAYS], NO_PARAMS) + pub async fn get_gateways(&self) -> Result, NymAPIError> { + self.query_nym_api(&[routes::API_VERSION, routes::GATEWAYS], NO_PARAMS) .await } - pub async fn get_active_mixnodes(&self) -> Result, ValidatorAPIError> { - self.query_validator_api( + pub async fn get_active_mixnodes(&self) -> Result, NymAPIError> { + self.query_nym_api( &[routes::API_VERSION, routes::MIXNODES, routes::ACTIVE], NO_PARAMS, ) @@ -162,8 +158,8 @@ impl Client { pub async fn get_active_mixnodes_detailed( &self, - ) -> Result, ValidatorAPIError> { - self.query_validator_api( + ) -> Result, NymAPIError> { + self.query_nym_api( &[ routes::API_VERSION, routes::STATUS, @@ -176,8 +172,8 @@ impl Client { .await } - pub async fn get_rewarded_mixnodes(&self) -> Result, ValidatorAPIError> { - self.query_validator_api( + pub async fn get_rewarded_mixnodes(&self) -> Result, NymAPIError> { + self.query_nym_api( &[routes::API_VERSION, routes::MIXNODES, routes::REWARDED], NO_PARAMS, ) @@ -187,8 +183,8 @@ impl Client { pub async fn get_mixnode_report( &self, mix_id: MixId, - ) -> Result { - self.query_validator_api( + ) -> Result { + self.query_nym_api( &[ routes::API_VERSION, routes::STATUS, @@ -204,8 +200,8 @@ impl Client { pub async fn get_gateway_report( &self, identity: IdentityKeyRef<'_>, - ) -> Result { - self.query_validator_api( + ) -> Result { + self.query_nym_api( &[ routes::API_VERSION, routes::STATUS, @@ -221,8 +217,8 @@ impl Client { pub async fn get_mixnode_history( &self, mix_id: MixId, - ) -> Result { - self.query_validator_api( + ) -> Result { + self.query_nym_api( &[ routes::API_VERSION, routes::STATUS, @@ -238,8 +234,8 @@ impl Client { pub async fn get_gateway_history( &self, identity: IdentityKeyRef<'_>, - ) -> Result { - self.query_validator_api( + ) -> Result { + self.query_nym_api( &[ routes::API_VERSION, routes::STATUS, @@ -254,8 +250,8 @@ impl Client { pub async fn get_rewarded_mixnodes_detailed( &self, - ) -> Result, ValidatorAPIError> { - self.query_validator_api( + ) -> Result, NymAPIError> { + self.query_nym_api( &[ routes::API_VERSION, routes::STATUS, @@ -272,9 +268,9 @@ impl Client { &self, identity: IdentityKeyRef<'_>, since: Option, - ) -> Result { + ) -> Result { if let Some(since) = since { - self.query_validator_api( + self.query_nym_api( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -286,7 +282,7 @@ impl Client { ) .await } else { - self.query_validator_api( + self.query_nym_api( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -303,9 +299,9 @@ impl Client { &self, mix_id: MixId, since: Option, - ) -> Result { + ) -> Result { if let Some(since) = since { - self.query_validator_api( + self.query_nym_api( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -317,7 +313,7 @@ impl Client { ) .await } else { - self.query_validator_api( + self.query_nym_api( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -334,8 +330,8 @@ impl Client { pub async fn get_mixnode_status( &self, mix_id: MixId, - ) -> Result { - self.query_validator_api( + ) -> Result { + self.query_nym_api( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -351,8 +347,8 @@ impl Client { pub async fn get_mixnode_reward_estimation( &self, mix_id: MixId, - ) -> Result { - self.query_validator_api_fallible( + ) -> Result { + self.query_nym_api_fallible( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -368,8 +364,8 @@ impl Client { pub async fn get_mixnode_stake_saturation( &self, mix_id: MixId, - ) -> Result { - self.query_validator_api_fallible( + ) -> Result { + self.query_nym_api_fallible( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -385,8 +381,8 @@ impl Client { pub async fn get_mixnode_inclusion_probability( &self, mix_id: MixId, - ) -> Result { - self.query_validator_api_fallible( + ) -> Result { + self.query_nym_api_fallible( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -402,8 +398,8 @@ impl Client { pub async fn get_mixnode_avg_uptime( &self, mix_id: MixId, - ) -> Result { - self.query_validator_api_fallible( + ) -> Result { + self.query_nym_api_fallible( &[ routes::API_VERSION, routes::STATUS_ROUTES, @@ -419,8 +415,8 @@ impl Client { pub async fn blind_sign( &self, request_body: &BlindSignRequestBody, - ) -> Result { - self.post_validator_api( + ) -> Result { + self.post_nym_api( &[ routes::API_VERSION, routes::COCONUT_ROUTES, @@ -436,8 +432,8 @@ impl Client { pub async fn partial_bandwidth_credential( &self, request_body: &str, - ) -> Result { - self.post_validator_api( + ) -> Result { + self.post_nym_api( &[ routes::API_VERSION, routes::COCONUT_ROUTES, @@ -453,8 +449,8 @@ impl Client { pub async fn verify_bandwidth_credential( &self, request_body: &VerifyCredentialBody, - ) -> Result { - self.post_validator_api( + ) -> Result { + self.post_nym_api( &[ routes::API_VERSION, routes::COCONUT_ROUTES, diff --git a/common/client-libs/validator-client/src/validator_api/routes.rs b/common/client-libs/validator-client/src/nym_api/routes.rs similarity index 92% rename from common/client-libs/validator-client/src/validator_api/routes.rs rename to common/client-libs/validator-client/src/nym_api/routes.rs index 66a822b4fd..5b3d1c266d 100644 --- a/common/client-libs/validator-client/src/validator_api/routes.rs +++ b/common/client-libs/validator-client/src/nym_api/routes.rs @@ -1,9 +1,9 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use network_defaults::VALIDATOR_API_VERSION; +use network_defaults::NYM_API_VERSION; -pub const API_VERSION: &str = VALIDATOR_API_VERSION; +pub const API_VERSION: &str = NYM_API_VERSION; pub const MIXNODES: &str = "mixnodes"; pub const GATEWAYS: &str = "gateways"; diff --git a/common/commands/src/context/mod.rs b/common/commands/src/context/mod.rs index 98709d6d98..3a21634afb 100644 --- a/common/commands/src/context/mod.rs +++ b/common/commands/src/context/mod.rs @@ -7,8 +7,8 @@ use network_defaults::{ NymNetworkDetails, }; use tap::prelude::*; +pub use validator_client::nym_api::Client as NymApiClient; use validator_client::nymd::{self, AccountId, NymdClient, QueryNymdClient, SigningNymdClient}; -pub use validator_client::validator_api::Client as ValidatorApiClient; use crate::context::errors::ContextError; @@ -16,14 +16,14 @@ pub mod errors; pub type SigningClient = validator_client::nymd::NymdClient; pub type QueryClient = validator_client::nymd::NymdClient; -pub type SigningClientWithValidatorAPI = validator_client::Client; -pub type QueryClientWithValidatorAPI = validator_client::Client; +pub type SigningClientWithNymd = validator_client::Client; +pub type QueryClientWithNymd = validator_client::Client; #[derive(Debug)] pub struct ClientArgs { pub config_env_file: Option, pub nymd_url: Option, - pub validator_api_url: Option, + pub nym_api_url: Option, pub mnemonic: Option, pub mixnet_contract_address: Option, pub vesting_contract_address: Option, @@ -38,8 +38,8 @@ pub fn get_network_details(args: &ClientArgs) -> Result Result { +) -> Result { let client_config = validator_client::Config::try_from_nym_network_details(network_details) .tap_err(|err| log::error!("Failed to get client config - {err}"))?; @@ -126,9 +126,9 @@ pub fn create_signing_client_with_validator_api( } } -pub fn create_query_client_with_validator_api( +pub fn create_query_client_with_nym_api( network_details: &NymNetworkDetails, -) -> Result { +) -> Result { let client_config = validator_client::Config::try_from_nym_network_details(network_details) .tap_err(|err| log::error!("Failed to get client config - {err}"))?; diff --git a/common/commands/src/validator/mixnet/delegators/query_for_delegations.rs b/common/commands/src/validator/mixnet/delegators/query_for_delegations.rs index d816e65a0c..6867f51e81 100644 --- a/common/commands/src/validator/mixnet/delegators/query_for_delegations.rs +++ b/common/commands/src/validator/mixnet/delegators/query_for_delegations.rs @@ -4,7 +4,7 @@ use clap::Parser; use log::info; -use crate::context::SigningClientWithValidatorAPI; +use crate::context::SigningClientWithNymd; use crate::utils::{pretty_cosmwasm_coin, show_error_passthrough}; use comfy_table::Table; @@ -14,7 +14,7 @@ use mixnet_contract_common::{Delegation, PendingEpochEvent, PendingEpochEventKin #[derive(Debug, Parser)] pub struct Args {} -pub async fn execute(_args: Args, client: SigningClientWithValidatorAPI) { +pub async fn execute(_args: Args, client: SigningClientWithNymd) { info!( "Getting delegations for account {}...", client.nymd.address() @@ -48,14 +48,14 @@ pub async fn execute(_args: Args, client: SigningClientWithValidatorAPI) { } } -async fn to_iso_timestamp(block_height: u32, client: &SigningClientWithValidatorAPI) -> String { +async fn to_iso_timestamp(block_height: u32, client: &SigningClientWithNymd) -> String { match client.nymd.get_block_timestamp(Some(block_height)).await { Ok(res) => res.to_rfc3339(), Err(_e) => "-".to_string(), } } -async fn print_delegations(delegations: Vec, client: &SigningClientWithValidatorAPI) { +async fn print_delegations(delegations: Vec, client: &SigningClientWithNymd) { let mut table = Table::new(); table.set_header(vec!["Timestamp", "Mix Id", "Delegation", "Proxy"]); @@ -75,10 +75,7 @@ async fn print_delegations(delegations: Vec, client: &SigningClientW println!("{table}"); } -async fn print_delegation_events( - events: Vec, - client: &SigningClientWithValidatorAPI, -) { +async fn print_delegation_events(events: Vec, client: &SigningClientWithNymd) { let mut table = Table::new(); table.set_header(vec![ 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 679ac08bcd..7904af2c4d 100644 --- a/common/commands/src/validator/mixnet/query/query_all_gateways.rs +++ b/common/commands/src/validator/mixnet/query/query_all_gateways.rs @@ -4,7 +4,7 @@ use clap::Parser; use comfy_table::Table; -use crate::context::QueryClientWithValidatorAPI; +use crate::context::QueryClientWithNymd; use crate::utils::{pretty_cosmwasm_coin, show_error}; #[derive(Debug, Parser)] @@ -14,8 +14,8 @@ pub struct Args { pub identity_key: Option, } -pub async fn query(args: Args, client: &QueryClientWithValidatorAPI) { - match client.validator_api.get_gateways().await { +pub async fn query(args: Args, client: &QueryClientWithNymd) { + match client.nym_api.get_gateways().await { Ok(res) => match args.identity_key { Some(identity_key) => { let node = res.iter().find(|node| { 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 4ec6b25b7b..cdcd70672f 100644 --- a/common/commands/src/validator/mixnet/query/query_all_mixnodes.rs +++ b/common/commands/src/validator/mixnet/query/query_all_mixnodes.rs @@ -4,7 +4,7 @@ use clap::Parser; use comfy_table::Table; -use crate::context::QueryClientWithValidatorAPI; +use crate::context::QueryClientWithNymd; use crate::utils::{pretty_decimal_with_denom, show_error}; #[derive(Debug, Parser)] @@ -14,8 +14,8 @@ pub struct Args { pub identity_key: Option, } -pub async fn query(args: Args, client: &QueryClientWithValidatorAPI) { - match client.validator_api.get_mixnodes().await { +pub async fn query(args: Args, client: &QueryClientWithNymd) { + match client.nym_api.get_mixnodes().await { Ok(res) => match args.identity_key { Some(identity_key) => { let node = res.iter().find(|node| { diff --git a/common/credentials/Cargo.toml b/common/credentials/Cargo.toml index 58d43af03f..2f754253cc 100644 --- a/common/credentials/Cargo.toml +++ b/common/credentials/Cargo.toml @@ -13,7 +13,7 @@ thiserror = "1.0" # I guess temporarily until we get serde support in coconut up and running coconut-interface = { path = "../coconut-interface" } crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric", "hashing"] } -validator-api-requests = { path = "../../validator-api/validator-api-requests" } +nym-api-requests = { path = "../../nym-api/nym-api-requests" } validator-client = { path = "../client-libs/validator-client" } [dev-dependencies] diff --git a/common/credentials/src/coconut/params.rs b/common/credentials/src/coconut/params.rs index 42b9205ebb..7e2260bc10 100644 --- a/common/credentials/src/coconut/params.rs +++ b/common/credentials/src/coconut/params.rs @@ -9,7 +9,7 @@ type Aes128Ctr = ctr::Ctr64LE; /// Hashing algorithm used during hkdf for ephemeral shared key generation per blinded signature /// response encryption. -pub type ValidatorApiCredentialHkdfAlgorithm = blake3::Hasher; +pub type NymApiCredentialHkdfAlgorithm = blake3::Hasher; /// Encryption algorithm used for end-to-end encryption of blinded signature response -pub type ValidatorApiCredentialEncryptionAlgorithm = Aes128Ctr; +pub type NymApiCredentialEncryptionAlgorithm = Aes128Ctr; diff --git a/common/credentials/src/coconut/utils.rs b/common/credentials/src/coconut/utils.rs index f701938d59..0305bb845b 100644 --- a/common/credentials/src/coconut/utils.rs +++ b/common/credentials/src/coconut/utils.rs @@ -8,13 +8,11 @@ use coconut_interface::{ use crypto::asymmetric::encryption::PublicKey; use crypto::shared_key::recompute_shared_key; use crypto::symmetric::stream_cipher; -use validator_api_requests::coconut::BlindSignRequestBody; +use nym_api_requests::coconut::BlindSignRequestBody; use validator_client::client::CoconutApiClient; use crate::coconut::bandwidth::{BandwidthVoucher, PRIVATE_ATTRIBUTES, PUBLIC_ATTRIBUTES}; -use crate::coconut::params::{ - ValidatorApiCredentialEncryptionAlgorithm, ValidatorApiCredentialHkdfAlgorithm, -}; +use crate::coconut::params::{NymApiCredentialEncryptionAlgorithm, NymApiCredentialHkdfAlgorithm}; use crate::error::Error; pub async fn obtain_aggregate_verification_key( @@ -66,11 +64,11 @@ async fn obtain_partial_credential( let remote_key = PublicKey::from_bytes(&response.remote_key)?; let encryption_key = recompute_shared_key::< - ValidatorApiCredentialEncryptionAlgorithm, - ValidatorApiCredentialHkdfAlgorithm, + NymApiCredentialEncryptionAlgorithm, + NymApiCredentialHkdfAlgorithm, >(&remote_key, attributes.encryption_key()); - let zero_iv = stream_cipher::zero_iv::(); - let blinded_signature_bytes = stream_cipher::decrypt::( + let zero_iv = stream_cipher::zero_iv::(); + let blinded_signature_bytes = stream_cipher::decrypt::( &encryption_key, &zero_iv, &encrypted_signature, diff --git a/common/mixnode-common/src/verloc/mod.rs b/common/mixnode-common/src/verloc/mod.rs index 48e9a7b483..fc7e19332a 100644 --- a/common/mixnode-common/src/verloc/mod.rs +++ b/common/mixnode-common/src/verloc/mod.rs @@ -69,8 +69,8 @@ pub struct Config { /// due to being unable to get the list of nodes. retry_timeout: Duration, - /// URLs to the validator apis for obtaining network topology. - validator_api_urls: Vec, + /// URLs to the nym apis for obtaining network topology. + nym_api_urls: Vec, } impl Config { @@ -132,15 +132,15 @@ impl ConfigBuilder { self } - pub fn validator_api_urls(mut self, validator_api_urls: Vec) -> Self { - self.0.validator_api_urls = validator_api_urls; + pub fn nym_api_urls(mut self, nym_api_urls: Vec) -> Self { + self.0.nym_api_urls = nym_api_urls; self } pub fn build(self) -> Config { // panics here are fine as those are only ever constructed at the initial setup assert!( - !self.0.validator_api_urls.is_empty(), + !self.0.nym_api_urls.is_empty(), "at least one validator endpoint must be provided", ); self.0 @@ -159,7 +159,7 @@ impl Default for ConfigBuilder { tested_nodes_batch_size: DEFAULT_BATCH_SIZE, testing_interval: DEFAULT_TESTING_INTERVAL, retry_timeout: DEFAULT_RETRY_TIMEOUT, - validator_api_urls: vec![], + nym_api_urls: vec![], }) } } @@ -186,7 +186,7 @@ impl VerlocMeasurer { identity: Arc, shutdown_listener: ShutdownListener, ) -> Self { - config.validator_api_urls.shuffle(&mut thread_rng()); + config.nym_api_urls.shuffle(&mut thread_rng()); VerlocMeasurer { packet_sender: Arc::new(PacketSender::new( @@ -204,24 +204,21 @@ impl VerlocMeasurer { )), shutdown_listener, currently_used_api: 0, - validator_client: validator_client::ApiClient::new( - config.validator_api_urls[0].clone(), - ), + validator_client: validator_client::ApiClient::new(config.nym_api_urls[0].clone()), config, results: AtomicVerlocResult::new(), } } - fn use_next_validator_api(&mut self) { - if self.config.validator_api_urls.len() == 1 { + fn use_next_nym_api(&mut self) { + if self.config.nym_api_urls.len() == 1 { warn!("There's only a single validator API available - it won't be possible to use a different one"); return; } - self.currently_used_api = - (self.currently_used_api + 1) % self.config.validator_api_urls.len(); + self.currently_used_api = (self.currently_used_api + 1) % self.config.nym_api_urls.len(); self.validator_client - .change_validator_api(self.config.validator_api_urls[self.currently_used_api].clone()) + .change_nym_api(self.config.nym_api_urls[self.currently_used_api].clone()) } pub fn get_verloc_results_pointer(&self) -> AtomicVerlocResult { @@ -308,7 +305,7 @@ impl VerlocMeasurer { "failed to obtain list of mixnodes from the validator - {}. Going to attempt to use another validator API in the next run", err ); - self.use_next_validator_api(); + self.use_next_nym_api(); sleep(self.config.retry_timeout).await; continue; } diff --git a/common/network-defaults/src/lib.rs b/common/network-defaults/src/lib.rs index d7b01622b1..3a2daeed42 100644 --- a/common/network-defaults/src/lib.rs +++ b/common/network-defaults/src/lib.rs @@ -355,14 +355,14 @@ pub const DEFAULT_WEBSOCKET_LISTENING_PORT: u16 = 1977; // 'SOCKS5' CLIENT pub const DEFAULT_SOCKS5_LISTENING_PORT: u16 = 1080; -// VALIDATOR-API -pub const DEFAULT_VALIDATOR_API_PORT: u16 = 8080; +// NYM-API +pub const DEFAULT_NYM_API_PORT: u16 = 8080; -pub const VALIDATOR_API_VERSION: &str = "v1"; +pub const NYM_API_VERSION: &str = "v1"; // REWARDING -/// We'll be assuming a few more things, profit margin and cost function. Since we don't have relialable 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 +/// 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 // pub const DEFAULT_OPERATOR_INTERVAL_COST: u64 = 40_000_000; // 40$/(30 days) at 1 Nym == 1$ // pub const DEFAULT_OPERATOR_INTERVAL_COST: u64 = 55_556; // 40$/1hr at 1 Nym == 1$ // pub const DEFAULT_OPERATOR_INTERVAL_COST: u64 = 9259; // 40$/1hr/6 at 1 Nym == 1$ diff --git a/common/types/src/error.rs b/common/types/src/error.rs index b0874ba7aa..864a6f6eb2 100644 --- a/common/types/src/error.rs +++ b/common/types/src/error.rs @@ -1,7 +1,7 @@ use serde::{Serialize, Serializer}; use std::io; use thiserror::Error; -use validator_client::validator_api::error::ValidatorAPIError; +use validator_client::nym_api::error::NymAPIError; use validator_client::{nymd::error::NymdError, ValidatorClientError}; // TODO: ask @MS why this even exists @@ -23,9 +23,9 @@ pub enum TypesError { source: eyre::Report, }, #[error("{source}")] - ValidatorApiError { + NymApiError { #[from] - source: ValidatorAPIError, + source: NymAPIError, }, #[error("{source}")] IOError { @@ -52,8 +52,8 @@ pub enum TypesError { #[from] source: cosmwasm_std::DecimalRangeExceeded, }, - #[error("No validator API URL configured")] - NoValidatorApiUrlConfigured, + #[error("No nym API URL configured")] + NoNymApiUrlConfigured, #[error("{0} is not a valid amount string")] InvalidAmount(String), #[error("{0} is not a valid denomination string")] @@ -88,10 +88,10 @@ impl Serialize for TypesError { impl From for TypesError { fn from(e: ValidatorClientError) -> Self { match e { - ValidatorClientError::ValidatorAPIError { source } => source.into(), + ValidatorClientError::NymAPIError { source } => source.into(), ValidatorClientError::MalformedUrlProvided(e) => e.into(), ValidatorClientError::NymdError(e) => e.into(), - ValidatorClientError::NoAPIUrlAvailable => TypesError::NoValidatorApiUrlConfigured, + ValidatorClientError::NoAPIUrlAvailable => TypesError::NoNymApiUrlConfigured, } } } diff --git a/contracts/mixnet/src/rewards/transactions.rs b/contracts/mixnet/src/rewards/transactions.rs index e25e4c1bd8..d1552bb50b 100644 --- a/contracts/mixnet/src/rewards/transactions.rs +++ b/contracts/mixnet/src/rewards/transactions.rs @@ -408,7 +408,7 @@ pub mod tests { let env = test.env(); // note: we don't have to test for cases where `is_unbonding` is set to true on a mixnode - // since before performing the validator-api should clear out the event queue + // since before performing the nym-api should clear out the event queue // manually adjust delegation info as to indicate the rewarding information shouldnt get removed let mut rewarding_details = storage::MIXNODE_REWARDING diff --git a/explorer-api/src/client.rs b/explorer-api/src/client.rs index 129a394d31..717a0800e5 100644 --- a/explorer-api/src/client.rs +++ b/explorer-api/src/client.rs @@ -21,7 +21,7 @@ impl ThreadsafeValidatorClient { } pub(crate) fn api_endpoint(&self) -> &Url { - self.0.validator_api.current_url() + self.0.nym_api.current_url() } } diff --git a/explorer-api/src/main.rs b/explorer-api/src/main.rs index 47dddf9f54..5154c87e78 100644 --- a/explorer-api/src/main.rs +++ b/explorer-api/src/main.rs @@ -54,8 +54,8 @@ impl ExplorerApi { async fn run(&mut self) { info!("Explorer API starting up..."); - let validator_api_url = self.state.inner.validator_client.api_endpoint(); - info!("Using validator API - {}", validator_api_url); + let nym_api_url = self.state.inner.validator_client.api_endpoint(); + info!("Using validator API - {}", nym_api_url); let shutdown = ShutdownNotifier::default(); diff --git a/explorer-api/src/mix_node/econ_stats.rs b/explorer-api/src/mix_node/econ_stats.rs index cde29d3a86..30d89a29b2 100644 --- a/explorer-api/src/mix_node/econ_stats.rs +++ b/explorer-api/src/mix_node/econ_stats.rs @@ -13,31 +13,26 @@ pub(crate) async fn retrieve_mixnode_econ_stats( ) -> Option { let stake_saturation = client .0 - .validator_api + .nym_api .get_mixnode_stake_saturation(mix_id) .await .ok()?; let inclusion_probability = client .0 - .validator_api + .nym_api .get_mixnode_inclusion_probability(mix_id) .await .ok()?; let reward_estimation = client .0 - .validator_api + .nym_api .get_mixnode_reward_estimation(mix_id) .await .ok()?; - let uptime_response = client - .0 - .validator_api - .get_mixnode_avg_uptime(mix_id) - .await - .ok()?; + let uptime_response = client.0.nym_api.get_mixnode_avg_uptime(mix_id).await.ok()?; Some(EconomicDynamicsStats { stake_saturation: best_effort_small_dec_to_f64(stake_saturation.saturation) as f32, diff --git a/explorer/.env.prod b/explorer/.env.prod index b1b1fe0d4c..70bd50c7ca 100644 --- a/explorer/.env.prod +++ b/explorer/.env.prod @@ -1,5 +1,5 @@ EXPLORER_API_URL=https://explorer.nymtech.net/api/v1 -VALIDATOR_API_URL=https://validator.nymtech.net +NYM_API_URL=https://validator.nymtech.net VALIDATOR_URL=https://rpc.nymtech.net BIG_DIPPER_URL=https://blocks.nymtech.net CURRENCY_DENOM=unym diff --git a/explorer/.env.qa b/explorer/.env.qa index 60b30e1bd1..dd7052ce4d 100644 --- a/explorer/.env.qa +++ b/explorer/.env.qa @@ -1,5 +1,5 @@ EXPLORER_API_URL=https://qa-explorer.nymtech.net/api/v1 -VALIDATOR_API_URL=https://qa-validator-api.nymtech.net +NYM_API_URL=https://qa-validator-api.nymtech.net VALIDATOR_URL=https://qa-validator.nymtech.net BIG_DIPPER_URL=https://qa-blocks.nymtech.net CURRENCY_DENOM=unym diff --git a/explorer/src/api/constants.ts b/explorer/src/api/constants.ts index fb7216b64f..dc6124c53d 100644 --- a/explorer/src/api/constants.ts +++ b/explorer/src/api/constants.ts @@ -1,6 +1,6 @@ // master APIs export const API_BASE_URL = process.env.EXPLORER_API_URL; -export const VALIDATOR_API_BASE_URL = process.env.VALIDATOR_API_URL; +export const NYM_API_BASE_URL = process.env.NYM_API_URL; export const VALIDATOR_BASE_URL = process.env.VALIDATOR_URL; export const BIG_DIPPER = process.env.BIG_DIPPER_URL; @@ -9,12 +9,12 @@ export const OVERVIEW_API = `${API_BASE_URL}/overview`; export const MIXNODE_PING = `${API_BASE_URL}/ping`; export const MIXNODES_API = `${API_BASE_URL}/mix-nodes`; export const MIXNODE_API = `${API_BASE_URL}/mix-node`; -export const GATEWAYS_API = `${VALIDATOR_API_BASE_URL}/api/v1/gateways`; +export const GATEWAYS_API = `${NYM_API_BASE_URL}/api/v1/gateways`; export const VALIDATORS_API = `${VALIDATOR_BASE_URL}/validators`; -export const BLOCK_API = `${VALIDATOR_API_BASE_URL}/block`; +export const BLOCK_API = `${NYM_API_BASE_URL}/block`; export const COUNTRY_DATA_API = `${API_BASE_URL}/countries`; -export const UPTIME_STORY_API = `${VALIDATOR_API_BASE_URL}/api/v1/status/mixnode`; // add ID then '/history' to this. -export const UPTIME_STORY_API_GATEWAY = `${VALIDATOR_API_BASE_URL}/api/v1/status/gateway`; // add ID then '/history' or '/report' to this. +export const UPTIME_STORY_API = `${NYM_API_BASE_URL}/api/v1/status/mixnode`; // add ID then '/history' to this. +export const UPTIME_STORY_API_GATEWAY = `${NYM_API_BASE_URL}/api/v1/status/gateway`; // add ID then '/history' or '/report' to this. // errors export const MIXNODE_API_ERROR = "We're having trouble finding that record, please try again or Contact Us."; diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index ab26fccea7..a531722d06 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -64,7 +64,7 @@ network-defaults = { path = "../common/network-defaults" } nymsphinx = { path = "../common/nymsphinx" } pemstore = { path = "../common/pemstore" } statistics-common = { path = "../common/statistics" } -validator-api-requests = { path = "../validator-api/validator-api-requests" } +nym-api-requests = { path = "../nym-api/nym-api-requests" } validator-client = { path = "../common/client-libs/validator-client", features = [ "nymd-client", ] } @@ -75,7 +75,7 @@ coconut = [ "coconut-interface", "gateway-requests/coconut", "credentials/coconut", - "validator-api-requests/coconut", + "nym-api-requests/coconut", ] [build-dependencies] diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index dca393213a..abd668b33f 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -39,9 +39,9 @@ pub struct Init { #[clap(long)] datastore: Option, - /// Comma separated list of endpoints of the validators APIs + /// Comma separated list of endpoints of nym APIs #[clap(long)] - validator_apis: Option, + nym_apis: Option, /// Comma separated list of endpoints of the validator #[clap(long)] @@ -75,7 +75,7 @@ impl From for OverrideConfig { clients_port: init_config.clients_port, datastore: init_config.datastore, announce_host: init_config.announce_host, - validator_apis: init_config.validator_apis, + nym_apis: init_config.nym_apis, validators: init_config.validators, mnemonic: init_config.mnemonic, @@ -165,7 +165,7 @@ mod tests { clients_port: Some(43), announce_host: Some("foo-announce-host".to_string()), datastore: Some("foo-datastore".to_string()), - validator_apis: None, + nym_apis: None, validators: None, mnemonic: None, statistics_service_url: None, diff --git a/gateway/src/commands/mod.rs b/gateway/src/commands/mod.rs index ef2ec235e8..b3fbb6f537 100644 --- a/gateway/src/commands/mod.rs +++ b/gateway/src/commands/mod.rs @@ -55,7 +55,7 @@ pub(crate) struct OverrideConfig { announce_host: Option, enabled_statistics: Option, statistics_service_url: Option, - validator_apis: Option, + nym_apis: Option, validators: Option, mnemonic: Option, @@ -119,11 +119,11 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi } } - if let Some(raw_validators) = args.validator_apis { - config = config.with_custom_validator_apis(parse_validators(&raw_validators)); + if let Some(raw_validators) = args.nym_apis { + config = config.with_custom_nym_apis(parse_validators(&raw_validators)); } else if std::env::var(CONFIGURED).is_ok() { if let Some(raw_validators) = read_var_if_not_default(API_VALIDATOR) { - config = config.with_custom_validator_apis(::config::parse_validators(&raw_validators)) + config = config.with_custom_nym_apis(::config::parse_validators(&raw_validators)) } } diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index 37320877fe..e91f260d1b 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -39,9 +39,9 @@ pub struct Run { #[clap(long)] datastore: Option, - /// Comma separated list of endpoints of the validators APIs + /// Comma separated list of endpoints of the nym APIs #[clap(long)] - validator_apis: Option, + nym_apis: Option, /// Comma separated list of endpoints of the validator #[clap(long)] @@ -75,7 +75,7 @@ impl From for OverrideConfig { clients_port: run_config.clients_port, datastore: run_config.datastore, announce_host: run_config.announce_host, - validator_apis: run_config.validator_apis, + nym_apis: run_config.nym_apis, validators: run_config.validators, mnemonic: run_config.mnemonic, diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index ac4f734dad..9eb15c1c5a 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -144,8 +144,8 @@ impl Config { self } - pub fn with_custom_validator_apis(mut self, validator_api_urls: Vec) -> Self { - self.gateway.validator_api_urls = validator_api_urls; + pub fn with_custom_nym_apis(mut self, nym_api_urls: Vec) -> Self { + self.gateway.nym_api_urls = nym_api_urls; self } @@ -240,8 +240,8 @@ impl Config { self.gateway.statistics_service_url.clone() } - pub fn get_validator_api_endpoints(&self) -> Vec { - self.gateway.validator_api_urls.clone() + pub fn get_nym_api_endpoints(&self) -> Vec { + self.gateway.nym_api_urls.clone() } #[cfg(feature = "coconut")] @@ -359,8 +359,8 @@ pub struct Gateway { /// Domain address of the statistics service statistics_service_url: Url, - /// Addresses to APIs running on validator from which the node gets the view of the network. - validator_api_urls: Vec, + /// Addresses to APIs from which the node gets the view of the network. + nym_api_urls: Vec, /// Addresses to validators which the node uses to check for double spending of ERC20 tokens. validator_nymd_urls: Vec, @@ -418,7 +418,7 @@ impl Default for Gateway { public_sphinx_key_file: Default::default(), enabled_statistics: false, statistics_service_url: Url::from_str(STATISTICS_SERVICE_DOMAIN_ADDRESS).expect("Invalid default statistics service URL"), - validator_api_urls: vec![Url::from_str(API_VALIDATOR).expect("Invalid default API URL")], + nym_api_urls: vec![Url::from_str(API_VALIDATOR).expect("Invalid default API URL")], validator_nymd_urls: vec![Url::from_str(NYMD_VALIDATOR).expect("Invalid default nymd URL")], cosmos_mnemonic: bip39::Mnemonic::from_str("exact antique hybrid width raise anchor puzzle degree fee quit long crack net vague hip despair write put useless civil mechanic broom music day").unwrap(), nym_root_directory: Config::default_root_directory(), diff --git a/gateway/src/config/template.rs b/gateway/src/config/template.rs index faba004a50..0d1759e820 100644 --- a/gateway/src/config/template.rs +++ b/gateway/src/config/template.rs @@ -60,8 +60,8 @@ enabled_statistics = {{ gateway.enabled_statistics }} statistics_service_url = '{{ gateway.statistics_service_url }}' # Addresses to APIs running on validator from which the node gets the view of the network. -validator_api_urls = [ - {{#each gateway.validator_api_urls }} +nym_api_urls = [ + {{#each gateway.nym_api_urls }} '{{this}}', {{/each}} ] diff --git a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs index e7c2658daa..40ca0d7715 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs @@ -56,8 +56,8 @@ pub(crate) enum RequestHandlingError { APIError(#[from] validator_client::ValidatorClientError), #[cfg(feature = "coconut")] - #[error("Not enough validator API endpoints provided. Needed {needed}, received {received}")] - NotEnoughValidatorAPIs { received: usize, needed: usize }, + #[error("Not enough nym API endpoints provided. Needed {needed}, received {received}")] + NotEnoughNymAPIs { received: usize, needed: usize }, #[cfg(feature = "coconut")] #[error("There was a problem with the proposal id: {reason}")] diff --git a/gateway/src/node/client_handling/websocket/connection_handler/coconut.rs b/gateway/src/node/client_handling/websocket/connection_handler/coconut.rs index e83c23e5e9..ba53fe4dbd 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/coconut.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/coconut.rs @@ -21,7 +21,7 @@ const ONE_HOUR_SEC: u64 = 3600; const MAX_FEEGRANT_UNYM: u128 = 10000; pub(crate) struct CoconutVerifier { - api_clients: Vec, + nym_api_clients: Vec, nymd_client: Client, mix_denom_base: String, aggregated_verification_key: VerificationKey, @@ -35,13 +35,13 @@ impl CoconutVerifier { aggregated_verification_key: VerificationKey, ) -> Result { if api_clients.is_empty() { - return Err(RequestHandlingError::NotEnoughValidatorAPIs { + return Err(RequestHandlingError::NotEnoughNymAPIs { received: 0, needed: 1, }); } Ok(CoconutVerifier { - api_clients, + nym_api_clients: api_clients, nymd_client, mix_denom_base, aggregated_verification_key, @@ -87,12 +87,12 @@ impl CoconutVerifier { }); } - let req = validator_api_requests::coconut::VerifyCredentialBody::new( + let req = nym_api_requests::coconut::VerifyCredentialBody::new( credential.clone(), proposal_id, self.nymd_client.nymd.address().clone(), ); - for client in self.api_clients.iter() { + for client in self.nym_api_clients.iter() { self.nymd_client .nymd .grant_allowance( @@ -115,7 +115,7 @@ impl CoconutVerifier { ) .await?; if !ret?.verification_result { - debug!("Validator {} didn't accept the credential. It will probably vote No on the spending proposal", client.api_client.validator_api.current_url()); + debug!("Validator {} didn't accept the credential. It will probably vote No on the spending proposal", client.api_client.nym_api_client.current_url()); } } diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index c04091ffdc..7500302787 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -231,12 +231,12 @@ where } fn random_api_client(&self) -> validator_client::ApiClient { - let endpoints = self.config.get_validator_api_endpoints(); - let validator_api = endpoints + let endpoints = self.config.get_nym_api_endpoints(); + let nym_api = endpoints .choose(&mut thread_rng()) .expect("The list of validator apis is empty"); - validator_client::ApiClient::new(validator_api.clone()) + validator_client::ApiClient::new(nym_api.clone()) } #[cfg(feature = "coconut")] diff --git a/mixnode/src/commands/mod.rs b/mixnode/src/commands/mod.rs index 6ec353e76b..2edad136f9 100644 --- a/mixnode/src/commands/mod.rs +++ b/mixnode/src/commands/mod.rs @@ -96,10 +96,10 @@ fn override_config(mut config: Config, args: OverrideConfig) -> Config { } if let Some(ref raw_validators) = args.validators { - config = config.with_custom_validator_apis(parse_validators(raw_validators)); + config = config.with_custom_nym_apis(parse_validators(raw_validators)); } else if std::env::var(CONFIGURED).is_ok() { if let Some(raw_validators) = read_var_if_not_default(API_VALIDATOR) { - config = config.with_custom_validator_apis(::config::parse_validators(&raw_validators)) + config = config.with_custom_nym_apis(::config::parse_validators(&raw_validators)) } } diff --git a/mixnode/src/config/mod.rs b/mixnode/src/config/mod.rs index 3f5208cee8..bc9278bc85 100644 --- a/mixnode/src/config/mod.rs +++ b/mixnode/src/config/mod.rs @@ -155,8 +155,8 @@ impl Config { self } - pub fn with_custom_validator_apis(mut self, validator_api_urls: Vec) -> Self { - self.mixnode.validator_api_urls = validator_api_urls; + pub fn with_custom_nym_apis(mut self, nym_api_urls: Vec) -> Self { + self.mixnode.nym_api_urls = nym_api_urls; self } @@ -233,8 +233,8 @@ impl Config { self.mixnode.public_sphinx_key_file.clone() } - pub fn get_validator_api_endpoints(&self) -> Vec { - self.mixnode.validator_api_urls.clone() + pub fn get_nym_api_endpoints(&self) -> Vec { + self.mixnode.nym_api_urls.clone() } pub fn get_node_stats_logging_delay(&self) -> Duration { @@ -369,8 +369,8 @@ struct MixNode { /// Path to file containing public sphinx key. public_sphinx_key_file: PathBuf, - /// Addresses to APIs running on validator from which the node gets the view of the network. - validator_api_urls: Vec, + /// Addresses to nym APIs from which the node gets the view of the network. + nym_api_urls: Vec, /// nym_home_directory specifies absolute path to the home nym MixNodes directory. /// It is expected to use default value and hence .toml file should not redefine this field. @@ -412,7 +412,7 @@ impl Default for MixNode { public_identity_key_file: Default::default(), private_sphinx_key_file: Default::default(), public_sphinx_key_file: Default::default(), - validator_api_urls: vec![Url::from_str(API_VALIDATOR).expect("Invalid default API URL")], + nym_api_urls: vec![Url::from_str(API_VALIDATOR).expect("Invalid default API URL")], nym_root_directory: Config::default_root_directory(), wallet_address: "nymXXXXXXXX".to_string(), } diff --git a/mixnode/src/config/template.rs b/mixnode/src/config/template.rs index 2af12a195b..f222275083 100644 --- a/mixnode/src/config/template.rs +++ b/mixnode/src/config/template.rs @@ -54,8 +54,8 @@ verloc_port = {{ mixnode.verloc_port }} http_api_port = {{ mixnode.http_api_port }} # Addresses to APIs running on validator from which the node gets the view of the network. -validator_api_urls = [ - {{#each mixnode.validator_api_urls }} +nym_api_urls = [ + {{#each mixnode.nym_api_urls }} '{{this}}', {{/each}} ] diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index 0bca9b31b0..e986c4fa67 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -245,7 +245,7 @@ impl MixNode { .tested_nodes_batch_size(self.config.get_measurement_tested_nodes_batch_size()) .testing_interval(self.config.get_measurement_testing_interval()) .retry_timeout(self.config.get_measurement_retry_timeout()) - .validator_api_urls(self.config.get_validator_api_endpoints()) + .nym_api_urls(self.config.get_nym_api_endpoints()) .build(); let mut verloc_measurer = @@ -256,12 +256,12 @@ impl MixNode { } fn random_api_client(&self) -> validator_client::ApiClient { - let endpoints = self.config.get_validator_api_endpoints(); - let validator_api = endpoints + let endpoints = self.config.get_nym_api_endpoints(); + let nym_api = endpoints .choose(&mut thread_rng()) .expect("The list of validator apis is empty"); - validator_client::ApiClient::new(validator_api.clone()) + validator_client::ApiClient::new(nym_api.clone()) } // TODO: ask DH whether this function still makes sense in ^0.10 diff --git a/validator-api/Cargo.toml b/nym-api/Cargo.toml similarity index 97% rename from validator-api/Cargo.toml rename to nym-api/Cargo.toml index ee2c169f65..643e9ecd23 100644 --- a/validator-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -84,7 +84,7 @@ nymsphinx = { path = "../common/nymsphinx" } pemstore = { path = "../common/pemstore", optional = true } task = { path = "../common/task" } topology = { path = "../common/topology" } -validator-api-requests = { path = "validator-api-requests" } +nym-api-requests = { path = "nym-api-requests" } validator-client = { path = "../common/client-libs/validator-client", features = [ "nymd-client", ] } @@ -97,7 +97,7 @@ coconut = [ "cw3", "gateway-client/coconut", "credentials/coconut", - "validator-api-requests/coconut", + "nym-api-requests/coconut", "nymcoconut", "coconut-dkg-common", "dkg", diff --git a/validator-api/README.md b/nym-api/README.md similarity index 100% rename from validator-api/README.md rename to nym-api/README.md diff --git a/validator-api/Rocket.toml b/nym-api/Rocket.toml similarity index 100% rename from validator-api/Rocket.toml rename to nym-api/Rocket.toml diff --git a/validator-api/build.rs b/nym-api/build.rs similarity index 92% rename from validator-api/build.rs rename to nym-api/build.rs index 1e967f0aab..6c92dffc59 100644 --- a/validator-api/build.rs +++ b/nym-api/build.rs @@ -5,7 +5,7 @@ use vergen::{vergen, Config}; #[tokio::main] async fn main() { let out_dir = env::var("OUT_DIR").unwrap(); - let database_path = format!("{}/validator-api-example.sqlite", out_dir); + let database_path = format!("{}/nym-api-example.sqlite", out_dir); let mut conn = SqliteConnection::connect(&format!("sqlite://{}?mode=rwc", database_path)) .await diff --git a/validator-api/migrations/20210722120000_create_initial_tables.sql b/nym-api/migrations/20210722120000_create_initial_tables.sql similarity index 100% rename from validator-api/migrations/20210722120000_create_initial_tables.sql rename to nym-api/migrations/20210722120000_create_initial_tables.sql diff --git a/validator-api/migrations/20210819120000_monitor_runs.sql b/nym-api/migrations/20210819120000_monitor_runs.sql similarity index 100% rename from validator-api/migrations/20210819120000_monitor_runs.sql rename to nym-api/migrations/20210819120000_monitor_runs.sql diff --git a/validator-api/migrations/20210824120000_rewarding_data.sql b/nym-api/migrations/20210824120000_rewarding_data.sql similarity index 100% rename from validator-api/migrations/20210824120000_rewarding_data.sql rename to nym-api/migrations/20210824120000_rewarding_data.sql diff --git a/validator-api/migrations/20211018120000_core_nodes_testing.sql b/nym-api/migrations/20211018120000_core_nodes_testing.sql similarity index 100% rename from validator-api/migrations/20211018120000_core_nodes_testing.sql rename to nym-api/migrations/20211018120000_core_nodes_testing.sql diff --git a/validator-api/migrations/20211101110000_no_gateway_rewarding.sql b/nym-api/migrations/20211101110000_no_gateway_rewarding.sql similarity index 100% rename from validator-api/migrations/20211101110000_no_gateway_rewarding.sql rename to nym-api/migrations/20211101110000_no_gateway_rewarding.sql diff --git a/validator-api/migrations/20220121120000_epoch_interval_renaming.sql b/nym-api/migrations/20220121120000_epoch_interval_renaming.sql similarity index 100% rename from validator-api/migrations/20220121120000_epoch_interval_renaming.sql rename to nym-api/migrations/20220121120000_epoch_interval_renaming.sql diff --git a/validator-api/migrations/20220323120000_drop_foreign_keys_constraints.sql b/nym-api/migrations/20220323120000_drop_foreign_keys_constraints.sql similarity index 100% rename from validator-api/migrations/20220323120000_drop_foreign_keys_constraints.sql rename to nym-api/migrations/20220323120000_drop_foreign_keys_constraints.sql diff --git a/validator-api/migrations/20220325120000_signed_deposits.sql b/nym-api/migrations/20220325120000_signed_deposits.sql similarity index 100% rename from validator-api/migrations/20220325120000_signed_deposits.sql rename to nym-api/migrations/20220325120000_signed_deposits.sql diff --git a/validator-api/migrations/20220410222400_add_timestamp_indexes.sql b/nym-api/migrations/20220410222400_add_timestamp_indexes.sql similarity index 100% rename from validator-api/migrations/20220410222400_add_timestamp_indexes.sql rename to nym-api/migrations/20220410222400_add_timestamp_indexes.sql diff --git a/validator-api/migrations/20220804120000_mixnet_contract_v2.sql b/nym-api/migrations/20220804120000_mixnet_contract_v2.sql similarity index 100% rename from validator-api/migrations/20220804120000_mixnet_contract_v2.sql rename to nym-api/migrations/20220804120000_mixnet_contract_v2.sql diff --git a/validator-api/validator-api-requests/Cargo.toml b/nym-api/nym-api-requests/Cargo.toml similarity index 95% rename from validator-api/validator-api-requests/Cargo.toml rename to nym-api/nym-api-requests/Cargo.toml index ecd29e78a4..6787dcacfa 100644 --- a/validator-api/validator-api-requests/Cargo.toml +++ b/nym-api/nym-api-requests/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "validator-api-requests" +name = "nym-api-requests" version = "0.1.0" edition = "2021" diff --git a/validator-api/validator-api-requests/src/coconut.rs b/nym-api/nym-api-requests/src/coconut.rs similarity index 100% rename from validator-api/validator-api-requests/src/coconut.rs rename to nym-api/nym-api-requests/src/coconut.rs diff --git a/validator-api/validator-api-requests/src/lib.rs b/nym-api/nym-api-requests/src/lib.rs similarity index 100% rename from validator-api/validator-api-requests/src/lib.rs rename to nym-api/nym-api-requests/src/lib.rs diff --git a/validator-api/validator-api-requests/src/models.rs b/nym-api/nym-api-requests/src/models.rs similarity index 100% rename from validator-api/validator-api-requests/src/models.rs rename to nym-api/nym-api-requests/src/models.rs diff --git a/validator-api/src/coconut/client.rs b/nym-api/src/coconut/client.rs similarity index 100% rename from validator-api/src/coconut/client.rs rename to nym-api/src/coconut/client.rs diff --git a/validator-api/src/coconut/comm.rs b/nym-api/src/coconut/comm.rs similarity index 100% rename from validator-api/src/coconut/comm.rs rename to nym-api/src/coconut/comm.rs diff --git a/validator-api/src/coconut/deposit.rs b/nym-api/src/coconut/deposit.rs similarity index 99% rename from validator-api/src/coconut/deposit.rs rename to nym-api/src/coconut/deposit.rs index 2112b3d76a..dcee8cebc0 100644 --- a/validator-api/src/coconut/deposit.rs +++ b/nym-api/src/coconut/deposit.rs @@ -8,7 +8,7 @@ use coconut_bandwidth_contract_common::events::{ use credentials::coconut::bandwidth::BandwidthVoucher; use crypto::asymmetric::encryption; use crypto::asymmetric::identity::{self, Signature}; -use validator_api_requests::coconut::BlindSignRequestBody; +use nym_api_requests::coconut::BlindSignRequestBody; use validator_client::nymd::TxResponse; use super::error::{CoconutError, Result}; diff --git a/validator-api/src/coconut/dkg/client.rs b/nym-api/src/coconut/dkg/client.rs similarity index 100% rename from validator-api/src/coconut/dkg/client.rs rename to nym-api/src/coconut/dkg/client.rs diff --git a/validator-api/src/coconut/dkg/complaints.rs b/nym-api/src/coconut/dkg/complaints.rs similarity index 100% rename from validator-api/src/coconut/dkg/complaints.rs rename to nym-api/src/coconut/dkg/complaints.rs diff --git a/validator-api/src/coconut/dkg/controller.rs b/nym-api/src/coconut/dkg/controller.rs similarity index 100% rename from validator-api/src/coconut/dkg/controller.rs rename to nym-api/src/coconut/dkg/controller.rs diff --git a/validator-api/src/coconut/dkg/dealing.rs b/nym-api/src/coconut/dkg/dealing.rs similarity index 100% rename from validator-api/src/coconut/dkg/dealing.rs rename to nym-api/src/coconut/dkg/dealing.rs diff --git a/validator-api/src/coconut/dkg/mod.rs b/nym-api/src/coconut/dkg/mod.rs similarity index 100% rename from validator-api/src/coconut/dkg/mod.rs rename to nym-api/src/coconut/dkg/mod.rs diff --git a/validator-api/src/coconut/dkg/public_key.rs b/nym-api/src/coconut/dkg/public_key.rs similarity index 100% rename from validator-api/src/coconut/dkg/public_key.rs rename to nym-api/src/coconut/dkg/public_key.rs diff --git a/validator-api/src/coconut/dkg/state.rs b/nym-api/src/coconut/dkg/state.rs similarity index 100% rename from validator-api/src/coconut/dkg/state.rs rename to nym-api/src/coconut/dkg/state.rs diff --git a/validator-api/src/coconut/dkg/verification_key.rs b/nym-api/src/coconut/dkg/verification_key.rs similarity index 100% rename from validator-api/src/coconut/dkg/verification_key.rs rename to nym-api/src/coconut/dkg/verification_key.rs diff --git a/validator-api/src/coconut/error.rs b/nym-api/src/coconut/error.rs similarity index 96% rename from validator-api/src/coconut/error.rs rename to nym-api/src/coconut/error.rs index 00c7d9c7a0..4c3a712eb2 100644 --- a/validator-api/src/coconut/error.rs +++ b/nym-api/src/coconut/error.rs @@ -14,7 +14,7 @@ use crypto::asymmetric::{ use dkg::error::DkgError; use validator_client::nymd::error::NymdError; -use crate::node_status_api::models::ValidatorApiStorageError; +use crate::node_status_api::models::NymApiStorageError; pub type Result = std::result::Result; @@ -77,7 +77,7 @@ pub enum CoconutError { CoconutInterfaceError(#[from] coconut_interface::error::CoconutInterfaceError), #[error("Storage error - {0}")] - StorageError(#[from] ValidatorApiStorageError), + StorageError(#[from] NymApiStorageError), #[error("Credentials error - {0}")] CredentialsError(#[from] credentials::error::Error), diff --git a/validator-api/src/coconut/keypair.rs b/nym-api/src/coconut/keypair.rs similarity index 100% rename from validator-api/src/coconut/keypair.rs rename to nym-api/src/coconut/keypair.rs diff --git a/validator-api/src/coconut/mod.rs b/nym-api/src/coconut/mod.rs similarity index 91% rename from validator-api/src/coconut/mod.rs rename to nym-api/src/coconut/mod.rs index 25bcb4afa0..ba3afa12b6 100644 --- a/validator-api/src/coconut/mod.rs +++ b/nym-api/src/coconut/mod.rs @@ -13,7 +13,7 @@ pub(crate) mod tests; use crate::coconut::client::Client as LocalClient; use crate::coconut::deposit::extract_encryption_key; use crate::coconut::error::{CoconutError, Result}; -use crate::ValidatorApiStorage; +use crate::NymApiStorage; use coconut_bandwidth_contract_common::spend_credential::{ funds_from_cosmos_msgs, SpendCredentialStatus, @@ -22,19 +22,19 @@ use coconut_interface::KeyPair as CoconutKeyPair; use coconut_interface::{ Attribute, BlindSignRequest, BlindedSignature, Parameters, VerificationKey, }; -use config::defaults::VALIDATOR_API_VERSION; +use config::defaults::NYM_API_VERSION; use credentials::coconut::params::{ - ValidatorApiCredentialEncryptionAlgorithm, ValidatorApiCredentialHkdfAlgorithm, + NymApiCredentialEncryptionAlgorithm, NymApiCredentialHkdfAlgorithm, }; use crypto::asymmetric::encryption; use crypto::shared_key::new_ephemeral_shared_key; use crypto::symmetric::stream_cipher; use keypair::KeyPair; -use validator_api_requests::coconut::{ +use nym_api_requests::coconut::{ BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse, }; +use validator_client::nym_api::routes::{BANDWIDTH, COCONUT_ROUTES}; use validator_client::nymd::{Coin, Fee}; -use validator_client::validator_api::routes::{BANDWIDTH, COCONUT_ROUTES}; use getset::{CopyGetters, Getters}; use rand_07::rngs::OsRng; @@ -51,7 +51,7 @@ pub struct State { mix_denom: String, key_pair: KeyPair, comm_channel: Arc, - storage: ValidatorApiStorage, + storage: NymApiStorage, rng: Arc>, } @@ -61,7 +61,7 @@ impl State { mix_denom: String, key_pair: KeyPair, comm_channel: D, - storage: ValidatorApiStorage, + storage: NymApiStorage, ) -> Self where C: LocalClient + Send + Sync + 'static, @@ -100,16 +100,16 @@ impl State { let (keypair, shared_key) = { let mut rng = *self.rng.lock().await; new_ephemeral_shared_key::< - ValidatorApiCredentialEncryptionAlgorithm, - ValidatorApiCredentialHkdfAlgorithm, + NymApiCredentialEncryptionAlgorithm, + NymApiCredentialHkdfAlgorithm, _, >(&mut rng, remote_key) }; let chunk_data = signature.to_bytes(); - let zero_iv = stream_cipher::zero_iv::(); - let encrypted_data = stream_cipher::encrypt::( + let zero_iv = stream_cipher::zero_iv::(); + let encrypted_data = stream_cipher::encrypt::( &shared_key, &zero_iv, &chunk_data, @@ -169,7 +169,7 @@ impl InternalSignRequest { mix_denom: String, key_pair: KeyPair, comm_channel: D, - storage: ValidatorApiStorage, + storage: NymApiStorage, ) -> AdHoc where C: LocalClient + Send + Sync + 'static, @@ -179,10 +179,7 @@ impl InternalSignRequest { AdHoc::on_ignite("Internal Sign Request Stage", |rocket| async { rocket.manage(state).mount( // this format! is so ugly... - format!( - "/{}/{}/{}", - VALIDATOR_API_VERSION, COCONUT_ROUTES, BANDWIDTH - ), + format!("/{}/{}/{}", NYM_API_VERSION, COCONUT_ROUTES, BANDWIDTH), routes![ post_blind_sign, post_partial_bandwidth_credential, diff --git a/validator-api/src/coconut/tests.rs b/nym-api/src/coconut/tests.rs similarity index 97% rename from validator-api/src/coconut/tests.rs rename to nym-api/src/coconut/tests.rs index 2a687eef24..3d9d6c46a7 100644 --- a/validator-api/src/coconut/tests.rs +++ b/nym-api/src/coconut/tests.rs @@ -15,26 +15,26 @@ use config::defaults::VOUCHER_INFO; use cosmwasm_std::{to_binary, Addr, CosmosMsg, Decimal, WasmMsg}; use credentials::coconut::bandwidth::BandwidthVoucher; use credentials::coconut::params::{ - ValidatorApiCredentialEncryptionAlgorithm, ValidatorApiCredentialHkdfAlgorithm, + NymApiCredentialEncryptionAlgorithm, NymApiCredentialHkdfAlgorithm, }; use crypto::shared_key::recompute_shared_key; use crypto::symmetric::stream_cipher; +use nym_api_requests::coconut::{ + BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse, +}; use nymcoconut::tests::helpers::theta_from_keys_and_attributes; use nymcoconut::{ prepare_blind_sign, ttp_keygen, Base58, BlindSignRequest, BlindedSignature, Parameters, }; -use validator_api_requests::coconut::{ - BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse, -}; -use validator_client::nymd::Coin; -use validator_client::nymd::{tx::Hash, AccountId, DeliverTx, Event, Fee, Tag, TxResponse}; -use validator_client::validator_api::routes::{ +use validator_client::nym_api::routes::{ API_VERSION, BANDWIDTH, COCONUT_BLIND_SIGN, COCONUT_PARTIAL_BANDWIDTH_CREDENTIAL, COCONUT_ROUTES, COCONUT_VERIFY_BANDWIDTH_CREDENTIAL, }; +use validator_client::nymd::Coin; +use validator_client::nymd::{tx::Hash, AccountId, DeliverTx, Event, Fee, Tag, TxResponse}; use crate::coconut::State; -use crate::ValidatorApiStorage; +use crate::NymApiStorage; use async_trait::async_trait; use coconut_dkg_common::dealer::{ ContractDealing, DealerDetails, DealerDetailsResponse, DealerType, @@ -456,7 +456,7 @@ async fn signed_before() { let key_pair = ttp_keygen(¶ms, 1, 1).unwrap().remove(0); let mut db_dir = std::env::temp_dir(); db_dir.push(&key_pair.verification_key().to_bs58()[..8]); - let storage = ValidatorApiStorage::init(db_dir).await.unwrap(); + let storage = NymApiStorage::init(db_dir).await.unwrap(); let tx_db = Arc::new(RwLock::new(HashMap::new())); tx_db .write() @@ -532,7 +532,7 @@ async fn state_functions() { let key_pair = ttp_keygen(¶ms, 1, 1).unwrap().remove(0); let mut db_dir = std::env::temp_dir(); db_dir.push(&key_pair.verification_key().to_bs58()[..8]); - let storage = ValidatorApiStorage::init(db_dir).await.unwrap(); + let storage = NymApiStorage::init(db_dir).await.unwrap(); let comm_channel = DummyCommunicationChannel::new(key_pair.verification_key()); let staged_key_pair = crate::coconut::KeyPair::new(); staged_key_pair.set(key_pair).await; @@ -601,11 +601,11 @@ async fn state_functions() { crypto::asymmetric::encryption::PublicKey::from_bytes(&response.remote_key).unwrap(); let encryption_key = recompute_shared_key::< - ValidatorApiCredentialEncryptionAlgorithm, - ValidatorApiCredentialHkdfAlgorithm, + NymApiCredentialEncryptionAlgorithm, + NymApiCredentialHkdfAlgorithm, >(&remote_key, encryption_keypair.private_key()); - let zero_iv = stream_cipher::zero_iv::(); - let blinded_signature_bytes = stream_cipher::decrypt::( + let zero_iv = stream_cipher::zero_iv::(); + let blinded_signature_bytes = stream_cipher::decrypt::( &encryption_key, &zero_iv, &response.encrypted_signature, @@ -665,7 +665,7 @@ async fn blind_sign_correct() { let key_pair = ttp_keygen(¶ms, 1, 1).unwrap().remove(0); let mut db_dir = std::env::temp_dir(); db_dir.push(&key_pair.verification_key().to_bs58()[..8]); - let storage = ValidatorApiStorage::init(db_dir).await.unwrap(); + let storage = NymApiStorage::init(db_dir).await.unwrap(); let tx_db = Arc::new(RwLock::new(HashMap::new())); let mut tx_entry = tx_entry_fixture(&tx_hash.to_string()); @@ -776,7 +776,7 @@ async fn signature_test() { let key_pair = ttp_keygen(¶ms, 1, 1).unwrap().remove(0); let mut db_dir = std::env::temp_dir(); db_dir.push(&key_pair.verification_key().to_bs58()[..8]); - let storage = ValidatorApiStorage::init(db_dir).await.unwrap(); + let storage = NymApiStorage::init(db_dir).await.unwrap(); let nymd_client = DummyClient::new(AccountId::from_str(TEST_REWARDING_VALIDATOR_ADDRESS).unwrap()); let comm_channel = DummyCommunicationChannel::new(key_pair.verification_key()); @@ -865,7 +865,7 @@ async fn verification_of_bandwidth_credential() { theta_from_keys_and_attributes(¶ms, &key_pairs, &indices, &public_attributes).unwrap(); let key_pair = key_pairs.remove(0); db_dir.push(&key_pair.verification_key().to_bs58()[..8]); - let storage1 = ValidatorApiStorage::init(db_dir).await.unwrap(); + let storage1 = NymApiStorage::init(db_dir).await.unwrap(); let comm_channel = DummyCommunicationChannel::new(key_pair.verification_key()); let staged_key_pair = crate::coconut::KeyPair::new(); staged_key_pair.set(key_pair).await; diff --git a/validator-api/src/config/mod.rs b/nym-api/src/config/mod.rs similarity index 98% rename from validator-api/src/config/mod.rs rename to nym-api/src/config/mod.rs index d38acfb546..2e30bf34dd 100644 --- a/validator-api/src/config/mod.rs +++ b/nym-api/src/config/mod.rs @@ -3,7 +3,7 @@ use crate::config::template::config_template; use config::defaults::mainnet::MIXNET_CONTRACT_ADDRESS; -use config::defaults::DEFAULT_VALIDATOR_API_PORT; +use config::defaults::DEFAULT_NYM_API_PORT; use config::NymConfig; use serde::{Deserialize, Serialize}; use std::path::PathBuf; @@ -67,11 +67,11 @@ impl NymConfig for Config { dirs::home_dir() .expect("Failed to evaluate $HOME value") .join(".nym") - .join("validator-api") + .join("nym-api") } fn try_default_root_directory() -> Option { - dirs::home_dir().map(|path| path.join(".nym").join("validator-api")) + dirs::home_dir().map(|path| path.join(".nym").join("nym-api")) } fn root_directory(&self) -> PathBuf { @@ -90,7 +90,7 @@ impl NymConfig for Config { #[derive(Debug, Deserialize, PartialEq, Eq, Serialize)] #[serde(default)] pub struct Base { - /// ID specifies the human readable ID of this particular validator-api. + /// ID specifies the human readable ID of this particular nym-api. id: String, local_validator: Url, @@ -114,7 +114,7 @@ impl Default for Base { .expect("default local validator is malformed!"); let mut default_announce_address = default_validator.clone(); default_announce_address - .set_port(Some(DEFAULT_VALIDATOR_API_PORT)) + .set_port(Some(DEFAULT_NYM_API_PORT)) .expect("default local validator is malformed!"); Base { id: String::default(), diff --git a/validator-api/src/config/template.rs b/nym-api/src/config/template.rs similarity index 97% rename from validator-api/src/config/template.rs rename to nym-api/src/config/template.rs index c2a3670e28..79773f56b7 100644 --- a/validator-api/src/config/template.rs +++ b/nym-api/src/config/template.rs @@ -6,11 +6,11 @@ pub(crate) fn config_template() -> &'static str { # This is a TOML config file. # For more information, see https://github.com/toml-lang/toml -##### main base validator-api config options ##### +##### main base nym-api config options ##### [base] -# ID specifies the human readable ID of this particular validator-api. +# ID specifies the human readable ID of this particular nym-api. id = '{{ base.id }}' # Validator server to which the API will be getting information about the network. diff --git a/validator-api/src/contract_cache/mod.rs b/nym-api/src/contract_cache/mod.rs similarity index 99% rename from validator-api/src/contract_cache/mod.rs rename to nym-api/src/contract_cache/mod.rs index b4619214b8..61a7150a02 100644 --- a/validator-api/src/contract_cache/mod.rs +++ b/nym-api/src/contract_cache/mod.rs @@ -9,6 +9,7 @@ use mixnet_contract_common::{ mixnode::MixNodeDetails, reward_params::RewardingParams, GatewayBond, IdentityKey, Interval, MixId, MixNodeBond, RewardedSetNodeStatus, }; +use nym_api_requests::models::MixnodeStatus; use okapi::openapi3::OpenApi; use rocket::fairing::AdHoc; use rocket::Route; @@ -23,7 +24,6 @@ use std::time::Duration; use task::ShutdownListener; use tokio::sync::{watch, RwLock}; use tokio::time; -use validator_api_requests::models::MixnodeStatus; use validator_client::nymd::CosmWasmClient; pub(crate) mod routes; diff --git a/validator-api/src/contract_cache/routes.rs b/nym-api/src/contract_cache/routes.rs similarity index 98% rename from validator-api/src/contract_cache/routes.rs rename to nym-api/src/contract_cache/routes.rs index 6aba1ba4f9..2d6b71e606 100644 --- a/validator-api/src/contract_cache/routes.rs +++ b/nym-api/src/contract_cache/routes.rs @@ -11,7 +11,7 @@ use crate::{ use mixnet_contract_common::{ mixnode::MixNodeDetails, reward_params::RewardingParams, GatewayBond, Interval, MixId, }; -use validator_api_requests::models::MixNodeBondAnnotated; +use nym_api_requests::models::MixNodeBondAnnotated; use rocket::{serde::json::Json, State}; use rocket_okapi::openapi; diff --git a/validator-api/src/epoch_operations/error.rs b/nym-api/src/epoch_operations/error.rs similarity index 85% rename from validator-api/src/epoch_operations/error.rs rename to nym-api/src/epoch_operations/error.rs index bb94df5f49..4455dfcfcc 100644 --- a/validator-api/src/epoch_operations/error.rs +++ b/nym-api/src/epoch_operations/error.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::node_status_api::models::ValidatorApiStorageError; +use crate::node_status_api::models::NymApiStorageError; use thiserror::Error; use validator_client::nymd::error::NymdError; use validator_client::ValidatorClientError; @@ -15,7 +15,7 @@ pub enum RewardingError { // The inner error should be modified at some point... #[error("We run into storage issues - {0}")] - StorageError(ValidatorApiStorageError), + StorageError(NymApiStorageError), #[error("Failed to query the smart contract - {0}")] ValidatorClientError(ValidatorClientError), @@ -38,8 +38,8 @@ impl From for RewardingError { } } -impl From for RewardingError { - fn from(err: ValidatorApiStorageError) -> Self { +impl From for RewardingError { + fn from(err: NymApiStorageError) -> Self { RewardingError::StorageError(err) } } diff --git a/validator-api/src/epoch_operations/helpers.rs b/nym-api/src/epoch_operations/helpers.rs similarity index 100% rename from validator-api/src/epoch_operations/helpers.rs rename to nym-api/src/epoch_operations/helpers.rs diff --git a/validator-api/src/epoch_operations/mod.rs b/nym-api/src/epoch_operations/mod.rs similarity index 99% rename from validator-api/src/epoch_operations/mod.rs rename to nym-api/src/epoch_operations/mod.rs index ec7bfbfaf4..cf0233e453 100644 --- a/validator-api/src/epoch_operations/mod.rs +++ b/nym-api/src/epoch_operations/mod.rs @@ -15,7 +15,7 @@ use crate::contract_cache::ValidatorCache; use crate::nymd_client::Client; use crate::storage::models::RewardingReport; -use crate::storage::ValidatorApiStorage; +use crate::storage::NymApiStorage; use mixnet_contract_common::families::FamilyHead; use mixnet_contract_common::{ reward_params::Performance, CurrentIntervalResponse, ExecuteMsg, Interval, MixId, @@ -56,7 +56,7 @@ impl From for ExecuteMsg { pub struct RewardedSetUpdater { nymd_client: Client, validator_cache: ValidatorCache, - storage: ValidatorApiStorage, + storage: NymApiStorage, } // Weight of a layer being chose is reciprocal to current count in layer @@ -79,7 +79,7 @@ impl RewardedSetUpdater { pub(crate) async fn new( nymd_client: Client, validator_cache: ValidatorCache, - storage: ValidatorApiStorage, + storage: NymApiStorage, ) -> Result { Ok(RewardedSetUpdater { nymd_client, diff --git a/validator-api/src/main.rs b/nym-api/src/main.rs similarity index 93% rename from validator-api/src/main.rs rename to nym-api/src/main.rs index e3411b1b7f..a47068f5fc 100644 --- a/validator-api/src/main.rs +++ b/nym-api/src/main.rs @@ -9,7 +9,7 @@ use crate::contract_cache::ValidatorCacheRefresher; use crate::network_monitor::NetworkMonitorBuilder; use crate::node_status_api::uptime_updater::HistoricalUptimeUpdater; use crate::nymd_client::Client; -use crate::storage::ValidatorApiStorage; +use crate::storage::NymApiStorage; use ::config::defaults::mainnet::read_var_if_not_default; use ::config::defaults::setup_env; use ::config::defaults::var_names::{CONFIGURED, MIXNET_CONTRACT_ADDRESS, MIX_DENOM}; @@ -113,20 +113,20 @@ fn long_version() -> String { fn parse_args() -> ArgMatches { let build_details = long_version(); - let base_app = App::new("Nym Validator API") + let base_app = App::new("Nym API") .version(crate_version!()) .long_version(&*build_details) .author("Nymtech") .arg( Arg::with_name(CONFIG_ENV_FILE) - .help("Path pointing to an env file that configures the validator API") + .help("Path pointing to an env file that configures the Nym API") .long(CONFIG_ENV_FILE) .short('c') .takes_value(true) ) .arg( Arg::with_name(ID) - .help("Id of the validator-api we want to run") + .help("Id of the nym-api we want to run") .long(ID) .takes_value(true) ) @@ -145,13 +145,13 @@ fn parse_args() -> ArgMatches { ) .arg( Arg::with_name(NYMD_VALIDATOR_ARG) - .help("Endpoint to nymd part of the validator from which the monitor will grab nodes to test") + .help("Endpoint to nymd instance from which the monitor will grab nodes to test") .long(NYMD_VALIDATOR_ARG) .takes_value(true) ) .arg(Arg::with_name(MIXNET_CONTRACT_ARG) .long(MIXNET_CONTRACT_ARG) - .help("Address of the validator contract managing the network") + .help("Address of the mixnet contract managing the network") .takes_value(true), ) .arg(Arg::with_name(MNEMONIC_ARG) @@ -174,19 +174,19 @@ fn parse_args() -> ArgMatches { .arg( Arg::with_name(MIN_MIXNODE_RELIABILITY_ARG) .long(MIN_MIXNODE_RELIABILITY_ARG) - .help("Mixnodes with relialability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.") + .help("Mixnodes with reliability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.") .takes_value(true) ) .arg( Arg::with_name(MIN_GATEWAY_RELIABILITY_ARG) .long(MIN_GATEWAY_RELIABILITY_ARG) - .help("Gateways with relialability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.") + .help("Gateways with reliability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set.") .takes_value(true) ) .arg( Arg::with_name(ENABLED_CREDENTIALS_MODE_ARG_NAME) .long(ENABLED_CREDENTIALS_MODE_ARG_NAME) - .help("Set this validator api to work in a enabled credentials that would attempt to use gateway with the bandwidth credential requirement") + .help("Set this nym api to work in a enabled credentials that would attempt to use gateway with the bandwidth credential requirement") ); #[cfg(feature = "coconut")] @@ -215,7 +215,7 @@ async fn wait_for_interrupt(mut shutdown: ShutdownNotifier) { log::info!("Waiting for tasks to finish... (Press ctrl-c to force)"); shutdown.wait_for_shutdown().await; - log::info!("Stopping nym validator API"); + log::info!("Stopping nym API"); } #[cfg(unix)] @@ -380,7 +380,7 @@ fn setup_network_monitor<'a>( } // get instances of managed states - let node_status_storage = rocket.state::().unwrap().clone(); + let node_status_storage = rocket.state::().unwrap().clone(); let validator_cache = rocket.state::().unwrap().clone(); Some(NetworkMonitorBuilder::new( @@ -433,7 +433,7 @@ async fn setup_rocket( // This is not a very nice approach. A lazy value would be more suitable, but that's still // a nightly feature: https://github.com/rust-lang/rust/issues/74465 let storage = if cfg!(feature = "coconut") || config.get_network_monitor_enabled() { - Some(ValidatorApiStorage::init(config.get_node_status_api_database_path()).await?) + Some(NymApiStorage::init(config.get_node_status_api_database_path()).await?) } else { None }; @@ -453,7 +453,7 @@ async fn setup_rocket( // see if we should start up network monitor let rocket = if config.get_network_monitor_enabled() { - rocket.attach(storage::ValidatorApiStorage::stage(storage.unwrap())) + rocket.attach(storage::NymApiStorage::stage(storage.unwrap())) } else { rocket }; @@ -490,7 +490,7 @@ fn get_servers() -> Vec { }] } -async fn run_validator_api(matches: ArgMatches) -> Result<()> { +async fn run_nym_api(matches: ArgMatches) -> Result<()> { let system_version = env!("CARGO_PKG_VERSION"); // try to load config from the file, if it doesn't exist, use default values @@ -565,7 +565,7 @@ async fn run_validator_api(matches: ArgMatches) -> Result<()> { // we're not starting signing client let validator_cache_listener = if config.get_network_monitor_enabled() { // Main storage - let storage = rocket.state::().unwrap().clone(); + let storage = rocket.state::().unwrap().clone(); // setup our daily uptime updater. Note that if network monitor is disabled, then we have // no data for the updates and hence we don't need to start it up @@ -610,8 +610,8 @@ async fn run_validator_api(matches: ArgMatches) -> Result<()> { // Spawn the node status cache refresher. // It is primarily refreshed in-sync with the validator cache, however provide a fallback // caching interval that is twice the validator cache - let storage = rocket.state::().cloned(); - let mut validator_api_cache_refresher = node_status_api::NodeStatusCacheRefresher::new( + let storage = rocket.state::().cloned(); + let mut nym_api_cache_refresher = node_status_api::NodeStatusCacheRefresher::new( node_status_cache, config.get_caching_interval().saturating_mul(2), validator_cache, @@ -619,12 +619,12 @@ async fn run_validator_api(matches: ArgMatches) -> Result<()> { storage, ); let shutdown_listener = shutdown.subscribe(); - tokio::spawn(async move { validator_api_cache_refresher.run(shutdown_listener).await }); + tokio::spawn(async move { nym_api_cache_refresher.run(shutdown_listener).await }); // launch the rocket! // 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 validator-api exits. + // Currently it's runtime is forcefully terminated once the nym-api exits. let shutdown_handle = rocket.shutdown(); tokio::spawn(rocket.launch()); @@ -663,5 +663,5 @@ async fn main() -> Result<()> { .value_of(CONFIG_ENV_FILE) .map(|s| PathBuf::from_str(s).expect("invalid env config file")); setup_env(config_env_file); - run_validator_api(args).await + run_nym_api(args).await } diff --git a/validator-api/src/network_monitor/chunker.rs b/nym-api/src/network_monitor/chunker.rs similarity index 100% rename from validator-api/src/network_monitor/chunker.rs rename to nym-api/src/network_monitor/chunker.rs diff --git a/validator-api/src/network_monitor/gateways_reader.rs b/nym-api/src/network_monitor/gateways_reader.rs similarity index 100% rename from validator-api/src/network_monitor/gateways_reader.rs rename to nym-api/src/network_monitor/gateways_reader.rs diff --git a/validator-api/src/network_monitor/mod.rs b/nym-api/src/network_monitor/mod.rs similarity index 98% rename from validator-api/src/network_monitor/mod.rs rename to nym-api/src/network_monitor/mod.rs index 8b85d5fd5a..0048e2be02 100644 --- a/validator-api/src/network_monitor/mod.rs +++ b/nym-api/src/network_monitor/mod.rs @@ -22,7 +22,7 @@ use crate::network_monitor::monitor::sender::PacketSender; use crate::network_monitor::monitor::summary_producer::SummaryProducer; use crate::network_monitor::monitor::Monitor; use crate::nymd_client::Client; -use crate::storage::ValidatorApiStorage; +use crate::storage::NymApiStorage; pub(crate) mod chunker; pub(crate) mod gateways_reader; @@ -36,7 +36,7 @@ pub(crate) struct NetworkMonitorBuilder<'a> { config: &'a Config, _nymd_client: Client, system_version: String, - node_status_storage: ValidatorApiStorage, + node_status_storage: NymApiStorage, validator_cache: ValidatorCache, } @@ -45,7 +45,7 @@ impl<'a> NetworkMonitorBuilder<'a> { config: &'a Config, _nymd_client: Client, system_version: &str, - node_status_storage: ValidatorApiStorage, + node_status_storage: NymApiStorage, validator_cache: ValidatorCache, ) -> Self { NetworkMonitorBuilder { diff --git a/validator-api/src/network_monitor/monitor/gateway_clients_cache.rs b/nym-api/src/network_monitor/monitor/gateway_clients_cache.rs similarity index 100% rename from validator-api/src/network_monitor/monitor/gateway_clients_cache.rs rename to nym-api/src/network_monitor/monitor/gateway_clients_cache.rs diff --git a/validator-api/src/network_monitor/monitor/gateways_pinger.rs b/nym-api/src/network_monitor/monitor/gateways_pinger.rs similarity index 100% rename from validator-api/src/network_monitor/monitor/gateways_pinger.rs rename to nym-api/src/network_monitor/monitor/gateways_pinger.rs diff --git a/validator-api/src/network_monitor/monitor/mod.rs b/nym-api/src/network_monitor/monitor/mod.rs similarity index 98% rename from validator-api/src/network_monitor/monitor/mod.rs rename to nym-api/src/network_monitor/monitor/mod.rs index e2d1a07128..c333c5e883 100644 --- a/validator-api/src/network_monitor/monitor/mod.rs +++ b/nym-api/src/network_monitor/monitor/mod.rs @@ -8,7 +8,7 @@ use crate::network_monitor::monitor::sender::PacketSender; use crate::network_monitor::monitor::summary_producer::{SummaryProducer, TestSummary}; use crate::network_monitor::test_packet::TestPacket; use crate::network_monitor::test_route::TestRoute; -use crate::storage::ValidatorApiStorage; +use crate::storage::NymApiStorage; use log::{debug, error, info}; use std::collections::{HashMap, HashSet}; use std::process; @@ -29,7 +29,7 @@ pub(super) struct Monitor { packet_sender: PacketSender, received_processor: ReceivedProcessor, summary_producer: SummaryProducer, - node_status_storage: ValidatorApiStorage, + node_status_storage: NymApiStorage, run_interval: Duration, gateway_ping_interval: Duration, packet_delivery_timeout: Duration, @@ -52,7 +52,7 @@ impl Monitor { packet_sender: PacketSender, received_processor: ReceivedProcessor, summary_producer: SummaryProducer, - node_status_storage: ValidatorApiStorage, + node_status_storage: NymApiStorage, ) -> Self { Monitor { test_nonce: 1, diff --git a/validator-api/src/network_monitor/monitor/preparer.rs b/nym-api/src/network_monitor/monitor/preparer.rs similarity index 100% rename from validator-api/src/network_monitor/monitor/preparer.rs rename to nym-api/src/network_monitor/monitor/preparer.rs diff --git a/validator-api/src/network_monitor/monitor/processor.rs b/nym-api/src/network_monitor/monitor/processor.rs similarity index 100% rename from validator-api/src/network_monitor/monitor/processor.rs rename to nym-api/src/network_monitor/monitor/processor.rs diff --git a/validator-api/src/network_monitor/monitor/receiver.rs b/nym-api/src/network_monitor/monitor/receiver.rs similarity index 100% rename from validator-api/src/network_monitor/monitor/receiver.rs rename to nym-api/src/network_monitor/monitor/receiver.rs diff --git a/validator-api/src/network_monitor/monitor/sender.rs b/nym-api/src/network_monitor/monitor/sender.rs similarity index 100% rename from validator-api/src/network_monitor/monitor/sender.rs rename to nym-api/src/network_monitor/monitor/sender.rs diff --git a/validator-api/src/network_monitor/monitor/summary_producer.rs b/nym-api/src/network_monitor/monitor/summary_producer.rs similarity index 100% rename from validator-api/src/network_monitor/monitor/summary_producer.rs rename to nym-api/src/network_monitor/monitor/summary_producer.rs diff --git a/validator-api/src/network_monitor/test_packet.rs b/nym-api/src/network_monitor/test_packet.rs similarity index 100% rename from validator-api/src/network_monitor/test_packet.rs rename to nym-api/src/network_monitor/test_packet.rs diff --git a/validator-api/src/network_monitor/test_route/mod.rs b/nym-api/src/network_monitor/test_route/mod.rs similarity index 100% rename from validator-api/src/network_monitor/test_route/mod.rs rename to nym-api/src/network_monitor/test_route/mod.rs diff --git a/validator-api/src/node_status_api/cache.rs b/nym-api/src/node_status_api/cache.rs similarity index 98% rename from validator-api/src/node_status_api/cache.rs rename to nym-api/src/node_status_api/cache.rs index 289a75a3f5..f485716e8e 100644 --- a/validator-api/src/node_status_api/cache.rs +++ b/nym-api/src/node_status_api/cache.rs @@ -2,12 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 use crate::contract_cache::{Cache, CacheNotification, ValidatorCache}; -use crate::storage::ValidatorApiStorage; +use crate::storage::NymApiStorage; use mixnet_contract_common::families::FamilyHead; use mixnet_contract_common::reward_params::Performance; use mixnet_contract_common::{ IdentityKey, Interval, MixId, MixNodeDetails, RewardedSetNodeStatus, RewardingParams, }; +use nym_api_requests::models::{MixNodeBondAnnotated, MixnodeStatus}; use rocket::fairing::AdHoc; use std::collections::HashMap; use std::{sync::Arc, time::Duration}; @@ -17,7 +18,6 @@ use tokio::{ sync::{watch, RwLock}, time, }; -use validator_api_requests::models::{MixNodeBondAnnotated, MixnodeStatus}; use self::inclusion_probabilities::InclusionProbabilities; @@ -154,7 +154,7 @@ pub struct NodeStatusCacheRefresher { // Sources for when refreshing data contract_cache: ValidatorCache, contract_cache_listener: watch::Receiver, - storage: Option, + storage: Option, } impl NodeStatusCacheRefresher { @@ -163,7 +163,7 @@ impl NodeStatusCacheRefresher { fallback_caching_interval: Duration, contract_cache: ValidatorCache, contract_cache_listener: watch::Receiver, - storage: Option, + storage: Option, ) -> Self { Self { cache, @@ -320,7 +320,7 @@ impl NodeStatusCacheRefresher { .rewarding_details .uncapped_bond_saturation(&interval_reward_params); - // If the performance can't be obtained, because the validator-api was not started with + // If the performance can't be obtained, because the nym-api was not started with // the monitoring (and hence, storage), then reward estimates will be all zero let performance = self .get_performance_from_storage(mixnode.mix_id(), current_interval) diff --git a/validator-api/src/node_status_api/cache/inclusion_probabilities.rs b/nym-api/src/node_status_api/cache/inclusion_probabilities.rs similarity index 98% rename from validator-api/src/node_status_api/cache/inclusion_probabilities.rs rename to nym-api/src/node_status_api/cache/inclusion_probabilities.rs index 21c1bdcab5..80643dae27 100644 --- a/validator-api/src/node_status_api/cache/inclusion_probabilities.rs +++ b/nym-api/src/node_status_api/cache/inclusion_probabilities.rs @@ -1,9 +1,9 @@ use contracts_common::truncate_decimal; use mixnet_contract_common::{MixId, MixNodeDetails, RewardingParams}; +use nym_api_requests::models::InclusionProbability; use serde::Serialize; use std::time::Duration; use tap::TapFallible; -use validator_api_requests::models::InclusionProbability; const MAX_SIMULATION_SAMPLES: u64 = 5000; const MAX_SIMULATION_TIME_SEC: u64 = 15; diff --git a/validator-api/src/node_status_api/helpers.rs b/nym-api/src/node_status_api/helpers.rs similarity index 97% rename from validator-api/src/node_status_api/helpers.rs rename to nym-api/src/node_status_api/helpers.rs index 4b084533bc..a2d102ebdd 100644 --- a/validator-api/src/node_status_api/helpers.rs +++ b/nym-api/src/node_status_api/helpers.rs @@ -3,24 +3,24 @@ use crate::contract_cache::Cache; use crate::node_status_api::models::ErrorResponse; -use crate::storage::ValidatorApiStorage; +use crate::storage::NymApiStorage; use crate::{NodeStatusCache, ValidatorCache}; use cosmwasm_std::Decimal; use mixnet_contract_common::reward_params::Performance; use mixnet_contract_common::{Interval, MixId, RewardedSetNodeStatus}; -use rocket::http::Status; -use rocket::State; -use validator_api_requests::models::{ +use nym_api_requests::models::{ AllInclusionProbabilitiesResponse, ComputeRewardEstParam, InclusionProbabilityResponse, MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse, MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RewardEstimationResponse, StakeSaturationResponse, UptimeResponse, }; +use rocket::http::Status; +use rocket::State; use super::reward_estimate::compute_reward_estimate; pub(crate) async fn _mixnode_report( - storage: &ValidatorApiStorage, + storage: &NymApiStorage, mix_id: MixId, ) -> Result { storage @@ -31,7 +31,7 @@ pub(crate) async fn _mixnode_report( } pub(crate) async fn _mixnode_uptime_history( - storage: &ValidatorApiStorage, + storage: &NymApiStorage, mix_id: MixId, ) -> Result { storage @@ -42,7 +42,7 @@ pub(crate) async fn _mixnode_uptime_history( } pub(crate) async fn _mixnode_core_status_count( - storage: &State, + storage: &State, mix_id: MixId, since: Option, ) -> Result { @@ -106,7 +106,7 @@ pub(crate) async fn _get_mixnode_reward_estimation( async fn average_mixnode_performance( mix_id: MixId, current_interval: Interval, - storage: &ValidatorApiStorage, + storage: &NymApiStorage, ) -> Result { storage .get_average_mixnode_uptime_in_the_last_24hrs( @@ -255,7 +255,7 @@ pub(crate) async fn _get_mixnode_inclusion_probability( pub(crate) async fn _get_mixnode_avg_uptime( cache: &ValidatorCache, - storage: &ValidatorApiStorage, + storage: &NymApiStorage, mix_id: MixId, ) -> Result { let current_interval = cache diff --git a/validator-api/src/node_status_api/local_guard.rs b/nym-api/src/node_status_api/local_guard.rs similarity index 100% rename from validator-api/src/node_status_api/local_guard.rs rename to nym-api/src/node_status_api/local_guard.rs diff --git a/validator-api/src/node_status_api/mod.rs b/nym-api/src/node_status_api/mod.rs similarity index 100% rename from validator-api/src/node_status_api/mod.rs rename to nym-api/src/node_status_api/mod.rs diff --git a/validator-api/src/node_status_api/models.rs b/nym-api/src/node_status_api/models.rs similarity index 99% rename from validator-api/src/node_status_api/models.rs rename to nym-api/src/node_status_api/models.rs index 329f9f7122..43a11627b3 100644 --- a/validator-api/src/node_status_api/models.rs +++ b/nym-api/src/node_status_api/models.rs @@ -5,6 +5,10 @@ use crate::node_status_api::utils::NodeUptimes; use crate::storage::models::NodeStatus; use mixnet_contract_common::reward_params::Performance; use mixnet_contract_common::{IdentityKey, MixId}; +use nym_api_requests::models::{ + GatewayStatusReportResponse, GatewayUptimeHistoryResponse, HistoricalUptimeResponse, + MixnodeStatusReportResponse, MixnodeUptimeHistoryResponse, RequestError, +}; use okapi::openapi3::{Responses, SchemaObject}; use rocket::http::Status; use rocket::response::{self, Responder, Response}; @@ -20,10 +24,6 @@ use serde::{Deserialize, Serialize}; use std::convert::TryFrom; use thiserror::Error; use time::OffsetDateTime; -use validator_api_requests::models::{ - GatewayStatusReportResponse, GatewayUptimeHistoryResponse, HistoricalUptimeResponse, - MixnodeStatusReportResponse, MixnodeUptimeHistoryResponse, RequestError, -}; #[derive(Error, Debug)] #[error("Received uptime value was within 0-100 range (got {received})")] @@ -373,7 +373,7 @@ impl OpenApiResponderInner for ErrorResponse { } #[derive(Debug, thiserror::Error)] -pub enum ValidatorApiStorageError { +pub enum NymApiStorageError { #[error("could not find status report associated with mixnode {mix_id}")] MixnodeReportNotFound { mix_id: MixId }, diff --git a/validator-api/src/node_status_api/reward_estimate.rs b/nym-api/src/node_status_api/reward_estimate.rs similarity index 100% rename from validator-api/src/node_status_api/reward_estimate.rs rename to nym-api/src/node_status_api/reward_estimate.rs diff --git a/validator-api/src/node_status_api/routes.rs b/nym-api/src/node_status_api/routes.rs similarity index 94% rename from validator-api/src/node_status_api/routes.rs rename to nym-api/src/node_status_api/routes.rs index 037ca7b117..70bb3db91e 100644 --- a/validator-api/src/node_status_api/routes.rs +++ b/nym-api/src/node_status_api/routes.rs @@ -10,25 +10,25 @@ use crate::node_status_api::helpers::{ _mixnode_report, _mixnode_uptime_history, }; use crate::node_status_api::models::ErrorResponse; -use crate::storage::ValidatorApiStorage; +use crate::storage::NymApiStorage; use crate::ValidatorCache; use mixnet_contract_common::MixId; -use rocket::http::Status; -use rocket::serde::json::Json; -use rocket::State; -use rocket_okapi::openapi; -use validator_api_requests::models::{ +use nym_api_requests::models::{ AllInclusionProbabilitiesResponse, ComputeRewardEstParam, GatewayCoreStatusResponse, GatewayStatusReportResponse, GatewayUptimeHistoryResponse, InclusionProbabilityResponse, MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse, MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RewardEstimationResponse, StakeSaturationResponse, UptimeResponse, }; +use rocket::http::Status; +use rocket::serde::json::Json; +use rocket::State; +use rocket_okapi::openapi; #[openapi(tag = "status")] #[get("/gateway//report")] pub(crate) async fn gateway_report( - storage: &State, + storage: &State, identity: &str, ) -> Result, ErrorResponse> { storage @@ -42,7 +42,7 @@ pub(crate) async fn gateway_report( #[openapi(tag = "status")] #[get("/gateway//history")] pub(crate) async fn gateway_uptime_history( - storage: &State, + storage: &State, identity: &str, ) -> Result, ErrorResponse> { storage @@ -56,7 +56,7 @@ pub(crate) async fn gateway_uptime_history( #[openapi(tag = "status")] #[get("/gateway//core-status-count?")] pub(crate) async fn gateway_core_status_count( - storage: &State, + storage: &State, identity: &str, since: Option, ) -> Json { @@ -74,7 +74,7 @@ pub(crate) async fn gateway_core_status_count( #[openapi(tag = "status")] #[get("/mixnode//report")] pub(crate) async fn mixnode_report( - storage: &State, + storage: &State, mix_id: MixId, ) -> Result, ErrorResponse> { Ok(Json(_mixnode_report(storage, mix_id).await?)) @@ -83,7 +83,7 @@ pub(crate) async fn mixnode_report( #[openapi(tag = "status")] #[get("/mixnode//history")] pub(crate) async fn mixnode_uptime_history( - storage: &State, + storage: &State, mix_id: MixId, ) -> Result, ErrorResponse> { Ok(Json(_mixnode_uptime_history(storage, mix_id).await?)) @@ -92,7 +92,7 @@ pub(crate) async fn mixnode_uptime_history( #[openapi(tag = "status")] #[get("/mixnode//core-status-count?")] pub(crate) async fn mixnode_core_status_count( - storage: &State, + storage: &State, mix_id: MixId, since: Option, ) -> Result, ErrorResponse> { @@ -171,7 +171,7 @@ pub(crate) async fn get_mixnode_inclusion_probability( #[get("/mixnode//avg_uptime")] pub(crate) async fn get_mixnode_avg_uptime( cache: &State, - storage: &State, + storage: &State, mix_id: MixId, ) -> Result, ErrorResponse> { Ok(Json(_get_mixnode_avg_uptime(cache, storage, mix_id).await?)) diff --git a/validator-api/src/node_status_api/uptime_updater.rs b/nym-api/src/node_status_api/uptime_updater.rs similarity index 92% rename from validator-api/src/node_status_api/uptime_updater.rs rename to nym-api/src/node_status_api/uptime_updater.rs index dcb4f6424c..cc22d75741 100644 --- a/validator-api/src/node_status_api/uptime_updater.rs +++ b/nym-api/src/node_status_api/uptime_updater.rs @@ -2,10 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 use crate::node_status_api::models::{ - GatewayStatusReport, MixnodeStatusReport, ValidatorApiStorageError, + GatewayStatusReport, MixnodeStatusReport, NymApiStorageError, }; use crate::node_status_api::ONE_DAY; -use crate::storage::ValidatorApiStorage; +use crate::storage::NymApiStorage; use log::error; use std::time::Duration; use task::ShutdownListener; @@ -13,11 +13,11 @@ use time::{OffsetDateTime, PrimitiveDateTime, Time}; use tokio::time::{interval, sleep}; pub(crate) struct HistoricalUptimeUpdater { - storage: ValidatorApiStorage, + storage: NymApiStorage, } impl HistoricalUptimeUpdater { - pub(crate) fn new(storage: ValidatorApiStorage) -> Self { + pub(crate) fn new(storage: NymApiStorage) -> Self { HistoricalUptimeUpdater { storage } } @@ -30,8 +30,7 @@ impl HistoricalUptimeUpdater { async fn get_active_nodes( &self, now: OffsetDateTime, - ) -> Result<(Vec, Vec), ValidatorApiStorageError> - { + ) -> Result<(Vec, Vec), NymApiStorageError> { let day_ago = (now - ONE_DAY).unix_timestamp(); let active_mixnodes = self .storage @@ -46,7 +45,7 @@ impl HistoricalUptimeUpdater { Ok((active_mixnodes, active_gateways)) } - async fn update_uptimes(&self) -> Result<(), ValidatorApiStorageError> { + async fn update_uptimes(&self) -> Result<(), NymApiStorageError> { let now = OffsetDateTime::now_utc(); let today_iso_8601 = now.date().to_string(); diff --git a/validator-api/src/node_status_api/utils.rs b/nym-api/src/node_status_api/utils.rs similarity index 100% rename from validator-api/src/node_status_api/utils.rs rename to nym-api/src/node_status_api/utils.rs diff --git a/validator-api/src/nymd_client.rs b/nym-api/src/nymd_client.rs similarity index 98% rename from validator-api/src/nymd_client.rs rename to nym-api/src/nymd_client.rs index 1f126d6fdc..d14a793fd4 100644 --- a/validator-api/src/nymd_client.rs +++ b/nym-api/src/nymd_client.rs @@ -3,7 +3,7 @@ use crate::config::Config; use crate::epoch_operations::MixnodeToReward; -use config::defaults::{NymNetworkDetails, DEFAULT_VALIDATOR_API_PORT}; +use config::defaults::{NymNetworkDetails, DEFAULT_NYM_API_PORT}; use mixnet_contract_common::families::{Family, FamilyHead}; use mixnet_contract_common::mixnode::MixNodeDetails; use mixnet_contract_common::reward_params::RewardingParams; @@ -59,7 +59,7 @@ impl Client { pub(crate) fn new_query(config: &Config) -> Self { // the api address is irrelevant here as **WE ARE THE API** // and we won't be talking on the socket here. - let api_url = format!("http://localhost:{}", DEFAULT_VALIDATOR_API_PORT) + let api_url = format!("http://localhost:{}", DEFAULT_NYM_API_PORT) .parse() .unwrap(); let nymd_url = config.get_nymd_validator_url(); @@ -82,7 +82,7 @@ impl Client { pub(crate) fn new_signing(config: &Config) -> Self { // the api address is irrelevant here as **WE ARE THE API** // and we won't be talking on the socket here. - let api_url = format!("http://localhost:{}", DEFAULT_VALIDATOR_API_PORT) + let api_url = format!("http://localhost:{}", DEFAULT_NYM_API_PORT) .parse() .unwrap(); let nymd_url = config.get_nymd_validator_url(); diff --git a/validator-api/src/storage/manager.rs b/nym-api/src/storage/manager.rs similarity index 100% rename from validator-api/src/storage/manager.rs rename to nym-api/src/storage/manager.rs diff --git a/validator-api/src/storage/mod.rs b/nym-api/src/storage/mod.rs similarity index 89% rename from validator-api/src/storage/mod.rs rename to nym-api/src/storage/mod.rs index 04186b7b57..1d513defdf 100644 --- a/validator-api/src/storage/mod.rs +++ b/nym-api/src/storage/mod.rs @@ -4,8 +4,8 @@ use crate::network_monitor::monitor::summary_producer::{GatewayResult, MixnodeResult}; use crate::network_monitor::test_route::TestRoute; use crate::node_status_api::models::{ - GatewayStatusReport, GatewayUptimeHistory, MixnodeStatusReport, MixnodeUptimeHistory, Uptime, - ValidatorApiStorageError, + GatewayStatusReport, GatewayUptimeHistory, MixnodeStatusReport, MixnodeUptimeHistory, + NymApiStorageError, Uptime, }; use crate::node_status_api::{ONE_DAY, ONE_HOUR}; use crate::storage::manager::StorageManager; @@ -23,13 +23,13 @@ pub(crate) mod models; // note that clone here is fine as upon cloning the same underlying pool will be used #[derive(Clone)] -pub(crate) struct ValidatorApiStorage { +pub(crate) struct NymApiStorage { pub manager: StorageManager, } -impl ValidatorApiStorage { - pub async fn init(database_path: PathBuf) -> Result { - // TODO: we can inject here more stuff based on our validator-api global config +impl NymApiStorage { + pub async fn init(database_path: PathBuf) -> Result { + // TODO: we can inject here more stuff based on our nym-api global config // struct. Maybe different pool size or timeout intervals? let mut opts = sqlx::sqlite::SqliteConnectOptions::new() .filename(&database_path) @@ -54,14 +54,14 @@ impl ValidatorApiStorage { info!("Database migration finished!"); - let storage = ValidatorApiStorage { + let storage = NymApiStorage { manager: StorageManager { connection_pool }, }; Ok(storage) } - pub(crate) fn stage(storage: ValidatorApiStorage) -> AdHoc { + pub(crate) fn stage(storage: NymApiStorage) -> AdHoc { AdHoc::try_on_ignite("SQLx Database", |rocket| async { Ok(rocket.manage(storage)) }) @@ -71,7 +71,7 @@ impl ValidatorApiStorage { pub(crate) async fn mix_identity_to_mix_ids( &self, identity: &str, - ) -> Result, ValidatorApiStorageError> { + ) -> Result, NymApiStorageError> { Ok(self .manager .get_mixnode_mix_ids_by_identity(identity) @@ -82,7 +82,7 @@ impl ValidatorApiStorage { pub(crate) async fn mix_identity_to_latest_mix_id( &self, identity: &str, - ) -> Result, ValidatorApiStorageError> { + ) -> Result, NymApiStorageError> { Ok(self .mix_identity_to_mix_ids(identity) .await? @@ -93,7 +93,7 @@ impl ValidatorApiStorage { pub(crate) async fn get_all_avg_gateway_reliability_in_last_24hr( &self, end_ts_secs: i64, - ) -> Result, ValidatorApiStorageError> { + ) -> Result, NymApiStorageError> { let result = self .manager .get_all_avg_gateway_reliability_in_last_24hr(end_ts_secs) @@ -105,7 +105,7 @@ impl ValidatorApiStorage { pub(crate) async fn get_all_avg_mix_reliability_in_last_24hr( &self, end_ts_secs: i64, - ) -> Result, ValidatorApiStorageError> { + ) -> Result, NymApiStorageError> { let result = self .manager .get_all_avg_mix_reliability_in_last_24hr(end_ts_secs) @@ -125,7 +125,7 @@ impl ValidatorApiStorage { &self, mix_id: MixId, since: i64, - ) -> Result, ValidatorApiStorageError> { + ) -> Result, NymApiStorageError> { let statuses = self .manager .get_mixnode_statuses_since(mix_id, since) @@ -145,7 +145,7 @@ impl ValidatorApiStorage { &self, identity: &str, since: i64, - ) -> Result, ValidatorApiStorageError> { + ) -> Result, NymApiStorageError> { let statuses = self .manager .get_gateway_statuses_since(identity, since) @@ -162,7 +162,7 @@ impl ValidatorApiStorage { pub(crate) async fn construct_mixnode_report( &self, mix_id: MixId, - ) -> Result { + ) -> Result { let now = OffsetDateTime::now_utc(); let day_ago = (now - ONE_DAY).unix_timestamp(); let hour_ago = (now - ONE_HOUR).unix_timestamp(); @@ -171,7 +171,7 @@ impl ValidatorApiStorage { // if we have no statuses, the node doesn't exist (or monitor is down), but either way, we can't make a report if statuses.is_empty() { - return Err(ValidatorApiStorageError::MixnodeReportNotFound { mix_id }); + return Err(NymApiStorageError::MixnodeReportNotFound { mix_id }); } // determine the number of runs the mixnode should have been online for @@ -206,7 +206,7 @@ impl ValidatorApiStorage { pub(crate) async fn construct_gateway_report( &self, identity: &str, - ) -> Result { + ) -> Result { let now = OffsetDateTime::now_utc(); let day_ago = (now - ONE_DAY).unix_timestamp(); let hour_ago = (now - ONE_HOUR).unix_timestamp(); @@ -215,7 +215,7 @@ impl ValidatorApiStorage { // if we have no statuses, the node doesn't exist (or monitor is down), but either way, we can't make a report if statuses.is_empty() { - return Err(ValidatorApiStorageError::GatewayReportNotFound { + return Err(NymApiStorageError::GatewayReportNotFound { identity: identity.to_owned(), }); } @@ -245,11 +245,11 @@ impl ValidatorApiStorage { pub(crate) async fn get_mixnode_uptime_history( &self, mix_id: MixId, - ) -> Result { + ) -> Result { let history = self.manager.get_mixnode_historical_uptimes(mix_id).await?; if history.is_empty() { - return Err(ValidatorApiStorageError::MixnodeUptimeHistoryNotFound { mix_id }); + return Err(NymApiStorageError::MixnodeUptimeHistoryNotFound { mix_id }); } let mixnode_owner = @@ -273,14 +273,14 @@ impl ValidatorApiStorage { pub(crate) async fn get_gateway_uptime_history( &self, identity: &str, - ) -> Result { + ) -> Result { let history = self .manager .get_gateway_historical_uptimes(identity) .await?; if history.is_empty() { - return Err(ValidatorApiStorageError::GatewayUptimeHistoryNotFound { + return Err(NymApiStorageError::GatewayUptimeHistoryNotFound { identity: identity.to_owned(), }); } @@ -301,7 +301,7 @@ impl ValidatorApiStorage { &self, mix_id: MixId, end_ts_secs: i64, - ) -> Result { + ) -> Result { let start = end_ts_secs - 86400; self.get_average_mixnode_uptime_in_time_interval(mix_id, start, end_ts_secs) .await @@ -320,7 +320,7 @@ impl ValidatorApiStorage { mix_id: MixId, start: i64, end: i64, - ) -> Result { + ) -> Result { let mixnode_database_id = match self.manager.get_mixnode_database_id(mix_id).await? { Some(id) => id, None => return Ok(Uptime::zero()), @@ -350,7 +350,7 @@ impl ValidatorApiStorage { &self, start: i64, end: i64, - ) -> Result, ValidatorApiStorageError> { + ) -> Result, NymApiStorageError> { if (end - start) as u64 != ONE_DAY.as_secs() { warn!("Our current interval length breaks the 24h length assumption") } @@ -394,7 +394,7 @@ impl ValidatorApiStorage { &self, start: i64, end: i64, - ) -> Result, ValidatorApiStorageError> { + ) -> Result, NymApiStorageError> { if (end - start) as u64 != ONE_DAY.as_secs() { warn!("Our current interval length breaks the 24h length assumption") } @@ -435,14 +435,14 @@ impl ValidatorApiStorage { &self, monitor_run_db_id: i64, test_route: TestRoute, - ) -> Result<(), ValidatorApiStorageError> { + ) -> Result<(), NymApiStorageError> { // we MUST have those entries in the database, otherwise the route wouldn't have been chosen // in the first place let layer1_mix_db_id = self .manager .get_mixnode_database_id(test_route.layer_one_mix().mix_id) .await? - .ok_or_else(|| ValidatorApiStorageError::DatabaseInconsistency { + .ok_or_else(|| NymApiStorageError::DatabaseInconsistency { reason: format!("could not get db id for layer1 mixnode from network monitor run {monitor_run_db_id}"), })?; @@ -450,7 +450,7 @@ impl ValidatorApiStorage { .manager .get_mixnode_database_id(test_route.layer_two_mix().mix_id) .await? - .ok_or_else(|| ValidatorApiStorageError::DatabaseInconsistency { + .ok_or_else(|| NymApiStorageError::DatabaseInconsistency { reason: format!("could not get db id for layer2 mixnode from network monitor run {monitor_run_db_id}"), })?; @@ -458,7 +458,7 @@ impl ValidatorApiStorage { .manager .get_mixnode_database_id(test_route.layer_three_mix().mix_id) .await? - .ok_or_else(|| ValidatorApiStorageError::DatabaseInconsistency { + .ok_or_else(|| NymApiStorageError::DatabaseInconsistency { reason: format!("could not get db id for layer3 mixnode from network monitor run {monitor_run_db_id}"), })?; @@ -466,7 +466,7 @@ impl ValidatorApiStorage { .manager .get_gateway_id(&test_route.gateway().identity_key.to_base58_string()) .await? - .ok_or_else(|| ValidatorApiStorageError::DatabaseInconsistency { + .ok_or_else(|| NymApiStorageError::DatabaseInconsistency { reason: format!( "could not get db id for gateway from network monitor run {monitor_run_db_id}" ), @@ -496,7 +496,7 @@ impl ValidatorApiStorage { &self, mix_id: MixId, since: Option, - ) -> Result { + ) -> Result { let db_id = self.manager.get_mixnode_database_id(mix_id).await?; if let Some(node_id) = db_id { @@ -524,7 +524,7 @@ impl ValidatorApiStorage { &self, identity: &str, since: Option, - ) -> Result { + ) -> Result { let node_id = self.manager.get_gateway_id(identity).await?; if let Some(node_id) = node_id { @@ -553,7 +553,7 @@ impl ValidatorApiStorage { mixnode_results: Vec, gateway_results: Vec, test_routes: Vec, - ) -> Result<(), ValidatorApiStorageError> { + ) -> Result<(), NymApiStorageError> { info!("Submitting new node results to the database. There are {} mixnode results and {} gateway results", mixnode_results.len(), gateway_results.len()); let now = OffsetDateTime::now_utc().unix_timestamp(); @@ -585,12 +585,12 @@ impl ValidatorApiStorage { &self, since: i64, until: i64, - ) -> Result { + ) -> Result { let run_count = self.manager.get_monitor_runs_count(since, until).await?; if run_count < 0 { // I don't think it's ever possible for SQL to return a negative value from COUNT? - return Err(ValidatorApiStorageError::DatabaseInconsistency { + return Err(NymApiStorageError::DatabaseInconsistency { reason: "Negative run count".to_string(), }); } @@ -610,7 +610,7 @@ impl ValidatorApiStorage { today_iso_8601: &str, mixnode_reports: &[MixnodeStatusReport], gateway_reports: &[GatewayStatusReport], - ) -> Result<(), ValidatorApiStorageError> { + ) -> Result<(), NymApiStorageError> { for report in mixnode_reports { // if this ever fails, we have a super weird error because we just constructed report for that node // and we never delete node data! @@ -655,7 +655,7 @@ impl ValidatorApiStorage { pub(crate) async fn check_if_historical_uptimes_exist_for_date( &self, date_iso_8601: &str, - ) -> Result { + ) -> Result { self.manager .check_for_historical_uptime_existence(date_iso_8601) .await @@ -668,10 +668,7 @@ impl ValidatorApiStorage { /// # Arguments /// /// * `until`: timestamp specifying the purge cutoff. - pub(crate) async fn purge_old_statuses( - &self, - until: i64, - ) -> Result<(), ValidatorApiStorageError> { + pub(crate) async fn purge_old_statuses(&self, until: i64) -> Result<(), NymApiStorageError> { self.manager.purge_old_mixnode_statuses(until).await?; self.manager .purge_old_gateway_statuses(until) @@ -682,7 +679,7 @@ impl ValidatorApiStorage { pub(crate) async fn insert_rewarding_report( &self, report: RewardingReport, - ) -> Result<(), ValidatorApiStorageError> { + ) -> Result<(), NymApiStorageError> { self.manager .insert_rewarding_report(report) .await @@ -692,7 +689,7 @@ impl ValidatorApiStorage { pub(crate) async fn get_rewarding_report( &self, absolute_epoch_id: EpochId, - ) -> Result, ValidatorApiStorageError> { + ) -> Result, NymApiStorageError> { self.manager .get_rewarding_report(absolute_epoch_id) .await @@ -703,7 +700,7 @@ impl ValidatorApiStorage { pub(crate) async fn get_blinded_signature_response( &self, tx_hash: &str, - ) -> Result, ValidatorApiStorageError> { + ) -> Result, NymApiStorageError> { self.manager .get_blinded_signature_response(tx_hash) .await @@ -715,7 +712,7 @@ impl ValidatorApiStorage { &self, tx_hash: &str, blinded_signature_response: &str, - ) -> Result<(), ValidatorApiStorageError> { + ) -> Result<(), NymApiStorageError> { self.manager .insert_blinded_signature_response(tx_hash, blinded_signature_response) .await diff --git a/validator-api/src/storage/models.rs b/nym-api/src/storage/models.rs similarity index 100% rename from validator-api/src/storage/models.rs rename to nym-api/src/storage/models.rs diff --git a/validator-api/src/swagger.rs b/nym-api/src/swagger.rs similarity index 100% rename from validator-api/src/swagger.rs rename to nym-api/src/swagger.rs diff --git a/validator-api/tests/README.md b/nym-api/tests/README.md similarity index 100% rename from validator-api/tests/README.md rename to nym-api/tests/README.md diff --git a/validator-api/tests/functional_test/validator-api/status/status-mixnode.test.ts b/nym-api/tests/functional_test/validator-api/status/status-mixnode.test.ts similarity index 100% rename from validator-api/tests/functional_test/validator-api/status/status-mixnode.test.ts rename to nym-api/tests/functional_test/validator-api/status/status-mixnode.test.ts diff --git a/validator-api/tests/jest.config.js b/nym-api/tests/jest.config.js similarity index 100% rename from validator-api/tests/jest.config.js rename to nym-api/tests/jest.config.js diff --git a/validator-api/tests/package.json b/nym-api/tests/package.json similarity index 100% rename from validator-api/tests/package.json rename to nym-api/tests/package.json diff --git a/validator-api/tests/src/config/config.yaml b/nym-api/tests/src/config/config.yaml similarity index 100% rename from validator-api/tests/src/config/config.yaml rename to nym-api/tests/src/config/config.yaml diff --git a/validator-api/tests/src/config/configHandler.ts b/nym-api/tests/src/config/configHandler.ts similarity index 100% rename from validator-api/tests/src/config/configHandler.ts rename to nym-api/tests/src/config/configHandler.ts diff --git a/validator-api/tests/src/endpoints/Status.ts b/nym-api/tests/src/endpoints/Status.ts similarity index 100% rename from validator-api/tests/src/endpoints/Status.ts rename to nym-api/tests/src/endpoints/Status.ts diff --git a/validator-api/tests/src/endpoints/abstracts/APIClient.ts b/nym-api/tests/src/endpoints/abstracts/APIClient.ts similarity index 100% rename from validator-api/tests/src/endpoints/abstracts/APIClient.ts rename to nym-api/tests/src/endpoints/abstracts/APIClient.ts diff --git a/validator-api/tests/src/interfaces/StatusInterfaces.ts b/nym-api/tests/src/interfaces/StatusInterfaces.ts similarity index 100% rename from validator-api/tests/src/interfaces/StatusInterfaces.ts rename to nym-api/tests/src/interfaces/StatusInterfaces.ts diff --git a/validator-api/tests/src/restClient/RestClient.ts b/nym-api/tests/src/restClient/RestClient.ts similarity index 100% rename from validator-api/tests/src/restClient/RestClient.ts rename to nym-api/tests/src/restClient/RestClient.ts diff --git a/validator-api/tests/tsconfig.eslint.json b/nym-api/tests/tsconfig.eslint.json similarity index 100% rename from validator-api/tests/tsconfig.eslint.json rename to nym-api/tests/tsconfig.eslint.json diff --git a/validator-api/tests/tsconfig.json b/nym-api/tests/tsconfig.json similarity index 100% rename from validator-api/tests/tsconfig.json rename to nym-api/tests/tsconfig.json diff --git a/validator-api/tests/yarn.lock b/nym-api/tests/yarn.lock similarity index 100% rename from validator-api/tests/yarn.lock rename to nym-api/tests/yarn.lock diff --git a/nym-connect/Cargo.lock b/nym-connect/Cargo.lock index 3ba62ad4f0..7522031a5e 100644 --- a/nym-connect/Cargo.lock +++ b/nym-connect/Cargo.lock @@ -1004,8 +1004,8 @@ dependencies = [ "bls12_381 0.5.0", "coconut-interface", "crypto", + "nym-api-requests", "thiserror", - "validator-api-requests", "validator-client", ] @@ -3339,6 +3339,20 @@ dependencies = [ "syn", ] +[[package]] +name = "nym-api-requests" +version = "0.1.0" +dependencies = [ + "bs58", + "coconut-interface", + "cosmrs", + "cosmwasm-std", + "getset", + "mixnet-contract-common", + "schemars", + "serde", +] + [[package]] name = "nym-connect" version = "1.1.4" @@ -6339,20 +6353,6 @@ dependencies = [ "getrandom 0.2.7", ] -[[package]] -name = "validator-api-requests" -version = "0.1.0" -dependencies = [ - "bs58", - "coconut-interface", - "cosmrs", - "cosmwasm-std", - "getset", - "mixnet-contract-common", - "schemars", - "serde", -] - [[package]] name = "validator-client" version = "0.1.0" @@ -6377,6 +6377,7 @@ dependencies = [ "mixnet-contract-common", "multisig-contract-common", "network-defaults", + "nym-api-requests", "prost", "reqwest", "serde", @@ -6385,7 +6386,6 @@ dependencies = [ "thiserror", "tokio", "url", - "validator-api-requests", "vesting-contract", "vesting-contract-common", ] diff --git a/nym-connect/src-tauri/src/config/mod.rs b/nym-connect/src-tauri/src/config/mod.rs index c27bf6b6b7..dcbbe12135 100644 --- a/nym-connect/src-tauri/src/config/mod.rs +++ b/nym-connect/src-tauri/src/config/mod.rs @@ -123,7 +123,7 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str if let Ok(raw_validators) = std::env::var(config_common::defaults::var_names::API_VALIDATOR) { config .get_base_mut() - .set_custom_validator_apis(config_common::parse_validators(&raw_validators)); + .set_custom_nym_apis(config_common::parse_validators(&raw_validators)); } // Setup gateway by either registering a new one, or reusing exiting keys diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 200fc3a81c..e27b6da0db 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -2874,6 +2874,20 @@ dependencies = [ "libc", ] +[[package]] +name = "nym-api-requests" +version = "0.1.0" +dependencies = [ + "bs58", + "coconut-interface", + "cosmrs", + "cosmwasm-std", + "getset", + "mixnet-contract-common", + "schemars", + "serde", +] + [[package]] name = "nym-types" version = "1.0.0" @@ -5397,20 +5411,6 @@ dependencies = [ "getrandom 0.2.5", ] -[[package]] -name = "validator-api-requests" -version = "0.1.0" -dependencies = [ - "bs58", - "coconut-interface", - "cosmrs", - "cosmwasm-std", - "getset", - "mixnet-contract-common", - "schemars", - "serde", -] - [[package]] name = "validator-client" version = "0.1.0" @@ -5435,6 +5435,7 @@ dependencies = [ "mixnet-contract-common", "multisig-contract-common", "network-defaults", + "nym-api-requests", "prost", "reqwest", "serde", @@ -5443,7 +5444,6 @@ dependencies = [ "thiserror", "tokio", "url", - "validator-api-requests", "vesting-contract", "vesting-contract-common", ] diff --git a/nym-wallet/src-tauri/src/config/mod.rs b/nym-wallet/src-tauri/src/config/mod.rs index ee0bba8963..49d7acfdd4 100644 --- a/nym-wallet/src-tauri/src/config/mod.rs +++ b/nym-wallet/src-tauri/src/config/mod.rs @@ -255,7 +255,7 @@ impl Config { } } - pub fn select_validator_api_url(&mut self, api_url: Url, network: WalletNetwork) { + pub fn select_nym_api_url(&mut self, api_url: Url, network: WalletNetwork) { if let Some(net) = self.networks.get_mut(&network.as_key()) { net.selected_api_url = Some(api_url); } else { @@ -275,7 +275,7 @@ impl Config { .and_then(|config| config.selected_nymd_url.clone()) } - pub fn get_selected_validator_api_url(&self, network: &WalletNetwork) -> Option { + pub fn get_selected_nym_api_url(&self, network: &WalletNetwork) -> Option { self.networks .get(&network.as_key()) .and_then(|config| config.selected_api_url.clone()) diff --git a/nym-wallet/src-tauri/src/error.rs b/nym-wallet/src-tauri/src/error.rs index bceff50f54..e5a8feeef5 100644 --- a/nym-wallet/src-tauri/src/error.rs +++ b/nym-wallet/src-tauri/src/error.rs @@ -4,7 +4,7 @@ use serde::{Serialize, Serializer}; use std::io; use std::num::ParseIntError; use thiserror::Error; -use validator_client::validator_api::error::ValidatorAPIError; +use validator_client::nym_api::error::NymAPIError; use validator_client::{nymd::error::NymdError, ValidatorClientError}; #[derive(Error, Debug)] @@ -40,9 +40,9 @@ pub enum BackendError { source: eyre::Report, }, #[error("{source}")] - ValidatorApiError { + NymApiError { #[from] - source: ValidatorAPIError, + source: NymAPIError, }, #[error("{source}")] KeyDerivationError { @@ -134,12 +134,10 @@ impl Serialize for BackendError { impl From for BackendError { fn from(e: ValidatorClientError) -> Self { match e { - ValidatorClientError::ValidatorAPIError { source } => source.into(), + ValidatorClientError::NymAPIError { source } => source.into(), ValidatorClientError::MalformedUrlProvided(e) => e.into(), ValidatorClientError::NymdError(e) => e.into(), - ValidatorClientError::NoAPIUrlAvailable => { - TypesError::NoValidatorApiUrlConfigured.into() - } + ValidatorClientError::NoAPIUrlAvailable => TypesError::NoNymApiUrlConfigured.into(), } } } diff --git a/nym-wallet/src-tauri/src/main.rs b/nym-wallet/src-tauri/src/main.rs index d34a04f920..63e2a43e4f 100644 --- a/nym-wallet/src-tauri/src/main.rs +++ b/nym-wallet/src-tauri/src/main.rs @@ -10,9 +10,9 @@ use mixnet_contract_common::{Gateway, MixNode}; use crate::menu::AddDefaultSubmenus; use crate::operations::help; use crate::operations::mixnet; +use crate::operations::nym_api; use crate::operations::signatures; use crate::operations::simulate; -use crate::operations::validator_api; use crate::operations::vesting; use crate::state::WalletState; @@ -85,10 +85,10 @@ fn main() { mixnet::rewards::claim_locked_and_unlocked_delegator_reward, mixnet::send::send, network_config::add_validator, - network_config::get_validator_api_urls, + network_config::get_nym_api_urls, network_config::get_validator_nymd_urls, network_config::remove_validator, - network_config::select_validator_api_url, + network_config::select_nym_api_url, network_config::select_validator_nymd_url, network_config::update_validator_urls, state::load_config_from_files, @@ -99,13 +99,13 @@ fn main() { utils::get_old_and_incorrect_hardcoded_fee, utils::try_convert_pubkey_to_mix_id, utils::default_mixnode_cost_params, - validator_api::status::gateway_core_node_status, - validator_api::status::mixnode_core_node_status, - validator_api::status::mixnode_inclusion_probability, - validator_api::status::mixnode_reward_estimation, - validator_api::status::mixnode_stake_saturation, - validator_api::status::mixnode_status, - validator_api::status::gateway_report, + nym_api::status::gateway_core_node_status, + nym_api::status::mixnode_core_node_status, + nym_api::status::mixnode_inclusion_probability, + nym_api::status::mixnode_reward_estimation, + nym_api::status::mixnode_stake_saturation, + nym_api::status::mixnode_status, + nym_api::status::gateway_report, vesting::rewards::vesting_claim_delegator_reward, vesting::rewards::vesting_claim_operator_reward, vesting::bond::vesting_bond_gateway, diff --git a/nym-wallet/src-tauri/src/network_config.rs b/nym-wallet/src-tauri/src/network_config.rs index 43e872b717..ce976b971d 100644 --- a/nym-wallet/src-tauri/src/network_config.rs +++ b/nym-wallet/src-tauri/src/network_config.rs @@ -17,7 +17,7 @@ pub async fn get_validator_nymd_urls( } #[tauri::command] -pub async fn get_validator_api_urls( +pub async fn get_nym_api_urls( network: WalletNetwork, state: tauri::State<'_, WalletState>, ) -> Result { @@ -41,13 +41,13 @@ pub async fn select_validator_nymd_url( } #[tauri::command] -pub async fn select_validator_api_url( +pub async fn select_nym_api_url( url: &str, network: WalletNetwork, state: tauri::State<'_, WalletState>, ) -> Result<(), BackendError> { log::debug!("Selecting new validator api_url for {network}: {url}"); - state.write().await.select_validator_api_url(url, network)?; + state.write().await.select_nym_api_url(url, network)?; Ok(()) } diff --git a/nym-wallet/src-tauri/src/operations/mixnet/account.rs b/nym-wallet/src-tauri/src/operations/mixnet/account.rs index 5811c007d1..9a3afafe6d 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/account.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/account.rs @@ -128,7 +128,7 @@ async fn _connect_with_mnemonic( .map(|(network, urls)| (*network, urls.iter().next().unwrap().clone())) .collect(); - // Run connection tests on all nymd and validator-api endpoints + // Run connection tests on all nymd and nym-api endpoints let (nymd_urls, api_urls) = run_connection_test(untested_nymd_urls, untested_api_urls, &config).await; @@ -222,7 +222,7 @@ fn create_clients( }) }; - let api_url = if let Some(url) = config.get_selected_validator_api_url(&network) { + let api_url = if let Some(url) = config.get_selected_nym_api_url(&network) { log::debug!("Using selected api_url for {network}: {url}"); url.clone() } else { diff --git a/nym-wallet/src-tauri/src/operations/mixnet/bond.rs b/nym-wallet/src-tauri/src/operations/mixnet/bond.rs index 567dc84290..5807fb7270 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/bond.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/bond.rs @@ -211,7 +211,7 @@ pub async fn get_mixnode_avg_uptime( let id = details.mix_id(); log::trace!(" >>> Get average uptime percentage: mix_id = {}", id); let avg_uptime_percent = client - .validator_api + .nym_api .get_mixnode_avg_uptime(id) .await .ok() diff --git a/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs b/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs index dfbf46389b..8b8f615244 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs @@ -238,7 +238,7 @@ pub async fn get_all_mix_delegations( d.mix_id ); let avg_uptime_percent = client - .validator_api + .nym_api .get_mixnode_avg_uptime(d.mix_id) .await .ok() diff --git a/nym-wallet/src-tauri/src/operations/mod.rs b/nym-wallet/src-tauri/src/operations/mod.rs index 457971d8c8..c6c175ee12 100644 --- a/nym-wallet/src-tauri/src/operations/mod.rs +++ b/nym-wallet/src-tauri/src/operations/mod.rs @@ -1,6 +1,6 @@ pub mod help; pub mod mixnet; +pub mod nym_api; pub mod signatures; pub mod simulate; -pub mod validator_api; pub mod vesting; diff --git a/nym-wallet/src-tauri/src/operations/validator_api/mod.rs b/nym-wallet/src-tauri/src/operations/nym_api/mod.rs similarity index 100% rename from nym-wallet/src-tauri/src/operations/validator_api/mod.rs rename to nym-wallet/src-tauri/src/operations/nym_api/mod.rs diff --git a/nym-wallet/src-tauri/src/operations/validator_api/status.rs b/nym-wallet/src-tauri/src/operations/nym_api/status.rs similarity index 100% rename from nym-wallet/src-tauri/src/operations/validator_api/status.rs rename to nym-wallet/src-tauri/src/operations/nym_api/status.rs diff --git a/nym-wallet/src-tauri/src/state.rs b/nym-wallet/src-tauri/src/state.rs index e36dfe1b5c..319e645c57 100644 --- a/nym-wallet/src-tauri/src/state.rs +++ b/nym-wallet/src-tauri/src/state.rs @@ -300,7 +300,7 @@ impl WalletStateInner { }) } - /// Get the list of validator-api urls in the network config format, suitable for passing on to + /// Get the list of nym-api urls in the network config format, suitable for passing on to /// the UI pub fn get_api_urls( &self, @@ -425,14 +425,10 @@ impl WalletStateInner { Ok(()) } - pub fn select_validator_api_url( - &mut self, - url: &str, - network: Network, - ) -> Result<(), BackendError> { - self.config.select_validator_api_url(url.parse()?, network); + pub fn select_nym_api_url(&mut self, url: &str, network: Network) -> Result<(), BackendError> { + self.config.select_nym_api_url(url.parse()?, network); if let Ok(client) = self.client_mut(network) { - client.change_validator_api(url.parse()?); + client.change_nym_api(url.parse()?); } Ok(()) } @@ -489,7 +485,7 @@ macro_rules! nymd_client { #[macro_export] macro_rules! api_client { ($state:ident) => { - $state.read().await.current_client()?.validator_api + $state.read().await.current_client()?.nym_api }; } diff --git a/sdk/typescript/examples/plain-html/src/index.ts b/sdk/typescript/examples/plain-html/src/index.ts index 16f53c380c..d279586b72 100644 --- a/sdk/typescript/examples/plain-html/src/index.ts +++ b/sdk/typescript/examples/plain-html/src/index.ts @@ -15,11 +15,11 @@ async function main() { } // // mixnet v1 - // const validatorApiUrl = 'https://validator.nymtech.net/api'; + // const nymApiUrl = 'https://validator.nymtech.net/api'; // const preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM'; // mixnet v2 - const validatorApiUrl = 'https://qwerty-validator-api.qa.nymte.ch/api'; // "http://localhost:8081"; + const nymApiUrl = 'https://qwerty-validator-api.qa.nymte.ch/api'; // "http://localhost:8081"; const preferredGatewayIdentityKey = undefined; // '36vfvEyBzo5cWEFbnP7fqgY39kFw9PQhvwzbispeNaxL'; // subscribe to connect event, so that we can show the client's address @@ -46,7 +46,7 @@ async function main() { // start up the client await nym.client.start({ clientId: 'My awesome client', - validatorApiUrl, + nymApiUrl, preferredGatewayIdentityKey, }); } diff --git a/sdk/typescript/examples/react-webpack-with-theme-example/src/App.tsx b/sdk/typescript/examples/react-webpack-with-theme-example/src/App.tsx index 6f6f4c2039..73c028d062 100644 --- a/sdk/typescript/examples/react-webpack-with-theme-example/src/App.tsx +++ b/sdk/typescript/examples/react-webpack-with-theme-example/src/App.tsx @@ -95,16 +95,16 @@ export const Content: React.FC = () => { React.useEffect(() => { if (isReady) { // // mixnet v1 - // const validatorApiUrl = 'https://validator.nymtech.net/api'; + // const nymApiUrl = 'https://validator.nymtech.net/api'; // const preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM'; // mixnet v2 - const validatorApiUrl = 'https://qwerty-validator-api.qa.nymte.ch/api'; // "http://localhost:8081"; + const nymApiUrl = 'https://qwerty-validator-api.qa.nymte.ch/api'; // "http://localhost:8081"; const preferredGatewayIdentityKey = undefined; // '36vfvEyBzo5cWEFbnP7fqgY39kFw9PQhvwzbispeNaxL'; connect({ clientId: 'Example Client', - validatorApiUrl, + nymApiUrl, preferredGatewayIdentityKey, }); } diff --git a/sdk/typescript/packages/sdk/README.md b/sdk/typescript/packages/sdk/README.md index e5f2fd51c5..af847d969a 100644 --- a/sdk/typescript/packages/sdk/README.md +++ b/sdk/typescript/packages/sdk/README.md @@ -18,7 +18,7 @@ import { createNymMixnetClient } from '@nymproject/sdk'; const main = async () => { const nym = await createNymMixnetClient(); - const validatorApiUrl = 'https://validator.nymtech.net/api'; + const nymApiUrl = 'https://validator.nymtech.net/api'; // show message payload content when received nym.events.subscribeToTextMessageReceivedEvent((e) => { @@ -28,7 +28,7 @@ const main = async () => { // start the client and connect to a gateway await nym.client.start({ clientId: 'My awesome client', - validatorApiUrl, + nymApiUrl, }); // send a message to yourself diff --git a/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts b/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts index 36aacd5adb..498e1b40de 100644 --- a/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts +++ b/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts @@ -21,13 +21,13 @@ export interface NymClientConfig { /** * The URL of a validator API to query for the network topology. */ - validatorApiUrl: string; + 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. */ diff --git a/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts b/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts index cb1c8a32e4..87d44bbb4b 100644 --- a/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts +++ b/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts @@ -130,19 +130,19 @@ wasm_bindgen(wasmUrl) const startHandler = async (config: NymClientConfig) => { // fetch the gateway details (randomly chosen if no preferred gateway is set) const gatewayEndpoint = await wasm_bindgen.get_gateway( - config.validatorApiUrl, + config.nymApiUrl, config.preferredGatewayIdentityKey, ); - + // set a different gatewayListener in order to avoid workaround ws over https error if (config.gatewayListener) - gatewayEndpoint.gateway_listener = config.gatewayListener; - + gatewayEndpoint.gateway_listener = config.gatewayListener; + // create the client, passing handlers for events wrapper.init( new wasm_bindgen.Config( config.clientId, - config.validatorApiUrl, + config.nymApiUrl, gatewayEndpoint, config.debug || wasm_bindgen.default_debug(), ), diff --git a/tools/nym-cli/src/main.rs b/tools/nym-cli/src/main.rs index ce81cd6a56..306d383c34 100644 --- a/tools/nym-cli/src/main.rs +++ b/tools/nym-cli/src/main.rs @@ -36,7 +36,7 @@ pub(crate) struct Cli { #[clap( help = "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file" )] - pub(crate) validator_api_url: Option, + pub(crate) nym_api_url: Option, #[clap(long, global = true)] #[clap( @@ -77,7 +77,7 @@ pub(crate) enum Commands { async fn execute(cli: Cli) -> anyhow::Result<()> { let args = ClientArgs { nymd_url: cli.nymd_url, - validator_api_url: cli.validator_api_url, + nym_api_url: cli.nym_api_url, mnemonic: cli.mnemonic, mixnet_contract_address: cli.mixnet_contract_address, vesting_contract_address: cli.vesting_contract_address, diff --git a/tools/nym-cli/src/validator/mixnet/delegators/mod.rs b/tools/nym-cli/src/validator/mixnet/delegators/mod.rs index ed1ac2f211..3e40d2d26a 100644 --- a/tools/nym-cli/src/validator/mixnet/delegators/mod.rs +++ b/tools/nym-cli/src/validator/mixnet/delegators/mod.rs @@ -3,7 +3,7 @@ use network_defaults::NymNetworkDetails; use nym_cli_commands::context::{ - create_signing_client, create_signing_client_with_validator_api, ClientArgs, + create_signing_client, create_signing_client_with_nym_api, ClientArgs, }; pub(crate) mod rewards; @@ -24,7 +24,7 @@ pub(crate) async fn execute( nym_cli_commands::validator::mixnet::delegators::undelegate_from_mixnode::undelegate_from_mixnode(args, create_signing_client(global_args, network_details)?).await } nym_cli_commands::validator::mixnet::delegators::MixnetDelegatorsCommands::List(args) => { - nym_cli_commands::validator::mixnet::delegators::query_for_delegations::execute(args, create_signing_client_with_validator_api(global_args, network_details)?).await + nym_cli_commands::validator::mixnet::delegators::query_for_delegations::execute(args, create_signing_client_with_nym_api(global_args, network_details)?).await } _ => unreachable!(), } diff --git a/tools/nym-cli/src/validator/mixnet/query/mod.rs b/tools/nym-cli/src/validator/mixnet/query/mod.rs index 21afb8c833..ea41ebd7d6 100644 --- a/tools/nym-cli/src/validator/mixnet/query/mod.rs +++ b/tools/nym-cli/src/validator/mixnet/query/mod.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use network_defaults::NymNetworkDetails; -use nym_cli_commands::context::create_query_client_with_validator_api; +use nym_cli_commands::context::create_query_client_with_nym_api; pub(crate) async fn execute( query: nym_cli_commands::validator::mixnet::query::MixnetQuery, @@ -12,14 +12,14 @@ pub(crate) async fn execute( nym_cli_commands::validator::mixnet::query::MixnetQueryCommands::Mixnodes(args) => { nym_cli_commands::validator::mixnet::query::query_all_mixnodes::query( args, - &create_query_client_with_validator_api(network_details)?, + &create_query_client_with_nym_api(network_details)?, ) .await } nym_cli_commands::validator::mixnet::query::MixnetQueryCommands::Gateways(args) => { nym_cli_commands::validator::mixnet::query::query_all_gateways::query( args, - &create_query_client_with_validator_api(network_details)?, + &create_query_client_with_nym_api(network_details)?, ) .await } diff --git a/tools/ts-rs-cli/Cargo.toml b/tools/ts-rs-cli/Cargo.toml index e6c3fa879e..c327083a04 100644 --- a/tools/ts-rs-cli/Cargo.toml +++ b/tools/ts-rs-cli/Cargo.toml @@ -13,7 +13,7 @@ walkdir = "2" validator-client = { path = "../../common/client-libs/validator-client", features = [ "nymd-client", "generate-ts" ] } -validator-api-requests = { path = "../../validator-api/validator-api-requests", features = ["generate-ts"] } +nym-api-requests = { path = "../../nym-api/nym-api-requests", features = ["generate-ts"] } mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract", features = [ "generate-ts" ] } vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract", features = [ "generate-ts" ] } nym-types = { path = "../../common/types", features = [ "generate-ts" ] } diff --git a/tools/ts-rs-cli/src/main.rs b/tools/ts-rs-cli/src/main.rs index 42217d4d8b..762dd4b03f 100644 --- a/tools/ts-rs-cli/src/main.rs +++ b/tools/ts-rs-cli/src/main.rs @@ -3,6 +3,11 @@ use mixnet_contract_common::{ Interval as ContractInterval, IntervalRewardParams, IntervalRewardingParamsUpdate, MixNode, MixNodeConfigUpdate, RewardedSetNodeStatus, RewardingParams, UnbondedMixnode, }; +use nym_api_requests::models::{ + GatewayCoreStatusResponse, InclusionProbabilityResponse, MixnodeCoreStatusResponse, + MixnodeStatus, MixnodeStatusResponse, RewardEstimationResponse, SelectionChance, + StakeSaturationResponse, +}; use nym_types::account::{Account, AccountEntry, AccountWithMnemonic, Balance}; use nym_types::currency::{CurrencyDenom, DecCoin}; use nym_types::delegation::{ @@ -27,11 +32,6 @@ use nym_wallet_types::network::Network; use nym_wallet_types::network_config::{Validator, ValidatorUrl, ValidatorUrls}; use std::path::Path; use ts_rs::TS; -use validator_api_requests::models::{ - GatewayCoreStatusResponse, InclusionProbabilityResponse, MixnodeCoreStatusResponse, - MixnodeStatus, MixnodeStatusResponse, RewardEstimationResponse, SelectionChance, - StakeSaturationResponse, -}; use vesting_contract_common::Period; use walkdir::WalkDir; @@ -112,7 +112,7 @@ fn main() { do_export!(VestingPeriod); do_export!(WrappedDelegationEvent); - // validator-api-requests + // nym-api-requests do_export!(MixnodeCoreStatusResponse); do_export!(GatewayCoreStatusResponse); do_export!(InclusionProbabilityResponse); From eb07ec85805f83989647b369ffada6fc2b5fb91b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Wed, 14 Dec 2022 17:13:00 +0100 Subject: [PATCH 06/21] client: sort out shutdown procedure and harmonize with socks5-client (#2695) * common/task: rename ShutdownNotifier to TaskManager * nym-client: return boxed error * nym-client: enable graceful shutdown * nym-client: task wait on shutdown to instead exit on closed channel * Fix build * Fix unused * changelog: update --- CHANGELOG.md | 1 + .../client-core/src/client/base_client/mod.rs | 48 +++++++------- .../src/client/cover_traffic_stream.rs | 2 +- clients/client-core/src/client/mix_traffic.rs | 7 +- .../acknowledgement_listener.rs | 4 +- .../action_controller.rs | 4 +- .../input_message_listener.rs | 4 +- .../acknowledgement_control/mod.rs | 2 +- .../retransmission_request_listener.rs | 4 +- .../sent_notification_listener.rs | 4 +- .../src/client/real_messages_control/mod.rs | 2 +- .../real_traffic_stream.rs | 6 +- .../sending_delay_controller.rs | 2 + .../client-core/src/client/received_buffer.rs | 28 ++++---- .../src/client/replies/reply_controller.rs | 4 +- .../src/client/replies/reply_storage/mod.rs | 2 +- .../src/client/topology_control.rs | 2 +- clients/native/src/client/mod.rs | 41 +++++++----- clients/native/src/commands/mod.rs | 5 +- clients/native/src/commands/run.rs | 8 ++- clients/native/src/main.rs | 5 +- clients/native/src/websocket/handler.rs | 66 ++++++++++++------- clients/native/src/websocket/listener.rs | 25 +++++-- clients/socks5/src/client/mod.rs | 16 +++-- clients/socks5/src/socks/client.rs | 6 +- clients/socks5/src/socks/mixnet_responses.rs | 6 +- clients/socks5/src/socks/server.rs | 6 +- clients/webassembly/src/client/mod.rs | 6 +- .../client-libs/gateway-client/src/client.rs | 8 +-- .../gateway-client/src/packet_router.rs | 6 +- .../gateway-client/src/socket_state.rs | 4 +- common/mixnode-common/src/verloc/listener.rs | 8 +-- common/mixnode-common/src/verloc/mod.rs | 6 +- common/mixnode-common/src/verloc/sender.rs | 6 +- .../src/connection_controller.rs | 6 +- .../proxy-helpers/src/proxy_runner/inbound.rs | 4 +- .../proxy-helpers/src/proxy_runner/mod.rs | 6 +- .../src/proxy_runner/outbound.rs | 4 +- common/task/src/lib.rs | 5 +- common/task/src/{shutdown.rs => manager.rs} | 64 ++++++++++-------- common/task/src/signal.rs | 6 +- common/task/src/spawn.rs | 4 +- .../src/country_statistics/distribution.rs | 6 +- .../src/country_statistics/geolocate.rs | 6 +- explorer-api/src/main.rs | 6 +- explorer-api/src/tasks.rs | 6 +- .../node/listener/connection_handler/mod.rs | 4 +- mixnode/src/node/listener/mod.rs | 6 +- mixnode/src/node/mod.rs | 14 ++-- mixnode/src/node/node_statistics.rs | 20 +++--- mixnode/src/node/packet_delayforwarder.rs | 10 +-- nym-api/src/coconut/dkg/controller.rs | 4 +- nym-api/src/contract_cache/mod.rs | 4 +- nym-api/src/epoch_operations/mod.rs | 9 +-- nym-api/src/main.rs | 6 +- nym-api/src/network_monitor/mod.rs | 4 +- .../monitor/gateways_pinger.rs | 4 +- nym-api/src/network_monitor/monitor/mod.rs | 4 +- .../src/network_monitor/monitor/receiver.rs | 4 +- nym-api/src/network_monitor/monitor/sender.rs | 10 +-- nym-api/src/node_status_api/cache.rs | 4 +- nym-api/src/node_status_api/uptime_updater.rs | 4 +- .../network-requester/src/connection.rs | 4 +- .../network-requester/src/core.rs | 10 +-- 64 files changed, 325 insertions(+), 277 deletions(-) rename common/task/src/{shutdown.rs => manager.rs} (89%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b66b2305c..a40671598e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ### Changed - all-binaries: improved error logging ([#2686]) +- native client: bring shutdown logic up to the same level as socks5-client [#2686]: https://github.com/nymtech/nym/pull/2686 diff --git a/clients/client-core/src/client/base_client/mod.rs b/clients/client-core/src/client/base_client/mod.rs index 6db0280019..807170cc84 100644 --- a/clients/client-core/src/client/base_client/mod.rs +++ b/clients/client-core/src/client/base_client/mod.rs @@ -36,19 +36,19 @@ use nymsphinx::addressing::nodes::NodeIdentity; use std::sync::Arc; use std::time::Duration; use tap::TapFallible; -use task::{ShutdownListener, ShutdownNotifier}; +use task::{TaskClient, TaskManager}; use url::Url; #[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))] pub mod non_wasm_helpers; pub struct ClientInput { - pub shared_lane_queue_lengths: LaneQueueLengths, pub connection_command_sender: ConnectionCommandSender, pub input_sender: InputMessageSender, } pub struct ClientOutput { + pub shared_lane_queue_lengths: LaneQueueLengths, pub received_buffer_request_sender: ReceivedBufferRequestSender, } @@ -127,8 +127,8 @@ where debug_config, disabled_credentials, nym_api_endpoints, - bandwidth_controller, reply_storage_backend, + bandwidth_controller, key_manager, } } @@ -151,7 +151,7 @@ where self_address: Recipient, topology_accessor: TopologyAccessor, mix_tx: BatchMixMessageSender, - shutdown: ShutdownListener, + shutdown: TaskClient, ) { info!("Starting loop cover traffic stream..."); @@ -185,7 +185,7 @@ where reply_controller_receiver: ReplyControllerReceiver, lane_queue_lengths: LaneQueueLengths, client_connection_rx: ConnectionCommandReceiver, - shutdown: ShutdownListener, + shutdown: TaskClient, ) { info!("Starting real traffic stream..."); @@ -212,7 +212,7 @@ where mixnet_receiver: MixnetMessageReceiver, reply_key_storage: SentReplyKeys, reply_controller_sender: ReplyControllerSender, - shutdown: ShutdownListener, + shutdown: TaskClient, ) { info!("Starting received messages buffer controller..."); ReceivedMessagesBufferController::new( @@ -229,7 +229,7 @@ where &mut self, mixnet_message_sender: MixnetMessageSender, ack_sender: AcknowledgementSender, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> Result> { let gateway_id = self.gateway_config.gateway_id.clone(); if gateway_id.is_empty() { @@ -284,7 +284,7 @@ where nym_api_urls: Vec, refresh_rate: Duration, topology_accessor: TopologyAccessor, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> Result<(), ClientCoreError> { let topology_refresher_config = TopologyRefresherConfig::new( nym_api_urls, @@ -317,7 +317,7 @@ where // requests? fn start_mix_traffic_controller( gateway_client: GatewayClient, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> BatchMixMessageSender { info!("Starting mix traffic controller..."); let (mix_traffic_controller, mix_tx) = MixTrafficController::new(gateway_client); @@ -327,7 +327,7 @@ where async fn setup_persistent_reply_storage( backend: B, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> Result> { let persistent_storage = PersistentReplyStorage::new(backend); let mem_store = persistent_storage @@ -367,7 +367,7 @@ where let shared_topology_accessor = TopologyAccessor::new(); // Shutdown notifier for signalling tasks to stop - let shutdown = ShutdownNotifier::default(); + let task_manager = TaskManager::default(); // channels responsible for dealing with reply-related fun let (reply_controller_sender, reply_controller_receiver) = @@ -378,18 +378,20 @@ where // the components are started in very specific order. Unless you know what you are doing, // do not change that. let gateway_client = self - .start_gateway_client(mixnet_messages_sender, ack_sender, shutdown.subscribe()) + .start_gateway_client(mixnet_messages_sender, ack_sender, task_manager.subscribe()) .await?; - let reply_storage = - Self::setup_persistent_reply_storage(self.reply_storage_backend, shutdown.subscribe()) - .await?; + let reply_storage = Self::setup_persistent_reply_storage( + self.reply_storage_backend, + task_manager.subscribe(), + ) + .await?; Self::start_topology_refresher( self.nym_api_endpoints.clone(), self.debug_config.topology_refresh_rate, shared_topology_accessor.clone(), - shutdown.subscribe(), + task_manager.subscribe(), ) .await?; @@ -399,7 +401,7 @@ where mixnet_messages_receiver, reply_storage.key_storage(), reply_controller_sender.clone(), - shutdown.subscribe(), + task_manager.subscribe(), ); // The sphinx_message_sender is the transmitter for any component generating sphinx packets @@ -407,7 +409,7 @@ where // traffic stream. // The MixTrafficController then sends the actual traffic let sphinx_message_sender = - Self::start_mix_traffic_controller(gateway_client, shutdown.subscribe()); + Self::start_mix_traffic_controller(gateway_client, task_manager.subscribe()); // Channels that the websocket listener can use to signal downstream to the real traffic // controller that connections are closed. @@ -439,7 +441,7 @@ where reply_controller_receiver, shared_lane_queue_lengths.clone(), client_connection_rx, - shutdown.subscribe(), + task_manager.subscribe(), ); if !self.debug_config.disable_loop_cover_traffic_stream { @@ -449,7 +451,7 @@ where self_address, shared_topology_accessor, sphinx_message_sender, - shutdown.subscribe(), + task_manager.subscribe(), ); } @@ -459,17 +461,17 @@ where Ok(BaseClient { client_input: ClientInputStatus::AwaitingProducer { client_input: ClientInput { - shared_lane_queue_lengths, connection_command_sender: client_connection_tx, input_sender, }, }, client_output: ClientOutputStatus::AwaitingConsumer { client_output: ClientOutput { + shared_lane_queue_lengths, received_buffer_request_sender, }, }, - shutdown_notifier: shutdown, + task_manager, }) } } @@ -478,5 +480,5 @@ pub struct BaseClient { pub client_input: ClientInputStatus, pub client_output: ClientOutputStatus, - pub shutdown_notifier: ShutdownNotifier, + pub task_manager: TaskManager, } diff --git a/clients/client-core/src/client/cover_traffic_stream.rs b/clients/client-core/src/client/cover_traffic_stream.rs index e3fd0ca197..a8ecad86b2 100644 --- a/clients/client-core/src/client/cover_traffic_stream.rs +++ b/clients/client-core/src/client/cover_traffic_stream.rs @@ -213,7 +213,7 @@ impl LoopCoverTrafficStream { tokio::task::yield_now().await; } - pub fn start_with_shutdown(mut self, mut shutdown: task::ShutdownListener) { + pub fn start_with_shutdown(mut self, mut shutdown: task::TaskClient) { // we should set initial delay only when we actually start the stream let sampled = sample_poisson_duration(&mut self.rng, self.average_cover_message_sending_delay); diff --git a/clients/client-core/src/client/mix_traffic.rs b/clients/client-core/src/client/mix_traffic.rs index ccba8f86ca..94944cb481 100644 --- a/clients/client-core/src/client/mix_traffic.rs +++ b/clients/client-core/src/client/mix_traffic.rs @@ -67,11 +67,11 @@ impl MixTrafficController { } } - pub fn start_with_shutdown(mut self, mut shutdown: task::ShutdownListener) { + pub fn start_with_shutdown(mut self, mut shutdown: task::TaskClient) { spawn_future(async move { debug!("Started MixTrafficController with graceful shutdown support"); - while !shutdown.is_shutdown() { + loop { tokio::select! { mix_packets = self.mix_rx.recv() => match mix_packets { Some(mix_packets) => { @@ -82,8 +82,9 @@ impl MixTrafficController { break; } }, - _ = shutdown.recv() => { + _ = shutdown.recv_with_delay() => { log::trace!("MixTrafficController: Received shutdown"); + break; } } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs index 95c431fd59..8febbfa85d 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs @@ -65,7 +65,7 @@ impl AcknowledgementListener { } } - pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { + pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) { debug!("Started AcknowledgementListener with graceful shutdown support"); while !shutdown.is_shutdown() { @@ -77,7 +77,7 @@ impl AcknowledgementListener { break; } }, - _ = shutdown.recv() => { + _ = shutdown.recv_with_delay() => { log::trace!("AcknowledgementListener: Received shutdown"); } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs index cb2e0cc7ca..c65592b2f6 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs @@ -249,7 +249,7 @@ impl ActionController { } } - pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { + pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) { debug!("Started ActionController with graceful shutdown support"); while !shutdown.is_shutdown() { @@ -270,7 +270,7 @@ impl ActionController { break; } }, - _ = shutdown.recv() => { + _ = shutdown.recv_with_delay() => { log::trace!("ActionController: Received shutdown"); } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs index cff6b6d719..f492de1aae 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs @@ -109,7 +109,7 @@ where }; } - pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { + pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) { debug!("Started InputMessageListener with graceful shutdown support"); while !shutdown.is_shutdown() { @@ -123,7 +123,7 @@ where break; } }, - _ = shutdown.recv() => { + _ = shutdown.recv_with_delay() => { log::trace!("InputMessageListener: Received shutdown"); } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs index 5587958f33..befc24b86a 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs @@ -249,7 +249,7 @@ where } } - pub(super) fn start_with_shutdown(self, shutdown: task::ShutdownListener) { + pub(super) fn start_with_shutdown(self, shutdown: task::TaskClient) { let mut acknowledgement_listener = self.acknowledgement_listener; let mut input_message_listener = self.input_message_listener; let mut retransmission_request_listener = self.retransmission_request_listener; diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs index b5c6e6a2a8..50a930b94e 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs @@ -137,7 +137,7 @@ where .await } - pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { + pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) { debug!("Started RetransmissionRequestListener with graceful shutdown support"); while !shutdown.is_shutdown() { @@ -149,7 +149,7 @@ where break; } }, - _ = shutdown.recv() => { + _ = shutdown.recv_with_delay() => { log::trace!("RetransmissionRequestListener: Received shutdown"); } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs index c273182d59..a931ce4962 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs @@ -37,7 +37,7 @@ impl SentNotificationListener { .unwrap(); } - pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { + pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) { debug!("Started SentNotificationListener with graceful shutdown support"); while !shutdown.is_shutdown() { @@ -51,7 +51,7 @@ impl SentNotificationListener { break; } }, - _ = shutdown.recv() => { + _ = shutdown.recv_with_delay() => { log::trace!("SentNotificationListener: Received shutdown"); } } diff --git a/clients/client-core/src/client/real_messages_control/mod.rs b/clients/client-core/src/client/real_messages_control/mod.rs index 8789cbdf6a..df04365c9b 100644 --- a/clients/client-core/src/client/real_messages_control/mod.rs +++ b/clients/client-core/src/client/real_messages_control/mod.rs @@ -263,7 +263,7 @@ impl RealMessagesController { } } - pub fn start_with_shutdown(self, shutdown: task::ShutdownListener) { + pub fn start_with_shutdown(self, shutdown: task::TaskClient) { let mut out_queue_control = self.out_queue_control; let ack_control = self.ack_control; let mut reply_control = self.reply_control; diff --git a/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs b/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs index ef1c03046d..a7d62910e5 100644 --- a/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs +++ b/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs @@ -469,7 +469,7 @@ where } #[cfg(not(target_arch = "wasm32"))] - fn log_status(&self, shutdown: &mut task::ShutdownListener) { + fn log_status(&self, shutdown: &mut task::TaskClient) { use crate::error::ClientCoreStatusMessage; let packets = self.transmission_buffer.total_size(); @@ -514,7 +514,7 @@ where } } - pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { + pub(super) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) { debug!("Started OutQueueControl with graceful shutdown support"); #[cfg(not(target_arch = "wasm32"))] @@ -525,7 +525,7 @@ where while !shutdown.is_shutdown() { tokio::select! { biased; - _ = shutdown.recv() => { + _ = shutdown.recv_with_delay() => { log::trace!("OutQueueControl: Received shutdown"); } _ = status_timer.tick() => { diff --git a/clients/client-core/src/client/real_messages_control/real_traffic_stream/sending_delay_controller.rs b/clients/client-core/src/client/real_messages_control/real_traffic_stream/sending_delay_controller.rs index 4ae2632b85..b7fdff2299 100644 --- a/clients/client-core/src/client/real_messages_control/real_traffic_stream/sending_delay_controller.rs +++ b/clients/client-core/src/client/real_messages_control/real_traffic_stream/sending_delay_controller.rs @@ -77,10 +77,12 @@ impl SendingDelayController { self.current_multiplier } + #[cfg(not(target_arch = "wasm32"))] pub(crate) fn min_multiplier(&self) -> u32 { self.lower_bound } + #[cfg(not(target_arch = "wasm32"))] pub(crate) fn max_multiplier(&self) -> u32 { self.upper_bound } diff --git a/clients/client-core/src/client/received_buffer.rs b/clients/client-core/src/client/received_buffer.rs index 2e7876ae62..afafec44ca 100644 --- a/clients/client-core/src/client/received_buffer.rs +++ b/clients/client-core/src/client/received_buffer.rs @@ -399,21 +399,20 @@ impl RequestReceiver { } } - async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { + async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) { debug!("Started RequestReceiver with graceful shutdown support"); while !shutdown.is_shutdown() { tokio::select! { biased; - _ = shutdown.recv() => { + _ = shutdown.recv_with_delay() => { log::trace!("RequestReceiver: Received shutdown"); } request = self.query_receiver.next() => { - match request { - Some(message) => self.handle_message(message).await, - None => { - log::trace!("RequestReceiver: Stopping since channel closed"); - break; - }, + if let Some(message) = request { + self.handle_message(message).await + } else { + log::trace!("RequestReceiver: Stopping since channel closed"); + break; } }, } @@ -439,20 +438,19 @@ impl FragmentedMessageReceiver { } } - async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { + async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) { debug!("Started FragmentedMessageReceiver with graceful shutdown support"); while !shutdown.is_shutdown() { tokio::select! { - new_messages = self.mixnet_packet_receiver.next() => match new_messages { - Some(new_messages) => { + new_messages = self.mixnet_packet_receiver.next() => { + if let Some(new_messages) = new_messages { self.received_buffer.handle_new_received(new_messages).await; - } - None => { + } else { log::trace!("FragmentedMessageReceiver: Stopping since channel closed"); break; } }, - _ = shutdown.recv() => { + _ = shutdown.recv_with_delay() => { log::trace!("FragmentedMessageReceiver: Received shutdown"); } } @@ -490,7 +488,7 @@ impl ReceivedMessagesBufferController { } } - pub fn start_with_shutdown(self, shutdown: task::ShutdownListener) { + pub fn start_with_shutdown(self, shutdown: task::TaskClient) { let mut fragmented_message_receiver = self.fragmented_message_receiver; let mut request_receiver = self.request_receiver; diff --git a/clients/client-core/src/client/replies/reply_controller.rs b/clients/client-core/src/client/replies/reply_controller.rs index 99687527f0..8716203734 100644 --- a/clients/client-core/src/client/replies/reply_controller.rs +++ b/clients/client-core/src/client/replies/reply_controller.rs @@ -891,7 +891,7 @@ where return gloo_timers::future::IntervalStream::new(polling_rate.as_millis() as u32); } - pub(crate) async fn run_with_shutdown(&mut self, mut shutdown: task::ShutdownListener) { + pub(crate) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) { debug!("Started ReplyController with graceful shutdown support"); let polling_rate = Duration::from_secs(5); @@ -904,7 +904,7 @@ where while !shutdown.is_shutdown() { tokio::select! { biased; - _ = shutdown.recv() => { + _ = shutdown.recv_with_delay() => { log::trace!("ReplyController: Received shutdown"); }, req = self.request_receiver.next() => match req { diff --git a/clients/client-core/src/client/replies/reply_storage/mod.rs b/clients/client-core/src/client/replies/reply_storage/mod.rs index 83c0e0e34f..c74ad2bb6b 100644 --- a/clients/client-core/src/client/replies/reply_storage/mod.rs +++ b/clients/client-core/src/client/replies/reply_storage/mod.rs @@ -37,7 +37,7 @@ where pub async fn flush_on_shutdown( mut self, mem_state: CombinedReplyStorage, - mut shutdown: task::ShutdownListener, + mut shutdown: task::TaskClient, ) { use log::{debug, error, info, warn}; diff --git a/clients/client-core/src/client/topology_control.rs b/clients/client-core/src/client/topology_control.rs index 897d6a0e3b..c51fd350cd 100644 --- a/clients/client-core/src/client/topology_control.rs +++ b/clients/client-core/src/client/topology_control.rs @@ -304,7 +304,7 @@ impl TopologyRefresher { self.topology_accessor.ensure_is_routable().await } - pub fn start_with_shutdown(mut self, mut shutdown: task::ShutdownListener) { + pub fn start_with_shutdown(mut self, mut shutdown: task::TaskClient) { spawn_future(async move { debug!("Started TopologyRefresher with graceful shutdown support"); diff --git a/clients/native/src/client/mod.rs b/clients/native/src/client/mod.rs index 0d61b502ab..1a90c48b6f 100644 --- a/clients/native/src/client/mod.rs +++ b/clients/native/src/client/mod.rs @@ -1,6 +1,8 @@ // Copyright 2021-2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use std::error::Error; + use crate::client::config::Config; use crate::error::ClientError; use crate::websocket; @@ -18,7 +20,7 @@ use log::*; use nymsphinx::addressing::clients::Recipient; use nymsphinx::anonymous_replies::requests::AnonymousSenderTag; use nymsphinx::receiver::ReconstructedMessage; -use task::{wait_for_signal, ShutdownNotifier}; +use task::TaskManager; pub(crate) mod config; @@ -85,16 +87,19 @@ impl SocketClient { client_input: ClientInput, client_output: ClientOutput, self_address: Recipient, + shutdown: task::TaskClient, ) { info!("Starting websocket listener..."); let ClientInput { - shared_lane_queue_lengths, connection_command_sender, input_sender, } = client_input; - let received_buffer_request_sender = client_output.received_buffer_request_sender; + let ClientOutput { + shared_lane_queue_lengths, + received_buffer_request_sender, + } = client_output; let websocket_handler = websocket::Handler::new( input_sender, @@ -104,32 +109,26 @@ impl SocketClient { shared_lane_queue_lengths, ); - websocket::Listener::new(config.get_listening_port()).start(websocket_handler); + websocket::Listener::new(config.get_listening_port()).start(websocket_handler, shutdown); } /// blocking version of `start_socket` method. Will run forever (or until SIGINT is sent) - pub async fn run_socket_forever(self) -> Result<(), ClientError> { + pub async fn run_socket_forever(self) -> Result<(), Box> { let mut shutdown = self.start_socket().await?; - wait_for_signal().await; - println!( - "Received signal - the client will terminate now (threads are not yet nicely stopped, if you see stack traces that's alright)." - ); + let res = task::wait_for_signal_and_error(&mut shutdown).await; log::info!("Sending shutdown"); shutdown.signal_shutdown().ok(); - // Some of these components have shutdown signalling implemented as part of socks5 work, - // but since it's not fully implemented (yet) for all the components of the native client, - // we don't try to wait and instead just stop immediately. log::info!("Waiting for tasks to finish... (Press ctrl-c to force)"); shutdown.wait_for_shutdown().await; log::info!("Stopping nym-client"); - Ok(()) + res } - pub async fn start_socket(self) -> Result { + pub async fn start_socket(self) -> Result { if !self.config.get_socket_type().is_websocket() { return Err(ClientError::InvalidSocketMode); } @@ -150,12 +149,18 @@ impl SocketClient { let client_input = started_client.client_input.register_producer(); let client_output = started_client.client_output.register_consumer(); - Self::start_websocket_listener(&self.config, client_input, client_output, self_address); + Self::start_websocket_listener( + &self.config, + client_input, + client_output, + self_address, + started_client.task_manager.subscribe(), + ); info!("Client startup finished!"); info!("The address of this client is: {}", self_address); - Ok(started_client.shutdown_notifier) + Ok(started_client.task_manager) } pub async fn start_direct(self) -> Result { @@ -192,7 +197,7 @@ impl SocketClient { Ok(DirectClient { client_input, reconstructed_receiver, - _shutdown_notifier: started_client.shutdown_notifier, + _shutdown_notifier: started_client.task_manager, }) } } @@ -202,7 +207,7 @@ pub struct DirectClient { reconstructed_receiver: ReconstructedMessagesReceiver, // we need to keep reference to this guy otherwise things will start dropping - _shutdown_notifier: ShutdownNotifier, + _shutdown_notifier: TaskManager, } impl DirectClient { diff --git a/clients/native/src/commands/mod.rs b/clients/native/src/commands/mod.rs index 4ad9d414dc..cf40470556 100644 --- a/clients/native/src/commands/mod.rs +++ b/clients/native/src/commands/mod.rs @@ -1,8 +1,9 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use std::error::Error; + use crate::client::config::{Config, SocketType}; -use crate::error::ClientError; use clap::CommandFactory; use clap::{Parser, Subcommand}; use completions::{fig_generate, ArgShell}; @@ -86,7 +87,7 @@ pub(crate) struct OverrideConfig { enabled_credentials_mode: bool, } -pub(crate) async fn execute(args: &Cli) -> Result<(), ClientError> { +pub(crate) async fn execute(args: &Cli) -> Result<(), Box> { let bin_name = "nym-native-client"; match &args.command { diff --git a/clients/native/src/commands/run.rs b/clients/native/src/commands/run.rs index d5c7eccbdb..3fffa60e18 100644 --- a/clients/native/src/commands/run.rs +++ b/clients/native/src/commands/run.rs @@ -1,6 +1,8 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use std::error::Error; + use crate::{ client::{config::Config, SocketClient}, commands::{override_config, OverrideConfig}, @@ -89,14 +91,14 @@ fn version_check(cfg: &Config) -> bool { } } -pub(crate) async fn execute(args: &Run) -> Result<(), ClientError> { +pub(crate) async fn execute(args: &Run) -> Result<(), Box> { let id = &args.id; let mut config = match Config::load_from_file(Some(id)) { Ok(cfg) => cfg, Err(err) => { error!("Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})", id); - return Err(ClientError::FailedToLoadConfig(id.to_string())); + return Err(Box::new(ClientError::FailedToLoadConfig(id.to_string()))); } }; @@ -105,7 +107,7 @@ pub(crate) async fn execute(args: &Run) -> Result<(), ClientError> { if !version_check(&config) { error!("failed the local version check"); - return Err(ClientError::FailedLocalVersionCheck); + return Err(Box::new(ClientError::FailedLocalVersionCheck)); } SocketClient::new(config).run_socket_forever().await diff --git a/clients/native/src/main.rs b/clients/native/src/main.rs index 00529494e7..972eef1925 100644 --- a/clients/native/src/main.rs +++ b/clients/native/src/main.rs @@ -1,8 +1,9 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use std::error::Error; + use clap::{crate_version, Parser}; -use error::ClientError; use logging::setup_logging; use network_defaults::setup_env; @@ -12,7 +13,7 @@ pub mod error; pub mod websocket; #[tokio::main] -async fn main() -> Result<(), ClientError> { +async fn main() -> Result<(), Box> { setup_logging(); println!("{}", banner()); diff --git a/clients/native/src/websocket/handler.rs b/clients/native/src/websocket/handler.rs index 476eb0a567..f35058485e 100644 --- a/clients/native/src/websocket/handler.rs +++ b/clients/native/src/websocket/handler.rs @@ -43,29 +43,16 @@ pub(crate) struct Handler { socket: Option>, received_response_type: ReceivedResponseType, lane_queue_lengths: LaneQueueLengths, -} - -// clone is used to use handler on a new connection, which initially is `None` -impl Clone for Handler { - fn clone(&self) -> Self { - Handler { - msg_input: self.msg_input.clone(), - client_connection_tx: self.client_connection_tx.clone(), - buffer_requester: self.buffer_requester.clone(), - self_full_address: self.self_full_address, - socket: None, - received_response_type: Default::default(), - lane_queue_lengths: self.lane_queue_lengths.clone(), - } - } + is_active: bool, } impl Drop for Handler { fn drop(&mut self) { - if self - .buffer_requester - .unbounded_send(ReceivedBufferMessage::ReceiverDisconnect) - .is_err() + if self.is_active + && self + .buffer_requester + .unbounded_send(ReceivedBufferMessage::ReceiverDisconnect) + .is_err() { error!("we failed to disconnect the receiver from the buffer! presumably the shutdown procedure has been initiated!") } @@ -88,6 +75,22 @@ impl Handler { socket: None, received_response_type: Default::default(), lane_queue_lengths, + is_active: false, + } + } + + // Used to use handler on a new connection, which initially is `None` + // TODO: make sure we only ever have one active handler + pub fn create_active_handler(&self) -> Self { + Handler { + msg_input: self.msg_input.clone(), + client_connection_tx: self.client_connection_tx.clone(), + buffer_requester: self.buffer_requester.clone(), + self_full_address: self.self_full_address, + socket: None, + received_response_type: Default::default(), + lane_queue_lengths: self.lane_queue_lengths.clone(), + is_active: true, } } @@ -362,8 +365,12 @@ impl Handler { } } - async fn listen_for_requests(&mut self, mut msg_receiver: ReconstructedMessagesReceiver) { - loop { + async fn listen_for_requests( + &mut self, + mut msg_receiver: ReconstructedMessagesReceiver, + mut task_client: task::TaskClient, + ) { + while !task_client.is_shutdown() { tokio::select! { // we can either get a client request from the websocket socket_msg = self.next_websocket_request() => { @@ -402,12 +409,24 @@ impl Handler { break; } } + _ = task_client.recv() => { + log::trace!("Websocket handler: Received shutdown"); + } } } + log::debug!("Websocket handler: Exiting"); } // consume self to make sure `drop` is called after this is done - pub(crate) async fn handle_connection(mut self, socket: TcpStream) { + pub(crate) async fn handle_connection( + mut self, + socket: TcpStream, + mut task_client: task::TaskClient, + ) { + // We don't want a crash in the connection handler to trigger a shutdown of the whole + // process. + task_client.mark_as_success(); + let ws_stream = match accept_async(socket).await { Ok(ws_stream) => ws_stream, Err(err) => { @@ -426,7 +445,8 @@ impl Handler { )) .expect("the buffer request failed!"); - self.listen_for_requests(reconstructed_receiver).await; + self.listen_for_requests(reconstructed_receiver, task_client) + .await; } } diff --git a/clients/native/src/websocket/listener.rs b/clients/native/src/websocket/listener.rs index cf9c7cfa65..aef9150b43 100644 --- a/clients/native/src/websocket/listener.rs +++ b/clients/native/src/websocket/listener.rs @@ -32,7 +32,7 @@ impl Listener { } } - pub(crate) async fn run(&mut self, handler: Handler) { + pub(crate) async fn run(&mut self, handler: Handler, mut task_client: task::TaskClient) { let tcp_listener = match tokio::net::TcpListener::bind(self.address).await { Ok(listener) => listener, Err(err) => { @@ -45,10 +45,23 @@ impl Listener { loop { tokio::select! { + // When the handler finishes we check if shutdown is signalled _ = notify.notified() => { + if task_client.is_shutdown() { + log::trace!("Websocket listener: detected shutdown after connection closed"); + break; + } // our connection terminated - we are open to a new one now! self.state = State::AwaitingConnection; } + // ... but when there is no connected client at the time of shutdown being + // signalled, we handle it here. + _ = task_client.recv() => { + if !self.state.is_connected() { + log::trace!("Not connected: shutting down"); + break; + } + } new_conn = tcp_listener.accept() => { match new_conn { Ok((mut socket, remote_addr)) => { @@ -70,9 +83,10 @@ impl Listener { // it's done so that any new connections to this listener could be rejected rather than left // hanging because the executor doesn't come back here let notify_clone = Arc::clone(¬ify); - let fresh_handler = handler.clone(); + let fresh_handler = handler.create_active_handler(); + let task_client_handler = task_client.clone(); tokio::spawn(async move { - fresh_handler.handle_connection(socket).await; + fresh_handler.handle_connection(socket, task_client_handler).await; notify_clone.notify_one(); }); self.state = State::Connected; @@ -83,11 +97,12 @@ impl Listener { } } } + log::debug!("Websocket listener: Exiting"); } - pub(crate) fn start(mut self, handler: Handler) -> JoinHandle<()> { + pub(crate) fn start(mut self, handler: Handler, shutdown: task::TaskClient) -> JoinHandle<()> { info!("Running websocket on {:?}", self.address.to_string()); - tokio::spawn(async move { self.run(handler).await }) + tokio::spawn(async move { self.run(handler, shutdown).await }) } } diff --git a/clients/socks5/src/client/mod.rs b/clients/socks5/src/client/mod.rs index 45c9ffad7f..2f62354a01 100644 --- a/clients/socks5/src/client/mod.rs +++ b/clients/socks5/src/client/mod.rs @@ -19,7 +19,7 @@ use gateway_client::bandwidth::BandwidthController; use log::*; use nymsphinx::addressing::clients::Recipient; use std::error::Error; -use task::{wait_for_signal_and_error, ShutdownListener, ShutdownNotifier}; +use task::{wait_for_signal_and_error, TaskClient, TaskManager}; pub mod config; @@ -96,19 +96,21 @@ impl NymClient { client_input: ClientInput, client_output: ClientOutput, self_address: Recipient, - shutdown: ShutdownListener, + shutdown: TaskClient, ) { info!("Starting socks5 listener..."); let auth_methods = vec![AuthenticationMethods::NoAuth as u8]; let allowed_users: Vec = Vec::new(); let ClientInput { - shared_lane_queue_lengths, connection_command_sender, input_sender, } = client_input; - let received_buffer_request_sender = client_output.received_buffer_request_sender; + let ClientOutput { + shared_lane_queue_lengths, + received_buffer_request_sender, + } = client_output; let authenticator = Authenticator::new(auth_methods, allowed_users); let mut sphinx_socks = SphinxSocksServer::new( @@ -200,7 +202,7 @@ impl NymClient { res } - pub async fn start(self) -> Result { + pub async fn start(self) -> Result { let base_builder = BaseClientBuilder::new_from_base_config( self.config.get_base(), self.key_manager, @@ -222,12 +224,12 @@ impl NymClient { client_input, client_output, self_address, - started_client.shutdown_notifier.subscribe(), + started_client.task_manager.subscribe(), ); info!("Client startup finished!"); info!("The address of this client is: {}", self_address); - Ok(started_client.shutdown_notifier) + Ok(started_client.task_manager) } } diff --git a/clients/socks5/src/socks/client.rs b/clients/socks5/src/socks/client.rs index e5a8fc9d56..ff7caa1b6b 100644 --- a/clients/socks5/src/socks/client.rs +++ b/clients/socks5/src/socks/client.rs @@ -20,7 +20,7 @@ use socks5_requests::{ConnectionId, Message, RemoteAddress, Request}; use std::io; use std::net::SocketAddr; use std::pin::Pin; -use task::ShutdownListener; +use task::TaskClient; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}; use tokio::{self, net::TcpStream}; @@ -164,7 +164,7 @@ pub(crate) struct SocksClient { self_address: Recipient, started_proxy: bool, lane_queue_lengths: LaneQueueLengths, - shutdown_listener: ShutdownListener, + shutdown_listener: TaskClient, } impl Drop for SocksClient { @@ -190,7 +190,7 @@ impl SocksClient { controller_sender: ControllerSender, self_address: &Recipient, lane_queue_lengths: LaneQueueLengths, - mut shutdown_listener: ShutdownListener, + mut shutdown_listener: TaskClient, ) -> Self { // If this task fails and exits, we don't want to send shutdown signal shutdown_listener.mark_as_success(); diff --git a/clients/socks5/src/socks/mixnet_responses.rs b/clients/socks5/src/socks/mixnet_responses.rs index d4fb8fd544..97835340df 100644 --- a/clients/socks5/src/socks/mixnet_responses.rs +++ b/clients/socks5/src/socks/mixnet_responses.rs @@ -9,13 +9,13 @@ use client_core::client::received_buffer::{ReceivedBufferMessage, ReceivedBuffer use nymsphinx::receiver::ReconstructedMessage; use proxy_helpers::connection_controller::{ControllerCommand, ControllerSender}; use socks5_requests::Message; -use task::ShutdownListener; +use task::TaskClient; pub(crate) struct MixnetResponseListener { buffer_requester: ReceivedBufferRequestSender, mix_response_receiver: ReconstructedMessagesReceiver, controller_sender: ControllerSender, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl Drop for MixnetResponseListener { @@ -37,7 +37,7 @@ impl MixnetResponseListener { pub(crate) fn new( buffer_requester: ReceivedBufferRequestSender, controller_sender: ControllerSender, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> Self { let (mix_response_sender, mix_response_receiver) = mpsc::unbounded(); buffer_requester diff --git a/clients/socks5/src/socks/server.rs b/clients/socks5/src/socks/server.rs index a7e0a3c0e3..0b193dc9d4 100644 --- a/clients/socks5/src/socks/server.rs +++ b/clients/socks5/src/socks/server.rs @@ -13,7 +13,7 @@ use nymsphinx::addressing::clients::Recipient; use proxy_helpers::connection_controller::{BroadcastActiveConnections, Controller}; use std::net::SocketAddr; use tap::TapFallible; -use task::ShutdownListener; +use task::TaskClient; use tokio::net::TcpListener; /// A Socks5 server that listens for connections. @@ -24,7 +24,7 @@ pub struct SphinxSocksServer { self_address: Recipient, client_config: client::Config, lane_queue_lengths: LaneQueueLengths, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl SphinxSocksServer { @@ -36,7 +36,7 @@ impl SphinxSocksServer { self_address: Recipient, lane_queue_lengths: LaneQueueLengths, client_config: client::Config, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> Self { // hardcode ip as we (presumably) ONLY want to listen locally. If we change it, we can // just modify the config diff --git a/clients/webassembly/src/client/mod.rs b/clients/webassembly/src/client/mod.rs index 9c9f20b2c6..bd9ceab576 100644 --- a/clients/webassembly/src/client/mod.rs +++ b/clients/webassembly/src/client/mod.rs @@ -14,7 +14,7 @@ use nymsphinx::addressing::clients::Recipient; use nymsphinx::anonymous_replies::requests::AnonymousSenderTag; use rand::rngs::OsRng; use std::sync::Arc; -use task::ShutdownNotifier; +use task::TaskManager; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; use wasm_utils::{console_error, console_log}; @@ -30,7 +30,7 @@ pub struct NymClient { // even though we don't use graceful shutdowns, other components rely on existence of this struct // and if it's dropped, everything will start going offline - _shutdown: ShutdownNotifier, + _task_manager: TaskManager, } #[wasm_bindgen] @@ -121,7 +121,7 @@ impl NymClientBuilder { Ok(JsValue::from(NymClient { self_address, client_input: Arc::new(client_input), - _shutdown: started_client.shutdown_notifier, + _task_manager: started_client.task_manager, })) }) } diff --git a/common/client-libs/gateway-client/src/client.rs b/common/client-libs/gateway-client/src/client.rs index bb6fe0bbd1..23cae7e4a6 100644 --- a/common/client-libs/gateway-client/src/client.rs +++ b/common/client-libs/gateway-client/src/client.rs @@ -22,7 +22,7 @@ use rand::rngs::OsRng; use std::convert::TryFrom; use std::sync::Arc; use std::time::Duration; -use task::ShutdownListener; +use task::TaskClient; use tungstenite::protocol::Message; #[cfg(feature = "coconut")] @@ -67,7 +67,7 @@ pub struct GatewayClient { reconnection_backoff: Duration, /// Listen to shutdown messages. - shutdown: ShutdownListener, + shutdown: TaskClient, } impl GatewayClient { @@ -83,7 +83,7 @@ impl GatewayClient { ack_sender: AcknowledgementSender, response_timeout_duration: Duration, bandwidth_controller: Option>, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> Self { GatewayClient { authenticated: false, @@ -135,7 +135,7 @@ impl GatewayClient { // perfectly fine here, because it's not meant to be used let (ack_tx, _) = mpsc::unbounded(); let (mix_tx, _) = mpsc::unbounded(); - let shutdown = ShutdownListener::dummy(); + let shutdown = TaskClient::dummy(); let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone()); GatewayClient { diff --git a/common/client-libs/gateway-client/src/packet_router.rs b/common/client-libs/gateway-client/src/packet_router.rs index c64fbf92f8..daeac0e548 100644 --- a/common/client-libs/gateway-client/src/packet_router.rs +++ b/common/client-libs/gateway-client/src/packet_router.rs @@ -9,7 +9,7 @@ use futures::channel::mpsc; use log::*; use nymsphinx::addressing::nodes::MAX_NODE_ADDRESS_UNPADDED_LEN; use nymsphinx::params::packet_sizes::PacketSize; -use task::ShutdownListener; +use task::TaskClient; pub type MixnetMessageSender = mpsc::UnboundedSender>>; pub type MixnetMessageReceiver = mpsc::UnboundedReceiver>>; @@ -21,14 +21,14 @@ pub type AcknowledgementReceiver = mpsc::UnboundedReceiver>>; pub struct PacketRouter { ack_sender: AcknowledgementSender, mixnet_message_sender: MixnetMessageSender, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl PacketRouter { pub fn new( ack_sender: AcknowledgementSender, mixnet_message_sender: MixnetMessageSender, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> Self { PacketRouter { ack_sender, diff --git a/common/client-libs/gateway-client/src/socket_state.rs b/common/client-libs/gateway-client/src/socket_state.rs index 8c66b20906..2bedf1e8ed 100644 --- a/common/client-libs/gateway-client/src/socket_state.rs +++ b/common/client-libs/gateway-client/src/socket_state.rs @@ -10,7 +10,7 @@ use futures::{SinkExt, StreamExt}; use gateway_requests::registration::handshake::SharedKeys; use log::*; use std::sync::Arc; -use task::ShutdownListener; +use task::TaskClient; use tungstenite::Message; #[cfg(not(target_arch = "wasm32"))] @@ -84,7 +84,7 @@ impl PartiallyDelegated { conn: WsConn, packet_router: PacketRouter, shared_key: Arc, - mut shutdown: ShutdownListener, + mut shutdown: TaskClient, ) -> Self { // when called for, it NEEDS TO yield back the stream so that we could merge it and // read control request responses. diff --git a/common/mixnode-common/src/verloc/listener.rs b/common/mixnode-common/src/verloc/listener.rs index 537ec3aad5..812358e330 100644 --- a/common/mixnode-common/src/verloc/listener.rs +++ b/common/mixnode-common/src/verloc/listener.rs @@ -11,7 +11,7 @@ use std::fmt::{Display, Formatter}; use std::net::SocketAddr; use std::sync::Arc; use std::{fmt, io, process}; -use task::ShutdownListener; +use task::TaskClient; use tokio::io::AsyncWriteExt; use tokio::net::{TcpListener, TcpStream}; use tokio_util::codec::{Decoder, Encoder, Framed}; @@ -19,14 +19,14 @@ use tokio_util::codec::{Decoder, Encoder, Framed}; pub(crate) struct PacketListener { address: SocketAddr, connection_handler: Arc, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl PacketListener { pub(crate) fn new( address: SocketAddr, identity: Arc, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> Self { PacketListener { address, @@ -91,7 +91,7 @@ impl ConnectionHandler { self: Arc, conn: TcpStream, remote: SocketAddr, - mut shutdown_listener: ShutdownListener, + mut shutdown_listener: TaskClient, ) { debug!("Starting connection handler for {:?}", remote); diff --git a/common/mixnode-common/src/verloc/mod.rs b/common/mixnode-common/src/verloc/mod.rs index fc7e19332a..21053dd7cc 100644 --- a/common/mixnode-common/src/verloc/mod.rs +++ b/common/mixnode-common/src/verloc/mod.rs @@ -12,7 +12,7 @@ use rand::thread_rng; use std::net::{SocketAddr, ToSocketAddrs}; use std::sync::Arc; use std::time::Duration; -use task::ShutdownListener; +use task::TaskClient; use tokio::task::JoinHandle; use tokio::time::sleep; use url::Url; @@ -168,7 +168,7 @@ pub struct VerlocMeasurer { config: Config, packet_sender: Arc, packet_listener: Arc, - shutdown_listener: ShutdownListener, + shutdown_listener: TaskClient, currently_used_api: usize, @@ -184,7 +184,7 @@ impl VerlocMeasurer { pub fn new( mut config: Config, identity: Arc, - shutdown_listener: ShutdownListener, + shutdown_listener: TaskClient, ) -> Self { config.nym_api_urls.shuffle(&mut thread_rng()); diff --git a/common/mixnode-common/src/verloc/sender.rs b/common/mixnode-common/src/verloc/sender.rs index bed34f4474..91f7ee9974 100644 --- a/common/mixnode-common/src/verloc/sender.rs +++ b/common/mixnode-common/src/verloc/sender.rs @@ -11,7 +11,7 @@ use std::net::SocketAddr; use std::sync::Arc; use std::time::Duration; use std::{fmt, io}; -use task::ShutdownListener; +use task::TaskClient; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::TcpStream; use tokio::time::sleep; @@ -45,7 +45,7 @@ pub(crate) struct PacketSender { packet_timeout: Duration, connection_timeout: Duration, delay_between_packets: Duration, - shutdown_listener: ShutdownListener, + shutdown_listener: TaskClient, } impl PacketSender { @@ -55,7 +55,7 @@ impl PacketSender { packet_timeout: Duration, connection_timeout: Duration, delay_between_packets: Duration, - shutdown_listener: ShutdownListener, + shutdown_listener: TaskClient, ) -> Self { PacketSender { identity, diff --git a/common/socks5/proxy-helpers/src/connection_controller.rs b/common/socks5/proxy-helpers/src/connection_controller.rs index d7e2645190..66c8b94a7a 100644 --- a/common/socks5/proxy-helpers/src/connection_controller.rs +++ b/common/socks5/proxy-helpers/src/connection_controller.rs @@ -11,7 +11,7 @@ use std::{ collections::{HashMap, HashSet}, time::Duration, }; -use task::ShutdownListener; +use task::TaskClient; use tokio::time; /// A generic message produced after reading from a socket/connection. It includes data that was @@ -98,14 +98,14 @@ pub struct Controller { // un-order messages. Note we don't ever expect to have more than 1-2 messages per connection here pending_messages: HashMap, bool)>>, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl Controller { pub fn new( client_connection_tx: ConnectionCommandSender, broadcast_connections: BroadcastActiveConnections, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> (Self, ControllerSender) { let (sender, receiver) = mpsc::unbounded(); ( diff --git a/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs b/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs index b6688657de..2065f7770b 100644 --- a/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs +++ b/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs @@ -15,7 +15,7 @@ use socks5_requests::ConnectionId; use std::fmt::Debug; use std::time::Duration; use std::{io, sync::Arc}; -use task::ShutdownListener; +use task::TaskClient; use tokio::select; use tokio::{net::tcp::OwnedReadHalf, sync::Notify, time::sleep}; @@ -170,7 +170,7 @@ pub(super) async fn run_inbound( adapter_fn: F, shutdown_notify: Arc, lane_queue_lengths: Option, - mut shutdown_listener: ShutdownListener, + mut shutdown_listener: TaskClient, ) -> OwnedReadHalf where F: Fn(ConnectionId, Vec, bool) -> S + Send + 'static, diff --git a/common/socks5/proxy-helpers/src/proxy_runner/mod.rs b/common/socks5/proxy-helpers/src/proxy_runner/mod.rs index defcbf4f5f..a87ada287e 100644 --- a/common/socks5/proxy-helpers/src/proxy_runner/mod.rs +++ b/common/socks5/proxy-helpers/src/proxy_runner/mod.rs @@ -6,7 +6,7 @@ use client_connections::LaneQueueLengths; use socks5_requests::ConnectionId; use std::fmt::Debug; use std::{sync::Arc, time::Duration}; -use task::ShutdownListener; +use task::TaskClient; use tokio::{net::TcpStream, sync::Notify}; mod inbound; @@ -50,7 +50,7 @@ pub struct ProxyRunner { lane_queue_lengths: Option, // Listens to shutdown commands from higher up - shutdown_listener: ShutdownListener, + shutdown_listener: TaskClient, } impl ProxyRunner @@ -66,7 +66,7 @@ where mix_sender: MixProxySender, connection_id: ConnectionId, lane_queue_lengths: Option, - shutdown_listener: ShutdownListener, + shutdown_listener: TaskClient, ) -> Self { ProxyRunner { mix_receiver: Some(mix_receiver), diff --git a/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs b/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs index f6c713e948..ed7f8d74c6 100644 --- a/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs +++ b/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs @@ -8,7 +8,7 @@ use futures::StreamExt; use log::*; use socks5_requests::ConnectionId; use std::{sync::Arc, time::Duration}; -use task::ShutdownListener; +use task::TaskClient; use tokio::io::AsyncWriteExt; use tokio::select; use tokio::{net::tcp::OwnedWriteHalf, sync::Notify, time::sleep, time::Instant}; @@ -51,7 +51,7 @@ pub(super) async fn run_outbound( mut mix_receiver: ConnectionReceiver, connection_id: ConnectionId, shutdown_notify: Arc, - mut shutdown_listener: ShutdownListener, + mut shutdown_listener: TaskClient, ) -> (OwnedWriteHalf, ConnectionReceiver) { let shutdown_future = shutdown_notify.notified().then(|_| sleep(SHUTDOWN_TIMEOUT)); tokio::pin!(shutdown_future); diff --git a/common/task/src/lib.rs b/common/task/src/lib.rs index 5d3d0ea2f5..7ac5ab8431 100644 --- a/common/task/src/lib.rs +++ b/common/task/src/lib.rs @@ -1,13 +1,12 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -pub mod shutdown; +pub mod manager; #[cfg(not(target_arch = "wasm32"))] pub mod signal; pub mod spawn; -// WIP(JON): those both need to be public? -pub use shutdown::{ShutdownListener, ShutdownNotifier, StatusReceiver, StatusSender}; +pub use manager::{StatusReceiver, StatusSender, TaskClient, TaskManager}; #[cfg(not(target_arch = "wasm32"))] pub use signal::{wait_for_signal, wait_for_signal_and_error}; diff --git a/common/task/src/shutdown.rs b/common/task/src/manager.rs similarity index 89% rename from common/task/src/shutdown.rs rename to common/task/src/manager.rs index 4fe7a22bdd..3729d317a9 100644 --- a/common/task/src/shutdown.rs +++ b/common/task/src/manager.rs @@ -14,7 +14,6 @@ use tokio::{ const DEFAULT_SHUTDOWN_TIMER_SECS: u64 = 5; -// WIP(JON): can these be from futures channel too? pub(crate) type SentError = Box; type ErrorSender = mpsc::UnboundedSender; type ErrorReceiver = mpsc::UnboundedReceiver; @@ -29,9 +28,10 @@ enum TaskError { UnexpectedHalt, } -/// Used to notify other tasks to gracefully shutdown +/// Listens to status and error messages from tasks, as well as notifying them to gracefully +/// shutdown. Keeps track of if task stop unexpectedly, such as in a panic. #[derive(Debug)] -pub struct ShutdownNotifier { +pub struct TaskManager { // These channels have the dual purpose of signalling it's time to shutdown, but also to keep // track of which tasks we are still waiting for. notify_tx: watch::Sender<()>, @@ -55,7 +55,7 @@ pub struct ShutdownNotifier { task_status_rx: Option, } -impl Default for ShutdownNotifier { +impl Default for TaskManager { fn default() -> Self { let (notify_tx, notify_rx) = watch::channel(()); let (task_halt_tx, task_halt_rx) = mpsc::unbounded_channel(); @@ -77,11 +77,7 @@ impl Default for ShutdownNotifier { } } -impl ShutdownNotifier { - pub fn take_task_status_rx(&mut self) -> Option { - self.task_status_rx.take() - } - +impl TaskManager { pub fn new(shutdown_timer_secs: u64) -> Self { Self { shutdown_timer_secs, @@ -89,8 +85,8 @@ impl ShutdownNotifier { } } - pub fn subscribe(&self) -> ShutdownListener { - ShutdownListener::new( + pub fn subscribe(&self) -> TaskClient { + TaskClient::new( self.notify_rx .as_ref() .expect("Unable to subscribe to shutdown notifier that is already shutdown") @@ -173,9 +169,10 @@ impl ShutdownNotifier { } } -/// Listen for shutdown notifications +/// Listen for shutdown notifications, and can send error and status messages back to the +/// `TaskManager` #[derive(Clone, Debug)] -pub struct ShutdownListener { +pub struct TaskClient { // If a shutdown notification has been registered shutdown: bool, @@ -193,10 +190,10 @@ pub struct ShutdownListener { status_msg: StatusSender, // The current operating mode - mode: ShutdownListenerMode, + mode: ClientOperatingMode, } -impl ShutdownListener { +impl TaskClient { #[cfg(not(target_arch = "wasm32"))] const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5); @@ -205,31 +202,31 @@ impl ShutdownListener { return_error: ErrorSender, drop_error: ErrorSender, status_msg: StatusSender, - ) -> ShutdownListener { - ShutdownListener { + ) -> TaskClient { + TaskClient { shutdown: false, notify, return_error, drop_error, status_msg, - mode: ShutdownListenerMode::Listening, + mode: ClientOperatingMode::Listening, } } // Create a dummy that will never report that we should shutdown. - pub fn dummy() -> ShutdownListener { + pub fn dummy() -> TaskClient { let (_notify_tx, notify_rx) = watch::channel(()); let (task_halt_tx, _task_halt_rx) = mpsc::unbounded_channel(); let (task_drop_tx, _task_drop_rx) = mpsc::unbounded_channel(); //let (task_status_tx, _task_status_rx) = futures::channel::mpsc::unbounded(); let (task_status_tx, _task_status_rx) = futures::channel::mpsc::channel(128); - ShutdownListener { + TaskClient { shutdown: false, notify: notify_rx, return_error: task_halt_tx, drop_error: task_drop_tx, status_msg: task_status_tx, - mode: ShutdownListenerMode::Dummy, + mode: ClientOperatingMode::Dummy, } } @@ -256,6 +253,15 @@ impl ShutdownListener { self.shutdown = true; } + pub async fn recv_with_delay(&mut self) { + self.recv() + .then(|msg| async move { + sleep(Duration::from_secs(1)).await; + msg + }) + .await + } + pub async fn recv_timeout(&mut self) { if self.mode.is_dummy() { return pending().await; @@ -315,7 +321,7 @@ impl ShutdownListener { } } -impl Drop for ShutdownListener { +impl Drop for TaskClient { fn drop(&mut self) { if !self.mode.should_signal_on_drop() { return; @@ -331,7 +337,7 @@ impl Drop for ShutdownListener { } #[derive(Clone, Debug, PartialEq, Eq)] -enum ShutdownListenerMode { +enum ClientOperatingMode { // Normal operations Listening, // Normal operations, but we don't report back if the we stop by getting dropped. @@ -340,20 +346,20 @@ enum ShutdownListenerMode { Dummy, } -impl ShutdownListenerMode { +impl ClientOperatingMode { fn is_dummy(&self) -> bool { - self == &ShutdownListenerMode::Dummy + self == &ClientOperatingMode::Dummy } fn should_signal_on_drop(&self) -> bool { match self { - ShutdownListenerMode::Listening => true, - ShutdownListenerMode::ListeningButDontReportHalt | ShutdownListenerMode::Dummy => false, + ClientOperatingMode::Listening => true, + ClientOperatingMode::ListeningButDontReportHalt | ClientOperatingMode::Dummy => false, } } fn set_should_not_signal_on_drop(&mut self) { - use ShutdownListenerMode::{Dummy, Listening, ListeningButDontReportHalt}; + use ClientOperatingMode::{Dummy, Listening, ListeningButDontReportHalt}; *self = match &self { ListeningButDontReportHalt | Listening => ListeningButDontReportHalt, Dummy => Dummy, @@ -367,7 +373,7 @@ mod tests { #[tokio::test] async fn signal_shutdown() { - let shutdown = ShutdownNotifier::default(); + let shutdown = TaskManager::default(); let mut listener = shutdown.subscribe(); let task = tokio::spawn(async move { diff --git a/common/task/src/signal.rs b/common/task/src/signal.rs index a04a0f5601..483c7c630b 100644 --- a/common/task/src/signal.rs +++ b/common/task/src/signal.rs @@ -1,4 +1,4 @@ -use crate::{shutdown::SentError, ShutdownNotifier}; +use crate::{manager::SentError, TaskManager}; #[cfg(unix)] pub async fn wait_for_signal() { @@ -29,7 +29,7 @@ pub async fn wait_for_signal() { } #[cfg(unix)] -pub async fn wait_for_signal_and_error(shutdown: &mut ShutdownNotifier) -> Result<(), SentError> { +pub async fn wait_for_signal_and_error(shutdown: &mut TaskManager) -> Result<(), SentError> { use tokio::signal::unix::{signal, SignalKind}; let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM channel"); @@ -56,7 +56,7 @@ pub async fn wait_for_signal_and_error(shutdown: &mut ShutdownNotifier) -> Resul } #[cfg(not(unix))] -pub async fn wait_for_signal_and_error(shutdown: &mut ShutdownNotifier) -> Result<(), SentError> { +pub async fn wait_for_signal_and_error(shutdown: &mut TaskManager) -> Result<(), SentError> { tokio::select! { _ = tokio::signal::ctrl_c() => { log::info!("Received SIGINT"); diff --git a/common/task/src/spawn.rs b/common/task/src/spawn.rs index ba66ea7f16..d30c9ac850 100644 --- a/common/task/src/spawn.rs +++ b/common/task/src/spawn.rs @@ -1,4 +1,4 @@ -use crate::ShutdownListener; +use crate::TaskClient; use std::future::Future; #[cfg(target_arch = "wasm32")] @@ -18,7 +18,7 @@ where tokio::spawn(future); } -pub fn spawn_with_report_error(future: F, mut shutdown: ShutdownListener) +pub fn spawn_with_report_error(future: F, mut shutdown: TaskClient) where F: Future> + Send + 'static, T: 'static, diff --git a/explorer-api/src/country_statistics/distribution.rs b/explorer-api/src/country_statistics/distribution.rs index f48e87eebb..93d12067b6 100644 --- a/explorer-api/src/country_statistics/distribution.rs +++ b/explorer-api/src/country_statistics/distribution.rs @@ -1,5 +1,5 @@ use log::info; -use task::ShutdownListener; +use task::TaskClient; use crate::country_statistics::country_nodes_distribution::CountryNodesDistribution; use crate::COUNTRY_DATA_REFRESH_INTERVAL; @@ -8,11 +8,11 @@ use crate::state::ExplorerApiStateContext; pub(crate) struct CountryStatisticsDistributionTask { state: ExplorerApiStateContext, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl CountryStatisticsDistributionTask { - pub(crate) fn new(state: ExplorerApiStateContext, shutdown: ShutdownListener) -> Self { + pub(crate) fn new(state: ExplorerApiStateContext, shutdown: TaskClient) -> Self { CountryStatisticsDistributionTask { state, shutdown } } diff --git a/explorer-api/src/country_statistics/geolocate.rs b/explorer-api/src/country_statistics/geolocate.rs index c77a61a9a1..0ae79985c7 100644 --- a/explorer-api/src/country_statistics/geolocate.rs +++ b/explorer-api/src/country_statistics/geolocate.rs @@ -4,15 +4,15 @@ use crate::mix_nodes::location::Location; use crate::state::ExplorerApiStateContext; use log::{info, warn}; -use task::ShutdownListener; +use task::TaskClient; pub(crate) struct GeoLocateTask { state: ExplorerApiStateContext, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl GeoLocateTask { - pub(crate) fn new(state: ExplorerApiStateContext, shutdown: ShutdownListener) -> Self { + pub(crate) fn new(state: ExplorerApiStateContext, shutdown: TaskClient) -> Self { GeoLocateTask { state, shutdown } } diff --git a/explorer-api/src/main.rs b/explorer-api/src/main.rs index 5154c87e78..e1a02c57ea 100644 --- a/explorer-api/src/main.rs +++ b/explorer-api/src/main.rs @@ -8,7 +8,7 @@ use dotenv::dotenv; use log::info; use logging::setup_logging; use network_defaults::setup_env; -use task::ShutdownNotifier; +use task::TaskManager; mod buy_terms; pub(crate) mod cache; @@ -57,7 +57,7 @@ impl ExplorerApi { let nym_api_url = self.state.inner.validator_client.api_endpoint(); info!("Using validator API - {}", nym_api_url); - let shutdown = ShutdownNotifier::default(); + let shutdown = TaskManager::default(); // spawn concurrent tasks crate::tasks::ExplorerApiTasks::new(self.state.clone(), shutdown.subscribe()).start(); @@ -78,7 +78,7 @@ impl ExplorerApi { self.wait_for_interrupt(shutdown).await } - async fn wait_for_interrupt(&self, mut shutdown: ShutdownNotifier) { + async fn wait_for_interrupt(&self, mut shutdown: TaskManager) { wait_for_signal().await; log::info!("Sending shutdown"); diff --git a/explorer-api/src/tasks.rs b/explorer-api/src/tasks.rs index bab29b798e..b7e72f72d2 100644 --- a/explorer-api/src/tasks.rs +++ b/explorer-api/src/tasks.rs @@ -4,7 +4,7 @@ use std::future::Future; use mixnet_contract_common::GatewayBond; -use task::ShutdownListener; +use task::TaskClient; use validator_client::models::MixNodeBondAnnotated; use validator_client::nymd::error::NymdError; use validator_client::nymd::{Paging, QueryNymdClient, ValidatorResponse}; @@ -15,11 +15,11 @@ use crate::state::ExplorerApiStateContext; pub(crate) struct ExplorerApiTasks { state: ExplorerApiStateContext, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl ExplorerApiTasks { - pub(crate) fn new(state: ExplorerApiStateContext, shutdown: ShutdownListener) -> Self { + pub(crate) fn new(state: ExplorerApiStateContext, shutdown: TaskClient) -> Self { ExplorerApiTasks { state, shutdown } } diff --git a/mixnode/src/node/listener/connection_handler/mod.rs b/mixnode/src/node/listener/connection_handler/mod.rs index 08e8395917..52203c89ab 100644 --- a/mixnode/src/node/listener/connection_handler/mod.rs +++ b/mixnode/src/node/listener/connection_handler/mod.rs @@ -5,7 +5,7 @@ use crate::node::listener::connection_handler::packet_processing::{ MixProcessingResult, PacketProcessor, }; use crate::node::packet_delayforwarder::PacketDelayForwardSender; -use crate::node::ShutdownListener; +use crate::node::TaskClient; use futures::StreamExt; use log::{error, info}; use nymsphinx::forwarding::packet::MixPacket; @@ -74,7 +74,7 @@ impl ConnectionHandler { self, conn: TcpStream, remote: SocketAddr, - mut shutdown: ShutdownListener, + mut shutdown: TaskClient, ) { debug!("Starting connection handler for {:?}", remote); let mut framed_conn = Framed::new(conn, SphinxCodec); diff --git a/mixnode/src/node/listener/mod.rs b/mixnode/src/node/listener/mod.rs index 6b8ddbee1a..18ab26bc63 100644 --- a/mixnode/src/node/listener/mod.rs +++ b/mixnode/src/node/listener/mod.rs @@ -8,17 +8,17 @@ use std::process; use tokio::net::TcpListener; use tokio::task::JoinHandle; -use super::ShutdownListener; +use super::TaskClient; pub(crate) mod connection_handler; pub(crate) struct Listener { address: SocketAddr, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl Listener { - pub(crate) fn new(address: SocketAddr, shutdown: ShutdownListener) -> Self { + pub(crate) fn new(address: SocketAddr, shutdown: TaskClient) -> Self { Listener { address, shutdown } } diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index e986c4fa67..9fdbff3ebb 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -26,7 +26,7 @@ use rand::thread_rng; use std::net::SocketAddr; use std::process; use std::sync::Arc; -use task::{wait_for_signal, ShutdownListener, ShutdownNotifier}; +use task::{wait_for_signal, TaskClient, TaskManager}; use version_checker::parse_version; mod http; @@ -153,7 +153,7 @@ impl MixNode { fn start_node_stats_controller( &self, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> (SharedNodeStats, node_statistics::UpdateSender) { info!("Starting node stats controller..."); let controller = node_statistics::Controller::new( @@ -171,7 +171,7 @@ impl MixNode { &self, node_stats_update_sender: node_statistics::UpdateSender, delay_forwarding_channel: PacketDelayForwardSender, - shutdown: ShutdownListener, + shutdown: TaskClient, ) { info!("Starting socket listener..."); @@ -191,7 +191,7 @@ impl MixNode { fn start_packet_delay_forwarder( &mut self, node_stats_update_sender: node_statistics::UpdateSender, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> PacketDelayForwardSender { info!("Starting packet delay-forwarder..."); @@ -215,7 +215,7 @@ impl MixNode { packet_sender } - fn start_verloc_measurements(&self, shutdown: ShutdownListener) -> AtomicVerlocResult { + fn start_verloc_measurements(&self, shutdown: TaskClient) -> AtomicVerlocResult { info!("Starting the round-trip-time measurer..."); // this is a sanity check to make sure we didn't mess up with the minimum version at some point @@ -288,7 +288,7 @@ impl MixNode { .map(|node| node.bond_information.mix_node.identity_key.clone()) } - async fn wait_for_interrupt(&self, mut shutdown: ShutdownNotifier) { + async fn wait_for_interrupt(&self, mut shutdown: TaskManager) { wait_for_signal().await; log::info!("Sending shutdown"); @@ -315,7 +315,7 @@ impl MixNode { } } - let shutdown = ShutdownNotifier::default(); + let shutdown = TaskManager::default(); let (node_stats_pointer, node_stats_update_sender) = self.start_node_stats_controller(shutdown.subscribe()); diff --git a/mixnode/src/node/node_statistics.rs b/mixnode/src/node/node_statistics.rs index 86f98401ab..2fa8c39b8e 100644 --- a/mixnode/src/node/node_statistics.rs +++ b/mixnode/src/node/node_statistics.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use std::time::{Duration, SystemTime}; use tokio::sync::{RwLock, RwLockReadGuard}; -use super::ShutdownListener; +use super::TaskClient; // convenience aliases type PacketsMap = HashMap; @@ -211,14 +211,14 @@ impl CurrentPacketData { struct UpdateHandler { current_data: CurrentPacketData, update_receiver: PacketDataReceiver, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl UpdateHandler { fn new( current_data: CurrentPacketData, update_receiver: PacketDataReceiver, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> Self { UpdateHandler { current_data, @@ -293,7 +293,7 @@ struct StatsUpdater { updating_delay: Duration, current_packet_data: CurrentPacketData, current_stats: SharedNodeStats, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl StatsUpdater { @@ -301,7 +301,7 @@ impl StatsUpdater { updating_delay: Duration, current_packet_data: CurrentPacketData, current_stats: SharedNodeStats, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> Self { StatsUpdater { updating_delay, @@ -335,11 +335,11 @@ impl StatsUpdater { struct PacketStatsConsoleLogger { logging_delay: Duration, stats: SharedNodeStats, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl PacketStatsConsoleLogger { - fn new(logging_delay: Duration, stats: SharedNodeStats, shutdown: ShutdownListener) -> Self { + fn new(logging_delay: Duration, stats: SharedNodeStats, shutdown: TaskClient) -> Self { PacketStatsConsoleLogger { logging_delay, stats, @@ -451,7 +451,7 @@ impl Controller { pub(crate) fn new( logging_delay: Duration, stats_updating_delay: Duration, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> Self { let (sender, receiver) = mpsc::unbounded(); let shared_packet_data = CurrentPacketData::new(); @@ -503,13 +503,13 @@ impl Controller { #[cfg(test)] mod tests { use super::*; - use task::ShutdownNotifier; + use task::TaskManager; #[tokio::test] async fn node_stats_reported_are_received() { let logging_delay = Duration::from_millis(20); let stats_updating_delay = Duration::from_millis(10); - let shutdown = ShutdownNotifier::default(); + let shutdown = TaskManager::default(); let node_stats_controller = Controller::new(logging_delay, stats_updating_delay, shutdown.subscribe()); diff --git a/mixnode/src/node/packet_delayforwarder.rs b/mixnode/src/node/packet_delayforwarder.rs index 81e0303afd..da098bcdf9 100644 --- a/mixnode/src/node/packet_delayforwarder.rs +++ b/mixnode/src/node/packet_delayforwarder.rs @@ -9,7 +9,7 @@ use nymsphinx::forwarding::packet::MixPacket; use std::io; use tokio::time::Instant; -use super::ShutdownListener; +use super::TaskClient; // Delay + MixPacket vs Instant + MixPacket @@ -28,7 +28,7 @@ where packet_sender: PacketDelayForwardSender, packet_receiver: PacketDelayForwardReceiver, node_stats_update_sender: UpdateSender, - shutdown: ShutdownListener, + shutdown: TaskClient, } impl DelayForwarder @@ -38,7 +38,7 @@ where pub(crate) fn new( client: C, node_stats_update_sender: UpdateSender, - shutdown: ShutdownListener, + shutdown: TaskClient, ) -> DelayForwarder { let (packet_sender, packet_receiver) = mpsc::unbounded(); @@ -134,7 +134,7 @@ mod tests { use std::sync::{Arc, Mutex}; use std::time::Duration; - use task::ShutdownNotifier; + use task::TaskManager; use nymsphinx::addressing::nodes::NymNodeRoutingAddress; use nymsphinx_params::packet_sizes::PacketSize; @@ -205,7 +205,7 @@ mod tests { let node_stats_update_sender = UpdateSender::new(stats_sender); let client = TestClient::default(); let client_packets_sent = client.packets_sent.clone(); - let shutdown = ShutdownNotifier::default(); + let shutdown = TaskManager::default(); let mut delay_forwarder = DelayForwarder::new(client, node_stats_update_sender, shutdown.subscribe()); let packet_sender = delay_forwarder.sender(); diff --git a/nym-api/src/coconut/dkg/controller.rs b/nym-api/src/coconut/dkg/controller.rs index 6a7268af47..c54074141d 100644 --- a/nym-api/src/coconut/dkg/controller.rs +++ b/nym-api/src/coconut/dkg/controller.rs @@ -19,7 +19,7 @@ use rand::rngs::OsRng; use rand::RngCore; use std::path::PathBuf; use std::time::Duration; -use task::ShutdownListener; +use task::TaskClient; use tokio::time::interval; use validator_client::nymd::SigningNymdClient; @@ -134,7 +134,7 @@ impl DkgController { } } - pub(crate) async fn run(mut self, mut shutdown: ShutdownListener) { + pub(crate) async fn run(mut self, mut shutdown: TaskClient) { let mut interval = interval(self.polling_rate); while !shutdown.is_shutdown() { tokio::select! { diff --git a/nym-api/src/contract_cache/mod.rs b/nym-api/src/contract_cache/mod.rs index 61a7150a02..0775ca5a85 100644 --- a/nym-api/src/contract_cache/mod.rs +++ b/nym-api/src/contract_cache/mod.rs @@ -21,7 +21,7 @@ use std::ops::Deref; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::time::Duration; -use task::ShutdownListener; +use task::TaskClient; use tokio::sync::{watch, RwLock}; use tokio::time; use validator_client::nymd::CosmWasmClient; @@ -198,7 +198,7 @@ impl ValidatorCacheRefresher { Ok(()) } - pub(crate) async fn run(&self, mut shutdown: ShutdownListener) + pub(crate) async fn run(&self, mut shutdown: TaskClient) where C: CosmWasmClient + Sync + Send, { diff --git a/nym-api/src/epoch_operations/mod.rs b/nym-api/src/epoch_operations/mod.rs index cf0233e453..7f109d3dea 100644 --- a/nym-api/src/epoch_operations/mod.rs +++ b/nym-api/src/epoch_operations/mod.rs @@ -35,7 +35,7 @@ mod helpers; use crate::epoch_operations::helpers::stake_to_f64; use crate::node_status_api::ONE_DAY; use error::RewardingError; -use task::ShutdownListener; +use task::TaskClient; #[derive(Debug, Clone, Copy)] pub(crate) struct MixnodeToReward { @@ -373,7 +373,7 @@ impl RewardedSetUpdater { Ok(()) } - async fn wait_until_epoch_end(&mut self, shutdown: &mut ShutdownListener) -> Option { + async fn wait_until_epoch_end(&mut self, shutdown: &mut TaskClient) -> Option { const POLL_INTERVAL: Duration = Duration::from_secs(120); loop { @@ -421,10 +421,7 @@ impl RewardedSetUpdater { } } - pub(crate) async fn run( - &mut self, - mut shutdown: ShutdownListener, - ) -> Result<(), RewardingError> { + pub(crate) async fn run(&mut self, mut shutdown: TaskClient) -> Result<(), RewardingError> { self.validator_cache.wait_for_initial_values().await; while !shutdown.is_shutdown() { diff --git a/nym-api/src/main.rs b/nym-api/src/main.rs index a47068f5fc..256bb527b9 100644 --- a/nym-api/src/main.rs +++ b/nym-api/src/main.rs @@ -31,7 +31,7 @@ use std::str::FromStr; use std::sync::Arc; use std::time::Duration; use std::{fs, process}; -use task::ShutdownNotifier; +use task::TaskManager; use tokio::sync::Notify; #[cfg(feature = "coconut")] use url::Url; @@ -206,7 +206,7 @@ fn parse_args() -> ArgMatches { base_app.get_matches() } -async fn wait_for_interrupt(mut shutdown: ShutdownNotifier) { +async fn wait_for_interrupt(mut shutdown: TaskManager) { wait_for_signal().await; log::info!("Sending shutdown"); @@ -527,7 +527,7 @@ async fn run_nym_api(matches: ArgMatches) -> Result<()> { let liftoff_notify = Arc::new(Notify::new()); // We need a bigger timeout - let shutdown = ShutdownNotifier::new(10); + let shutdown = TaskManager::new(10); #[cfg(feature = "coconut")] let coconut_keypair = coconut::keypair::KeyPair::new(); diff --git a/nym-api/src/network_monitor/mod.rs b/nym-api/src/network_monitor/mod.rs index 0048e2be02..ff4d6bd585 100644 --- a/nym-api/src/network_monitor/mod.rs +++ b/nym-api/src/network_monitor/mod.rs @@ -6,7 +6,7 @@ use crypto::asymmetric::{encryption, identity}; use futures::channel::mpsc; use gateway_client::bandwidth::BandwidthController; use std::sync::Arc; -use task::ShutdownNotifier; +use task::TaskManager; use validator_client::nymd::SigningNymdClient; use crate::config::Config; @@ -142,7 +142,7 @@ impl NetworkMonitorRunnables { // TODO: note, that is not exactly doing what we want, because when // `ReceivedProcessor` is constructed, it already spawns a future // this needs to be refactored! - pub(crate) fn spawn_tasks(self, shutdown: &ShutdownNotifier) { + pub(crate) fn spawn_tasks(self, shutdown: &TaskManager) { let mut packet_receiver = self.packet_receiver; let mut monitor = self.monitor; let shutdown_listener = shutdown.subscribe(); diff --git a/nym-api/src/network_monitor/monitor/gateways_pinger.rs b/nym-api/src/network_monitor/monitor/gateways_pinger.rs index 24cd581bf3..986c1db5fb 100644 --- a/nym-api/src/network_monitor/monitor/gateways_pinger.rs +++ b/nym-api/src/network_monitor/monitor/gateways_pinger.rs @@ -7,7 +7,7 @@ use crypto::asymmetric::identity; use crypto::asymmetric::identity::PUBLIC_KEY_LENGTH; use log::{debug, info, trace, warn}; use std::time::Duration; -use task::ShutdownListener; +use task::TaskClient; use tokio::time::{sleep, Instant}; // TODO: should it perhaps be moved to config along other timeout values? @@ -144,7 +144,7 @@ impl GatewayPinger { info!("Pinging all active gateways took {:?}", time_taken); } - pub(crate) async fn run(&self, mut shutdown: ShutdownListener) { + pub(crate) async fn run(&self, mut shutdown: TaskClient) { while !shutdown.is_shutdown() { tokio::select! { _ = sleep(self.pinging_interval) => { diff --git a/nym-api/src/network_monitor/monitor/mod.rs b/nym-api/src/network_monitor/monitor/mod.rs index c333c5e883..f0f17bad09 100644 --- a/nym-api/src/network_monitor/monitor/mod.rs +++ b/nym-api/src/network_monitor/monitor/mod.rs @@ -12,7 +12,7 @@ use crate::storage::NymApiStorage; use log::{debug, error, info}; use std::collections::{HashMap, HashSet}; use std::process; -use task::ShutdownListener; +use task::TaskClient; use tokio::time::{sleep, Duration, Instant}; pub(crate) mod gateway_clients_cache; @@ -301,7 +301,7 @@ impl Monitor { self.test_nonce += 1; } - pub(crate) async fn run(&mut self, mut shutdown: ShutdownListener) { + pub(crate) async fn run(&mut self, mut shutdown: TaskClient) { self.received_processor.start_receiving(); // wait for validator cache to be ready diff --git a/nym-api/src/network_monitor/monitor/receiver.rs b/nym-api/src/network_monitor/monitor/receiver.rs index 991da5fa05..c232458c6f 100644 --- a/nym-api/src/network_monitor/monitor/receiver.rs +++ b/nym-api/src/network_monitor/monitor/receiver.rs @@ -7,7 +7,7 @@ use crypto::asymmetric::identity; use futures::channel::mpsc; use futures::StreamExt; use gateway_client::{AcknowledgementReceiver, MixnetMessageReceiver}; -use task::ShutdownListener; +use task::TaskClient; pub(crate) type GatewayClientUpdateSender = mpsc::UnboundedSender; pub(crate) type GatewayClientUpdateReceiver = mpsc::UnboundedReceiver; @@ -56,7 +56,7 @@ impl PacketReceiver { .expect("packet processor seems to have crashed!"); } - pub(crate) async fn run(&mut self, mut shutdown: ShutdownListener) { + pub(crate) async fn run(&mut self, mut shutdown: TaskClient) { while !shutdown.is_shutdown() { tokio::select! { biased; diff --git a/nym-api/src/network_monitor/monitor/sender.rs b/nym-api/src/network_monitor/monitor/sender.rs index d2fa815a11..5c6f3df22d 100644 --- a/nym-api/src/network_monitor/monitor/sender.rs +++ b/nym-api/src/network_monitor/monitor/sender.rs @@ -24,7 +24,7 @@ use std::pin::Pin; use std::sync::Arc; use std::task::Poll; use std::time::Duration; -use task::ShutdownListener; +use task::TaskClient; use gateway_client::bandwidth::BandwidthController; @@ -166,11 +166,7 @@ impl PacketSender { } } - pub(crate) fn spawn_gateways_pinger( - &self, - pinging_interval: Duration, - shutdown: ShutdownListener, - ) { + pub(crate) fn spawn_gateways_pinger(&self, pinging_interval: Duration, shutdown: TaskClient) { let gateway_pinger = GatewayPinger::new( self.active_gateway_clients.clone(), self.fresh_gateway_client_data @@ -209,7 +205,7 @@ impl PacketSender { ack_sender, fresh_gateway_client_data.gateway_response_timeout, Some(fresh_gateway_client_data.bandwidth_controller.clone()), - task::ShutdownListener::dummy(), + task::TaskClient::dummy(), ); gateway_client diff --git a/nym-api/src/node_status_api/cache.rs b/nym-api/src/node_status_api/cache.rs index f485716e8e..5a76ffd85a 100644 --- a/nym-api/src/node_status_api/cache.rs +++ b/nym-api/src/node_status_api/cache.rs @@ -12,7 +12,7 @@ use nym_api_requests::models::{MixNodeBondAnnotated, MixnodeStatus}; use rocket::fairing::AdHoc; use std::collections::HashMap; use std::{sync::Arc, time::Duration}; -use task::ShutdownListener; +use task::TaskClient; use tokio::sync::RwLockReadGuard; use tokio::{ sync::{watch, RwLock}, @@ -174,7 +174,7 @@ impl NodeStatusCacheRefresher { } } - pub async fn run(&mut self, mut shutdown: ShutdownListener) { + pub async fn run(&mut self, mut shutdown: TaskClient) { let mut fallback_interval = time::interval(self.fallback_caching_interval); while !shutdown.is_shutdown() { tokio::select! { diff --git a/nym-api/src/node_status_api/uptime_updater.rs b/nym-api/src/node_status_api/uptime_updater.rs index cc22d75741..0c36c1a124 100644 --- a/nym-api/src/node_status_api/uptime_updater.rs +++ b/nym-api/src/node_status_api/uptime_updater.rs @@ -8,7 +8,7 @@ use crate::node_status_api::ONE_DAY; use crate::storage::NymApiStorage; use log::error; use std::time::Duration; -use task::ShutdownListener; +use task::TaskClient; use time::{OffsetDateTime, PrimitiveDateTime, Time}; use tokio::time::{interval, sleep}; @@ -68,7 +68,7 @@ impl HistoricalUptimeUpdater { Ok(()) } - pub(crate) async fn run(&self, mut shutdown: ShutdownListener) { + pub(crate) async fn run(&self, mut shutdown: TaskClient) { // update uptimes at 23:00 UTC each day so that we'd have data from the actual [almost] whole day // and so that we would avoid the edge case of starting validator API at 23:59 and having some // nodes update for different days diff --git a/service-providers/network-requester/src/connection.rs b/service-providers/network-requester/src/connection.rs index f4ffaca992..3457375737 100644 --- a/service-providers/network-requester/src/connection.rs +++ b/service-providers/network-requester/src/connection.rs @@ -7,7 +7,7 @@ use proxy_helpers::connection_controller::ConnectionReceiver; use proxy_helpers::proxy_runner::{MixProxySender, ProxyRunner}; use socks5_requests::{ConnectionId, Message as Socks5Message, RemoteAddress, Response}; use std::io; -use task::ShutdownListener; +use task::TaskClient; use tokio::net::TcpStream; /// A TCP connection between the Socks5 service provider, which makes @@ -42,7 +42,7 @@ impl Connection { mix_receiver: ConnectionReceiver, mix_sender: MixProxySender<(Socks5Message, ReturnAddress)>, lane_queue_lengths: LaneQueueLengths, - shutdown: ShutdownListener, + shutdown: TaskClient, ) { let stream = self.conn.take().unwrap(); let remote_source_address = "???".to_string(); // we don't know ip address of requester diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index 202ac3d1c1..42ded9fbd0 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -28,7 +28,7 @@ use socks5_requests::{ use statistics_common::collector::StatisticsSender; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering}; -use task::ShutdownListener; +use task::TaskClient; use tokio_tungstenite::tungstenite::protocol::Message; use websocket_requests::{requests::ClientRequest, responses::ServerResponse}; @@ -250,7 +250,7 @@ impl ServiceProvider { controller_sender: ControllerSender, mix_input_sender: MixProxySender<(Socks5Message, ReturnAddress)>, lane_queue_lengths: LaneQueueLengths, - shutdown: ShutdownListener, + shutdown: TaskClient, ) { let mut conn = match Connection::new(conn_id, remote_addr.clone(), return_address.clone()).await { @@ -313,7 +313,7 @@ impl ServiceProvider { lane_queue_lengths: LaneQueueLengths, sender_tag: Option, connect_req: Box, - shutdown: ShutdownListener, + shutdown: TaskClient, ) { let return_address = match ReturnAddress::new(connect_req.return_address, sender_tag) { Some(address) => address, @@ -379,7 +379,7 @@ impl ServiceProvider { mix_input_sender: &MixProxySender<(Socks5Message, ReturnAddress)>, lane_queue_lengths: LaneQueueLengths, stats_collector: Option, - shutdown: ShutdownListener, + shutdown: TaskClient, ) { let deserialized_msg = match Socks5Message::try_from_bytes(&message.message) { Ok(msg) => msg, @@ -445,7 +445,7 @@ impl ServiceProvider { tokio::sync::mpsc::channel::<(Socks5Message, ReturnAddress)>(1); // Used to notify tasks to shutdown. Not all tasks fully supports this (yet). - let shutdown = task::ShutdownNotifier::default(); + let shutdown = task::TaskManager::default(); // Channel for announcing client connection state by the controller. // The `mixnet_response_listener` will use this to either report closed connection to the From 5e600de9322e30814f7424f508435c1edbb479c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Thu, 15 Dec 2022 12:22:43 +0200 Subject: [PATCH 07/21] Modify wasm specific make targets (#2693) --- Makefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 8f5aba2678..883be67453 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ clippy-coconut: cargo clippy --workspace --features coconut -- -D warnings clippy-wasm: - cargo clippy --workspace --features wasm -- -D warnings + cargo clippy --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown --workspace -- -D warnings clippy-all-contracts: @@ -49,9 +49,6 @@ test-main: test-coconut: cargo test --workspace --features coconut -test-wasm: - cargo test --workspace --features wasm - test-main-expensive: cargo test --workspace -- --ignored From c2c883e8407cb7e65334a714e840abf2d638a898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 16 Dec 2022 00:23:58 +0100 Subject: [PATCH 08/21] client: create websocket handler builder (#2700) * client: create websocket handler builder * rustfmt --- clients/native/src/client/mod.rs | 6 +-- clients/native/src/websocket/handler.rs | 57 +++++++++++++----------- clients/native/src/websocket/listener.rs | 10 +++-- clients/native/src/websocket/mod.rs | 2 +- 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/clients/native/src/client/mod.rs b/clients/native/src/client/mod.rs index 1a90c48b6f..bc28ce514b 100644 --- a/clients/native/src/client/mod.rs +++ b/clients/native/src/client/mod.rs @@ -86,7 +86,7 @@ impl SocketClient { config: &Config, client_input: ClientInput, client_output: ClientOutput, - self_address: Recipient, + self_address: &Recipient, shutdown: task::TaskClient, ) { info!("Starting websocket listener..."); @@ -101,7 +101,7 @@ impl SocketClient { received_buffer_request_sender, } = client_output; - let websocket_handler = websocket::Handler::new( + let websocket_handler = websocket::HandlerBuilder::new( input_sender, connection_command_sender, received_buffer_request_sender, @@ -153,7 +153,7 @@ impl SocketClient { &self.config, client_input, client_output, - self_address, + &self_address, started_client.task_manager.subscribe(), ); diff --git a/clients/native/src/websocket/handler.rs b/clients/native/src/websocket/handler.rs index f35058485e..f22bf49c67 100644 --- a/clients/native/src/websocket/handler.rs +++ b/clients/native/src/websocket/handler.rs @@ -35,53 +35,33 @@ impl Default for ReceivedResponseType { } } -pub(crate) struct Handler { +pub(crate) struct HandlerBuilder { msg_input: InputMessageSender, client_connection_tx: ConnectionCommandSender, buffer_requester: ReceivedBufferRequestSender, self_full_address: Recipient, - socket: Option>, - received_response_type: ReceivedResponseType, lane_queue_lengths: LaneQueueLengths, - is_active: bool, } -impl Drop for Handler { - fn drop(&mut self) { - if self.is_active - && self - .buffer_requester - .unbounded_send(ReceivedBufferMessage::ReceiverDisconnect) - .is_err() - { - error!("we failed to disconnect the receiver from the buffer! presumably the shutdown procedure has been initiated!") - } - } -} - -impl Handler { +impl HandlerBuilder { pub(crate) fn new( msg_input: InputMessageSender, client_connection_tx: ConnectionCommandSender, buffer_requester: ReceivedBufferRequestSender, - self_full_address: Recipient, + self_full_address: &Recipient, lane_queue_lengths: LaneQueueLengths, ) -> Self { - Handler { + Self { msg_input, client_connection_tx, buffer_requester, - self_full_address, - socket: None, - received_response_type: Default::default(), + self_full_address: *self_full_address, lane_queue_lengths, - is_active: false, } } - // Used to use handler on a new connection, which initially is `None` // TODO: make sure we only ever have one active handler - pub fn create_active_handler(&self) -> Self { + pub fn create_active_handler(&self) -> Handler { Handler { msg_input: self.msg_input.clone(), client_connection_tx: self.client_connection_tx.clone(), @@ -90,10 +70,33 @@ impl Handler { socket: None, received_response_type: Default::default(), lane_queue_lengths: self.lane_queue_lengths.clone(), - is_active: true, } } +} +pub(crate) struct Handler { + msg_input: InputMessageSender, + client_connection_tx: ConnectionCommandSender, + buffer_requester: ReceivedBufferRequestSender, + self_full_address: Recipient, + socket: Option>, + received_response_type: ReceivedResponseType, + lane_queue_lengths: LaneQueueLengths, +} + +impl Drop for Handler { + fn drop(&mut self) { + if self + .buffer_requester + .unbounded_send(ReceivedBufferMessage::ReceiverDisconnect) + .is_err() + { + error!("we failed to disconnect the receiver from the buffer! presumably the shutdown procedure has been initiated!") + } + } +} + +impl Handler { async fn handle_send( &mut self, recipient: Recipient, diff --git a/clients/native/src/websocket/listener.rs b/clients/native/src/websocket/listener.rs index aef9150b43..459eb1bc17 100644 --- a/clients/native/src/websocket/listener.rs +++ b/clients/native/src/websocket/listener.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use super::handler::Handler; +use super::handler::HandlerBuilder; use log::*; use std::{net::SocketAddr, process, sync::Arc}; use tokio::io::AsyncWriteExt; @@ -32,7 +32,7 @@ impl Listener { } } - pub(crate) async fn run(&mut self, handler: Handler, mut task_client: task::TaskClient) { + pub(crate) async fn run(&mut self, handler: HandlerBuilder, mut task_client: task::TaskClient) { let tcp_listener = match tokio::net::TcpListener::bind(self.address).await { Ok(listener) => listener, Err(err) => { @@ -100,7 +100,11 @@ impl Listener { log::debug!("Websocket listener: Exiting"); } - pub(crate) fn start(mut self, handler: Handler, shutdown: task::TaskClient) -> JoinHandle<()> { + pub(crate) fn start( + mut self, + handler: HandlerBuilder, + shutdown: task::TaskClient, + ) -> JoinHandle<()> { info!("Running websocket on {:?}", self.address.to_string()); tokio::spawn(async move { self.run(handler, shutdown).await }) diff --git a/clients/native/src/websocket/mod.rs b/clients/native/src/websocket/mod.rs index bd17b6ee08..38dadbd005 100644 --- a/clients/native/src/websocket/mod.rs +++ b/clients/native/src/websocket/mod.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -pub(crate) use handler::Handler; +pub(crate) use handler::HandlerBuilder; pub(crate) use listener::Listener; pub(crate) mod handler; From 870c4f73a847b6d1e56ec515a3896eb9a22d44b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 16 Dec 2022 00:24:45 +0100 Subject: [PATCH 09/21] socks5: send additional status messages available for the frontend (#2715) * socks5: send network-requester error in status channel * Minor tidy * task-manager: send status msg to indicate ready * changelog: add note * coconut/tests: fix clippy for rustc 1.66 --- CHANGELOG.md | 4 +++ clients/socks5/src/client/mod.rs | 2 +- clients/socks5/src/error.rs | 7 +++++ clients/socks5/src/socks/mixnet_responses.rs | 29 +++++++++++++------ .../src/network_requester_response.rs | 2 +- common/task/src/manager.rs | 19 ++++++++++-- nym-api/src/coconut/tests.rs | 2 +- nym-connect/src-tauri/src/tasks.rs | 2 +- 8 files changed, 51 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a40671598e..6eaa8b5bea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ## [Unreleased] +### Added + +- socks5: send status message for service ready, and network-requester error response + ### Changed - all-binaries: improved error logging ([#2686]) diff --git a/clients/socks5/src/client/mod.rs b/clients/socks5/src/client/mod.rs index 2f62354a01..c7710056f8 100644 --- a/clients/socks5/src/client/mod.rs +++ b/clients/socks5/src/client/mod.rs @@ -166,7 +166,7 @@ impl NymClient { let mut shutdown = self.start().await?; // Listen to status messages from task, that we forward back to the caller - shutdown.start_status_listener(sender); + shutdown.start_status_listener(sender).await; let res = tokio::select! { biased; diff --git a/clients/socks5/src/error.rs b/clients/socks5/src/error.rs index 23cd715cf5..6318d0ec0a 100644 --- a/clients/socks5/src/error.rs +++ b/clients/socks5/src/error.rs @@ -1,6 +1,7 @@ use crate::socks::types::SocksProxyError; use client_core::client::replies::reply_storage::fs_backend; use client_core::error::ClientCoreError; +use socks5_requests::ConnectionId; #[derive(thiserror::Error, Debug)] pub enum Socks5ClientError { @@ -21,4 +22,10 @@ pub enum Socks5ClientError { #[error("Fail to bind address")] FailToBindAddress, + + #[error("Network requester: connection id {connection_id}: {error}")] + NetworkRequesterError { + connection_id: ConnectionId, + error: String, + }, } diff --git a/clients/socks5/src/socks/mixnet_responses.rs b/clients/socks5/src/socks/mixnet_responses.rs index 97835340df..85d0a7da86 100644 --- a/clients/socks5/src/socks/mixnet_responses.rs +++ b/clients/socks5/src/socks/mixnet_responses.rs @@ -11,6 +11,8 @@ use proxy_helpers::connection_controller::{ControllerCommand, ControllerSender}; use socks5_requests::Message; use task::TaskClient; +use crate::error::Socks5ClientError; + pub(crate) struct MixnetResponseListener { buffer_requester: ReceivedBufferRequestSender, mix_response_receiver: ReconstructedMessagesReceiver, @@ -52,7 +54,10 @@ impl MixnetResponseListener { } } - async fn on_message(&self, reconstructed_message: ReconstructedMessage) { + fn on_message( + &self, + reconstructed_message: ReconstructedMessage, + ) -> Result<(), Socks5ClientError> { let raw_message = reconstructed_message.message; if reconstructed_message.sender_tag.is_some() { warn!("this message was sent anonymously - it couldn't have come from the service provider"); @@ -61,11 +66,11 @@ impl MixnetResponseListener { let response = match Message::try_from_bytes(&raw_message) { Err(err) => { warn!("failed to parse received response - {err}"); - return; + return Ok(()); } Ok(Message::Request(_)) => { warn!("unexpected request"); - return; + return Ok(()); } Ok(Message::Response(data)) => data, Ok(Message::NetworkRequesterResponse(r)) => { @@ -73,7 +78,10 @@ impl MixnetResponseListener { "Network requester failed on connection id {} with error: {}", r.connection_id, r.network_requester_error ); - return; + return Err(Socks5ClientError::NetworkRequesterError { + connection_id: r.connection_id, + error: r.network_requester_error, + }); } }; @@ -84,18 +92,21 @@ impl MixnetResponseListener { response.is_closed, )) .unwrap(); + + Ok(()) } pub(crate) async fn run(&mut self) { while !self.shutdown.is_shutdown() { tokio::select! { - received_responses = self.mix_response_receiver.next() => match received_responses { - Some(received_responses) => { + received_responses = self.mix_response_receiver.next() => { + if let Some(received_responses) = received_responses { for reconstructed_message in received_responses { - self.on_message(reconstructed_message).await; + if let Err(err) = self.on_message(reconstructed_message) { + self.shutdown.send_status_msg(Box::new(err)); + } } - }, - None => { + } else { log::trace!("MixnetResponseListener: Stopping since channel closed"); break; } diff --git a/common/socks5/requests/src/network_requester_response.rs b/common/socks5/requests/src/network_requester_response.rs index 64e459dfb0..eba3f88dd9 100644 --- a/common/socks5/requests/src/network_requester_response.rs +++ b/common/socks5/requests/src/network_requester_response.rs @@ -63,7 +63,7 @@ impl NetworkRequesterResponse { self.connection_id .to_be_bytes() .iter() - .cloned() + .copied() .chain(self.network_requester_error.into_bytes().into_iter()) .collect() } diff --git a/common/task/src/manager.rs b/common/task/src/manager.rs index 3729d317a9..82129e9478 100644 --- a/common/task/src/manager.rs +++ b/common/task/src/manager.rs @@ -28,6 +28,13 @@ enum TaskError { UnexpectedHalt, } +// TODO: possibly we should create a `Status` trait instead of reusing `Error` +#[derive(thiserror::Error, Debug)] +pub enum TaskStatus { + #[error("Ready")] + Ready, +} + /// Listens to status and error messages from tasks, as well as notifying them to gracefully /// shutdown. Keeps track of if task stop unexpectedly, such as in a panic. #[derive(Debug)] @@ -101,15 +108,21 @@ impl TaskManager { self.notify_tx.send(()) } - pub fn start_status_listener(&mut self, mut sender: StatusSender) { + pub async fn start_status_listener(&mut self, mut sender: StatusSender) { + // Announce that we are operational. This means that in the application where this is used, + // everything is up and running and ready to go. + if let Err(msg) = sender.send(Box::new(TaskStatus::Ready)).await { + log::error!("Error sending status message: {}", msg); + }; + if let Some(mut task_status_rx) = self.task_status_rx.take() { log::info!("Starting status message listener"); crate::spawn::spawn(async move { loop { if let Some(msg) = task_status_rx.next().await { log::trace!("Got msg: {}", msg); - if sender.send(msg).await.is_err() { - log::error!("Error sending status message"); + if let Err(msg) = sender.send(msg).await { + log::error!("Error sending status message: {}", msg); } } else { log::trace!("Stopping since channel closed"); diff --git a/nym-api/src/coconut/tests.rs b/nym-api/src/coconut/tests.rs index 3d9d6c46a7..3408dda0a3 100644 --- a/nym-api/src/coconut/tests.rs +++ b/nym-api/src/coconut/tests.rs @@ -282,7 +282,7 @@ impl super::client::Client for DummyClient { self.dealer_details.write().unwrap().insert( self.validator_address.to_string(), DealerDetails { - address: Addr::unchecked(&self.validator_address.to_string()), + address: Addr::unchecked(self.validator_address.to_string()), bte_public_key_with_proof, announce_address, assigned_index, diff --git a/nym-connect/src-tauri/src/tasks.rs b/nym-connect/src-tauri/src/tasks.rs index ea3c1b1fd9..3201648e6e 100644 --- a/nym-connect/src-tauri/src/tasks.rs +++ b/nym-connect/src-tauri/src/tasks.rs @@ -100,7 +100,7 @@ pub fn start_status_listener( log::info!("SOCKS5 proxy sent status message: {}", msg); window .emit( - "socks5-event", + "socks5-status-event", Payload { title: "SOCKS5 update".into(), message: msg.to_string(), From 254302ec38917c33cc4ff6031f1b366de32967ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Fri, 16 Dec 2022 12:21:39 +0200 Subject: [PATCH 10/21] Feature/auto dkg advance (#2714) * Add dkg epoch * Make epoch state advancement dependent only on time * Nym api tries advancing the dkg epoch state * Update the time table a bit It still needs to be changed before production, as the sign-up timeframe needs to be something like a few days. * Update changelog * Fix tests * Fix clippy after rustc update --- CHANGELOG.md | 2 + .../src/nymd/traits/dkg_query_client.rs | 6 +- .../src/nymd/traits/dkg_signing_client.rs | 16 ++ .../coconut-dkg/src/msg.rs | 1 - .../coconut-dkg/src/types.rs | 35 +++- contracts/coconut-dkg/src/contract.rs | 26 ++- contracts/coconut-dkg/src/dealers/queries.rs | 11 +- .../coconut-dkg/src/dealers/transactions.rs | 10 +- contracts/coconut-dkg/src/dealings/queries.rs | 6 - .../coconut-dkg/src/dealings/transactions.rs | 9 +- .../coconut-dkg/src/epoch_state/queries.rs | 23 ++- .../coconut-dkg/src/epoch_state/storage.rs | 4 +- .../src/epoch_state/transactions.rs | 178 +++++++++++++----- .../coconut-dkg/src/epoch_state/utils.rs | 14 +- contracts/coconut-dkg/src/error.rs | 3 + contracts/coconut-dkg/src/state/mod.rs | 1 - .../coconut-dkg/src/support/tests/fixtures.rs | 2 +- .../coconut-dkg/src/support/tests/helpers.rs | 1 - .../src/verification_key_shares/queries.rs | 5 - .../verification_key_shares/transactions.rs | 56 ++++-- .../src/submit_vk_creates_proposal.rs | 3 +- nym-api/src/coconut/client.rs | 5 +- nym-api/src/coconut/dkg/client.rs | 12 +- nym-api/src/coconut/dkg/controller.rs | 21 ++- nym-api/src/coconut/tests.rs | 18 +- nym-api/src/nymd_client.rs | 16 +- 26 files changed, 335 insertions(+), 149 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6eaa8b5bea..2a6d66b676 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,10 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// - all-binaries: improved error logging ([#2686]) - native client: bring shutdown logic up to the same level as socks5-client +- nym-api, coconut-dkg contract: automatic, time-based dkg epoch state advancement ([#2670]) [#2686]: https://github.com/nymtech/nym/pull/2686 +[#2670]: https://github.com/nymtech/nym/pull/2670 ## [v1.1.3] (2022-12-13) diff --git a/common/client-libs/validator-client/src/nymd/traits/dkg_query_client.rs b/common/client-libs/validator-client/src/nymd/traits/dkg_query_client.rs index b67627d316..ce69556137 100644 --- a/common/client-libs/validator-client/src/nymd/traits/dkg_query_client.rs +++ b/common/client-libs/validator-client/src/nymd/traits/dkg_query_client.rs @@ -8,13 +8,13 @@ use coconut_dkg_common::dealer::{ DealerDetailsResponse, PagedDealerResponse, PagedDealingsResponse, }; use coconut_dkg_common::msg::QueryMsg as DkgQueryMsg; -use coconut_dkg_common::types::EpochState; +use coconut_dkg_common::types::Epoch; use coconut_dkg_common::verification_key::PagedVKSharesResponse; use cosmrs::AccountId; #[async_trait] pub trait DkgQueryClient { - async fn get_current_epoch_state(&self) -> Result; + async fn get_current_epoch(&self) -> Result; async fn get_current_epoch_threshold(&self) -> Result, NymdError>; async fn get_dealer_details( &self, @@ -49,7 +49,7 @@ impl DkgQueryClient for NymdClient where C: CosmWasmClient + Send + Sync, { - async fn get_current_epoch_state(&self) -> Result { + async fn get_current_epoch(&self) -> Result { let request = DkgQueryMsg::GetCurrentEpochState {}; self.client .query_contract_smart(self.coconut_dkg_contract_address(), &request) diff --git a/common/client-libs/validator-client/src/nymd/traits/dkg_signing_client.rs b/common/client-libs/validator-client/src/nymd/traits/dkg_signing_client.rs index b0d1dfaf08..6fee83ac5d 100644 --- a/common/client-libs/validator-client/src/nymd/traits/dkg_signing_client.rs +++ b/common/client-libs/validator-client/src/nymd/traits/dkg_signing_client.rs @@ -12,6 +12,7 @@ use contracts_common::dealings::ContractSafeBytes; #[async_trait] pub trait DkgSigningClient { + async fn advance_dkg_epoch_state(&self, fee: Option) -> Result; async fn register_dealer( &self, bte_key: EncodedBTEPublicKeyWithProof, @@ -37,6 +38,21 @@ impl DkgSigningClient for NymdClient where C: SigningCosmWasmClient + Send + Sync, { + async fn advance_dkg_epoch_state(&self, fee: Option) -> Result { + let req = DkgExecuteMsg::AdvanceEpochState {}; + + self.client + .execute( + self.address(), + self.coconut_dkg_contract_address(), + &req, + fee.unwrap_or_default(), + "advancing DKG state", + vec![], + ) + .await + } + async fn register_dealer( &self, bte_key: EncodedBTEPublicKeyWithProof, diff --git a/common/cosmwasm-smart-contracts/coconut-dkg/src/msg.rs b/common/cosmwasm-smart-contracts/coconut-dkg/src/msg.rs index b2d0f1ae20..7a85486eb0 100644 --- a/common/cosmwasm-smart-contracts/coconut-dkg/src/msg.rs +++ b/common/cosmwasm-smart-contracts/coconut-dkg/src/msg.rs @@ -11,7 +11,6 @@ use serde::{Deserialize, Serialize}; pub struct InstantiateMsg { pub group_addr: String, pub multisig_addr: String, - pub admin: String, pub mix_denom: String, } diff --git a/common/cosmwasm-smart-contracts/coconut-dkg/src/types.rs b/common/cosmwasm-smart-contracts/coconut-dkg/src/types.rs index ffb1653919..4de725cebf 100644 --- a/common/cosmwasm-smart-contracts/coconut-dkg/src/types.rs +++ b/common/cosmwasm-smart-contracts/coconut-dkg/src/types.rs @@ -6,15 +6,48 @@ use std::fmt::{Display, Formatter}; pub use crate::dealer::{DealerDetails, PagedDealerResponse}; pub use contracts_common::dealings::ContractSafeBytes; -pub use cosmwasm_std::{Addr, Coin}; +pub use cosmwasm_std::{Addr, Coin, Timestamp}; pub type EncodedBTEPublicKeyWithProof = String; pub type EncodedBTEPublicKeyWithProofRef<'a> = &'a str; pub type NodeIndex = u64; +// The time sign-up is open for dealers to join (2 minutes) +pub const PUBLIC_KEY_SUBMISSION_TIME_SECS: u64 = 60 * 2; +pub const DEALING_EXCHANGE_TIME_SECS: u64 = 60 * 5; +pub const VERIFICATION_KEY_SUBMISSION_TIME_SECS: u64 = 60 * 5; +pub const VERIFICATION_KEY_VALIDATION_TIME_SECS: u64 = 60; +pub const VERIFICATION_KEY_FINALIZATION_TIME_SECS: u64 = 60; +// The time an epoch lasts (2 weeks) +pub const IN_PROGRESS_TIME_SECS: u64 = 60 * 60 * 24 * 14; + // 2 public attributes, 2 private attributes, 1 fixed for coconut credential pub const TOTAL_DEALINGS: usize = 2 + 2 + 1; +#[derive(Serialize, Deserialize, Default, Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)] +#[serde(rename_all = "snake_case")] +pub struct Epoch { + pub state: EpochState, + pub finish_timestamp: Timestamp, +} + +impl Epoch { + pub fn new(state: EpochState, current_timestamp: Timestamp) -> Self { + let duration = match state { + EpochState::PublicKeySubmission => PUBLIC_KEY_SUBMISSION_TIME_SECS, + EpochState::DealingExchange => DEALING_EXCHANGE_TIME_SECS, + EpochState::VerificationKeySubmission => VERIFICATION_KEY_SUBMISSION_TIME_SECS, + EpochState::VerificationKeyValidation => VERIFICATION_KEY_VALIDATION_TIME_SECS, + EpochState::VerificationKeyFinalization => VERIFICATION_KEY_FINALIZATION_TIME_SECS, + EpochState::InProgress => IN_PROGRESS_TIME_SECS, + }; + Epoch { + state, + finish_timestamp: current_timestamp.plus_seconds(duration), + } + } +} + // currently (it is still extremely likely to change, we might be able to get rid of verification key-related complaints), // the epoch can be in the following states (in order): // 1. PublicKeySubmission -> potential dealers are submitting their BTE and ed25519 public keys to participate in dealing exchange diff --git a/contracts/coconut-dkg/src/contract.rs b/contracts/coconut-dkg/src/contract.rs index 5394e845af..650cf312f0 100644 --- a/contracts/coconut-dkg/src/contract.rs +++ b/contracts/coconut-dkg/src/contract.rs @@ -7,16 +7,16 @@ use crate::dealers::queries::{ use crate::dealers::transactions::try_add_dealer; use crate::dealings::queries::query_dealings_paged; use crate::dealings::transactions::try_commit_dealings; -use crate::epoch_state::queries::{query_current_epoch_state, query_current_epoch_threshold}; -use crate::epoch_state::storage::CURRENT_EPOCH_STATE; +use crate::epoch_state::queries::{query_current_epoch, query_current_epoch_threshold}; +use crate::epoch_state::storage::CURRENT_EPOCH; use crate::epoch_state::transactions::advance_epoch_state; use crate::error::ContractError; -use crate::state::{State, ADMIN, MULTISIG, STATE}; +use crate::state::{State, MULTISIG, STATE}; use crate::verification_key_shares::queries::query_vk_shares_paged; use crate::verification_key_shares::transactions::try_commit_verification_key_share; use crate::verification_key_shares::transactions::try_verify_verification_key_share; use coconut_dkg_common::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; -use coconut_dkg_common::types::EpochState; +use coconut_dkg_common::types::{Epoch, EpochState}; use cosmwasm_std::{ entry_point, to_binary, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, }; @@ -30,13 +30,11 @@ use cw4::Cw4Contract; #[entry_point] pub fn instantiate( mut deps: DepsMut<'_>, - _env: Env, + env: Env, _info: MessageInfo, msg: InstantiateMsg, ) -> Result { - let admin_addr = deps.api.addr_validate(&msg.admin)?; let multisig_addr = deps.api.addr_validate(&msg.multisig_addr)?; - ADMIN.set(deps.branch(), Some(admin_addr))?; MULTISIG.set(deps.branch(), Some(multisig_addr.clone()))?; let group_addr = Cw4Contract(deps.api.addr_validate(&msg.group_addr).map_err(|_| { @@ -52,7 +50,10 @@ pub fn instantiate( }; STATE.save(deps.storage, &state)?; - CURRENT_EPOCH_STATE.save(deps.storage, &EpochState::default())?; + CURRENT_EPOCH.save( + deps.storage, + &Epoch::new(EpochState::default(), env.block.time), + )?; Ok(Response::default()) } @@ -79,14 +80,14 @@ pub fn execute( ExecuteMsg::VerifyVerificationKeyShare { owner } => { try_verify_verification_key_share(deps, info, owner) } - ExecuteMsg::AdvanceEpochState {} => advance_epoch_state(deps, info), + ExecuteMsg::AdvanceEpochState {} => advance_epoch_state(deps, env), } } #[entry_point] pub fn query(deps: Deps<'_>, _env: Env, msg: QueryMsg) -> Result { let response = match msg { - QueryMsg::GetCurrentEpochState {} => to_binary(&query_current_epoch_state(deps.storage)?)?, + QueryMsg::GetCurrentEpochState {} => to_binary(&query_current_epoch(deps.storage)?)?, QueryMsg::GetCurrentEpochThreshold {} => { to_binary(&query_current_epoch_threshold(deps.storage)?)? } @@ -120,9 +121,8 @@ pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result, mapping: &IndexedDealersMap<'_>, size: usize) { for n in 0..size { @@ -95,8 +94,7 @@ pub(crate) mod tests { #[test] fn dealers_empty_on_init() { - let mut deps = init_contract(); - let env = mock_env(); + let deps = init_contract(); for mapping in [storage::current_dealers(), storage::past_dealers()] { let page1 = query_dealers(deps.as_ref(), None, None, &mapping).unwrap(); @@ -107,8 +105,6 @@ pub(crate) mod tests { #[test] fn dealers_paged_retrieval_obeys_limits() { let mut deps = init_contract(); - let env = mock_env(); - let owner = Addr::unchecked("owner"); let limit = 2; for mapping in [storage::current_dealers(), storage::past_dealers()] { @@ -124,7 +120,6 @@ pub(crate) mod tests { #[test] fn dealers_paged_retrieval_has_default_limit() { let mut deps = init_contract(); - let env = mock_env(); for mapping in [storage::current_dealers(), storage::past_dealers()] { fill_dealers(deps.as_mut(), &mapping, 1000); @@ -141,7 +136,6 @@ pub(crate) mod tests { #[test] fn dealers_paged_retrieval_has_max_limit() { let mut deps = init_contract(); - let env = mock_env(); // query with a crazily high limit in an attempt to use too many resources let crazy_limit = 1000 * DEALERS_PAGE_MAX_LIMIT; @@ -163,7 +157,6 @@ pub(crate) mod tests { #[test] fn dealers_pagination_works() { let mut deps = init_contract(); - let env = mock_env(); let per_page = 2; diff --git a/contracts/coconut-dkg/src/dealers/transactions.rs b/contracts/coconut-dkg/src/dealers/transactions.rs index 6c5ccbb8db..6566581221 100644 --- a/contracts/coconut-dkg/src/dealers/transactions.rs +++ b/contracts/coconut-dkg/src/dealers/transactions.rs @@ -70,21 +70,21 @@ pub fn try_add_dealer( pub(crate) mod tests { use super::*; use crate::epoch_state::transactions::advance_epoch_state; - use crate::support::tests::fixtures::dealer_details_fixture; use crate::support::tests::helpers; - use crate::support::tests::helpers::ADMIN_ADDRESS; - use cosmwasm_std::testing::mock_info; + use coconut_dkg_common::types::PUBLIC_KEY_SUBMISSION_TIME_SECS; + use cosmwasm_std::testing::{mock_env, mock_info}; #[test] fn invalid_state() { let mut deps = helpers::init_contract(); let owner = Addr::unchecked("owner"); + let mut env = mock_env(); let info = mock_info(owner.as_str(), &[]); - let dealer_details = dealer_details_fixture(1); let bte_key_with_proof = String::from("bte_key_with_proof"); let announce_address = String::from("localhost:8000"); - advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap(); + env.block.time = env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS); + advance_epoch_state(deps.as_mut(), env).unwrap(); let ret = try_add_dealer( deps.as_mut(), diff --git a/contracts/coconut-dkg/src/dealings/queries.rs b/contracts/coconut-dkg/src/dealings/queries.rs index 7fe476a458..0bf0452c14 100644 --- a/contracts/coconut-dkg/src/dealings/queries.rs +++ b/contracts/coconut-dkg/src/dealings/queries.rs @@ -50,7 +50,6 @@ pub(crate) mod tests { use crate::dealings::storage::{DEALINGS_PAGE_DEFAULT_LIMIT, DEALINGS_PAGE_MAX_LIMIT}; use crate::support::tests::fixtures::dealing_bytes_fixture; use crate::support::tests::helpers::init_contract; - use cosmwasm_std::testing::mock_env; use cosmwasm_std::{Addr, DepsMut}; fn fill_dealings(deps: DepsMut<'_>, size: usize) { @@ -68,7 +67,6 @@ pub(crate) mod tests { #[test] fn empty_on_bad_idx() { let mut deps = init_contract(); - let env = mock_env(); fill_dealings(deps.as_mut(), 1000); for idx in TOTAL_DEALINGS as u64..100 * TOTAL_DEALINGS as u64 { @@ -89,7 +87,6 @@ pub(crate) mod tests { #[test] fn dealings_paged_retrieval_obeys_limits() { let mut deps = init_contract(); - let env = mock_env(); let limit = 2; fill_dealings(deps.as_mut(), 1000); @@ -103,7 +100,6 @@ pub(crate) mod tests { #[test] fn dealings_paged_retrieval_has_default_limit() { let mut deps = init_contract(); - let env = mock_env(); fill_dealings(deps.as_mut(), 1000); for idx in 0..TOTAL_DEALINGS as u64 { @@ -117,7 +113,6 @@ pub(crate) mod tests { #[test] fn dealings_paged_retrieval_has_max_limit() { let mut deps = init_contract(); - let env = mock_env(); fill_dealings(deps.as_mut(), 1000); // query with a crazily high limit in an attempt to use too many resources @@ -135,7 +130,6 @@ pub(crate) mod tests { #[test] fn dealings_pagination_works() { let mut deps = init_contract(); - let env = mock_env(); fill_dealings(deps.as_mut(), 1); diff --git a/contracts/coconut-dkg/src/dealings/transactions.rs b/contracts/coconut-dkg/src/dealings/transactions.rs index 7320768979..fe2e5544cb 100644 --- a/contracts/coconut-dkg/src/dealings/transactions.rs +++ b/contracts/coconut-dkg/src/dealings/transactions.rs @@ -42,16 +42,16 @@ pub(crate) mod tests { use crate::epoch_state::transactions::advance_epoch_state; use crate::support::tests::fixtures::dealing_bytes_fixture; use crate::support::tests::helpers; - use crate::support::tests::helpers::ADMIN_ADDRESS; use coconut_dkg_common::dealer::DealerDetails; - use coconut_dkg_common::types::TOTAL_DEALINGS; - use cosmwasm_std::testing::mock_info; + use coconut_dkg_common::types::PUBLIC_KEY_SUBMISSION_TIME_SECS; + use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::Addr; #[test] fn invalid_commit_dealing() { let mut deps = helpers::init_contract(); let owner = Addr::unchecked("owner"); + let mut env = mock_env(); let info = mock_info(owner.as_str(), &[]); let dealing_bytes = dealing_bytes_fixture(); @@ -65,7 +65,8 @@ pub(crate) mod tests { } ); - advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap(); + env.block.time = env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS); + advance_epoch_state(deps.as_mut(), env).unwrap(); let ret = try_commit_dealings(deps.as_mut(), info.clone(), dealing_bytes.clone()).unwrap_err(); diff --git a/contracts/coconut-dkg/src/epoch_state/queries.rs b/contracts/coconut-dkg/src/epoch_state/queries.rs index a7027ca488..3a68e0117c 100644 --- a/contracts/coconut-dkg/src/epoch_state/queries.rs +++ b/contracts/coconut-dkg/src/epoch_state/queries.rs @@ -1,15 +1,13 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::epoch_state::storage::{CURRENT_EPOCH_STATE, THRESHOLD}; +use crate::epoch_state::storage::{CURRENT_EPOCH, THRESHOLD}; use crate::error::ContractError; -use coconut_dkg_common::types::EpochState; +use coconut_dkg_common::types::Epoch; use cosmwasm_std::Storage; -pub(crate) fn query_current_epoch_state( - storage: &dyn Storage, -) -> Result { - CURRENT_EPOCH_STATE +pub(crate) fn query_current_epoch(storage: &dyn Storage) -> Result { + CURRENT_EPOCH .load(storage) .map_err(|_| ContractError::EpochNotInitialised) } @@ -24,12 +22,21 @@ pub(crate) fn query_current_epoch_threshold( pub(crate) mod test { use super::*; use crate::support::tests::helpers::init_contract; + use coconut_dkg_common::types::{EpochState, PUBLIC_KEY_SUBMISSION_TIME_SECS}; + use cosmwasm_std::testing::mock_env; #[test] fn query_state() { let mut deps = init_contract(); - let state = query_current_epoch_state(deps.as_mut().storage).unwrap(); - assert_eq!(state, EpochState::PublicKeySubmission); + let epoch = query_current_epoch(deps.as_mut().storage).unwrap(); + assert_eq!(epoch.state, EpochState::PublicKeySubmission); + assert_eq!( + epoch.finish_timestamp, + mock_env() + .block + .time + .plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS) + ); } #[test] diff --git a/contracts/coconut-dkg/src/epoch_state/storage.rs b/contracts/coconut-dkg/src/epoch_state/storage.rs index b5c670d899..d5aac5b041 100644 --- a/contracts/coconut-dkg/src/epoch_state/storage.rs +++ b/contracts/coconut-dkg/src/epoch_state/storage.rs @@ -1,8 +1,8 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use coconut_dkg_common::types::EpochState; +use coconut_dkg_common::types::Epoch; use cw_storage_plus::Item; -pub(crate) const CURRENT_EPOCH_STATE: Item<'_, EpochState> = Item::new("current_epoch_state"); +pub(crate) const CURRENT_EPOCH: Item<'_, Epoch> = Item::new("current_epoch"); pub const THRESHOLD: Item = Item::new("threshold"); diff --git a/contracts/coconut-dkg/src/epoch_state/transactions.rs b/contracts/coconut-dkg/src/epoch_state/transactions.rs index fbb597f668..e2e75a1678 100644 --- a/contracts/coconut-dkg/src/epoch_state/transactions.rs +++ b/contracts/coconut-dkg/src/epoch_state/transactions.rs @@ -2,25 +2,29 @@ // SPDX-License-Identifier: Apache-2.0 use crate::dealers::storage::current_dealers; -use crate::epoch_state::storage::{CURRENT_EPOCH_STATE, THRESHOLD}; +use crate::epoch_state::storage::{CURRENT_EPOCH, THRESHOLD}; use crate::error::ContractError; -use crate::state::ADMIN; -use coconut_dkg_common::types::EpochState; -use cosmwasm_std::{DepsMut, MessageInfo, Order, Response}; +use coconut_dkg_common::types::{Epoch, EpochState}; +use cosmwasm_std::{DepsMut, Env, Order, Response}; -pub(crate) fn advance_epoch_state( - deps: DepsMut<'_>, - info: MessageInfo, -) -> Result { - ADMIN.assert_admin(deps.as_ref(), &info.sender)?; - let current_epoch_state = - CURRENT_EPOCH_STATE.update::<_, ContractError>(deps.storage, |mut epoch_state| { - // TODO: When defaulting to the first state, some action will probably need to be taken on the - // rest of the contract, as we're starting with a new set of signers - epoch_state = epoch_state.next().unwrap_or_default(); - Ok(epoch_state) - })?; - if current_epoch_state == EpochState::DealingExchange { +pub(crate) fn advance_epoch_state(deps: DepsMut<'_>, env: Env) -> Result { + let epoch = CURRENT_EPOCH.load(deps.storage)?; + if epoch.finish_timestamp > env.block.time { + return Err(ContractError::EarlyEpochStateAdvancement( + epoch + .finish_timestamp + .minus_seconds(env.block.time.seconds()) + .seconds(), + )); + } + + let current_epoch = CURRENT_EPOCH.update::<_, ContractError>(deps.storage, |mut epoch| { + // TODO: When defaulting to the first state, some action will probably need to be taken on the + // rest of the contract, as we're starting with a new set of signers + epoch = Epoch::new(epoch.state.next().unwrap_or_default(), env.block.time); + Ok(epoch) + })?; + if current_epoch.state == EpochState::DealingExchange { let current_dealer_count = current_dealers() .keys(deps.storage, None, None, Order::Ascending) .count(); @@ -34,64 +38,147 @@ pub(crate) fn advance_epoch_state( #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::support::tests::helpers::{init_contract, ADMIN_ADDRESS}; - use coconut_dkg_common::types::{DealerDetails, EpochState}; - use cosmwasm_std::testing::mock_info; + use crate::error::ContractError::EarlyEpochStateAdvancement; + use crate::support::tests::helpers::init_contract; + use coconut_dkg_common::types::{ + DealerDetails, EpochState, DEALING_EXCHANGE_TIME_SECS, IN_PROGRESS_TIME_SECS, + PUBLIC_KEY_SUBMISSION_TIME_SECS, VERIFICATION_KEY_FINALIZATION_TIME_SECS, + VERIFICATION_KEY_SUBMISSION_TIME_SECS, VERIFICATION_KEY_VALIDATION_TIME_SECS, + }; + use cosmwasm_std::testing::mock_env; use cosmwasm_std::Addr; - use cw_controllers::AdminError; #[test] fn advance_state() { let mut deps = init_contract(); - let info = mock_info("requester", &[]); - let admin_info = mock_info(ADMIN_ADDRESS, &[]); + let mut env = mock_env(); + let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap(); + assert_eq!(epoch.state, EpochState::PublicKeySubmission); assert_eq!( - advance_epoch_state(deps.as_mut(), info).unwrap_err(), - ContractError::Admin(AdminError::NotAdmin {}) + epoch.finish_timestamp, + env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS) ); - advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap(); + env.block.time = env + .block + .time + .plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS - 1); assert_eq!( - CURRENT_EPOCH_STATE.load(deps.as_mut().storage).unwrap(), - EpochState::DealingExchange + advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(), + EarlyEpochStateAdvancement(1) ); - advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap(); + env.block.time = env.block.time.plus_seconds(1); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); + let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap(); + assert_eq!(epoch.state, EpochState::DealingExchange); assert_eq!( - CURRENT_EPOCH_STATE.load(deps.as_mut().storage).unwrap(), - EpochState::VerificationKeySubmission + epoch.finish_timestamp, + env.block.time.plus_seconds(DEALING_EXCHANGE_TIME_SECS) ); - advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap(); + env.block.time = env.block.time.plus_seconds(DEALING_EXCHANGE_TIME_SECS - 2); assert_eq!( - CURRENT_EPOCH_STATE.load(deps.as_mut().storage).unwrap(), - EpochState::VerificationKeyValidation + advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(), + EarlyEpochStateAdvancement(2) ); - advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap(); + env.block.time = env.block.time.plus_seconds(3); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); + let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap(); + assert_eq!(epoch.state, EpochState::VerificationKeySubmission); assert_eq!( - CURRENT_EPOCH_STATE.load(deps.as_mut().storage).unwrap(), - EpochState::VerificationKeyFinalization + epoch.finish_timestamp, + env.block + .time + .plus_seconds(VERIFICATION_KEY_SUBMISSION_TIME_SECS) ); - advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap(); + env.block.time = env + .block + .time + .plus_seconds(VERIFICATION_KEY_SUBMISSION_TIME_SECS - 2); assert_eq!( - CURRENT_EPOCH_STATE.load(deps.as_mut().storage).unwrap(), - EpochState::InProgress + advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(), + EarlyEpochStateAdvancement(2) ); - advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap(); + env.block.time = env.block.time.plus_seconds(3); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); + let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap(); + assert_eq!(epoch.state, EpochState::VerificationKeyValidation); assert_eq!( - CURRENT_EPOCH_STATE.load(deps.as_mut().storage).unwrap(), - EpochState::PublicKeySubmission + epoch.finish_timestamp, + env.block + .time + .plus_seconds(VERIFICATION_KEY_VALIDATION_TIME_SECS) + ); + + env.block.time = env + .block + .time + .plus_seconds(VERIFICATION_KEY_VALIDATION_TIME_SECS - 3); + assert_eq!( + advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(), + EarlyEpochStateAdvancement(3) + ); + + env.block.time = env.block.time.plus_seconds(3); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); + let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap(); + assert_eq!(epoch.state, EpochState::VerificationKeyFinalization); + assert_eq!( + epoch.finish_timestamp, + env.block + .time + .plus_seconds(VERIFICATION_KEY_FINALIZATION_TIME_SECS) + ); + + env.block.time = env + .block + .time + .plus_seconds(VERIFICATION_KEY_FINALIZATION_TIME_SECS - 1); + assert_eq!( + advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(), + EarlyEpochStateAdvancement(1) + ); + + env.block.time = env.block.time.plus_seconds(1); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); + let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap(); + assert_eq!(epoch.state, EpochState::InProgress); + assert_eq!( + epoch.finish_timestamp, + env.block.time.plus_seconds(IN_PROGRESS_TIME_SECS) + ); + + env.block.time = env.block.time.plus_seconds(IN_PROGRESS_TIME_SECS - 100); + assert_eq!( + advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(), + EarlyEpochStateAdvancement(100) + ); + + env.block.time = env.block.time.plus_seconds(50); + assert_eq!( + advance_epoch_state(deps.as_mut(), env.clone()).unwrap_err(), + EarlyEpochStateAdvancement(50) + ); + + env.block.time = env.block.time.plus_seconds(100); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); + let epoch = CURRENT_EPOCH.load(deps.as_mut().storage).unwrap(); + assert_eq!(epoch.state, EpochState::PublicKeySubmission); + assert_eq!( + epoch.finish_timestamp, + env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS) ); } #[test] fn verify_threshold() { let mut deps = init_contract(); - let admin_info = mock_info(ADMIN_ADDRESS, &[]); + let mut env = mock_env(); assert!(THRESHOLD.may_load(deps.as_mut().storage).unwrap().is_none()); @@ -111,7 +198,8 @@ pub(crate) mod tests { .unwrap(); } - advance_epoch_state(deps.as_mut(), admin_info.clone()).unwrap(); + env.block.time = env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS); + advance_epoch_state(deps.as_mut(), env).unwrap(); assert_eq!( THRESHOLD.may_load(deps.as_mut().storage).unwrap().unwrap(), 67 diff --git a/contracts/coconut-dkg/src/epoch_state/utils.rs b/contracts/coconut-dkg/src/epoch_state/utils.rs index b944ad361d..280436ee2e 100644 --- a/contracts/coconut-dkg/src/epoch_state/utils.rs +++ b/contracts/coconut-dkg/src/epoch_state/utils.rs @@ -1,7 +1,7 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::epoch_state::storage::CURRENT_EPOCH_STATE; +use crate::epoch_state::storage::CURRENT_EPOCH; use crate::error::ContractError; use coconut_dkg_common::types::EpochState; use cosmwasm_std::Storage; @@ -10,7 +10,7 @@ pub(crate) fn check_epoch_state( storage: &dyn Storage, against: EpochState, ) -> Result<(), ContractError> { - let epoch_state = CURRENT_EPOCH_STATE.load(storage)?; + let epoch_state = CURRENT_EPOCH.load(storage)?.state; if epoch_state != against { Err(ContractError::IncorrectEpochState { current_state: epoch_state.to_string(), @@ -25,14 +25,20 @@ pub(crate) fn check_epoch_state( pub(crate) mod test { use super::*; use crate::support::tests::helpers::init_contract; + use coconut_dkg_common::types::Epoch; + use cosmwasm_std::testing::mock_env; #[test] pub fn check_state() { let mut deps = init_contract(); + let env = mock_env(); for fixed_state in EpochState::default().all_until(EpochState::InProgress) { - CURRENT_EPOCH_STATE - .save(deps.as_mut().storage, &fixed_state) + CURRENT_EPOCH + .save( + deps.as_mut().storage, + &Epoch::new(fixed_state, env.block.time), + ) .unwrap(); for against_state in EpochState::default().all_until(EpochState::InProgress) { let ret = check_epoch_state(deps.as_mut().storage, against_state); diff --git a/contracts/coconut-dkg/src/error.rs b/contracts/coconut-dkg/src/error.rs index cd359579d0..0baeae5edd 100644 --- a/contracts/coconut-dkg/src/error.rs +++ b/contracts/coconut-dkg/src/error.rs @@ -23,6 +23,9 @@ pub enum ContractError { #[error("This sender is already a dealer for the epoch")] AlreadyADealer, + #[error("Too soon to advance epoch state. {0} more seconds until it can be advanced")] + EarlyEpochStateAdvancement(u64), + #[error("Epoch hasn't been correctly initialised!")] EpochNotInitialised, diff --git a/contracts/coconut-dkg/src/state/mod.rs b/contracts/coconut-dkg/src/state/mod.rs index 729618ec60..533bd98a0a 100644 --- a/contracts/coconut-dkg/src/state/mod.rs +++ b/contracts/coconut-dkg/src/state/mod.rs @@ -10,7 +10,6 @@ use serde::{Deserialize, Serialize}; // unique items pub const STATE: Item = Item::new("state"); -pub const ADMIN: Admin = Admin::new("admin"); pub const MULTISIG: Admin = Admin::new("multisig"); #[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)] diff --git a/contracts/coconut-dkg/src/support/tests/fixtures.rs b/contracts/coconut-dkg/src/support/tests/fixtures.rs index e0bdee4e4d..19aad555d1 100644 --- a/contracts/coconut-dkg/src/support/tests/fixtures.rs +++ b/contracts/coconut-dkg/src/support/tests/fixtures.rs @@ -1,7 +1,7 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use coconut_dkg_common::dealer::{ContractDealing, DealerDetails}; +use coconut_dkg_common::dealer::DealerDetails; use coconut_dkg_common::types::ContractSafeBytes; use coconut_dkg_common::verification_key::ContractVKShare; use cosmwasm_std::Addr; diff --git a/contracts/coconut-dkg/src/support/tests/helpers.rs b/contracts/coconut-dkg/src/support/tests/helpers.rs index ec46ff0215..b59ee40bcf 100644 --- a/contracts/coconut-dkg/src/support/tests/helpers.rs +++ b/contracts/coconut-dkg/src/support/tests/helpers.rs @@ -17,7 +17,6 @@ pub fn init_contract() -> OwnedDeps> let msg = InstantiateMsg { group_addr: String::from(GROUP_CONTRACT), multisig_addr: String::from(MULTISIG_CONTRACT), - admin: String::from(ADMIN_ADDRESS), mix_denom: TEST_MIX_DENOM.to_string(), }; let env = mock_env(); diff --git a/contracts/coconut-dkg/src/verification_key_shares/queries.rs b/contracts/coconut-dkg/src/verification_key_shares/queries.rs index e9c4d00dca..331c42e58a 100644 --- a/contracts/coconut-dkg/src/verification_key_shares/queries.rs +++ b/contracts/coconut-dkg/src/verification_key_shares/queries.rs @@ -45,7 +45,6 @@ pub(crate) mod tests { use crate::verification_key_shares::storage::{ VERIFICATION_KEY_SHARES_PAGE_DEFAULT_LIMIT, VERIFICATION_KEY_SHARES_PAGE_MAX_LIMIT, }; - use cosmwasm_std::testing::mock_env; use cosmwasm_std::Addr; #[test] @@ -58,7 +57,6 @@ pub(crate) mod tests { #[test] fn vk_shares_paged_retrieval_obeys_limits() { let mut deps = init_contract(); - let env = mock_env(); let limit = 2; for n in 0..1000 { let vk_share = vk_share_fixture(n); @@ -75,7 +73,6 @@ pub(crate) mod tests { #[test] fn vk_shares_paged_retrieval_has_default_limit() { let mut deps = init_contract(); - let env = mock_env(); for n in 0..1000 { let vk_share = vk_share_fixture(n); let sender = Addr::unchecked(format!("owner{}", n)); @@ -96,7 +93,6 @@ pub(crate) mod tests { #[test] fn vk_shares_paged_retrieval_has_max_limit() { let mut deps = init_contract(); - let env = mock_env(); for n in 0..1000 { let vk_share = vk_share_fixture(n); let sender = Addr::unchecked(format!("owner{}", n)); @@ -117,7 +113,6 @@ pub(crate) mod tests { #[test] fn vk_shares_pagination_works() { let mut deps = init_contract(); - let env = mock_env(); let vk_share = vk_share_fixture(1); let sender = Addr::unchecked(format!("owner{}", 1)); diff --git a/contracts/coconut-dkg/src/verification_key_shares/transactions.rs b/contracts/coconut-dkg/src/verification_key_shares/transactions.rs index 0f76fc7811..69df1bad7b 100644 --- a/contracts/coconut-dkg/src/verification_key_shares/transactions.rs +++ b/contracts/coconut-dkg/src/verification_key_shares/transactions.rs @@ -73,20 +73,21 @@ pub fn try_verify_verification_key_share( #[cfg(test)] mod tests { use super::*; - use crate::epoch_state::storage::CURRENT_EPOCH_STATE; use crate::epoch_state::transactions::advance_epoch_state; use crate::support::tests::helpers; - use crate::support::tests::helpers::{ADMIN_ADDRESS, MULTISIG_CONTRACT}; + use crate::support::tests::helpers::MULTISIG_CONTRACT; use coconut_dkg_common::dealer::DealerDetails; - use coconut_dkg_common::types::EpochState; + use coconut_dkg_common::types::{ + EpochState, DEALING_EXCHANGE_TIME_SECS, PUBLIC_KEY_SUBMISSION_TIME_SECS, + VERIFICATION_KEY_SUBMISSION_TIME_SECS, VERIFICATION_KEY_VALIDATION_TIME_SECS, + }; use cosmwasm_std::testing::{mock_env, mock_info}; - use cosmwasm_std::Storage; use cw_controllers::AdminError; #[test] fn commit_vk_share() { let mut deps = helpers::init_contract(); - let env = mock_env(); + let mut env = mock_env(); let info = mock_info("requester", &[]); let share = "share".to_string(); @@ -104,8 +105,10 @@ mod tests { expected_state: EpochState::VerificationKeySubmission.to_string() } ); - advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap(); - advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap(); + env.block.time = env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); + env.block.time = env.block.time.plus_seconds(DEALING_EXCHANGE_TIME_SECS); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); let ret = try_commit_verification_key_share( deps.as_mut(), env.clone(), @@ -147,6 +150,7 @@ mod tests { #[test] fn invalid_verify_vk_share() { let mut deps = helpers::init_contract(); + let mut env = mock_env(); let info = mock_info("requester", &[]); let owner = Addr::unchecked("owner"); let multisig_info = mock_info(MULTISIG_CONTRACT, &[]); @@ -161,10 +165,20 @@ mod tests { } ); - advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap(); - advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap(); - advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap(); - advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap(); + env.block.time = env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); + env.block.time = env.block.time.plus_seconds(DEALING_EXCHANGE_TIME_SECS); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); + env.block.time = env + .block + .time + .plus_seconds(VERIFICATION_KEY_SUBMISSION_TIME_SECS); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); + env.block.time = env + .block + .time + .plus_seconds(VERIFICATION_KEY_VALIDATION_TIME_SECS); + advance_epoch_state(deps.as_mut(), env).unwrap(); let ret = try_verify_verification_key_share(deps.as_mut(), info, owner.clone()).unwrap_err(); @@ -183,14 +197,16 @@ mod tests { #[test] fn verify_vk_share() { let mut deps = helpers::init_contract(); - let env = mock_env(); + let mut env = mock_env(); let owner = Addr::unchecked("owner"); let info = mock_info(owner.as_ref(), &[]); let share = "share".to_string(); let multisig_info = mock_info(MULTISIG_CONTRACT, &[]); - advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap(); - advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap(); + env.block.time = env.block.time.plus_seconds(PUBLIC_KEY_SUBMISSION_TIME_SECS); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); + env.block.time = env.block.time.plus_seconds(DEALING_EXCHANGE_TIME_SECS); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); let dealer_details = DealerDetails { address: owner.clone(), @@ -204,8 +220,16 @@ mod tests { try_commit_verification_key_share(deps.as_mut(), env.clone(), info.clone(), share.clone()) .unwrap(); - advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap(); - advance_epoch_state(deps.as_mut(), mock_info(ADMIN_ADDRESS, &[])).unwrap(); + env.block.time = env + .block + .time + .plus_seconds(VERIFICATION_KEY_SUBMISSION_TIME_SECS); + advance_epoch_state(deps.as_mut(), env.clone()).unwrap(); + env.block.time = env + .block + .time + .plus_seconds(VERIFICATION_KEY_VALIDATION_TIME_SECS); + advance_epoch_state(deps.as_mut(), env).unwrap(); try_verify_verification_key_share(deps.as_mut(), multisig_info, owner.clone()).unwrap(); } diff --git a/contracts/coconut-test/src/submit_vk_creates_proposal.rs b/contracts/coconut-test/src/submit_vk_creates_proposal.rs index 15bbd65341..1122115b6d 100644 --- a/contracts/coconut-test/src/submit_vk_creates_proposal.rs +++ b/contracts/coconut-test/src/submit_vk_creates_proposal.rs @@ -71,7 +71,6 @@ fn dkg_proposal() { let msg = DkgInstantiateMsg { group_addr: group_contract_addr.to_string(), multisig_addr: multisig_contract_addr.to_string(), - admin: Addr::unchecked(OWNER).to_string(), mix_denom: TEST_COIN_DENOM.to_string(), }; let coconut_dkg_contract_addr = app @@ -109,6 +108,7 @@ fn dkg_proposal() { .unwrap(); for _ in 0..2 { + app.update_block(|block| block.time = block.time.plus_seconds(1000)); app.execute_contract( Addr::unchecked(OWNER), coconut_dkg_contract_addr.clone(), @@ -175,6 +175,7 @@ fn dkg_proposal() { .unwrap(); for _ in 0..2 { + app.update_block(|block| block.time = block.time.plus_seconds(1000)); app.execute_contract( Addr::unchecked(OWNER), coconut_dkg_contract_addr.clone(), diff --git a/nym-api/src/coconut/client.rs b/nym-api/src/coconut/client.rs index 87a64a4e6e..92af589921 100644 --- a/nym-api/src/coconut/client.rs +++ b/nym-api/src/coconut/client.rs @@ -4,7 +4,7 @@ use crate::coconut::error::Result; use coconut_bandwidth_contract_common::spend_credential::SpendCredentialResponse; use coconut_dkg_common::dealer::{ContractDealing, DealerDetails, DealerDetailsResponse}; -use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, EpochState}; +use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, Epoch}; use coconut_dkg_common::verification_key::{ContractVKShare, VerificationKeyShare}; use contracts_common::dealings::ContractSafeBytes; use cw3::ProposalResponse; @@ -22,7 +22,7 @@ pub trait Client { &self, blinded_serial_number: String, ) -> Result; - async fn get_current_epoch_state(&self) -> Result; + async fn get_current_epoch(&self) -> Result; async fn get_current_epoch_threshold(&self) -> Result>; async fn get_self_registered_dealer_details(&self) -> Result; async fn get_current_dealers(&self) -> Result>; @@ -31,6 +31,7 @@ pub trait Client { async fn vote_proposal(&self, proposal_id: u64, vote_yes: bool, fee: Option) -> Result<()>; async fn execute_proposal(&self, proposal_id: u64) -> Result<()>; + async fn advance_epoch_state(&self) -> Result<()>; async fn register_dealer( &self, bte_key: EncodedBTEPublicKeyWithProof, diff --git a/nym-api/src/coconut/dkg/client.rs b/nym-api/src/coconut/dkg/client.rs index d8a0cf5d69..61b583b84b 100644 --- a/nym-api/src/coconut/dkg/client.rs +++ b/nym-api/src/coconut/dkg/client.rs @@ -4,7 +4,7 @@ use crate::coconut::client::Client; use crate::coconut::error::CoconutError; use coconut_dkg_common::dealer::{ContractDealing, DealerDetails, DealerDetailsResponse}; -use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, EpochState, NodeIndex}; +use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, Epoch, NodeIndex}; use coconut_dkg_common::verification_key::{ContractVKShare, VerificationKeyShare}; use contracts_common::dealings::ContractSafeBytes; use cw3::ProposalResponse; @@ -35,13 +35,13 @@ impl DkgClient { self.inner.address().await } - pub(crate) async fn get_current_epoch_state(&self) -> Result { - let mut ret = self.inner.get_current_epoch_state().await; + pub(crate) async fn get_current_epoch(&self) -> Result { + let mut ret = self.inner.get_current_epoch().await; for _ in 0..Self::RETRIES { if ret.is_ok() { return ret; } - ret = self.inner.get_current_epoch_state().await; + ret = self.inner.get_current_epoch().await; } ret } @@ -86,6 +86,10 @@ impl DkgClient { self.inner.list_proposals().await } + pub(crate) async fn advance_epoch_state(&self) -> Result<(), CoconutError> { + self.inner.advance_epoch_state().await + } + pub(crate) async fn register_dealer( &self, bte_key: EncodedBTEPublicKeyWithProof, diff --git a/nym-api/src/coconut/dkg/controller.rs b/nym-api/src/coconut/dkg/controller.rs index c54074141d..bebb68f4d1 100644 --- a/nym-api/src/coconut/dkg/controller.rs +++ b/nym-api/src/coconut/dkg/controller.rs @@ -18,7 +18,7 @@ use dkg::bte::keys::KeyPair as DkgKeyPair; use rand::rngs::OsRng; use rand::RngCore; use std::path::PathBuf; -use std::time::Duration; +use std::time::{Duration, SystemTime}; use task::TaskClient; use tokio::time::interval; use validator_client::nymd::SigningNymdClient; @@ -83,16 +83,16 @@ impl DkgController { } pub(crate) async fn handle_epoch_state(&mut self) { - match self.dkg_client.get_current_epoch_state().await { + match self.dkg_client.get_current_epoch().await { Err(e) => warn!("Could not get current epoch state {}", e), - Ok(epoch_state) => { - if let Err(e) = self.state.is_consistent(epoch_state).await { + Ok(epoch) => { + if let Err(e) = self.state.is_consistent(epoch.state).await { error!( "Epoch state is corrupted - {}, the process should be terminated", e ); } - let ret = match epoch_state { + let ret = match epoch.state { EpochState::PublicKeySubmission => { public_key_submission(&self.dkg_client, &mut self.state).await } @@ -122,7 +122,7 @@ impl DkgController { }; if let Err(e) = ret { warn!("Could not handle this iteration for the epoch state: {}", e); - } else if epoch_state != EpochState::InProgress { + } else if epoch.state != EpochState::InProgress { let persistent_state = PersistentState::from(&self.state); if let Err(e) = persistent_state.save_to_file(self.state.persistent_state_path()) @@ -130,6 +130,15 @@ impl DkgController { warn!("Could not backup the state for this iteration: {}", e); } } + if let Ok(current_timestamp) = + SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) + { + if current_timestamp.as_secs() >= epoch.finish_timestamp.seconds() { + // We try advancing the epoch state, on a best-effort basis + info!("Trying to advance the epoch"); + self.dkg_client.advance_epoch_state().await.ok(); + } + } } } } diff --git a/nym-api/src/coconut/tests.rs b/nym-api/src/coconut/tests.rs index 3408dda0a3..d0165e1f1e 100644 --- a/nym-api/src/coconut/tests.rs +++ b/nym-api/src/coconut/tests.rs @@ -40,7 +40,7 @@ use coconut_dkg_common::dealer::{ ContractDealing, DealerDetails, DealerDetailsResponse, DealerType, }; use coconut_dkg_common::event_attributes::{DKG_PROPOSAL_ID, NODE_INDEX}; -use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, EpochState, TOTAL_DEALINGS}; +use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, Epoch, TOTAL_DEALINGS}; use coconut_dkg_common::verification_key::{ContractVKShare, VerificationKeyShare}; use contracts_common::dealings::ContractSafeBytes; use crypto::asymmetric::{encryption, identity}; @@ -66,7 +66,7 @@ pub(crate) struct DummyClient { proposal_db: Arc>>, spent_credential_db: Arc>>, - epoch_state: Arc>, + epoch: Arc>, dealer_details: Arc>>, threshold: Arc>>, dealings: Arc>>>, @@ -80,7 +80,7 @@ impl DummyClient { tx_db: Arc::new(RwLock::new(HashMap::new())), proposal_db: Arc::new(RwLock::new(HashMap::new())), spent_credential_db: Arc::new(RwLock::new(HashMap::new())), - epoch_state: Arc::new(RwLock::new(EpochState::default())), + epoch: Arc::new(RwLock::new(Epoch::default())), dealer_details: Arc::new(RwLock::new(HashMap::new())), threshold: Arc::new(RwLock::new(None)), dealings: Arc::new(RwLock::new(HashMap::new())), @@ -109,8 +109,8 @@ impl DummyClient { self } - pub fn _with_epoch_state(mut self, epoch_state: &Arc>) -> Self { - self.epoch_state = Arc::clone(epoch_state); + pub fn _with_epoch(mut self, epoch: &Arc>) -> Self { + self.epoch = Arc::clone(epoch); self } @@ -188,8 +188,8 @@ impl super::client::Client for DummyClient { }) } - async fn get_current_epoch_state(&self) -> Result { - Ok(*self.epoch_state.read().unwrap()) + async fn get_current_epoch(&self) -> Result { + Ok(*self.epoch.read().unwrap()) } async fn get_current_epoch_threshold(&self) -> Result> { @@ -273,6 +273,10 @@ impl super::client::Client for DummyClient { Ok(()) } + async fn advance_epoch_state(&self) -> Result<()> { + todo!() + } + async fn register_dealer( &self, bte_public_key_with_proof: EncodedBTEPublicKeyWithProof, diff --git a/nym-api/src/nymd_client.rs b/nym-api/src/nymd_client.rs index d14a793fd4..f7780b2871 100644 --- a/nym-api/src/nymd_client.rs +++ b/nym-api/src/nymd_client.rs @@ -30,7 +30,7 @@ use coconut_bandwidth_contract_common::spend_credential::SpendCredentialResponse #[cfg(feature = "coconut")] use coconut_dkg_common::dealer::{ContractDealing, DealerDetails, DealerDetailsResponse}; #[cfg(feature = "coconut")] -use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, EpochState}; +use coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, Epoch}; #[cfg(feature = "coconut")] use coconut_dkg_common::verification_key::{ContractVKShare, VerificationKeyShare}; #[cfg(feature = "coconut")] @@ -329,8 +329,8 @@ where .await?) } - async fn get_current_epoch_state(&self) -> crate::coconut::error::Result { - Ok(self.0.read().await.nymd.get_current_epoch_state().await?) + async fn get_current_epoch(&self) -> crate::coconut::error::Result { + Ok(self.0.read().await.nymd.get_current_epoch().await?) } async fn get_current_epoch_threshold( @@ -405,6 +405,16 @@ where Ok(()) } + async fn advance_epoch_state(&self) -> crate::coconut::error::Result<()> { + self.0 + .write() + .await + .nymd + .advance_dkg_epoch_state(None) + .await?; + Ok(()) + } + async fn register_dealer( &self, bte_key: EncodedBTEPublicKeyWithProof, From da094f02087f97bc8b301a28805dd07f82583efb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 16 Dec 2022 12:02:23 +0100 Subject: [PATCH 11/21] wallet: rewrite some abci errors on the fly (#2716) * wallet: rewrite some abci errors on the fly * changelog: update * Tidy --- .../validator-client/src/connection_tester.rs | 2 +- .../src/nymd/cosmwasm_client/client.rs | 10 +--- .../validator-client/src/nymd/error.rs | 55 ++++++++++++++++--- nym-wallet/CHANGELOG.md | 4 ++ nym-wallet/src-tauri/src/error.rs | 33 ++++++++++- 5 files changed, 85 insertions(+), 19 deletions(-) diff --git a/common/client-libs/validator-client/src/connection_tester.rs b/common/client-libs/validator-client/src/connection_tester.rs index dc1acb8cd9..30e57ff95e 100644 --- a/common/client-libs/validator-client/src/connection_tester.rs +++ b/common/client-libs/validator-client/src/connection_tester.rs @@ -108,7 +108,7 @@ async fn test_nymd_connection( log::debug!("Checking: nymd_url: {url}: {}: {}", "failed".red(), e); false } - Ok(Err(NymdError::AbciError(code, log))) => { + Ok(Err(NymdError::AbciError { code, log, .. })) => { // We accept the mixnet contract not found as ok from a connection standpoint. This happens // for example on a pre-launch network. log::debug!( diff --git a/common/client-libs/validator-client/src/nymd/cosmwasm_client/client.rs b/common/client-libs/validator-client/src/nymd/cosmwasm_client/client.rs index 8da9d3192c..580a8c7c05 100644 --- a/common/client-libs/validator-client/src/nymd/cosmwasm_client/client.rs +++ b/common/client-libs/validator-client/src/nymd/cosmwasm_client/client.rs @@ -1,6 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::nymd; use crate::nymd::coin::Coin; use crate::nymd::cosmwasm_client::helpers::{create_pagination, next_page_key}; use crate::nymd::cosmwasm_client::types::{ @@ -23,7 +24,6 @@ use cosmrs::rpc::endpoint::broadcast; use cosmrs::rpc::endpoint::tx::Response as TxResponse; use cosmrs::rpc::query::Query; use cosmrs::rpc::{self, HttpClient, Order}; -use cosmrs::tendermint::abci::Code as AbciCode; use cosmrs::tendermint::abci::Transaction; use cosmrs::tendermint::{abci, block, chain}; use cosmrs::{tx, AccountId, Coin as CosmosCoin, Tx}; @@ -66,13 +66,9 @@ pub trait CosmWasmClient: rpc::Client { req.encode(&mut buf)?; let res = self.abci_query(path, buf, None, false).await?; + let res_success = nymd::error::parse_abci_query_result(res)?; - match res.code { - AbciCode::Err(code) => return Err(NymdError::AbciError(code, res.log)), - AbciCode::Ok => (), - } - - Ok(Res::decode(res.value.as_ref())?) + Ok(Res::decode(res_success.value.as_ref())?) } async fn get_chain_id(&self) -> Result { diff --git a/common/client-libs/validator-client/src/nymd/error.rs b/common/client-libs/validator-client/src/nymd/error.rs index 0b6dcfe22b..e530f6c54d 100644 --- a/common/client-libs/validator-client/src/nymd/error.rs +++ b/common/client-libs/validator-client/src/nymd/error.rs @@ -2,16 +2,23 @@ // SPDX-License-Identifier: Apache-2.0 use crate::nymd::cosmwasm_client::types::ContractCodeId; -use cosmrs::tendermint::{abci, block}; -use cosmrs::{bip32, tx, AccountId}; -use std::io; -use std::time::Duration; +use cosmrs::{ + bip32, + rpc::endpoint::abci_query::AbciQuery, + tendermint::{ + abci::{self, Code as AbciCode}, + block, + }, + tx, AccountId, +}; use thiserror::Error; -pub use cosmrs::rpc::error::{ - Error as TendermintRpcError, ErrorDetail as TendermintRpcErrorDetail, +use std::{io, time::Duration}; + +pub use cosmrs::rpc::{ + error::{Error as TendermintRpcError, ErrorDetail as TendermintRpcErrorDetail}, + response_error::{Code, ResponseError}, }; -pub use cosmrs::rpc::response_error::{Code, ResponseError}; #[derive(Debug, Error)] pub enum NymdError { @@ -110,8 +117,12 @@ pub enum NymdError { #[error("Failed to estimate gas price for the transaction")] GasEstimationFailure, - #[error("Abci query failed with code {0} - {1}")] - AbciError(u32, abci::Log), + #[error("Abci query failed with code {code} - {log}")] + AbciError { + code: u32, + log: abci::Log, + pretty_log: Option, + }, #[error("Unsupported account type: {type_url}")] UnsupportedAccountType { type_url: String }, @@ -135,6 +146,32 @@ pub enum NymdError { UnexpectedBech32Prefix { got: String, expected: String }, } +// The purpose of parsing the abci query result is that we want to generate the `pretty_log` if +// possible. +pub fn parse_abci_query_result(query_result: AbciQuery) -> Result { + match query_result.code { + AbciCode::Ok => Ok(query_result), + AbciCode::Err(code) => Err(NymdError::AbciError { + code, + log: query_result.log.clone(), + pretty_log: try_parse_abci_log(&query_result.log), + }), + } +} + +// Some of the error strings returned by the query are a bit too technical to present to the +// enduser. So we special case some commonly encountered errors. +fn try_parse_abci_log(log: &abci::Log) -> Option { + if log + .value() + .contains("Maximum amount of locked coins has already been pledged") + { + Some("Maximum amount of locked tokens has alredy been used. You can only use up tp 10% of your locked tokens for bonding and delegating.".to_string()) + } else { + None + } +} + impl NymdError { pub fn is_tendermint_response_timeout(&self) -> bool { match &self { diff --git a/nym-wallet/CHANGELOG.md b/nym-wallet/CHANGELOG.md index d6ca3521d9..ef1fb52d15 100644 --- a/nym-wallet/CHANGELOG.md +++ b/nym-wallet/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## UNRELEASED + +- wallet: present some cases of the more technical errors (abci, ..) in a more human readable form. + ## [nym-wallet-v1.1.3](https://github.com/nymtech/nym/releases/tag/nym-wallet-v1.1.3) (2022-12-13) - wallet: improved unbond screen. diff --git a/nym-wallet/src-tauri/src/error.rs b/nym-wallet/src-tauri/src/error.rs index e5a8feeef5..7f5dfe0812 100644 --- a/nym-wallet/src-tauri/src/error.rs +++ b/nym-wallet/src-tauri/src/error.rs @@ -24,9 +24,10 @@ pub enum BackendError { #[from] source: tendermint_rpc::Error, }, - #[error("{source}")] + #[error("{pretty_error}")] NymdError { - #[from] + pretty_error: String, + #[source] source: NymdError, }, #[error("{source}")] @@ -131,6 +132,34 @@ impl Serialize for BackendError { } } +impl From for BackendError { + fn from(source: NymdError) -> Self { + match source { + NymdError::AbciError { + code: _, + log: _, + ref pretty_log, + } => { + if let Some(pretty_log) = pretty_log { + Self::NymdError { + pretty_error: pretty_log.to_string(), + source, + } + } else { + Self::NymdError { + pretty_error: source.to_string(), + source, + } + } + } + nymd_error => Self::NymdError { + pretty_error: nymd_error.to_string(), + source: nymd_error, + }, + } + } +} + impl From for BackendError { fn from(e: ValidatorClientError) -> Self { match e { From 052a9a71c2411cf114aa6fe27719eee0b465c89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 16 Dec 2022 17:03:39 +0100 Subject: [PATCH 12/21] client: tweak shutdown order (#2724) * clients: slightly tweak shutdown * tweak log --- .../retransmission_request_listener.rs | 2 +- common/task/src/manager.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs index 50a930b94e..d8fb2b0a8d 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs @@ -149,7 +149,7 @@ where break; } }, - _ = shutdown.recv_with_delay() => { + _ = shutdown.recv() => { log::trace!("RetransmissionRequestListener: Received shutdown"); } } diff --git a/common/task/src/manager.rs b/common/task/src/manager.rs index 82129e9478..f40a525527 100644 --- a/common/task/src/manager.rs +++ b/common/task/src/manager.rs @@ -158,7 +158,7 @@ impl TaskManager { } pub async fn wait_for_shutdown(&mut self) { - log::info!("Waiting for shutdown"); + log::debug!("Waiting for shutdown"); if let Some(notify_rx) = self.notify_rx.take() { drop(notify_rx); } @@ -269,7 +269,7 @@ impl TaskClient { pub async fn recv_with_delay(&mut self) { self.recv() .then(|msg| async move { - sleep(Duration::from_secs(1)).await; + sleep(Duration::from_secs(2)).await; msg }) .await From 6c4f0bc2f498e3f6fb9e11f16c98064cd62495a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 19 Dec 2022 09:12:33 +0100 Subject: [PATCH 13/21] validator-client: fix typo in error message --- common/client-libs/validator-client/src/nymd/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/client-libs/validator-client/src/nymd/error.rs b/common/client-libs/validator-client/src/nymd/error.rs index e530f6c54d..1ebaa4e020 100644 --- a/common/client-libs/validator-client/src/nymd/error.rs +++ b/common/client-libs/validator-client/src/nymd/error.rs @@ -166,7 +166,7 @@ fn try_parse_abci_log(log: &abci::Log) -> Option { .value() .contains("Maximum amount of locked coins has already been pledged") { - Some("Maximum amount of locked tokens has alredy been used. You can only use up tp 10% of your locked tokens for bonding and delegating.".to_string()) + Some("Maximum amount of locked tokens has alredy been used. You can only use up to 10% of your locked tokens for bonding and delegating.".to_string()) } else { None } From 7c12a3422cb6ad0d2fcca2f046c89f81f62ae640 Mon Sep 17 00:00:00 2001 From: Fouad Date: Mon, 19 Dec 2022 11:22:51 +0000 Subject: [PATCH 14/21] Feature/node settings apy playground (#1677) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * initial ui for test my node use svg for node path add stories for test my node * add initial rewards calculation * update validation for rewards playground * init playground with default values * get node uptime * get mixnode reward estimation * calculate saturation calculate stake saturation * Make ComputeRewardEstParam derive Debug * set active set to be always true Co-authored-by: Jon Häggblad --- .../validator-client/src/nym_api/mod.rs | 28 +++- .../validator-client/src/nym_api/routes.rs | 1 + nym-api/nym-api-requests/src/models.rs | 2 +- nym-wallet/src-tauri/src/main.rs | 3 + .../src-tauri/src/operations/mixnet/bond.rs | 15 ++ .../src/operations/mixnet/rewards.rs | 16 +- .../src/operations/nym_api/status.rs | 31 +++- nym-wallet/src/components/AppBar.tsx | 2 +- .../InclusionProbability.tsx | 19 +++ .../components/RewardsPlayground/Inputs.tsx | 91 ++++++++++++ .../RewardsPlayground/NodeDetail.tsx | 32 ++++ .../RewardsPlayground/ResultsTable.tsx | 75 ++++++++++ .../inputsValidationSchema.ts | 41 ++++++ nym-wallet/src/context/bonding.tsx | 15 +- nym-wallet/src/context/mocks/bonding.tsx | 4 +- .../bonding/node-settings/NodeSettings.tsx | 4 +- .../node-settings/apy-playground/index.tsx | 139 ++++++++++++++++++ .../node-settings/apy-playground/utils.tsx | 66 +++++++++ .../node-settings/node-settings.constant.tsx | 2 +- nym-wallet/src/requests/queries.ts | 15 ++ nym-wallet/src/requests/rewards.ts | 5 +- nym-wallet/src/types/rust/AppEnv.ts | 7 +- nym-wallet/src/types/rust/Network.ts | 3 +- nym-wallet/src/types/rust/StateParams.ts | 8 +- nym-wallet/src/types/rust/ValidatorUrl.ts | 6 +- nym-wallet/src/types/rust/ValidatorUrls.ts | 6 +- ts-packages/mui-theme/src/theme/theme.ts | 1 + ts-packages/types/src/types/rust/Account.ts | 1 + .../types/src/types/rust/AccountEntry.ts | 2 + .../src/types/rust/AccountWithMnemonic.ts | 1 + ts-packages/types/src/types/rust/Balance.ts | 1 + ts-packages/types/src/types/rust/Coin.ts | 2 + ts-packages/types/src/types/rust/CosmosFee.ts | 1 + .../types/src/types/rust/CurrencyDenom.ts | 2 + ts-packages/types/src/types/rust/DecCoin.ts | 1 + .../types/src/types/rust/Delegation.ts | 1 + .../types/src/types/rust/DelegationEvent.ts | 1 + .../src/types/rust/DelegationEventKind.ts | 2 + .../types/src/types/rust/DelegationResult.ts | 1 + .../types/rust/DelegationSummaryResponse.ts | 1 + .../types/rust/DelegationWithEverything.ts | 1 + ts-packages/types/src/types/rust/Fee.ts | 1 + .../types/src/types/rust/FeeDetails.ts | 1 + ts-packages/types/src/types/rust/Gas.ts | 2 + ts-packages/types/src/types/rust/GasInfo.ts | 1 + ts-packages/types/src/types/rust/Gateway.ts | 2 + .../types/src/types/rust/GatewayBond.ts | 1 + .../rust/InclusionProbabilityResponse.ts | 1 + ts-packages/types/src/types/rust/Interval.ts | 2 +- .../types/src/types/rust/MixNodeBond.ts | 1 + ts-packages/types/src/types/rust/Mixnode.ts | 2 + .../types/src/types/rust/MixnodeStatus.ts | 2 + .../src/types/rust/MixnodeStatusResponse.ts | 1 + .../src/types/rust/OriginalVestingResponse.ts | 1 + ts-packages/types/src/types/rust/Period.ts | 2 + .../types/src/types/rust/PledgeData.ts | 1 + .../src/types/rust/RewardedSetNodeStatus.ts | 2 + .../src/types/rust/RpcTransactionResponse.ts | 1 + .../types/src/types/rust/SendTxResult.ts | 1 + .../src/types/rust/StakeSaturationResponse.ts | 2 + .../src/types/rust/TransactionDetails.ts | 1 + .../types/rust/TransactionExecuteResult.ts | 1 + .../src/types/rust/VestingAccountInfo.ts | 1 + .../types/src/types/rust/VestingPeriod.ts | 2 + ts-packages/types/src/utils/decimal/index.ts | 3 + 65 files changed, 661 insertions(+), 29 deletions(-) create mode 100644 nym-wallet/src/components/RewardsPlayground/InclusionProbability.tsx create mode 100644 nym-wallet/src/components/RewardsPlayground/Inputs.tsx create mode 100644 nym-wallet/src/components/RewardsPlayground/NodeDetail.tsx create mode 100644 nym-wallet/src/components/RewardsPlayground/ResultsTable.tsx create mode 100644 nym-wallet/src/components/RewardsPlayground/inputsValidationSchema.ts create mode 100644 nym-wallet/src/pages/bonding/node-settings/apy-playground/index.tsx create mode 100644 nym-wallet/src/pages/bonding/node-settings/apy-playground/utils.tsx 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 00fd839d4e..e1d65959c6 100644 --- a/common/client-libs/validator-client/src/nym_api/mod.rs +++ b/common/client-libs/validator-client/src/nym_api/mod.rs @@ -9,10 +9,11 @@ use nym_api_requests::coconut::{ BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse, }; use nym_api_requests::models::{ - GatewayCoreStatusResponse, GatewayStatusReportResponse, GatewayUptimeHistoryResponse, - InclusionProbabilityResponse, MixNodeBondAnnotated, MixnodeCoreStatusResponse, - MixnodeStatusReportResponse, MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RequestError, - RewardEstimationResponse, StakeSaturationResponse, UptimeResponse, + ComputeRewardEstParam, GatewayCoreStatusResponse, GatewayStatusReportResponse, + GatewayUptimeHistoryResponse, InclusionProbabilityResponse, MixNodeBondAnnotated, + MixnodeCoreStatusResponse, MixnodeStatusReportResponse, MixnodeStatusResponse, + MixnodeUptimeHistoryResponse, RequestError, RewardEstimationResponse, StakeSaturationResponse, + UptimeResponse, }; use reqwest::Response; use serde::{Deserialize, Serialize}; @@ -361,6 +362,25 @@ impl Client { .await } + pub async fn compute_mixnode_reward_estimation( + &self, + mix_id: MixId, + request_body: &ComputeRewardEstParam, + ) -> Result { + self.post_nym_api( + &[ + routes::API_VERSION, + routes::STATUS_ROUTES, + routes::MIXNODE, + &mix_id.to_string(), + routes::COMPUTE_REWARD_ESTIMATION, + ], + NO_PARAMS, + request_body, + ) + .await + } + pub async fn get_mixnode_stake_saturation( &self, mix_id: MixId, 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 5b3d1c266d..cd8a16047a 100644 --- a/common/client-libs/validator-client/src/nym_api/routes.rs +++ b/common/client-libs/validator-client/src/nym_api/routes.rs @@ -28,6 +28,7 @@ pub const STATUS: &str = "status"; pub const REPORT: &str = "report"; pub const HISTORY: &str = "history"; pub const REWARD_ESTIMATION: &str = "reward-estimation"; +pub const COMPUTE_REWARD_ESTIMATION: &str = "compute-reward-estimation"; pub const AVG_UPTIME: &str = "avg_uptime"; pub const STAKE_SATURATION: &str = "stake-saturation"; pub const INCLUSION_CHANCE: &str = "inclusion-probability"; diff --git a/nym-api/nym-api-requests/src/models.rs b/nym-api/nym-api-requests/src/models.rs index eee713a701..df5fe07768 100644 --- a/nym-api/nym-api-requests/src/models.rs +++ b/nym-api/nym-api-requests/src/models.rs @@ -114,7 +114,7 @@ impl MixNodeBondAnnotated { } } -#[derive(Deserialize, JsonSchema)] +#[derive(Debug, Serialize, Deserialize, JsonSchema)] pub struct ComputeRewardEstParam { pub performance: Option, pub active_in_rewarded_set: Option, diff --git a/nym-wallet/src-tauri/src/main.rs b/nym-wallet/src-tauri/src/main.rs index 63e2a43e4f..8705891c0a 100644 --- a/nym-wallet/src-tauri/src/main.rs +++ b/nym-wallet/src-tauri/src/main.rs @@ -83,7 +83,9 @@ fn main() { mixnet::rewards::claim_delegator_reward, mixnet::rewards::claim_operator_reward, mixnet::rewards::claim_locked_and_unlocked_delegator_reward, + mixnet::rewards::get_current_rewarding_parameters, mixnet::send::send, + mixnet::bond::get_mixnode_uptime, network_config::add_validator, network_config::get_nym_api_urls, network_config::get_validator_nymd_urls, @@ -99,6 +101,7 @@ fn main() { utils::get_old_and_incorrect_hardcoded_fee, utils::try_convert_pubkey_to_mix_id, utils::default_mixnode_cost_params, + nym_api::status::compute_mixnode_reward_estimation, nym_api::status::gateway_core_node_status, nym_api::status::mixnode_core_node_status, nym_api::status::mixnode_inclusion_probability, diff --git a/nym-wallet/src-tauri/src/operations/mixnet/bond.rs b/nym-wallet/src-tauri/src/operations/mixnet/bond.rs index 5807fb7270..1ccdc243ae 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/bond.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/bond.rs @@ -341,3 +341,18 @@ pub async fn get_mix_node_description( .json() .await?) } + +#[tauri::command] +pub async fn get_mixnode_uptime( + mix_id: MixId, + state: tauri::State<'_, WalletState>, +) -> Result { + log::info!(">>> Get mixnode uptime"); + + let guard = state.read().await; + let client = guard.current_client()?; + let uptime = client.nym_api.get_mixnode_avg_uptime(mix_id).await?; + + log::info!(">>> Uptime response: {}", uptime.avg_uptime); + Ok(uptime.avg_uptime) +} diff --git a/nym-wallet/src-tauri/src/operations/mixnet/rewards.rs b/nym-wallet/src-tauri/src/operations/mixnet/rewards.rs index 6fb8893ee9..b4a048eeea 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/rewards.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/rewards.rs @@ -1,7 +1,7 @@ use crate::error::BackendError; use crate::state::WalletState; use crate::vesting::rewards::vesting_claim_delegator_reward; -use mixnet_contract_common::MixId; +use mixnet_contract_common::{MixId, RewardingParams}; use nym_types::transaction::TransactionExecuteResult; use validator_client::nymd::traits::{MixnetQueryClient, MixnetSigningClient}; use validator_client::nymd::Fee; @@ -95,3 +95,17 @@ pub async fn claim_locked_and_unlocked_delegator_reward( log::trace!("<<< {:?}", res); Ok(res) } + +#[tauri::command] +pub async fn get_current_rewarding_parameters( + state: tauri::State<'_, WalletState>, +) -> Result { + log::info!(">>> Get current rewarding params",); + + let guard = state.read().await; + let client = guard.current_client()?; + + let reward_params = client.nymd.get_rewarding_parameters().await?; + + Ok(reward_params) +} diff --git a/nym-wallet/src-tauri/src/operations/nym_api/status.rs b/nym-wallet/src-tauri/src/operations/nym_api/status.rs index 16c83cfb67..873a1fa0a4 100644 --- a/nym-wallet/src-tauri/src/operations/nym_api/status.rs +++ b/nym-wallet/src-tauri/src/operations/nym_api/status.rs @@ -4,11 +4,11 @@ use crate::api_client; use crate::error::BackendError; use crate::state::WalletState; -use mixnet_contract_common::{IdentityKeyRef, MixId}; +use mixnet_contract_common::{reward_params::Performance, Coin, IdentityKeyRef, MixId, Percent}; use validator_client::models::{ - GatewayCoreStatusResponse, GatewayStatusReportResponse, InclusionProbabilityResponse, - MixnodeCoreStatusResponse, MixnodeStatusResponse, RewardEstimationResponse, - StakeSaturationResponse, + ComputeRewardEstParam, GatewayCoreStatusResponse, GatewayStatusReportResponse, + InclusionProbabilityResponse, MixnodeCoreStatusResponse, MixnodeStatusResponse, + RewardEstimationResponse, StakeSaturationResponse, }; #[tauri::command] @@ -59,6 +59,29 @@ pub async fn mixnode_reward_estimation( .await?) } +#[tauri::command] +pub async fn compute_mixnode_reward_estimation( + mix_id: u32, + performance: Option, + pledge_amount: Option, + total_delegation: Option, + interval_operating_cost: Option, + profit_margin_percent: Option, + state: tauri::State<'_, WalletState>, +) -> Result { + let request_body = ComputeRewardEstParam { + performance, + active_in_rewarded_set: Some(true), + pledge_amount, + total_delegation, + interval_operating_cost, + profit_margin_percent, + }; + Ok(api_client!(state) + .compute_mixnode_reward_estimation(mix_id, &request_body) + .await?) +} + #[tauri::command] pub async fn mixnode_stake_saturation( mix_id: MixId, diff --git a/nym-wallet/src/components/AppBar.tsx b/nym-wallet/src/components/AppBar.tsx index 24b2f93942..3022646798 100644 --- a/nym-wallet/src/components/AppBar.tsx +++ b/nym-wallet/src/components/AppBar.tsx @@ -15,7 +15,7 @@ export const AppBar = () => { const navigate = useNavigate(); return ( - + diff --git a/nym-wallet/src/components/RewardsPlayground/InclusionProbability.tsx b/nym-wallet/src/components/RewardsPlayground/InclusionProbability.tsx new file mode 100644 index 0000000000..d60f7886c7 --- /dev/null +++ b/nym-wallet/src/components/RewardsPlayground/InclusionProbability.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Typography } from '@mui/material'; +import { SelectionChance } from '@nymproject/types'; + +const colorMap: { [key in SelectionChance]: string } = { + Low: 'error.main', + Good: 'warning.main', + High: 'success.main', +}; + +const textMap: { [key in SelectionChance]: string } = { + Low: 'Low', + Good: 'Good', + High: 'High', +}; + +export const InclusionProbability = ({ probability }: { probability: SelectionChance }) => ( + {textMap[probability]} +); diff --git a/nym-wallet/src/components/RewardsPlayground/Inputs.tsx b/nym-wallet/src/components/RewardsPlayground/Inputs.tsx new file mode 100644 index 0000000000..1f1dbac935 --- /dev/null +++ b/nym-wallet/src/components/RewardsPlayground/Inputs.tsx @@ -0,0 +1,91 @@ +import React, { useCallback } from 'react'; +import { yupResolver } from '@hookform/resolvers/yup'; +import { Button, Grid, TextField, Typography } from '@mui/material'; +import { useForm } from 'react-hook-form'; +import { DefaultInputValues } from 'src/pages/bonding/node-settings/apy-playground'; +import { inputValidationSchema } from './inputsValidationSchema'; + +export type InputFields = { + label: string; + name: 'profitMargin' | 'uptime' | 'bond' | 'delegations' | 'operatorCost' | 'uptime'; + isPercentage?: boolean; +}[]; + +export type CalculateArgs = { + bond: string; + delegations: string; + uptime: string; + profitMargin: string; + operatorCost: string; +}; + +const inputFields: InputFields = [ + { label: 'Profit margin', name: 'profitMargin', isPercentage: true }, + { label: 'Operator cost', name: 'operatorCost' }, + { label: 'Bond', name: 'bond' }, + { label: 'Delegations', name: 'delegations' }, + { label: 'Uptime', name: 'uptime', isPercentage: true }, +]; + +export const Inputs = ({ + onCalculate, + defaultValues, +}: { + onCalculate: (args: CalculateArgs) => Promise; + defaultValues: DefaultInputValues; +}) => { + const handleCalculate = useCallback( + async (args: CalculateArgs) => { + onCalculate({ + bond: args.bond, + delegations: args.delegations, + uptime: args.uptime, + profitMargin: args.profitMargin, + operatorCost: args.operatorCost, + }); + }, + [onCalculate], + ); + + const { + register, + handleSubmit, + formState: { errors }, + } = useForm({ + resolver: yupResolver(inputValidationSchema), + defaultValues, + }); + + return ( + + {inputFields.map((field) => ( + + {field.isPercentage ? '%' : 'NYM'}, + }} + InputLabelProps={{ shrink: true }} + /> + + ))}{' '} + + + + + ); +}; diff --git a/nym-wallet/src/components/RewardsPlayground/NodeDetail.tsx b/nym-wallet/src/components/RewardsPlayground/NodeDetail.tsx new file mode 100644 index 0000000000..fb8a239be0 --- /dev/null +++ b/nym-wallet/src/components/RewardsPlayground/NodeDetail.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { Card, CardContent, Divider, Stack, Typography } from '@mui/material'; +import { SelectionChance } from '@nymproject/types'; +import { InclusionProbability } from './InclusionProbability'; + +const computeSelectionProbability = (saturation: number): SelectionChance => { + if (saturation < 5) return 'Low'; + + if (saturation > 5 && saturation < 15) return 'Good'; + + return 'High'; +}; + +export const NodeDetails = ({ saturation }: { saturation?: string }) => { + if (!saturation) return null; + + return ( + + + + Stake saturation + {saturation || '- '}% + + + + Selection probability + + + + + ); +}; diff --git a/nym-wallet/src/components/RewardsPlayground/ResultsTable.tsx b/nym-wallet/src/components/RewardsPlayground/ResultsTable.tsx new file mode 100644 index 0000000000..19196c176d --- /dev/null +++ b/nym-wallet/src/components/RewardsPlayground/ResultsTable.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import { + Card, + CardContent, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Typography, +} from '@mui/material'; + +export type Results = { + operator: { + daily: string; + monthly: string; + yearly: string; + }; + delegator: { + daily: string; + monthly: string; + yearly: string; + }; + total: { + daily: string; + monthly: string; + yearly: string; + }; +}; + +const tableHeader = [ + { title: 'Estimated rewards', bold: true }, + { title: 'Per day' }, + { title: 'Per month' }, + { title: 'Per year' }, +]; + +export const ResultsTable = ({ results }: { results: Results }) => { + const tableRows = [ + { title: 'Total node reward', ...results.total }, + { title: 'Operator rewards', ...results.operator }, + { title: 'Delegator rewards', ...results.delegator }, + ]; + + return ( + + + + + + + {tableHeader.map((header) => ( + + {header.title} + + ))} + + + + {tableRows.map((row) => ( + + {row.title} + {row.daily} + {row.monthly} + {row.yearly} + + ))} + +
+
+
+
+ ); +}; diff --git a/nym-wallet/src/components/RewardsPlayground/inputsValidationSchema.ts b/nym-wallet/src/components/RewardsPlayground/inputsValidationSchema.ts new file mode 100644 index 0000000000..ef5d9ecc0d --- /dev/null +++ b/nym-wallet/src/components/RewardsPlayground/inputsValidationSchema.ts @@ -0,0 +1,41 @@ +import * as Yup from 'yup'; +import { isGreaterThan, isLessThan } from 'src/utils'; + +export const inputValidationSchema = Yup.object().shape({ + profitMargin: Yup.string() + .required('profit margin is a required field') + .test('Is valid profit margin value', (value, ctx) => { + const stringValueToNumber = Math.round(Number(value)); + + if (isGreaterThan(stringValueToNumber, -1) && isLessThan(stringValueToNumber, 101)) return true; + return ctx.createError({ message: 'Profit margin must be a number from 0 and 100' }); + }), + uptime: Yup.string() + .required() + .test('Is valid uptime value', (value, ctx) => { + const stringValueToNumber = Math.round(Number(value)); + if (stringValueToNumber && isGreaterThan(stringValueToNumber, 0) && isLessThan(stringValueToNumber, 101)) + return true; + return ctx.createError({ message: 'Uptime must be a number between 0 and 100' }); + }), + bond: Yup.string() + .required() + .test('Is valid bond value', (value, ctx) => { + if (Number(value)) return true; + return ctx.createError({ message: 'Bond must be a valid number' }); + }), + delegations: Yup.string() + .required() + .test('Is valid delegation value', (value, ctx) => { + if (Number(value)) return true; + return ctx.createError({ message: 'Delegations must be a valid number' }); + }), + operatorCost: Yup.string() + .required('operator cost is a required field') + .test('Is valid operator cost value', (value, ctx) => { + const stringValueToNumber = Math.round(Number(value)); + + if (isGreaterThan(stringValueToNumber, -1) && isLessThan(stringValueToNumber, 101)) return true; + return ctx.createError({ message: 'Operator cost must be a valid number' }); + }), +}); diff --git a/nym-wallet/src/context/bonding.tsx b/nym-wallet/src/context/bonding.tsx index 7225360456..94bf5271ca 100644 --- a/nym-wallet/src/context/bonding.tsx +++ b/nym-wallet/src/context/bonding.tsx @@ -24,7 +24,6 @@ import { vestingBondMixNode, vestingUnbondGateway, vestingUnbondMixnode, - getPendingEpochEvents, updateMixnodeCostParams as updateMixnodeCostParamsRequest, vestingUpdateMixnodeCostParams as updateMixnodeVestingCostParamsRequest, getNodeDescription as getNodeDescriptionRequest, @@ -36,6 +35,7 @@ import { getMixnodeAvgUptime, getMixnodeRewardEstimation, getGatewayReport, + getMixnodeUptime, } from '../requests'; import { useCheckOwnership } from '../hooks/useCheckOwnership'; import { AppContext } from './main'; @@ -71,10 +71,12 @@ export type TBondedMixnode = { verlocPort: number; version: string; isUnbonding: boolean; + uptime: number; }; export interface TBondedGateway { - name: string; + name?: string; + id: number; identityKey: string; ip: string; bond: DecCoin; @@ -154,14 +156,18 @@ export const BondingContextProvider = ({ children }: { children?: React.ReactNod status: MixnodeStatus; stakeSaturation: string; estimatedRewards?: DecCoin; + uptime: number; } = { status: 'not_found', stakeSaturation: '0', + uptime: 0, }; try { const statusResponse = await getMixnodeStatus(mixId); + const uptime = await getMixnodeUptime(mixId); additionalDetails.status = statusResponse.status; + additionalDetails.uptime = uptime; } catch (e) { Console.log('getMixnodeStatus fails', e); } @@ -259,7 +265,8 @@ export const BondingContextProvider = ({ children }: { children?: React.ReactNod rewarding_details, bond_information: { mix_id }, } = data; - const { status, stakeSaturation, estimatedRewards } = await getAdditionalMixnodeDetails(mix_id); + + const { status, stakeSaturation, estimatedRewards, uptime } = await getAdditionalMixnodeDetails(mix_id); const setProbabilities = await getSetProbabilities(mix_id); const nodeDescription = await getNodeDescription( bond_information.mix_node.host, @@ -267,6 +274,7 @@ export const BondingContextProvider = ({ children }: { children?: React.ReactNod ); const routingScore = await getAvgUptime(); setBondedNode({ + id: data.bond_information.mix_id, name: nodeDescription?.name, mixId: mix_id, identityKey: bond_information.mix_node.identity_key, @@ -279,6 +287,7 @@ export const BondingContextProvider = ({ children }: { children?: React.ReactNod delegators: rewarding_details.unique_delegations, proxy: bond_information.proxy, operatorRewards, + uptime, status, stakeSaturation, operatorCost: decCoinToDisplay(rewarding_details.cost_params.interval_operating_cost), diff --git a/nym-wallet/src/context/mocks/bonding.tsx b/nym-wallet/src/context/mocks/bonding.tsx index 95e770850b..f38168ee28 100644 --- a/nym-wallet/src/context/mocks/bonding.tsx +++ b/nym-wallet/src/context/mocks/bonding.tsx @@ -7,8 +7,8 @@ import { mockSleep } from './utils'; const SLEEP_MS = 1000; const bondedMixnodeMock: TBondedMixnode = { - name: 'Monster node', mixId: 1, + name: 'Monster node', identityKey: '7mjM2fYbtN6kxMwp1TrmQ4VwPks3URR5pBgWPWhzT98F', stake: { denom: 'nym', amount: '1234' }, bond: { denom: 'nym', amount: '1234' }, @@ -28,9 +28,11 @@ const bondedMixnodeMock: TBondedMixnode = { verlocPort: 1790, version: '1.0.2', isUnbonding: false, + uptime: 1, }; const bondedGatewayMock: TBondedGateway = { + id: 1, name: 'Monster node', identityKey: 'WayM2fYbtN6kxMwp1TrmQ4VwPks3URR5pBgWPWhzT98F', ip: '112.43.234.57', diff --git a/nym-wallet/src/pages/bonding/node-settings/NodeSettings.tsx b/nym-wallet/src/pages/bonding/node-settings/NodeSettings.tsx index da50bc2d2d..798993dc49 100644 --- a/nym-wallet/src/pages/bonding/node-settings/NodeSettings.tsx +++ b/nym-wallet/src/pages/bonding/node-settings/NodeSettings.tsx @@ -10,13 +10,14 @@ import { LoadingModal } from 'src/components/Modals/LoadingModal'; import { NymCard } from 'src/components'; import { PageLayout } from 'src/layouts'; import { Tabs } from 'src/components/Tabs'; -import { useBondingContext, BondingContextProvider } from 'src/context'; +import { useBondingContext, BondingContextProvider, TBondedMixnode } from 'src/context'; import { AppContext, urls } from 'src/context/main'; import { NodeGeneralSettings } from './settings-pages/general-settings'; import { NodeUnbondPage } from './settings-pages/NodeUnbondPage'; import { createNavItems } from './node-settings.constant'; import { isMixnode } from 'src/types'; +import { ApyPlayground } from './apy-playground'; export const NodeSettings = () => { const theme = useTheme(); @@ -123,6 +124,7 @@ export const NodeSettings = () => { {value === 'Unbond' && bondedNode && ( )} + {value === 'Playground' && bondedNode && } {confirmationDetails && confirmationDetails.status === 'success' && ( { + const { enqueueSnackbar } = useSnackbar(); + + const [results, setResults] = useState({ + total: { daily: '-', monthly: '-', yearly: '-' }, + operator: { daily: '-', monthly: '-', yearly: '-' }, + delegator: { daily: '-', monthly: '-', yearly: '-' }, + }); + + const [defaultInputValues, setDefaultInputValues] = useState(); + const [stakeSaturation, setStakeSaturation] = useState(); + const [isLoading, setIsLoading] = useState(true); + + const initialise = async (node: TBondedMixnode) => { + try { + const delegations = await getDelegationSummary(); + + const { estimation } = await computeEstimate({ + mixId: node.mixId, + uptime: node.uptime.toString(), + profitMargin: node.profitMargin, + operatorCost: node.operatorCost.amount, + totalDelegation: delegations.total_delegations.amount, + pledgeAmount: node.bond.amount, + }); + + setResults( + handleCalculatePeriodRewards({ + estimatedOperatorReward: estimation.operator, + estimatedDelegatorsReward: estimation.delegates, + }), + ); + + setStakeSaturation(node.stakeSaturation); + + setDefaultInputValues({ + profitMargin: node.profitMargin, + uptime: (node.uptime || 0).toString(), + bond: node.bond.amount || '', + delegations: delegations.total_delegations.amount, + operatorCost: node.operatorCost.amount, + }); + setIsLoading(false); + } catch (e) { + enqueueSnackbar(e as string, { variant: 'error' }); + } + }; + + useEffect(() => { + if (bondedNode) { + initialise(bondedNode); + } + }, []); + + if (isLoading) return ; + + const handleCalculateEstimate = async ({ bond, delegations, uptime, profitMargin, operatorCost }: CalculateArgs) => { + try { + const { estimation, reward_params } = await computeEstimate({ + mixId: bondedNode.mixId, + uptime: uptime, + profitMargin: profitMargin, + operatorCost: operatorCost, + totalDelegation: delegations, + pledgeAmount: bond, + }); + + const estimationResult = handleCalculatePeriodRewards({ + estimatedOperatorReward: estimation.operator, + estimatedDelegatorsReward: estimation.delegates, + }); + + const computedStakeSaturation = computeStakeSaturation( + bond, + delegations, + reward_params.interval.stake_saturation_point, + ); + + setStakeSaturation(computedStakeSaturation); + setResults(estimationResult); + } catch (e) { + console.log(e); + } + }; + + return ( + + + Playground + + + This is your parameters playground - change the parameters below to see the node specific estimations in the + table + + {defaultInputValues && ( + + + Estimation calculator + + } + /> + + + + + )} + + + + + + + + + + ); +}; diff --git a/nym-wallet/src/pages/bonding/node-settings/apy-playground/utils.tsx b/nym-wallet/src/pages/bonding/node-settings/apy-playground/utils.tsx new file mode 100644 index 0000000000..bc99898b45 --- /dev/null +++ b/nym-wallet/src/pages/bonding/node-settings/apy-playground/utils.tsx @@ -0,0 +1,66 @@ +import { decimalToPercentage, percentToDecimal } from '@nymproject/types'; +import { computeMixnodeRewardEstimation } from 'src/requests'; + +const SCALE_FACTOR = 1_000_000; + +export const computeStakeSaturation = (bond: string, delegations: string, stakeSaturationPoint: string) => { + const res = ((+bond + +delegations) * SCALE_FACTOR) / +stakeSaturationPoint; + return decimalToPercentage(res.toFixed(18).toString()); +}; + +export const computeEstimate = async ({ + mixId, + uptime, + pledgeAmount, + totalDelegation, + profitMargin, + operatorCost, +}: { + mixId: number; + uptime: string; + pledgeAmount: string; + totalDelegation: string; + profitMargin: string; + operatorCost: string; +}) => { + const computedEstimate = await computeMixnodeRewardEstimation({ + mixId: mixId, + performance: percentToDecimal(uptime), + pledgeAmount: Math.round(+pledgeAmount * SCALE_FACTOR), + totalDelegation: Math.round(+totalDelegation * SCALE_FACTOR), + profitMarginPercent: percentToDecimal(profitMargin), + intervalOperatingCost: { denom: 'unym', amount: Math.round(+operatorCost * SCALE_FACTOR).toString() }, + }); + + return computedEstimate; +}; + +export const handleCalculatePeriodRewards = ({ + estimatedOperatorReward, + estimatedDelegatorsReward, +}: { + estimatedOperatorReward: string; + estimatedDelegatorsReward: string; +}) => { + const dailyOperatorReward = (+estimatedOperatorReward / SCALE_FACTOR) * 24; // epoch_reward * 1 epoch_per_hour * 24 hours + const dailyDelegatorReward = (+estimatedDelegatorsReward / SCALE_FACTOR) * 24; + const dailyTotal = dailyOperatorReward + dailyDelegatorReward; + + return { + total: { + daily: dailyTotal.toFixed(3).toString(), + monthly: (dailyTotal * 30).toFixed(3).toString(), + yearly: (dailyTotal * 365).toFixed(3).toString(), + }, + operator: { + daily: dailyOperatorReward.toFixed(3).toString(), + monthly: (dailyOperatorReward * 30).toFixed(3).toString(), + yearly: (dailyOperatorReward * 365).toFixed(3).toString(), + }, + delegator: { + daily: dailyDelegatorReward.toFixed(3).toString(), + monthly: (dailyDelegatorReward * 30).toFixed(3).toString(), + yearly: (dailyDelegatorReward * 365).toFixed(3).toString(), + }, + }; +}; diff --git a/nym-wallet/src/pages/bonding/node-settings/node-settings.constant.tsx b/nym-wallet/src/pages/bonding/node-settings/node-settings.constant.tsx index f00409a182..0e8b6204fd 100644 --- a/nym-wallet/src/pages/bonding/node-settings/node-settings.constant.tsx +++ b/nym-wallet/src/pages/bonding/node-settings/node-settings.constant.tsx @@ -1,5 +1,5 @@ export const createNavItems = (isMixnode: boolean) => { const navItems = ['Unbond']; - if (isMixnode) return ['General', ...navItems]; + if (isMixnode) return ['General', 'Playground', ...navItems]; return navItems; }; diff --git a/nym-wallet/src/requests/queries.ts b/nym-wallet/src/requests/queries.ts index 5fba51beec..640fc79abb 100644 --- a/nym-wallet/src/requests/queries.ts +++ b/nym-wallet/src/requests/queries.ts @@ -8,6 +8,7 @@ import { RewardEstimationResponse, WrappedDelegationEvent, PendingIntervalEvent, + Coin, } from '@nymproject/types'; import { Interval, TGatewayReport, TNodeDescription } from 'src/types'; import { invokeWrapper } from './wrapper'; @@ -51,3 +52,17 @@ export const getPendingIntervalEvents = async () => export const getGatewayReport = async (identity: string) => invokeWrapper('gateway_report', { identity }); + +export const computeMixnodeRewardEstimation = async (args: { + mixId: number; + performance: string; + pledgeAmount: number; + totalDelegation: number; + profitMarginPercent: string; + intervalOperatingCost: { denom: 'unym'; amount: string }; +}) => { + console.log(args); + + return invokeWrapper('compute_mixnode_reward_estimation', args); +}; +export const getMixnodeUptime = async (mixId: number) => invokeWrapper('get_mixnode_uptime', { mixId }); diff --git a/nym-wallet/src/requests/rewards.ts b/nym-wallet/src/requests/rewards.ts index 5c8c63e34e..36b90838e7 100644 --- a/nym-wallet/src/requests/rewards.ts +++ b/nym-wallet/src/requests/rewards.ts @@ -1,4 +1,4 @@ -import { Fee, FeeDetails, TransactionExecuteResult } from '@nymproject/types'; +import { Fee, FeeDetails, RewardingParams, TransactionExecuteResult } from '@nymproject/types'; import { invokeWrapper } from './wrapper'; export const claimOperatorReward = async (fee?: Fee) => @@ -9,3 +9,6 @@ export const claimDelegatorRewards = async (mixId: number, fee?: FeeDetails) => mixId, fee: fee?.fee, }); + +export const getCurrentRewardingParameter = async () => + invokeWrapper('get_current_rewarding_parameters', {}); diff --git a/nym-wallet/src/types/rust/AppEnv.ts b/nym-wallet/src/types/rust/AppEnv.ts index 3f47419469..861ecd9ef5 100644 --- a/nym-wallet/src/types/rust/AppEnv.ts +++ b/nym-wallet/src/types/rust/AppEnv.ts @@ -1,2 +1,5 @@ - -export interface AppEnv { ADMIN_ADDRESS: string | null, SHOW_TERMINAL: string | null, ENABLE_QA_MODE: string | null, } \ No newline at end of file +export interface AppEnv { + ADMIN_ADDRESS: string | null; + SHOW_TERMINAL: string | null; + ENABLE_QA_MODE: string | null; +} diff --git a/nym-wallet/src/types/rust/Network.ts b/nym-wallet/src/types/rust/Network.ts index fd31bccafa..f8615cd992 100644 --- a/nym-wallet/src/types/rust/Network.ts +++ b/nym-wallet/src/types/rust/Network.ts @@ -1,2 +1 @@ - -export type Network = "QA" | "SANDBOX" | "MAINNET"; \ No newline at end of file +export type Network = 'QA' | 'SANDBOX' | 'MAINNET'; diff --git a/nym-wallet/src/types/rust/StateParams.ts b/nym-wallet/src/types/rust/StateParams.ts index 85c362a3b2..c9420f50dc 100644 --- a/nym-wallet/src/types/rust/StateParams.ts +++ b/nym-wallet/src/types/rust/StateParams.ts @@ -1,3 +1,7 @@ -import type { DecCoin } from "../../../../ts-packages/types/src/types/rust/DecCoin"; +import type { DecCoin } from '../../../../ts-packages/types/src/types/rust/DecCoin'; -export interface TauriContractStateParams { minimum_mixnode_pledge: DecCoin, minimum_gateway_pledge: DecCoin, minimum_mixnode_delegation: DecCoin | null, } \ No newline at end of file +export interface TauriContractStateParams { + minimum_mixnode_pledge: DecCoin; + minimum_gateway_pledge: DecCoin; + minimum_mixnode_delegation: DecCoin | null; +} diff --git a/nym-wallet/src/types/rust/ValidatorUrl.ts b/nym-wallet/src/types/rust/ValidatorUrl.ts index 9c74679bac..801e045a00 100644 --- a/nym-wallet/src/types/rust/ValidatorUrl.ts +++ b/nym-wallet/src/types/rust/ValidatorUrl.ts @@ -1,2 +1,4 @@ - -export interface ValidatorUrl { url: string, name: string | null, } \ No newline at end of file +export interface ValidatorUrl { + url: string; + name: string | null; +} diff --git a/nym-wallet/src/types/rust/ValidatorUrls.ts b/nym-wallet/src/types/rust/ValidatorUrls.ts index 3a104150b1..98ca799fb5 100644 --- a/nym-wallet/src/types/rust/ValidatorUrls.ts +++ b/nym-wallet/src/types/rust/ValidatorUrls.ts @@ -1,3 +1,5 @@ -import type { ValidatorUrl } from "./ValidatorUrl"; +import type { ValidatorUrl } from './ValidatorUrl'; -export interface ValidatorUrls { urls: Array, } \ No newline at end of file +export interface ValidatorUrls { + urls: Array; +} diff --git a/ts-packages/mui-theme/src/theme/theme.ts b/ts-packages/mui-theme/src/theme/theme.ts index a12e706e9e..bb4dcae533 100644 --- a/ts-packages/mui-theme/src/theme/theme.ts +++ b/ts-packages/mui-theme/src/theme/theme.ts @@ -84,6 +84,7 @@ export const getDesignTokens = (mode: PaletteMode): ThemeOptions => { ].join(','), fontSize: 14, fontWeightRegular: 500, + fontWeightMedium: 600, button: { textTransform: 'none', fontWeight: '600', diff --git a/ts-packages/types/src/types/rust/Account.ts b/ts-packages/types/src/types/rust/Account.ts index ea0586828f..da0afb666e 100644 --- a/ts-packages/types/src/types/rust/Account.ts +++ b/ts-packages/types/src/types/rust/Account.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { CurrencyDenom } from './CurrencyDenom'; export interface Account { diff --git a/ts-packages/types/src/types/rust/AccountEntry.ts b/ts-packages/types/src/types/rust/AccountEntry.ts index f6ad1b53a9..472a9befcd 100644 --- a/ts-packages/types/src/types/rust/AccountEntry.ts +++ b/ts-packages/types/src/types/rust/AccountEntry.ts @@ -1,3 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + export interface AccountEntry { id: string; address: string; diff --git a/ts-packages/types/src/types/rust/AccountWithMnemonic.ts b/ts-packages/types/src/types/rust/AccountWithMnemonic.ts index 6b3757bdab..edbf9b9de6 100644 --- a/ts-packages/types/src/types/rust/AccountWithMnemonic.ts +++ b/ts-packages/types/src/types/rust/AccountWithMnemonic.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { Account } from './Account'; export interface AccountWithMnemonic { diff --git a/ts-packages/types/src/types/rust/Balance.ts b/ts-packages/types/src/types/rust/Balance.ts index ba6be26651..fe11917327 100644 --- a/ts-packages/types/src/types/rust/Balance.ts +++ b/ts-packages/types/src/types/rust/Balance.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; export interface Balance { diff --git a/ts-packages/types/src/types/rust/Coin.ts b/ts-packages/types/src/types/rust/Coin.ts index dda00291d7..493c2e6b41 100644 --- a/ts-packages/types/src/types/rust/Coin.ts +++ b/ts-packages/types/src/types/rust/Coin.ts @@ -1,3 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + export interface Coin { denom: string; amount: bigint; diff --git a/ts-packages/types/src/types/rust/CosmosFee.ts b/ts-packages/types/src/types/rust/CosmosFee.ts index 54c0f689bc..d77c4d3dd8 100644 --- a/ts-packages/types/src/types/rust/CosmosFee.ts +++ b/ts-packages/types/src/types/rust/CosmosFee.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { Coin } from './Coin'; export interface CosmosFee { diff --git a/ts-packages/types/src/types/rust/CurrencyDenom.ts b/ts-packages/types/src/types/rust/CurrencyDenom.ts index 04760b4fd7..3e7696c28d 100644 --- a/ts-packages/types/src/types/rust/CurrencyDenom.ts +++ b/ts-packages/types/src/types/rust/CurrencyDenom.ts @@ -1 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + export type CurrencyDenom = 'unknown' | 'nym' | 'nymt' | 'nyx' | 'nyxt'; diff --git a/ts-packages/types/src/types/rust/DecCoin.ts b/ts-packages/types/src/types/rust/DecCoin.ts index d2b1b4dd69..9411bf358b 100644 --- a/ts-packages/types/src/types/rust/DecCoin.ts +++ b/ts-packages/types/src/types/rust/DecCoin.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { CurrencyDenom } from './CurrencyDenom'; export type DecCoin = { denom: CurrencyDenom; amount: string }; diff --git a/ts-packages/types/src/types/rust/Delegation.ts b/ts-packages/types/src/types/rust/Delegation.ts index 18d6df201f..58de13e6cc 100644 --- a/ts-packages/types/src/types/rust/Delegation.ts +++ b/ts-packages/types/src/types/rust/Delegation.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; export interface Delegation { diff --git a/ts-packages/types/src/types/rust/DelegationEvent.ts b/ts-packages/types/src/types/rust/DelegationEvent.ts index d9e2c0a21d..30ff21943f 100644 --- a/ts-packages/types/src/types/rust/DelegationEvent.ts +++ b/ts-packages/types/src/types/rust/DelegationEvent.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; import type { DelegationEventKind } from './DelegationEventKind'; diff --git a/ts-packages/types/src/types/rust/DelegationEventKind.ts b/ts-packages/types/src/types/rust/DelegationEventKind.ts index a1db5fac12..a242220102 100644 --- a/ts-packages/types/src/types/rust/DelegationEventKind.ts +++ b/ts-packages/types/src/types/rust/DelegationEventKind.ts @@ -1 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + export type DelegationEventKind = 'Delegate' | 'Undelegate'; diff --git a/ts-packages/types/src/types/rust/DelegationResult.ts b/ts-packages/types/src/types/rust/DelegationResult.ts index f6d29d9435..d8f8a77ce3 100644 --- a/ts-packages/types/src/types/rust/DelegationResult.ts +++ b/ts-packages/types/src/types/rust/DelegationResult.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; export interface DelegationResult { diff --git a/ts-packages/types/src/types/rust/DelegationSummaryResponse.ts b/ts-packages/types/src/types/rust/DelegationSummaryResponse.ts index 0cb9346c59..21e85d513b 100644 --- a/ts-packages/types/src/types/rust/DelegationSummaryResponse.ts +++ b/ts-packages/types/src/types/rust/DelegationSummaryResponse.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; import type { DelegationWithEverything } from './DelegationWithEverything'; diff --git a/ts-packages/types/src/types/rust/DelegationWithEverything.ts b/ts-packages/types/src/types/rust/DelegationWithEverything.ts index 0d3423a133..ecf949c5ae 100644 --- a/ts-packages/types/src/types/rust/DelegationWithEverything.ts +++ b/ts-packages/types/src/types/rust/DelegationWithEverything.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; import type { DelegationEvent } from './DelegationEvent'; import type { MixNodeCostParams } from './MixNodeCostParams'; diff --git a/ts-packages/types/src/types/rust/Fee.ts b/ts-packages/types/src/types/rust/Fee.ts index 5a7a0af56e..1e3f747e92 100644 --- a/ts-packages/types/src/types/rust/Fee.ts +++ b/ts-packages/types/src/types/rust/Fee.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { CosmosFee } from './CosmosFee'; export type Fee = { Manual: CosmosFee } | { Auto: number | null }; diff --git a/ts-packages/types/src/types/rust/FeeDetails.ts b/ts-packages/types/src/types/rust/FeeDetails.ts index 60bcd4cae5..7db283dbc1 100644 --- a/ts-packages/types/src/types/rust/FeeDetails.ts +++ b/ts-packages/types/src/types/rust/FeeDetails.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; import type { Fee } from './Fee'; diff --git a/ts-packages/types/src/types/rust/Gas.ts b/ts-packages/types/src/types/rust/Gas.ts index e207dcb1e1..2b93e47509 100644 --- a/ts-packages/types/src/types/rust/Gas.ts +++ b/ts-packages/types/src/types/rust/Gas.ts @@ -1,3 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + export interface Gas { gas_units: bigint; } diff --git a/ts-packages/types/src/types/rust/GasInfo.ts b/ts-packages/types/src/types/rust/GasInfo.ts index fd5b21e582..3e34323018 100644 --- a/ts-packages/types/src/types/rust/GasInfo.ts +++ b/ts-packages/types/src/types/rust/GasInfo.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { Gas } from './Gas'; export interface GasInfo { diff --git a/ts-packages/types/src/types/rust/Gateway.ts b/ts-packages/types/src/types/rust/Gateway.ts index 1dbba0e5ed..4c449b578d 100644 --- a/ts-packages/types/src/types/rust/Gateway.ts +++ b/ts-packages/types/src/types/rust/Gateway.ts @@ -1,3 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + export interface Gateway { host: string; mix_port: number; diff --git a/ts-packages/types/src/types/rust/GatewayBond.ts b/ts-packages/types/src/types/rust/GatewayBond.ts index 277994efac..405c1cab92 100644 --- a/ts-packages/types/src/types/rust/GatewayBond.ts +++ b/ts-packages/types/src/types/rust/GatewayBond.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; import type { Gateway } from './Gateway'; diff --git a/ts-packages/types/src/types/rust/InclusionProbabilityResponse.ts b/ts-packages/types/src/types/rust/InclusionProbabilityResponse.ts index 56d81bde41..3f80b794a0 100644 --- a/ts-packages/types/src/types/rust/InclusionProbabilityResponse.ts +++ b/ts-packages/types/src/types/rust/InclusionProbabilityResponse.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { SelectionChance } from './SelectionChance'; export interface InclusionProbabilityResponse { diff --git a/ts-packages/types/src/types/rust/Interval.ts b/ts-packages/types/src/types/rust/Interval.ts index b47687ae22..7a7fa7bb4d 100644 --- a/ts-packages/types/src/types/rust/Interval.ts +++ b/ts-packages/types/src/types/rust/Interval.ts @@ -3,6 +3,6 @@ export interface Interval { epochs_in_interval: number; current_epoch_start: string; current_epoch_id: number; - epoch_length: string; + epoch_length: { secs: number; nanos: number }; total_elapsed_epochs: number; } diff --git a/ts-packages/types/src/types/rust/MixNodeBond.ts b/ts-packages/types/src/types/rust/MixNodeBond.ts index 37059b9b61..173ce9599d 100644 --- a/ts-packages/types/src/types/rust/MixNodeBond.ts +++ b/ts-packages/types/src/types/rust/MixNodeBond.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; import type { MixNode } from './Mixnode'; diff --git a/ts-packages/types/src/types/rust/Mixnode.ts b/ts-packages/types/src/types/rust/Mixnode.ts index 0deaa5b919..8dddce4eb2 100644 --- a/ts-packages/types/src/types/rust/Mixnode.ts +++ b/ts-packages/types/src/types/rust/Mixnode.ts @@ -1,3 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + export interface MixNode { host: string; mix_port: number; diff --git a/ts-packages/types/src/types/rust/MixnodeStatus.ts b/ts-packages/types/src/types/rust/MixnodeStatus.ts index da89c7e8a7..6421988dce 100644 --- a/ts-packages/types/src/types/rust/MixnodeStatus.ts +++ b/ts-packages/types/src/types/rust/MixnodeStatus.ts @@ -1 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + export type MixnodeStatus = 'active' | 'standby' | 'inactive' | 'not_found'; diff --git a/ts-packages/types/src/types/rust/MixnodeStatusResponse.ts b/ts-packages/types/src/types/rust/MixnodeStatusResponse.ts index 2225b26df3..2dd6bb6f54 100644 --- a/ts-packages/types/src/types/rust/MixnodeStatusResponse.ts +++ b/ts-packages/types/src/types/rust/MixnodeStatusResponse.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { MixnodeStatus } from './MixnodeStatus'; export interface MixnodeStatusResponse { diff --git a/ts-packages/types/src/types/rust/OriginalVestingResponse.ts b/ts-packages/types/src/types/rust/OriginalVestingResponse.ts index 8d781d5ad0..ea10cd24af 100644 --- a/ts-packages/types/src/types/rust/OriginalVestingResponse.ts +++ b/ts-packages/types/src/types/rust/OriginalVestingResponse.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; export interface OriginalVestingResponse { diff --git a/ts-packages/types/src/types/rust/Period.ts b/ts-packages/types/src/types/rust/Period.ts index 05d9890d5f..76a8876b31 100644 --- a/ts-packages/types/src/types/rust/Period.ts +++ b/ts-packages/types/src/types/rust/Period.ts @@ -1 +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'; diff --git a/ts-packages/types/src/types/rust/PledgeData.ts b/ts-packages/types/src/types/rust/PledgeData.ts index 9fb19f9aaf..76adc23018 100644 --- a/ts-packages/types/src/types/rust/PledgeData.ts +++ b/ts-packages/types/src/types/rust/PledgeData.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; export interface PledgeData { diff --git a/ts-packages/types/src/types/rust/RewardedSetNodeStatus.ts b/ts-packages/types/src/types/rust/RewardedSetNodeStatus.ts index 8ddd13d047..5a8da8dbea 100644 --- a/ts-packages/types/src/types/rust/RewardedSetNodeStatus.ts +++ b/ts-packages/types/src/types/rust/RewardedSetNodeStatus.ts @@ -1 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + export type RewardedSetNodeStatus = 'Active' | 'Standby'; diff --git a/ts-packages/types/src/types/rust/RpcTransactionResponse.ts b/ts-packages/types/src/types/rust/RpcTransactionResponse.ts index 2463e3dd20..2f9c3bdc8a 100644 --- a/ts-packages/types/src/types/rust/RpcTransactionResponse.ts +++ b/ts-packages/types/src/types/rust/RpcTransactionResponse.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; import type { Gas } from './Gas'; diff --git a/ts-packages/types/src/types/rust/SendTxResult.ts b/ts-packages/types/src/types/rust/SendTxResult.ts index b44de3324d..02fb0b5b0c 100644 --- a/ts-packages/types/src/types/rust/SendTxResult.ts +++ b/ts-packages/types/src/types/rust/SendTxResult.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; import type { Gas } from './Gas'; import type { TransactionDetails } from './TransactionDetails'; diff --git a/ts-packages/types/src/types/rust/StakeSaturationResponse.ts b/ts-packages/types/src/types/rust/StakeSaturationResponse.ts index 038d261c46..6be2ae0e0e 100644 --- a/ts-packages/types/src/types/rust/StakeSaturationResponse.ts +++ b/ts-packages/types/src/types/rust/StakeSaturationResponse.ts @@ -1,3 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + export interface StakeSaturationResponse { saturation: string; uncapped_saturation: string; diff --git a/ts-packages/types/src/types/rust/TransactionDetails.ts b/ts-packages/types/src/types/rust/TransactionDetails.ts index 8de1cf9ec3..043db71473 100644 --- a/ts-packages/types/src/types/rust/TransactionDetails.ts +++ b/ts-packages/types/src/types/rust/TransactionDetails.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; export interface TransactionDetails { diff --git a/ts-packages/types/src/types/rust/TransactionExecuteResult.ts b/ts-packages/types/src/types/rust/TransactionExecuteResult.ts index e6d93e8448..ce06484dd1 100644 --- a/ts-packages/types/src/types/rust/TransactionExecuteResult.ts +++ b/ts-packages/types/src/types/rust/TransactionExecuteResult.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; import type { GasInfo } from './GasInfo'; diff --git a/ts-packages/types/src/types/rust/VestingAccountInfo.ts b/ts-packages/types/src/types/rust/VestingAccountInfo.ts index d317d045d1..538e941edb 100644 --- a/ts-packages/types/src/types/rust/VestingAccountInfo.ts +++ b/ts-packages/types/src/types/rust/VestingAccountInfo.ts @@ -1,3 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DecCoin } from './DecCoin'; import type { VestingPeriod } from './VestingPeriod'; diff --git a/ts-packages/types/src/types/rust/VestingPeriod.ts b/ts-packages/types/src/types/rust/VestingPeriod.ts index de1089005f..dae6901c10 100644 --- a/ts-packages/types/src/types/rust/VestingPeriod.ts +++ b/ts-packages/types/src/types/rust/VestingPeriod.ts @@ -1,3 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + export interface VestingPeriod { start_time: bigint; period_seconds: bigint; diff --git a/ts-packages/types/src/utils/decimal/index.ts b/ts-packages/types/src/utils/decimal/index.ts index 2f58196372..62807f25d6 100644 --- a/ts-packages/types/src/utils/decimal/index.ts +++ b/ts-packages/types/src/utils/decimal/index.ts @@ -10,5 +10,8 @@ export const stringToDecimal = (raw: string): Decimal => Decimal.fromUserInput(r export const decimalToPercentage = (raw: string) => Math.round(Decimal.fromUserInput(raw, 18).toFloatApproximation() * 100).toString(); +export const percentToDecimal = (raw: string) => + (Decimal.fromUserInput(raw, 18).toFloatApproximation() / 100).toString(); + export const decimalToFloatApproximation = (raw: string): number => Decimal.fromUserInput(raw, 18).toFloatApproximation(); From a746738d489b5224864a893da88f80021b7372e9 Mon Sep 17 00:00:00 2001 From: Gala Date: Mon, 19 Dec 2022 13:40:26 +0100 Subject: [PATCH 15/21] make fields match button height --- explorer/src/components/TableToolbar.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/explorer/src/components/TableToolbar.tsx b/explorer/src/components/TableToolbar.tsx index 7452b4707a..7426433868 100644 --- a/explorer/src/components/TableToolbar.tsx +++ b/explorer/src/components/TableToolbar.tsx @@ -4,6 +4,8 @@ import Select, { SelectChangeEvent } from '@mui/material/Select'; import { Filters } from './Filters/Filters'; import { useIsMobile } from '../hooks/useIsMobile'; +const fieldsHeight = '42.25px'; + type TableToolBarProps = { onChangeSearch: (arg: string) => void; onChangePageSize: (event: SelectChangeEvent) => void; @@ -35,7 +37,7 @@ export const TableToolbar: React.FC = ({ }} > - + {childrenBefore}