diff --git a/CHANGELOG.md b/CHANGELOG.md index e43f1ea1dc..b1c28a8062 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - Maker/taker pubkeys were added to new columns in `stats_swaps` table in [#1665](https://github.com/KomodoPlatform/atomicDEX-API/pull/1665) - Get rid of unnecessary / old dependencies: `crossterm`, `crossterm_winapi`, `mio 0.7.13`, `miow`, `ntapi`, `signal-hook`, `signal-hook-mio` in [#1710](https://github.com/KomodoPlatform/atomicDEX-API/pull/1710) - A bug that caused EVM swap payments validation to fail because the tx was not available yet in the RPC node when calling `eth_getTransactionByHash` was fixed in [#1716](https://github.com/KomodoPlatform/atomicDEX-API/pull/1716). `eth_getTransactionByHash` in now retried in `wait_for_confirmations` until tx is found in the RPC node, this makes sure that the transaction is returned from `eth_getTransactionByHash` later when validating. +- `OperationFailure::Other` error was expanded. New error variants were matched with `HwRpcError`, so error type will be `HwError`, not `InternalError` [#1719](https://github.com/KomodoPlatform/atomicDEX-API/pull/1719) ## v1.0.0-beta - 2023-03-08 diff --git a/mm2src/coins_activation/src/utxo_activation/init_utxo_standard_activation_error.rs b/mm2src/coins_activation/src/utxo_activation/init_utxo_standard_activation_error.rs index d6a3497640..47894c2a6f 100644 --- a/mm2src/coins_activation/src/utxo_activation/init_utxo_standard_activation_error.rs +++ b/mm2src/coins_activation/src/utxo_activation/init_utxo_standard_activation_error.rs @@ -115,7 +115,23 @@ impl InitUtxoStandardError { HwError::CannotChooseDevice { .. } => InitUtxoStandardError::HwError(HwRpcError::FoundMultipleDevices), HwError::ConnectionTimedOut { timeout } => InitUtxoStandardError::TaskTimedOut { duration: timeout }, HwError::FoundUnexpectedDevice => InitUtxoStandardError::HwError(HwRpcError::FoundUnexpectedDevice), - HwError::Failure(error) => InitUtxoStandardError::CoinCreationError { ticker, error }, + HwError::InvalidPin + | HwError::UnexpectedMessage + | HwError::ButtonExpected + | HwError::DataError + | HwError::PinExpected + | HwError::InvalidSignature + | HwError::ProcessError + | HwError::NotEnoughFunds + | HwError::NotInitialized + | HwError::WipeCodeMismatch + | HwError::InvalidSession + | HwError::FirmwareError + | HwError::FailureMessageNotFound + | HwError::UserCancelled => InitUtxoStandardError::CoinCreationError { + ticker, + error: hw_error.to_string(), + }, other => InitUtxoStandardError::Internal(other.to_string()), } } diff --git a/mm2src/crypto/src/hw_error.rs b/mm2src/crypto/src/hw_error.rs index d9e7b03610..1efd4b243f 100644 --- a/mm2src/crypto/src/hw_error.rs +++ b/mm2src/crypto/src/hw_error.rs @@ -3,7 +3,7 @@ use hw_common::primitives::Bip32Error; use mm2_err_handle::prelude::*; use serde::Serialize; use std::time::Duration; -use trezor::{TrezorError, TrezorUserInteraction}; +use trezor::{OperationFailure, TrezorError, TrezorUserInteraction}; pub type HwResult = Result>; @@ -28,11 +28,25 @@ pub enum HwError { }, #[display(fmt = "Invalid xpub received from a device: '{}'", _0)] InvalidXpub(String), - Failure(String), UnderlyingError(String), ProtocolError(String), UnexpectedUserInteractionRequest(TrezorUserInteraction), Internal(String), + InvalidPin, + UnexpectedMessage, + ButtonExpected, + DataError, + PinExpected, + InvalidSignature, + ProcessError, + NotEnoughFunds, + NotInitialized, + WipeCodeMismatch, + InvalidSession, + FirmwareError, + FailureMessageNotFound, + UserCancelled, + PongMessageMismatch, } impl From for HwError { @@ -44,10 +58,25 @@ impl From for HwError { TrezorError::DeviceDisconnected => HwError::DeviceDisconnected, TrezorError::UnderlyingError(_) => HwError::UnderlyingError(error), TrezorError::ProtocolError(_) | TrezorError::UnexpectedMessageType(_) => HwError::Internal(error), - // TODO handle the failure correctly later - TrezorError::Failure(_) => HwError::Failure(error), + TrezorError::Failure(failure) => match failure { + OperationFailure::InvalidPin => HwError::InvalidPin, + OperationFailure::UnexpectedMessage => HwError::UnexpectedMessage, + OperationFailure::ButtonExpected => HwError::ButtonExpected, + OperationFailure::DataError => HwError::DataError, + OperationFailure::PinExpected => HwError::PinExpected, + OperationFailure::InvalidSignature => HwError::InvalidSignature, + OperationFailure::ProcessError => HwError::ProcessError, + OperationFailure::NotEnoughFunds => HwError::NotEnoughFunds, + OperationFailure::NotInitialized => HwError::NotInitialized, + OperationFailure::WipeCodeMismatch => HwError::WipeCodeMismatch, + OperationFailure::InvalidSession => HwError::InvalidSession, + OperationFailure::FirmwareError => HwError::FirmwareError, + OperationFailure::FailureMessageNotFound => HwError::FailureMessageNotFound, + OperationFailure::UserCancelled => HwError::UserCancelled, + }, TrezorError::UnexpectedInteractionRequest(req) => HwError::UnexpectedUserInteractionRequest(req), TrezorError::Internal(_) => HwError::Internal(error), + TrezorError::PongMessageMismatch => HwError::PongMessageMismatch, } } } @@ -69,6 +98,36 @@ pub enum HwRpcError { FoundMultipleDevices, #[display(fmt = "Found unexpected device. Please re-initialize Hardware wallet")] FoundUnexpectedDevice, + #[display(fmt = "Pin is invalid")] + InvalidPin, + #[display(fmt = "Unexpected message")] + UnexpectedMessage, + #[display(fmt = "Button expected")] + ButtonExpected, + #[display(fmt = "Got data error")] + DataError, + #[display(fmt = "Pin expected")] + PinExpected, + #[display(fmt = "Invalid signature")] + InvalidSignature, + #[display(fmt = "Got process error")] + ProcessError, + #[display(fmt = "Not enough funds")] + NotEnoughFunds, + #[display(fmt = "Not initialized")] + NotInitialized, + #[display(fmt = "Wipe code mismatch")] + WipeCodeMismatch, + #[display(fmt = "Invalid session")] + InvalidSession, + #[display(fmt = "Got firmware error")] + FirmwareError, + #[display(fmt = "Failure message not found")] + FailureMessageNotFound, + #[display(fmt = "User cancelled action")] + UserCancelled, + #[display(fmt = "PONG message mismatch after ping")] + PongMessageMismatch, } /// The trait is implemented for those error enumerations that have `HwRpcError` variant. @@ -90,6 +149,21 @@ where HwError::CannotChooseDevice { .. } => T::hw_rpc_error(HwRpcError::FoundMultipleDevices), HwError::ConnectionTimedOut { timeout } => T::timeout(timeout), HwError::FoundUnexpectedDevice => T::hw_rpc_error(HwRpcError::FoundUnexpectedDevice), + HwError::InvalidPin => T::hw_rpc_error(HwRpcError::InvalidPin), + HwError::UnexpectedMessage => T::hw_rpc_error(HwRpcError::UnexpectedMessage), + HwError::ButtonExpected => T::hw_rpc_error(HwRpcError::ButtonExpected), + HwError::DataError => T::hw_rpc_error(HwRpcError::DataError), + HwError::PinExpected => T::hw_rpc_error(HwRpcError::PinExpected), + HwError::InvalidSignature => T::hw_rpc_error(HwRpcError::InvalidSignature), + HwError::ProcessError => T::hw_rpc_error(HwRpcError::ProcessError), + HwError::NotEnoughFunds => T::hw_rpc_error(HwRpcError::NotEnoughFunds), + HwError::NotInitialized => T::hw_rpc_error(HwRpcError::NotInitialized), + HwError::WipeCodeMismatch => T::hw_rpc_error(HwRpcError::WipeCodeMismatch), + HwError::InvalidSession => T::hw_rpc_error(HwRpcError::InvalidSession), + HwError::FirmwareError => T::hw_rpc_error(HwRpcError::FirmwareError), + HwError::FailureMessageNotFound => T::hw_rpc_error(HwRpcError::FailureMessageNotFound), + HwError::UserCancelled => T::hw_rpc_error(HwRpcError::UserCancelled), + HwError::PongMessageMismatch => T::hw_rpc_error(HwRpcError::PongMessageMismatch), other => T::internal(other.to_string()), } } diff --git a/mm2src/trezor/src/client.rs b/mm2src/trezor/src/client.rs index cb4bcc3bf5..3e06023ad5 100644 --- a/mm2src/trezor/src/client.rs +++ b/mm2src/trezor/src/client.rs @@ -116,11 +116,10 @@ impl<'a> TrezorSession<'a> { }; let result_handler = ResultHandler::<()>::new(move |pong: proto_common::Success| { - if pong.message == Some(ping_message.clone()) { + if pong.message == Some(ping_message) { Ok(()) } else { - let error = format!("Expected '{ping_message}' PONG message, found: {:?}", pong.message); - MmError::err(TrezorError::Failure(OperationFailure::Other(error))) + MmError::err(TrezorError::PongMessageMismatch) } }); self.call(req, result_handler).await diff --git a/mm2src/trezor/src/error.rs b/mm2src/trezor/src/error.rs index dfcf5303ba..60397e55a1 100644 --- a/mm2src/trezor/src/error.rs +++ b/mm2src/trezor/src/error.rs @@ -32,14 +32,25 @@ pub enum TrezorError { #[display(fmt = "Unexpected interaction request: {:?}", _0)] UnexpectedInteractionRequest(TrezorUserInteraction), Internal(String), + PongMessageMismatch, } -#[derive(Debug, Display)] +#[derive(Clone, Debug, Display)] pub enum OperationFailure { InvalidPin, - /// TODO expand it to other types. - #[display(fmt = "Operation failed due to unknown reason: {}", _0)] - Other(String), + UnexpectedMessage, + ButtonExpected, + DataError, + PinExpected, + InvalidSignature, + ProcessError, + NotEnoughFunds, + NotInitialized, + WipeCodeMismatch, + InvalidSession, + FirmwareError, + FailureMessageNotFound, + UserCancelled, } impl From for OperationFailure { @@ -48,15 +59,25 @@ impl From for OperationFailure { Some(FailureType::FailurePinInvalid) | Some(FailureType::FailurePinMismatch) => { OperationFailure::InvalidPin }, - _ => OperationFailure::Other(format!("{:?}", failure)), + Some(FailureType::FailureActionCancelled) | Some(FailureType::FailurePinCancelled) => { + OperationFailure::UserCancelled + }, + Some(FailureType::FailureUnexpectedMessage) => OperationFailure::UnexpectedMessage, + Some(FailureType::FailureButtonExpected) => OperationFailure::ButtonExpected, + Some(FailureType::FailureDataError) => OperationFailure::DataError, + Some(FailureType::FailurePinExpected) => OperationFailure::PinExpected, + Some(FailureType::FailureInvalidSignature) => OperationFailure::InvalidSignature, + Some(FailureType::FailureProcessError) => OperationFailure::ProcessError, + Some(FailureType::FailureNotEnoughFunds) => OperationFailure::NotEnoughFunds, + Some(FailureType::FailureNotInitialized) => OperationFailure::NotInitialized, + Some(FailureType::FailureWipeCodeMismatch) => OperationFailure::WipeCodeMismatch, + Some(FailureType::FailureInvalidSession) => OperationFailure::InvalidSession, + Some(FailureType::FailureFirmwareError) => OperationFailure::FirmwareError, + None => OperationFailure::FailureMessageNotFound, } } } -impl From for TrezorError { - fn from(failure: OperationFailure) -> Self { TrezorError::Failure(failure) } -} - impl From for TrezorError { fn from(e: DecodeError) -> Self { TrezorError::ProtocolError(e.to_string()) } }