Bläddra i källkod

feat: use thiserror for error types

Matthias Seitz 4 år sedan
förälder
incheckning
5bac09d327

+ 1 - 0
Cargo.lock

@@ -1347,6 +1347,7 @@ dependencies = [
  "solana-sdk",
  "spl-associated-token-account",
  "spl-token",
+ "thiserror",
  "toml",
  "tungstenite 0.15.0",
  "url",

+ 1 - 0
Cargo.toml

@@ -79,6 +79,7 @@ secp256k1 = {version = "0.20.3", default-features = false, features = ["rand-std
 ## Cashier Ethereum Dependencies
 hash-db = {version = "0.15.2", optional = true}
 keccak-hasher = {version = "0.15.3", optional = true}
+thiserror = "1.0.30"
 
 [features]
 btc = ["bdk", "bitcoin", "secp256k1"]

+ 2 - 5
src/bin/cashierd.rs

@@ -472,10 +472,7 @@ impl Cashierd {
         mut client: Client,
         state: Arc<Mutex<State>>,
         executor: Arc<Executor<'_>>,
-    ) -> Result<(
-        smol::Task<Result<()>>,
-        smol::Task<Result<()>>,
-    )> {
+    ) -> Result<(smol::Task<Result<()>>, smol::Task<Result<()>>)> {
         self.cashier_wallet.init_db().await?;
 
         for network in self.networks.iter() {
@@ -512,7 +509,7 @@ impl Cashierd {
                         )?)?;
                         let keypair_bytes: Vec<u8> = serde_json::from_str(&keypair_str)?;
                         main_keypair = Keypair::from_bytes(&keypair_bytes)
-                            .map_err(|e| SolFailed::ParseError(e.to_string()))?;
+                            .map_err(|e| SolFailed::Signature(e.to_string()))?;
                     }
 
                     let sol_client = SolClient::new(main_keypair, &network.blockchain).await?;

+ 2 - 2
src/cli/cli_config.rs

@@ -145,9 +145,9 @@ pub struct CashierdConfig {
     pub client_wallet_password: String,
     /// Path to database
     pub database_path: String,
-    /// Geth IPC endpoint 
+    /// Geth IPC endpoint
     pub geth_socket: String,
-    /// Geth passphrase 
+    /// Geth passphrase
     pub geth_passphrase: String,
     /// The configured networks to use
     pub networks: Vec<FeatureNetwork>,

+ 13 - 38
src/client.rs

@@ -25,19 +25,31 @@ use crate::{
     Result,
 };
 
-#[derive(Debug)]
+#[derive(Debug, Clone, thiserror::Error)]
 pub enum ClientFailed {
+    #[error("here is no enough value {0}")]
     NotEnoughValue(u64),
+    #[error("Invalid Address  {0}")]
     InvalidAddress(String),
+    #[error("Invalid Amount {0}")]
     InvalidAmount(u64),
+    #[error("Unable to get deposit address")]
     UnableToGetDepositAddress,
+    #[error("Unable to get withdraw address")]
     UnableToGetWithdrawAddress,
+    #[error("Does not have cashier public key")]
     DoesNotHaveCashierPublicKey,
+    #[error("Does not have keypair")]
     DoesNotHaveKeypair,
+    #[error("Password is empty. Cannot create database")]
     EmptyPassword,
+    #[error("Wallet already initalized")]
     WalletInitialized,
+    #[error("Keypair already exists")]
     KeyExists,
+    #[error("{0}")]
     ClientError(String),
+    #[error("Verify error: {0}")]
     VerifyError(String),
 }
 
@@ -526,43 +538,6 @@ impl State {
     }
 }
 
-impl std::error::Error for ClientFailed {}
-
-impl std::fmt::Display for ClientFailed {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        match self {
-            ClientFailed::NotEnoughValue(i) => {
-                write!(f, "There is no enough value {}", i)
-            }
-            ClientFailed::InvalidAddress(i) => {
-                write!(f, "Invalid Address {}", i)
-            }
-            ClientFailed::InvalidAmount(i) => {
-                write!(f, "Invalid Amount {}", i)
-            }
-            ClientFailed::UnableToGetDepositAddress => f.write_str("Unable to get deposit address"),
-            ClientFailed::UnableToGetWithdrawAddress => {
-                f.write_str("Unable to get withdraw address")
-            }
-            ClientFailed::DoesNotHaveCashierPublicKey => {
-                f.write_str("Does not have cashier public key")
-            }
-            ClientFailed::DoesNotHaveKeypair => f.write_str("Does not have keypair"),
-            ClientFailed::EmptyPassword => f.write_str("Password is empty. Cannot create database"),
-            ClientFailed::WalletInitialized => f.write_str("Wallet already initalized"),
-            ClientFailed::KeyExists => f.write_str("Keypair already exists"),
-
-            ClientFailed::ClientError(i) => {
-                write!(f, "{}", i)
-            }
-
-            ClientFailed::VerifyError(i) => {
-                write!(f, "Verify error: {}", i)
-            }
-        }
-    }
-}
-
 impl From<super::error::Error> for ClientFailed {
     fn from(err: super::error::Error) -> ClientFailed {
         ClientFailed::ClientError(err.to_string())

+ 0 - 1
src/crypto/coin.rs

@@ -29,4 +29,3 @@ impl Decodable for Coin {
         })
     }
 }
-

+ 1 - 1
src/crypto/mod.rs

@@ -25,7 +25,7 @@ pub struct OwnCoin {
     pub note: note::Note,
     pub secret: jubjub::Fr,
     pub witness: merkle::IncrementalWitness<merkle_node::MerkleNode>,
-    pub nullifier: nullifier::Nullifier 
+    pub nullifier: nullifier::Nullifier,
 }
 
 pub type OwnCoins = Vec<OwnCoin>;

+ 0 - 2
src/crypto/nullifier.rs

@@ -5,7 +5,6 @@ use crate::{
     serial::{Decodable, Encodable},
 };
 
-
 #[derive(Debug, Clone, PartialEq)]
 pub struct Nullifier {
     pub repr: [u8; 32],
@@ -30,4 +29,3 @@ impl Decodable for Nullifier {
         })
     }
 }
