Replace failure with thiserror (#654)

* updated util and libwallet with thiserror

* update impl crate to thiserror

* api crate converted to thiserror

* update of controller crate to thiserror

* update final bin + tests to thiserror

* update unused import

* remove failure derive

* reset import of grin to master

* update cargo lock

* update from master
This commit is contained in:
Yeastplume
2022-07-28 10:21:45 +01:00
committed by GitHub
parent 67f0e2b0e0
commit 64cab53b1b
63 changed files with 1066 additions and 1586 deletions
+9 -11
View File
@@ -18,7 +18,7 @@ use crate::api::TLSConfig;
use crate::apiwallet::{try_slatepack_sync_workflow, Owner};
use crate::config::{TorConfig, WalletConfig, WALLET_CONFIG_FILE_NAME};
use crate::core::{core, global};
use crate::error::{Error, ErrorKind};
use crate::error::Error;
use crate::impls::PathToSlatepack;
use crate::impls::SlateGetter as _;
use crate::keychain;
@@ -184,7 +184,6 @@ where
}
Err(e) => {
error!("View wallet check failed: {}", e);
error!("Backtrace: {}", e.backtrace().unwrap());
Err(e)
}
}
@@ -235,7 +234,7 @@ where
let r = t.join();
if let Err(_) = r {
error!("Error starting listener");
return Err(ErrorKind::ListenerError.into());
return Err(Error::ListenerError);
}
}
}
@@ -269,7 +268,7 @@ where
test_mode,
);
if let Err(e) = res {
return Err(ErrorKind::LibWallet(e.kind(), e.cause_string()).into());
return Err(Error::LibWallet(e));
}
Ok(())
}
@@ -299,7 +298,7 @@ where
});
if let Err(e) = res {
error!("Error listing accounts: {}", e);
return Err(ErrorKind::LibWallet(e.kind(), e.cause_string()).into());
return Err(Error::LibWallet(e));
}
} else {
let label = args.create.unwrap();
@@ -312,7 +311,7 @@ where
if let Err(e) = res {
thread::sleep(Duration::from_millis(200));
error!("Error creating account '{}': {}", label, e);
return Err(ErrorKind::LibWallet(e.kind(), e.cause_string()).into());
return Err(Error::LibWallet(e));
}
}
Ok(())
@@ -616,7 +615,7 @@ where
}
None => {
let msg = "No slate provided via file or direct input";
return Err(ErrorKind::GenericError(msg.into()).into());
return Err(Error::GenericError(msg.into()).into());
}
}
slate
@@ -740,7 +739,7 @@ where
sp
}
None => {
return Err(ErrorKind::ArgumentError("Invalid Slatepack Input".into()).into());
return Err(Error::ArgumentError("Invalid Slatepack Input".into()).into());
}
},
};
@@ -1343,7 +1342,6 @@ where
}
Err(e) => {
error!("Wallet check failed: {}", e);
error!("Backtrace: {}", e.backtrace().unwrap());
Err(e)
}
}
@@ -1436,7 +1434,7 @@ where
"Unable to open payment proof file at {}: {}",
args.input_file, e
);
return Err(libwallet::ErrorKind::PaymentProofParsing(msg).into());
return Err(libwallet::Error::PaymentProofParsing(msg));
}
};
let mut proof = String::new();
@@ -1447,7 +1445,7 @@ where
Err(e) => {
let msg = format!("{}", e);
error!("Unable to parse payment proof file: {}", e);
return Err(libwallet::ErrorKind::PaymentProofParsing(msg).into());
return Err(libwallet::Error::PaymentProofParsing(msg));
}
};
let result = api.verify_payment_proof(m, &proof);
+23 -29
View File
@@ -18,12 +18,11 @@ use crate::api::{self, ApiServer, BasicAuthMiddleware, ResponseFuture, Router, T
use crate::config::TorConfig;
use crate::keychain::Keychain;
use crate::libwallet::{
address, Error, ErrorKind, NodeClient, NodeVersionInfo, Slate, SlatepackAddress, WalletInst,
address, Error, NodeClient, NodeVersionInfo, Slate, SlatepackAddress, WalletInst,
WalletLCProvider, GRIN_BLOCK_HEADER_VERSION,
};
use crate::util::secp::key::SecretKey;
use crate::util::{from_hex, static_secp_instance, to_base64, Mutex};
use failure::ResultExt;
use futures::channel::oneshot;
use grin_wallet_api::JsonId;
use grin_wallet_config::types::{TorBridgeConfig, TorProxyConfig};
@@ -70,7 +69,7 @@ fn check_middleware(
}
if let Some(s) = slate {
if bhv > 4 && s.version_info.block_header_version < GRIN_BLOCK_HEADER_VERSION {
Err(ErrorKind::Compatibility(
Err(Error::Compatibility(
"Incoming Slate is not compatible with this wallet. \
Please upgrade the node or use a different one."
.into(),
@@ -105,9 +104,9 @@ where
let parent_key_id = w_inst.parent_key_id();
let tor_dir = format!("{}/tor/listener", lc.get_top_level_directory()?);
let sec_key = address::address_from_derivation_path(&k, &parent_key_id, 0)
.map_err(|e| ErrorKind::TorConfig(format!("{:?}", e).into()))?;
.map_err(|e| Error::TorConfig(format!("{:?}", e)))?;
let onion_address = OnionV3Address::from_private(&sec_key.0)
.map_err(|e| ErrorKind::TorConfig(format!("{:?}", e).into()))?;
.map_err(|e| Error::TorConfig(format!("{:?}", e)))?;
let sp_address = SlatepackAddress::try_from(onion_address.clone())?;
let mut hm_tor_bridge: HashMap<String, String> = HashMap::new();
@@ -115,19 +114,19 @@ where
if bridge.bridge_line.is_some() {
tor_timeout = 40;
let bridge_config = tor_bridge::TorBridge::try_from(bridge)
.map_err(|e| ErrorKind::TorConfig(format!("{}", e).into()))?;
.map_err(|e| Error::TorConfig(format!("{}", e).into()))?;
hm_tor_bridge = bridge_config
.to_hashmap()
.map_err(|e| ErrorKind::TorConfig(format!("{}", e).into()))?;
.map_err(|e| Error::TorConfig(format!("{}", e).into()))?;
}
let mut hm_tor_poxy: HashMap<String, String> = HashMap::new();
if tor_proxy.transport.is_some() || tor_proxy.allowed_port.is_some() {
let proxy_config = tor_proxy::TorProxy::try_from(tor_proxy)
.map_err(|e| ErrorKind::TorConfig(format!("{}", e).into()))?;
.map_err(|e| Error::TorConfig(format!("{}", e).into()))?;
hm_tor_poxy = proxy_config
.to_hashmap()
.map_err(|e| ErrorKind::TorConfig(format!("{}", e.kind()).into()))?;
.map_err(|e| Error::TorConfig(format!("{}", e).into()))?;
}
warn!(
@@ -141,7 +140,7 @@ where
hm_tor_bridge,
hm_tor_poxy,
)
.map_err(|e| ErrorKind::TorConfig(format!("{:?}", e).into()))?;
.map_err(|e| Error::TorConfig(format!("{:?}", e).into()))?;
// Start TOR process
process
.torrc_path(&format!("{}/torrc", tor_dir))
@@ -149,7 +148,7 @@ where
.timeout(tor_timeout)
.completion_percent(100)
.launch()
.map_err(|e| ErrorKind::TorProcess(format!("{:?}", e).into()))?;
.map_err(|e| Error::TorProcess(format!("{:?}", e)))?;
Ok((process, sp_address))
}
@@ -173,10 +172,9 @@ where
let wallet = match wallet {
Some(w) => w,
None => {
return Err(ErrorKind::GenericError(format!(
return Err(Error::GenericError(format!(
"Instantiated wallet or Owner API context must be provided"
))
.into())
)))
}
};
f(&mut Owner::new(wallet, None), keychain_mask)?
@@ -251,7 +249,7 @@ where
router
.add_route("/v3/owner", Arc::new(api_handler_v3))
.map_err(|_| ErrorKind::GenericError("Router failed to add route".to_string()))?;
.map_err(|_| Error::GenericError("Router failed to add route".to_string()))?;
// If so configured, add the foreign API to the same port
if running_foreign {
@@ -260,7 +258,7 @@ where
ForeignAPIHandlerV2::new(wallet, keychain_mask, test_mode, Mutex::new(tor_config));
router
.add_route("/v2/foreign", Arc::new(foreign_api_handler_v2))
.map_err(|_| ErrorKind::GenericError("Router failed to add route".to_string()))?;
.map_err(|_| Error::GenericError("Router failed to add route".to_string()))?;
}
let api_chan: &'static mut (oneshot::Sender<()>, oneshot::Receiver<()>) =
@@ -271,13 +269,11 @@ where
let socket_addr: SocketAddr = addr.parse().expect("unable to parse socket address");
let api_thread = apis
.start(socket_addr, router, tls_config, api_chan)
.context(ErrorKind::GenericError(
"API thread failed to start".to_string(),
))?;
.map_err(|_| Error::GenericError("API thread failed to start".to_string()))?;
warn!("HTTP Owner listener started.");
api_thread
.join()
.map_err(|e| ErrorKind::GenericError(format!("API thread panicked :{:?}", e)).into())
.map_err(|e| Error::GenericError(format!("API thread panicked :{:?}", e)))
}
/// Listener version, providing same API but listening for requests on a
@@ -336,7 +332,7 @@ where
router
.add_route("/v2/foreign", Arc::new(api_handler_v2))
.map_err(|_| ErrorKind::GenericError("Router failed to add route".to_string()))?;
.map_err(|_| Error::GenericError("Router failed to add route".to_string()))?;
let api_chan: &'static mut (oneshot::Sender<()>, oneshot::Receiver<()>) =
Box::leak(Box::new(oneshot::channel::<()>()));
@@ -346,9 +342,7 @@ where
let socket_addr: SocketAddr = addr.parse().expect("unable to parse socket address");
let api_thread = apis
.start(socket_addr, router, tls_config, api_chan)
.context(ErrorKind::GenericError(
"API thread failed to start".to_string(),
))?;
.map_err(|_| Error::GenericError("API thread failed to start".to_string()))?;
warn!("HTTP Foreign listener started.");
if let Some(a) = address {
@@ -361,7 +355,7 @@ where
api_thread
.join()
.map_err(|e| ErrorKind::GenericError(format!("API thread panicked :{:?}", e)).into())
.map_err(|e| Error::GenericError(format!("API thread panicked :{:?}", e)))
}
/// V3 API Handler/Wrapper for owner functions, which include a secure
@@ -477,7 +471,7 @@ impl OwnerV3Helpers {
})?;
let id = enc_req.id.clone();
let res = enc_req.decrypt(&shared_key).map_err(|e| {
EncryptionErrorResponse::new(1, -32002, &format!("Decryption error: {}", e.kind()))
EncryptionErrorResponse::new(1, -32002, &format!("Decryption error: {}", e))
.as_json_value()
})?;
Ok((id, res))
@@ -492,7 +486,7 @@ impl OwnerV3Helpers {
let share_key_ref = key.lock();
let shared_key = share_key_ref.as_ref().unwrap();
let enc_res = EncryptedResponse::from_json(id, res, &shared_key).map_err(|e| {
EncryptionErrorResponse::new(1, -32003, &format!("EncryptionError: {}", e.kind()))
EncryptionErrorResponse::new(1, -32003, &format!("EncryptionError: {}", e))
.as_json_value()
})?;
let res = enc_res.as_json_value().map_err(|e| {
@@ -874,8 +868,8 @@ where
{
let body = body::to_bytes(req.into_body())
.await
.map_err(|_| ErrorKind::GenericError("Failed to read request".to_string()))?;
.map_err(|_| Error::GenericError("Failed to read request".to_string()))?;
serde_json::from_reader(&body[..])
.map_err(|e| ErrorKind::GenericError(format!("Invalid request body: {}", e)).into())
.map_err(|e| Error::GenericError(format!("Invalid request body: {}", e)))
}
+28 -150
View File
@@ -19,209 +19,87 @@ use crate::core::libtx;
use crate::impls;
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<ErrorKind>,
}
/// Wallet errors, mostly wrappers around underlying crypto or I/O errors.
#[derive(Clone, Eq, PartialEq, Debug, Fail)]
pub enum ErrorKind {
#[derive(Clone, Eq, PartialEq, Debug, thiserror::Error)]
pub enum Error {
/// LibTX Error
#[fail(display = "LibTx Error")]
LibTX(libtx::ErrorKind),
#[error("LibTx Error")]
LibTX(#[from] libtx::Error),
/// Impls error
#[fail(display = "Impls Error")]
Impls(impls::ErrorKind),
#[error("Impls Error")]
Impls(#[from] impls::Error),
/// LibWallet Error
#[fail(display = "LibWallet Error: {}", _1)]
LibWallet(libwallet::ErrorKind, String),
#[error("LibWallet Error: {0}")]
LibWallet(#[from] libwallet::Error),
/// Keychain error
#[fail(display = "Keychain error")]
Keychain(keychain::Error),
#[error("Keychain error")]
Keychain(#[from] keychain::Error),
/// Transaction Error
#[fail(display = "Transaction error")]
Transaction(transaction::Error),
#[error("Transaction error")]
Transaction(#[from] transaction::Error),
/// Secp Error
#[fail(display = "Secp error")]
#[error("Secp error")]
Secp,
/// Filewallet error
#[fail(display = "Wallet data error: {}", _0)]
#[error("Wallet data error: {0}")]
FileWallet(&'static str),
/// Error when formatting json
#[fail(display = "IO error")]
#[error("IO error")]
IO,
/// Error when formatting json
#[fail(display = "Serde JSON error")]
#[error("Serde JSON error")]
Format,
/// Error when contacting a node through its API
#[fail(display = "Node API error")]
Node(api::ErrorKind),
#[error("Node API error")]
Node(#[from] api::Error),
/// Error originating from hyper.
#[fail(display = "Hyper error")]
#[error("Hyper error")]
Hyper,
/// Error originating from hyper uri parsing.
#[fail(display = "Uri parsing error")]
#[error("Uri parsing error")]
Uri,
/// Attempt to use duplicate transaction id in separate transactions
#[fail(display = "Duplicate transaction ID error")]
#[error("Duplicate transaction ID error")]
DuplicateTransactionId,
/// Wallet seed already exists
#[fail(display = "Wallet seed file exists: {}", _0)]
#[error("Wallet seed file exists: {0}")]
WalletSeedExists(String),
/// Wallet seed doesn't exist
#[fail(display = "Wallet seed doesn't exist error")]
#[error("Wallet seed doesn't exist error")]
WalletSeedDoesntExist,
/// Enc/Decryption Error
#[fail(display = "Enc/Decryption error (check password?)")]
#[error("Enc/Decryption error (check password?)")]
Encryption,
/// BIP 39 word list
#[fail(display = "BIP39 Mnemonic (word list) Error")]
#[error("BIP39 Mnemonic (word list) Error")]
Mnemonic,
/// Command line argument error
#[fail(display = "{}", _0)]
#[error("{0}")]
ArgumentError(String),
/// Other
#[fail(display = "Listener Startup Error")]
#[error("Listener Startup Error")]
ListenerError,
/// Other
#[fail(display = "Generic error: {}", _0)]
#[error("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<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Error {
Error {
inner: Context::new(kind),
}
}
}
impl From<Context<ErrorKind>> for Error {
fn from(inner: Context<ErrorKind>) -> Error {
Error { inner: inner }
}
}
impl From<api::Error> for Error {
fn from(error: api::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Node(error.kind().clone())),
}
}
}
impl From<keychain::Error> for Error {
fn from(error: keychain::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Keychain(error)),
}
}
}
impl From<transaction::Error> for Error {
fn from(error: transaction::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Transaction(error)),
}
}
}
impl From<libwallet::Error> for Error {
fn from(error: libwallet::Error) -> Error {
Error {
inner: Context::new(ErrorKind::LibWallet(error.kind(), format!("{}", error))),
}
}
}
impl From<libtx::Error> for Error {
fn from(error: libtx::Error) -> Error {
Error {
inner: Context::new(ErrorKind::LibTX(error.kind())),
}
}
}
impl From<impls::Error> for Error {
fn from(error: impls::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Impls(error.kind())),
}
}
}
+1 -2
View File
@@ -21,7 +21,6 @@ extern crate prettytable;
extern crate log;
#[macro_use]
extern crate lazy_static;
use failure;
use grin_wallet_api as apiwallet;
use grin_wallet_config as config;
use grin_wallet_impls as impls;
@@ -36,4 +35,4 @@ pub mod controller;
pub mod display;
mod error;
pub use crate::error::{Error, ErrorKind};
pub use crate::error::Error;