// Copyright 2018 The Grin Developers // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! Implementation specific error types use api; use keychain; use libtx; use libwallet; use std::fmt::{self, Display}; use core::core::transaction; use failure::{Backtrace, Context, Fail}; /// Error definition #[derive(Debug)] pub struct Error { inner: Context, } /// Wallet errors, mostly wrappers around underlying crypto or I/O errors. #[derive(Clone, Eq, PartialEq, Debug, Fail)] pub enum ErrorKind { /// LibTX Error #[fail(display = "LibTx Error")] LibTX(libtx::ErrorKind), /// LibWallet Error #[fail(display = "LibWallet Error")] LibWallet(libwallet::ErrorKind), /// Keychain error #[fail(display = "Keychain error")] Keychain(keychain::Error), /// Transaction Error #[fail(display = "Transaction error")] Transaction(transaction::Error), /// Secp Error #[fail(display = "Secp error")] Secp, /// Filewallet error #[fail(display = "Wallet data error: {}", _0)] FileWallet(&'static str), /// Error when formatting json #[fail(display = "IO error")] IO, /// Error when formatting json #[fail(display = "Serde JSON error")] Format, /// Error when contacting a node through its API #[fail(display = "Node API error")] Node(api::ErrorKind), /// Error originating from hyper. #[fail(display = "Hyper error")] Hyper, /// Error originating from hyper uri parsing. #[fail(display = "Uri parsing error")] Uri, /// Attempt to use duplicate transaction id in separate transactions #[fail(display = "Duplicate transaction ID error")] DuplicateTransactionId, /// Wallet seed already exists #[fail(display = "Wallet seed exists error")] WalletSeedExists, /// Wallet seed doesn't exist #[fail(display = "Wallet seed doesn't exist error")] WalletSeedDoesntExist, /// Other #[fail(display = "Generic error: {}", _0)] GenericError(&'static str), } impl Fail for Error { fn cause(&self) -> Option<&Fail> { self.inner.cause() } fn backtrace(&self) -> Option<&Backtrace> { self.inner.backtrace() } } impl Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let cause = match self.cause() { Some(c) => format!("{}", c), None => String::from("Unknown"), }; let backtrace = match self.backtrace() { Some(b) => format!("{}", b), None => String::from("Unknown"), }; let output = format!( "{} \n Cause: {} \n Backtrace: {}", self.inner, cause, backtrace ); Display::fmt(&output, f) } } impl Error { /// get kind pub fn kind(&self) -> ErrorKind { self.inner.get_context().clone() } /// get cause pub fn cause(&self) -> Option<&Fail> { self.inner.cause() } /// get backtrace pub fn backtrace(&self) -> Option<&Backtrace> { self.inner.backtrace() } } impl From for Error { fn from(kind: ErrorKind) -> Error { Error { inner: Context::new(kind), } } } impl From> for Error { fn from(inner: Context) -> Error { Error { inner: inner } } } impl From for Error { fn from(error: api::Error) -> Error { Error { inner: Context::new(ErrorKind::Node(error.kind().clone())), } } } impl From for Error { fn from(error: keychain::Error) -> Error { Error { inner: Context::new(ErrorKind::Keychain(error)), } } } impl From for Error { fn from(error: transaction::Error) -> Error { Error { inner: Context::new(ErrorKind::Transaction(error)), } } } impl From for Error { fn from(error: libwallet::Error) -> Error { Error { inner: Context::new(ErrorKind::LibWallet(error.kind())), } } } impl From for Error { fn from(error: libtx::Error) -> Error { Error { inner: Context::new(ErrorKind::LibTX(error.kind())), } } }