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()) } }