// 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 crate::core::libtx; use crate::keychain; use crate::libwallet; use failure::{Backtrace, Context, Fail}; use std::env; use std::fmt::{self, Display}; /// Error definition #[derive(Debug)] pub struct Error { pub 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: {}", _1)] LibWallet(libwallet::ErrorKind, String), /// Keychain error #[fail(display = "Keychain error")] Keychain(keychain::Error), /// Error when formatting json #[fail(display = "IO error")] IO, /// Error when formatting json #[fail(display = "Serde JSON error")] Format, /// Wallet seed already exists #[fail(display = "Wallet seed file exists: {}", _0)] WalletSeedExists(String), /// Wallet seed doesn't exist #[fail(display = "Wallet seed doesn't exist error")] WalletSeedDoesntExist, /// Enc/Decryption Error #[fail(display = "Enc/Decryption error (check password?)")] Encryption, /// BIP 39 word list #[fail(display = "BIP39 Mnemonic (word list) Error")] Mnemonic, /// Command line argument error #[fail(display = "{}", _0)] ArgumentError(String), /// Other #[fail(display = "Generic error: {}", _0)] GenericError(String), } impl Fail for Error { fn cause(&self) -> Option<&dyn 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 show_bt = match env::var("RUST_BACKTRACE") { Ok(r) => { if r == "1" { true } else { false } } Err(_) => false, }; let backtrace = match self.backtrace() { Some(b) => format!("{}", b), None => String::from("Unknown"), }; let inner_output = format!("{}", self.inner,); let backtrace_output = format!("\nBacktrace: {}", backtrace); let mut output = inner_output.clone(); if show_bt { output.push_str(&backtrace_output); } 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<&dyn 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: keychain::Error) -> Error { Error { inner: Context::new(ErrorKind::Keychain(error)), } } } impl From for Error { fn from(error: libwallet::Error) -> Error { Error { inner: Context::new(ErrorKind::LibWallet(error.kind(), format!("{}", error))), } } } impl From for Error { fn from(error: libtx::Error) -> Error { Error { inner: Context::new(ErrorKind::LibTX(error.kind())), } } }