diff --git a/Cargo.lock b/Cargo.lock index c4da13cc9..e4bf44f31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1347,6 +1347,7 @@ dependencies = [ "solana-sdk", "spl-associated-token-account", "spl-token", + "thiserror", "toml", "tungstenite 0.15.0", "url", diff --git a/Cargo.toml b/Cargo.toml index b52bcd71f..c25a30897 100644 --- a/Cargo.toml +++ b/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"] diff --git a/src/bin/cashierd.rs b/src/bin/cashierd.rs index 0b357c7f5..ae742ecc4 100644 --- a/src/bin/cashierd.rs +++ b/src/bin/cashierd.rs @@ -472,10 +472,7 @@ impl Cashierd { mut client: Client, state: Arc>, executor: Arc>, - ) -> Result<( - smol::Task>, - smol::Task>, - )> { + ) -> Result<(smol::Task>, smol::Task>)> { self.cashier_wallet.init_db().await?; for network in self.networks.iter() { @@ -512,7 +509,7 @@ impl Cashierd { )?)?; let keypair_bytes: Vec = 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?; diff --git a/src/cli/cli_config.rs b/src/cli/cli_config.rs index 7169ad3a6..b821a5eb6 100644 --- a/src/cli/cli_config.rs +++ b/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, diff --git a/src/client.rs b/src/client.rs index 66636513a..cdd1cb648 100644 --- a/src/client.rs +++ b/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 for ClientFailed { fn from(err: super::error::Error) -> ClientFailed { ClientFailed::ClientError(err.to_string()) diff --git a/src/crypto/coin.rs b/src/crypto/coin.rs index bf3d576fe..d54f4f633 100644 --- a/src/crypto/coin.rs +++ b/src/crypto/coin.rs @@ -29,4 +29,3 @@ impl Decodable for Coin { }) } } - diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs index a9c6e7e70..60dc2df2f 100644 --- a/src/crypto/mod.rs +++ b/src/crypto/mod.rs @@ -25,7 +25,7 @@ pub struct OwnCoin { pub note: note::Note, pub secret: jubjub::Fr, pub witness: merkle::IncrementalWitness, - pub nullifier: nullifier::Nullifier + pub nullifier: nullifier::Nullifier, } pub type OwnCoins = Vec; diff --git a/src/crypto/nullifier.rs b/src/crypto/nullifier.rs index 641bbdb15..b2a37d32b 100644 --- a/src/crypto/nullifier.rs +++ b/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 { }) } } - diff --git a/src/error.rs b/src/error.rs index 4f172e302..74f9f031c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,166 +1,154 @@ -use std::fmt; - use crate::client; use crate::state; use crate::vm::ZkVmError; pub type Result = std::result::Result; -#[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), + #[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 for Error { @@ -175,6 +163,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: rusqlite::Error) -> Error { + Error::RusqliteError(err.to_string()) + } +} + impl From for Error { fn from(err: serde_json::Error) -> Error { Error::SerdeJsonError(err.to_string()) @@ -187,150 +181,15 @@ impl From for Error { } } -impl From for Error { - fn from(err: rusqlite::Error) -> Error { - Error::RusqliteError(err.to_string()) - } -} - -impl From for Error { - fn from(_err: ZkVmError) -> Error { - Error::VmError - } -} - -impl From for Error { - fn from(_err: bellman::SynthesisError) -> Error { - Error::Groth16Error - } -} - -impl From> for Error { - fn from(_err: async_channel::SendError) -> Error { - Error::AsyncChannelSenderError - } -} - -impl From for Error { - fn from(_err: async_channel::RecvError) -> Error { - Error::AsyncChannelReceiverError - } -} - -impl From for Error { - fn from(_err: async_native_tls::Error) -> Error { - Error::AsyncNativeTlsError - } -} - -impl From for Error { - fn from(_err: std::net::AddrParseError) -> Error { - Error::AddrParseError - } -} - -impl From for Error { - fn from(_err: url::ParseError) -> Error { - Error::UrlParseError - } -} - -impl From for Error { - fn from(_err: hex::FromHexError) -> Error { - Error::FromHexError - } -} - -impl From for Error { - fn from(_err: std::num::ParseIntError) -> Error { - Error::ParseIntError - } -} - -impl From for Error { - fn from(_err: num_bigint::ParseBigIntError) -> Error { - Error::ParseBigIntError - } -} - -impl From> for Error { - fn from(_err: num_bigint::TryFromBigIntError) -> Error { - Error::TryFromBigIntError - } -} - -impl From for Error { - fn from(_err: std::num::ParseFloatError) -> Error { - Error::ParseFloatError - } -} - -impl From for Error { - fn from(_err: std::string::FromUtf8Error) -> Error { - Error::Utf8Error - } -} - -impl From for Error { - fn from(err: std::str::Utf8Error) -> Error { - Error::StrUtf8Error(err.to_string()) - } -} - -impl From for Error { - fn from(_err: state::VerifyFailed) -> Error { - Error::VerifyFailed - } -} - impl From for Error { fn from(err: client::ClientFailed) -> Error { Error::ClientFailed(err.to_string()) } } -#[cfg(feature = "btc")] -impl From for Error { - fn from(err: crate::service::BtcFailed) -> Error { - Error::BtcFailed(err.to_string()) - } -} - -#[cfg(feature = "sol")] -impl From for Error { - fn from(err: crate::service::SolFailed) -> Error { - Error::SolFailed(err.to_string()) - } -} - -#[cfg(feature = "eth")] -impl From for Error { - fn from(err: crate::service::EthFailed) -> Error { - Error::EthFailed(err.to_string()) - } -} - -impl From for Error { - fn from(err: toml::de::Error) -> Error { - Error::TomlDeserializeError(err.to_string()) - } -} - -impl From for Error { - fn from(err: toml::ser::Error) -> Error { - Error::TomlSerializeError(err.to_string()) - } -} - -impl From for Error { - fn from(err: bs58::encode::Error) -> Error { - Error::Base58EncodeError(err.to_string()) - } -} - -impl From for Error { - fn from(err: bs58::decode::Error) -> Error { - Error::Base58DecodeError(err.to_string()) +impl From> for Error { + fn from(_err: async_channel::SendError) -> Error { + Error::AsyncChannelSenderError } } @@ -341,7 +200,31 @@ impl From for Error { } impl From for Error { - fn from(_err: tungstenite::Error) -> Error { - Error::TungsteniteError + fn from(err: tungstenite::Error) -> Error { + Error::TungsteniteError(err.to_string()) + } +} +impl From for Error { + fn from(err: async_native_tls::Error) -> Error { + Error::AsyncNativeTlsError(err.to_string()) + } +} + +impl From for Error { + fn from(err: url::ParseError) -> Error { + Error::UrlParseError(err.to_string()) + } +} + +#[cfg(feature = "sol")] +impl From for Error { + fn from(err: crate::service::SolFailed) -> Error { + Error::SolFailed(err.to_string()) + } +} + +impl From for Error { + fn from(err: bellman::SynthesisError) -> Error { + Error::Groth16Error(err.to_string()) } } diff --git a/src/rpc/jsonrpc.rs b/src/rpc/jsonrpc.rs index f25e61d58..472f97238 100644 --- a/src/rpc/jsonrpc.rs +++ b/src/rpc/jsonrpc.rs @@ -154,7 +154,12 @@ pub async fn send_raw_request(url: &str, data: Value) -> Result 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 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 + ))), } } diff --git a/src/service/btc.rs b/src/service/btc.rs index 5bf12f812..98f4b3421 100644 --- a/src/service/btc.rs +++ b/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 for BtcFailed { fn from(err: crate::error::Error) -> BtcFailed { diff --git a/src/service/eth.rs b/src/service/eth.rs index 542bf83af..dbe1821ec 100644 --- a/src/service/eth.rs +++ b/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 for EthFailed { fn from(err: crate::error::Error) -> EthFailed { EthFailed::EthClientError(err.to_string()) diff --git a/src/service/gateway.rs b/src/service/gateway.rs index 424fa4275..0856f0675 100644 --- a/src/service/gateway.rs +++ b/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, diff --git a/src/service/sol.rs b/src/service/sol.rs index 00d22eea5..4b68760be 100644 --- a/src/service/sol.rs +++ b/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 for SolFailed { - fn from(err: solana_sdk::pubkey::ParsePubkeyError) -> SolFailed { - SolFailed::ParseError(err.to_string()) - } -} - -impl From for SolFailed { - fn from(err: tungstenite::Error) -> SolFailed { - SolFailed::WebSocketError(err.to_string()) - } -} - -impl From for SolFailed { - fn from(err: solana_client::client_error::ClientError) -> SolFailed { - SolFailed::SolClientError(err.to_string()) - } -} - -impl From for SolFailed { - fn from(err: solana_sdk::program_error::ProgramError) -> SolFailed { - SolFailed::ProgramError(err.to_string()) - } -} - -impl From for SolFailed { - fn from(err: crate::error::Error) -> SolFailed { - SolFailed::SolClientError(err.to_string()) - } -} -impl From 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 = std::result::Result; diff --git a/src/state.rs b/src/state.rs index 9a9fe0fa4..d1e6780f7 100644 --- a/src/state.rs +++ b/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 = std::result::Result; -#[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( state: &async_std::sync::MutexGuard, tx: tx::Transaction, diff --git a/src/util/mod.rs b/src/util/mod.rs index 7cfcd410d..1de20edea 100644 --- a/src/util/mod.rs +++ b/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}; diff --git a/src/vm.rs b/src/vm.rs index 4380cb527..8f40c9da7 100644 --- a/src/vm.rs +++ b/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, } diff --git a/src/wallet/cashierdb.rs b/src/wallet/cashierdb.rs index b44c493d9..94ca6f324 100644 --- a/src/wallet/cashierdb.rs +++ b/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)?;