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
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
63 changed files with 1066 additions and 1586 deletions

635
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -22,8 +22,7 @@ exclude = ["integration"]
[dependencies] [dependencies]
clap = { version = "2.33", features = ["yaml"] } clap = { version = "2.33", features = ["yaml"] }
rpassword = "4.0" rpassword = "4.0"
failure = "0.1" thiserror = "1"
failure_derive = "0.1"
prettytable-rs = "0.8" prettytable-rs = "0.8"
log = "0.4" log = "0.4"
linefeed = "0.6" linefeed = "0.6"

View file

@ -10,8 +10,6 @@ exclude = ["**/*.grin", "**/*.grin2"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
failure = "0.1"
failure_derive = "0.1"
log = "0.4" log = "0.4"
uuid = { version = "0.8", features = ["serde", "v4"] } uuid = { version = "0.8", features = ["serde", "v4"] }
serde = "1" serde = "1"

View file

@ -16,9 +16,8 @@
use crate::keychain::Keychain; use crate::keychain::Keychain;
use crate::libwallet::{ use crate::libwallet::{
self, BlockFees, CbData, ErrorKind, InitTxArgs, IssueInvoiceTxArgs, NodeClient, self, BlockFees, CbData, Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient, NodeVersionInfo,
NodeVersionInfo, Slate, SlateVersion, VersionInfo, VersionedCoinbase, VersionedSlate, Slate, SlateVersion, VersionInfo, VersionedCoinbase, VersionedSlate, WalletLCProvider,
WalletLCProvider,
}; };
use crate::{Foreign, ForeignCheckMiddlewareFn}; use crate::{Foreign, ForeignCheckMiddlewareFn};
use easy_jsonrpc_mw; use easy_jsonrpc_mw;
@ -62,7 +61,7 @@ pub trait ForeignRpc {
# ,false, 0, false, false); # ,false, 0, false, false);
``` ```
*/ */
fn check_version(&self) -> Result<VersionInfo, ErrorKind>; fn check_version(&self) -> Result<VersionInfo, Error>;
/** /**
Networked Legacy (non-secure token) version of [Foreign::build_coinbase](struct.Foreign.html#method.build_coinbase). Networked Legacy (non-secure token) version of [Foreign::build_coinbase](struct.Foreign.html#method.build_coinbase).
@ -111,7 +110,7 @@ pub trait ForeignRpc {
``` ```
*/ */
fn build_coinbase(&self, block_fees: &BlockFees) -> Result<VersionedCoinbase, ErrorKind>; fn build_coinbase(&self, block_fees: &BlockFees) -> Result<VersionedCoinbase, Error>;
/** /**
;Networked version of [Foreign::receive_tx](struct.Foreign.html#method.receive_tx). ;Networked version of [Foreign::receive_tx](struct.Foreign.html#method.receive_tx).
@ -190,7 +189,7 @@ pub trait ForeignRpc {
slate: VersionedSlate, slate: VersionedSlate,
dest_acct_name: Option<String>, dest_acct_name: Option<String>,
dest: Option<String>, dest: Option<String>,
) -> Result<VersionedSlate, ErrorKind>; ) -> Result<VersionedSlate, Error>;
/** /**
@ -284,7 +283,7 @@ pub trait ForeignRpc {
# ,false, 5, false, true); # ,false, 5, false, true);
``` ```
*/ */
fn finalize_tx(&self, slate: VersionedSlate) -> Result<VersionedSlate, ErrorKind>; fn finalize_tx(&self, slate: VersionedSlate) -> Result<VersionedSlate, Error>;
} }
impl<'a, L, C, K> ForeignRpc for Foreign<'a, L, C, K> impl<'a, L, C, K> ForeignRpc for Foreign<'a, L, C, K>
@ -293,12 +292,12 @@ where
C: NodeClient + 'a, C: NodeClient + 'a,
K: Keychain + 'a, K: Keychain + 'a,
{ {
fn check_version(&self) -> Result<VersionInfo, ErrorKind> { fn check_version(&self) -> Result<VersionInfo, Error> {
Foreign::check_version(self).map_err(|e| e.kind()) Foreign::check_version(self)
} }
fn build_coinbase(&self, block_fees: &BlockFees) -> Result<VersionedCoinbase, ErrorKind> { fn build_coinbase(&self, block_fees: &BlockFees) -> Result<VersionedCoinbase, Error> {
let cb: CbData = Foreign::build_coinbase(self, block_fees).map_err(|e| e.kind())?; let cb: CbData = Foreign::build_coinbase(self, block_fees)?;
Ok(VersionedCoinbase::into_version(cb, SlateVersion::V4)) Ok(VersionedCoinbase::into_version(cb, SlateVersion::V4))
} }
@ -307,7 +306,7 @@ where
in_slate: VersionedSlate, in_slate: VersionedSlate,
dest_acct_name: Option<String>, dest_acct_name: Option<String>,
dest: Option<String>, dest: Option<String>,
) -> Result<VersionedSlate, ErrorKind> { ) -> Result<VersionedSlate, Error> {
let version = in_slate.version(); let version = in_slate.version();
let slate_from = Slate::from(in_slate); let slate_from = Slate::from(in_slate);
let out_slate = Foreign::receive_tx( let out_slate = Foreign::receive_tx(
@ -315,16 +314,14 @@ where
&slate_from, &slate_from,
dest_acct_name.as_ref().map(String::as_str), dest_acct_name.as_ref().map(String::as_str),
dest, dest,
) )?;
.map_err(|e| e.kind())?; Ok(VersionedSlate::into_version(out_slate, version)?)
Ok(VersionedSlate::into_version(out_slate, version).map_err(|e| e.kind())?)
} }
fn finalize_tx(&self, in_slate: VersionedSlate) -> Result<VersionedSlate, ErrorKind> { fn finalize_tx(&self, in_slate: VersionedSlate) -> Result<VersionedSlate, Error> {
let version = in_slate.version(); let version = in_slate.version();
let out_slate = let out_slate = Foreign::finalize_tx(self, &Slate::from(in_slate), true)?;
Foreign::finalize_tx(self, &Slate::from(in_slate), true).map_err(|e| e.kind())?; Ok(VersionedSlate::into_version(out_slate, version)?)
Ok(VersionedSlate::into_version(out_slate, version).map_err(|e| e.kind())?)
} }
} }
@ -334,7 +331,7 @@ fn test_check_middleware(
_slate: Option<&Slate>, _slate: Option<&Slate>,
) -> Result<(), libwallet::Error> { ) -> Result<(), libwallet::Error> {
// TODO: Implement checks // TODO: Implement checks
// return Err(ErrorKind::GenericError("Test Rejection".into()))? // return Err(Error::GenericError("Test Rejection".into()))?
Ok(()) Ok(())
} }

View file

@ -29,7 +29,6 @@ use grin_wallet_util::grin_util as util;
extern crate grin_wallet_impls as impls; extern crate grin_wallet_impls as impls;
extern crate grin_wallet_libwallet as libwallet; extern crate grin_wallet_libwallet as libwallet;
extern crate failure_derive;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
extern crate serde_json; extern crate serde_json;

View file

