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
28 changed files with 258 additions and 165 deletions
+66 -31
View File
@@ -40,8 +40,8 @@ pub mod tui;
use std::env::current_dir;
use std::process::exit;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
@@ -51,10 +51,9 @@ use daemonize::Daemonize;
use config::GlobalConfig;
use core::core::amount_to_hr_string;
use core::global;
use keychain::ExtKeychain;
use tui::ui;
use util::{init_logger, LoggingConfig, LOGGER};
use wallet::{libwallet, FileWallet};
use wallet::{libwallet, wallet_db_exists, FileWallet, LMDBBackend, WalletConfig, WalletInst};
// include build information
pub mod built_info {
@@ -296,8 +295,11 @@ fn main() {
.about("basic wallet contents summary"))
.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")
.about("Attempt to restore wallet contents from the chain using seed and password. \
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 {
let use_db = server_config.use_db_wallet == Some(true);
let mut wallet_config = global_config.members.as_ref().unwrap().wallet.clone();
if let Err(_) = wallet::WalletSeed::from_file(&wallet_config) {
wallet::WalletSeed::init_file(&wallet_config)
.expect("Failed to create wallet seed file.");
};
init_wallet_seed(wallet_config.clone());
let _ = thread::Builder::new()
.name("wallet_listener".to_string())
.spawn(move || {
let wallet: FileWallet<keychain::ExtKeychain> =
FileWallet::new(wallet_config.clone(), "").unwrap_or_else(|e| {
panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config)
});
let wallet = instantiate_wallet(wallet_config.clone(), "", use_db);
wallet::controller::foreign_listener(wallet, &wallet_config.api_listen_addr())
.unwrap_or_else(|e| {
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 {
let use_db = server_config.use_db_wallet == Some(true);
let mut wallet_config = global_config.members.unwrap().wallet;
if let Err(_) = wallet::WalletSeed::from_file(&wallet_config) {
wallet::WalletSeed::init_file(&wallet_config)
.expect("Failed to create wallet seed file.");
};
init_wallet_seed(wallet_config.clone());
let _ = thread::Builder::new()
.name("wallet_owner_listener".to_string())
.spawn(move || {
let wallet: FileWallet<ExtKeychain> = FileWallet::new(wallet_config.clone(), "")
.unwrap_or_else(|e| {
panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config)
});
let wallet = instantiate_wallet(wallet_config.clone(), "", use_db);
wallet::controller::owner_listener(wallet, "127.0.0.1:13420").unwrap_or_else(|e| {
panic!(
"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) {
// just get defaults from the global config
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.
// 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.");
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
return;
}
@@ -584,12 +622,12 @@ fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
.value_of("pass")
.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
{
let wallet: FileWallet<keychain::ExtKeychain> =
FileWallet::new(wallet_config.clone(), passphrase).unwrap_or_else(|e| {
panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config)
});
let wallet = instantiate_wallet(wallet_config.clone(), passphrase, use_db);
match wallet_args.subcommand() {
("listen", Some(listen_args)) => {
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
{
let mut wallet: FileWallet<keychain::ExtKeychain> =
FileWallet::new(wallet_config.clone(), passphrase).unwrap_or_else(|e| {
panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config)
});
let _res = wallet::controller::owner_single_use(&mut wallet, |api| {
let wallet = instantiate_wallet(wallet_config.clone(), passphrase, use_db);
let _res = wallet::controller::owner_single_use(wallet, |api| {
match wallet_args.subcommand() {
("send", Some(send_args)) => {
let amount = send_args
+8 -4
View File
@@ -14,16 +14,20 @@
//! Main Menu definition
use cursive::Cursive;
use cursive::align::HAlign;
use cursive::direction::Orientation;
use cursive::event::{EventResult, Key};
use cursive::view::Identifiable;
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,
VIEW_PEER_SYNC, VIEW_VERSION};
use tui::constants::{
MAIN_MENU, ROOT_STACK, SUBMENU_MINING_BUTTON, VIEW_BASIC_STATUS, VIEW_MINING, VIEW_PEER_SYNC,
VIEW_VERSION,
};
pub fn create() -> Box<View> {
let mut main_menu = SelectView::new().h_align(HAlign::Left).with_id(MAIN_MENU);
+7 -5
View File
@@ -16,18 +16,20 @@
use std::cmp::Ordering;
use cursive::Cursive;
use cursive::direction::Orientation;
use cursive::event::Key;
use cursive::traits::{Boxable, Identifiable};
use cursive::view::View;
use cursive::views::{BoxView, Button, Dialog, LinearLayout, OnEventView, Panel, StackView,
TextView};
use cursive::views::{
BoxView, Button, Dialog, LinearLayout, OnEventView, Panel, StackView, TextView,
};
use cursive::Cursive;
use std::time;
use tui::chrono::prelude::{DateTime, NaiveDateTime, Utc};
use tui::constants::{MAIN_MENU, SUBMENU_MINING_BUTTON, TABLE_MINING_DIFF_STATUS,
TABLE_MINING_STATUS, VIEW_MINING};
use tui::constants::{
MAIN_MENU, SUBMENU_MINING_BUTTON, TABLE_MINING_DIFF_STATUS, TABLE_MINING_STATUS, VIEW_MINING,
};
use tui::types::TUIStatusListener;
use servers::{DiffBlock, ServerStats, WorkerStats};
+1 -1
View File
@@ -18,11 +18,11 @@ use std::cmp::Ordering;
use servers::{PeerStats, ServerStats};
use cursive::Cursive;
use cursive::direction::Orientation;
use cursive::traits::{Boxable, Identifiable};
use cursive::view::View;
use cursive::views::{BoxView, Dialog, LinearLayout, TextView};
use cursive::Cursive;
use tui::constants::{TABLE_PEER_STATUS, VIEW_PEER_SYNC};
use tui::table::{TableView, TableViewItem};
+1 -1
View File
@@ -14,11 +14,11 @@
//! Basic status view definition
use cursive::Cursive;
use cursive::direction::Orientation;
use cursive::traits::Identifiable;
use cursive::view::View;
use cursive::views::{BoxView, LinearLayout, TextView};
use cursive::Cursive;
use tui::constants::VIEW_BASIC_STATUS;
use tui::types::TUIStatusListener;
+1 -1
View File
@@ -54,7 +54,6 @@ use std::hash::Hash;
use std::rc::Rc;
// External Dependencies ------------------------------------------------------
use cursive::With;
use cursive::align::HAlign;
use cursive::direction::Direction;
use cursive::event::{Callback, Event, EventResult, Key};
@@ -62,6 +61,7 @@ use cursive::theme::ColorStyle;
use cursive::theme::PaletteColor::{Highlight, HighlightInactive, Primary};
use cursive::vec::Vec2;
use cursive::view::{ScrollBase, View};
use cursive::With;
use cursive::{Cursive, Printer};
/// A trait for displaying and sorting items inside a
+1 -1
View File
@@ -14,8 +14,8 @@
//! Types specific to the UI module
use cursive::Cursive;
use cursive::view::View;
use cursive::Cursive;
use servers::ServerStats;
/// Main message struct to communicate between the UI and
+4 -2
View File
@@ -19,15 +19,17 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{mpsc, Arc};
use time;
use cursive::Cursive;
use cursive::direction::Orientation;
use cursive::theme::BaseColor::{Black, Blue, Cyan, White};
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::traits::Identifiable;
use cursive::utils::markup::StyledString;
use cursive::views::{LinearLayout, Panel, StackView, TextView, ViewBox};
use cursive::Cursive;
use servers::Server;
+1 -1
View File
@@ -14,11 +14,11 @@
//! Version and build info
use cursive::Cursive;
use cursive::direction::Orientation;
use cursive::traits::Identifiable;
use cursive::view::View;
use cursive::views::{BoxView, LinearLayout, TextView};
use cursive::Cursive;
use tui::constants::VIEW_VERSION;
use tui::types::TUIStatusListener;