-

+ 109 - 226
src/error.rs

@@ -1,166 +1,154 @@
-use std::fmt;
-
 use crate::client;
 use crate::state;
 use crate::vm::ZkVmError;
 
 pub type Result<T> = std::result::Result<T, Error>;
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, thiserror::Error)]
 pub enum Error {
+    #[error("io error: `{0:?}`")]
     Io(std::io::ErrorKind),
 
-    /// VarInt was encoded in a non-minimal way
+    #[error("Cannot find home directory")]
     PathNotFound,
+    /// VarInt was encoded in a non-minimal way
+    #[error("non-minimal varint")]
     NonMinimalVarInt,
 
     /// Parsing And Encode/Decode errors
+    #[error("parse failed: `{0}`")]
     ParseFailed(&'static str),
-    ParseIntError,
-    ParseBigIntError,
-    ParseFloatError,
-    FromHexError,
-    UrlParseError,
+    #[error(transparent)]
+    ParseIntError(#[from] std::num::ParseIntError),
+    #[error(transparent)]
+    ParseBigIntError(#[from] num_bigint::ParseBigIntError),
+    #[error(transparent)]
+    ParseFloatError(#[from] std::num::ParseFloatError),
+    #[error(transparent)]
+    FromHexError(#[from] hex::FromHexError),
+    #[error("Url parse erro `{0}`")]
+    UrlParseError(String),
+    #[error("No url found")]
+    NoUrlFound,
+    #[error("Malformed packet")]
     MalformedPacket,
-    AddrParseError,
-    Base58EncodeError(String),
-    Base58DecodeError(String),
-    Utf8Error,
-    StrUtf8Error(String),
+    #[error(transparent)]
+    AddrParseError(#[from] std::net::AddrParseError),
+    #[error(transparent)]
+    Base58EncodeError(#[from] bs58::encode::Error),
+    #[error(transparent)]
+    Base58DecodeError(#[from] bs58::decode::Error),
+    #[error(transparent)]
+    Utf8Error(#[from] std::string::FromUtf8Error),
+    #[error(transparent)]
+    StrUtf8Error(#[from] std::str::Utf8Error),
+    #[error("TryInto error")]
     TryIntoError,
+    #[error("TryFrom error")]
     TryFromError,
-    TryFromBigIntError,
+    #[error(transparent)]
+    TryFromBigIntError(#[from] num_bigint::TryFromBigIntError<num_bigint::BigUint>),
+    #[error("Json serialization error: `{0}`")]
     SerdeJsonError(String),
-    TomlDeserializeError(String),
-    TomlSerializeError(String),
+    #[error(transparent)]
+    TomlDeserializeError(#[from] toml::de::Error),
+    #[error(transparent)]
+    TomlSerializeError(#[from] toml::ser::Error),
 
     /// Contract
+    #[error("Bad variable ref type byte")]
     BadVariableRefType,
+    #[error("Bad operation type byte")]
     BadOperationType,
+    #[error("Bad constraint type byte")]
     BadConstraintType,
+    #[error("Invalid param name")]
     InvalidParamName,
+    #[error("Missing params")]
     MissingParams,
-    VmError,
+    #[error(transparent)]
+    VmError(#[from] ZkVmError),
+    #[error("Contract is poorly defined")]
     BadContract,
-    Groth16Error,
+    #[error("Groth16 Error: `{0}`")]
+    Groth16Error(String),
+    #[error("Operation failed")]
     OperationFailed,
+    #[error("Unable to decrypt mint note")]
     NoteDecryptionFailed,
-    VerifyFailed,
+    #[error(transparent)]
+    VerifyFailed(#[from] state::VerifyFailed),
+    #[error("MerkleTree is full")]
     TreeFull,
 
     /// Service
+    #[error("Services Error: `{0}`")]
     ServicesError(&'static str),
+    #[error("Client failed: `{0}`")]
     ClientFailed(String),
     #[cfg(feature = "btc")]
-    BtcFailed(String),
+    #[error(transparent)]
+    BtcFailed(#[from] crate::service::BtcFailed),
     #[cfg(feature = "sol")]
+    #[error("Sol client failed: `{0}`")]
     SolFailed(String),
     #[cfg(feature = "eth")]
-    EthFailed(String),
+    #[error(transparent)]
+    EthFailed(#[from] crate::service::EthFailed),
+    #[error("BridgeError Error: `{0}`")]
     BridgeError(String),
+    #[error("ZmqError: `{0}`")]
     ZmqError(String),
 
     /// Database/Sql errors
+    #[error("Rocksdb error: `{0}`")]
     RocksdbError(String),
+    #[error("Rusqlite error: `{0}`")]
     RusqliteError(String),
+    #[error("SlabsStore Error: `{0}`")]
     SlabsStore(String),
 
     /// RPC errors
+    #[error("JsonRpc Error: `{0}`")]
     JsonRpcError(String),
+    #[error("Not supported network")]
     NotSupportedNetwork,
+    #[error("Not supported token")]
     NotSupportedToken,
+    #[error("Could not parse token parameter")]
     TokenParseError,
+    #[error("Cannot parse network parameter")]
     NetworkParseError,
-    AsyncNativeTlsError,
-    TungsteniteError,
+    #[error("Async_Native_TLS error: `{0}`")]
+    AsyncNativeTlsError(String),
+    #[error("TungsteniteError: `{0}`")]
+    TungsteniteError(String),
 
     /// Network
+    #[error("Connection failed")]
     ConnectFailed,
+    #[error("Connection timed out")]
     ConnectTimeout,
+    #[error("Channel stopped")]
     ChannelStopped,
+    #[error("Channel timed out")]
     ChannelTimeout,
+    #[error("Service stopped")]
     ServiceStopped,
 
     /// Util
+    #[error("No config file detected. Please create one.")]
     ConfigNotFound,
+    #[error("No keypair file detected.")]
     KeypairPathNotFound,
+    #[error("No cashier public keys detected.")]
     CashierKeysNotFound,
+    #[error("SetLoggerError")]
     SetLoggerError,
+    #[error("Async_channel sender error")]
     AsyncChannelSenderError,
-    AsyncChannelReceiverError,
-}
-
-impl std::error::Error for Error {}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
-        match *self {
-            Error::PathNotFound => f.write_str("Cannot find home directory"),
-            Error::Io(ref err) => write!(f, "io error:{:?}", err),
-            Error::NonMinimalVarInt => f.write_str("non-minimal varint"),
-            Error::ParseFailed(ref err) => write!(f, "parse failed: {}", err),
-            Error::ParseIntError => f.write_str("Parse int error"),
-            Error::ParseBigIntError => f.write_str("Parse big int error"),
-            Error::ParseFloatError => f.write_str("Parse float error"),
-            Error::UrlParseError => f.write_str("Failed to parse URL"),
-            Error::FromHexError => f.write_str("Failed to convert from hex"),
-            Error::AsyncChannelSenderError => f.write_str("Async_channel sender error"),
-            Error::AsyncChannelReceiverError => f.write_str("Async_channel receiver error"),
-            Error::AsyncNativeTlsError => f.write_str("Async_Native_TLS error"),
-            Error::MalformedPacket => f.write_str("Malformed packet"),
-            Error::AddrParseError => f.write_str("Unable to parse address"),
-            Error::BadVariableRefType => f.write_str("Bad variable ref type byte"),
-            Error::BadOperationType => f.write_str("Bad operation type byte"),
-            Error::BadConstraintType => f.write_str("Bad constraint type byte"),
-            Error::InvalidParamName => f.write_str("Invalid param name"),
-            Error::MissingParams => f.write_str("Missing params"),
-            Error::VmError => f.write_str("VM error"),
-            Error::BadContract => f.write_str("Contract is poorly defined"),
-            Error::Groth16Error => f.write_str("Groth16 error"),
-            Error::RusqliteError(ref err) => write!(f, "Rusqlite error {}", err),
-            Error::OperationFailed => f.write_str("Operation failed"),
-            Error::ConnectFailed => f.write_str("Connection failed"),
-            Error::ConnectTimeout => f.write_str("Connection timed out"),
-            Error::ChannelStopped => f.write_str("Channel stopped"),
-            Error::ChannelTimeout => f.write_str("Channel timed out"),
-            Error::ServiceStopped => f.write_str("Service stopped"),
-            Error::Utf8Error => f.write_str("Malformed UTF8"),
-            Error::StrUtf8Error(ref err) => write!(f, "Malformed UTF8: {}", err),
-            Error::NoteDecryptionFailed => f.write_str("Unable to decrypt mint note"),
-            Error::ServicesError(ref err) => write!(f, "Services error: {}", err),
-            Error::ZmqError(ref err) => write!(f, "ZmqError: {}", err),
-            Error::VerifyFailed => f.write_str("Verify failed"),
-            Error::ClientFailed(ref err) => write!(f, "Client failed: {}", err),
-            #[cfg(feature = "btc")]
-            Error::BtcFailed(ref err) => write!(f, "Btc client failed: {}", err),
-            #[cfg(feature = "sol")]
-            Error::SolFailed(ref err) => write!(f, "Sol client failed: {}", err),
-            #[cfg(feature = "eth")]
-            Error::EthFailed(ref err) => write!(f, "Eth client failed: {}", err),
-            Error::TryIntoError => f.write_str("TryInto error"),
-            Error::TryFromError => f.write_str("TryFrom error"),
-            Error::TryFromBigIntError => f.write_str("TryFromBigInt error"),
-            Error::RocksdbError(ref err) => write!(f, "Rocksdb Error: {}", err),
-            Error::SlabsStore(ref err) => write!(f, "SlabsStore Error: {}", err),
-            Error::JsonRpcError(ref err) => write!(f, "JsonRpc Error: {}", err),
-            Error::TreeFull => f.write_str("MerkleTree is full"),
-            Error::NotSupportedNetwork => f.write_str("Not supported network"),
-            Error::NotSupportedToken => f.write_str("Not supported token"),
-            Error::BridgeError(ref err) => write!(f, "Bridge error: {}", err),
-            Error::SerdeJsonError(ref err) => write!(f, "Json serialization error: {}", err),
-            Error::TomlDeserializeError(ref err) => write!(f, "Toml parsing error: {}", err),
-            Error::TomlSerializeError(ref err) => write!(f, "Toml parsing error: {}", err),
-            Error::Base58EncodeError(ref err) => write!(f, "bs58 encode error: {}", err),
-            Error::Base58DecodeError(ref err) => write!(f, "bs58 decode error: {}", err),
-            Error::ConfigNotFound => f.write_str("No config file detected. Please create one."),
-            Error::KeypairPathNotFound => f.write_str("No keypair file detected."),
-            Error::CashierKeysNotFound => f.write_str("No cashier public keys detected."),
-            Error::SetLoggerError => f.write_str("SetLoggerError"),
-            Error::TokenParseError => f.write_str("Could not parse token parameter"),
-            Error::TungsteniteError => f.write_str("TungsteniteError"),
-            Error::NetworkParseError => f.write_str("Cannot parse network parameter"),
-        }
-    }
+    #[error(transparent)]
+    AsyncChannelReceiverError(#[from] async_channel::RecvError),
 }
 
 impl From<zeromq::ZmqError> for Error {
@@ -175,6 +163,12 @@ impl From<rocksdb::Error> for Error {
     }
 }
 
+impl From<rusqlite::Error> for Error {
+    fn from(err: rusqlite::Error) -> Error {
+        Error::RusqliteError(err.to_string())
+    }
+}
+
 impl From<serde_json::Error> for Error {
     fn from(err: serde_json::Error) -> Error {
         Error::SerdeJsonError(err.to_string())
@@ -187,21 +181,9 @@ impl From<std::io::Error> for Error {
     }
 }
 
-impl From<rusqlite::Error> for Error {
-    fn from(err: rusqlite::Error) -> Error {
-        Error::RusqliteError(err.to_string())
-    }
-}
-
-impl From<ZkVmError> for Error {
-    fn from(_err: ZkVmError) -> Error {
-        Error::VmError
-    }
-}
-
-impl From<bellman::SynthesisError> for Error {
-    fn from(_err: bellman::SynthesisError) -> Error {
-        Error::Groth16Error
+impl From<client::ClientFailed> for Error {
+    fn from(err: client::ClientFailed) -> Error {
+        Error::ClientFailed(err.to_string())
     }
 }
 
@@ -211,88 +193,26 @@ impl<T> From<async_channel::SendError<T>> for Error {
     }
 }
 
-impl From<async_channel::RecvError> for Error {
-    fn from(_err: async_channel::RecvError) -> Error {
-        Error::AsyncChannelReceiverError
+impl From<log::SetLoggerError> for Error {
+    fn from(_err: log::SetLoggerError) -> Error {
+        Error::SetLoggerError
     }
 }
 
-impl From<async_native_tls::Error> for Error {
-    fn from(_err: async_native_tls::Error) -> Error {
-        Error::AsyncNativeTlsError
+impl From<tungstenite::Error> for Error {
+    fn from(err: tungstenite::Error) -> Error {
+        Error::TungsteniteError(err.to_string())
     }
 }
-
-impl From<std::net::AddrParseError> for Error {
-    fn from(_err: std::net::AddrParseError) -> Error {
-        Error::AddrParseError
+impl From<async_native_tls::Error> for Error {
+    fn from(err: async_native_tls::Error) -> Error {
+        Error::AsyncNativeTlsError(err.to_string())
     }
 }
 
 impl From<url::ParseError> for Error {
-    fn from(_err: url::ParseError) -> Error {
-        Error::UrlParseError
-    }
-}
-
-impl From<hex::FromHexError> for Error {
-    fn from(_err: hex::FromHexError) -> Error {
-        Error::FromHexError
-    }
-}
-
-impl From<std::num::ParseIntError> for Error {
-    fn from(_err: std::num::ParseIntError) -> Error {
-        Error::ParseIntError
-    }
-}
-
-impl From<num_bigint::ParseBigIntError> for Error {
-    fn from(_err: num_bigint::ParseBigIntError) -> Error {
-        Error::ParseBigIntError
-    }
-}
-
-impl From<num_bigint::TryFromBigIntError<num_bigint::BigUint>> for Error {
-    fn from(_err: num_bigint::TryFromBigIntError<num_bigint::BigUint>) -> Error {
-        Error::TryFromBigIntError
-    }
-}
-
-impl From<std::num::ParseFloatError> for Error {
-    fn from(_err: std::num::ParseFloatError) -> Error {
-        Error::ParseFloatError
-    }
-}
-
-impl From<std::string::FromUtf8Error> for Error {
-    fn from(_err: std::string::FromUtf8Error) -> Error {
-        Error::Utf8Error
-    }
-}
-
-impl From<std::str::Utf8Error> for Error {
-    fn from(err: std::str::Utf8Error) -> Error {
-        Error::StrUtf8Error(err.to_string())
-    }
-}
-
-impl From<state::VerifyFailed> for Error {
-    fn from(_err: state::VerifyFailed) -> Error {
-        Error::VerifyFailed
-    }
-}
-
-impl From<client::ClientFailed> for Error {
-    fn from(err: client::ClientFailed) -> Error {
-        Error::ClientFailed(err.to_string())
-    }
-}
-
-#[cfg(feature = "btc")]
-impl From<crate::service::BtcFailed> for Error {
-    fn from(err: crate::service::BtcFailed) -> Error {
-        Error::BtcFailed(err.to_string())
+    fn from(err: url::ParseError) -> Error {
+        Error::UrlParseError(err.to_string())
     }
 }
 
@@ -303,45 +223,8 @@ impl From<crate::service::SolFailed> for Error {
     }
 }
 
-#[cfg(feature = "eth")]
-impl From<crate::service::EthFailed> for Error {
-    fn from(err: crate::service::EthFailed) -> Error {
-        Error::EthFailed(err.to_string())
-    }
-}
-
-impl From<toml::de::Error> for Error {
-    fn from(err: toml::de::Error) -> Error {
-        Error::TomlDeserializeError(err.to_string())
-    }
-}
-
-impl From<toml::ser::Error> for Error {
-    fn from(err: toml::ser::Error) -> Error {
-        Error::TomlSerializeError(err.to_string())
-    }
-}
-
-impl From<bs58::encode::Error> for Error {
-    fn from(err: bs58::encode::Error) -> Error {
-        Error::Base58EncodeError(err.to_string())
-    }
-}
-
-impl From<bs58::decode::Error> for Error {
-    fn from(err: bs58::decode::Error) -> Error {
-        Error::Base58DecodeError(err.to_string())
-    }
-}
-
-impl From<log::SetLoggerError> for Error {
-    fn from(_err: log::SetLoggerError) -> Error {
-        Error::SetLoggerError
-    }
-}
-
-impl From<tungstenite::Error> for Error {
-    fn from(_err: tungstenite::Error) -> Error {
-        Error::TungsteniteError
+impl From<bellman::SynthesisError> for Error {
+    fn from(err: bellman::SynthesisError) -> Error {
+        Error::Groth16Error(err.to_string())
     }
 }

+ 7 - 2
src/rpc/jsonrpc.rs

@@ -154,7 +154,12 @@ pub async fn send_raw_request(url: &str, data: Value) -> Result<JsonResult, Erro
     match parsed_url.scheme() {
         "tcp" => use_tls = false,
         "tls" => use_tls = true,
-        _ => return Err(Error::UrlParseError),
+        scheme => {
+            return Err(Error::UrlParseError(format!(
+                "Invalid scheme `{}` found in `{}`",
+                scheme, parsed_url
+            )))
+        }
     }
 
     // TODO: Error handling
@@ -166,7 +171,7 @@ pub async fn send_raw_request(url: &str, data: Value) -> Result<JsonResult, Erro
         smol::unblock(move || (host.as_str(), port).to_socket_addrs())
             .await?
             .next()
-            .ok_or(Error::UrlParseError)?
+            .ok_or(Error::NoUrlFound)?
     };
 
     let mut buf = [0; 2048];

+ 12 - 4
src/rpc/websockets.rs

@@ -63,15 +63,20 @@ impl Stream for WsStream {
 /// Connects to a WebSocket address (optionally secured by TLS).
 pub async fn connect(addr: &str, tls: TlsConnector) -> DrkResult<(WsStream, Response)> {
     let url = Url::parse(addr)?;
-    let host = url.host_str().ok_or(Error::UrlParseError)?.to_string();
-    let port = url.port_or_known_default().ok_or(Error::UrlParseError)?;
+    let host = url
+        .host_str()
+        .ok_or(Error::UrlParseError(format!("Missing Host in {}", url)))?
+        .to_string();
+    let port = url
+        .port_or_known_default()
+        .ok_or_else(|| Error::UrlParseError(format!("Missing port in {}", url)))?;
 
     let socket_addr = {
         let host = host.clone();
         smol::unblock(move || (host.as_str(), port).to_socket_addrs())
             .await?
             .next()
-            .ok_or(Error::UrlParseError)?
+            .ok_or(Error::NoUrlFound)?
     };
 
     match url.scheme() {
@@ -86,6 +91,9 @@ pub async fn connect(addr: &str, tls: TlsConnector) -> DrkResult<(WsStream, Resp
             let (stream, resp) = async_tungstenite::client_async(addr, stream).await?;
             Ok((WsStream::Tls(stream), resp))
         }
-        _scheme => Err(Error::UrlParseError),
+        scheme => Err(Error::UrlParseError(format!(
+            "Invalid url scheme `{}`, in `{}`",
+            scheme, url
+        ))),
     }
 }

+ 8 - 29
src/service/btc.rs

@@ -391,7 +391,6 @@ impl BtcClient {
             match new_status {
                 ScriptStatus::Unseen => continue,
                 ScriptStatus::InMempool => {
-
                     break;
                 }
                 ScriptStatus::Confirmed(inner) => {
@@ -842,43 +841,23 @@ impl Decodable for Keypair {
     }
 }
 
-#[derive(Debug)]
+#[derive(Debug, Clone, thiserror::Error)]
 pub enum BtcFailed {
+    #[error("There is no enough value {0}")]
     NotEnoughValue(u64),
+    #[error("could not parse BTC address: {0}")]
     BadBtcAddress(String),
+    #[error("Unable to create Electrum Client: {0}")]
     ElectrumError(String),
+    #[error("BtcFailed: {0}")]
     BtcError(String),
+    #[error("Decode and decode keys error: {0}")]
     DecodeAndEncodeError(String),
+    #[error("Keypair error from Secp256k1:  {0}")]
     KeypairError(String),
+    #[error("Received Notification Error: {0}")]
     Notification(String),
 }
-impl std::error::Error for BtcFailed {}
-
-impl std::fmt::Display for BtcFailed {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        match self {
-            BtcFailed::NotEnoughValue(i) => {
-                write!(f, "There is no enough value {}", i)
-            }
-            BtcFailed::BadBtcAddress(ref err) => {
-                write!(f, "Unable to create Electrum Client: {}", err)
-            }
-            BtcFailed::ElectrumError(ref err) => write!(f, "could not parse BTC address: {}", err),
-            BtcFailed::DecodeAndEncodeError(ref err) => {
-                write!(f, "Decode and decode keys error: {}", err)
-            }
-            BtcFailed::KeypairError(ref err) => {
-                write!(f, "Keypair error from Secp256k1: {}", err)
-            }
-            BtcFailed::Notification(i) => {
-                write!(f, "Received Notification Error: {}", i)
-            }
-            BtcFailed::BtcError(i) => {
-                write!(f, "BtcFailed: {}", i)
-            }
-        }
-    }
-}
 
 impl From<crate::error::Error> for BtcFailed {
     fn from(err: crate::error::Error) -> BtcFailed {

+ 11 - 40
src/service/eth.rs

@@ -502,59 +502,30 @@ impl Decodable for Keypair {
     }
 }
 
-#[derive(Debug)]
+#[derive(Debug, Clone, thiserror::Error)]
 pub enum EthFailed {
+    #[error("There is no enough value {0}")]
     NotEnoughValue(u64),
+    #[error("Main Account Has no enough value")]
     MainAccountNotEnoughValue,
+    #[error("Bad Eth Address: {0}")]
     BadEthAddress(String),
+    #[error("Decode and decode keys error: {0}")]
     DecodeAndEncodeError(String),
+    #[error("Rpc Error: {0}")]
     RpcError(String),
+    #[error("Eth client error: {0}")]
     EthClientError(String),
+    #[error("Given mint is not valid: {0}")]
     MintIsNotValid(String),
+    #[error("JsonError: {0}")]
     JsonError(String),
+    #[error("Parse Error: {0}")]
     ParseError(String),
+    #[error("Unable to derive address from private key")]
     ImportPrivateError,
 }
 
-impl std::error::Error for EthFailed {}
-
-impl std::fmt::Display for EthFailed {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        match self {
-            EthFailed::NotEnoughValue(i) => {
-                write!(f, "There is no enough value {}", i)
-            }
-            EthFailed::MainAccountNotEnoughValue => {
-                write!(f, "Main Account Has no enough value")
-            }
-            EthFailed::BadEthAddress(ref err) => {
-                write!(f, "Bad Eth Address: {}", err)
-            }
-            EthFailed::DecodeAndEncodeError(ref err) => {
-                write!(f, "Decode and decode keys error: {}", err)
-            }
-            EthFailed::RpcError(i) => {
-                write!(f, "Rpc Error: {}", i)
-            }
-            EthFailed::ParseError(i) => {
-                write!(f, "Parse Error: {}", i)
-            }
-            EthFailed::MintIsNotValid(i) => {
-                write!(f, "Given mint is not valid: {}", i)
-            }
-            EthFailed::JsonError(i) => {
-                write!(f, "JsonError: {}", i)
-            }
-            EthFailed::ImportPrivateError => {
-                write!(f, "Unable to derive address from private key")
-            }
-            EthFailed::EthClientError(i) => {
-                write!(f, "Eth client error: {}", i)
-            }
-        }
-    }
-}
-
 impl From<crate::error::Error> for EthFailed {
     fn from(err: crate::error::Error) -> EthFailed {
         EthFailed::EthClientError(err.to_string())

+ 2 - 2
src/service/gateway.rs

@@ -186,7 +186,7 @@ impl GatewayClient {
         let addr_sock = (addr.host().unwrap().to_string(), addr.port().unwrap())
             .to_socket_addrs()?
             .next()
-            .ok_or(Error::UrlParseError)?;
+            .ok_or(Error::NoUrlFound)?;
         let protocol = ReqProtocol::new(addr_sock, String::from("GATEWAY CLIENT"));
 
         let slabstore = SlabStore::new(rocks)?;
@@ -199,7 +199,7 @@ impl GatewayClient {
         )
             .to_socket_addrs()?
             .next()
-            .ok_or(Error::UrlParseError)?;
+            .ok_or(Error::NoUrlFound)?;
 
         Ok(GatewayClient {
             protocol,

+ 29 - 97
src/service/sol.rs

@@ -177,7 +177,10 @@ impl SolClient {
         let mut sub_iter = 0;
 
         loop {
-            let message = read.next().await.ok_or(Error::TungsteniteError)?;
+            let message = read
+                .next()
+                .await
+                .ok_or_else(|| Error::TungsteniteError("No more messages".to_string()))?;
             let message = message?;
 
             if let Message::Pong(_) = message.clone() {
@@ -324,16 +327,9 @@ impl SolClient {
 
         match rpc.get_account_data(&main_tok_pk) {
             Ok(v) => {
-                match spl_token::state::Account::unpack_from_slice(&v) {
-                    // It's valid token data, and we consider account initialized.
-                    Ok(_) => {}
-                    // Some other unexpected data.
-                    Err(_) => {
-                        return Err(SolFailed::SolClientError(
-                            "Invalid data on derived account".into(),
-                        ));
-                    }
-                }
+                // This will fail in the event of unexpected data
+                // otherwise it's valid token data, and we consider account initialized.
+                spl_token::state::Account::unpack_from_slice(&v)?;
             }
             Err(_) => {
                 // Unitinialized, so we add a creation instruction
@@ -619,100 +615,36 @@ impl Decodable for Pubkey {
     }
 }
 
-#[derive(Debug)]
+#[derive(Debug, thiserror::Error)]
 pub enum SolFailed {
+    #[error("There is no enough value `{0}`")]
     NotEnoughValue(u64),
+    #[error("Main Account Has no enough value")]
     MainAccountNotEnoughValue,
+    #[error("Bad Sol Address: `{0}`")]
     BadSolAddress(String),
+    #[error("Decode and decode keys error: `{0}`")]
     DecodeAndEncodeError(String),
-    WebSocketError(String),
+    #[error(transparent)]
+    WebSocketError(#[from] tungstenite::Error),
+    #[error("RpcError: `{0}`")]
     RpcError(String),
-    SolClientError(String),
+    #[error(transparent)]
+    SolClientError(#[from] solana_client::client_error::ClientError),
+    #[error("Received Notification Error: `{0}`")]
     Notification(String),
-    ProgramError(String),
+    #[error(transparent)]
+    ProgramError(#[from] solana_sdk::program_error::ProgramError),
+    #[error("Given mint is not valid: `{0}`")]
     MintIsNotValid(String),
-    JsonError(String),
-    ParseError(String),
-}
-
-impl std::error::Error for SolFailed {}
-
-impl std::fmt::Display for SolFailed {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        match self {
-            SolFailed::NotEnoughValue(i) => {
-                write!(f, "There is no enough value {}", i)
-            }
-            SolFailed::MainAccountNotEnoughValue => {
-                write!(f, "Main Account Has no enough value")
-            }
-            SolFailed::BadSolAddress(ref err) => {
-                write!(f, "Bad Sol Address: {}", err)
-            }
-            SolFailed::DecodeAndEncodeError(ref err) => {
-                write!(f, "Decode and decode keys error: {}", err)
-            }
-            SolFailed::WebSocketError(i) => {
-                write!(f, "WebSocket Error: {}", i)
-            }
-            SolFailed::RpcError(i) => {
-                write!(f, "Rpc Error: {}", i)
-            }
-            SolFailed::ParseError(i) => {
-                write!(f, "Parse Error: {}", i)
-            }
-            SolFailed::SolClientError(i) => {
-                write!(f, "Solana Client Error: {}", i)
-            }
-            SolFailed::Notification(i) => {
-                write!(f, "Received Notification Error: {}", i)
-            }
-            SolFailed::ProgramError(i) => {
-                write!(f, "ProgramError Error: {}", i)
-            }
-            SolFailed::MintIsNotValid(i) => {
-                write!(f, "Given mint is not valid: {}", i)
-            }
-            SolFailed::JsonError(i) => {
-                write!(f, "JsonError: {}", i)
-            }
-        }
-    }
-}
-
-impl From<solana_sdk::pubkey::ParsePubkeyError> for SolFailed {
-    fn from(err: solana_sdk::pubkey::ParsePubkeyError) -> SolFailed {
-        SolFailed::ParseError(err.to_string())
-    }
-}
-
-impl From<tungstenite::Error> for SolFailed {
-    fn from(err: tungstenite::Error) -> SolFailed {
-        SolFailed::WebSocketError(err.to_string())
-    }
-}
-
-impl From<solana_client::client_error::ClientError> for SolFailed {
-    fn from(err: solana_client::client_error::ClientError) -> SolFailed {
-        SolFailed::SolClientError(err.to_string())
-    }
-}
-
-impl From<solana_sdk::program_error::ProgramError> for SolFailed {
-    fn from(err: solana_sdk::program_error::ProgramError) -> SolFailed {
-        SolFailed::ProgramError(err.to_string())
-    }
-}
-
-impl From<crate::error::Error> for SolFailed {
-    fn from(err: crate::error::Error) -> SolFailed {
-        SolFailed::SolClientError(err.to_string())
-    }
-}
-impl From<serde_json::Error> for SolFailed {
-    fn from(err: serde_json::Error) -> SolFailed {
-        SolFailed::JsonError(err.to_string())
-    }
+    #[error(transparent)]
+    JsonError(#[from] serde_json::Error),
+    #[error(transparent)]
+    ParseError(#[from] solana_sdk::pubkey::ParsePubkeyError),
+    #[error("Signature Error: `{0}`")]
+    Signature(String),
+    #[error(transparent)]
+    Darkfi(#[from] crate::error::Error),
 }
 
 pub type SolResult<T> = std::result::Result<T, SolFailed>;

+ 10 - 33
src/state.rs

@@ -1,5 +1,3 @@
-use std::fmt;
-
 use bellman::groth16;
 use bls12_381::Bls12;
 use log::debug;
@@ -26,49 +24,28 @@ pub struct StateUpdate {
 
 pub type VerifyResult<T> = std::result::Result<T, VerifyFailed>;
 
-#[derive(Debug)]
+#[derive(Debug, Clone, thiserror::Error)]
 pub enum VerifyFailed {
+    #[error("Invalid cashier public key for clear input {0}")]
     InvalidCashierKey(usize),
+    #[error("Invalid merkle root for input {0}")]
     InvalidMerkle(usize),
+    #[error("Duplicate nullifier for input {0}")]
     DuplicateNullifier(usize),
+    #[error("Spend proof for input {0}")]
     SpendProof(usize),
+    #[error("Mint proof for input {0}")]
     MintProof(usize),
+    #[error("Invalid signature for clear input {0}")]
     ClearInputSignature(usize),
+    #[error("Invalid signature for input {0}")]
     InputSignature(usize),
+    #[error("Money in does not match money out (value commits)")]
     MissingFunds,
+    #[error("Assets don't match some inputs or outputs (token commits)")]
     AssetMismatch,
 }
 
-impl std::error::Error for VerifyFailed {}
-
-impl fmt::Display for VerifyFailed {
-    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
-        match *self {
-            VerifyFailed::InvalidCashierKey(i) => {
-                write!(f, "Invalid cashier public key for clear input {}", i)
-            }
-            VerifyFailed::InvalidMerkle(i) => {
-                write!(f, "Invalid merkle root for input {}", i)
-            }
-            VerifyFailed::DuplicateNullifier(i) => {
-                write!(f, "Duplicate nullifier for input {}", i)
-            }
-            VerifyFailed::SpendProof(i) => write!(f, "Spend proof for input {}", i),
-            VerifyFailed::MintProof(i) => write!(f, "Mint proof for input {}", i),
-            VerifyFailed::ClearInputSignature(i) => {
-                write!(f, "Invalid signature for clear input {}", i)
-            }
-            VerifyFailed::InputSignature(i) => write!(f, "Invalid signature for input {}", i),
-            VerifyFailed::MissingFunds => {
-                f.write_str("Money in does not match money out (value commits)")
-            }
-            VerifyFailed::AssetMismatch => {
-                f.write_str("Assets don't match some inputs or outputs (token commits)")
-            }
-        }
-    }
-}
-
 pub fn state_transition<S: ProgramState>(
     state: &async_std::sync::MutexGuard<S>,
     tx: tx::Transaction,

+ 3 - 3
src/util/mod.rs

@@ -1,11 +1,11 @@
+pub mod address;
 pub mod net_name;
 pub mod parse;
 pub mod path;
 pub mod token_list;
-pub mod address;
 
+pub use address::Address;
 pub use net_name::NetworkName;
 pub use parse::{assign_id, decode_base10, encode_base10, generate_id};
-pub use address::Address;
-pub use token_list::{DrkTokenList, TokenList};
 pub use path::{expand_path, join_config_path};
+pub use token_list::{DrkTokenList, TokenList};

+ 3 - 1
src/vm.rs

@@ -75,9 +75,11 @@ pub enum ConstraintInstruction {
     LcCoeffDouble,
 }
 
-#[derive(Debug)]
+#[derive(Debug, Copy, Clone, thiserror::Error)]
 pub enum ZkVmError {
+    #[error("DivisionByZero")]
     DivisionByZero,
+    #[error("MalformedRange")]
     MalformedRange,
 }
 

+ 1 - 3
src/wallet/cashierdb.rs

@@ -148,8 +148,6 @@ impl CashierDb {
         Ok(())
     }
 
-
-
     pub fn put_withdraw_keys(
         &self,
         token_key_public: &[u8],
@@ -652,7 +650,7 @@ mod tests {
         let addr = wallet.get_withdraw_keys_by_token_public_key(&token_addr, &network)?;
 
         assert!(addr.is_some());
-        
+
         wallet.remove_withdraw_and_deposit_keys()?;
 
         std::fs::remove_file(walletdb_path)?;