@ -20,7 +20,7 @@ use crate::core::core::OutputFeatures;
use crate::core::global; use crate::core::global;
use crate::keychain::{Identifier, Keychain}; use crate::keychain::{Identifier, Keychain};
use crate::libwallet::{ use crate::libwallet::{
AcctPathMapping, Amount, BuiltOutput, ErrorKind, InitTxArgs, IssueInvoiceTxArgs, NodeClient, AcctPathMapping, Amount, BuiltOutput, Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient,
NodeHeightResult, OutputCommitMapping, PaymentProof, Slate, SlateVersion, Slatepack, NodeHeightResult, OutputCommitMapping, PaymentProof, Slate, SlateVersion, Slatepack,
SlatepackAddress, StatusMessage, TxLogEntry, VersionedSlate, ViewWallet, WalletInfo, SlatepackAddress, StatusMessage, TxLogEntry, VersionedSlate, ViewWallet, WalletInfo,
WalletLCProvider, WalletLCProvider,
@ -78,7 +78,7 @@ pub trait OwnerRpc {
# , 4, false, false, false, false); # , 4, false, false, false, false);
``` ```
*/ */
fn accounts(&self, token: Token) -> Result<Vec<AcctPathMapping>, ErrorKind>; fn accounts(&self, token: Token) -> Result<Vec<AcctPathMapping>, Error>;
/** /**
Networked version of [Owner::create_account_path](struct.Owner.html#method.create_account_path). Networked version of [Owner::create_account_path](struct.Owner.html#method.create_account_path).
@ -111,7 +111,7 @@ pub trait OwnerRpc {
# , 4, false, false, false, false); # , 4, false, false, false, false);
``` ```
*/ */
fn create_account_path(&self, token: Token, label: &String) -> Result<Identifier, ErrorKind>; fn create_account_path(&self, token: Token, label: &String) -> Result<Identifier, Error>;
/** /**
Networked version of [Owner::set_active_account](struct.Owner.html#method.set_active_account). Networked version of [Owner::set_active_account](struct.Owner.html#method.set_active_account).
@ -144,7 +144,7 @@ pub trait OwnerRpc {
# , 4, false, false, false, false); # , 4, false, false, false, false);
``` ```
*/ */
fn set_active_account(&self, token: Token, label: &String) -> Result<(), ErrorKind>; fn set_active_account(&self, token: Token, label: &String) -> Result<(), Error>;
/** /**
Networked version of [Owner::retrieve_outputs](struct.Owner.html#method.retrieve_outputs). Networked version of [Owner::retrieve_outputs](struct.Owner.html#method.retrieve_outputs).
@ -221,7 +221,7 @@ pub trait OwnerRpc {
include_spent: bool, include_spent: bool,
refresh_from_node: bool, refresh_from_node: bool,
tx_id: Option<u32>, tx_id: Option<u32>,
) -> Result<(bool, Vec<OutputCommitMapping>), ErrorKind>; ) -> Result<(bool, Vec<OutputCommitMapping>), Error>;
/** /**
Networked version of [Owner::retrieve_txs](struct.Owner.html#method.retrieve_txs). Networked version of [Owner::retrieve_txs](struct.Owner.html#method.retrieve_txs).
@ -307,7 +307,7 @@ pub trait OwnerRpc {
refresh_from_node: bool, refresh_from_node: bool,
tx_id: Option<u32>, tx_id: Option<u32>,
tx_slate_id: Option<Uuid>, tx_slate_id: Option<Uuid>,
) -> Result<(bool, Vec<TxLogEntry>), ErrorKind>; ) -> Result<(bool, Vec<TxLogEntry>), Error>;
/** /**
Networked version of [Owner::retrieve_summary_info](struct.Owner.html#method.retrieve_summary_info). Networked version of [Owner::retrieve_summary_info](struct.Owner.html#method.retrieve_summary_info).
@ -358,7 +358,7 @@ pub trait OwnerRpc {
token: Token, token: Token,
refresh_from_node: bool, refresh_from_node: bool,
minimum_confirmations: u64, minimum_confirmations: u64,
) -> Result<(bool, WalletInfo), ErrorKind>; ) -> Result<(bool, WalletInfo), Error>;
/** /**
;Networked version of [Owner::init_send_tx](struct.Owner.html#method.init_send_tx). ;Networked version of [Owner::init_send_tx](struct.Owner.html#method.init_send_tx).
@ -417,7 +417,7 @@ pub trait OwnerRpc {
``` ```
*/ */
fn init_send_tx(&self, token: Token, args: InitTxArgs) -> Result<VersionedSlate, ErrorKind>; fn init_send_tx(&self, token: Token, args: InitTxArgs) -> Result<VersionedSlate, Error>;
/** /**
;Networked version of [Owner::issue_invoice_tx](struct.Owner.html#method.issue_invoice_tx). ;Networked version of [Owner::issue_invoice_tx](struct.Owner.html#method.issue_invoice_tx).
@ -468,7 +468,7 @@ pub trait OwnerRpc {
&self, &self,
token: Token, token: Token,
args: IssueInvoiceTxArgs, args: IssueInvoiceTxArgs,
) -> Result<VersionedSlate, ErrorKind>; ) -> Result<VersionedSlate, Error>;
/** /**
;Networked version of [Owner::process_invoice_tx](struct.Owner.html#method.process_invoice_tx). ;Networked version of [Owner::process_invoice_tx](struct.Owner.html#method.process_invoice_tx).
@ -552,7 +552,7 @@ pub trait OwnerRpc {
token: Token, token: Token,
slate: VersionedSlate, slate: VersionedSlate,
args: InitTxArgs, args: InitTxArgs,
) -> Result<VersionedSlate, ErrorKind>; ) -> Result<VersionedSlate, Error>;
/** /**
Networked version of [Owner::tx_lock_outputs](struct.Owner.html#method.tx_lock_outputs). Networked version of [Owner::tx_lock_outputs](struct.Owner.html#method.tx_lock_outputs).
@ -597,7 +597,7 @@ pub trait OwnerRpc {
``` ```
*/ */
fn tx_lock_outputs(&self, token: Token, slate: VersionedSlate) -> Result<(), ErrorKind>; fn tx_lock_outputs(&self, token: Token, slate: VersionedSlate) -> Result<(), Error>;
/** /**
Networked version of [Owner::finalize_tx](struct.Owner.html#method.finalize_tx). Networked version of [Owner::finalize_tx](struct.Owner.html#method.finalize_tx).
@ -683,8 +683,7 @@ pub trait OwnerRpc {
# , 5, true, true, false, false); # , 5, true, true, false, false);
``` ```
*/ */
fn finalize_tx(&self, token: Token, slate: VersionedSlate) fn finalize_tx(&self, token: Token, slate: VersionedSlate) -> Result<VersionedSlate, Error>;
-> Result<VersionedSlate, ErrorKind>;
/** /**
Networked version of [Owner::post_tx](struct.Owner.html#method.post_tx). Networked version of [Owner::post_tx](struct.Owner.html#method.post_tx).
@ -753,7 +752,7 @@ pub trait OwnerRpc {
``` ```
*/ */
fn post_tx(&self, token: Token, slate: VersionedSlate, fluff: bool) -> Result<(), ErrorKind>; fn post_tx(&self, token: Token, slate: VersionedSlate, fluff: bool) -> Result<(), Error>;
/** /**
Networked version of [Owner::cancel_tx](struct.Owner.html#method.cancel_tx). Networked version of [Owner::cancel_tx](struct.Owner.html#method.cancel_tx).
@ -791,7 +790,7 @@ pub trait OwnerRpc {
token: Token, token: Token,
tx_id: Option<u32>, tx_id: Option<u32>,
tx_slate_id: Option<Uuid>, tx_slate_id: Option<Uuid>,
) -> Result<(), ErrorKind>; ) -> Result<(), Error>;
/** /**
Networked version of [Owner::get_stored_tx](struct.Owner.html#method.get_stored_tx). Networked version of [Owner::get_stored_tx](struct.Owner.html#method.get_stored_tx).
@ -840,7 +839,7 @@ pub trait OwnerRpc {
token: Token, token: Token,
id: Option<u32>, id: Option<u32>,
slate_id: Option<Uuid>, slate_id: Option<Uuid>,
) -> Result<Option<VersionedSlate>, ErrorKind>; ) -> Result<Option<VersionedSlate>, Error>;
/** /**
Networked version of [Owner::get_rewind_hash](struct.Owner.html#method.get_rewind_hash). Networked version of [Owner::get_rewind_hash](struct.Owner.html#method.get_rewind_hash).
@ -869,7 +868,7 @@ pub trait OwnerRpc {
# , 0, false, false, false, false); # , 0, false, false, false, false);
``` ```
*/ */
fn get_rewind_hash(&self, token: Token) -> Result<String, ErrorKind>; fn get_rewind_hash(&self, token: Token) -> Result<String, Error>;
/** /**
Networked version of [Owner::scan_rewind_hash](struct.Owner.html#method.scan_rewind_hash). Networked version of [Owner::scan_rewind_hash](struct.Owner.html#method.scan_rewind_hash).
@ -949,7 +948,7 @@ pub trait OwnerRpc {
&self, &self,
rewind_hash: String, rewind_hash: String,
start_height: Option<u64>, start_height: Option<u64>,
) -> Result<ViewWallet, ErrorKind>; ) -> Result<ViewWallet, Error>;
/** /**
Networked version of [Owner::scan](struct.Owner.html#method.scan). Networked version of [Owner::scan](struct.Owner.html#method.scan).
@ -987,7 +986,7 @@ pub trait OwnerRpc {
token: Token, token: Token,
start_height: Option<u64>, start_height: Option<u64>,
delete_unconfirmed: bool, delete_unconfirmed: bool,
) -> Result<(), ErrorKind>; ) -> Result<(), Error>;
/** /**
Networked version of [Owner::node_height](struct.Owner.html#method.node_height). Networked version of [Owner::node_height](struct.Owner.html#method.node_height).
@ -1021,7 +1020,7 @@ pub trait OwnerRpc {
# , 5, false, false, false, false); # , 5, false, false, false, false);
``` ```
*/ */
fn node_height(&self, token: Token) -> Result<NodeHeightResult, ErrorKind>; fn node_height(&self, token: Token) -> Result<NodeHeightResult, Error>;
/** /**
Initializes the secure JSON-RPC API. This function must be called and a shared key Initializes the secure JSON-RPC API. This function must be called and a shared key
@ -1075,7 +1074,7 @@ pub trait OwnerRpc {
*/ */
fn init_secure_api(&self, ecdh_pubkey: ECDHPubkey) -> Result<ECDHPubkey, ErrorKind>; fn init_secure_api(&self, ecdh_pubkey: ECDHPubkey) -> Result<ECDHPubkey, Error>;
/** /**
Networked version of [Owner::get_top_level_directory](struct.Owner.html#method.get_top_level_directory). Networked version of [Owner::get_top_level_directory](struct.Owner.html#method.get_top_level_directory).
@ -1105,7 +1104,7 @@ pub trait OwnerRpc {
``` ```
*/ */
fn get_top_level_directory(&self) -> Result<String, ErrorKind>; fn get_top_level_directory(&self) -> Result<String, Error>;
/** /**
Networked version of [Owner::set_top_level_directory](struct.Owner.html#method.set_top_level_directory). Networked version of [Owner::set_top_level_directory](struct.Owner.html#method.set_top_level_directory).
@ -1135,7 +1134,7 @@ pub trait OwnerRpc {
``` ```
*/ */
fn set_top_level_directory(&self, dir: String) -> Result<(), ErrorKind>; fn set_top_level_directory(&self, dir: String) -> Result<(), Error>;
/** /**
Networked version of [Owner::create_config](struct.Owner.html#method.create_config). Networked version of [Owner::create_config](struct.Owner.html#method.create_config).
@ -1205,7 +1204,7 @@ pub trait OwnerRpc {
wallet_config: Option<WalletConfig>, wallet_config: Option<WalletConfig>,
logging_config: Option<LoggingConfig>, logging_config: Option<LoggingConfig>,
tor_config: Option<TorConfig>, tor_config: Option<TorConfig>,
) -> Result<(), ErrorKind>; ) -> Result<(), Error>;
/** /**
Networked version of [Owner::create_wallet](struct.Owner.html#method.create_wallet). Networked version of [Owner::create_wallet](struct.Owner.html#method.create_wallet).
@ -1244,7 +1243,7 @@ pub trait OwnerRpc {
mnemonic: Option<String>, mnemonic: Option<String>,
mnemonic_length: u32, mnemonic_length: u32,
password: String, password: String,
) -> Result<(), ErrorKind>; ) -> Result<(), Error>;
/** /**
Networked version of [Owner::open_wallet](struct.Owner.html#method.open_wallet). Networked version of [Owner::open_wallet](struct.Owner.html#method.open_wallet).
@ -1275,7 +1274,7 @@ pub trait OwnerRpc {
``` ```
*/ */
fn open_wallet(&self, name: Option<String>, password: String) -> Result<Token, ErrorKind>; fn open_wallet(&self, name: Option<String>, password: String) -> Result<Token, Error>;
/** /**
Networked version of [Owner::close_wallet](struct.Owner.html#method.close_wallet). Networked version of [Owner::close_wallet](struct.Owner.html#method.close_wallet).
@ -1305,7 +1304,7 @@ pub trait OwnerRpc {
``` ```
*/ */
fn close_wallet(&self, name: Option<String>) -> Result<(), ErrorKind>; fn close_wallet(&self, name: Option<String>) -> Result<(), Error>;
/** /**
Networked version of [Owner::get_mnemonic](struct.Owner.html#method.get_mnemonic). Networked version of [Owner::get_mnemonic](struct.Owner.html#method.get_mnemonic).
@ -1336,7 +1335,7 @@ pub trait OwnerRpc {
``` ```
*/ */
fn get_mnemonic(&self, name: Option<String>, password: String) -> Result<String, ErrorKind>; fn get_mnemonic(&self, name: Option<String>, password: String) -> Result<String, Error>;
/** /**
Networked version of [Owner::change_password](struct.Owner.html#method.change_password). Networked version of [Owner::change_password](struct.Owner.html#method.change_password).
@ -1367,12 +1366,7 @@ pub trait OwnerRpc {
# , 0, false, false, false, false); # , 0, false, false, false, false);
``` ```
*/ */
fn change_password( fn change_password(&self, name: Option<String>, old: String, new: String) -> Result<(), Error>;
&self,
name: Option<String>,
old: String,
new: String,
) -> Result<(), ErrorKind>;
/** /**
Networked version of [Owner::delete_wallet](struct.Owner.html#method.delete_wallet). Networked version of [Owner::delete_wallet](struct.Owner.html#method.delete_wallet).
@ -1401,7 +1395,7 @@ pub trait OwnerRpc {
# , 0, false, false, false, false); # , 0, false, false, false, false);
``` ```
*/ */
fn delete_wallet(&self, name: Option<String>) -> Result<(), ErrorKind>; fn delete_wallet(&self, name: Option<String>) -> Result<(), Error>;
/** /**
Networked version of [Owner::start_updated](struct.Owner.html#method.start_updater). Networked version of [Owner::start_updated](struct.Owner.html#method.start_updater).
@ -1432,7 +1426,7 @@ pub trait OwnerRpc {
``` ```
*/ */
fn start_updater(&self, token: Token, frequency: u32) -> Result<(), ErrorKind>; fn start_updater(&self, token: Token, frequency: u32) -> Result<(), Error>;
/** /**
Networked version of [Owner::stop_updater](struct.Owner.html#method.stop_updater). Networked version of [Owner::stop_updater](struct.Owner.html#method.stop_updater).
@ -1459,7 +1453,7 @@ pub trait OwnerRpc {
# , 0, false, false, false, false); # , 0, false, false, false, false);
``` ```
*/ */
fn stop_updater(&self) -> Result<(), ErrorKind>; fn stop_updater(&self) -> Result<(), Error>;
/** /**
Networked version of [Owner::get_updater_messages](struct.Owner.html#method.get_updater_messages). Networked version of [Owner::get_updater_messages](struct.Owner.html#method.get_updater_messages).
@ -1489,7 +1483,7 @@ pub trait OwnerRpc {
``` ```
*/ */
fn get_updater_messages(&self, count: u32) -> Result<Vec<StatusMessage>, ErrorKind>; fn get_updater_messages(&self, count: u32) -> Result<Vec<StatusMessage>, Error>;
/** /**
Networked version of [Owner::get_slatepack_address](struct.Owner.html#method.get_slatepack_address). Networked version of [Owner::get_slatepack_address](struct.Owner.html#method.get_slatepack_address).
@ -1524,7 +1518,7 @@ pub trait OwnerRpc {
&self, &self,
token: Token, token: Token,
derivation_index: u32, derivation_index: u32,
) -> Result<SlatepackAddress, ErrorKind>; ) -> Result<SlatepackAddress, Error>;
/** /**
Networked version of [Owner::get_slatepack_secret_key](struct.Owner.html#method.get_slatepack_secret_key). Networked version of [Owner::get_slatepack_secret_key](struct.Owner.html#method.get_slatepack_secret_key).
@ -1559,7 +1553,7 @@ pub trait OwnerRpc {
&self, &self,
token: Token, token: Token,
derivation_index: u32, derivation_index: u32,
) -> Result<Ed25519SecretKey, ErrorKind>; ) -> Result<Ed25519SecretKey, Error>;
/** /**
Networked version of [Owner::create_slatepack_message](struct.Owner.html#method.create_slatepack_message). Networked version of [Owner::create_slatepack_message](struct.Owner.html#method.create_slatepack_message).
@ -1611,7 +1605,7 @@ pub trait OwnerRpc {
slate: VersionedSlate, slate: VersionedSlate,
sender_index: Option<u32>, sender_index: Option<u32>,
recipients: Vec<SlatepackAddress>, recipients: Vec<SlatepackAddress>,
) -> Result<String, ErrorKind>; ) -> Result<String, Error>;
/** /**
Networked version of [Owner::slate_from_slatepack_message](struct.Owner.html#method.slate_from_slatepack_message). Networked version of [Owner::slate_from_slatepack_message](struct.Owner.html#method.slate_from_slatepack_message).
@ -1665,7 +1659,7 @@ pub trait OwnerRpc {
token: Token, token: Token,
message: String, message: String,
secret_indices: Vec<u32>, secret_indices: Vec<u32>,
) -> Result<VersionedSlate, ErrorKind>; ) -> Result<VersionedSlate, Error>;
/** /**
Networked version of [Owner::decode_slatepack_message](struct.Owner.html#method.decode_slatepack_message). Networked version of [Owner::decode_slatepack_message](struct.Owner.html#method.decode_slatepack_message).
@ -1707,7 +1701,7 @@ pub trait OwnerRpc {
token: Token, token: Token,
message: String, message: String,
secret_indices: Vec<u32>, secret_indices: Vec<u32>,
) -> Result<Slatepack, ErrorKind>; ) -> Result<Slatepack, Error>;
/** /**
Networked version of [Owner::retrieve_payment_proof](struct.Owner.html#method.retrieve_payment_proof). Networked version of [Owner::retrieve_payment_proof](struct.Owner.html#method.retrieve_payment_proof).
@ -1753,7 +1747,7 @@ pub trait OwnerRpc {
refresh_from_node: bool, refresh_from_node: bool,
tx_id: Option<u32>, tx_id: Option<u32>,
tx_slate_id: Option<Uuid>, tx_slate_id: Option<Uuid>,
) -> Result<PaymentProof, ErrorKind>; ) -> Result<PaymentProof, Error>;
/** /**
Networked version of [Owner::verify_payment_proof](struct.Owner.html#method.verify_payment_proof). Networked version of [Owner::verify_payment_proof](struct.Owner.html#method.verify_payment_proof).
@ -1798,7 +1792,7 @@ pub trait OwnerRpc {
&self, &self,
token: Token, token: Token,
proof: PaymentProof, proof: PaymentProof,
) -> Result<(bool, bool), ErrorKind>; ) -> Result<(bool, bool), Error>;
/** /**
Networked version of [Owner::set_tor_config](struct.Owner.html#method.set_tor_config). Networked version of [Owner::set_tor_config](struct.Owner.html#method.set_tor_config).
@ -1831,7 +1825,7 @@ pub trait OwnerRpc {
# , 0, false, false, false, false); # , 0, false, false, false, false);
``` ```
*/ */
fn set_tor_config(&self, tor_config: Option<TorConfig>) -> Result<(), ErrorKind>; fn set_tor_config(&self, tor_config: Option<TorConfig>) -> Result<(), Error>;
/** /**
Networked version of [Owner::build_output](struct.Owner.html#method.build_output). Networked version of [Owner::build_output](struct.Owner.html#method.build_output).
@ -1875,7 +1869,7 @@ pub trait OwnerRpc {
token: Token, token: Token,
features: OutputFeatures, features: OutputFeatures,
amount: Amount, amount: Amount,
) -> Result<BuiltOutput, ErrorKind>; ) -> Result<BuiltOutput, Error>;
} }
impl<L, C, K> OwnerRpc for Owner<L, C, K> impl<L, C, K> OwnerRpc for Owner<L, C, K>
@ -1884,18 +1878,16 @@ where
C: NodeClient + 'static, C: NodeClient + 'static,
K: Keychain + 'static, K: Keychain + 'static,
{ {
fn accounts(&self, token: Token) -> Result<Vec<AcctPathMapping>, ErrorKind> { fn accounts(&self, token: Token) -> Result<Vec<AcctPathMapping>, Error> {
Owner::accounts(self, (&token.keychain_mask).as_ref()).map_err(|e| e.kind()) Owner::accounts(self, (&token.keychain_mask).as_ref())
} }
fn create_account_path(&self, token: Token, label: &String) -> Result<Identifier, ErrorKind> { fn create_account_path(&self, token: Token, label: &String) -> Result<Identifier, Error> {
Owner::create_account_path(self, (&token.keychain_mask).as_ref(), label) Owner::create_account_path(self, (&token.keychain_mask).as_ref(), label)
.map_err(|e| e.kind())
} }
fn set_active_account(&self, token: Token, label: &String) -> Result<(), ErrorKind> { fn set_active_account(&self, token: Token, label: &String) -> Result<(), Error> {
Owner::set_active_account(self, (&token.keychain_mask).as_ref(), label) Owner::set_active_account(self, (&token.keychain_mask).as_ref(), label)
.map_err(|e| e.kind())
} }
fn retrieve_outputs( fn retrieve_outputs(
@ -1904,7 +1896,7 @@ where
include_spent: bool, include_spent: bool,
refresh_from_node: bool, refresh_from_node: bool,
tx_id: Option<u32>, tx_id: Option<u32>,
) -> Result<(bool, Vec<OutputCommitMapping>), ErrorKind> { ) -> Result<(bool, Vec<OutputCommitMapping>), Error> {
Owner::retrieve_outputs( Owner::retrieve_outputs(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
@ -1912,7 +1904,6 @@ where
refresh_from_node, refresh_from_node,
tx_id, tx_id,
) )
.map_err(|e| e.kind())
} }
fn retrieve_txs( fn retrieve_txs(
@ -1921,7 +1912,7 @@ where
refresh_from_node: bool, refresh_from_node: bool,
tx_id: Option<u32>, tx_id: Option<u32>,
tx_slate_id: Option<Uuid>, tx_slate_id: Option<Uuid>,
) -> Result<(bool, Vec<TxLogEntry>), ErrorKind> { ) -> Result<(bool, Vec<TxLogEntry>), Error> {
Owner::retrieve_txs( Owner::retrieve_txs(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
@ -1929,7 +1920,6 @@ where
tx_id, tx_id,
tx_slate_id, tx_slate_id,
) )
.map_err(|e| e.kind())
} }
fn retrieve_summary_info( fn retrieve_summary_info(
@ -1937,32 +1927,29 @@ where
token: Token, token: Token,
refresh_from_node: bool, refresh_from_node: bool,
minimum_confirmations: u64, minimum_confirmations: u64,
) -> Result<(bool, WalletInfo), ErrorKind> { ) -> Result<(bool, WalletInfo), Error> {
Owner::retrieve_summary_info( Owner::retrieve_summary_info(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
refresh_from_node, refresh_from_node,
minimum_confirmations, minimum_confirmations,
) )
.map_err(|e| e.kind())
} }
fn init_send_tx(&self, token: Token, args: InitTxArgs) -> Result<VersionedSlate, ErrorKind> { fn init_send_tx(&self, token: Token, args: InitTxArgs) -> Result<VersionedSlate, Error> {
let slate = Owner::init_send_tx(self, (&token.keychain_mask).as_ref(), args) let slate = Owner::init_send_tx(self, (&token.keychain_mask).as_ref(), args)?;
.map_err(|e| e.kind())?;
let version = SlateVersion::V4; let version = SlateVersion::V4;
Ok(VersionedSlate::into_version(slate, version).map_err(|e| e.kind())?) VersionedSlate::into_version(slate, version)
} }
fn issue_invoice_tx( fn issue_invoice_tx(
&self, &self,
token: Token, token: Token,
args: IssueInvoiceTxArgs, args: IssueInvoiceTxArgs,
) -> Result<VersionedSlate, ErrorKind> { ) -> Result<VersionedSlate, Error> {
let slate = Owner::issue_invoice_tx(self, (&token.keychain_mask).as_ref(), args) let slate = Owner::issue_invoice_tx(self, (&token.keychain_mask).as_ref(), args)?;
.map_err(|e| e.kind())?;
let version = SlateVersion::V4; let version = SlateVersion::V4;
Ok(VersionedSlate::into_version(slate, version).map_err(|e| e.kind())?) VersionedSlate::into_version(slate, version)
} }
fn process_invoice_tx( fn process_invoice_tx(
@ -1970,40 +1957,33 @@ where
token: Token, token: Token,
in_slate: VersionedSlate, in_slate: VersionedSlate,
args: InitTxArgs, args: InitTxArgs,
) -> Result<VersionedSlate, ErrorKind> { ) -> Result<VersionedSlate, Error> {
let out_slate = Owner::process_invoice_tx( let out_slate = Owner::process_invoice_tx(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
&Slate::from(in_slate), &Slate::from(in_slate),
args, args,
) )?;
.map_err(|e| e.kind())?;
let version = SlateVersion::V4; let version = SlateVersion::V4;
Ok(VersionedSlate::into_version(out_slate, version).map_err(|e| e.kind())?) VersionedSlate::into_version(out_slate, version)
} }
fn finalize_tx( fn finalize_tx(&self, token: Token, in_slate: VersionedSlate) -> Result<VersionedSlate, Error> {
&self,
token: Token,
in_slate: VersionedSlate,
) -> Result<VersionedSlate, ErrorKind> {
let out_slate = Owner::finalize_tx( let out_slate = Owner::finalize_tx(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
&Slate::from(in_slate), &Slate::from(in_slate),
) )?;
.map_err(|e| e.kind())?;
let version = SlateVersion::V4; let version = SlateVersion::V4;
Ok(VersionedSlate::into_version(out_slate, version).map_err(|e| e.kind())?) VersionedSlate::into_version(out_slate, version)
} }
fn tx_lock_outputs(&self, token: Token, in_slate: VersionedSlate) -> Result<(), ErrorKind> { fn tx_lock_outputs(&self, token: Token, in_slate: VersionedSlate) -> Result<(), Error> {
Owner::tx_lock_outputs( Owner::tx_lock_outputs(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
&Slate::from(in_slate), &Slate::from(in_slate),
) )
.map_err(|e| e.kind())
} }
fn cancel_tx( fn cancel_tx(
@ -2011,9 +1991,8 @@ where
token: Token, token: Token,
tx_id: Option<u32>, tx_id: Option<u32>,
tx_slate_id: Option<Uuid>, tx_slate_id: Option<Uuid>,
) -> Result<(), ErrorKind> { ) -> Result<(), Error> {
Owner::cancel_tx(self, (&token.keychain_mask).as_ref(), tx_id, tx_slate_id) Owner::cancel_tx(self, (&token.keychain_mask).as_ref(), tx_id, tx_slate_id)
.map_err(|e| e.kind())
} }
fn get_stored_tx( fn get_stored_tx(
@ -2021,45 +2000,41 @@ where
token: Token, token: Token,
id: Option<u32>, id: Option<u32>,
slate_id: Option<Uuid>, slate_id: Option<Uuid>,
) -> Result<Option<VersionedSlate>, ErrorKind> { ) -> Result<Option<VersionedSlate>, Error> {
let out_slate = Owner::get_stored_tx( let out_slate = Owner::get_stored_tx(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
id, id,
(&slate_id).as_ref(), (&slate_id).as_ref(),
) )?;
.map_err(|e| e.kind())?;
match out_slate { match out_slate {
Some(s) => { Some(s) => {
let version = SlateVersion::V4; let version = SlateVersion::V4;
Ok(Some( Ok(Some(VersionedSlate::into_version(s, version)?))
VersionedSlate::into_version(s, version).map_err(|e| e.kind())?,
))
} }
None => Ok(None), None => Ok(None),
} }
} }
fn post_tx(&self, token: Token, slate: VersionedSlate, fluff: bool) -> Result<(), ErrorKind> { fn post_tx(&self, token: Token, slate: VersionedSlate, fluff: bool) -> Result<(), Error> {
Owner::post_tx( Owner::post_tx(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
&Slate::from(slate), &Slate::from(slate),
fluff, fluff,
) )
.map_err(|e| e.kind())
} }
fn get_rewind_hash(&self, token: Token) -> Result<String, ErrorKind> { fn get_rewind_hash(&self, token: Token) -> Result<String, Error> {
Owner::get_rewind_hash(self, (&token.keychain_mask).as_ref()).map_err(|e| e.kind()) Owner::get_rewind_hash(self, (&token.keychain_mask).as_ref())
} }
fn scan_rewind_hash( fn scan_rewind_hash(
&self, &self,
rewind_hash: String, rewind_hash: String,
start_height: Option<u64>, start_height: Option<u64>,
) -> Result<ViewWallet, ErrorKind> { ) -> Result<ViewWallet, Error> {
Owner::scan_rewind_hash(self, rewind_hash, start_height).map_err(|e| e.kind()) Owner::scan_rewind_hash(self, rewind_hash, start_height)
} }
fn scan( fn scan(
@ -2067,21 +2042,20 @@ where
token: Token, token: Token,
start_height: Option<u64>, start_height: Option<u64>,
delete_unconfirmed: bool, delete_unconfirmed: bool,
) -> Result<(), ErrorKind> { ) -> Result<(), Error> {
Owner::scan( Owner::scan(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
start_height, start_height,
delete_unconfirmed, delete_unconfirmed,
) )
.map_err(|e| e.kind())
} }
fn node_height(&self, token: Token) -> Result<NodeHeightResult, ErrorKind> { fn node_height(&self, token: Token) -> Result<NodeHeightResult, Error> {
Owner::node_height(self, (&token.keychain_mask).as_ref()).map_err(|e| e.kind()) Owner::node_height(self, (&token.keychain_mask).as_ref())
} }
fn init_secure_api(&self, ecdh_pubkey: ECDHPubkey) -> Result<ECDHPubkey, ErrorKind> { fn init_secure_api(&self, ecdh_pubkey: ECDHPubkey) -> Result<ECDHPubkey, Error> {
let secp_inst = static_secp_instance(); let secp_inst = static_secp_instance();
let secp = secp_inst.lock(); let secp = secp_inst.lock();
let sec_key = SecretKey::new(&secp, &mut thread_rng()); let sec_key = SecretKey::new(&secp, &mut thread_rng());
@ -2089,28 +2063,28 @@ where
let mut shared_pubkey = ecdh_pubkey.ecdh_pubkey; let mut shared_pubkey = ecdh_pubkey.ecdh_pubkey;
shared_pubkey shared_pubkey
.mul_assign(&secp, &sec_key) .mul_assign(&secp, &sec_key)
.map_err(ErrorKind::Secp)?; .map_err(Error::Secp)?;
let x_coord = shared_pubkey.serialize_vec(&secp, true); let x_coord = shared_pubkey.serialize_vec(&secp, true);
let shared_key = SecretKey::from_slice(&secp, &x_coord[1..]).map_err(ErrorKind::Secp)?; let shared_key = SecretKey::from_slice(&secp, &x_coord[1..]).map_err(Error::Secp)?;
{ {
let mut s = self.shared_key.lock(); let mut s = self.shared_key.lock();
*s = Some(shared_key); *s = Some(shared_key);
} }
let pub_key = PublicKey::from_secret_key(&secp, &sec_key).map_err(ErrorKind::Secp)?; let pub_key = PublicKey::from_secret_key(&secp, &sec_key).map_err(Error::Secp)?;
Ok(ECDHPubkey { Ok(ECDHPubkey {
ecdh_pubkey: pub_key, ecdh_pubkey: pub_key,
}) })
} }
fn get_top_level_directory(&self) -> Result<String, ErrorKind> { fn get_top_level_directory(&self) -> Result<String, Error> {
Owner::get_top_level_directory(self).map_err(|e| e.kind()) Owner::get_top_level_directory(self)
} }
fn set_top_level_directory(&self, dir: String) -> Result<(), ErrorKind> { fn set_top_level_directory(&self, dir: String) -> Result<(), Error> {
Owner::set_top_level_directory(self, &dir).map_err(|e| e.kind()) Owner::set_top_level_directory(self, &dir)
} }
fn create_config( fn create_config(
@ -2119,9 +2093,8 @@ where
wallet_config: Option<WalletConfig>, wallet_config: Option<WalletConfig>,
logging_config: Option<LoggingConfig>, logging_config: Option<LoggingConfig>,
tor_config: Option<TorConfig>, tor_config: Option<TorConfig>,
) -> Result<(), ErrorKind> { ) -> Result<(), Error> {
Owner::create_config(self, &chain_type, wallet_config, logging_config, tor_config) Owner::create_config(self, &chain_type, wallet_config, logging_config, tor_config)
.map_err(|e| e.kind())
} }
fn create_wallet( fn create_wallet(
@ -2130,90 +2103,78 @@ where
mnemonic: Option<String>, mnemonic: Option<String>,
mnemonic_length: u32, mnemonic_length: u32,
password: String, password: String,
) -> Result<(), ErrorKind> { ) -> Result<(), Error> {
let n = name.as_ref().map(|s| s.as_str()); let n = name.as_ref().map(|s| s.as_str());
let m = match mnemonic { let m = match mnemonic {
Some(s) => Some(ZeroingString::from(s)), Some(s) => Some(ZeroingString::from(s)),
None => None, None => None,
}; };
Owner::create_wallet(self, n, m, mnemonic_length, ZeroingString::from(password)) Owner::create_wallet(self, n, m, mnemonic_length, ZeroingString::from(password))
.map_err(|e| e.kind())
} }
fn open_wallet(&self, name: Option<String>, password: String) -> Result<Token, ErrorKind> { fn open_wallet(&self, name: Option<String>, password: String) -> Result<Token, Error> {
let n = name.as_ref().map(|s| s.as_str()); let n = name.as_ref().map(|s| s.as_str());
let sec_key = Owner::open_wallet(self, n, ZeroingString::from(password), true) let sec_key = Owner::open_wallet(self, n, ZeroingString::from(password), true)?;
.map_err(|e| e.kind())?;
Ok(Token { Ok(Token {
keychain_mask: sec_key, keychain_mask: sec_key,
}) })
} }
fn close_wallet(&self, name: Option<String>) -> Result<(), ErrorKind> { fn close_wallet(&self, name: Option<String>) -> Result<(), Error> {
let n = name.as_ref().map(|s| s.as_str()); let n = name.as_ref().map(|s| s.as_str());
Owner::close_wallet(self, n).map_err(|e| e.kind()) Owner::close_wallet(self, n)
} }
fn get_mnemonic(&self, name: Option<String>, password: String) -> Result<String, ErrorKind> { fn get_mnemonic(&self, name: Option<String>, password: String) -> Result<String, Error> {
let n = name.as_ref().map(|s| s.as_str()); let n = name.as_ref().map(|s| s.as_str());
let res = let res = Owner::get_mnemonic(self, n, ZeroingString::from(password))?;
Owner::get_mnemonic(self, n, ZeroingString::from(password)).map_err(|e| e.kind())?;
Ok((&*res).to_string()) Ok((&*res).to_string())
} }
fn change_password( fn change_password(&self, name: Option<String>, old: String, new: String) -> Result<(), Error> {
&self,
name: Option<String>,
old: String,
new: String,
) -> Result<(), ErrorKind> {
let n = name.as_ref().map(|s| s.as_str()); let n = name.as_ref().map(|s| s.as_str());
Owner::change_password(self, n, ZeroingString::from(old), ZeroingString::from(new)) Owner::change_password(self, n, ZeroingString::from(old), ZeroingString::from(new))
.map_err(|e| e.kind())
} }
fn delete_wallet(&self, name: Option<String>) -> Result<(), ErrorKind> { fn delete_wallet(&self, name: Option<String>) -> Result<(), Error> {
let n = name.as_ref().map(|s| s.as_str()); let n = name.as_ref().map(|s| s.as_str());
Owner::delete_wallet(self, n).map_err(|e| e.kind()) Owner::delete_wallet(self, n)
} }
fn start_updater(&self, token: Token, frequency: u32) -> Result<(), ErrorKind> { fn start_updater(&self, token: Token, frequency: u32) -> Result<(), Error> {
Owner::start_updater( Owner::start_updater(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
Duration::from_millis(frequency as u64), Duration::from_millis(frequency as u64),
) )
.map_err(|e| e.kind())
} }
fn stop_updater(&self) -> Result<(), ErrorKind> { fn stop_updater(&self) -> Result<(), Error> {
Owner::stop_updater(self).map_err(|e| e.kind()) Owner::stop_updater(self)
} }
fn get_updater_messages(&self, count: u32) -> Result<Vec<StatusMessage>, ErrorKind> { fn get_updater_messages(&self, count: u32) -> Result<Vec<StatusMessage>, Error> {
Owner::get_updater_messages(self, count as usize).map_err(|e| e.kind()) Owner::get_updater_messages(self, count as usize)
} }
fn get_slatepack_address( fn get_slatepack_address(
&self, &self,
token: Token, token: Token,
derivation_index: u32, derivation_index: u32,
) -> Result<SlatepackAddress, ErrorKind> { ) -> Result<SlatepackAddress, Error> {
Owner::get_slatepack_address(self, (&token.keychain_mask).as_ref(), derivation_index) Owner::get_slatepack_address(self, (&token.keychain_mask).as_ref(), derivation_index)
.map_err(|e| e.kind())
} }
fn get_slatepack_secret_key( fn get_slatepack_secret_key(
&self, &self,
token: Token, token: Token,
derivation_index: u32, derivation_index: u32,
) -> Result<Ed25519SecretKey, ErrorKind> { ) -> Result<Ed25519SecretKey, Error> {
let key = Owner::get_slatepack_secret_key( let key = Owner::get_slatepack_secret_key(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
derivation_index, derivation_index,
) )?;
.map_err(|e| e.kind())?;
Ok(Ed25519SecretKey { key }) Ok(Ed25519SecretKey { key })
} }
@ -2223,15 +2184,14 @@ where
slate: VersionedSlate, slate: VersionedSlate,
sender_index: Option<u32>, sender_index: Option<u32>,
recipients: Vec<SlatepackAddress>, recipients: Vec<SlatepackAddress>,
) -> Result<String, ErrorKind> { ) -> Result<String, Error> {
let res = Owner::create_slatepack_message( let res = Owner::create_slatepack_message(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
&Slate::from(slate), &Slate::from(slate),
sender_index, sender_index,
recipients, recipients,
) )?;
.map_err(|e| e.kind())?;
Ok(res.trim().into()) Ok(res.trim().into())
} }
@ -2240,16 +2200,15 @@ where
token: Token, token: Token,
message: String, message: String,
secret_indices: Vec<u32>, secret_indices: Vec<u32>,
) -> Result<VersionedSlate, ErrorKind> { ) -> Result<VersionedSlate, Error> {
let slate = Owner::slate_from_slatepack_message( let slate = Owner::slate_from_slatepack_message(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
message, message,
secret_indices, secret_indices,
) )?;
.map_err(|e| e.kind())?;
let version = SlateVersion::V4; let version = SlateVersion::V4;
Ok(VersionedSlate::into_version(slate, version).map_err(|e| e.kind())?) VersionedSlate::into_version(slate, version)
} }
fn decode_slatepack_message( fn decode_slatepack_message(
@ -2257,14 +2216,13 @@ where
token: Token, token: Token,
message: String, message: String,
secret_indices: Vec<u32>, secret_indices: Vec<u32>,
) -> Result<Slatepack, ErrorKind> { ) -> Result<Slatepack, Error> {
Owner::decode_slatepack_message( Owner::decode_slatepack_message(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
message, message,
secret_indices, secret_indices,
) )
.map_err(|e| e.kind())
} }
fn retrieve_payment_proof( fn retrieve_payment_proof(
@ -2273,7 +2231,7 @@ where
refresh_from_node: bool, refresh_from_node: bool,
tx_id: Option<u32>, tx_id: Option<u32>,
tx_slate_id: Option<Uuid>, tx_slate_id: Option<Uuid>,
) -> Result<PaymentProof, ErrorKind> { ) -> Result<PaymentProof, Error> {
Owner::retrieve_payment_proof( Owner::retrieve_payment_proof(
self, self,
(&token.keychain_mask).as_ref(), (&token.keychain_mask).as_ref(),
@ -2281,19 +2239,17 @@ where
tx_id, tx_id,
tx_slate_id, tx_slate_id,
) )
.map_err(|e| e.kind())
} }
fn verify_payment_proof( fn verify_payment_proof(
&self, &self,
token: Token, token: Token,
proof: PaymentProof, proof: PaymentProof,
) -> Result<(bool, bool), ErrorKind> { ) -> Result<(bool, bool), Error> {
Owner::verify_payment_proof(self, (&token.keychain_mask).as_ref(), &proof) Owner::verify_payment_proof(self, (&token.keychain_mask).as_ref(), &proof)
.map_err(|e| e.kind())
} }
fn set_tor_config(&self, tor_config: Option<TorConfig>) -> Result<(), ErrorKind> { fn set_tor_config(&self, tor_config: Option<TorConfig>) -> Result<(), Error> {
Owner::set_tor_config(self, tor_config); Owner::set_tor_config(self, tor_config);
Ok(()) Ok(())
} }
@ -2303,9 +2259,8 @@ where
token: Token, token: Token,
features: OutputFeatures, features: OutputFeatures,
amount: Amount, amount: Amount,
) -> Result<BuiltOutput, ErrorKind> { ) -> Result<BuiltOutput, Error> {
Owner::build_output(self, (&token.keychain_mask).as_ref(), features, amount.0) Owner::build_output(self, (&token.keychain_mask).as_ref(), features, amount.0)
.map_err(|e| e.kind())
} }
} }

View file

@ -13,11 +13,10 @@
use crate::core::libtx::secp_ser; use crate::core::libtx::secp_ser;
use crate::libwallet::slate_versions::ser as dalek_ser; use crate::libwallet::slate_versions::ser as dalek_ser;
use crate::libwallet::{Error, ErrorKind}; use crate::libwallet::Error;
use crate::util::secp::key::{PublicKey, SecretKey}; use crate::util::secp::key::{PublicKey, SecretKey};
use crate::util::{from_hex, ToHex}; use crate::util::{from_hex, ToHex};
use ed25519_dalek::SecretKey as DalekSecretKey; use ed25519_dalek::SecretKey as DalekSecretKey;
use failure::ResultExt;
use base64; use base64;
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
@ -75,9 +74,9 @@ impl EncryptedBody {
/// Encrypts and encodes json as base 64 /// Encrypts and encodes json as base 64
pub fn from_json(json_in: &Value, enc_key: &SecretKey) -> Result<Self, Error> { pub fn from_json(json_in: &Value, enc_key: &SecretKey) -> Result<Self, Error> {
let mut to_encrypt = serde_json::to_string(&json_in) let mut to_encrypt = serde_json::to_string(&json_in)
.context(ErrorKind::APIEncryption( .map_err(|_| {
"EncryptedBody Enc: Unable to encode JSON".to_owned(), Error::APIEncryption("EncryptedBody Enc: Unable to encode JSON".to_owned())
))? })?
.as_bytes() .as_bytes()
.to_vec(); .to_vec();
@ -92,9 +91,7 @@ impl EncryptedBody {
&mut to_encrypt, &mut to_encrypt,
); );
if let Err(_) = res { if let Err(_) = res {
return Err( return Err(Error::APIEncryption("EncryptedBody: encryption failed".to_owned()).into());
ErrorKind::APIEncryption("EncryptedBody: encryption failed".to_owned()).into(),
);
} }
Ok(EncryptedBody { Ok(EncryptedBody {
@ -105,31 +102,32 @@ impl EncryptedBody {
/// return serialize JSON self /// return serialize JSON self
pub fn as_json_value(&self) -> Result<Value, Error> { pub fn as_json_value(&self) -> Result<Value, Error> {
let res = serde_json::to_value(self).context(ErrorKind::APIEncryption( let res = serde_json::to_value(self).map_err(|_| {
"EncryptedBody: JSON serialization failed".to_owned(), Error::APIEncryption("EncryptedBody: JSON serialization failed".to_owned())
))?; })?;
Ok(res) Ok(res)
} }
/// return serialized JSON self as string /// return serialized JSON self as string
pub fn as_json_str(&self) -> Result<String, Error> { pub fn as_json_str(&self) -> Result<String, Error> {
let res = self.as_json_value()?; let res = self.as_json_value()?;
let res = serde_json::to_string(&res).context(ErrorKind::APIEncryption( let res = serde_json::to_string(&res).map_err(|_| {
"EncryptedBody: JSON String serialization failed".to_owned(), Error::APIEncryption("EncryptedBody: JSON String serialization failed".to_owned())
))?; })?;
Ok(res) Ok(res)
} }
/// Return original request /// Return original request
pub fn decrypt(&self, dec_key: &SecretKey) -> Result<Value, Error> { pub fn decrypt(&self, dec_key: &SecretKey) -> Result<Value, Error> {
let mut to_decrypt = base64::decode(&self.body_enc).context(ErrorKind::APIEncryption( let mut to_decrypt = base64::decode(&self.body_enc).map_err(|_| {
Error::APIEncryption(
"EncryptedBody Dec: Encrypted request contains invalid Base64".to_string(), "EncryptedBody Dec: Encrypted request contains invalid Base64".to_string(),
))?; )
let nonce = from_hex(&self.nonce).map_err(|_| {
ErrorKind::APIEncryption("EncryptedBody Dec: Invalid Nonce".to_string())
})?; })?;
let nonce = from_hex(&self.nonce)
.map_err(|_| Error::APIEncryption("EncryptedBody Dec: Invalid Nonce".to_string()))?;
if nonce.len() < 12 { if nonce.len() < 12 {
return Err(ErrorKind::APIEncryption( return Err(Error::APIEncryption(
"EncryptedBody Dec: Invalid Nonce length".to_string(), "EncryptedBody Dec: Invalid Nonce length".to_string(),
) )
.into()); .into());
@ -142,22 +140,16 @@ impl EncryptedBody {
let res = let res =
opening_key.open_in_place(aead::Nonce::assume_unique_for_key(n), aad, &mut to_decrypt); opening_key.open_in_place(aead::Nonce::assume_unique_for_key(n), aad, &mut to_decrypt);
if let Err(_) = res { if let Err(_) = res {
return Err( return Err(Error::APIEncryption("EncryptedBody: decryption failed".to_owned()).into());
ErrorKind::APIEncryption("EncryptedBody: decryption failed".to_owned()).into(),
);
} }
for _ in 0..aead::AES_256_GCM.tag_len() { for _ in 0..aead::AES_256_GCM.tag_len() {
to_decrypt.pop(); to_decrypt.pop();
} }
let decrypted = String::from_utf8(to_decrypt).context(ErrorKind::APIEncryption( let decrypted = String::from_utf8(to_decrypt)
"EncryptedBody Dec: Invalid UTF-8".to_string(), .map_err(|_| Error::APIEncryption("EncryptedBody Dec: Invalid UTF-8".to_string()))?;
))?; Ok(serde_json::from_str(&decrypted)
Ok( .map_err(|_| Error::APIEncryption("EncryptedBody Dec: Invalid JSON".to_string()))?)
serde_json::from_str(&decrypted).context(ErrorKind::APIEncryption(
"EncryptedBody Dec: Invalid JSON".to_string(),
))?,
)
} }
} }
@ -187,18 +179,18 @@ impl EncryptedRequest {
/// return serialize JSON self /// return serialize JSON self
pub fn as_json_value(&self) -> Result<Value, Error> { pub fn as_json_value(&self) -> Result<Value, Error> {
let res = serde_json::to_value(self).context(ErrorKind::APIEncryption( let res = serde_json::to_value(self).map_err(|_| {
"EncryptedRequest: JSON serialization failed".to_owned(), Error::APIEncryption("EncryptedRequest: JSON serialization failed".to_owned())
))?; })?;
Ok(res) Ok(res)
} }
/// return serialized JSON self as string /// return serialized JSON self as string
pub fn as_json_str(&self) -> Result<String, Error> { pub fn as_json_str(&self) -> Result<String, Error> {
let res = self.as_json_value()?; let res = self.as_json_value()?;
let res = serde_json::to_string(&res).context(ErrorKind::APIEncryption( let res = serde_json::to_string(&res).map_err(|_| {
"EncryptedRequest: JSON String serialization failed".to_owned(), Error::APIEncryption("EncryptedRequest: JSON String serialization failed".to_owned())
))?; })?;
Ok(res) Ok(res)
} }
@ -236,18 +228,18 @@ impl EncryptedResponse {
/// return serialize JSON self /// return serialize JSON self
pub fn as_json_value(&self) -> Result<Value, Error> { pub fn as_json_value(&self) -> Result<Value, Error> {
let res = serde_json::to_value(self).context(ErrorKind::APIEncryption( let res = serde_json::to_value(self).map_err(|_| {
"EncryptedResponse: JSON serialization failed".to_owned(), Error::APIEncryption("EncryptedResponse: JSON serialization failed".to_owned())
))?; })?;
Ok(res) Ok(res)
} }
/// return serialized JSON self as string /// return serialized JSON self as string
pub fn as_json_str(&self) -> Result<String, Error> { pub fn as_json_str(&self) -> Result<String, Error> {
let res = self.as_json_value()?; let res = self.as_json_value()?;
let res = serde_json::to_string(&res).context(ErrorKind::APIEncryption( let res = serde_json::to_string(&res).map_err(|_| {
"EncryptedResponse: JSON String serialization failed".to_owned(), Error::APIEncryption("EncryptedResponse: JSON String serialization failed".to_owned())
))?; })?;
Ok(res) Ok(res)
} }
@ -293,9 +285,9 @@ impl EncryptionErrorResponse {
/// return serialized JSON self /// return serialized JSON self
pub fn as_json_value(&self) -> Value { pub fn as_json_value(&self) -> Value {
let res = serde_json::to_value(self).context(ErrorKind::APIEncryption( let res = serde_json::to_value(self).map_err(|_| {
"EncryptedResponse: JSON serialization failed".to_owned(), Error::APIEncryption("EncryptedResponse: JSON serialization failed".to_owned())
)); });
match res { match res {
Ok(r) => r, Ok(r) => r,
// proverbial "should never happen" // proverbial "should never happen"

View file

@ -11,8 +11,6 @@ exclude = ["**/*.grin", "**/*.grin2"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
failure = "0.1"
failure_derive = "0.1"
futures = "0.3" futures = "0.3"
hyper = "0.13" hyper = "0.13"
rand = "0.7" rand = "0.7"
@ -29,6 +27,7 @@ url = "2.1"
chrono = { version = "0.4.11", features = ["serde"] } chrono = { version = "0.4.11", features = ["serde"] }
easy-jsonrpc-mw = "0.5.4" easy-jsonrpc-mw = "0.5.4"
lazy_static = "1" lazy_static = "1"
thiserror = "1"
qr_code = "1.1.0" qr_code = "1.1.0"
grin_wallet_util = { path = "../util", version = "5.2.0-alpha.1" } grin_wallet_util = { path = "../util", version = "5.2.0-alpha.1" }

View file

@ -18,7 +18,7 @@ use crate::api::TLSConfig;
use crate::apiwallet::{try_slatepack_sync_workflow, Owner}; use crate::apiwallet::{try_slatepack_sync_workflow, Owner};
use crate::config::{TorConfig, WalletConfig, WALLET_CONFIG_FILE_NAME}; use crate::config::{TorConfig, WalletConfig, WALLET_CONFIG_FILE_NAME};
use crate::core::{core, global}; use crate::core::{core, global};
use crate::error::{Error, ErrorKind}; use crate::error::Error;
use crate::impls::PathToSlatepack; use crate::impls::PathToSlatepack;
use crate::impls::SlateGetter as _; use crate::impls::SlateGetter as _;
use crate::keychain; use crate::keychain;
@ -184,7 +184,6 @@ where
} }
Err(e) => { Err(e) => {
error!("View wallet check failed: {}", e); error!("View wallet check failed: {}", e);
error!("Backtrace: {}", e.backtrace().unwrap());
Err(e) Err(e)
} }
} }
@ -235,7 +234,7 @@ where
let r = t.join(); let r = t.join();
if let Err(_) = r { if let Err(_) = r {
error!("Error starting listener"); error!("Error starting listener");
return Err(ErrorKind::ListenerError.into()); return Err(Error::ListenerError);
} }
} }
} }
@ -269,7 +268,7 @@ where
test_mode, test_mode,
); );
if let Err(e) = res { if let Err(e) = res {
return Err(ErrorKind::LibWallet(e.kind(), e.cause_string()).into()); return Err(Error::LibWallet(e));
} }
Ok(()) Ok(())
} }
@ -299,7 +298,7 @@ where
}); });
if let Err(e) = res { if let Err(e) = res {
error!("Error listing accounts: {}", e); error!("Error listing accounts: {}", e);
return Err(ErrorKind::LibWallet(e.kind(), e.cause_string()).into()); return Err(Error::LibWallet(e));
} }
} else { } else {
let label = args.create.unwrap(); let label = args.create.unwrap();
@ -312,7 +311,7 @@ where
if let Err(e) = res { if let Err(e) = res {
thread::sleep(Duration::from_millis(200)); thread::sleep(Duration::from_millis(200));
error!("Error creating account '{}': {}", label, e); error!("Error creating account '{}': {}", label, e);
return Err(ErrorKind::LibWallet(e.kind(), e.cause_string()).into()); return Err(Error::LibWallet(e));
} }
} }
Ok(()) Ok(())
@ -616,7 +615,7 @@ where
} }
None => { None => {
let msg = "No slate provided via file or direct input"; 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 slate
@ -740,7 +739,7 @@ where
sp sp
} }
None => { 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) => { Err(e) => {
error!("Wallet check failed: {}", e); error!("Wallet check failed: {}", e);
error!("Backtrace: {}", e.backtrace().unwrap());
Err(e) Err(e)
} }
} }
@ -1436,7 +1434,7 @@ where
"Unable to open payment proof file at {}: {}", "Unable to open payment proof file at {}: {}",
args.input_file, e args.input_file, e
); );
return Err(libwallet::ErrorKind::PaymentProofParsing(msg).into()); return Err(libwallet::Error::PaymentProofParsing(msg));
} }
}; };
let mut proof = String::new(); let mut proof = String::new();
@ -1447,7 +1445,7 @@ where
Err(e) => { Err(e) => {
let msg = format!("{}", e); let msg = format!("{}", e);
error!("Unable to parse payment proof file: {}", 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); let result = api.verify_payment_proof(m, &proof);

View file

@ -18,12 +18,11 @@ use crate::api::{self, ApiServer, BasicAuthMiddleware, ResponseFuture, Router, T
use crate::config::TorConfig; use crate::config::TorConfig;
use crate::keychain::Keychain; use crate::keychain::Keychain;
use crate::libwallet::{ use crate::libwallet::{
address, Error, ErrorKind, NodeClient, NodeVersionInfo, Slate, SlatepackAddress, WalletInst, address, Error, NodeClient, NodeVersionInfo, Slate, SlatepackAddress, WalletInst,
WalletLCProvider, GRIN_BLOCK_HEADER_VERSION, WalletLCProvider, GRIN_BLOCK_HEADER_VERSION,
}; };
use crate::util::secp::key::SecretKey; use crate::util::secp::key::SecretKey;
use crate::util::{from_hex, static_secp_instance, to_base64, Mutex}; use crate::util::{from_hex, static_secp_instance, to_base64, Mutex};
use failure::ResultExt;
use futures::channel::oneshot; use futures::channel::oneshot;
use grin_wallet_api::JsonId; use grin_wallet_api::JsonId;
use grin_wallet_config::types::{TorBridgeConfig, TorProxyConfig}; use grin_wallet_config::types::{TorBridgeConfig, TorProxyConfig};
@ -70,7 +69,7 @@ fn check_middleware(
} }
if let Some(s) = slate { if let Some(s) = slate {
if bhv > 4 && s.version_info.block_header_version < GRIN_BLOCK_HEADER_VERSION { 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. \ "Incoming Slate is not compatible with this wallet. \
Please upgrade the node or use a different one." Please upgrade the node or use a different one."
.into(), .into(),
@ -105,9 +104,9 @@ where
let parent_key_id = w_inst.parent_key_id(); let parent_key_id = w_inst.parent_key_id();
let tor_dir = format!("{}/tor/listener", lc.get_top_level_directory()?); let tor_dir = format!("{}/tor/listener", lc.get_top_level_directory()?);
let sec_key = address::address_from_derivation_path(&k, &parent_key_id, 0) 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) 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 sp_address = SlatepackAddress::try_from(onion_address.clone())?;
let mut hm_tor_bridge: HashMap<String, String> = HashMap::new(); let mut hm_tor_bridge: HashMap<String, String> = HashMap::new();
@ -115,19 +114,19 @@ where
if bridge.bridge_line.is_some() { if bridge.bridge_line.is_some() {
tor_timeout = 40; tor_timeout = 40;
let bridge_config = tor_bridge::TorBridge::try_from(bridge) 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 hm_tor_bridge = bridge_config
.to_hashmap() .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(); let mut hm_tor_poxy: HashMap<String, String> = HashMap::new();
if tor_proxy.transport.is_some() || tor_proxy.allowed_port.is_some() { if tor_proxy.transport.is_some() || tor_proxy.allowed_port.is_some() {
let proxy_config = tor_proxy::TorProxy::try_from(tor_proxy) 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 hm_tor_poxy = proxy_config
.to_hashmap() .to_hashmap()
.map_err(|e| ErrorKind::TorConfig(format!("{}", e.kind()).into()))?; .map_err(|e| Error::TorConfig(format!("{}", e).into()))?;
} }
warn!( warn!(
@ -141,7 +140,7 @@ where
hm_tor_bridge, hm_tor_bridge,
hm_tor_poxy, hm_tor_poxy,
) )
.map_err(|e| ErrorKind::TorConfig(format!("{:?}", e).into()))?; .map_err(|e| Error::TorConfig(format!("{:?}", e).into()))?;
// Start TOR process // Start TOR process
process process
.torrc_path(&format!("{}/torrc", tor_dir)) .torrc_path(&format!("{}/torrc", tor_dir))
@ -149,7 +148,7 @@ where
.timeout(tor_timeout) .timeout(tor_timeout)
.completion_percent(100) .completion_percent(100)
.launch() .launch()
.map_err(|e| ErrorKind::TorProcess(format!("{:?}", e).into()))?; .map_err(|e| Error::TorProcess(format!("{:?}", e)))?;
Ok((process, sp_address)) Ok((process, sp_address))
} }
@ -173,10 +172,9 @@ where
let wallet = match wallet { let wallet = match wallet {
Some(w) => w, Some(w) => w,
None => { None => {
return Err(ErrorKind::GenericError(format!( return Err(Error::GenericError(format!(
"Instantiated wallet or Owner API context must be provided" "Instantiated wallet or Owner API context must be provided"
)) )))
.into())
} }
}; };
f(&mut Owner::new(wallet, None), keychain_mask)? f(&mut Owner::new(wallet, None), keychain_mask)?
@ -251,7 +249,7 @@ where
router router
.add_route("/v3/owner", Arc::new(api_handler_v3)) .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 so configured, add the foreign API to the same port
if running_foreign { if running_foreign {
@ -260,7 +258,7 @@ where
ForeignAPIHandlerV2::new(wallet, keychain_mask, test_mode, Mutex::new(tor_config)); ForeignAPIHandlerV2::new(wallet, keychain_mask, test_mode, Mutex::new(tor_config));
router router
.add_route("/v2/foreign", Arc::new(foreign_api_handler_v2)) .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<()>) = 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 socket_addr: SocketAddr = addr.parse().expect("unable to parse socket address");
let api_thread = apis let api_thread = apis
.start(socket_addr, router, tls_config, api_chan) .start(socket_addr, router, tls_config, api_chan)
.context(ErrorKind::GenericError( .map_err(|_| Error::GenericError("API thread failed to start".to_string()))?;
"API thread failed to start".to_string(),
))?;
warn!("HTTP Owner listener started."); warn!("HTTP Owner listener started.");
api_thread api_thread
.join() .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 /// Listener version, providing same API but listening for requests on a
@ -336,7 +332,7 @@ where
router router
.add_route("/v2/foreign", Arc::new(api_handler_v2)) .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<()>) = let api_chan: &'static mut (oneshot::Sender<()>, oneshot::Receiver<()>) =
Box::leak(Box::new(oneshot::channel::<()>())); Box::leak(Box::new(oneshot::channel::<()>()));
@ -346,9 +342,7 @@ where
let socket_addr: SocketAddr = addr.parse().expect("unable to parse socket address"); let socket_addr: SocketAddr = addr.parse().expect("unable to parse socket address");
let api_thread = apis let api_thread = apis
.start(socket_addr, router, tls_config, api_chan) .start(socket_addr, router, tls_config, api_chan)
.context(ErrorKind::GenericError( .map_err(|_| Error::GenericError("API thread failed to start".to_string()))?;
"API thread failed to start".to_string(),
))?;
warn!("HTTP Foreign listener started."); warn!("HTTP Foreign listener started.");
if let Some(a) = address { if let Some(a) = address {
@ -361,7 +355,7 @@ where
api_thread api_thread
.join() .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 /// V3 API Handler/Wrapper for owner functions, which include a secure
@ -477,7 +471,7 @@ impl OwnerV3Helpers {
})?; })?;
let id = enc_req.id.clone(); let id = enc_req.id.clone();
let res = enc_req.decrypt(&shared_key).map_err(|e| { 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() .as_json_value()
})?; })?;
Ok((id, res)) Ok((id, res))
@ -492,7 +486,7 @@ impl OwnerV3Helpers {
let share_key_ref = key.lock(); let share_key_ref = key.lock();
let shared_key = share_key_ref.as_ref().unwrap(); let shared_key = share_key_ref.as_ref().unwrap();
let enc_res = EncryptedResponse::from_json(id, res, &shared_key).map_err(|e| { 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() .as_json_value()
})?; })?;
let res = enc_res.as_json_value().map_err(|e| { let res = enc_res.as_json_value().map_err(|e| {
@ -874,8 +868,8 @@ where
{ {
let body = body::to_bytes(req.into_body()) let body = body::to_bytes(req.into_body())
.await .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[..]) 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)))
} }

View file

@ -19,209 +19,87 @@ use crate::core::libtx;
use crate::impls; use crate::impls;
use crate::keychain; use crate::keychain;
use crate::libwallet; 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. /// Wallet errors, mostly wrappers around underlying crypto or I/O errors.
#[derive(Clone, Eq, PartialEq, Debug, Fail)] #[derive(Clone, Eq, PartialEq, Debug, thiserror::Error)]
pub enum ErrorKind { pub enum Error {
/// LibTX Error /// LibTX Error
#[fail(display = "LibTx Error")] #[error("LibTx Error")]
LibTX(libtx::ErrorKind), LibTX(#[from] libtx::Error),
/// Impls error /// Impls error
#[fail(display = "Impls Error")] #[error("Impls Error")]
Impls(impls::ErrorKind), Impls(#[from] impls::Error),
/// LibWallet Error /// LibWallet Error
#[fail(display = "LibWallet Error: {}", _1)] #[error("LibWallet Error: {0}")]
LibWallet(libwallet::ErrorKind, String), LibWallet(#[from] libwallet::Error),
/// Keychain error /// Keychain error
#[fail(display = "Keychain error")] #[error("Keychain error")]
Keychain(keychain::Error), Keychain(#[from] keychain::Error),
/// Transaction Error /// Transaction Error
#[fail(display = "Transaction error")] #[error("Transaction error")]
Transaction(transaction::Error), Transaction(#[from] transaction::Error),
/// Secp Error /// Secp Error
#[fail(display = "Secp error")] #[error("Secp error")]
Secp, Secp,
/// Filewallet error /// Filewallet error
#[fail(display = "Wallet data error: {}", _0)] #[error("Wallet data error: {0}")]
FileWallet(&'static str), FileWallet(&'static str),
/// Error when formatting json /// Error when formatting json
#[fail(display = "IO error")] #[error("IO error")]
IO, IO,
/// Error when formatting json /// Error when formatting json
#[fail(display = "Serde JSON error")] #[error("Serde JSON error")]
Format, Format,
/// Error when contacting a node through its API /// Error when contacting a node through its API
#[fail(display = "Node API error")] #[error("Node API error")]
Node(api::ErrorKind), Node(#[from] api::Error),
/// Error originating from hyper. /// Error originating from hyper.
#[fail(display = "Hyper error")] #[error("Hyper error")]
Hyper, Hyper,
/// Error originating from hyper uri parsing. /// Error originating from hyper uri parsing.
#[fail(display = "Uri parsing error")] #[error("Uri parsing error")]
Uri, Uri,
/// Attempt to use duplicate transaction id in separate transactions /// Attempt to use duplicate transaction id in separate transactions
#[fail(display = "Duplicate transaction ID error")] #[error("Duplicate transaction ID error")]
DuplicateTransactionId, DuplicateTransactionId,
/// Wallet seed already exists /// Wallet seed already exists
#[fail(display = "Wallet seed file exists: {}", _0)] #[error("Wallet seed file exists: {0}")]
WalletSeedExists(String), WalletSeedExists(String),
/// Wallet seed doesn't exist /// Wallet seed doesn't exist
#[fail(display = "Wallet seed doesn't exist error")] #[error("Wallet seed doesn't exist error")]
WalletSeedDoesntExist, WalletSeedDoesntExist,
/// Enc/Decryption Error /// Enc/Decryption Error
#[fail(display = "Enc/Decryption error (check password?)")] #[error("Enc/Decryption error (check password?)")]
Encryption, Encryption,
/// BIP 39 word list /// BIP 39 word list
#[fail(display = "BIP39 Mnemonic (word list) Error")] #[error("BIP39 Mnemonic (word list) Error")]
Mnemonic, Mnemonic,
/// Command line argument error /// Command line argument error
#[fail(display = "{}", _0)] #[error("{0}")]
ArgumentError(String), ArgumentError(String),
/// Other /// Other
#[fail(display = "Listener Startup Error")] #[error("Listener Startup Error")]
ListenerError, ListenerError,
/// Other /// Other
#[fail(display = "Generic error: {}", _0)] #[error("Generic error: {0}")]
GenericError(String), 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())),
}
}
}

View file

@ -21,7 +21,6 @@ extern crate prettytable;
extern crate log; extern crate log;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
use failure;
use grin_wallet_api as apiwallet; use grin_wallet_api as apiwallet;
use grin_wallet_config as config; use grin_wallet_config as config;
use grin_wallet_impls as impls; use grin_wallet_impls as impls;
@ -36,4 +35,4 @@ pub mod controller;
pub mod display; pub mod display;
mod error; mod error;
pub use crate::error::{Error, ErrorKind}; pub use crate::error::Error;

View file

@ -270,7 +270,7 @@ fn accounts() {
let test_dir = "test_output/accounts"; let test_dir = "test_output/accounts";
setup(test_dir); setup(test_dir);
if let Err(e) = accounts_test_impl(test_dir) { if let Err(e) = accounts_test_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -165,7 +165,7 @@ fn build_chain_to_height() {
clean_output_dir(test_dir); clean_output_dir(test_dir);
setup(test_dir); setup(test_dir);
if let Err(e) = build_chain(test_dir, 2048) { if let Err(e) = build_chain(test_dir, 2048) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
// don't clean to get the result for testing // don't clean to get the result for testing
} }

View file

@ -95,7 +95,7 @@ fn build_output() {
let test_dir = "test_output/build_output"; let test_dir = "test_output/build_output";
setup(test_dir); setup(test_dir);
if let Err(e) = build_output_test_impl(test_dir) { if let Err(e) = build_output_test_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -852,7 +852,7 @@ fn scan() {
let test_dir = "test_output/scan"; let test_dir = "test_output/scan";
setup(test_dir); setup(test_dir);
if let Err(e) = scan_impl(test_dir) { if let Err(e) = scan_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }
@ -862,7 +862,7 @@ fn two_wallets_one_seed() {
let test_dir = "test_output/two_wallets_one_seed"; let test_dir = "test_output/two_wallets_one_seed";
setup(test_dir); setup(test_dir);
if let Err(e) = two_wallets_one_seed_impl(test_dir) { if let Err(e) = two_wallets_one_seed_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }
@ -872,7 +872,7 @@ fn output_scanning() {
let test_dir = "test_output/output_scanning"; let test_dir = "test_output/output_scanning";
setup(test_dir); setup(test_dir);
if let Err(e) = output_scanning_impl(test_dir) { if let Err(e) = output_scanning_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -304,7 +304,7 @@ fn wallet_file_exchange_json() {
setup(test_dir); setup(test_dir);
// Json output // Json output
if let Err(e) = file_exchange_test_impl(test_dir, false) { if let Err(e) = file_exchange_test_impl(test_dir, false) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }
@ -314,7 +314,7 @@ fn wallet_file_exchange_bin() {
let test_dir = "test_output/file_exchange_bin"; let test_dir = "test_output/file_exchange_bin";
setup(test_dir); setup(test_dir);
if let Err(e) = file_exchange_test_impl(test_dir, true) { if let Err(e) = file_exchange_test_impl(test_dir, true) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -152,7 +152,7 @@ fn late_lock() {
let test_dir = "test_output/late_lock"; let test_dir = "test_output/late_lock";
setup(test_dir); setup(test_dir);
if let Err(e) = late_lock_test_impl(test_dir) { if let Err(e) = late_lock_test_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -206,7 +206,7 @@ fn no_change() {
let test_dir = "test_output/no_change"; let test_dir = "test_output/no_change";
setup(test_dir); setup(test_dir);
if let Err(e) = no_change_test_impl(test_dir) { if let Err(e) = no_change_test_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -166,7 +166,7 @@ fn payment_proofs() {
let test_dir = "test_output/payment_proofs"; let test_dir = "test_output/payment_proofs";
setup(test_dir); setup(test_dir);
if let Err(e) = payment_proofs_test_impl(test_dir) { if let Err(e) = payment_proofs_test_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -262,7 +262,7 @@ fn wallet_file_repost() {
let test_dir = "test_output/file_repost"; let test_dir = "test_output/file_repost";
setup(test_dir); setup(test_dir);
if let Err(e) = file_repost_test_impl(test_dir) { if let Err(e) = file_repost_test_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -363,7 +363,7 @@ fn tx_revert_reconfirm() {
let test_dir = "test_output/revert_tx"; let test_dir = "test_output/revert_tx";
setup(test_dir); setup(test_dir);
if let Err(e) = revert_reconfirm_impl(test_dir) { if let Err(e) = revert_reconfirm_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }
@ -373,7 +373,7 @@ fn tx_revert_cancel() {
let test_dir = "test_output/revert_tx_cancel"; let test_dir = "test_output/revert_tx_cancel";
setup(test_dir); setup(test_dir);
if let Err(e) = revert_cancel_impl(test_dir) { if let Err(e) = revert_cancel_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -142,7 +142,7 @@ fn wallet_self_send() {
let test_dir = "test_output/self_send"; let test_dir = "test_output/self_send";
setup(test_dir); setup(test_dir);
if let Err(e) = self_send_test_impl(test_dir) { if let Err(e) = self_send_test_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -515,7 +515,7 @@ fn slatepack_exchange_json() {
setup(test_dir); setup(test_dir);
// Json output // Json output
if let Err(e) = slatepack_exchange_test_impl(test_dir, false, false, false) { if let Err(e) = slatepack_exchange_test_impl(test_dir, false, false, false) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }
@ -526,7 +526,7 @@ fn slatepack_exchange_bin() {
setup(test_dir); setup(test_dir);
// Bin output // Bin output
if let Err(e) = slatepack_exchange_test_impl(test_dir, true, false, false) { if let Err(e) = slatepack_exchange_test_impl(test_dir, true, false, false) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }
@ -537,7 +537,7 @@ fn slatepack_exchange_armored() {
setup(test_dir); setup(test_dir);
// Bin output // Bin output
if let Err(e) = slatepack_exchange_test_impl(test_dir, true, true, true) { if let Err(e) = slatepack_exchange_test_impl(test_dir, true, true, true) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }
@ -548,7 +548,7 @@ fn slatepack_exchange_json_enc() {
setup(test_dir); setup(test_dir);
// Json output // Json output
if let Err(e) = slatepack_exchange_test_impl(test_dir, false, false, true) { if let Err(e) = slatepack_exchange_test_impl(test_dir, false, false, true) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }
@ -559,7 +559,7 @@ fn slatepack_exchange_bin_enc() {
setup(test_dir); setup(test_dir);
// Bin output // Bin output
if let Err(e) = slatepack_exchange_test_impl(test_dir, true, false, true) { if let Err(e) = slatepack_exchange_test_impl(test_dir, true, false, true) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }
@ -570,7 +570,7 @@ fn slatepack_exchange_armored_enc() {
setup(test_dir); setup(test_dir);
// Bin output // Bin output
if let Err(e) = slatepack_exchange_test_impl(test_dir, true, true, true) { if let Err(e) = slatepack_exchange_test_impl(test_dir, true, true, true) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }
@ -581,7 +581,7 @@ fn slatepack_api() {
setup(test_dir); setup(test_dir);
// Json output // Json output
if let Err(e) = slatepack_api_impl(test_dir) { if let Err(e) = slatepack_api_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -585,7 +585,7 @@ fn db_wallet_basic_transaction_api() {
let test_dir = "test_output/basic_transaction_api"; let test_dir = "test_output/basic_transaction_api";
setup(test_dir); setup(test_dir);
if let Err(e) = basic_transaction_api(test_dir) { if let Err(e) = basic_transaction_api(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }
@ -595,7 +595,7 @@ fn db_wallet_tx_rollback() {
let test_dir = "test_output/tx_rollback"; let test_dir = "test_output/tx_rollback";
setup(test_dir); setup(test_dir);
if let Err(e) = tx_rollback(test_dir) { if let Err(e) = tx_rollback(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -179,7 +179,7 @@ fn ttl_cutoff() {
let test_dir = "test_output/ttl_cutoff"; let test_dir = "test_output/ttl_cutoff";
setup(test_dir); setup(test_dir);
if let Err(e) = ttl_cutoff_test_impl(test_dir) { if let Err(e) = ttl_cutoff_test_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -117,7 +117,7 @@ fn updater_thread() {
let test_dir = "test_output/updater_thread"; let test_dir = "test_output/updater_thread";
setup(test_dir); setup(test_dir);
if let Err(e) = updater_thread_test_impl(test_dir) { if let Err(e) = updater_thread_test_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
clean_output_dir(test_dir); clean_output_dir(test_dir);
} }

View file

@ -11,8 +11,7 @@ edition = "2018"
[dependencies] [dependencies]
blake2-rfc = "0.2" blake2-rfc = "0.2"
failure = "0.1" thiserror = "1"
failure_derive = "0.1"
futures = "0.3" futures = "0.3"
rand = "0.6" rand = "0.6"
serde = "1" serde = "1"

View file

@ -16,7 +16,7 @@
use std::fs::File; use std::fs::File;
use std::io::{Read, Write}; use std::io::{Read, Write};
use crate::libwallet::{Error, ErrorKind, Slate, SlateVersion, VersionedBinSlate, VersionedSlate}; use crate::libwallet::{Error, Slate, SlateVersion, VersionedBinSlate, VersionedSlate};
use crate::{SlateGetter, SlatePutter}; use crate::{SlateGetter, SlatePutter};
use grin_wallet_util::byte_ser; use grin_wallet_util::byte_ser;
use std::convert::TryFrom; use std::convert::TryFrom;
@ -39,13 +39,12 @@ impl SlatePutter for PathToSlate {
// TODO: // TODO:
let out_slate = VersionedSlate::into_version(slate.clone(), SlateVersion::V4)?; let out_slate = VersionedSlate::into_version(slate.clone(), SlateVersion::V4)?;
if as_bin { if as_bin {
let bin_slate = let bin_slate = VersionedBinSlate::try_from(out_slate).map_err(|_| Error::SlateSer)?;
VersionedBinSlate::try_from(out_slate).map_err(|_| ErrorKind::SlateSer)?; pub_tx.write_all(&byte_ser::to_bytes(&bin_slate).map_err(|_| Error::SlateSer)?)?;
pub_tx.write_all(&byte_ser::to_bytes(&bin_slate).map_err(|_| ErrorKind::SlateSer)?)?;
} else { } else {
pub_tx.write_all( pub_tx.write_all(
serde_json::to_string_pretty(&out_slate) serde_json::to_string_pretty(&out_slate)
.map_err(|_| ErrorKind::SlateSer)? .map_err(|_| Error::SlateSer)?
.as_bytes(), .as_bytes(),
)?; )?;
} }
@ -68,7 +67,7 @@ impl SlateGetter for PathToSlate {
} }
// Otherwise try json // Otherwise try json
let content = String::from_utf8(data).map_err(|_| ErrorKind::SlateSer)?; let content = String::from_utf8(data).map_err(|_| Error::SlateSer)?;
Ok((Slate::deserialize_upgrade(&content)?, false)) Ok((Slate::deserialize_upgrade(&content)?, false))
} }
} }

View file

@ -13,9 +13,9 @@
// limitations under the License. // limitations under the License.
/// HTTP Wallet 'plugin' implementation /// HTTP Wallet 'plugin' implementation
use crate::client_utils::{Client, ClientError, ClientErrorKind}; use crate::client_utils::{Client, ClientError};
use crate::libwallet::slate_versions::{SlateVersion, VersionedSlate}; use crate::libwallet::slate_versions::{SlateVersion, VersionedSlate};
use crate::libwallet::{Error, ErrorKind, Slate}; use crate::libwallet::{Error, Slate};
use crate::tor::bridge::TorBridge; use crate::tor::bridge::TorBridge;
use crate::tor::proxy::TorProxy; use crate::tor::proxy::TorProxy;
use crate::SlateSender; use crate::SlateSender;
@ -97,19 +97,19 @@ impl HttpSlateSender {
let mut hm_tor_bridge: HashMap<String, String> = HashMap::new(); let mut hm_tor_bridge: HashMap<String, String> = HashMap::new();
if self.bridge.bridge_line.is_some() { if self.bridge.bridge_line.is_some() {
let bridge_struct = TorBridge::try_from(self.bridge.clone()) let bridge_struct = TorBridge::try_from(self.bridge.clone())
.map_err(|e| ErrorKind::TorConfig(format!("{:?}", e).into()))?; .map_err(|e| Error::TorConfig(format!("{:?}", e)))?;
hm_tor_bridge = bridge_struct hm_tor_bridge = bridge_struct
.to_hashmap() .to_hashmap()
.map_err(|e| ErrorKind::TorConfig(format!("{:?}", e).into()))?; .map_err(|e| Error::TorConfig(format!("{:?}", e)))?;
} }
let mut hm_tor_proxy: HashMap<String, String> = HashMap::new(); let mut hm_tor_proxy: HashMap<String, String> = HashMap::new();
if self.proxy.transport.is_some() || self.proxy.allowed_port.is_some() { if self.proxy.transport.is_some() || self.proxy.allowed_port.is_some() {
let proxy = TorProxy::try_from(self.proxy.clone()) let proxy = TorProxy::try_from(self.proxy.clone())
.map_err(|e| ErrorKind::TorConfig(format!("{:?}", e).into()))?; .map_err(|e| Error::TorConfig(format!("{:?}", e)))?;
hm_tor_proxy = proxy hm_tor_proxy = proxy
.to_hashmap() .to_hashmap()
.map_err(|e| ErrorKind::TorConfig(format!("{:?}", e).into()))?; .map_err(|e| Error::TorConfig(format!("{:?}", e)))?;
} }
tor_config::output_tor_sender_config( tor_config::output_tor_sender_config(
@ -118,14 +118,14 @@ impl HttpSlateSender {
hm_tor_bridge, hm_tor_bridge,
hm_tor_proxy, hm_tor_proxy,
) )
.map_err(|e| ErrorKind::TorConfig(format!("{:?}", e)))?; .map_err(|e| Error::TorConfig(format!("{:?}", e)))?;
// Start TOR process // Start TOR process
tor.torrc_path(&format!("{}/torrc", &tor_dir)) tor.torrc_path(&format!("{}/torrc", &tor_dir))
.working_dir(&tor_dir) .working_dir(&tor_dir)
.timeout(20) .timeout(20)
.completion_percent(100) .completion_percent(100)
.launch() .launch()
.map_err(|e| ErrorKind::TorProcess(format!("{:?}", e)))?; .map_err(|e| Error::TorProcess(format!("{:?}", e)))?;
self.process = Some(Arc::new(tor)); self.process = Some(Arc::new(tor));
} }
Ok(()) Ok(())
@ -151,7 +151,7 @@ impl HttpSlateSender {
.to_string(); .to_string();
error!("{}", report); error!("{}", report);
} }
ErrorKind::ClientCallback(report) Error::ClientCallback(report)
})?; })?;
let res: Value = serde_json::from_str(&res).unwrap(); let res: Value = serde_json::from_str(&res).unwrap();
@ -162,7 +162,7 @@ impl HttpSlateSender {
res["error"]["code"], res["error"]["message"] res["error"]["code"], res["error"]["message"]
); );
error!("{}", report); error!("{}", report);
return Err(ErrorKind::ClientCallback(report).into()); return Err(Error::ClientCallback(report));
} }
let resp_value = res["result"]["Ok"].clone(); let resp_value = res["result"]["Ok"].clone();
@ -176,7 +176,7 @@ impl HttpSlateSender {
if foreign_api_version < 2 { if foreign_api_version < 2 {
let report = "Other wallet reports unrecognized API format.".to_string(); let report = "Other wallet reports unrecognized API format.".to_string();
error!("{}", report); error!("{}", report);
return Err(ErrorKind::ClientCallback(report).into()); return Err(Error::ClientCallback(report));
} }
if supported_slate_versions.contains(&"V4".to_owned()) { if supported_slate_versions.contains(&"V4".to_owned()) {
@ -185,7 +185,7 @@ impl HttpSlateSender {
let report = "Unable to negotiate slate format with other wallet.".to_string(); let report = "Unable to negotiate slate format with other wallet.".to_string();
error!("{}", report); error!("{}", report);
Err(ErrorKind::ClientCallback(report).into()) Err(Error::ClientCallback(report))
} }
fn post<IN>( fn post<IN>(
@ -197,15 +197,15 @@ impl HttpSlateSender {
where where
IN: Serialize, IN: Serialize,
{ {
let client = let client = if !self.use_socks {
if !self.use_socks {
Client::new() Client::new()
} else { } else {
Client::with_socks_proxy(self.socks_proxy_addr.ok_or_else(|| { Client::with_socks_proxy(
ClientErrorKind::Internal("No socks proxy address set".into()) self.socks_proxy_addr
})?) .ok_or_else(|| ClientError::Internal("No socks proxy address set".into()))?,
)
} }
.map_err(|_| ClientErrorKind::Internal("Unable to create http client".into()))?; .map_err(|_| ClientError::Internal("Unable to create http client".into()))?;
let req = client.create_post_request(url, api_secret, &input)?; let req = client.create_post_request(url, api_secret, &input)?;
let res = client.send_request(req)?; let res = client.send_request(req)?;
Ok(res) Ok(res)
@ -254,7 +254,7 @@ impl SlateSender for HttpSlateSender {
"Sending transaction slate to other wallet (is recipient listening?): {}", "Sending transaction slate to other wallet (is recipient listening?): {}",
e e
); );
ErrorKind::ClientCallback(report) Error::ClientCallback(report)
})?; })?;
let res: Value = serde_json::from_str(&res).unwrap(); let res: Value = serde_json::from_str(&res).unwrap();
@ -265,7 +265,7 @@ impl SlateSender for HttpSlateSender {
res["error"]["code"], res["error"]["message"] res["error"]["code"], res["error"]["message"]
); );
error!("{}", report); error!("{}", report);
return Err(ErrorKind::ClientCallback(report).into()); return Err(Error::ClientCallback(report));
} }
let slate_value = res["result"]["Ok"].clone(); let slate_value = res["result"]["Ok"].clone();
@ -274,7 +274,7 @@ impl SlateSender for HttpSlateSender {
let slate = Slate::deserialize_upgrade(&serde_json::to_string(&slate_value).unwrap()) let slate = Slate::deserialize_upgrade(&serde_json::to_string(&slate_value).unwrap())
.map_err(|e| { .map_err(|e| {
error!("Error deserializing response slate: {}", e); error!("Error deserializing response slate: {}", e);
ErrorKind::SlateDeser Error::SlateDeser
})?; })?;
Ok(slate) Ok(slate)
@ -287,6 +287,6 @@ pub struct SchemeNotHttp;
impl Into<Error> for SchemeNotHttp { impl Into<Error> for SchemeNotHttp {
fn into(self) -> Error { fn into(self) -> Error {
let err_str = "url scheme must be http".to_string(); let err_str = "url scheme must be http".to_string();
ErrorKind::GenericError(err_str).into() Error::GenericError(err_str)
} }
} }

View file

@ -17,7 +17,7 @@ use std::fs::{metadata, File};
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::PathBuf; use std::path::PathBuf;
use crate::libwallet::{slatepack, Error, ErrorKind, Slate, Slatepack, SlatepackBin, Slatepacker}; use crate::libwallet::{slatepack, Error, Slate, Slatepack, SlatepackBin, Slatepacker};
use crate::{SlateGetter, SlatePutter}; use crate::{SlateGetter, SlatePutter};
use grin_wallet_util::byte_ser; use grin_wallet_util::byte_ser;
@ -48,7 +48,7 @@ impl<'a> PathToSlatepack<'a> {
"Data is invalid length: {} | min: {}, max: {} |", "Data is invalid length: {} | min: {}, max: {} |",
len, min_len, max_len len, min_len, max_len
); );
return Err(ErrorKind::SlatepackDeser(msg).into()); return Err(Error::SlatepackDeser(msg));
} }
let mut pub_tx_f = File::open(&self.pathbuf)?; let mut pub_tx_f = File::open(&self.pathbuf)?;
let mut data = Vec::new(); let mut data = Vec::new();
@ -73,13 +73,13 @@ impl<'a> SlatePutter for PathToSlatepack<'a> {
} else { } else {
pub_tx.write_all( pub_tx.write_all(
&byte_ser::to_bytes(&SlatepackBin(slatepack)) &byte_ser::to_bytes(&SlatepackBin(slatepack))
.map_err(|_| ErrorKind::SlatepackSer)?, .map_err(|_| Error::SlatepackSer)?,
)?; )?;
} }
} else { } else {
pub_tx.write_all( pub_tx.write_all(
serde_json::to_string_pretty(&slatepack) serde_json::to_string_pretty(&slatepack)
.map_err(|_| ErrorKind::SlateSer)? .map_err(|_| Error::SlateSer)?
.as_bytes(), .as_bytes(),
)?; )?;
} }

View file

@ -31,8 +31,8 @@ use crate::store::{self, option_to_not_found, to_key, to_key_u64};
use crate::core::core::Transaction; use crate::core::core::Transaction;
use crate::core::ser; use crate::core::ser;
use crate::libwallet::{ use crate::libwallet::{
AcctPathMapping, Context, Error, ErrorKind, NodeClient, OutputData, ScannedBlockInfo, AcctPathMapping, Context, Error, NodeClient, OutputData, ScannedBlockInfo, TxLogEntry,
TxLogEntry, WalletBackend, WalletInitStatus, WalletOutputBatch, WalletBackend, WalletInitStatus, WalletOutputBatch,
}; };
use crate::util::secp::constants::SECRET_KEY_SIZE; use crate::util::secp::constants::SECRET_KEY_SIZE;
use crate::util::secp::key::SecretKey; use crate::util::secp::key::SecretKey;
@ -238,11 +238,11 @@ where
hasher.update(&root_key.0[..]); hasher.update(&root_key.0[..]);
if *self.master_checksum != Some(hasher.finalize()) { if *self.master_checksum != Some(hasher.finalize()) {
error!("Supplied keychain mask is invalid"); error!("Supplied keychain mask is invalid");
return Err(ErrorKind::InvalidKeychainMask.into()); return Err(Error::InvalidKeychainMask);
} }
Ok(k_masked) Ok(k_masked)
} }
None => Err(ErrorKind::KeychainDoesntExist.into()), None => Err(Error::KeychainDoesntExist),
} }
} }
@ -281,7 +281,7 @@ where
self.set_parent_key_id(a.path); self.set_parent_key_id(a.path);
Ok(()) Ok(())
} else { } else {
Err(ErrorKind::UnknownAccountLabel(label).into()) Err(Error::UnknownAccountLabel(label))
} }
} }

View file

@ -15,13 +15,11 @@
//! High level JSON/HTTP client API //! High level JSON/HTTP client API
use crate::util::to_base64; use crate::util::to_base64;
use failure::{Backtrace, Context, Fail, ResultExt};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, AUTHORIZATION, CONTENT_TYPE, USER_AGENT}; use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, AUTHORIZATION, CONTENT_TYPE, USER_AGENT};
use reqwest::{ClientBuilder, Method, Proxy, RequestBuilder}; use reqwest::{ClientBuilder, Method, Proxy, RequestBuilder};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json; use serde_json;
use std::fmt::{self, Display};
use std::net::SocketAddr; use std::net::SocketAddr;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
@ -42,62 +40,20 @@ lazy_static! {
)); ));
} }
/// Errors that can be returned by an ApiEndpoint implementation. #[derive(Clone, Eq, thiserror::Error, PartialEq, Debug)]
#[derive(Debug)] pub enum Error {
pub struct Error { #[error("Internal error: {0}")]
inner: Context<ErrorKind>,
}
#[derive(Clone, Eq, PartialEq, Debug, Fail)]
pub enum ErrorKind {
#[fail(display = "Internal error: {}", _0)]
Internal(String), Internal(String),
#[fail(display = "Bad arguments: {}", _0)] #[error("Bad arguments: {0}")]
_Argument(String), _Argument(String),
#[fail(display = "Not found.")] #[error("Not found.")]
_NotFound, _NotFound,
#[fail(display = "Request error: {}", _0)] #[error("Request error: {0}")]
RequestError(String), RequestError(String),
#[fail(display = "ResponseError error: {}", _0)] #[error("ResponseError error: {0}")]
ResponseError(String), ResponseError(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 {
Display::fmt(&self.inner, f)
}
}
impl Error {
pub fn _kind(&self) -> &ErrorKind {
self.inner.get_context()
}
}
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 }
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct Client { pub struct Client {
client: reqwest::Client, client: reqwest::Client,
@ -126,13 +82,13 @@ impl Client {
if let Some(s) = socks_proxy_addr { if let Some(s) = socks_proxy_addr {
let proxy = Proxy::all(&format!("socks5h://{}:{}", s.ip(), s.port())) let proxy = Proxy::all(&format!("socks5h://{}:{}", s.ip(), s.port()))
.map_err(|e| ErrorKind::Internal(format!("Unable to create proxy: {}", e)))?; .map_err(|e| Error::Internal(format!("Unable to create proxy: {}", e)))?;
builder = builder.proxy(proxy); builder = builder.proxy(proxy);
} }
let client = builder let client = builder
.build() .build()
.map_err(|e| ErrorKind::Internal(format!("Unable to build client: {}", e)))?; .map_err(|e| Error::Internal(format!("Unable to build client: {}", e)))?;
Ok(Client { client }) Ok(Client { client })
} }
@ -273,9 +229,8 @@ impl Client {
where where
IN: Serialize, IN: Serialize,
{ {
let json = serde_json::to_string(input).context(ErrorKind::Internal( let json = serde_json::to_string(input)
"Could not serialize data to JSON".to_owned(), .map_err(|_| Error::Internal("Could not serialize data to JSON".to_owned()))?;
))?;
self.build_request(url, Method::POST, api_secret, Some(json)) self.build_request(url, Method::POST, api_secret, Some(json))
} }
@ -284,10 +239,8 @@ impl Client {
for<'de> T: Deserialize<'de>, for<'de> T: Deserialize<'de>,
{ {
let data = self.send_request(req)?; let data = self.send_request(req)?;
serde_json::from_str(&data).map_err(|e| { serde_json::from_str(&data)
e.context(ErrorKind::ResponseError("Cannot parse response".to_owned())) .map_err(|_| Error::ResponseError("Cannot parse response".to_owned()))
.into()
})
} }
async fn handle_request_async<T>(&self, req: RequestBuilder) -> Result<T, Error> async fn handle_request_async<T>(&self, req: RequestBuilder) -> Result<T, Error>
@ -296,7 +249,7 @@ impl Client {
{ {
let data = self.send_request_async(req).await?; let data = self.send_request_async(req).await?;
let ser = serde_json::from_str(&data) let ser = serde_json::from_str(&data)
.map_err(|e| e.context(ErrorKind::ResponseError("Cannot parse response".to_owned())))?; .map_err(|_| Error::ResponseError("Cannot parse response".to_owned()))?;
Ok(ser) Ok(ser)
} }
@ -304,11 +257,11 @@ impl Client {
let resp = req let resp = req
.send() .send()
.await .await
.map_err(|e| ErrorKind::RequestError(format!("Cannot make request: {}", e)))?; .map_err(|e| Error::RequestError(format!("Cannot make request: {}", e)))?;
let text = resp let text = resp
.text() .text()
.await .await
.map_err(|e| ErrorKind::ResponseError(format!("Cannot parse response: {}", e)))?; .map_err(|e| Error::ResponseError(format!("Cannot parse response: {}", e)))?;
Ok(text) Ok(text)
} }

View file

@ -15,4 +15,4 @@
mod client; mod client;
pub mod json_rpc; pub mod json_rpc;
pub use client::{Client, Error as ClientError, ErrorKind as ClientErrorKind, RUNTIME}; pub use client::{Client, Error as ClientError, RUNTIME};

View file

@ -17,194 +17,88 @@ use crate::core::libtx;
use crate::keychain; use crate::keychain;
use crate::libwallet; use crate::libwallet;
use crate::util::secp; use crate::util::secp;
use failure::{Backtrace, Context, Fail};
use grin_wallet_util::OnionV3AddressError; use grin_wallet_util::OnionV3AddressError;
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. /// Wallet errors, mostly wrappers around underlying crypto or I/O errors.
#[derive(Clone, Eq, PartialEq, Debug, Fail)] #[derive(Clone, thiserror::Error, Eq, PartialEq, Debug)]
pub enum ErrorKind { pub enum Error {
/// LibTX Error /// LibTX Error
#[fail(display = "LibTx Error")] #[error("LibTx Error")]
LibTX(libtx::ErrorKind), LibTX(#[from] libtx::Error),
/// LibWallet Error /// LibWallet Error
#[fail(display = "LibWallet Error: {}", _1)] #[error("LibWallet Error: {0}")]
LibWallet(libwallet::ErrorKind, String), LibWallet(#[from] libwallet::Error),
/// Keychain error /// Keychain error
#[fail(display = "Keychain error")] #[error("Keychain error")]
Keychain(keychain::Error), Keychain(#[from] keychain::Error),
/// Onion V3 Address Error /// Onion V3 Address Error
#[fail(display = "Onion V3 Address Error")] #[error("Onion V3 Address Error")]
OnionV3Address(OnionV3AddressError), OnionV3Address(#[from] OnionV3AddressError),
/// Error when obfs4proxy is not in the user path if TOR brigde is enabled /// Error when obfs4proxy is not in the user path if TOR brigde is enabled
#[fail(display = "Unable to find obfs4proxy binary in your path; {}", _0)] #[error("Unable to find obfs4proxy binary in your path; {}", _0)]
Obfs4proxyBin(String), Obfs4proxyBin(String),
/// Error the bridge input is in bad format /// Error the bridge input is in bad format
#[fail(display = "Bridge line is in bad format; {}", _0)] #[error("Bridge line is in bad format; {}", _0)]
BridgeLine(String), BridgeLine(String),
/// Error when formatting json /// Error when formatting json
#[fail(display = "IO error")] #[error("IO error")]
IO, IO,
/// Secp Error /// Secp Error
#[fail(display = "Secp error")] #[error("Secp error")]
Secp(secp::Error), Secp(#[from] secp::Error),
/// Error when formatting json /// Error when formatting json
#[fail(display = "Serde JSON error")] #[error("Serde JSON error")]
Format, Format,
/// Wallet seed already exists /// Wallet seed already exists
#[fail(display = "Wallet seed file exists: {}", _0)] #[error("Wallet seed file exists: {}", _0)]
WalletSeedExists(String), WalletSeedExists(String),
/// Wallet seed doesn't exist /// Wallet seed doesn't exist
#[fail(display = "Wallet seed doesn't exist error")] #[error("Wallet seed doesn't exist error")]
WalletSeedDoesntExist, WalletSeedDoesntExist,
/// Wallet seed doesn't exist /// Wallet seed doesn't exist
#[fail(display = "Wallet doesn't exist at {}. {}", _0, _1)] #[error("Wallet doesn't exist at {}. {}", _0, _1)]
WalletDoesntExist(String, String), WalletDoesntExist(String, String),
/// Enc/Decryption Error /// Enc/Decryption Error
#[fail(display = "Enc/Decryption error (check password?)")] #[error("Enc/Decryption error (check password?)")]
Encryption, Encryption,
/// BIP 39 word list /// BIP 39 word list
#[fail(display = "BIP39 Mnemonic (word list) Error")] #[error("BIP39 Mnemonic (word list) Error")]
Mnemonic, Mnemonic,
/// Command line argument error /// Command line argument error
#[fail(display = "{}", _0)] #[error("{}", _0)]
ArgumentError(String), ArgumentError(String),
/// Tor Bridge error /// Tor Bridge error
#[fail(display = "Tor Bridge Error: {}", _0)] #[error("Tor Bridge Error: {}", _0)]
TorBridge(String), TorBridge(String),
/// Tor Proxy error /// Tor Proxy error
#[fail(display = "Tor Proxy Error: {}", _0)] #[error("Tor Proxy Error: {}", _0)]
TorProxy(String), TorProxy(String),
/// Generating ED25519 Public Key /// Generating ED25519 Public Key
#[fail(display = "Error generating ed25519 secret key: {}", _0)] #[error("Error generating ed25519 secret key: {}", _0)]
ED25519Key(String), ED25519Key(String),
/// Checking for onion address /// Checking for onion address
#[fail(display = "Address is not an Onion v3 Address: {}", _0)] #[error("Address is not an Onion v3 Address: {}", _0)]
NotOnion(String), NotOnion(String),
/// Other /// Other
#[fail(display = "Generic error: {}", _0)] #[error("Generic error: {}", _0)]
GenericError(String), 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) => r == "1",
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;
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<keychain::Error> for Error {
fn from(error: keychain::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Keychain(error)),
}
}
}
impl From<secp::Error> for Error {
fn from(error: secp::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Secp(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<OnionV3AddressError> for Error {
fn from(error: OnionV3AddressError) -> Error {
Error::from(ErrorKind::OnionV3Address(error))
}
}

View file

@ -48,7 +48,7 @@ pub use crate::adapters::{
SlateSender, SlateSender,
}; };
pub use crate::backends::{wallet_db_exists, LMDBBackend}; pub use crate::backends::{wallet_db_exists, LMDBBackend};
pub use crate::error::{Error, ErrorKind}; pub use crate::error::Error;
pub use crate::lifecycle::DefaultLCProvider; pub use crate::lifecycle::DefaultLCProvider;
pub use crate::node_clients::HTTPNodeClient; pub use crate::node_clients::HTTPNodeClient;

View file

@ -19,14 +19,11 @@ use crate::config::{
}; };
use crate::core::global; use crate::core::global;
use crate::keychain::Keychain; use crate::keychain::Keychain;
use crate::libwallet::{ use crate::libwallet::{Error, NodeClient, WalletBackend, WalletInitStatus, WalletLCProvider};
Error, ErrorKind, NodeClient, WalletBackend, WalletInitStatus, WalletLCProvider,
};
use crate::lifecycle::seed::WalletSeed; use crate::lifecycle::seed::WalletSeed;
use crate::util::secp::key::SecretKey; use crate::util::secp::key::SecretKey;
use crate::util::ZeroingString; use crate::util::ZeroingString;
use crate::LMDBBackend; use crate::LMDBBackend;
use failure::ResultExt;
use grin_wallet_util::grin_util::logger::LoggingConfig; use grin_wallet_util::grin_util::logger::LoggingConfig;
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
@ -132,7 +129,7 @@ where
file_name, file_name,
config_file_name.to_str().unwrap() config_file_name.to_str().unwrap()
); );
return Err(ErrorKind::Lifecycle(msg).into()); return Err(Error::Lifecycle(msg));
} }
// just leave as is if file exists but there's no data dir // just leave as is if file exists but there's no data dir
@ -152,7 +149,7 @@ where
config_file_name.to_str().unwrap(), config_file_name.to_str().unwrap(),
e e
); );
return Err(ErrorKind::Lifecycle(msg).into()); return Err(Error::Lifecycle(msg));
} }
info!( info!(
@ -186,7 +183,7 @@ where
if !test_mode { if !test_mode {
if let Ok(true) = exists { if let Ok(true) = exists {
let msg = format!("Wallet seed already exists at: {}", data_dir_name); let msg = format!("Wallet seed already exists at: {}", data_dir_name);
return Err(ErrorKind::WalletSeedExists(msg).into()); return Err(Error::WalletSeedExists(msg));
} }
} }
WalletSeed::init_file( WalletSeed::init_file(
@ -196,16 +193,16 @@ where
password, password,
test_mode, test_mode,
) )
.context(ErrorKind::Lifecycle( .map_err(|_| {
"Error creating wallet seed (is mnemonic valid?)".into(), Error::Lifecycle("Error creating wallet seed (is mnemonic valid?)".to_owned())
))?; })?;
info!("Wallet seed file created"); info!("Wallet seed file created");
let mut wallet: LMDBBackend<'a, C, K> = let mut wallet: LMDBBackend<'a, C, K> =
match LMDBBackend::new(&data_dir_name, self.node_client.clone()) { match LMDBBackend::new(&data_dir_name, self.node_client.clone()) {
Err(e) => { Err(e) => {
let msg = format!("Error creating wallet: {}, Data Dir: {}", e, &data_dir_name); let msg = format!("Error creating wallet: {}, Data Dir: {}", e, &data_dir_name);
error!("{}", msg); error!("{}", msg);
return Err(ErrorKind::Lifecycle(msg).into()); return Err(Error::Lifecycle(msg).into());
} }
Ok(d) => d, Ok(d) => d,
}; };
@ -234,16 +231,16 @@ where
match LMDBBackend::new(&data_dir_name, self.node_client.clone()) { match LMDBBackend::new(&data_dir_name, self.node_client.clone()) {
Err(e) => { Err(e) => {
let msg = format!("Error opening wallet: {}, Data Dir: {}", e, &data_dir_name); let msg = format!("Error opening wallet: {}, Data Dir: {}", e, &data_dir_name);
return Err(ErrorKind::Lifecycle(msg).into()); return Err(Error::Lifecycle(msg));
} }
Ok(d) => d, Ok(d) => d,
}; };
let wallet_seed = WalletSeed::from_file(&data_dir_name, password).context( let wallet_seed = WalletSeed::from_file(&data_dir_name, password).map_err(|_| {
ErrorKind::Lifecycle("Error opening wallet (is password correct?)".into()), Error::Lifecycle("Error opening wallet (is password correct?)".to_owned())
)?; })?;
let keychain = wallet_seed let keychain = wallet_seed
.derive_keychain(global::is_testnet()) .derive_keychain(global::is_testnet())
.context(ErrorKind::Lifecycle("Error deriving keychain".into()))?; .map_err(|_| Error::Lifecycle("Error deriving keychain".to_owned()))?;
let mask = wallet.set_keychain(Box::new(keychain), create_mask, use_test_rng)?; let mask = wallet.set_keychain(Box::new(keychain), create_mask, use_test_rng)?;
self.backend = Some(Box::new(wallet)); self.backend = Some(Box::new(wallet));
@ -262,9 +259,8 @@ where
let mut data_dir_name = PathBuf::from(self.data_dir.clone()); let mut data_dir_name = PathBuf::from(self.data_dir.clone());
data_dir_name.push(GRIN_WALLET_DIR); data_dir_name.push(GRIN_WALLET_DIR);
let data_dir_name = data_dir_name.to_str().unwrap(); let data_dir_name = data_dir_name.to_str().unwrap();
let res = WalletSeed::seed_file_exists(&data_dir_name).context(ErrorKind::CallbackImpl( let res = WalletSeed::seed_file_exists(&data_dir_name)
"Error checking for wallet existence", .map_err(|_| Error::CallbackImpl("Error checking for wallet existence"))?;
))?;
Ok(res) Ok(res)
} }
@ -276,19 +272,18 @@ where
let mut data_dir_name = PathBuf::from(self.data_dir.clone()); let mut data_dir_name = PathBuf::from(self.data_dir.clone());
data_dir_name.push(GRIN_WALLET_DIR); data_dir_name.push(GRIN_WALLET_DIR);
let data_dir_name = data_dir_name.to_str().unwrap(); let data_dir_name = data_dir_name.to_str().unwrap();
let wallet_seed = WalletSeed::from_file(&data_dir_name, password).context( let wallet_seed = WalletSeed::from_file(&data_dir_name, password)
ErrorKind::Lifecycle("Error opening wallet seed file".into()), .map_err(|_| Error::Lifecycle("Error opening wallet seed file".into()))?;
)?;
let res = wallet_seed let res = wallet_seed
.to_mnemonic() .to_mnemonic()
.context(ErrorKind::Lifecycle("Error recovering wallet seed".into()))?; .map_err(|_| Error::Lifecycle("Error recovering wallet seed".into()))?;
Ok(ZeroingString::from(res)) Ok(ZeroingString::from(res))
} }
fn validate_mnemonic(&self, mnemonic: ZeroingString) -> Result<(), Error> { fn validate_mnemonic(&self, mnemonic: ZeroingString) -> Result<(), Error> {
match WalletSeed::from_mnemonic(mnemonic) { match WalletSeed::from_mnemonic(mnemonic) {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(_) => Err(ErrorKind::GenericError("Validating mnemonic".into()).into()), Err(_) => Err(Error::GenericError("Validating mnemonic".into())),
} }
} }
@ -300,9 +295,8 @@ where
let mut data_dir_name = PathBuf::from(self.data_dir.clone()); let mut data_dir_name = PathBuf::from(self.data_dir.clone());
data_dir_name.push(GRIN_WALLET_DIR); data_dir_name.push(GRIN_WALLET_DIR);
let data_dir_name = data_dir_name.to_str().unwrap(); let data_dir_name = data_dir_name.to_str().unwrap();
WalletSeed::recover_from_phrase(data_dir_name, mnemonic, password).context( WalletSeed::recover_from_phrase(data_dir_name, mnemonic, password)
ErrorKind::Lifecycle("Error recovering from mnemonic".into()), .map_err(|_| Error::Lifecycle("Error recovering from mnemonic".into()))?;
)?;
Ok(()) Ok(())
} }
@ -317,23 +311,21 @@ where
let data_dir_name = data_dir_name.to_str().unwrap(); let data_dir_name = data_dir_name.to_str().unwrap();
// get seed for later check // get seed for later check
let orig_wallet_seed = WalletSeed::from_file(&data_dir_name, old).context( let orig_wallet_seed = WalletSeed::from_file(&data_dir_name, old)
ErrorKind::Lifecycle("Error opening wallet seed file".into()), .map_err(|_| Error::Lifecycle("Error opening wallet seed file".into()))?;
)?;
let orig_mnemonic = orig_wallet_seed let orig_mnemonic = orig_wallet_seed
.to_mnemonic() .to_mnemonic()
.context(ErrorKind::Lifecycle("Error recovering mnemonic".into()))?; .map_err(|_| Error::Lifecycle("Error recovering mnemonic".into()))?;
// Back up existing seed, and keep track of filename as we're deleting it // Back up existing seed, and keep track of filename as we're deleting it
// once the password change is confirmed // once the password change is confirmed
let backup_name = WalletSeed::backup_seed(data_dir_name).context(ErrorKind::Lifecycle( let backup_name = WalletSeed::backup_seed(data_dir_name)
"Error temporarily backing up existing seed".into(), .map_err(|_| Error::Lifecycle("Error temporarily backing up existing seed".into()))?;
))?;
// Delete seed file // Delete seed file
WalletSeed::delete_seed_file(data_dir_name).context(ErrorKind::Lifecycle( WalletSeed::delete_seed_file(data_dir_name).map_err(|_| {
"Unable to delete seed file for password change".into(), Error::Lifecycle("Unable to delete seed file for password change".into())
))?; })?;
// Init a new file // Init a new file
let _ = WalletSeed::init_file( let _ = WalletSeed::init_file(
@ -345,19 +337,18 @@ where
); );
info!("Wallet seed file created"); info!("Wallet seed file created");
let new_wallet_seed = WalletSeed::from_file(&data_dir_name, new).context( let new_wallet_seed = WalletSeed::from_file(&data_dir_name, new)
ErrorKind::Lifecycle("Error opening wallet seed file".into()), .map_err(|_| Error::Lifecycle("Error opening wallet seed file".into()))?;
)?;
if orig_wallet_seed != new_wallet_seed { if orig_wallet_seed != new_wallet_seed {
let msg = let msg =
"New and Old wallet seeds are not equal on password change, not removing backups." "New and Old wallet seeds are not equal on password change, not removing backups."
.to_string(); .to_string();
return Err(ErrorKind::Lifecycle(msg).into()); return Err(Error::Lifecycle(msg));
} }
// Removin // Removin
info!("Password change confirmed, removing old seed file."); info!("Password change confirmed, removing old seed file.");
fs::remove_file(backup_name).context(ErrorKind::IO)?; fs::remove_file(backup_name).map_err(|e| Error::IO(e.to_string()))?;
Ok(()) Ok(())
} }
@ -368,7 +359,7 @@ where
"Removing all wallet data from: {}", "Removing all wallet data from: {}",
data_dir_name.to_str().unwrap() data_dir_name.to_str().unwrap()
); );
fs::remove_dir_all(data_dir_name).context(ErrorKind::IO)?; fs::remove_dir_all(data_dir_name).map_err(|e| Error::IO(e.to_string()))?;
Ok(()) Ok(())
} }
@ -376,7 +367,7 @@ where
match self.backend.as_mut() { match self.backend.as_mut() {
None => { None => {
let msg = "Wallet has not been opened".into(); let msg = "Wallet has not been opened".into();
Err(ErrorKind::Lifecycle(msg).into()) Err(Error::Lifecycle(msg))
} }
Some(_) => Ok(&mut *self.backend.as_mut().unwrap()), Some(_) => Ok(&mut *self.backend.as_mut().unwrap()),
} }

View file

@ -27,8 +27,7 @@ use ring::pbkdf2;
use crate::keychain::{mnemonic, Keychain}; use crate::keychain::{mnemonic, Keychain};
use crate::util::{self, ToHex}; use crate::util::{self, ToHex};
use crate::{Error, ErrorKind}; use crate::Error;
use failure::ResultExt;
pub const SEED_FILE: &str = "wallet.seed"; pub const SEED_FILE: &str = "wallet.seed";
@ -44,13 +43,13 @@ impl WalletSeed {
let res = mnemonic::to_entropy(&word_list); let res = mnemonic::to_entropy(&word_list);
match res { match res {
Ok(s) => Ok(WalletSeed::from_bytes(&s)), Ok(s) => Ok(WalletSeed::from_bytes(&s)),
Err(_) => Err(ErrorKind::Mnemonic.into()), Err(_) => Err(Error::Mnemonic.into()),
} }
} }
pub fn _from_hex(hex: &str) -> Result<WalletSeed, Error> { pub fn _from_hex(hex: &str) -> Result<WalletSeed, Error> {
let bytes = util::from_hex(&hex.to_string()) let bytes = util::from_hex(&hex.to_string())
.map_err(|_| ErrorKind::GenericError("Invalid hex".to_owned()))?; .map_err(|_| Error::GenericError("Invalid hex".to_owned()))?;
Ok(WalletSeed::from_bytes(&bytes)) Ok(WalletSeed::from_bytes(&bytes))
} }
@ -62,7 +61,7 @@ impl WalletSeed {
let result = mnemonic::from_entropy(&self.0); let result = mnemonic::from_entropy(&self.0);
match result { match result {
Ok(r) => Ok(r), Ok(r) => Ok(r),
Err(_) => Err(ErrorKind::Mnemonic.into()), Err(_) => Err(Error::Mnemonic.into()),
} }
} }
@ -122,7 +121,7 @@ impl WalletSeed {
} }
path.push(backup_seed_file_name.clone()); path.push(backup_seed_file_name.clone());
if fs::rename(seed_file_name, backup_seed_file_name.as_str()).is_err() { if fs::rename(seed_file_name, backup_seed_file_name.as_str()).is_err() {
return Err(ErrorKind::GenericError("Can't rename wallet seed file".to_owned()).into()); return Err(Error::GenericError("Can't rename wallet seed file".to_owned()).into());
} }
warn!("{} backed up as {}", seed_file_name, backup_seed_file_name); warn!("{} backed up as {}", seed_file_name, backup_seed_file_name);
Ok(backup_seed_file_name) Ok(backup_seed_file_name)
@ -140,7 +139,7 @@ impl WalletSeed {
WalletSeed::backup_seed(data_file_dir)?; WalletSeed::backup_seed(data_file_dir)?;
} }
if !Path::new(&data_file_dir).exists() { if !Path::new(&data_file_dir).exists() {
return Err(ErrorKind::WalletDoesntExist( return Err(Error::WalletDoesntExist(
data_file_dir.to_owned(), data_file_dir.to_owned(),
"To create a new wallet from a recovery phrase, use 'grin-wallet init -r'" "To create a new wallet from a recovery phrase, use 'grin-wallet init -r'"
.to_owned(), .to_owned(),
@ -149,10 +148,10 @@ impl WalletSeed {
} }
let seed = WalletSeed::from_mnemonic(word_list)?; let seed = WalletSeed::from_mnemonic(word_list)?;
let enc_seed = EncryptedWalletSeed::from_seed(&seed, password)?; let enc_seed = EncryptedWalletSeed::from_seed(&seed, password)?;
let enc_seed_json = serde_json::to_string_pretty(&enc_seed).context(ErrorKind::Format)?; let enc_seed_json = serde_json::to_string_pretty(&enc_seed).map_err(|_| Error::Format)?;
let mut file = File::create(seed_file_path).context(ErrorKind::IO)?; let mut file = File::create(seed_file_path).map_err(|_| Error::IO)?;
file.write_all(&enc_seed_json.as_bytes()) file.write_all(&enc_seed_json.as_bytes())
.context(ErrorKind::IO)?; .map_err(|_| Error::IO)?;
warn!("Seed created from word list"); warn!("Seed created from word list");
Ok(()) Ok(())
} }
@ -165,7 +164,7 @@ impl WalletSeed {
test_mode: bool, test_mode: bool,
) -> Result<WalletSeed, Error> { ) -> Result<WalletSeed, Error> {
// create directory if it doesn't exist // create directory if it doesn't exist
fs::create_dir_all(data_file_dir).context(ErrorKind::IO)?; fs::create_dir_all(data_file_dir).map_err(|_| Error::IO)?;
let seed_file_path = &format!("{}{}{}", data_file_dir, MAIN_SEPARATOR, SEED_FILE,); let seed_file_path = &format!("{}{}{}", data_file_dir, MAIN_SEPARATOR, SEED_FILE,);
@ -174,7 +173,7 @@ impl WalletSeed {
if exists && !test_mode { if exists && !test_mode {
let msg = format!("Wallet seed already exists at: {}", data_file_dir); let msg = format!("Wallet seed already exists at: {}", data_file_dir);
error!("{}", msg); error!("{}", msg);
return Err(ErrorKind::WalletSeedExists(msg).into()); return Err(Error::WalletSeedExists(msg));
} }
let seed = match recovery_phrase { let seed = match recovery_phrase {
@ -183,10 +182,10 @@ impl WalletSeed {
}; };
let enc_seed = EncryptedWalletSeed::from_seed(&seed, password)?; let enc_seed = EncryptedWalletSeed::from_seed(&seed, password)?;
let enc_seed_json = serde_json::to_string_pretty(&enc_seed).context(ErrorKind::Format)?; let enc_seed_json = serde_json::to_string_pretty(&enc_seed).map_err(|_| Error::Format)?;
let mut file = File::create(seed_file_path).context(ErrorKind::IO)?; let mut file = File::create(seed_file_path).map_err(|_| Error::IO)?;
file.write_all(&enc_seed_json.as_bytes()) file.write_all(&enc_seed_json.as_bytes())
.context(ErrorKind::IO)?; .map_err(|_| Error::IO)?;
Ok(seed) Ok(seed)
} }
@ -195,18 +194,18 @@ impl WalletSeed {
password: util::ZeroingString, password: util::ZeroingString,
) -> Result<WalletSeed, Error> { ) -> Result<WalletSeed, Error> {
// create directory if it doesn't exist // create directory if it doesn't exist
fs::create_dir_all(data_file_dir).context(ErrorKind::IO)?; fs::create_dir_all(data_file_dir).map_err(|_| Error::IO)?;
let seed_file_path = &format!("{}{}{}", data_file_dir, MAIN_SEPARATOR, SEED_FILE,); let seed_file_path = &format!("{}{}{}", data_file_dir, MAIN_SEPARATOR, SEED_FILE,);
debug!("Using wallet seed file at: {}", seed_file_path); debug!("Using wallet seed file at: {}", seed_file_path);
if Path::new(seed_file_path).exists() { if Path::new(seed_file_path).exists() {
let mut file = File::open(seed_file_path).context(ErrorKind::IO)?; let mut file = File::open(seed_file_path).map_err(|_| Error::IO)?;
let mut buffer = String::new(); let mut buffer = String::new();
file.read_to_string(&mut buffer).context(ErrorKind::IO)?; file.read_to_string(&mut buffer).map_err(|_| Error::IO)?;
let enc_seed: EncryptedWalletSeed = let enc_seed: EncryptedWalletSeed =
serde_json::from_str(&buffer).context(ErrorKind::Format)?; serde_json::from_str(&buffer).map_err(|_| Error::Format)?;
let wallet_seed = enc_seed.decrypt(&password)?; let wallet_seed = enc_seed.decrypt(&password)?;
Ok(wallet_seed) Ok(wallet_seed)
} else { } else {
@ -215,7 +214,7 @@ impl WalletSeed {
Run \"grin-wallet init\" to initialize a new wallet.", Run \"grin-wallet init\" to initialize a new wallet.",
seed_file_path seed_file_path
); );
Err(ErrorKind::WalletSeedDoesntExist.into()) Err(Error::WalletSeedDoesntExist)
} }
} }
@ -223,7 +222,7 @@ impl WalletSeed {
let seed_file_path = &format!("{}{}{}", data_file_dir, MAIN_SEPARATOR, SEED_FILE,); let seed_file_path = &format!("{}{}{}", data_file_dir, MAIN_SEPARATOR, SEED_FILE,);
if Path::new(seed_file_path).exists() { if Path::new(seed_file_path).exists() {
debug!("Deleting wallet seed file at: {}", seed_file_path); debug!("Deleting wallet seed file at: {}", seed_file_path);
fs::remove_file(seed_file_path).context(ErrorKind::IO)?; fs::remove_file(seed_file_path).map_err(|_| Error::IO)?;
} }
Ok(()) Ok(())
} }
@ -274,7 +273,7 @@ impl EncryptedWalletSeed {
&mut enc_bytes, &mut enc_bytes,
); );
if let Err(_) = res { if let Err(_) = res {
return Err(ErrorKind::Encryption.into()); return Err(Error::Encryption);
} }
Ok(EncryptedWalletSeed { Ok(EncryptedWalletSeed {
@ -288,15 +287,15 @@ impl EncryptedWalletSeed {
pub fn decrypt(&self, password: &str) -> Result<WalletSeed, Error> { pub fn decrypt(&self, password: &str) -> Result<WalletSeed, Error> {
let mut encrypted_seed = match util::from_hex(&self.encrypted_seed.clone()) { let mut encrypted_seed = match util::from_hex(&self.encrypted_seed.clone()) {
Ok(s) => s, Ok(s) => s,
Err(_) => return Err(ErrorKind::Encryption.into()), Err(_) => return Err(Error::Encryption),
}; };
let salt = match util::from_hex(&self.salt.clone()) { let salt = match util::from_hex(&self.salt.clone()) {
Ok(s) => s, Ok(s) => s,
Err(_) => return Err(ErrorKind::Encryption.into()), Err(_) => return Err(Error::Encryption),
}; };
let nonce = match util::from_hex(&self.nonce.clone()) { let nonce = match util::from_hex(&self.nonce.clone()) {
Ok(s) => s, Ok(s) => s,
Err(_) => return Err(ErrorKind::Encryption.into()), Err(_) => return Err(Error::Encryption),
}; };
let password = password.as_bytes(); let password = password.as_bytes();
let mut key = [0; 32]; let mut key = [0; 32];
@ -319,7 +318,7 @@ impl EncryptedWalletSeed {
&mut encrypted_seed, &mut encrypted_seed,
); );
if let Err(_) = res { if let Err(_) = res {
return Err(ErrorKind::Encryption.into()); return Err(Error::Encryption);
} }
for _ in 0..aead::AES_256_GCM.tag_len() { for _ in 0..aead::AES_256_GCM.tag_len() {
encrypted_seed.pop(); encrypted_seed.pop();

View file

@ -47,7 +47,7 @@ impl HTTPNodeClient {
node_api_secret: Option<String>, node_api_secret: Option<String>,
) -> Result<HTTPNodeClient, libwallet::Error> { ) -> Result<HTTPNodeClient, libwallet::Error> {
Ok(HTTPNodeClient { Ok(HTTPNodeClient {
client: Client::new().map_err(|_| libwallet::ErrorKind::Node)?, client: Client::new().map_err(|_| libwallet::Error::Node)?,
node_url: node_url.to_owned(), node_url: node_url.to_owned(),
node_api_secret: node_api_secret, node_api_secret: node_api_secret,
node_version_info: None, node_version_info: None,
@ -74,7 +74,7 @@ impl HTTPNodeClient {
Err(e) => { Err(e) => {
let report = format!("Error calling {}: {}", method, e); let report = format!("Error calling {}: {}", method, e);
error!("{}", report); error!("{}", report);
Err(libwallet::ErrorKind::ClientCallback(report).into()) Err(libwallet::Error::ClientCallback(report))
} }
Ok(inner) => match inner.clone().into_result() { Ok(inner) => match inner.clone().into_result() {
Ok(r) => Ok(r), Ok(r) => Ok(r),
@ -82,7 +82,7 @@ impl HTTPNodeClient {
error!("{:?}", inner); error!("{:?}", inner);
let report = format!("Unable to parse response for {}: {}", method, e); let report = format!("Unable to parse response for {}: {}", method, e);
error!("{}", report); error!("{}", report);
Err(libwallet::ErrorKind::ClientCallback(report).into()) Err(libwallet::Error::ClientCallback(report))
} }
}, },
} }
@ -170,7 +170,7 @@ impl NodeClient for HTTPNodeClient {
Err(e) => { Err(e) => {
let report = format!("Error calling {}: {}", method, e); let report = format!("Error calling {}: {}", method, e);
error!("{}", report); error!("{}", report);
Err(libwallet::ErrorKind::ClientCallback(report).into()) Err(libwallet::Error::ClientCallback(report))
} }
Ok(inner) => match inner.clone().into_result::<LocatedTxKernel>() { Ok(inner) => match inner.clone().into_result::<LocatedTxKernel>() {
Ok(r) => Ok(Some((r.tx_kernel, r.height, r.mmr_index))), Ok(r) => Ok(Some((r.tx_kernel, r.height, r.mmr_index))),
@ -181,7 +181,7 @@ impl NodeClient for HTTPNodeClient {
} else { } else {
let report = format!("Unable to parse response for {}: {}", method, e); let report = format!("Unable to parse response for {}: {}", method, e);
error!("{}", report); error!("{}", report);
Err(libwallet::ErrorKind::ClientCallback(report).into()) Err(libwallet::Error::ClientCallback(report))
} }
} }
}, },
@ -270,7 +270,7 @@ impl NodeClient for HTTPNodeClient {
Err(e) => { Err(e) => {
let report = format!("Unable to parse response for get_outputs: {}", e); let report = format!("Unable to parse response for get_outputs: {}", e);
error!("{}", report); error!("{}", report);
return Err(libwallet::ErrorKind::ClientCallback(report).into()); return Err(libwallet::Error::ClientCallback(report));
} }
}; };
} }
@ -279,7 +279,7 @@ impl NodeClient for HTTPNodeClient {
Err(e) => { Err(e) => {
let report = format!("Getting outputs by id: {}", e); let report = format!("Getting outputs by id: {}", e);
error!("Outputs by id failed: {}", e); error!("Outputs by id failed: {}", e);
return Err(libwallet::ErrorKind::ClientCallback(report).into()); return Err(libwallet::Error::ClientCallback(report));
} }
}; };
@ -288,7 +288,7 @@ impl NodeClient for HTTPNodeClient {
Some(h) => h, Some(h) => h,
None => { None => {
let msg = format!("Missing block height for output {:?}", out.commit); let msg = format!("Missing block height for output {:?}", out.commit);
return Err(libwallet::ErrorKind::ClientCallback(msg).into()); return Err(libwallet::Error::ClientCallback(msg));
} }
}; };
api_outputs.insert( api_outputs.insert(
@ -331,7 +331,7 @@ impl NodeClient for HTTPNodeClient {
out.commit, out, e out.commit, out, e
); );
error!("{}", msg); error!("{}", msg);
return Err(libwallet::ErrorKind::ClientCallback(msg).into()); return Err(libwallet::Error::ClientCallback(msg));
} }
}; };
let block_height = match out.block_height { let block_height = match out.block_height {
@ -342,7 +342,7 @@ impl NodeClient for HTTPNodeClient {
out.commit, out out.commit, out
); );
error!("{}", msg); error!("{}", msg);
return Err(libwallet::ErrorKind::ClientCallback(msg).into()); return Err(libwallet::Error::ClientCallback(msg));
} }
}; };
api_outputs.push(( api_outputs.push((

View file

@ -32,7 +32,6 @@ use crate::util::secp::key::SecretKey;
use crate::util::secp::pedersen; use crate::util::secp::pedersen;
use crate::util::secp::pedersen::Commitment; use crate::util::secp::pedersen::Commitment;
use crate::util::{Mutex, ToHex}; use crate::util::{Mutex, ToHex};
use failure::ResultExt;
use serde_json; use serde_json;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
@ -181,9 +180,9 @@ where
fn post_tx(&mut self, m: WalletProxyMessage) -> Result<WalletProxyMessage, libwallet::Error> { fn post_tx(&mut self, m: WalletProxyMessage) -> Result<WalletProxyMessage, libwallet::Error> {
let dest_wallet = self.wallets.get_mut(&m.sender_id).unwrap().1.clone(); let dest_wallet = self.wallets.get_mut(&m.sender_id).unwrap().1.clone();
let dest_wallet_mask = self.wallets.get_mut(&m.sender_id).unwrap().2.clone(); let dest_wallet_mask = self.wallets.get_mut(&m.sender_id).unwrap().2.clone();
let tx: Transaction = serde_json::from_str(&m.body).context( let tx: Transaction = serde_json::from_str(&m.body).map_err(|_| {
libwallet::ErrorKind::ClientCallback("Error parsing Transaction".to_owned()), libwallet::Error::ClientCallback("Error parsing Transaction".to_owned())
)?; })?;
super::award_block_to_wallet( super::award_block_to_wallet(
&self.chain, &self.chain,
@ -211,9 +210,8 @@ where
Some(w) => w, Some(w) => w,
}; };
let slate: SlateV4 = serde_json::from_str(&m.body).context( let slate: SlateV4 = serde_json::from_str(&m.body)
libwallet::ErrorKind::ClientCallback("Error parsing TxWrapper".to_owned()), .map_err(|_| libwallet::Error::ClientCallback("Error parsing TxWrapper".to_owned()))?;
)?;
let slate: Slate = { let slate: Slate = {
let mut w_lock = wallet.1.lock(); let mut w_lock = wallet.1.lock();
@ -403,16 +401,15 @@ impl LocalWalletClient {
}; };
{ {
let p = self.proxy_tx.lock(); let p = self.proxy_tx.lock();
p.send(m).context(libwallet::ErrorKind::ClientCallback( p.send(m)
"Send TX Slate".to_owned(), .map_err(|_| libwallet::Error::ClientCallback("Send TX Slate".to_owned()))?;
))?;
} }
let r = self.rx.lock(); let r = self.rx.lock();
let m = r.recv().unwrap(); let m = r.recv().unwrap();
trace!("Received send_tx_slate response: {:?}", m.clone()); trace!("Received send_tx_slate response: {:?}", m.clone());
let slate: SlateV4 = serde_json::from_str(&m.body).context( let slate: SlateV4 = serde_json::from_str(&m.body).map_err(|_| {
libwallet::ErrorKind::ClientCallback("Parsing send_tx_slate response".to_owned()), libwallet::Error::ClientCallback("Parsing send_tx_slate response".to_owned())
)?; })?;
Ok(Slate::from(slate)) Ok(Slate::from(slate))
} }
} }
@ -440,9 +437,8 @@ impl NodeClient for LocalWalletClient {
}; };
{ {
let p = self.proxy_tx.lock(); let p = self.proxy_tx.lock();
p.send(m).context(libwallet::ErrorKind::ClientCallback( p.send(m)
"post_tx send".to_owned(), .map_err(|_| libwallet::Error::ClientCallback("post_tx send".to_owned()))?;
))?;
} }
let r = self.rx.lock(); let r = self.rx.lock();
let m = r.recv().unwrap(); let m = r.recv().unwrap();
@ -460,19 +456,16 @@ impl NodeClient for LocalWalletClient {
}; };
{ {
let p = self.proxy_tx.lock(); let p = self.proxy_tx.lock();
p.send(m).context(libwallet::ErrorKind::ClientCallback( p.send(m).map_err(|_| {
"Get chain height send".to_owned(), libwallet::Error::ClientCallback("Get chain height send".to_owned())
))?; })?;
} }
let r = self.rx.lock(); let r = self.rx.lock();
let m = r.recv().unwrap(); let m = r.recv().unwrap();
trace!("Received get_chain_tip response: {:?}", m.clone()); trace!("Received get_chain_tip response: {:?}", m.clone());
let res = m let res = m.body.parse::<String>().map_err(|_| {
.body libwallet::Error::ClientCallback("Parsing get_height response".to_owned())
.parse::<String>() })?;
.context(libwallet::ErrorKind::ClientCallback(
"Parsing get_height response".to_owned(),
))?;
let split: Vec<&str> = res.split(',').collect(); let split: Vec<&str> = res.split(',').collect();
Ok((split[0].parse::<u64>().unwrap(), split[1].to_owned())) Ok((split[0].parse::<u64>().unwrap(), split[1].to_owned()))
} }
@ -495,9 +488,9 @@ impl NodeClient for LocalWalletClient {
}; };
{ {
let p = self.proxy_tx.lock(); let p = self.proxy_tx.lock();
p.send(m).context(libwallet::ErrorKind::ClientCallback( p.send(m).map_err(|_| {
"Get outputs from node send".to_owned(), libwallet::Error::ClientCallback("Get outputs from node send".to_owned())
))?; })?;
} }
let r = self.rx.lock(); let r = self.rx.lock();
let m = r.recv().unwrap(); let m = r.recv().unwrap();
@ -538,15 +531,17 @@ impl NodeClient for LocalWalletClient {
}; };
{ {
let p = self.proxy_tx.lock(); let p = self.proxy_tx.lock();
p.send(m).context(libwallet::ErrorKind::ClientCallback( p.send(m).map_err(|_| {
libwallet::Error::ClientCallback(
"Get outputs from node by PMMR index send".to_owned(), "Get outputs from node by PMMR index send".to_owned(),
))?; )
})?;
} }
let r = self.rx.lock(); let r = self.rx.lock();
let m = r.recv().unwrap(); let m = r.recv().unwrap();
let res: Option<LocatedTxKernel> = serde_json::from_str(&m.body).context( let res: Option<LocatedTxKernel> = serde_json::from_str(&m.body).map_err(|_| {
libwallet::ErrorKind::ClientCallback("Get transaction kernels send".to_owned()), libwallet::Error::ClientCallback("Get transaction kernels send".to_owned())
)?; })?;
match res { match res {
Some(k) => Ok(Some((k.tx_kernel, k.height, k.mmr_index))), Some(k) => Ok(Some((k.tx_kernel, k.height, k.mmr_index))),
None => Ok(None), None => Ok(None),
@ -580,9 +575,11 @@ impl NodeClient for LocalWalletClient {
}; };
{ {
let p = self.proxy_tx.lock(); let p = self.proxy_tx.lock();
p.send(m).context(libwallet::ErrorKind::ClientCallback( p.send(m).map_err(|_| {
libwallet::Error::ClientCallback(
"Get outputs from node by PMMR index send".to_owned(), "Get outputs from node by PMMR index send".to_owned(),
))?; )
})?;
} }
let r = self.rx.lock(); let r = self.rx.lock();
@ -627,9 +624,9 @@ impl NodeClient for LocalWalletClient {
}; };
{ {
let p = self.proxy_tx.lock(); let p = self.proxy_tx.lock();
p.send(m).context(libwallet::ErrorKind::ClientCallback( p.send(m).map_err(|_| {
"Get outputs within height range send".to_owned(), libwallet::Error::ClientCallback("Get outputs within height range send".to_owned())
))?; })?;
} }
let r = self.rx.lock(); let r = self.rx.lock();

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::{Error, ErrorKind}; use crate::Error;
use base64; use base64;
use grin_wallet_config::types::TorBridgeConfig; use grin_wallet_config::types::TorBridgeConfig;
use std::collections::HashMap; use std::collections::HashMap;
@ -165,13 +165,13 @@ impl Transport {
match arg { match arg {
Some(addr) => { Some(addr) => {
let address = addr.parse::<SocketAddr>().map_err(|_e| { let address = addr.parse::<SocketAddr>().map_err(|_e| {
ErrorKind::TorBridge(format!("Invalid bridge server address: {}", addr).into()) Error::TorBridge(format!("Invalid bridge server address: {}", addr))
})?; })?;
Ok(address.to_string()) Ok(address.to_string())
} }
None => { None => {
let msg = format!("Missing bridge server address"); let msg = format!("Missing bridge server address");
Err(ErrorKind::TorBridge(msg).into()) Err(Error::TorBridge(msg))
} }
} }
} }
@ -185,7 +185,7 @@ impl Transport {
let fingerprint = fgp.to_uppercase(); let fingerprint = fgp.to_uppercase();
if !(is_hex && fingerprint.len() == 40) { if !(is_hex && fingerprint.len() == 40) {
let msg = format!("Invalid fingerprint: {}", fingerprint); let msg = format!("Invalid fingerprint: {}", fingerprint);
return Err(ErrorKind::TorBridge(msg).into()); return Err(Error::TorBridge(msg));
} }
Ok(Some(fingerprint)) Ok(Some(fingerprint))
} }
@ -195,14 +195,14 @@ impl Transport {
/// Parse the certificate of the bridge line (obfs4) /// Parse the certificate of the bridge line (obfs4)
pub fn parse_cert_arg(arg: &str) -> Result<String, Error> { pub fn parse_cert_arg(arg: &str) -> Result<String, Error> {
let cert_vec = base64::decode(arg).map_err(|_e| { let cert_vec = base64::decode(arg).map_err(|_e| {
ErrorKind::TorBridge(format!( Error::TorBridge(format!(
"Invalid certificate, error decoding bridge certificate: {}", "Invalid certificate, error decoding bridge certificate: {}",
arg arg
)) ))
})?; })?;
if cert_vec.len() != 52 { if cert_vec.len() != 52 {
let msg = format!("Invalid certificate: {}", arg); let msg = format!("Invalid certificate: {}", arg);
return Err(ErrorKind::TorBridge(msg).into()); return Err(Error::TorBridge(msg).into());
} }
Ok(arg.to_string()) Ok(arg.to_string())
} }
@ -211,7 +211,7 @@ impl Transport {
let iatmode = arg.parse::<u8>().unwrap_or(0); let iatmode = arg.parse::<u8>().unwrap_or(0);
if !((0..3).contains(&iatmode)) { if !((0..3).contains(&iatmode)) {
let msg = format!("Invalid iatmode: {}, must be between 0 and 2", iatmode); let msg = format!("Invalid iatmode: {}, must be between 0 and 2", iatmode);
return Err(ErrorKind::TorBridge(msg).into()); return Err(Error::TorBridge(msg));
} }
Ok(iatmode.to_string()) Ok(iatmode.to_string())
} }
@ -219,7 +219,7 @@ impl Transport {
/// Parse the max value for the arg -max in the client line option (snowflake) /// Parse the max value for the arg -max in the client line option (snowflake)
fn parse_hpkp_arg(arg: &str) -> Result<String, Error> { fn parse_hpkp_arg(arg: &str) -> Result<String, Error> {
let max = arg.parse::<bool>().map_err(|_e| { let max = arg.parse::<bool>().map_err(|_e| {
ErrorKind::TorBridge( Error::TorBridge(
format!("Invalid -max value: {}, must be \"true\" or \"false\"", arg).into(), format!("Invalid -max value: {}, must be \"true\" or \"false\"", arg).into(),
) )
})?; })?;
@ -289,7 +289,7 @@ impl PluginClient {
Some(path) => Ok(path.into_os_string().into_string().unwrap()), Some(path) => Ok(path.into_os_string().into_string().unwrap()),
None => { None => {
let msg = format!("Transport client \"{}\" is missing, make sure it's installed and on your path.", plugin); let msg = format!("Transport client \"{}\" is missing, make sure it's installed and on your path.", plugin);
Err(ErrorKind::TorBridge(msg).into()) Err(Error::TorBridge(msg))
} }
} }
} }
@ -298,15 +298,14 @@ impl PluginClient {
fn parse_url_arg(arg: &str) -> Result<String, Error> { fn parse_url_arg(arg: &str) -> Result<String, Error> {
let url = arg let url = arg
.parse::<Url>() .parse::<Url>()
.map_err(|_e| ErrorKind::TorBridge(format!("Invalid -url value: {}", arg).into()))?; .map_err(|_e| Error::TorBridge(format!("Invalid -url value: {}", arg)))?;
Ok(url.to_string()) Ok(url.to_string())
} }
/// Parse the DNS domain value for the arg -front in the client line option (snowflake) /// Parse the DNS domain value for the arg -front in the client line option (snowflake)
fn parse_front_arg(arg: &str) -> Result<String, Error> { fn parse_front_arg(arg: &str) -> Result<String, Error> {
let front = Host::parse(arg).map_err(|_e| { let front = Host::parse(arg)
ErrorKind::TorBridge(format!("Invalid -front hostname value: {}", arg).into()) .map_err(|_e| Error::TorBridge(format!("Invalid -front hostname value: {}", arg)))?;
})?;
match front { match front {
Host::Domain(_) => Ok(front.to_string()), Host::Domain(_) => Ok(front.to_string()),
Host::Ipv4(_) | Host::Ipv6(_) => { Host::Ipv4(_) | Host::Ipv6(_) => {
@ -314,7 +313,7 @@ impl PluginClient {
"Invalid front argument: {}, in the client option. Must be a DNS Domain", "Invalid front argument: {}, in the client option. Must be a DNS Domain",
front front
); );
Err(ErrorKind::TorBridge(msg).into()) Err(Error::TorBridge(msg))
} }
} }
} }
@ -328,13 +327,13 @@ impl PluginClient {
if addr.starts_with("stun:") || addr.starts_with("turn:") { if addr.starts_with("stun:") || addr.starts_with("turn:") {
let address = addr.replace("stun:", "").replace("turn:", ""); let address = addr.replace("stun:", "").replace("turn:", "");
let _p_address = TorProxy::parse_address(&address) let _p_address = TorProxy::parse_address(&address)
.map_err(|e| ErrorKind::TorBridge(format!("{}", e.kind()).into()))?; .map_err(|e| Error::TorBridge(format!("{}", e)))?;
} else { } else {
let msg = format!( let msg = format!(
"Invalid ICE address: {}. Must be a stun or turn address", "Invalid ICE address: {}. Must be a stun or turn address",
addr addr
); );
return Err(ErrorKind::TorBridge(msg).into()); return Err(Error::TorBridge(msg).into());
} }
} }
Ok(ice_addr.to_string()) Ok(ice_addr.to_string())
@ -346,7 +345,7 @@ impl PluginClient {
Ok(max) => Ok(max.to_string()), Ok(max) => Ok(max.to_string()),
Err(_e) => { Err(_e) => {
let msg = format!("Invalid -max argument: {} in the client option.", arg); let msg = format!("Invalid -max argument: {} in the client option.", arg);
Err(ErrorKind::TorBridge(msg).into()) Err(Error::TorBridge(msg))
} }
} }
} }
@ -358,7 +357,7 @@ impl PluginClient {
"ERROR" | "WARN" | "INFO" | "DEBUG" => Ok(log_level.to_string()), "ERROR" | "WARN" | "INFO" | "DEBUG" => Ok(log_level.to_string()),
_ => { _ => {
let msg = format!("Invalid log level argurment: {}, in the client option. Must be: ERROR, WARN, INFO or DEBUG", log_level); let msg = format!("Invalid log level argurment: {}, in the client option. Must be: ERROR, WARN, INFO or DEBUG", log_level);
Err(ErrorKind::TorBridge(msg).into()) Err(Error::TorBridge(msg))
} }
} }
} }
@ -377,7 +376,7 @@ impl PluginClient {
} else { } else {
format!("Missing ICE argurment for snowflake transport, specify \"-ice\"") format!("Missing ICE argurment for snowflake transport, specify \"-ice\"")
}; };
return Err(ErrorKind::TorBridge(msg).into()); return Err(Error::TorBridge(msg));
} }
for (key, value) in hm_flags { for (key, value) in hm_flags {
let p_value = match key { let p_value = match key {
@ -517,7 +516,7 @@ impl TorBridge {
"Invalid transport method: {} - must be obfs4/meek_lite/meek/snowflake", "Invalid transport method: {} - must be obfs4/meek_lite/meek/snowflake",
transport transport
); );
Err(ErrorKind::TorBridge(msg).into()) Err(Error::TorBridge(msg))
} }
} }
} }
@ -544,7 +543,7 @@ impl TryFrom<TorBridgeConfig> for TorBridge {
None => { None => {
let msg = let msg =
format!("Missing cert argurment in obfs4 transport, specify \"cert=\""); format!("Missing cert argurment in obfs4 transport, specify \"cert=\"");
return Err(ErrorKind::TorBridge(msg).into()); return Err(Error::TorBridge(msg));
} }
}; };
let iatmode = match flags.get_key_value("iat-mode=") { let iatmode = match flags.get_key_value("iat-mode=") {
@ -582,7 +581,7 @@ impl TryFrom<TorBridgeConfig> for TorBridge {
let msg = format!( let msg = format!(
"Missing url argurment in meek_lite transport, specify \"url=\"" "Missing url argurment in meek_lite transport, specify \"url=\""
); );
return Err(ErrorKind::TorBridge(msg).into()); return Err(Error::TorBridge(msg));
} }
}; };
let front = match flags.get_key_value("front=") { let front = match flags.get_key_value("front=") {
@ -654,7 +653,7 @@ impl TryFrom<TorBridgeConfig> for TorBridge {
"Invalid transport method: {} - must be obfs4/meek_lite/meek/snowflake", "Invalid transport method: {} - must be obfs4/meek_lite/meek/snowflake",
transport transport
); );
Err(ErrorKind::TorBridge(msg).into()) Err(Error::TorBridge(msg))
} }
} }
} }

View file

@ -14,7 +14,7 @@
//! Tor Configuration + Onion (Hidden) Service operations //! Tor Configuration + Onion (Hidden) Service operations
use crate::util::secp::key::SecretKey; use crate::util::secp::key::SecretKey;
use crate::{Error, ErrorKind}; use crate::Error;
use grin_wallet_util::OnionV3Address; use grin_wallet_util::OnionV3Address;
use ed25519_dalek::ExpandedSecretKey; use ed25519_dalek::ExpandedSecretKey;
@ -27,8 +27,6 @@ use std::io::Write;
use std::path::{Path, MAIN_SEPARATOR}; use std::path::{Path, MAIN_SEPARATOR};
use std::string::String; use std::string::String;
use failure::ResultExt;
const SEC_KEY_FILE: &str = "hs_ed25519_secret_key"; const SEC_KEY_FILE: &str = "hs_ed25519_secret_key";
const PUB_KEY_FILE: &str = "hs_ed25519_public_key"; const PUB_KEY_FILE: &str = "hs_ed25519_public_key";
const HOSTNAME_FILE: &str = "hostname"; const HOSTNAME_FILE: &str = "hostname";
@ -40,7 +38,7 @@ const HIDDEN_SERVICES_DIR: &str = "onion_service_addresses";
#[cfg(unix)] #[cfg(unix)]
fn set_permissions(file_path: &str) -> Result<(), Error> { fn set_permissions(file_path: &str) -> Result<(), Error> {
use std::os::unix::prelude::*; use std::os::unix::prelude::*;
fs::set_permissions(file_path, fs::Permissions::from_mode(0o700)).context(ErrorKind::IO)?; fs::set_permissions(file_path, fs::Permissions::from_mode(0o700)).map_err(|_| Error::IO)?;
Ok(()) Ok(())
} }
@ -81,14 +79,14 @@ impl TorRcConfig {
/// write to file /// write to file
pub fn write_to_file(&self, file_path: &str) -> Result<(), Error> { pub fn write_to_file(&self, file_path: &str) -> Result<(), Error> {
let mut file = File::create(file_path).context(ErrorKind::IO)?; let mut file = File::create(file_path).map_err(|_| Error::IO)?;
for item in &self.items { for item in &self.items {
file.write_all(item.name.as_bytes()) file.write_all(item.name.as_bytes())
.context(ErrorKind::IO)?; .map_err(|_| Error::IO)?;
file.write_all(b" ").context(ErrorKind::IO)?; file.write_all(b" ").map_err(|_| Error::IO)?;
file.write_all(item.value.as_bytes()) file.write_all(item.value.as_bytes())
.context(ErrorKind::IO)?; .map_err(|_| Error::IO)?;
file.write_all(b"\n").context(ErrorKind::IO)?; file.write_all(b"\n").map_err(|_| Error::IO)?;
} }
Ok(()) Ok(())
} }
@ -99,13 +97,13 @@ pub fn create_onion_service_sec_key_file(
sec_key: &DalekSecretKey, sec_key: &DalekSecretKey,
) -> Result<(), Error> { ) -> Result<(), Error> {
let key_file_path = &format!("{}{}{}", os_directory, MAIN_SEPARATOR, SEC_KEY_FILE); let key_file_path = &format!("{}{}{}", os_directory, MAIN_SEPARATOR, SEC_KEY_FILE);
let mut file = File::create(key_file_path).context(ErrorKind::IO)?; let mut file = File::create(key_file_path).map_err(|_| Error::IO)?;
// Tag is always 32 bytes, so pad with null zeroes // Tag is always 32 bytes, so pad with null zeroes
file.write(b"== ed25519v1-secret: type0 ==\0\0\0") file.write(b"== ed25519v1-secret: type0 ==\0\0\0")
.context(ErrorKind::IO)?; .map_err(|_| Error::IO)?;
let expanded_skey: ExpandedSecretKey = ExpandedSecretKey::from(sec_key); let expanded_skey: ExpandedSecretKey = ExpandedSecretKey::from(sec_key);
file.write_all(&expanded_skey.to_bytes()) file.write_all(&expanded_skey.to_bytes())
.context(ErrorKind::IO)?; .map_err(|_| Error::IO)?;
Ok(()) Ok(())
} }
@ -114,25 +112,25 @@ pub fn create_onion_service_pub_key_file(
pub_key: &DalekPublicKey, pub_key: &DalekPublicKey,
) -> Result<(), Error> { ) -> Result<(), Error> {
let key_file_path = &format!("{}{}{}", os_directory, MAIN_SEPARATOR, PUB_KEY_FILE); let key_file_path = &format!("{}{}{}", os_directory, MAIN_SEPARATOR, PUB_KEY_FILE);
let mut file = File::create(key_file_path).context(ErrorKind::IO)?; let mut file = File::create(key_file_path).map_err(|_| Error::IO)?;
// Tag is always 32 bytes, so pad with null zeroes // Tag is always 32 bytes, so pad with null zeroes
file.write(b"== ed25519v1-public: type0 ==\0\0\0") file.write(b"== ed25519v1-public: type0 ==\0\0\0")
.context(ErrorKind::IO)?; .map_err(|_| Error::IO)?;
file.write_all(pub_key.as_bytes()).context(ErrorKind::IO)?; file.write_all(pub_key.as_bytes()).map_err(|_| Error::IO)?;
Ok(()) Ok(())
} }
pub fn create_onion_service_hostname_file(os_directory: &str, hostname: &str) -> Result<(), Error> { pub fn create_onion_service_hostname_file(os_directory: &str, hostname: &str) -> Result<(), Error> {
let file_path = &format!("{}{}{}", os_directory, MAIN_SEPARATOR, HOSTNAME_FILE); let file_path = &format!("{}{}{}", os_directory, MAIN_SEPARATOR, HOSTNAME_FILE);
let mut file = File::create(file_path).context(ErrorKind::IO)?; let mut file = File::create(file_path).map_err(|_| Error::IO)?;
file.write_all(&format!("{}.onion\n", hostname).as_bytes()) file.write_all(&format!("{}.onion\n", hostname).as_bytes())
.context(ErrorKind::IO)?; .map_err(|_| Error::IO)?;
Ok(()) Ok(())
} }
pub fn create_onion_auth_clients_dir(os_directory: &str) -> Result<(), Error> { pub fn create_onion_auth_clients_dir(os_directory: &str) -> Result<(), Error> {
let auth_dir_path = &format!("{}{}{}", os_directory, MAIN_SEPARATOR, AUTH_CLIENTS_DIR); let auth_dir_path = &format!("{}{}{}", os_directory, MAIN_SEPARATOR, AUTH_CLIENTS_DIR);
fs::create_dir_all(auth_dir_path).context(ErrorKind::IO)?; fs::create_dir_all(auth_dir_path).map_err(|_| Error::IO)?;
Ok(()) Ok(())
} }
/// output an onion service config for the secret key, and return the address /// output an onion service config for the secret key, and return the address
@ -141,7 +139,7 @@ pub fn output_onion_service_config(
sec_key: &SecretKey, sec_key: &SecretKey,
) -> Result<OnionV3Address, Error> { ) -> Result<OnionV3Address, Error> {
let d_sec_key = DalekSecretKey::from_bytes(&sec_key.0) let d_sec_key = DalekSecretKey::from_bytes(&sec_key.0)
.context(ErrorKind::ED25519Key("Unable to parse private key".into()))?; .map_err(|_| Error::ED25519Key("Unable to parse private key".into()))?;
let address = OnionV3Address::from_private(&sec_key.0)?; let address = OnionV3Address::from_private(&sec_key.0)?;
let hs_dir_file_path = format!( let hs_dir_file_path = format!(
"{}{}{}{}{}", "{}{}{}{}{}",
@ -154,7 +152,7 @@ pub fn output_onion_service_config(
} }
// create directory if it doesn't exist // create directory if it doesn't exist
fs::create_dir_all(&hs_dir_file_path).context(ErrorKind::IO)?; fs::create_dir_all(&hs_dir_file_path).map_err(|_| Error::IO)?;
create_onion_service_sec_key_file(&hs_dir_file_path, &d_sec_key)?; create_onion_service_sec_key_file(&hs_dir_file_path, &d_sec_key)?;
create_onion_service_pub_key_file(&hs_dir_file_path, &address.to_ed25519()?)?; create_onion_service_pub_key_file(&hs_dir_file_path, &address.to_ed25519()?)?;
@ -218,7 +216,7 @@ pub fn output_tor_listener_config(
let tor_data_dir = format!("{}{}{}", tor_config_directory, MAIN_SEPARATOR, TOR_DATA_DIR); let tor_data_dir = format!("{}{}{}", tor_config_directory, MAIN_SEPARATOR, TOR_DATA_DIR);
// create data directory if it doesn't exist // create data directory if it doesn't exist
fs::create_dir_all(&tor_data_dir).context(ErrorKind::IO)?; fs::create_dir_all(&tor_data_dir).map_err(|_| Error::IO)?;
let mut service_dirs = vec![]; let mut service_dirs = vec![];
@ -248,7 +246,7 @@ pub fn output_tor_sender_config(
hm_tor_proxy: HashMap<String, String>, hm_tor_proxy: HashMap<String, String>,
) -> Result<(), Error> { ) -> Result<(), Error> {
// create data directory if it doesn't exist // create data directory if it doesn't exist
fs::create_dir_all(&tor_config_dir).context(ErrorKind::IO)?; fs::create_dir_all(&tor_config_dir).map_err(|_| Error::IO)?;
output_torrc( output_torrc(
tor_config_dir, tor_config_dir,
@ -267,7 +265,7 @@ pub fn is_tor_address(input: &str) -> Result<(), Error> {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(e) => { Err(e) => {
let msg = format!("{:?}", e); let msg = format!("{:?}", e);
Err(ErrorKind::NotOnion(msg).into()) Err(Error::NotOnion(msg).into())
} }
} }
} }

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::{Error, ErrorKind}; use crate::Error;
use grin_wallet_config::types::TorProxyConfig; use grin_wallet_config::types::TorProxyConfig;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryFrom; use std::convert::TryFrom;
@ -72,11 +72,11 @@ impl TorProxy {
pub fn parse_address(addr: &str) -> Result<(String, Option<u16>), Error> { pub fn parse_address(addr: &str) -> Result<(String, Option<u16>), Error> {
let (host, str_port) = TorProxy::parse_host_port(&addr)?; let (host, str_port) = TorProxy::parse_host_port(&addr)?;
let host = Host::parse(&host) let host = Host::parse(&host)
.map_err(|_e| ErrorKind::TorProxy(format!("Invalid host address: {}", host)))?; .map_err(|_e| Error::TorProxy(format!("Invalid host address: {}", host)))?;
let port = if let Some(p) = str_port { let port = if let Some(p) = str_port {
let res = p let res = p
.parse::<u16>() .parse::<u16>()
.map_err(|_e| ErrorKind::TorProxy(format!("Invalid port number: {}", p)))?; .map_err(|_e| Error::TorProxy(format!("Invalid port number: {}", p)))?;
Some(res) Some(res)
} else { } else {
None None
@ -167,7 +167,7 @@ impl TryFrom<TorProxyConfig> for TorProxy {
"Missing proxy address: {} - must be <IP:PORT> or <Hostname>", "Missing proxy address: {} - must be <IP:PORT> or <Hostname>",
transport transport
); );
return Err(ErrorKind::TorProxy(msg).into()); return Err(Error::TorProxy(msg).into());
} }
} }
// Missing transport type // Missing transport type
@ -176,7 +176,7 @@ impl TryFrom<TorProxyConfig> for TorProxy {
"Invalid proxy transport: {} - must be socks4/socks5/http(s)", "Invalid proxy transport: {} - must be socks4/socks5/http(s)",
transport transport
); );
Err(ErrorKind::TorProxy(msg).into()) Err(Error::TorProxy(msg).into())
} }
} }
} else { } else {

View file

@ -12,8 +12,6 @@ edition = "2018"
[dependencies] [dependencies]
blake2-rfc = "0.2" blake2-rfc = "0.2"
failure = "0.1"
failure_derive = "0.1"
rand = "0.6" rand = "0.6"
serde = "1" serde = "1"
serde_derive = "1" serde_derive = "1"
@ -24,6 +22,7 @@ chrono = { version = "0.4.11", features = ["serde"] }
lazy_static = "1" lazy_static = "1"
strum = "0.18" strum = "0.18"
strum_macros = "0.18" strum_macros = "0.18"
thiserror = "1"
ed25519-dalek = "1.0.0-pre.4" ed25519-dalek = "1.0.0-pre.4"
x25519-dalek = "0.6" x25519-dalek = "0.6"
base64 = "0.9" base64 = "0.9"

View file

@ -23,8 +23,8 @@ use crate::grin_util::secp::key::SecretKey;
use crate::internal::{selection, tx, updater}; use crate::internal::{selection, tx, updater};
use crate::slate_versions::SlateVersion; use crate::slate_versions::SlateVersion;
use crate::{ use crate::{
address, BlockFees, CbData, Error, ErrorKind, NodeClient, Slate, SlateState, TxLogEntryType, address, BlockFees, CbData, Error, NodeClient, Slate, SlateState, TxLogEntryType, VersionInfo,
VersionInfo, WalletBackend, WalletBackend,
}; };
const FOREIGN_API_VERSION: u16 = 2; const FOREIGN_API_VERSION: u16 = 2;
@ -87,7 +87,7 @@ where
)?; )?;
for t in &tx { for t in &tx {
if t.tx_type == TxLogEntryType::TxReceived { if t.tx_type == TxLogEntryType::TxReceived {
return Err(ErrorKind::TransactionAlreadyReceived(ret_slate.id.to_string()).into()); return Err(Error::TransactionAlreadyReceived(ret_slate.id.to_string()));
} }
} }

View file

@ -30,12 +30,12 @@ use crate::grin_keychain::{BlindingFactor, Identifier, Keychain, SwitchCommitmen
use crate::internal::{keys, scan, selection, tx, updater}; use crate::internal::{keys, scan, selection, tx, updater};
use crate::slate::{PaymentInfo, Slate, SlateState}; use crate::slate::{PaymentInfo, Slate, SlateState};
use crate::types::{AcctPathMapping, NodeClient, TxLogEntry, WalletBackend, WalletInfo}; use crate::types::{AcctPathMapping, NodeClient, TxLogEntry, WalletBackend, WalletInfo};
use crate::Error;
use crate::{ use crate::{
address, wallet_lock, BuiltOutput, InitTxArgs, IssueInvoiceTxArgs, NodeHeightResult, address, wallet_lock, BuiltOutput, InitTxArgs, IssueInvoiceTxArgs, NodeHeightResult,
OutputCommitMapping, PaymentProof, ScannedBlockInfo, Slatepack, SlatepackAddress, Slatepacker, OutputCommitMapping, PaymentProof, ScannedBlockInfo, Slatepack, SlatepackAddress, Slatepacker,
SlatepackerArgs, TxLogEntryType, ViewWallet, WalletInitStatus, WalletInst, WalletLCProvider, SlatepackerArgs, TxLogEntryType, ViewWallet, WalletInitStatus, WalletInst, WalletLCProvider,
}; };
use crate::{Error, ErrorKind};
use ed25519_dalek::PublicKey as DalekPublicKey; use ed25519_dalek::PublicKey as DalekPublicKey;
use ed25519_dalek::SecretKey as DalekSecretKey; use ed25519_dalek::SecretKey as DalekSecretKey;
use ed25519_dalek::Verifier; use ed25519_dalek::Verifier;
@ -211,9 +211,9 @@ where
}; };
return packer.get_slate(&slatepack); return packer.get_slate(&slatepack);
} }
return Err(ErrorKind::SlatepackDecryption( return Err(Error::SlatepackDecryption(
"Could not decrypt slatepack with any provided index on the address derivation path" "Could not decrypt slatepack with any provided index on the address derivation path"
.into(), .to_owned(),
) )
.into()); .into());
} }
@ -382,10 +382,9 @@ where
K: Keychain + 'a, K: Keychain + 'a,
{ {
if tx_id.is_none() && tx_slate_id.is_none() { if tx_id.is_none() && tx_slate_id.is_none() {
return Err(ErrorKind::PaymentProofRetrieval( return Err(Error::PaymentProofRetrieval(
"Transaction ID or Slate UUID must be specified".into(), "Transaction ID or Slate UUID must be specified".to_owned(),
) ));
.into());
} }
if refresh_from_node { if refresh_from_node {
update_wallet_state( update_wallet_state(
@ -406,17 +405,18 @@ where
tx_slate_id, tx_slate_id,
)?; )?;
if txs.1.len() != 1 { if txs.1.len() != 1 {
return Err(ErrorKind::PaymentProofRetrieval("Transaction doesn't exist".into()).into()); return Err(Error::PaymentProofRetrieval(
"Transaction doesn't exist".to_owned(),
));
} }
// Pull out all needed fields, returning an error if they're not present // Pull out all needed fields, returning an error if they're not present
let tx = txs.1[0].clone(); let tx = txs.1[0].clone();
let proof = match tx.payment_proof { let proof = match tx.payment_proof {
Some(p) => p, Some(p) => p,
None => { None => {
return Err(ErrorKind::PaymentProofRetrieval( return Err(Error::PaymentProofRetrieval(
"Transaction does not contain a payment proof".into(), "Transaction does not contain a payment proof".to_owned(),
) ));
.into());
} }
}; };
let amount = if tx.amount_credited >= tx.amount_debited { let amount = if tx.amount_credited >= tx.amount_debited {
@ -431,28 +431,25 @@ where
let excess = match tx.kernel_excess { let excess = match tx.kernel_excess {
Some(e) => e, Some(e) => e,
None => { None => {
return Err(ErrorKind::PaymentProofRetrieval( return Err(Error::PaymentProofRetrieval(
"Transaction does not contain kernel excess".into(), "Transaction does not contain kernel excess".to_owned(),
) ));
.into());
} }
}; };
let r_sig = match proof.receiver_signature { let r_sig = match proof.receiver_signature {
Some(e) => e, Some(e) => e,
None => { None => {
return Err(ErrorKind::PaymentProofRetrieval( return Err(Error::PaymentProofRetrieval(
"Proof does not contain receiver signature ".into(), "Proof does not contain receiver signature ".to_owned(),
) ));
.into());
} }
}; };
let s_sig = match proof.sender_signature { let s_sig = match proof.sender_signature {
Some(e) => e, Some(e) => e,
None => { None => {
return Err(ErrorKind::PaymentProofRetrieval( return Err(Error::PaymentProofRetrieval(
"Proof does not contain sender signature ".into(), "Proof does not contain sender signature ".to_owned(),
) ));
.into());
} }
}; };
Ok(PaymentProof { Ok(PaymentProof {
@ -669,7 +666,7 @@ where
)?; )?;
for t in &tx { for t in &tx {
if t.tx_type == TxLogEntryType::TxSent { if t.tx_type == TxLogEntryType::TxSent {
return Err(ErrorKind::TransactionAlreadyReceived(ret_slate.id.to_string()).into()); return Err(Error::TransactionAlreadyReceived(ret_slate.id.to_string()));
} }
} }
@ -882,10 +879,9 @@ where
status_send_channel, status_send_channel,
false, false,
)? { )? {
return Err(ErrorKind::TransactionCancellationError( return Err(Error::TransactionCancellationError(
"Can't contact running Grin node. Not Cancelling.", "Can't contact running Grin node. Not Cancelling.",
) ));
.into());
} }
wallet_lock!(wallet_inst, w); wallet_lock!(wallet_inst, w);
let parent_key_id = w.parent_key_id(); let parent_key_id = w.parent_key_id();
@ -919,10 +915,9 @@ where
let id = match uuid { let id = match uuid {
Some(u) => u, Some(u) => u,
None => { None => {
return Err(ErrorKind::StoredTx( return Err(Error::StoredTx(
"Both the provided Transaction Id and Slate UUID are invalid.".to_owned(), "Both the provided Transaction Id and Slate UUID are invalid.".to_owned(),
) ));
.into());
} }
}; };
let tx_res = w.get_stored_tx(&format!("{}", id))?; let tx_res = w.get_stored_tx(&format!("{}", id))?;
@ -977,7 +972,7 @@ where
let rewind_hash = rewind_hash.to_lowercase(); let rewind_hash = rewind_hash.to_lowercase();
if !(is_hex && rewind_hash.len() == 64) { if !(is_hex && rewind_hash.len() == 64) {
let msg = format!("Invalid Rewind Hash"); let msg = format!("Invalid Rewind Hash");
return Err(ErrorKind::RewindHash(msg).into()); return Err(Error::RewindHash(msg));
} }
let tip = { let tip = {
@ -1227,7 +1222,7 @@ where
let last_confirmed_height = w.last_confirmed_height()?; let last_confirmed_height = w.last_confirmed_height()?;
if slate.ttl_cutoff_height != 0 { if slate.ttl_cutoff_height != 0 {
if last_confirmed_height >= slate.ttl_cutoff_height { if last_confirmed_height >= slate.ttl_cutoff_height {
return Err(ErrorKind::TransactionExpired.into()); return Err(Error::TransactionExpired);
} }
} }
Ok(()) Ok(())
@ -1260,18 +1255,16 @@ where
// Check kernel exists // Check kernel exists
match client.get_kernel(&proof.excess, None, None) { match client.get_kernel(&proof.excess, None, None) {
Err(e) => { Err(e) => {
return Err(ErrorKind::PaymentProof(format!( return Err(Error::PaymentProof(format!(
"Error retrieving kernel from chain: {}", "Error retrieving kernel from chain: {}",
e e
)) )));
.into());
} }
Ok(None) => { Ok(None) => {
return Err(ErrorKind::PaymentProof(format!( return Err(Error::PaymentProof(format!(
"Transaction kernel with excess {:?} not found on chain", "Transaction kernel with excess {:?} not found on chain",
proof.excess proof.excess
)) )));
.into());
} }
Ok(Some(_)) => {} Ok(Some(_)) => {}
}; };
@ -1279,12 +1272,14 @@ where
// Check Sigs // Check Sigs
let recipient_pubkey = proof.recipient_address.pub_key; let recipient_pubkey = proof.recipient_address.pub_key;
if recipient_pubkey.verify(&msg, &proof.recipient_sig).is_err() { if recipient_pubkey.verify(&msg, &proof.recipient_sig).is_err() {
return Err(ErrorKind::PaymentProof("Invalid recipient signature".to_owned()).into()); return Err(Error::PaymentProof(
"Invalid recipient signature".to_owned(),
));
}; };
let sender_pubkey = proof.sender_address.pub_key; let sender_pubkey = proof.sender_address.pub_key;
if sender_pubkey.verify(&msg, &proof.sender_sig).is_err() { if sender_pubkey.verify(&msg, &proof.sender_sig).is_err() {
return Err(ErrorKind::PaymentProof("Invalid sender signature".to_owned()).into()); return Err(Error::PaymentProof("Invalid sender signature".to_owned()));
}; };
// for now, simple test as to whether one of the addresses belongs to this wallet // for now, simple test as to whether one of the addresses belongs to this wallet
@ -1292,7 +1287,7 @@ where
let d_skey = match DalekSecretKey::from_bytes(&sec_key.0) { let d_skey = match DalekSecretKey::from_bytes(&sec_key.0) {
Ok(k) => k, Ok(k) => k,
Err(e) => { Err(e) => {
return Err(ErrorKind::ED25519Key(format!("{}", e)).into()); return Err(Error::ED25519Key(format!("{}", e)));
} }
}; };
let my_address_pubkey: DalekPublicKey = (&d_skey).into(); let my_address_pubkey: DalekPublicKey = (&d_skey).into();
@ -1319,7 +1314,7 @@ where
match updater::refresh_outputs(&mut **w, keychain_mask, &parent_key_id, update_all) { match updater::refresh_outputs(&mut **w, keychain_mask, &parent_key_id, update_all) {
Ok(_) => Ok(true), Ok(_) => Ok(true),
Err(e) => { Err(e) => {
if let ErrorKind::InvalidKeychainMask = e.kind() { if let Error::InvalidKeychainMask = e {
return Err(e); return Err(e);
} }
Ok(false) Ok(false)

View file

@ -17,28 +17,14 @@
use crate::grin_core::core::{committed, transaction}; use crate::grin_core::core::{committed, transaction};
use crate::grin_core::libtx; use crate::grin_core::libtx;
use crate::grin_keychain; use crate::grin_keychain;
use crate::grin_store;
use crate::grin_util::secp; use crate::grin_util::secp;
use crate::util; use crate::util::{self, grin_store};
use failure::{Backtrace, Context, Fail};
use std::env;
use std::fmt::{self, Display};
use std::io;
/// Error definition
#[derive(Debug, Fail)]
pub struct Error {
inner: Context<ErrorKind>,
}
/// Wallet errors, mostly wrappers around underlying crypto or I/O errors. /// Wallet errors, mostly wrappers around underlying crypto or I/O errors.
#[derive(Clone, Eq, PartialEq, Debug, Fail, Serialize, Deserialize)] #[derive(Clone, Eq, PartialEq, Debug, thiserror::Error, Serialize, Deserialize)]
pub enum ErrorKind { pub enum Error {
/// Not enough funds /// Not enough funds
#[fail( #[error("Not enough funds. Required: {needed_disp:?}, Available: {available_disp:?}")]
display = "Not enough funds. Required: {}, Available: {}",
needed_disp, available_disp
)]
NotEnoughFunds { NotEnoughFunds {
/// available funds /// available funds
available: u64, available: u64,
@ -51,426 +37,306 @@ pub enum ErrorKind {
}, },
/// Fee error /// Fee error
#[fail(display = "Fee Error: {}", _0)] #[error("Fee Error: {0}")]
Fee(String), Fee(String),
/// LibTX Error /// LibTX Error
#[fail(display = "LibTx Error")] #[error("LibTx Error")]
LibTX(libtx::ErrorKind), LibTX(#[from] libtx::Error),
/// Keychain error /// Keychain error
#[fail(display = "Keychain error")] #[error("Keychain error")]
Keychain(grin_keychain::Error), Keychain(#[from] grin_keychain::Error),
/// Transaction Error /// Transaction Error
#[fail(display = "Transaction error")] #[error("Transaction error")]
Transaction(transaction::Error), Transaction(#[from] transaction::Error),
/// API Error /// API Error
#[fail(display = "Client Callback Error: {}", _0)] #[error("Client Callback Error: {0}")]
ClientCallback(String), ClientCallback(String),
/// Secp Error /// Error from underlying secp lib
#[fail(display = "Secp error")] #[error("Secp Lib Error")]
Secp(secp::Error), Secp(#[from] secp::Error),
/// Onion V3 Address Error /// Onion V3 Address Error
#[fail(display = "Onion V3 Address Error")] #[error("Onion V3 Address Error: {0}")]
OnionV3Address(util::OnionV3AddressError), OnionV3Address(#[from] util::OnionV3AddressError),
/// Callback implementation error conversion /// Callback implementation error conversion
#[fail(display = "Trait Implementation error")] #[error("Trait Implementation error")]
CallbackImpl(&'static str), CallbackImpl(&'static str),
/// Wallet backend error /// Wallet backend error
#[fail(display = "Wallet store error: {}", _0)] #[error("Wallet store error: {0}")]
Backend(String), Backend(String),
/// Callback implementation error conversion /// Callback implementation error conversion
#[fail(display = "Restore Error")] #[error("Restore Error")]
Restore, Restore,
/// An error in the format of the JSON structures exchanged by the wallet /// An error in the format of the JSON structures exchanged by the wallet
#[fail(display = "JSON format error: {}", _0)] #[error("JSON format error: {0}")]
Format(String), Format(String),
/// Other serialization errors /// Other serialization errors
#[fail(display = "Ser/Deserialization error")] #[error("Ser/Deserialization error")]
Deser(crate::grin_core::ser::Error), Deser(crate::grin_core::ser::Error),
/// IO Error /// IO Error
#[fail(display = "I/O error")] #[error("I/O error {0}")]
IO, IO(String),
/// Error when contacting a node through its API /// Error when contacting a node through its API
#[fail(display = "Node API error")] #[error("Node API error")]
Node, Node,
/// Error contacting wallet API /// Error contacting wallet API
#[fail(display = "Wallet Communication Error: {}", _0)] #[error("Wallet Communication Error: {0}")]
WalletComms(String), WalletComms(String),
/// Error originating from hyper. /// Error originating from hyper.
#[fail(display = "Hyper error")] #[error("Hyper error")]
Hyper, Hyper,
/// Error originating from hyper uri parsing. /// Error originating from hyper uri parsing.
#[fail(display = "Uri parsing error")] #[error("Uri parsing error")]
Uri, Uri,
/// Signature error /// Signature error
#[fail(display = "Signature error: {}", _0)] #[error("Signature error: {0}")]
Signature(String), Signature(String),
/// OwnerAPIEncryption /// OwnerAPIEncryption
#[fail(display = "{}", _0)] #[error("{}", _0)]
APIEncryption(String), APIEncryption(String),
/// Attempt to use duplicate transaction id in separate transactions /// Attempt to use duplicate transaction id in separate transactions
#[fail(display = "Duplicate transaction ID error")] #[error("Duplicate transaction ID error")]
DuplicateTransactionId, DuplicateTransactionId,
/// Wallet seed already exists /// Wallet seed already exists
#[fail(display = "Wallet seed exists error: {}", _0)] #[error("Wallet seed exists error: {0}")]
WalletSeedExists(String), WalletSeedExists(String),
/// Wallet seed doesn't exist /// Wallet seed doesn't exist
#[fail(display = "Wallet seed doesn't exist error")] #[error("Wallet seed doesn't exist error")]
WalletSeedDoesntExist, WalletSeedDoesntExist,
/// Wallet seed doesn't exist /// Wallet seed doesn't exist
#[fail(display = "Wallet seed decryption error")] #[error("Wallet seed decryption error")]
WalletSeedDecryption, WalletSeedDecryption,
/// Transaction doesn't exist /// Transaction doesn't exist
#[fail(display = "Transaction {} doesn't exist", _0)] #[error("Transaction {0} doesn't exist")]
TransactionDoesntExist(String), TransactionDoesntExist(String),
/// Transaction already rolled back /// Transaction already rolled back
#[fail(display = "Transaction {} cannot be cancelled", _0)] #[error("Transaction {0} cannot be cancelled")]
TransactionNotCancellable(String), TransactionNotCancellable(String),
/// Cancellation error /// Cancellation error
#[fail(display = "Cancellation Error: {}", _0)] #[error("Cancellation Error: {0}")]
TransactionCancellationError(&'static str), TransactionCancellationError(&'static str),
/// Cancellation error /// Cancellation error
#[fail(display = "Tx dump Error: {}", _0)] #[error("Tx dump Error: {0}")]
TransactionDumpError(&'static str), TransactionDumpError(&'static str),
/// Attempt to repost a transaction that's already confirmed /// Attempt to repost a transaction that's already confirmed
#[fail(display = "Transaction already confirmed error")] #[error("Transaction already confirmed error")]
TransactionAlreadyConfirmed, TransactionAlreadyConfirmed,
/// Transaction has already been received /// Transaction has already been received
#[fail(display = "Transaction {} has already been received", _0)] #[error("Transaction {0} has already been received")]
TransactionAlreadyReceived(String), TransactionAlreadyReceived(String),
/// Attempt to repost a transaction that's not completed and stored /// Attempt to repost a transaction that's not completed and stored
#[fail(display = "Transaction building not completed: {}", _0)] #[error("Transaction building not completed: {0}")]
TransactionBuildingNotCompleted(u32), TransactionBuildingNotCompleted(u32),
/// Invalid BIP-32 Depth /// Invalid BIP-32 Depth
#[fail(display = "Invalid BIP32 Depth (must be 1 or greater)")] #[error("Invalid BIP32 Depth (must be 1 or greater)")]
InvalidBIP32Depth, InvalidBIP32Depth,
/// Attempt to add an account that exists /// Attempt to add an account that exists
#[fail(display = "Account Label '{}' already exists", _0)] #[error("Account Label '{0}' already exists")]
AccountLabelAlreadyExists(String), AccountLabelAlreadyExists(String),
/// Reference unknown account label /// Reference unknown account label
#[fail(display = "Unknown Account Label '{}'", _0)] #[error("Unknown Account Label '{0}'")]
UnknownAccountLabel(String), UnknownAccountLabel(String),
/// Error from summing commitments via committed trait. /// Error from summing commitments via committed trait.
#[fail(display = "Committed Error")] #[error("Committed Error")]
Committed(committed::Error), Committed(committed::Error),
/// Error from summing commitments /// Error from summing commitments
#[fail(display = "Committed Error: {}", _0)] #[error("Committed Error: {0}")]
Commit(String), Commit(String),
/// Can't parse slate version /// Can't parse slate version
#[fail(display = "Can't parse slate version")] #[error("Can't parse slate version")]
SlateVersionParse, SlateVersionParse,
/// Can't serialize slate /// Can't serialize slate
#[fail(display = "Can't Serialize slate")] #[error("Can't Serialize slate")]
SlateSer, SlateSer,
/// Can't deserialize slate /// Can't deserialize slate
#[fail(display = "Can't Deserialize slate")] #[error("Can't Deserialize slate")]
SlateDeser, SlateDeser,
/// Can't serialize slate pack /// Can't serialize slate pack
#[fail(display = "Can't Serialize slatepack")] #[error("Can't Serialize slatepack")]
SlatepackSer, SlatepackSer,
/// Can't deserialize slate /// Can't deserialize slate
#[fail(display = "Can't Deserialize slatepack: {}", _0)] #[error("Can't Deserialize slatepack: {0}")]
SlatepackDeser(String), SlatepackDeser(String),
/// Unknown slate version /// Unknown slate version
#[fail(display = "Unknown Slate Version: {}", _0)] #[error("Unknown Slate Version: {0}")]
SlateVersion(u16), SlateVersion(u16),
/// Attempt to use slate transaction data that doesn't exists /// Attempt to use slate transaction data that doesn't exists
#[fail(display = "Slate transaction required in this context")] #[error("Slate transaction required in this context")]
SlateTransactionRequired, SlateTransactionRequired,
/// Attempt to downgrade slate that can't be downgraded /// Attempt to downgrade slate that can't be downgraded
#[fail(display = "Can't downgrade slate: {}", _0)] #[error("Can't downgrade slate: {0}")]
SlateInvalidDowngrade(String), SlateInvalidDowngrade(String),
/// Compatibility error between incoming slate versions and what's expected /// Compatibility error between incoming slate versions and what's expected
#[fail(display = "Compatibility Error: {}", _0)] #[error("Compatibility Error: {0}")]
Compatibility(String), Compatibility(String),
/// Keychain doesn't exist (wallet not openend) /// Keychain doesn't exist (wallet not openend)
#[fail(display = "Keychain doesn't exist (has wallet been opened?)")] #[error("Keychain doesn't exist (has wallet been opened?)")]
KeychainDoesntExist, KeychainDoesntExist,
/// Lifecycle Error /// Lifecycle Error
#[fail(display = "Lifecycle Error: {}", _0)] #[error("Lifecycle Error: {0}")]
Lifecycle(String), Lifecycle(String),
/// Invalid Keychain Mask Error /// Invalid Keychain Mask Error
#[fail(display = "Supplied Keychain Mask Token is incorrect")] #[error("Supplied Keychain Mask Token is incorrect")]
InvalidKeychainMask, InvalidKeychainMask,
/// Tor Process error /// Tor Process error
#[fail(display = "Tor Process Error: {}", _0)] #[error("Tor Process Error: {0}")]
TorProcess(String), TorProcess(String),
/// Tor Configuration Error /// Tor Configuration Error
#[fail(display = "Tor Config Error: {}", _0)] #[error("Tor Config Error: {0}")]
TorConfig(String), TorConfig(String),
/// Generating ED25519 Public Key /// Generating ED25519 Public Key
#[fail(display = "Error generating ed25519 secret key: {}", _0)] #[error("Error generating ed25519 secret key: {0}")]
ED25519Key(String), ED25519Key(String),
/// Generating Payment Proof /// Generating Payment Proof
#[fail(display = "Payment Proof generation error: {}", _0)] #[error("Payment Proof generation error: {0}")]
PaymentProof(String), PaymentProof(String),
/// Retrieving Payment Proof /// Retrieving Payment Proof
#[fail(display = "Payment Proof retrieval error: {}", _0)] #[error("Payment Proof retrieval error: {0}")]
PaymentProofRetrieval(String), PaymentProofRetrieval(String),
/// Retrieving Payment Proof /// Retrieving Payment Proof
#[fail(display = "Payment Proof parsing error: {}", _0)] #[error("Payment Proof parsing error: {0}")]
PaymentProofParsing(String), PaymentProofParsing(String),
/// Decoding OnionV3 addresses to payment proof addresses /// Decoding OnionV3 addresses to payment proof addresses
#[fail(display = "Proof Address decoding: {}", _0)] #[error("Proof Address decoding: {0}")]
AddressDecoding(String), AddressDecoding(String),
/// Transaction has expired it's TTL /// Transaction has expired it's TTL
#[fail(display = "Transaction Expired")] #[error("Transaction Expired")]
TransactionExpired, TransactionExpired,
/// Kernel features args don't exist /// Kernel features args don't exist
#[fail(display = "Kernel Features Arg {} missing", _0)] #[error("Kernel Features Arg {0} missing")]
KernelFeaturesMissing(String), KernelFeaturesMissing(String),
/// Unknown Kernel Feature /// Unknown Kernel Feature
#[fail(display = "Unknown Kernel Feature: {}", _0)] #[error("Unknown Kernel Feature: {0}")]
UnknownKernelFeatures(u8), UnknownKernelFeatures(u8),
/// Invalid Kernel Feature /// Invalid Kernel Feature
#[fail(display = "Invalid Kernel Feature: {}", _0)] #[error("Invalid Kernel Feature: {0}")]
InvalidKernelFeatures(u8), InvalidKernelFeatures(u8),
/// Invalid Slatepack Data /// Invalid Slatepack Data
#[fail(display = "Invalid Slatepack Data: {}", _0)] #[error("Invalid Slatepack Data: {0}")]
InvalidSlatepackData(String), InvalidSlatepackData(String),
/// Slatepack Encryption /// Slatepack Encryption
#[fail(display = "Couldn't encrypt Slatepack: {}", _0)] #[error("Couldn't encrypt Slatepack: {0}")]
SlatepackEncryption(String), SlatepackEncryption(String),
/// Slatepack Decryption /// Slatepack Decryption
#[fail(display = "Couldn't decrypt Slatepack: {}", _0)] #[error("Couldn't decrypt Slatepack: {0}")]
SlatepackDecryption(String), SlatepackDecryption(String),
/// age error /// age error
#[fail(display = "Age error: {}", _0)] #[error("Age error: {0}")]
Age(String), Age(String),
/// Rewind Hash parsing error /// Rewind Hash parsing error
#[fail(display = "Rewind Hash error: {}", _0)] #[error("Rewind Hash error: {0}")]
RewindHash(String), RewindHash(String),
/// Nonce creation error /// Nonce creation error
#[fail(display = "Nonce error: {}", _0)] #[error("Nonce error: {0}")]
Nonce(String), Nonce(String),
/// Slatepack address parsing error /// Slatepack address parsing error
#[fail(display = "SlatepackAddress error: {}", _0)] #[error("SlatepackAddress error: {0}")]
SlatepackAddress(String), SlatepackAddress(String),
/// Retrieving Stored Tx /// Retrieving Stored Tx
#[fail(display = "Stored Tx error: {}", _0)] #[error("Stored Tx error: {0}")]
StoredTx(String), StoredTx(String),
/// Other /// Other
#[fail(display = "Generic error: {}", _0)] #[error("Generic error: {0}")]
GenericError(String), GenericError(String),
} }
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let show_bt = match env::var("RUST_BACKTRACE") {
Ok(r) => r == "1",
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!("\n Backtrace: {}", backtrace);
let mut output = inner_output;
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 string
pub fn cause_string(&self) -> String {
match self.cause() {
Some(k) => format!("{}", k),
None => "Unknown".to_string(),
}
}
/// 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<io::Error> for Error {
fn from(_error: io::Error) -> Error {
Error {
inner: Context::new(ErrorKind::IO),
}
}
}
impl From<grin_keychain::Error> for Error {
fn from(error: grin_keychain::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Keychain(error)),
}
}
}
impl From<libtx::Error> for Error {
fn from(error: crate::grin_core::libtx::Error) -> Error {
Error {
inner: Context::new(ErrorKind::LibTX(error.kind())),
}
}
}
impl From<transaction::Error> for Error {
fn from(error: transaction::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Transaction(error)),
}
}
}
impl From<crate::grin_core::ser::Error> for Error {
fn from(error: crate::grin_core::ser::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Deser(error)),
}
}
}
impl From<secp::Error> for Error {
fn from(error: secp::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Secp(error)),
}
}
}
impl From<committed::Error> for Error {
fn from(error: committed::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Committed(error)),
}
}
}
impl From<grin_store::Error> for Error { impl From<grin_store::Error> for Error {
fn from(error: grin_store::Error) -> Error { fn from(error: grin_store::Error) -> Error {
Error::from(ErrorKind::Backend(format!("{}", error))) Error::Backend(format!("{}", error))
}
}
impl From<util::OnionV3AddressError> for Error {
fn from(error: util::OnionV3AddressError) -> Error {
Error::from(ErrorKind::OnionV3Address(error))
} }
} }
impl From<age::EncryptError> for Error { impl From<age::EncryptError> for Error {
fn from(error: age::EncryptError) -> Error { fn from(error: age::EncryptError) -> Error {
Error { Error::Age(format!("{}", error))
inner: Context::new(ErrorKind::Age(format!("{}", error))),
}
} }
} }
impl From<age::DecryptError> for Error { impl From<age::DecryptError> for Error {
fn from(error: age::DecryptError) -> Error { fn from(error: age::DecryptError) -> Error {
Error { Error::Age(format!("{}", error))
inner: Context::new(ErrorKind::Age(format!("{}", error))),
} }
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Error {
Error::IO(e.to_string())
} }
} }
impl From<&str> for Error { impl From<&str> for Error {
fn from(error: &str) -> Error { fn from(error: &str) -> Error {
Error { Error::Age(format!("Bech32 Key Encoding - {}", error))
inner: Context::new(ErrorKind::Age(format!("Bech32 Key Encoding - {}", error))),
}
} }
} }
impl From<bech32::Error> for Error { impl From<bech32::Error> for Error {
fn from(error: bech32::Error) -> Error { fn from(error: bech32::Error) -> Error {
Error { Error::SlatepackAddress(format!("{}", error))
inner: Context::new(ErrorKind::SlatepackAddress(format!("{}", error))),
}
} }
} }

View file

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
//! Wallet key management functions //! Wallet key management functions
use crate::error::{Error, ErrorKind}; use crate::error::Error;
use crate::grin_keychain::{ChildNumber, ExtKeychain, Identifier, Keychain}; use crate::grin_keychain::{ChildNumber, ExtKeychain, Identifier, Keychain};
use crate::grin_util::secp::key::SecretKey; use crate::grin_util::secp::key::SecretKey;
use crate::types::{AcctPathMapping, NodeClient, WalletBackend}; use crate::types::{AcctPathMapping, NodeClient, WalletBackend};
@ -72,7 +72,7 @@ where
{ {
let label = label.to_owned(); let label = label.to_owned();
if wallet.acct_path_iter().any(|l| l.label == label) { if wallet.acct_path_iter().any(|l| l.label == label) {
return Err(ErrorKind::AccountLabelAlreadyExists(label).into()); return Err(Error::AccountLabelAlreadyExists(label));
} }
// We're always using paths at m/k/0 for parent keys for output derivations // We're always using paths at m/k/0 for parent keys for output derivations

View file

@ -25,7 +25,7 @@ use crate::grin_util::secp::{ContextFlag, Secp256k1};
use crate::grin_util::Mutex; use crate::grin_util::Mutex;
use crate::grin_util::{from_hex, ToHex}; use crate::grin_util::{from_hex, ToHex};
use crate::internal::{keys, updater}; use crate::internal::{keys, updater};
use crate::{types::*, ErrorKind}; use crate::types::*;
use crate::{wallet_lock, Error, OutputCommitMapping}; use crate::{wallet_lock, Error, OutputCommitMapping};
use blake2_rfc::blake2b::blake2b; use blake2_rfc::blake2b::blake2b;
use std::cmp; use std::cmp;
@ -187,12 +187,11 @@ where
// Scanning outputs // Scanning outputs
for output in outputs.iter() { for output in outputs.iter() {
let (commit, proof, is_coinbase, height, mmr_index) = output; let (commit, proof, is_coinbase, height, mmr_index) = output;
let rewind_hash = from_hex(vw.rewind_hash.as_str()).map_err(|e| { let rewind_hash = from_hex(vw.rewind_hash.as_str())
ErrorKind::RewindHash(format!("Unable to decode rewind hash: {}", e)) .map_err(|e| Error::RewindHash(format!("Unable to decode rewind hash: {}", e)))?;
})?;
let rewind_nonce = blake2b(32, &commit.0, &rewind_hash); let rewind_nonce = blake2b(32, &commit.0, &rewind_hash);
let nonce = SecretKey::from_slice(&secp, rewind_nonce.as_bytes()) let nonce = SecretKey::from_slice(&secp, rewind_nonce.as_bytes())
.map_err(|e| ErrorKind::Nonce(format!("Unable to create nonce: {}", e)))?; .map_err(|e| Error::Nonce(format!("Unable to create nonce: {}", e)))?;
let info = secp.rewind_bullet_proof(*commit, nonce.clone(), None, *proof); let info = secp.rewind_bullet_proof(*commit, nonce.clone(), None, *proof);
if info.is_err() { if info.is_err() {

View file

@ -15,7 +15,7 @@
//! Selection of inputs for building transactions //! Selection of inputs for building transactions
use crate::address; use crate::address;
use crate::error::{Error, ErrorKind}; use crate::error::Error;
use crate::grin_core::core::amount_to_hr_string; use crate::grin_core::core::amount_to_hr_string;
use crate::grin_core::libtx::{ use crate::grin_core::libtx::{
build, build,
@ -72,16 +72,15 @@ where
false, false,
)?; )?;
if amount_includes_fee { if amount_includes_fee {
slate.amount = slate slate.amount = slate.amount.checked_sub(fee).ok_or(Error::GenericError(
.amount
.checked_sub(fee)
.ok_or(ErrorKind::GenericError(
format!("Transaction amount is too small to include fee").into(), format!("Transaction amount is too small to include fee").into(),
))?; ))?;
}; };
if fixed_fee.map(|f| fee != f).unwrap_or(false) { if fixed_fee.map(|f| fee != f).unwrap_or(false) {
return Err(ErrorKind::Fee("The initially selected fee is not sufficient".into()).into()); return Err(Error::Fee(
"The initially selected fee is not sufficient".into(),
));
} }
// Update the fee on the slate so we account for this when building the tx. // Update the fee on the slate so we account for this when building the tx.
@ -192,7 +191,7 @@ where
let sender_address_path = match context.payment_proof_derivation_index { let sender_address_path = match context.payment_proof_derivation_index {
Some(p) => p, Some(p) => p,
None => { None => {
return Err(ErrorKind::PaymentProof( return Err(Error::PaymentProof(
"Payment proof derivation index required".to_owned(), "Payment proof derivation index required".to_owned(),
) )
.into()); .into());
@ -420,24 +419,22 @@ where
}; };
if total == 0 { if total == 0 {
return Err(ErrorKind::NotEnoughFunds { return Err(Error::NotEnoughFunds {
available: 0, available: 0,
available_disp: amount_to_hr_string(0, false), available_disp: amount_to_hr_string(0, false),
needed: amount_with_fee as u64, needed: amount_with_fee as u64,
needed_disp: amount_to_hr_string(amount_with_fee as u64, false), needed_disp: amount_to_hr_string(amount_with_fee as u64, false),
} });
.into());
} }
// The amount with fee is more than the total values of our max outputs // The amount with fee is more than the total values of our max outputs
if total < amount_with_fee && coins.len() == max_outputs { if total < amount_with_fee && coins.len() == max_outputs {
return Err(ErrorKind::NotEnoughFunds { return Err(Error::NotEnoughFunds {
available: total, available: total,
available_disp: amount_to_hr_string(total, false), available_disp: amount_to_hr_string(total, false),
needed: amount_with_fee as u64, needed: amount_with_fee as u64,
needed_disp: amount_to_hr_string(amount_with_fee as u64, false), needed_disp: amount_to_hr_string(amount_with_fee as u64, false),
} });
.into());
} }
let num_outputs = change_outputs + 1; let num_outputs = change_outputs + 1;
@ -455,13 +452,12 @@ where
while total < amount_with_fee { while total < amount_with_fee {
// End the loop if we have selected all the outputs and still not enough funds // End the loop if we have selected all the outputs and still not enough funds
if coins.len() == max_outputs { if coins.len() == max_outputs {
return Err(ErrorKind::NotEnoughFunds { return Err(Error::NotEnoughFunds {
available: total as u64, available: total as u64,
available_disp: amount_to_hr_string(total, false), available_disp: amount_to_hr_string(total, false),
needed: amount_with_fee as u64, needed: amount_with_fee as u64,
needed_disp: amount_to_hr_string(amount_with_fee as u64, false), needed_disp: amount_to_hr_string(amount_with_fee as u64, false),
} });
.into());
} }
// select some spendable coins from the wallet // select some spendable coins from the wallet
@ -486,7 +482,7 @@ where
// If original amount includes fee, the new amount should // If original amount includes fee, the new amount should
// be reduced, to accommodate the fee. // be reduced, to accommodate the fee.
let new_amount = match amount_includes_fee { let new_amount = match amount_includes_fee {
true => amount.checked_sub(fee).ok_or(ErrorKind::GenericError( true => amount.checked_sub(fee).ok_or(Error::GenericError(
format!("Transaction amount is too small to include fee").into(), format!("Transaction amount is too small to include fee").into(),
))?, ))?,
false => amount, false => amount,
@ -688,7 +684,7 @@ where
if update_fee { if update_fee {
slate.fee_fields = context slate.fee_fields = context
.fee .fee
.ok_or_else(|| ErrorKind::Fee("Missing fee fields".into()))?; .ok_or_else(|| Error::Fee("Missing fee fields".into()))?;
} }
let keychain = wallet.keychain(keychain_mask)?; let keychain = wallet.keychain(keychain_mask)?;

View file

@ -29,7 +29,7 @@ use crate::slate::Slate;
use crate::types::{Context, NodeClient, StoredProofInfo, TxLogEntryType, WalletBackend}; use crate::types::{Context, NodeClient, StoredProofInfo, TxLogEntryType, WalletBackend};
use crate::util::OnionV3Address; use crate::util::OnionV3Address;
use crate::InitTxArgs; use crate::InitTxArgs;
use crate::{address, Error, ErrorKind}; use crate::{address, Error};
use ed25519_dalek::Keypair as DalekKeypair; use ed25519_dalek::Keypair as DalekKeypair;
use ed25519_dalek::PublicKey as DalekPublicKey; use ed25519_dalek::PublicKey as DalekPublicKey;
use ed25519_dalek::SecretKey as DalekSecretKey; use ed25519_dalek::SecretKey as DalekSecretKey;
@ -353,15 +353,15 @@ where
} }
let tx_vec = updater::retrieve_txs(wallet, tx_id, tx_slate_id, Some(&parent_key_id), false)?; let tx_vec = updater::retrieve_txs(wallet, tx_id, tx_slate_id, Some(&parent_key_id), false)?;
if tx_vec.len() != 1 { if tx_vec.len() != 1 {
return Err(ErrorKind::TransactionDoesntExist(tx_id_string).into()); return Err(Error::TransactionDoesntExist(tx_id_string));
} }
let tx = tx_vec[0].clone(); let tx = tx_vec[0].clone();
match tx.tx_type { match tx.tx_type {
TxLogEntryType::TxSent | TxLogEntryType::TxReceived | TxLogEntryType::TxReverted => {} TxLogEntryType::TxSent | TxLogEntryType::TxReceived | TxLogEntryType::TxReverted => {}
_ => return Err(ErrorKind::TransactionNotCancellable(tx_id_string).into()), _ => return Err(Error::TransactionNotCancellable(tx_id_string)),
} }
if tx.confirmed { if tx.confirmed {
return Err(ErrorKind::TransactionNotCancellable(tx_id_string).into()); return Err(Error::TransactionNotCancellable(tx_id_string));
} }
// get outputs associated with tx // get outputs associated with tx
let res = updater::retrieve_outputs( let res = updater::retrieve_outputs(
@ -405,7 +405,7 @@ where
} }
let mut tx = match tx { let mut tx = match tx {
Some(t) => t, Some(t) => t,
None => return Err(ErrorKind::TransactionDoesntExist(slate.id.to_string()).into()), None => return Err(Error::TransactionDoesntExist(slate.id.to_string())),
}; };
let parent_key = tx.parent_key_id.clone(); let parent_key = tx.parent_key_id.clone();
{ {
@ -487,7 +487,7 @@ pub fn create_payment_proof_signature(
let d_skey = match DalekSecretKey::from_bytes(&sec_key.0) { let d_skey = match DalekSecretKey::from_bytes(&sec_key.0) {
Ok(k) => k, Ok(k) => k,
Err(e) => { Err(e) => {
return Err(ErrorKind::ED25519Key(format!("{}", e)).into()); return Err(Error::ED25519Key(format!("{}", e)));
} }
}; };
let pub_key: DalekPublicKey = (&d_skey).into(); let pub_key: DalekPublicKey = (&d_skey).into();
@ -513,56 +513,50 @@ where
{ {
let tx_vec = updater::retrieve_txs(wallet, None, Some(slate.id), Some(parent_key_id), false)?; let tx_vec = updater::retrieve_txs(wallet, None, Some(slate.id), Some(parent_key_id), false)?;
if tx_vec.is_empty() { if tx_vec.is_empty() {
return Err(ErrorKind::PaymentProof( return Err(Error::PaymentProof(
"TxLogEntry with original proof info not found (is account correct?)".to_owned(), "TxLogEntry with original proof info not found (is account correct?)".to_owned(),
) ));
.into());
} }
let orig_proof_info = tx_vec[0].clone().payment_proof; let orig_proof_info = tx_vec[0].clone().payment_proof;
if orig_proof_info.is_some() && slate.payment_proof.is_none() { if orig_proof_info.is_some() && slate.payment_proof.is_none() {
return Err(ErrorKind::PaymentProof( return Err(Error::PaymentProof(
"Expected Payment Proof for this Transaction is not present".to_owned(), "Expected Payment Proof for this Transaction is not present".to_owned(),
) ));
.into());
} }
if let Some(ref p) = slate.clone().payment_proof { if let Some(ref p) = slate.clone().payment_proof {
let orig_proof_info = match orig_proof_info { let orig_proof_info = match orig_proof_info {
Some(p) => p.clone(), Some(p) => p.clone(),
None => { None => {
return Err(ErrorKind::PaymentProof( return Err(Error::PaymentProof(
"Original proof info not stored in tx".to_owned(), "Original proof info not stored in tx".to_owned(),
) ));
.into());
} }
}; };
let keychain = wallet.keychain(keychain_mask)?; let keychain = wallet.keychain(keychain_mask)?;
let index = match context.payment_proof_derivation_index { let index = match context.payment_proof_derivation_index {
Some(i) => i, Some(i) => i,
None => { None => {
return Err(ErrorKind::PaymentProof( return Err(Error::PaymentProof(
"Payment proof derivation index required".to_owned(), "Payment proof derivation index required".to_owned(),
) ));
.into());
} }
}; };
let orig_sender_sk = let orig_sender_sk =
address::address_from_derivation_path(&keychain, parent_key_id, index)?; address::address_from_derivation_path(&keychain, parent_key_id, index)?;
let orig_sender_address = OnionV3Address::from_private(&orig_sender_sk.0)?; let orig_sender_address = OnionV3Address::from_private(&orig_sender_sk.0)?;
if p.sender_address != orig_sender_address.to_ed25519()? { if p.sender_address != orig_sender_address.to_ed25519()? {
return Err(ErrorKind::PaymentProof( return Err(Error::PaymentProof(
"Sender address on slate does not match original sender address".to_owned(), "Sender address on slate does not match original sender address".to_owned(),
) ));
.into());
} }
if orig_proof_info.receiver_address != p.receiver_address { if orig_proof_info.receiver_address != p.receiver_address {
return Err(ErrorKind::PaymentProof( return Err(Error::PaymentProof(
"Recipient address on slate does not match original recipient address".to_owned(), "Recipient address on slate does not match original recipient address".to_owned(),
) ));
.into());
} }
let msg = payment_proof_message( let msg = payment_proof_message(
slate.amount, slate.amount,
@ -572,15 +566,14 @@ where
let sig = match p.receiver_signature { let sig = match p.receiver_signature {
Some(s) => s, Some(s) => s,
None => { None => {
return Err(ErrorKind::PaymentProof( return Err(Error::PaymentProof(
"Recipient did not provide requested proof signature".to_owned(), "Recipient did not provide requested proof signature".to_owned(),
) ));
.into());
} }
}; };
if p.receiver_address.verify(&msg, &sig).is_err() { if p.receiver_address.verify(&msg, &sig).is_err() {
return Err(ErrorKind::PaymentProof("Invalid proof signature".to_owned()).into()); return Err(Error::PaymentProof("Invalid proof signature".to_owned()));
}; };
} }
Ok(()) Ok(())

View file

@ -25,16 +25,12 @@
use grin_wallet_config as config; use grin_wallet_config as config;
use grin_wallet_util::grin_core; use grin_wallet_util::grin_core;
use grin_wallet_util::grin_keychain; use grin_wallet_util::grin_keychain;
use grin_wallet_util::grin_store;
use grin_wallet_util::grin_util; use grin_wallet_util::grin_util;
use grin_wallet_util as util; use grin_wallet_util as util;
use blake2_rfc as blake2; use blake2_rfc as blake2;
use failure;
extern crate failure_derive;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[macro_use] #[macro_use]
@ -55,7 +51,7 @@ pub mod slate_versions;
pub mod slatepack; pub mod slatepack;
mod types; mod types;
pub use crate::error::{Error, ErrorKind}; pub use crate::error::Error;
pub use crate::slate::{ParticipantData, Slate, SlateState}; pub use crate::slate::{ParticipantData, Slate, SlateState};
pub use crate::slate_versions::v4::sig_is_blank; pub use crate::slate_versions::v4::sig_is_blank;
pub use crate::slate_versions::{ pub use crate::slate_versions::{

View file

@ -15,7 +15,7 @@
//! Functions for building partial transactions to be passed //! Functions for building partial transactions to be passed
//! around during an interactive wallet exchange //! around during an interactive wallet exchange
use crate::error::{Error, ErrorKind}; use crate::error::Error;
use crate::grin_core::core::amount_to_hr_string; use crate::grin_core::core::amount_to_hr_string;
use crate::grin_core::core::transaction::{ use crate::grin_core::core::transaction::{
FeeFields, Input, Inputs, KernelFeatures, NRDRelativeHeight, Output, OutputFeatures, FeeFields, Input, Inputs, KernelFeatures, NRDRelativeHeight, Output, OutputFeatures,
@ -196,7 +196,7 @@ impl Slate {
pub fn tx_or_err(&self) -> Result<&Transaction, Error> { pub fn tx_or_err(&self) -> Result<&Transaction, Error> {
match &self.tx { match &self.tx {
Some(t) => Ok(t), Some(t) => Ok(t),
None => Err(ErrorKind::SlateTransactionRequired.into()), None => Err(Error::SlateTransactionRequired),
} }
} }
@ -204,7 +204,7 @@ impl Slate {
pub fn tx_or_err_mut(&mut self) -> Result<&mut Transaction, Error> { pub fn tx_or_err_mut(&mut self) -> Result<&mut Transaction, Error> {
match &mut self.tx { match &mut self.tx {
Some(t) => Ok(t), Some(t) => Ok(t),
None => Err(ErrorKind::SlateTransactionRequired.into()), None => Err(Error::SlateTransactionRequired),
} }
} }
@ -220,7 +220,7 @@ impl Slate {
/// Throw error if this can't be done /// Throw error if this can't be done
pub fn deserialize_upgrade(slate_json: &str) -> Result<Slate, Error> { pub fn deserialize_upgrade(slate_json: &str) -> Result<Slate, Error> {
let v_slate: VersionedSlate = let v_slate: VersionedSlate =
serde_json::from_str(slate_json).map_err(|_| ErrorKind::SlateVersionParse)?; serde_json::from_str(slate_json).map_err(|_| Error::SlateVersionParse)?;
Slate::upgrade(v_slate) Slate::upgrade(v_slate)
} }
@ -352,26 +352,22 @@ impl Slate {
0 => Ok(KernelFeatures::Plain { 0 => Ok(KernelFeatures::Plain {
fee: self.fee_fields, fee: self.fee_fields,
}), }),
1 => Err(ErrorKind::InvalidKernelFeatures(1).into()), 1 => Err(Error::InvalidKernelFeatures(1)),
2 => Ok(KernelFeatures::HeightLocked { 2 => Ok(KernelFeatures::HeightLocked {
fee: self.fee_fields, fee: self.fee_fields,
lock_height: match &self.kernel_features_args { lock_height: match &self.kernel_features_args {
Some(a) => a.lock_height, Some(a) => a.lock_height,
None => { None => return Err(Error::KernelFeaturesMissing(format!("lock_height"))),
return Err(ErrorKind::KernelFeaturesMissing(format!("lock_height")).into())
}
}, },
}), }),
3 => Ok(KernelFeatures::NoRecentDuplicate { 3 => Ok(KernelFeatures::NoRecentDuplicate {
fee: self.fee_fields, fee: self.fee_fields,
relative_height: match &self.kernel_features_args { relative_height: match &self.kernel_features_args {
Some(a) => NRDRelativeHeight::new(a.lock_height)?, Some(a) => NRDRelativeHeight::new(a.lock_height)?,
None => { None => return Err(Error::KernelFeaturesMissing(format!("lock_height"))),
return Err(ErrorKind::KernelFeaturesMissing(format!("lock_height")).into())
}
}, },
}), }),
n => Err(ErrorKind::UnknownKernelFeatures(n).into()), n => Err(Error::UnknownKernelFeatures(n)),
} }
} }
@ -436,11 +432,11 @@ impl Slate {
.map(|p| &p.public_nonce) .map(|p| &p.public_nonce)
.collect(); .collect();
if pub_nonces.len() == 0 { if pub_nonces.len() == 0 {
return Err(ErrorKind::Commit(format!("Participant nonces cannot be empty")).into()); return Err(Error::Commit(format!("Participant nonces cannot be empty")));
} }
match PublicKey::from_combination(secp, pub_nonces) { match PublicKey::from_combination(secp, pub_nonces) {
Ok(k) => Ok(k), Ok(k) => Ok(k),
Err(e) => Err(ErrorKind::Secp(e).into()), Err(e) => Err(Error::Secp(e)),
} }
} }
@ -452,13 +448,13 @@ impl Slate {
.map(|p| &p.public_blind_excess) .map(|p| &p.public_blind_excess)
.collect(); .collect();
if pub_blinds.len() == 0 { if pub_blinds.len() == 0 {
return Err( return Err(Error::Commit(format!(
ErrorKind::Commit(format!("Participant Blind sums cannot be empty")).into(), "Participant Blind sums cannot be empty"
); )));
} }
match PublicKey::from_combination(secp, pub_blinds) { match PublicKey::from_combination(secp, pub_blinds) {
Ok(k) => Ok(k), Ok(k) => Ok(k),
Err(e) => Err(ErrorKind::Secp(e).into()), Err(e) => Err(Error::Secp(e)),
} }
} }
@ -553,9 +549,11 @@ impl Slate {
if fee > tx.fee() { if fee > tx.fee() {
// apply fee mask past HF4 // apply fee mask past HF4
return Err( return Err(Error::Fee(format!(
ErrorKind::Fee(format!("Fee Dispute Error: {}, {}", tx.fee(), fee,)).into(), "Fee Dispute Error: {}, {}",
); tx.fee(),
fee,
)));
} }
if fee > self.amount + self.fee_fields.fee() { if fee > self.amount + self.fee_fields.fee() {
@ -565,7 +563,7 @@ impl Slate {
amount_to_hr_string(self.amount + self.fee_fields.fee(), false) amount_to_hr_string(self.amount + self.fee_fields.fee(), false)
); );
info!("{}", reason); info!("{}", reason);
return Err(ErrorKind::Fee(reason).into()); return Err(Error::Fee(reason));
} }
Ok(()) Ok(())

View file

@ -24,7 +24,7 @@ use crate::grin_core::global;
use crate::grin_core::ser::{self, Readable, Reader, Writeable, Writer}; use crate::grin_core::ser::{self, Readable, Reader, Writeable, Writer};
use crate::grin_util::secp::key::SecretKey; use crate::grin_util::secp::key::SecretKey;
use crate::util::OnionV3Address; use crate::util::OnionV3Address;
use crate::{Error, ErrorKind}; use crate::Error;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
@ -91,7 +91,7 @@ impl TryFrom<&str> for SlatepackAddress {
let pub_key = match edDalekPublicKey::from_bytes(&bytes) { let pub_key = match edDalekPublicKey::from_bytes(&bytes) {
Ok(k) => k, Ok(k) => k,
Err(e) => { Err(e) => {
return Err(ErrorKind::ED25519Key(format!("{}", e)).into()); return Err(Error::ED25519Key(format!("{}", e)));
} }
}; };
Ok(SlatepackAddress { hrp, pub_key }) Ok(SlatepackAddress { hrp, pub_key })
@ -127,9 +127,9 @@ impl TryFrom<&SlatepackAddress> for xDalekPublicKey {
let ep = match cep.decompress() { let ep = match cep.decompress() {
Some(p) => p, Some(p) => p,
None => { None => {
return Err( return Err(Error::ED25519Key(
ErrorKind::ED25519Key("Can't decompress ed25519 Edwards Point".into()).into(), "Can't decompress ed25519 Edwards Point".into(),
); ));
} }
}; };
let res = xDalekPublicKey::from(ep.to_montgomery().to_bytes()); let res = xDalekPublicKey::from(ep.to_montgomery().to_bytes());
@ -143,11 +143,10 @@ impl TryFrom<&SecretKey> for SlatepackAddress {
let d_skey = match edDalekSecretKey::from_bytes(&key.0) { let d_skey = match edDalekSecretKey::from_bytes(&key.0) {
Ok(k) => k, Ok(k) => k,
Err(e) => { Err(e) => {
return Err(ErrorKind::ED25519Key(format!( return Err(Error::ED25519Key(format!(
"Can't create slatepack address from SecretKey: {}", "Can't create slatepack address from SecretKey: {}",
e e
)) )));
.into());
} }
}; };
let d_pub_key: edDalekPublicKey = (&d_skey).into(); let d_pub_key: edDalekPublicKey = (&d_skey).into();

View file

@ -20,7 +20,7 @@
// 3. Base58 encode bytes from step 2 // 3. Base58 encode bytes from step 2
// Finally add armor framing and space/newline formatting as desired // Finally add armor framing and space/newline formatting as desired
use crate::{Error, ErrorKind}; use crate::Error;
use grin_wallet_util::{byte_ser, grin_core::global::max_tx_weight}; use grin_wallet_util::{byte_ser, grin_core::global::max_tx_weight};
use regex::Regex; use regex::Regex;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
@ -97,7 +97,7 @@ impl SlatepackArmor {
// Decode payload from base58 // Decode payload from base58
let base_decode = bs58::decode(&clean_payload) let base_decode = bs58::decode(&clean_payload)
.into_vec() .into_vec()
.map_err(|_| ErrorKind::SlatepackDeser("Bad bytes".into()))?; .map_err(|_| Error::SlatepackDeser("Bad bytes".into()))?;
let error_code = &base_decode[0..4]; let error_code = &base_decode[0..4];
let slatepack_bytes = &base_decode[4..]; let slatepack_bytes = &base_decode[4..];
// Make sure the error check code is valid for the slate data // Make sure the error check code is valid for the slate data
@ -109,7 +109,7 @@ impl SlatepackArmor {
/// Encode an armored slatepack /// Encode an armored slatepack
pub fn encode(slatepack: &Slatepack) -> Result<String, Error> { pub fn encode(slatepack: &Slatepack) -> Result<String, Error> {
let slatepack_bytes = byte_ser::to_bytes(&SlatepackBin(slatepack.clone())) let slatepack_bytes = byte_ser::to_bytes(&SlatepackBin(slatepack.clone()))
.map_err(|_| ErrorKind::SlatepackSer)?; .map_err(|_| Error::SlatepackSer)?;
let encoded_slatepack = base58check(&slatepack_bytes)?; let encoded_slatepack = base58check(&slatepack_bytes)?;
let formatted_slatepack = format_slatepack(&format!("{}{}", HEADER, encoded_slatepack))?; let formatted_slatepack = format_slatepack(&format!("{}{}", HEADER, encoded_slatepack))?;
Ok(format!("{}{}\n", formatted_slatepack, FOOTER)) Ok(format!("{}{}\n", formatted_slatepack, FOOTER))
@ -122,32 +122,29 @@ fn error_check(error_code: &[u8], slate_bytes: &[u8]) -> Result<(), Error> {
if error_code.iter().eq(new_check.iter()) { if error_code.iter().eq(new_check.iter()) {
Ok(()) Ok(())
} else { } else {
Err(ErrorKind::InvalidSlatepackData( Err(Error::InvalidSlatepackData(
"Bad slate error code- some data was corrupted".to_string(), "Bad slate error code- some data was corrupted".to_string(),
) ))
.into())
} }
} }
// Checks header framing bytes and returns an error if they are invalid // Checks header framing bytes and returns an error if they are invalid
fn check_header(header: &[u8]) -> Result<(), Error> { fn check_header(header: &[u8]) -> Result<(), Error> {
let framing = let framing = str::from_utf8(header).map_err(|_| Error::SlatepackDeser("Bad bytes".into()))?;
str::from_utf8(header).map_err(|_| ErrorKind::SlatepackDeser("Bad bytes".into()))?;
if HEADER_REGEX.is_match(framing) { if HEADER_REGEX.is_match(framing) {
Ok(()) Ok(())
} else { } else {
Err(ErrorKind::InvalidSlatepackData("Bad armor header".to_string()).into()) Err(Error::InvalidSlatepackData("Bad armor header".to_string()))
} }
} }
// Checks footer framing bytes and returns an error if they are invalid // Checks footer framing bytes and returns an error if they are invalid
fn check_footer(footer: &[u8]) -> Result<(), Error> { fn check_footer(footer: &[u8]) -> Result<(), Error> {
let framing = let framing = str::from_utf8(footer).map_err(|_| Error::SlatepackDeser("Bad bytes".into()))?;
str::from_utf8(footer).map_err(|_| ErrorKind::SlatepackDeser("Bad bytes".into()))?;
if FOOTER_REGEX.is_match(framing) { if FOOTER_REGEX.is_match(framing) {
Ok(()) Ok(())
} else { } else {
Err(ErrorKind::InvalidSlatepackData("Bad armor footer".to_string()).into()) Err(Error::InvalidSlatepackData("Bad armor footer".to_string()))
} }
} }

View file

@ -16,11 +16,11 @@ use std::convert::TryFrom;
use std::str; use std::str;
use super::armor::HEADER; use super::armor::HEADER;
use crate::Error;
use crate::{ use crate::{
slatepack, Slate, SlateVersion, Slatepack, SlatepackAddress, SlatepackArmor, SlatepackBin, slatepack, Slate, SlateVersion, Slatepack, SlatepackAddress, SlatepackArmor, SlatepackBin,
VersionedBinSlate, VersionedSlate, VersionedBinSlate, VersionedSlate,
}; };
use crate::{Error, ErrorKind};
use grin_wallet_util::byte_ser; use grin_wallet_util::byte_ser;
@ -53,7 +53,7 @@ impl<'a> Slatepacker<'a> {
let data_len = data.len() as u64; let data_len = data.len() as u64;
if data_len < slatepack::min_size() || data_len > slatepack::max_size() { if data_len < slatepack::min_size() || data_len > slatepack::max_size() {
let msg = format!("Data invalid length"); let msg = format!("Data invalid length");
return Err(ErrorKind::SlatepackDeser(msg).into()); return Err(Error::SlatepackDeser(msg));
} }
let test_header = &data[..HEADER.len()]; let test_header = &data[..HEADER.len()];
@ -76,11 +76,11 @@ impl<'a> Slatepacker<'a> {
debug!("Not a valid binary slatepack: {} - Will try JSON", e); debug!("Not a valid binary slatepack: {} - Will try JSON", e);
let content = String::from_utf8(data).map_err(|e| { let content = String::from_utf8(data).map_err(|e| {
let msg = format!("{}", e); let msg = format!("{}", e);
ErrorKind::SlatepackDeser(msg) Error::SlatepackDeser(msg)
})?; })?;
serde_json::from_str(&content).map_err(|e| { serde_json::from_str(&content).map_err(|e| {
let msg = format!("Error reading JSON slatepack: {}", e); let msg = format!("Error reading JSON slatepack: {}", e);
ErrorKind::SlatepackDeser(msg) Error::SlatepackDeser(msg)
})? })?
} }
}; };
@ -95,10 +95,9 @@ impl<'a> Slatepacker<'a> {
/// Create slatepack from slate and args /// Create slatepack from slate and args
pub fn create_slatepack(&self, slate: &Slate) -> Result<Slatepack, Error> { pub fn create_slatepack(&self, slate: &Slate) -> Result<Slatepack, Error> {
let out_slate = VersionedSlate::into_version(slate.clone(), SlateVersion::V4)?; let out_slate = VersionedSlate::into_version(slate.clone(), SlateVersion::V4)?;
let bin_slate = let bin_slate = VersionedBinSlate::try_from(out_slate).map_err(|_| Error::SlatepackSer)?;
VersionedBinSlate::try_from(out_slate).map_err(|_| ErrorKind::SlatepackSer)?;
let mut slatepack = Slatepack::default(); let mut slatepack = Slatepack::default();
slatepack.payload = byte_ser::to_bytes(&bin_slate).map_err(|_| ErrorKind::SlatepackSer)?; slatepack.payload = byte_ser::to_bytes(&bin_slate).map_err(|_| Error::SlatepackSer)?;
slatepack.sender = self.0.sender.clone(); slatepack.sender = self.0.sender.clone();
slatepack.try_encrypt_payload(self.0.recipients.clone())?; slatepack.try_encrypt_payload(self.0.recipients.clone())?;
Ok(slatepack) Ok(slatepack)
@ -115,7 +114,7 @@ impl<'a> Slatepacker<'a> {
byte_ser::from_bytes::<VersionedBinSlate>(&slatepack.payload).map_err(|e| { byte_ser::from_bytes::<VersionedBinSlate>(&slatepack.payload).map_err(|e| {
error!("Error reading slate from armored slatepack: {}", e); error!("Error reading slate from armored slatepack: {}", e);
let msg = format!("{}", e); let msg = format!("{}", e);
ErrorKind::SlatepackDeser(msg) Error::SlatepackDeser(msg)
})?; })?;
Ok(Slate::upgrade(slate_bin.into())?) Ok(Slate::upgrade(slate_bin.into())?)
} }

View file

@ -21,7 +21,7 @@ use x25519_dalek::StaticSecret;
use crate::dalek_ser; use crate::dalek_ser;
use crate::grin_core::ser::{self, Readable, Reader, Writeable, Writer}; use crate::grin_core::ser::{self, Readable, Reader, Writeable, Writer};
use crate::{Error, ErrorKind}; use crate::Error;
use grin_wallet_util::byte_ser; use grin_wallet_util::byte_ser;
use super::SlatepackAddress; use super::SlatepackAddress;
@ -147,7 +147,7 @@ impl Slatepack {
// Create encrypted metadata, which will be length prefixed // Create encrypted metadata, which will be length prefixed
let bin_meta = SlatepackEncMetadataBin(self.encrypted_meta.clone()); let bin_meta = SlatepackEncMetadataBin(self.encrypted_meta.clone());
let mut to_encrypt = byte_ser::to_bytes(&bin_meta).map_err(|_| ErrorKind::SlatepackSer)?; let mut to_encrypt = byte_ser::to_bytes(&bin_meta).map_err(|_| Error::SlatepackSer)?;
if self.future_test_mode { if self.future_test_mode {
Slatepack::pad_test_data(&mut to_encrypt); Slatepack::pad_test_data(&mut to_encrypt);
@ -213,7 +213,7 @@ impl Slatepack {
let meta_len = Cursor::new(len_bytes).read_u32::<BigEndian>()?; let meta_len = Cursor::new(len_bytes).read_u32::<BigEndian>()?;
self.payload = decrypted.split_off(meta_len as usize + 4); self.payload = decrypted.split_off(meta_len as usize + 4);
let meta = byte_ser::from_bytes::<SlatepackEncMetadataBin>(&decrypted) let meta = byte_ser::from_bytes::<SlatepackEncMetadataBin>(&decrypted)
.map_err(|_| ErrorKind::SlatepackSer)? .map_err(|_| Error::SlatepackSer)?
.0; .0;
self.sender = meta.sender; self.sender = meta.sender;
self.encrypted_meta.recipients = meta.recipients; self.encrypted_meta.recipients = meta.recipients;
@ -777,8 +777,8 @@ fn slatepack_encrypted_meta() -> Result<(), Error> {
slatepack.add_recipient(SlatepackAddress::random()); slatepack.add_recipient(SlatepackAddress::random());
let v_slate = VersionedSlate::into_version(Slate::blank(2, false), SlateVersion::V4)?; let v_slate = VersionedSlate::into_version(Slate::blank(2, false), SlateVersion::V4)?;
let bin_slate = VersionedBinSlate::try_from(v_slate).map_err(|_| ErrorKind::SlatepackSer)?; let bin_slate = VersionedBinSlate::try_from(v_slate).map_err(|_| Error::SlatepackSer)?;
slatepack.payload = byte_ser::to_bytes(&bin_slate).map_err(|_| ErrorKind::SlatepackSer)?; slatepack.payload = byte_ser::to_bytes(&bin_slate).map_err(|_| Error::SlatepackSer)?;
let orig_sp = slatepack.clone(); let orig_sp = slatepack.clone();
@ -826,8 +826,8 @@ fn slatepack_encrypted_meta_future() -> Result<(), Error> {
slatepack.add_recipient(SlatepackAddress::random()); slatepack.add_recipient(SlatepackAddress::random());
let v_slate = VersionedSlate::into_version(Slate::blank(2, false), SlateVersion::V4)?; let v_slate = VersionedSlate::into_version(Slate::blank(2, false), SlateVersion::V4)?;
let bin_slate = VersionedBinSlate::try_from(v_slate).map_err(|_| ErrorKind::SlatepackSer)?; let bin_slate = VersionedBinSlate::try_from(v_slate).map_err(|_| Error::SlatepackSer)?;
slatepack.payload = byte_ser::to_bytes(&bin_slate).map_err(|_| ErrorKind::SlatepackSer)?; slatepack.payload = byte_ser::to_bytes(&bin_slate).map_err(|_| Error::SlatepackSer)?;
let orig_sp = slatepack.clone(); let orig_sp = slatepack.clone();

View file

@ -16,7 +16,7 @@
//! implementation //! implementation
use crate::config::{TorConfig, WalletConfig}; use crate::config::{TorConfig, WalletConfig};
use crate::error::{Error, ErrorKind}; use crate::error::Error;
use crate::grin_core::core::hash::Hash; use crate::grin_core::core::hash::Hash;
use crate::grin_core::core::FeeFields; use crate::grin_core::core::FeeFields;
use crate::grin_core::core::{Output, Transaction, TxKernel}; use crate::grin_core::core::{Output, Transaction, TxKernel};
@ -32,7 +32,6 @@ use crate::InitTxArgs;
use chrono::prelude::*; use chrono::prelude::*;
use ed25519_dalek::PublicKey as DalekPublicKey; use ed25519_dalek::PublicKey as DalekPublicKey;
use ed25519_dalek::Signature as DalekSignature; use ed25519_dalek::Signature as DalekSignature;
use failure::ResultExt;
use rand::rngs::mock::StepRng; use rand::rngs::mock::StepRng;
use rand::thread_rng; use rand::thread_rng;
use serde; use serde;
@ -681,7 +680,7 @@ impl BlockIdentifier {
/// convert to hex string /// convert to hex string
pub fn from_hex(hex: &str) -> Result<BlockIdentifier, Error> { pub fn from_hex(hex: &str) -> Result<BlockIdentifier, Error> {
let hash = let hash =
Hash::from_hex(hex).context(ErrorKind::GenericError("Invalid hex".to_owned()))?; Hash::from_hex(hex).map_err(|e| Error::GenericError(format!("Invalid hex: {}", e)))?;
Ok(BlockIdentifier(hash)) Ok(BlockIdentifier(hash))
} }
} }

View file

@ -20,11 +20,9 @@ use crate::util::secp::key::SecretKey;
use crate::util::{Mutex, ZeroingString}; use crate::util::{Mutex, ZeroingString};
/// Argument parsing and error handling for wallet commands /// Argument parsing and error handling for wallet commands
use clap::ArgMatches; use clap::ArgMatches;
use failure::Fail;
use grin_wallet_api::Owner; use grin_wallet_api::Owner;
use grin_wallet_config::{config_file_exists, TorConfig, WalletConfig}; use grin_wallet_config::{config_file_exists, TorConfig, WalletConfig};
use grin_wallet_controller::command; use grin_wallet_controller::{command, Error};
use grin_wallet_controller::{Error, ErrorKind};
use grin_wallet_impls::{DefaultLCProvider, DefaultWalletImpl}; use grin_wallet_impls::{DefaultLCProvider, DefaultWalletImpl};
use grin_wallet_libwallet::{self, Slate, SlatepackAddress, SlatepackArmor}; use grin_wallet_libwallet::{self, Slate, SlatepackAddress, SlatepackArmor};
use grin_wallet_libwallet::{IssueInvoiceTxArgs, NodeClient, WalletInst, WalletLCProvider}; use grin_wallet_libwallet::{IssueInvoiceTxArgs, NodeClient, WalletInst, WalletLCProvider};
@ -44,22 +42,22 @@ macro_rules! arg_parse {
match $r { match $r {
Ok(res) => res, Ok(res) => res,
Err(e) => { Err(e) => {
return Err(ErrorKind::ArgumentError(format!("{}", e)).into()); return Err(Error::ArgumentError(format!("{}", e)));
} }
} }
}; };
} }
/// Simple error definition, just so we can return errors from all commands /// Simple error definition, just so we can return errors from all commands
/// and let the caller figure out what to do /// and let the caller figure out what to do
#[derive(Clone, Eq, PartialEq, Debug, Fail)] #[derive(Clone, Eq, PartialEq, Debug, thiserror::Error)]
pub enum ParseError { pub enum ParseError {
#[fail(display = "Invalid Arguments: {}", _0)] #[error("Invalid Arguments: {0}")]
ArgumentError(String), ArgumentError(String),
#[fail(display = "Parsing IO error: {}", _0)] #[error("Parsing IO error: {0}")]
IOError(String), IOError(String),
#[fail(display = "Wallet configuration already exists: {}", _0)] #[error("Wallet configuration already exists: {0}")]
WalletExists(String), WalletExists(String),
#[fail(display = "User Cancelled")] #[error("User Cancelled")]
CancelledError, CancelledError,
} }
@ -722,7 +720,7 @@ where
// validate input // validate input
if !Path::new(&file).is_file() { if !Path::new(&file).is_file() {
let msg = format!("File {} not found.", &file); let msg = format!("File {} not found.", &file);
return Err(ErrorKind::GenericError(msg).into()); return Err(Error::GenericError(msg));
} }
Some(file) Some(file)
} }
@ -733,7 +731,7 @@ where
if input_file.is_none() { if input_file.is_none() {
input_slatepack_message = Some(prompt_slatepack().map_err(|e| { input_slatepack_message = Some(prompt_slatepack().map_err(|e| {
let msg = format!("{}", e); let msg = format!("{}", e);
ErrorKind::GenericError(msg) Error::GenericError(msg)
})?) })?)
} }
@ -1299,7 +1297,7 @@ where
} }
_ => { _ => {
let msg = format!("Unknown wallet command, use 'grin-wallet help' for details"); let msg = format!("Unknown wallet command, use 'grin-wallet help' for details");
return Err(ErrorKind::ArgumentError(msg).into()); return Err(Error::ArgumentError(msg));
} }
} }
} }

View file

@ -721,6 +721,6 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
fn wallet_command_line() { fn wallet_command_line() {
let test_dir = "target/test_output/command_line"; let test_dir = "target/test_output/command_line";
if let Err(e) = command_line_test_impl(test_dir) { if let Err(e) = command_line_test_impl(test_dir) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap()); panic!("Libwallet Error: {}", e);
} }
} }

View file

@ -160,7 +160,7 @@ pub fn config_command_wallet(
let mut config_file_name = current_dir.clone(); let mut config_file_name = current_dir.clone();
config_file_name.push("grin-wallet.toml"); config_file_name.push("grin-wallet.toml");
if config_file_name.exists() { if config_file_name.exists() {
return Err(grin_wallet_controller::ErrorKind::ArgumentError( return Err(grin_wallet_controller::Error::ArgumentError(
"grin-wallet.toml already exists in the target directory. Please remove it first" "grin-wallet.toml already exists in the target directory. Please remove it first"
.to_owned(), .to_owned(),
))?; ))?;
@ -472,11 +472,26 @@ pub fn derive_ecdh_key(sec_key_str: &str, other_pubkey: &PublicKey) -> SecretKey
} }
// Types to make working with json responses easier // Types to make working with json responses easier
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize, thiserror::Error)]
pub struct WalletAPIReturnError { pub struct WalletAPIReturnError {
pub message: String, pub message: String,
pub code: i32, pub code: i32,
} }
impl std::fmt::Display for WalletAPIReturnError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} - {}", self.code, &self.message)
}
}
impl From<grin_wallet_controller::Error> for WalletAPIReturnError {
fn from(error: grin_wallet_controller::Error) -> WalletAPIReturnError {
WalletAPIReturnError {
message: error.to_string(),
code: -1,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RetrieveSummaryInfoResp(pub bool, pub WalletInfo); pub struct RetrieveSummaryInfoResp(pub bool, pub WalletInfo);

View file

@ -16,6 +16,7 @@ serde_derive = "1"
ed25519-dalek = "1.0.0-pre.4" ed25519-dalek = "1.0.0-pre.4"
data-encoding = "2" data-encoding = "2"
sha3 = "0.8" sha3 = "0.8"
thiserror = "1"
# For Release # For Release
#grin_core = "4.0.0" #grin_core = "4.0.0"

View file

@ -20,12 +20,14 @@ use sha3::{Digest, Sha3_256};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt; use std::fmt;
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, thiserror::Error, Serialize, Deserialize)]
/// OnionV3 Address Errors /// OnionV3 Address Errors
pub enum OnionV3Error { pub enum OnionV3Error {
/// Error decoding an address from a string /// Error decoding an address from a string
#[error("Address Decoding: {0}")]
AddressDecoding(String), AddressDecoding(String),
/// Error with given private key /// Error with given private key
#[error("Invalid Private Key: {0}")]
InvalidPrivateKey(String), InvalidPrivateKey(String),
} }