Wallet implementation dynamic dispatch (#1235)

* add ability to instantiate wallets with different backend implementations

* test fix
This commit is contained in:
Yeastplume 2018-07-09 18:01:19 +01:00 committed by GitHub
parent 6450b603ea
commit d5a6992be9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 258 additions and 165 deletions

View file

@ -186,6 +186,9 @@ pub struct ServerConfig {
/// Whether to run the web wallet owner listener /// Whether to run the web wallet owner listener
pub run_wallet_owner_api: Option<bool>, pub run_wallet_owner_api: Option<bool>,
/// Whether to use the DB wallet backend implementation
pub use_db_wallet: Option<bool>,
/// Whether to run the test miner (internal, cuckoo 16) /// Whether to run the test miner (internal, cuckoo 16)
pub run_test_miner: Option<bool>, pub run_test_miner: Option<bool>,
@ -212,6 +215,7 @@ impl Default for ServerConfig {
run_tui: None, run_tui: None,
run_wallet_listener: Some(false), run_wallet_listener: Some(false),
run_wallet_owner_api: Some(false), run_wallet_owner_api: Some(false),
use_db_wallet: Some(false),
run_test_miner: Some(false), run_test_miner: Some(false),
test_miner_wallet_url: None, test_miner_wallet_url: None,
} }
@ -323,9 +327,7 @@ impl SyncState {
debug!( debug!(
LOGGER, LOGGER,
"sync_state: sync_status: {:?} -> {:?}", "sync_state: sync_status: {:?} -> {:?}", *status, new_status,
*status,
new_status,
); );
*status = new_status; *status = new_status;

View file

@ -274,7 +274,7 @@ impl LocalServerContainer {
) )
}); });
wallet::controller::foreign_listener(wallet, &self.wallet_config.api_listen_addr()) wallet::controller::foreign_listener(Box::new(wallet), &self.wallet_config.api_listen_addr())
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
panic!( panic!(
"Error creating wallet listener: {:?} Config: {:?}", "Error creating wallet listener: {:?} Config: {:?}",
@ -330,7 +330,7 @@ impl LocalServerContainer {
.unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, config)); .unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, config));
wallet.keychain = Some(keychain); wallet.keychain = Some(keychain);
let _ = let _ =
wallet::controller::owner_single_use(&mut wallet, |api| { wallet::controller::owner_single_use(Box::new(wallet), |api| {
let result = api.issue_send_tx( let result = api.issue_send_tx(
amount, amount,
minimum_confirmations, minimum_confirmations,

View file

@ -40,8 +40,8 @@ pub mod tui;
use std::env::current_dir; use std::env::current_dir;
use std::process::exit; use std::process::exit;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
@ -51,10 +51,9 @@ use daemonize::Daemonize;
use config::GlobalConfig; use config::GlobalConfig;
use core::core::amount_to_hr_string; use core::core::amount_to_hr_string;
use core::global; use core::global;
use keychain::ExtKeychain;
use tui::ui; use tui::ui;
use util::{init_logger, LoggingConfig, LOGGER}; use util::{init_logger, LoggingConfig, LOGGER};
use wallet::{libwallet, FileWallet}; use wallet::{libwallet, wallet_db_exists, FileWallet, LMDBBackend, WalletConfig, WalletInst};
// include build information // include build information
pub mod built_info { pub mod built_info {
@ -296,8 +295,11 @@ fn main() {
.about("basic wallet contents summary")) .about("basic wallet contents summary"))
.subcommand(SubCommand::with_name("init") .subcommand(SubCommand::with_name("init")
.about("Initialize a new wallet seed file.")) .about("Initialize a new wallet seed file.")
.arg(Arg::with_name("db")
.help("Use database backend. (Default: false)")
.short("d")
.long("db")))
.subcommand(SubCommand::with_name("restore") .subcommand(SubCommand::with_name("restore")
.about("Attempt to restore wallet contents from the chain using seed and password. \ .about("Attempt to restore wallet contents from the chain using seed and password. \
NOTE: Backup wallet.* and run `wallet listen` before running restore."))) NOTE: Backup wallet.* and run `wallet listen` before running restore.")))
@ -437,19 +439,14 @@ fn server_command(server_args: Option<&ArgMatches>, mut global_config: GlobalCon
} }
if let Some(true) = server_config.run_wallet_listener { if let Some(true) = server_config.run_wallet_listener {
let use_db = server_config.use_db_wallet == Some(true);
let mut wallet_config = global_config.members.as_ref().unwrap().wallet.clone(); let mut wallet_config = global_config.members.as_ref().unwrap().wallet.clone();
if let Err(_) = wallet::WalletSeed::from_file(&wallet_config) { init_wallet_seed(wallet_config.clone());
wallet::WalletSeed::init_file(&wallet_config)
.expect("Failed to create wallet seed file.");
};
let _ = thread::Builder::new() let _ = thread::Builder::new()
.name("wallet_listener".to_string()) .name("wallet_listener".to_string())
.spawn(move || { .spawn(move || {
let wallet: FileWallet<keychain::ExtKeychain> = let wallet = instantiate_wallet(wallet_config.clone(), "", use_db);
FileWallet::new(wallet_config.clone(), "").unwrap_or_else(|e| {
panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config)
});
wallet::controller::foreign_listener(wallet, &wallet_config.api_listen_addr()) wallet::controller::foreign_listener(wallet, &wallet_config.api_listen_addr())
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
panic!( panic!(
@ -460,19 +457,14 @@ fn server_command(server_args: Option<&ArgMatches>, mut global_config: GlobalCon
}); });
} }
if let Some(true) = server_config.run_wallet_owner_api { if let Some(true) = server_config.run_wallet_owner_api {
let use_db = server_config.use_db_wallet == Some(true);
let mut wallet_config = global_config.members.unwrap().wallet; let mut wallet_config = global_config.members.unwrap().wallet;
if let Err(_) = wallet::WalletSeed::from_file(&wallet_config) { init_wallet_seed(wallet_config.clone());
wallet::WalletSeed::init_file(&wallet_config)
.expect("Failed to create wallet seed file.");
};
let _ = thread::Builder::new() let _ = thread::Builder::new()
.name("wallet_owner_listener".to_string()) .name("wallet_owner_listener".to_string())
.spawn(move || { .spawn(move || {
let wallet: FileWallet<ExtKeychain> = FileWallet::new(wallet_config.clone(), "") let wallet = instantiate_wallet(wallet_config.clone(), "", use_db);
.unwrap_or_else(|e| {
panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config)
});
wallet::controller::owner_listener(wallet, "127.0.0.1:13420").unwrap_or_else(|e| { wallet::controller::owner_listener(wallet, "127.0.0.1:13420").unwrap_or_else(|e| {
panic!( panic!(
"Error creating wallet api listener: {:?} Config: {:?}", "Error creating wallet api listener: {:?} Config: {:?}",
@ -551,6 +543,34 @@ fn client_command(client_args: &ArgMatches, global_config: GlobalConfig) {
} }
} }
fn init_wallet_seed(wallet_config: WalletConfig) {
if let Err(_) = wallet::WalletSeed::from_file(&wallet_config) {
wallet::WalletSeed::init_file(&wallet_config).expect("Failed to create wallet seed file.");
};
}
fn instantiate_wallet(
wallet_config: WalletConfig,
passphrase: &str,
use_db: bool,
) -> Box<WalletInst<keychain::ExtKeychain>> {
if use_db {
let db_wallet = LMDBBackend::new(wallet_config.clone(), "").unwrap_or_else(|e| {
panic!(
"Error creating DB wallet: {} Config: {:?}",
e, wallet_config
);
});
info!(LOGGER, "Using LMDB Backend for wallet");
Box::new(db_wallet)
} else {
let file_wallet = FileWallet::new(wallet_config.clone(), passphrase)
.unwrap_or_else(|e| panic!("Error creating wallet: {} Config: {:?}", e, wallet_config));
info!(LOGGER, "Using File Backend for wallet");
Box::new(file_wallet)
}
}
fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) { fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
// just get defaults from the global config // just get defaults from the global config
let mut wallet_config = global_config.members.unwrap().wallet; let mut wallet_config = global_config.members.unwrap().wallet;
@ -574,8 +594,26 @@ fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
// Derive the keychain based on seed from seed file and specified passphrase. // Derive the keychain based on seed from seed file and specified passphrase.
// Generate the initial wallet seed if we are running "wallet init". // Generate the initial wallet seed if we are running "wallet init".
if let ("init", Some(_)) = wallet_args.subcommand() { if let ("init", Some(init_args)) = wallet_args.subcommand() {
let mut use_db = false;
if init_args.is_present("db") {
info!(LOGGER, "Use db");
use_db = true;
}
wallet::WalletSeed::init_file(&wallet_config).expect("Failed to init wallet seed file."); wallet::WalletSeed::init_file(&wallet_config).expect("Failed to init wallet seed file.");
info!(LOGGER, "Wallet seed file created");
if use_db {
let _: LMDBBackend<keychain::ExtKeychain> = LMDBBackend::new(wallet_config.clone(), "")
.unwrap_or_else(|e| {
panic!(
"Error creating DB wallet: {} Config: {:?}",
e, wallet_config
);
});
info!(LOGGER, "Wallet database backend created");
}
// give logging thread a moment to catch up
thread::sleep(Duration::from_millis(200));
// we are done here with creating the wallet, so just return // we are done here with creating the wallet, so just return
return; return;
} }
@ -584,12 +622,12 @@ fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
.value_of("pass") .value_of("pass")
.expect("Failed to read passphrase."); .expect("Failed to read passphrase.");
// use database if one exists, otherwise use file
let use_db = wallet_db_exists(wallet_config.clone());
// Handle listener startup commands // Handle listener startup commands
{ {
let wallet: FileWallet<keychain::ExtKeychain> = let wallet = instantiate_wallet(wallet_config.clone(), passphrase, use_db);
FileWallet::new(wallet_config.clone(), passphrase).unwrap_or_else(|e| {
panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config)
});
match wallet_args.subcommand() { match wallet_args.subcommand() {
("listen", Some(listen_args)) => { ("listen", Some(listen_args)) => {
if let Some(port) = listen_args.value_of("port") { if let Some(port) = listen_args.value_of("port") {
@ -617,11 +655,8 @@ fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
// Handle single-use (command line) owner commands // Handle single-use (command line) owner commands
{ {
let mut wallet: FileWallet<keychain::ExtKeychain> = let wallet = instantiate_wallet(wallet_config.clone(), passphrase, use_db);
FileWallet::new(wallet_config.clone(), passphrase).unwrap_or_else(|e| { let _res = wallet::controller::owner_single_use(wallet, |api| {
panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config)
});
let _res = wallet::controller::owner_single_use(&mut wallet, |api| {
match wallet_args.subcommand() { match wallet_args.subcommand() {
("send", Some(send_args)) => { ("send", Some(send_args)) => {
let amount = send_args let amount = send_args

View file

@ -14,16 +14,20 @@
//! Main Menu definition //! Main Menu definition
use cursive::Cursive;
use cursive::align::HAlign; use cursive::align::HAlign;
use cursive::direction::Orientation; use cursive::direction::Orientation;
use cursive::event::{EventResult, Key}; use cursive::event::{EventResult, Key};
use cursive::view::Identifiable; use cursive::view::Identifiable;
use cursive::view::View; use cursive::view::View;
use cursive::views::{BoxView, LinearLayout, OnEventView, SelectView, StackView, TextView, ViewRef}; use cursive::views::{
BoxView, LinearLayout, OnEventView, SelectView, StackView, TextView, ViewRef,
};
use cursive::Cursive;
use tui::constants::{MAIN_MENU, ROOT_STACK, SUBMENU_MINING_BUTTON, VIEW_BASIC_STATUS, VIEW_MINING, use tui::constants::{
VIEW_PEER_SYNC, VIEW_VERSION}; MAIN_MENU, ROOT_STACK, SUBMENU_MINING_BUTTON, VIEW_BASIC_STATUS, VIEW_MINING, VIEW_PEER_SYNC,
VIEW_VERSION,
};
pub fn create() -> Box<View> { pub fn create() -> Box<View> {
let mut main_menu = SelectView::new().h_align(HAlign::Left).with_id(MAIN_MENU); let mut main_menu = SelectView::new().h_align(HAlign::Left).with_id(MAIN_MENU);

View file

@ -16,18 +16,20 @@
use std::cmp::Ordering; use std::cmp::Ordering;
use cursive::Cursive;
use cursive::direction::Orientation; use cursive::direction::Orientation;
use cursive::event::Key; use cursive::event::Key;
use cursive::traits::{Boxable, Identifiable}; use cursive::traits::{Boxable, Identifiable};
use cursive::view::View; use cursive::view::View;
use cursive::views::{BoxView, Button, Dialog, LinearLayout, OnEventView, Panel, StackView, use cursive::views::{
TextView}; BoxView, Button, Dialog, LinearLayout, OnEventView, Panel, StackView, TextView,
};
use cursive::Cursive;
use std::time; use std::time;
use tui::chrono::prelude::{DateTime, NaiveDateTime, Utc}; use tui::chrono::prelude::{DateTime, NaiveDateTime, Utc};
use tui::constants::{MAIN_MENU, SUBMENU_MINING_BUTTON, TABLE_MINING_DIFF_STATUS, use tui::constants::{
TABLE_MINING_STATUS, VIEW_MINING}; MAIN_MENU, SUBMENU_MINING_BUTTON, TABLE_MINING_DIFF_STATUS, TABLE_MINING_STATUS, VIEW_MINING,
};
use tui::types::TUIStatusListener; use tui::types::TUIStatusListener;
use servers::{DiffBlock, ServerStats, WorkerStats}; use servers::{DiffBlock, ServerStats, WorkerStats};

View file

@ -18,11 +18,11 @@ use std::cmp::Ordering;
use servers::{PeerStats, ServerStats}; use servers::{PeerStats, ServerStats};
use cursive::Cursive;
use cursive::direction::Orientation; use cursive::direction::Orientation;
use cursive::traits::{Boxable, Identifiable}; use cursive::traits::{Boxable, Identifiable};
use cursive::view::View; use cursive::view::View;
use cursive::views::{BoxView, Dialog, LinearLayout, TextView}; use cursive::views::{BoxView, Dialog, LinearLayout, TextView};
use cursive::Cursive;
use tui::constants::{TABLE_PEER_STATUS, VIEW_PEER_SYNC}; use tui::constants::{TABLE_PEER_STATUS, VIEW_PEER_SYNC};
use tui::table::{TableView, TableViewItem}; use tui::table::{TableView, TableViewItem};

View file

@ -14,11 +14,11 @@
//! Basic status view definition //! Basic status view definition
use cursive::Cursive;
use cursive::direction::Orientation; use cursive::direction::Orientation;
use cursive::traits::Identifiable; use cursive::traits::Identifiable;
use cursive::view::View; use cursive::view::View;
use cursive::views::{BoxView, LinearLayout, TextView}; use cursive::views::{BoxView, LinearLayout, TextView};
use cursive::Cursive;
use tui::constants::VIEW_BASIC_STATUS; use tui::constants::VIEW_BASIC_STATUS;
use tui::types::TUIStatusListener; use tui::types::TUIStatusListener;

View file

@ -54,7 +54,6 @@ use std::hash::Hash;
use std::rc::Rc; use std::rc::Rc;
// External Dependencies ------------------------------------------------------ // External Dependencies ------------------------------------------------------
use cursive::With;
use cursive::align::HAlign; use cursive::align::HAlign;
use cursive::direction::Direction; use cursive::direction::Direction;
use cursive::event::{Callback, Event, EventResult, Key}; use cursive::event::{Callback, Event, EventResult, Key};
@ -62,6 +61,7 @@ use cursive::theme::ColorStyle;
use cursive::theme::PaletteColor::{Highlight, HighlightInactive, Primary}; use cursive::theme::PaletteColor::{Highlight, HighlightInactive, Primary};
use cursive::vec::Vec2; use cursive::vec::Vec2;
use cursive::view::{ScrollBase, View}; use cursive::view::{ScrollBase, View};
use cursive::With;
use cursive::{Cursive, Printer}; use cursive::{Cursive, Printer};
/// A trait for displaying and sorting items inside a /// A trait for displaying and sorting items inside a

View file

@ -14,8 +14,8 @@
//! Types specific to the UI module //! Types specific to the UI module
use cursive::Cursive;
use cursive::view::View; use cursive::view::View;
use cursive::Cursive;
use servers::ServerStats; use servers::ServerStats;
/// Main message struct to communicate between the UI and /// Main message struct to communicate between the UI and

View file

@ -19,15 +19,17 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{mpsc, Arc}; use std::sync::{mpsc, Arc};
use time; use time;
use cursive::Cursive;
use cursive::direction::Orientation; use cursive::direction::Orientation;
use cursive::theme::BaseColor::{Black, Blue, Cyan, White}; use cursive::theme::BaseColor::{Black, Blue, Cyan, White};
use cursive::theme::Color::Dark; use cursive::theme::Color::Dark;
use cursive::theme::PaletteColor::{Background, Highlight, HighlightInactive, Primary, Shadow, View}; use cursive::theme::PaletteColor::{
Background, Highlight, HighlightInactive, Primary, Shadow, View,
};
use cursive::theme::{BaseColor, BorderStyle, Color, Theme}; use cursive::theme::{BaseColor, BorderStyle, Color, Theme};
use cursive::traits::Identifiable; use cursive::traits::Identifiable;
use cursive::utils::markup::StyledString; use cursive::utils::markup::StyledString;
use cursive::views::{LinearLayout, Panel, StackView, TextView, ViewBox}; use cursive::views::{LinearLayout, Panel, StackView, TextView, ViewBox};
use cursive::Cursive;
use servers::Server; use servers::Server;

View file

@ -14,11 +14,11 @@
//! Version and build info //! Version and build info
use cursive::Cursive;
use cursive::direction::Orientation; use cursive::direction::Orientation;
use cursive::traits::Identifiable; use cursive::traits::Identifiable;
use cursive::view::View; use cursive::view::View;
use cursive::views::{BoxView, LinearLayout, TextView}; use cursive::views::{BoxView, LinearLayout, TextView};
use cursive::Cursive;
use tui::constants::VIEW_VERSION; use tui::constants::VIEW_VERSION;
use tui::types::TUIStatusListener; use tui::types::TUIStatusListener;

View file

@ -13,8 +13,8 @@
// limitations under the License. // limitations under the License.
use core::core::{self, amount_to_hr_string}; use core::core::{self, amount_to_hr_string};
use libwallet::Error;
use libwallet::types::{OutputData, WalletInfo}; use libwallet::types::{OutputData, WalletInfo};
use libwallet::Error;
use prettytable; use prettytable;
use std::io::prelude::Write; use std::io::prelude::Write;
use term; use term;

View file

@ -104,7 +104,19 @@ impl Fail for Error {
impl Display for Error { impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.inner, f) let cause = match self.cause() {
Some(c) => format!("{}", c),
None => String::from("Unknown"),
};
let backtrace = match self.backtrace() {
Some(b) => format!("{}", b),
None => String::from("Unknown"),
};
let output = format!(
"{} \n Cause: {} \n Backtrace: {}",
self.inner, cause, backtrace
);
Display::fmt(&output, f)
} }
} }

View file

@ -19,14 +19,14 @@ use std::path::{Path, MAIN_SEPARATOR};
use serde_json; use serde_json;
use tokio_core::reactor; use tokio_core::reactor;
use tokio_retry::Retry;
use tokio_retry::strategy::FibonacciBackoff; use tokio_retry::strategy::FibonacciBackoff;
use tokio_retry::Retry;
use failure::ResultExt; use failure::ResultExt;
use keychain::{self, Identifier, Keychain}; use keychain::{self, Identifier, Keychain};
use util::LOGGER;
use util::secp::pedersen; use util::secp::pedersen;
use util::LOGGER;
use error::{Error, ErrorKind}; use error::{Error, ErrorKind};
@ -35,8 +35,8 @@ use libtx::slate::Slate;
use libwallet; use libwallet;
use libwallet::types::{ use libwallet::types::{
BlockFees, CbData, OutputData, TxWrapper, WalletBackend, BlockFees, CbData, OutputData, TxWrapper, WalletBackend, WalletClient, WalletDetails,
WalletClient, WalletDetails, WalletOutputBatch, WalletOutputBatch,
}; };
use types::{WalletConfig, WalletSeed}; use types::{WalletConfig, WalletSeed};

View file

@ -60,5 +60,6 @@ pub use client::create_coinbase;
pub use error::{Error, ErrorKind}; pub use error::{Error, ErrorKind};
pub use file_wallet::FileWallet; pub use file_wallet::FileWallet;
pub use libwallet::controller; pub use libwallet::controller;
pub use libwallet::types::{BlockFees, CbData, WalletInfo}; pub use libwallet::types::{BlockFees, CbData, WalletInfo, WalletInst};
pub use lmdb_wallet::{wallet_db_exists, LMDBBackend};
pub use types::{WalletConfig, WalletSeed}; pub use types::{WalletConfig, WalletSeed};

View file

@ -47,11 +47,7 @@ pub type Append<K> = for<'a> Fn(&'a mut Context<K>, (Transaction, TxKernel, Blin
/// Adds an input with the provided value and blinding key to the transaction /// Adds an input with the provided value and blinding key to the transaction
/// being built. /// being built.
fn build_input<K>( fn build_input<K>(value: u64, features: OutputFeatures, key_id: Identifier) -> Box<Append<K>>
value: u64,
features: OutputFeatures,
key_id: Identifier,
) -> Box<Append<K>>
where where
K: Keychain, K: Keychain,
{ {
@ -78,10 +74,7 @@ where
} }
/// Adds a coinbase input spending a coinbase output. /// Adds a coinbase input spending a coinbase output.
pub fn coinbase_input<K>( pub fn coinbase_input<K>(value: u64, key_id: Identifier) -> Box<Append<K>>
value: u64,
key_id: Identifier,
) -> Box<Append<K>>
where where
K: Keychain, K: Keychain,
{ {

View file

@ -23,8 +23,8 @@ use keychain::{BlindSum, BlindingFactor, Keychain};
use libtx::error::{Error, ErrorKind}; use libtx::error::{Error, ErrorKind};
use libtx::{aggsig, build, tx_fee}; use libtx::{aggsig, build, tx_fee};
use util::secp::Signature;
use util::secp::key::{PublicKey, SecretKey}; use util::secp::key::{PublicKey, SecretKey};
use util::secp::Signature;
use util::{secp, LOGGER}; use util::{secp, LOGGER};
/// Public data for each participant in the slate /// Public data for each participant in the slate
@ -261,11 +261,7 @@ impl Slate {
// double check the fee amount included in the partial tx // double check the fee amount included in the partial tx
// we don't necessarily want to just trust the sender // we don't necessarily want to just trust the sender
// we could just overwrite the fee here (but we won't) due to the sig // we could just overwrite the fee here (but we won't) due to the sig
let fee = tx_fee( let fee = tx_fee(self.tx.inputs.len(), self.tx.outputs.len(), None);
self.tx.inputs.len(),
self.tx.outputs.len(),
None,
);
if fee > self.tx.fee() { if fee > self.tx.fee() {
return Err(ErrorKind::Fee( return Err(ErrorKind::Fee(
format!("Fee Dispute Error: {}, {}", self.tx.fee(), fee,).to_string(), format!("Fee Dispute Error: {}, {}", self.tx.fee(), fee,).to_string(),

View file

@ -22,32 +22,33 @@ use std::marker::PhantomData;
use core::ser; use core::ser;
use keychain::Keychain; use keychain::Keychain;
use libtx::slate::Slate; use libtx::slate::Slate;
use libwallet::Error;
use libwallet::internal::{tx, updater}; use libwallet::internal::{tx, updater};
use libwallet::types::{BlockFees, CbData, OutputData, TxWrapper, WalletBackend, WalletClient, use libwallet::types::{
WalletInfo}; BlockFees, CbData, OutputData, TxWrapper, WalletBackend, WalletClient, WalletInfo,
};
use libwallet::Error;
use util::{self, LOGGER}; use util::{self, LOGGER};
/// Wrapper around internal API functions, containing a reference to /// Wrapper around internal API functions, containing a reference to
/// the wallet/keychain that they're acting upon /// the wallet/keychain that they're acting upon
pub struct APIOwner<'a, W, K> pub struct APIOwner<'a, W: ?Sized, K>
where where
W: 'a + WalletBackend<K> + WalletClient, W: 'a + WalletBackend<K> + WalletClient,
K: Keychain, K: Keychain,
{ {
/// Wallet, contains its keychain (TODO: Split these up into 2 traits /// Wallet, contains its keychain (TODO: Split these up into 2 traits
/// perhaps) /// perhaps)
pub wallet: &'a mut W, pub wallet: &'a mut Box<W>,
phantom: PhantomData<K>, phantom: PhantomData<K>,
} }
impl<'a, W, K> APIOwner<'a, W, K> impl<'a, W: ?Sized, K> APIOwner<'a, W, K>
where where
W: 'a + WalletBackend<K> + WalletClient, W: 'a + WalletBackend<K> + WalletClient,
K: Keychain, K: Keychain,
{ {
/// Create new API instance /// Create new API instance
pub fn new(wallet_in: &'a mut W) -> APIOwner<'a, W, K> { pub fn new(wallet_in: &'a mut Box<W>) -> APIOwner<'a, W, K> {
APIOwner { APIOwner {
wallet: wallet_in, wallet: wallet_in,
phantom: PhantomData, phantom: PhantomData,
@ -67,7 +68,7 @@ where
} }
Ok(( Ok((
validated, validated,
updater::retrieve_outputs(self.wallet, include_spent)?, updater::retrieve_outputs(&mut **self.wallet, include_spent)?,
)) ))
} }
@ -80,7 +81,7 @@ where
if refresh_from_node { if refresh_from_node {
validated = self.update_outputs(); validated = self.update_outputs();
} }
let wallet_info = updater::retrieve_info(self.wallet)?; let wallet_info = updater::retrieve_info(&mut **self.wallet)?;
Ok((validated, wallet_info)) Ok((validated, wallet_info))
} }
@ -95,7 +96,7 @@ where
fluff: bool, fluff: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let (slate, context, lock_fn) = tx::create_send_tx( let (slate, context, lock_fn) = tx::create_send_tx(
self.wallet, &mut **self.wallet,
amount, amount,
minimum_confirmations, minimum_confirmations,
max_outputs, max_outputs,
@ -114,7 +115,7 @@ where
} }
}; };
tx::complete_tx(self.wallet, &mut slate, &context)?; tx::complete_tx(&mut **self.wallet, &mut slate, &context)?;
// All good here, so let's post it // All good here, so let's post it
let tx_hex = util::to_hex(ser::ser_vec(&slate.tx).unwrap()); let tx_hex = util::to_hex(ser::ser_vec(&slate.tx).unwrap());
@ -132,7 +133,12 @@ where
minimum_confirmations: u64, minimum_confirmations: u64,
max_outputs: usize, max_outputs: usize,
) -> Result<(), Error> { ) -> Result<(), Error> {
let tx_burn = tx::issue_burn_tx(self.wallet, amount, minimum_confirmations, max_outputs)?; let tx_burn = tx::issue_burn_tx(
&mut **self.wallet,
amount,
minimum_confirmations,
max_outputs,
)?;
let tx_hex = util::to_hex(ser::ser_vec(&tx_burn).unwrap()); let tx_hex = util::to_hex(ser::ser_vec(&tx_burn).unwrap());
self.wallet.post_tx(&TxWrapper { tx_hex: tx_hex }, false)?; self.wallet.post_tx(&TxWrapper { tx_hex: tx_hex }, false)?;
Ok(()) Ok(())
@ -160,7 +166,7 @@ where
/// Attempt to update outputs in wallet, return whether it was successful /// Attempt to update outputs in wallet, return whether it was successful
fn update_outputs(&mut self) -> bool { fn update_outputs(&mut self) -> bool {
match updater::refresh_outputs(self.wallet) { match updater::refresh_outputs(&mut **self.wallet) {
Ok(_) => true, Ok(_) => true,
Err(_) => false, Err(_) => false,
} }
@ -169,24 +175,24 @@ where
/// Wrapper around external API functions, intended to communicate /// Wrapper around external API functions, intended to communicate
/// with other parties /// with other parties
pub struct APIForeign<'a, W, K> pub struct APIForeign<'a, W: ?Sized, K>
where where
W: 'a + WalletBackend<K> + WalletClient, W: WalletBackend<K> + WalletClient + 'a,
K: Keychain, K: Keychain,
{ {
/// Wallet, contains its keychain (TODO: Split these up into 2 traits /// Wallet, contains its keychain (TODO: Split these up into 2 traits
/// perhaps) /// perhaps)
pub wallet: &'a mut W, pub wallet: &'a mut Box<W>,
phantom: PhantomData<K>, phantom: PhantomData<K>,
} }
impl<'a, W, K> APIForeign<'a, W, K> impl<'a, W: ?Sized, K> APIForeign<'a, W, K>
where where
W: 'a + WalletBackend<K> + WalletClient, W: WalletBackend<K> + WalletClient,
K: Keychain, K: Keychain,
{ {
/// Create new API instance /// Create new API instance
pub fn new(wallet_in: &'a mut W) -> APIForeign<'a, W, K> { pub fn new(wallet_in: &'a mut Box<W>) -> APIForeign<W, K> {
APIForeign { APIForeign {
wallet: wallet_in, wallet: wallet_in,
phantom: PhantomData, phantom: PhantomData,
@ -195,11 +201,11 @@ where
/// Build a new (potential) coinbase transaction in the wallet /// Build a new (potential) coinbase transaction in the wallet
pub fn build_coinbase(&mut self, block_fees: &BlockFees) -> Result<CbData, Error> { pub fn build_coinbase(&mut self, block_fees: &BlockFees) -> Result<CbData, Error> {
updater::build_coinbase(self.wallet, block_fees) updater::build_coinbase(&mut **self.wallet, block_fees)
} }
/// Receive a transaction from a sender /// Receive a transaction from a sender
pub fn receive_tx(&mut self, slate: &mut Slate) -> Result<(), Error> { pub fn receive_tx(&mut self, slate: &mut Slate) -> Result<(), Error> {
tx::receive_tx(self.wallet, slate) tx::receive_tx(&mut **self.wallet, slate)
} }
} }

View file

@ -31,29 +31,31 @@ use failure::Fail;
use keychain::Keychain; use keychain::Keychain;
use libtx::slate::Slate; use libtx::slate::Slate;
use libwallet::api::{APIForeign, APIOwner}; use libwallet::api::{APIForeign, APIOwner};
use libwallet::types::{BlockFees, CbData, OutputData, SendTXArgs, WalletBackend, WalletClient, use libwallet::types::{
WalletInfo}; BlockFees, CbData, OutputData, SendTXArgs, WalletBackend, WalletClient, WalletInfo, WalletInst,
};
use libwallet::{Error, ErrorKind}; use libwallet::{Error, ErrorKind};
use util::LOGGER; use util::LOGGER;
/// Instantiate wallet Owner API for a single-use (command line) call /// Instantiate wallet Owner API for a single-use (command line) call
/// Return a function containing a loaded API context to call /// Return a function containing a loaded API context to call
pub fn owner_single_use<F, T, K>(wallet: &mut T, f: F) -> Result<(), Error> pub fn owner_single_use<F, T: ?Sized, K>(wallet: Box<T>, f: F) -> Result<(), Error>
where where
T: WalletBackend<K> + WalletClient, T: WalletBackend<K> + WalletClient,
F: FnOnce(&mut APIOwner<T, K>) -> Result<(), Error>, F: FnOnce(&mut APIOwner<T, K>) -> Result<(), Error>,
K: Keychain, K: Keychain,
{ {
wallet.open_with_credentials()?; let mut w = wallet;
f(&mut APIOwner::new(wallet))?; w.open_with_credentials()?;
wallet.close()?; f(&mut APIOwner::new(&mut w))?;
w.close()?;
Ok(()) Ok(())
} }
/// Instantiate wallet Foreign API for a single-use (command line) call /// Instantiate wallet Foreign API for a single-use (command line) call
/// Return a function containing a loaded API context to call /// Return a function containing a loaded API context to call
pub fn foreign_single_use<F, T, K>(wallet: &mut T, f: F) -> Result<(), Error> pub fn foreign_single_use<F, T: ?Sized, K>(wallet: &mut Box<T>, f: F) -> Result<(), Error>
where where
T: WalletBackend<K> + WalletClient, T: WalletBackend<K> + WalletClient,
F: FnOnce(&mut APIForeign<T, K>) -> Result<(), Error>, F: FnOnce(&mut APIForeign<T, K>) -> Result<(), Error>,
@ -67,9 +69,9 @@ where
/// Listener version, providing same API but listening for requests on a /// Listener version, providing same API but listening for requests on a
/// port and wrapping the calls /// port and wrapping the calls
pub fn owner_listener<T, K>(wallet: T, addr: &str) -> Result<(), Error> pub fn owner_listener<T: ?Sized, K>(wallet: Box<T>, addr: &str) -> Result<(), Error>
where where
T: WalletBackend<K> + WalletClient, T: WalletInst<K>,
OwnerAPIGetHandler<T, K>: Handler, OwnerAPIGetHandler<T, K>: Handler,
OwnerAPIPostHandler<T, K>: Handler, OwnerAPIPostHandler<T, K>: Handler,
K: Keychain, K: Keychain,
@ -99,9 +101,9 @@ where
/// Listener version, providing same API but listening for requests on a /// Listener version, providing same API but listening for requests on a
/// port and wrapping the calls /// port and wrapping the calls
pub fn foreign_listener<T, K>(wallet: T, addr: &str) -> Result<(), Error> pub fn foreign_listener<T: ?Sized, K>(wallet: Box<T>, addr: &str) -> Result<(), Error>
where where
T: WalletBackend<K> + WalletClient, T: WalletInst<K>,
ForeignAPIHandler<T, K>: Handler, ForeignAPIHandler<T, K>: Handler,
K: Keychain, K: Keychain,
{ {
@ -124,23 +126,23 @@ where
} }
/// API Handler/Wrapper for owner functions /// API Handler/Wrapper for owner functions
pub struct OwnerAPIGetHandler<T, K> pub struct OwnerAPIGetHandler<T: ?Sized, K>
where where
T: WalletBackend<K>, T: WalletBackend<K> + WalletClient,
K: Keychain, K: Keychain,
{ {
/// Wallet instance /// Wallet instance
pub wallet: Arc<Mutex<T>>, pub wallet: Arc<Mutex<Box<T>>>,
phantom: PhantomData<K>, phantom: PhantomData<K>,
} }
impl<T, K> OwnerAPIGetHandler<T, K> impl<T: ?Sized, K> OwnerAPIGetHandler<T, K>
where where
T: WalletBackend<K> + WalletClient, T: WalletBackend<K> + WalletClient,
K: Keychain, K: Keychain,
{ {
/// Create a new owner API handler for GET methods /// Create a new owner API handler for GET methods
pub fn new(wallet: Arc<Mutex<T>>) -> OwnerAPIGetHandler<T, K> { pub fn new(wallet: Arc<Mutex<Box<T>>>) -> OwnerAPIGetHandler<T, K> {
OwnerAPIGetHandler { OwnerAPIGetHandler {
wallet, wallet,
phantom: PhantomData, phantom: PhantomData,
@ -201,7 +203,7 @@ where
} }
} }
impl<T, K> Handler for OwnerAPIGetHandler<T, K> impl<T: ?Sized, K> Handler for OwnerAPIGetHandler<T, K>
where where
T: WalletBackend<K> + WalletClient + Send + Sync + 'static, T: WalletBackend<K> + WalletClient + Send + Sync + 'static,
K: Keychain + 'static, K: Keychain + 'static,
@ -215,7 +217,8 @@ where
error!(LOGGER, "Error opening wallet: {:?}", e); error!(LOGGER, "Error opening wallet: {:?}", e);
IronError::new(Fail::compat(e), status::BadRequest) IronError::new(Fail::compat(e), status::BadRequest)
})?; })?;
let mut api = APIOwner::new(&mut *wallet); let mut w = wallet;
let mut api = APIOwner::new(&mut w);
let mut resp_json = self.handle_request(req, &mut api); let mut resp_json = self.handle_request(req, &mut api);
if !resp_json.is_err() { if !resp_json.is_err() {
resp_json resp_json
@ -232,23 +235,23 @@ where
} }
/// Handles all owner API POST requests /// Handles all owner API POST requests
pub struct OwnerAPIPostHandler<T, K> pub struct OwnerAPIPostHandler<T: ?Sized, K>
where where
T: WalletBackend<K>, T: WalletBackend<K>,
K: Keychain, K: Keychain,
{ {
/// Wallet instance /// Wallet instance
pub wallet: Arc<Mutex<T>>, pub wallet: Arc<Mutex<Box<T>>>,
phantom: PhantomData<K>, phantom: PhantomData<K>,
} }
impl<T, K> OwnerAPIPostHandler<T, K> impl<T: ?Sized, K> OwnerAPIPostHandler<T, K>
where where
T: WalletBackend<K> + WalletClient, T: WalletBackend<K> + WalletClient,
K: Keychain, K: Keychain,
{ {
/// New POST handler /// New POST handler
pub fn new(wallet: Arc<Mutex<T>>) -> OwnerAPIPostHandler<T, K> { pub fn new(wallet: Arc<Mutex<Box<T>>>) -> OwnerAPIPostHandler<T, K> {
OwnerAPIPostHandler { OwnerAPIPostHandler {
wallet, wallet,
phantom: PhantomData, phantom: PhantomData,
@ -320,7 +323,7 @@ where
} }
} }
impl<T, K> Handler for OwnerAPIPostHandler<T, K> impl<T: ?Sized, K> Handler for OwnerAPIPostHandler<T, K>
where where
T: WalletBackend<K> + WalletClient + Send + Sync + 'static, T: WalletBackend<K> + WalletClient + Send + Sync + 'static,
K: Keychain + 'static, K: Keychain + 'static,
@ -329,12 +332,15 @@ where
// every request should open with stored credentials, // every request should open with stored credentials,
// do its thing and then de-init whatever secrets have been // do its thing and then de-init whatever secrets have been
// stored // stored
{
let mut wallet = self.wallet.lock().unwrap(); let mut wallet = self.wallet.lock().unwrap();
wallet.open_with_credentials().map_err(|e| { wallet.open_with_credentials().map_err(|e| {
error!(LOGGER, "Error opening wallet: {:?}", e); error!(LOGGER, "Error opening wallet: {:?}", e);
IronError::new(Fail::compat(e), status::BadRequest) IronError::new(Fail::compat(e), status::BadRequest)
})?; })?;
let mut api = APIOwner::new(&mut *wallet); }
let mut wallet = self.wallet.lock().unwrap();
let mut api = APIOwner::new(&mut wallet);
let resp = match self.handle_request(req, &mut api) { let resp = match self.handle_request(req, &mut api) {
Ok(r) => self.create_ok_response(&r), Ok(r) => self.create_ok_response(&r),
Err(e) => { Err(e) => {
@ -367,23 +373,23 @@ impl Handler for OwnerAPIOptionsHandler where {
} }
/// API Handler/Wrapper for foreign functions /// API Handler/Wrapper for foreign functions
pub struct ForeignAPIHandler<T, K> pub struct ForeignAPIHandler<T: ?Sized, K>
where where
T: WalletBackend<K> + WalletClient, T: WalletBackend<K> + WalletClient,
K: Keychain, K: Keychain,
{ {
/// Wallet instance /// Wallet instance
pub wallet: Arc<Mutex<T>>, pub wallet: Arc<Mutex<Box<T>>>,
phantom: PhantomData<K>, phantom: PhantomData<K>,
} }
impl<T, K> ForeignAPIHandler<T, K> impl<T: ?Sized, K> ForeignAPIHandler<T, K>
where where
T: WalletBackend<K> + WalletClient, T: WalletBackend<K> + WalletClient,
K: Keychain, K: Keychain,
{ {
/// create a new api handler /// create a new api handler
pub fn new(wallet: Arc<Mutex<T>>) -> ForeignAPIHandler<T, K> { pub fn new(wallet: Arc<Mutex<Box<T>>>) -> ForeignAPIHandler<T, K> {
ForeignAPIHandler { ForeignAPIHandler {
wallet, wallet,
phantom: PhantomData, phantom: PhantomData,
@ -442,7 +448,7 @@ where
} }
} }
} }
impl<T, K> Handler for ForeignAPIHandler<T, K> impl<T: ?Sized, K> Handler for ForeignAPIHandler<T, K>
where where
T: WalletBackend<K> + WalletClient + Send + Sync + 'static, T: WalletBackend<K> + WalletClient + Send + Sync + 'static,
K: Keychain + 'static, K: Keychain + 'static,
@ -451,12 +457,15 @@ where
// every request should open with stored credentials, // every request should open with stored credentials,
// do its thing and then de-init whatever secrets have been // do its thing and then de-init whatever secrets have been
// stored // stored
{
let mut wallet = self.wallet.lock().unwrap(); let mut wallet = self.wallet.lock().unwrap();
wallet.open_with_credentials().map_err(|e| { wallet.open_with_credentials().map_err(|e| {
error!(LOGGER, "Error opening wallet: {:?}", e); error!(LOGGER, "Error opening wallet: {:?}", e);
IronError::new(Fail::compat(e), status::BadRequest) IronError::new(Fail::compat(e), status::BadRequest)
})?; })?;
let mut api = APIForeign::new(&mut *wallet); }
let mut wallet = self.wallet.lock().unwrap();
let mut api = APIForeign::new(&mut wallet);
let resp_json = self.handle_request(req, &mut api); let resp_json = self.handle_request(req, &mut api);
api.wallet api.wallet
.close() .close()

View file

@ -48,8 +48,11 @@ pub enum ErrorKind {
}, },
/// Fee Exceeds amount /// Fee Exceeds amount
#[fail(display = "Fee exceeds amount: sender amount {}, recipient fee {}", sender_amount, #[fail(
recipient_fee)] display = "Fee exceeds amount: sender amount {}, recipient fee {}",
sender_amount,
recipient_fee
)]
FeeExceedsAmount { FeeExceedsAmount {
/// sender amount /// sender amount
sender_amount: u64, sender_amount: u64,

View file

@ -18,7 +18,7 @@ use libwallet::error::Error;
use libwallet::types::WalletBackend; use libwallet::types::WalletBackend;
/// Get next available key in the wallet /// Get next available key in the wallet
pub fn next_available_key<T, K>(wallet: &mut T) -> Result<(Identifier, u32), Error> pub fn next_available_key<T: ?Sized, K>(wallet: &mut T) -> Result<(Identifier, u32), Error>
where where
T: WalletBackend<K>, T: WalletBackend<K>,
K: Keychain, K: Keychain,
@ -30,7 +30,7 @@ where
} }
/// Retrieve an existing key from a wallet /// Retrieve an existing key from a wallet
pub fn retrieve_existing_key<T, K>( pub fn retrieve_existing_key<T: ?Sized, K>(
wallet: &T, wallet: &T,
key_id: Identifier, key_id: Identifier,
) -> Result<(Identifier, u32), Error> ) -> Result<(Identifier, u32), Error>

View file

@ -16,9 +16,9 @@
use core::global; use core::global;
use keychain::{Identifier, Keychain}; use keychain::{Identifier, Keychain};
use libtx::proof; use libtx::proof;
use libwallet::Error;
use libwallet::types::*; use libwallet::types::*;
use util::secp::{pedersen, key::SecretKey}; use libwallet::Error;
use util::secp::{key::SecretKey, pedersen};
use util::LOGGER; use util::LOGGER;
/// Utility struct for return values from below /// Utility struct for return values from below

View file

@ -15,7 +15,7 @@
//! Selection of inputs for building transactions //! Selection of inputs for building transactions
use keychain::{Identifier, Keychain}; use keychain::{Identifier, Keychain};
use libtx::{build, tx_fee, slate::Slate}; use libtx::{build, slate::Slate, tx_fee};
use libwallet::error::{Error, ErrorKind}; use libwallet::error::{Error, ErrorKind};
use libwallet::internal::{keys, sigcontext}; use libwallet::internal::{keys, sigcontext};
use libwallet::types::*; use libwallet::types::*;
@ -25,7 +25,7 @@ use libwallet::types::*;
/// and saves the private wallet identifiers of our selected outputs /// and saves the private wallet identifiers of our selected outputs
/// into our transaction context /// into our transaction context
pub fn build_send_tx_slate<T, K>( pub fn build_send_tx_slate<T: ?Sized, K>(
wallet: &mut T, wallet: &mut T,
num_participants: usize, num_participants: usize,
amount: u64, amount: u64,
@ -122,7 +122,7 @@ where
/// returning the key of the fresh output and a closure /// returning the key of the fresh output and a closure
/// that actually performs the addition of the output to the /// that actually performs the addition of the output to the
/// wallet /// wallet
pub fn build_recipient_output_with_slate<T, K>( pub fn build_recipient_output_with_slate<T: ?Sized, K>(
wallet: &mut T, wallet: &mut T,
slate: &mut Slate, slate: &mut Slate,
) -> Result< ) -> Result<
@ -182,7 +182,7 @@ where
/// Builds a transaction to send to someone from the HD seed associated with the /// Builds a transaction to send to someone from the HD seed associated with the
/// wallet and the amount to send. Handles reading through the wallet data file, /// wallet and the amount to send. Handles reading through the wallet data file,
/// selecting outputs to spend and building the change. /// selecting outputs to spend and building the change.
pub fn select_send_tx<T, K>( pub fn select_send_tx<T: ?Sized, K>(
wallet: &mut T, wallet: &mut T,
amount: u64, amount: u64,
current_height: u64, current_height: u64,
@ -287,7 +287,7 @@ where
} }
/// Selects inputs and change for a transaction /// Selects inputs and change for a transaction
pub fn inputs_and_change<T, K>( pub fn inputs_and_change<T: ?Sized, K>(
coins: &Vec<OutputData>, coins: &Vec<OutputData>,
wallet: &mut T, wallet: &mut T,
amount: u64, amount: u64,
@ -313,10 +313,7 @@ where
for coin in coins { for coin in coins {
let key_id = wallet.keychain().derive_key_id(coin.n_child)?; let key_id = wallet.keychain().derive_key_id(coin.n_child)?;
if coin.is_coinbase { if coin.is_coinbase {
parts.push(build::coinbase_input( parts.push(build::coinbase_input(coin.value, key_id));
coin.value,
key_id,
));
} else { } else {
parts.push(build::input(coin.value, key_id)); parts.push(build::input(coin.value, key_id));
} }

View file

@ -25,7 +25,7 @@ use util::LOGGER;
/// Receive a transaction, modifying the slate accordingly (which can then be /// Receive a transaction, modifying the slate accordingly (which can then be
/// sent back to sender for posting) /// sent back to sender for posting)
pub fn receive_tx<T, K>(wallet: &mut T, slate: &mut Slate) -> Result<(), Error> pub fn receive_tx<T: ?Sized, K>(wallet: &mut T, slate: &mut Slate) -> Result<(), Error>
where where
T: WalletBackend<K>, T: WalletBackend<K>,
K: Keychain, K: Keychain,
@ -53,7 +53,7 @@ where
/// Issue a new transaction to the provided sender by spending some of our /// Issue a new transaction to the provided sender by spending some of our
/// wallet /// wallet
pub fn create_send_tx<T, K>( pub fn create_send_tx<T: ?Sized, K>(
wallet: &mut T, wallet: &mut T,
amount: u64, amount: u64,
minimum_confirmations: u64, minimum_confirmations: u64,
@ -110,7 +110,7 @@ where
} }
/// Complete a transaction as the sender /// Complete a transaction as the sender
pub fn complete_tx<T, K>( pub fn complete_tx<T: ?Sized, K>(
wallet: &mut T, wallet: &mut T,
slate: &mut Slate, slate: &mut Slate,
context: &sigcontext::Context, context: &sigcontext::Context,
@ -129,7 +129,7 @@ where
} }
/// Issue a burn tx /// Issue a burn tx
pub fn issue_burn_tx<T, K>( pub fn issue_burn_tx<T: ?Sized, K>(
wallet: &mut T, wallet: &mut T,
amount: u64, amount: u64,
minimum_confirmations: u64, minimum_confirmations: u64,

View file

@ -26,13 +26,17 @@ use libtx::reward;
use libwallet; use libwallet;
use libwallet::error::{Error, ErrorKind}; use libwallet::error::{Error, ErrorKind};
use libwallet::internal::keys; use libwallet::internal::keys;
use libwallet::types::{BlockFees, CbData, OutputData, OutputStatus, WalletBackend, WalletClient, use libwallet::types::{
WalletInfo}; BlockFees, CbData, OutputData, OutputStatus, WalletBackend, WalletClient, WalletInfo,
};
use util::secp::pedersen; use util::secp::pedersen;
use util::{self, LOGGER}; use util::{self, LOGGER};
/// Retrieve all of the outputs (doesn't attempt to update from node) /// Retrieve all of the outputs (doesn't attempt to update from node)
pub fn retrieve_outputs<T, K>(wallet: &mut T, show_spent: bool) -> Result<Vec<OutputData>, Error> pub fn retrieve_outputs<T: ?Sized, K>(
wallet: &mut T,
show_spent: bool,
) -> Result<Vec<OutputData>, Error>
where where
T: WalletBackend<K>, T: WalletBackend<K>,
K: Keychain, K: Keychain,
@ -57,7 +61,7 @@ where
/// Refreshes the outputs in a wallet with the latest information /// Refreshes the outputs in a wallet with the latest information
/// from a node /// from a node
pub fn refresh_outputs<T, K>(wallet: &mut T) -> Result<(), Error> pub fn refresh_outputs<T: ?Sized, K>(wallet: &mut T) -> Result<(), Error>
where where
T: WalletBackend<K> + WalletClient, T: WalletBackend<K> + WalletClient,
K: Keychain, K: Keychain,
@ -69,7 +73,7 @@ where
/// build a local map of wallet outputs keyed by commit /// build a local map of wallet outputs keyed by commit
/// and a list of outputs we want to query the node for /// and a list of outputs we want to query the node for
pub fn map_wallet_outputs<T, K>( pub fn map_wallet_outputs<T: ?Sized, K>(
wallet: &mut T, wallet: &mut T,
) -> Result<HashMap<pedersen::Commitment, Identifier>, Error> ) -> Result<HashMap<pedersen::Commitment, Identifier>, Error>
where where
@ -90,7 +94,7 @@ where
} }
/// Apply refreshed API output data to the wallet /// Apply refreshed API output data to the wallet
pub fn apply_api_outputs<T, K>( pub fn apply_api_outputs<T: ?Sized, K>(
wallet: &mut T, wallet: &mut T,
wallet_outputs: &HashMap<pedersen::Commitment, Identifier>, wallet_outputs: &HashMap<pedersen::Commitment, Identifier>,
api_outputs: &HashMap<pedersen::Commitment, String>, api_outputs: &HashMap<pedersen::Commitment, String>,
@ -125,7 +129,7 @@ where
/// Builds a single api query to retrieve the latest output data from the node. /// Builds a single api query to retrieve the latest output data from the node.
/// So we can refresh the local wallet outputs. /// So we can refresh the local wallet outputs.
fn refresh_output_state<T, K>(wallet: &mut T, height: u64) -> Result<(), Error> fn refresh_output_state<T: ?Sized, K>(wallet: &mut T, height: u64) -> Result<(), Error>
where where
T: WalletBackend<K> + WalletClient, T: WalletBackend<K> + WalletClient,
K: Keychain, K: Keychain,
@ -144,7 +148,7 @@ where
Ok(()) Ok(())
} }
fn clean_old_unconfirmed<T, K>(wallet: &mut T, height: u64) -> Result<(), Error> fn clean_old_unconfirmed<T: ?Sized, K>(wallet: &mut T, height: u64) -> Result<(), Error>
where where
T: WalletBackend<K>, T: WalletBackend<K>,
K: Keychain, K: Keychain,
@ -168,7 +172,7 @@ where
/// Retrieve summary info about the wallet /// Retrieve summary info about the wallet
/// caller should refresh first if desired /// caller should refresh first if desired
pub fn retrieve_info<T, K>(wallet: &mut T) -> Result<WalletInfo, Error> pub fn retrieve_info<T: ?Sized, K>(wallet: &mut T) -> Result<WalletInfo, Error>
where where
T: WalletBackend<K> + WalletClient, T: WalletBackend<K> + WalletClient,
K: Keychain, K: Keychain,
@ -209,7 +213,7 @@ where
} }
/// Build a coinbase output and insert into wallet /// Build a coinbase output and insert into wallet
pub fn build_coinbase<T, K>(wallet: &mut T, block_fees: &BlockFees) -> Result<CbData, Error> pub fn build_coinbase<T: ?Sized, K>(wallet: &mut T, block_fees: &BlockFees) -> Result<CbData, Error>
where where
T: WalletBackend<K>, T: WalletBackend<K>,
K: Keychain, K: Keychain,
@ -234,7 +238,7 @@ where
//TODO: Split up the output creation and the wallet insertion //TODO: Split up the output creation and the wallet insertion
/// Build a coinbase output and the corresponding kernel /// Build a coinbase output and the corresponding kernel
pub fn receive_coinbase<T, K>( pub fn receive_coinbase<T: ?Sized, K>(
wallet: &mut T, wallet: &mut T,
block_fees: &BlockFees, block_fees: &BlockFees,
) -> Result<(Output, TxKernel, BlockFees), Error> ) -> Result<(Output, TxKernel, BlockFees), Error>

View file

@ -33,6 +33,19 @@ use libwallet::error::{Error, ErrorKind};
use util::secp::pedersen; use util::secp::pedersen;
/// Combined trait to allow dynamic wallet dispatch
pub trait WalletInst<K>: WalletBackend<K> + WalletClient + Send + Sync + 'static
where
K: Keychain,
{
}
impl<T, K> WalletInst<K> for T
where
T: WalletBackend<K> + WalletClient + Send + Sync + 'static,
K: Keychain,
{
}
/// TODO: /// TODO:
/// Wallets should implement this backend for their storage. All functions /// Wallets should implement this backend for their storage. All functions
/// here expect that the wallet instance has instantiated itself or stored /// here expect that the wallet instance has instantiated itself or stored

View file

@ -29,7 +29,7 @@ use libwallet::{internal, Error, ErrorKind};
use types::{WalletConfig, WalletSeed}; use types::{WalletConfig, WalletSeed};
use util::secp::pedersen; use util::secp::pedersen;
pub const DB_DIR: &'static str = "wallet"; pub const DB_DIR: &'static str = "wallet_data";
const OUTPUT_PREFIX: u8 = 'o' as u8; const OUTPUT_PREFIX: u8 = 'o' as u8;
const DERIV_PREFIX: u8 = 'd' as u8; const DERIV_PREFIX: u8 = 'd' as u8;
@ -40,6 +40,13 @@ impl From<store::Error> for Error {
} }
} }
/// test to see if database files exist in the current directory. If so,
/// use a DB backend for all operations
pub fn wallet_db_exists(config: WalletConfig) -> bool {
let db_path = path::Path::new(&config.data_file_dir).join(DB_DIR);
db_path.exists()
}
pub struct LMDBBackend<K> { pub struct LMDBBackend<K> {
db: store::Store, db: store::Store,
config: WalletConfig, config: WalletConfig,
@ -64,6 +71,13 @@ impl<K> LMDBBackend<K> {
keychain: None, keychain: None,
}) })
} }
/// Just test to see if database files exist in the current directory. If
/// so, use a DB backend for all operations
pub fn exists(config: WalletConfig) -> bool {
let db_path = path::Path::new(&config.data_file_dir).join(DB_DIR);
db_path.exists()
}
} }
impl<K> WalletBackend<K> for LMDBBackend<K> impl<K> WalletBackend<K> for LMDBBackend<K>

View file

@ -15,8 +15,8 @@
use std::cmp::min; use std::cmp::min;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::MAIN_SEPARATOR;
use std::path::Path; use std::path::Path;
use std::path::MAIN_SEPARATOR;
use blake2; use blake2;
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};