Merge milestone/2.1.0 into master (#199)

* version bump for next potential release

* Merge master into milestone/2.1.0 (#182)

* Derive --version output dynamically from cargo package version (#174)

* add --txid to the `wallet txs` command (#176)

* add --txid to the `wallet txs` command

* add test for `wallet txs` command with `--txid` parameter

* Refactor - Split WalletCommAdapter into multiple traits (#180)

* Derive --version output dynamically from cargo package version (#174)

* add server auth argument to http client

* Revert "add server auth argument to http client"

This reverts commit f52a8d2c7cdfb8583af5716ad621eb560811d6ee.

* modify WalletCommAdapter, moving dest argument into fields on implementors,
visiting havok on automated tests, at least one of which is now out of date and failing

* Split WalletCommAdapter into four traits, one for each of its intended behaviors.

* Remove two vestigals
1. args, a stringly typed argument to put_tx
2. NullAdapter, which is no longer used

* Remove unused "params" argument from listen method.

* Re-add previously existing TODO comment

* Fix non-test build

* completely Fix non-test build

* Full Lifecycle API Support (#184)

* refactoring wallet lib traits

* rustfmt

* rustfmt

* add new files

* explicit lifetime specifiers on all wallet traits

* rustfmt

* modify apis to use new walletinst

* rustfmt

* converting controller crate

* rustfmt

* controller crate compiling

* rustfmt

* compilation

* rustfmt

* Remove config from wallet, implement open_wallet, close_wallet in lifecycle provider, remove password + open_with_credentials from WalletBackend + impl

* rustfmt

* full compilation, changing recovery + init to new model

* rustfmt

* wallet initialisation working, init command output and flow identical to v2.0.0 wallet

* rustfmt

* fix listener and owner api startup

* rustfmt

* rustfmt

* move encryption test

* rustfmt

* fix api doctests

* rustfmt

* fix for most tests in controller crate

* rustfmt

* fix for check tests in controller crate

* fix main wallet tests

* rustfmt

* add explicit functions to handle mnemonic recovery, fix CLI recovery workflow

* rustfmt

* update keybase adapter to use new wallet format

* rustfmt

* test fix

* remove debug output
This commit is contained in:
Yeastplume
2019-07-29 13:25:03 +01:00
committed by GitHub
parent 7b6d597d39
commit c40e8a915b
54 changed files with 2405 additions and 1942 deletions
+34 -66
View File
@@ -15,7 +15,6 @@
use crate::api;
use crate::chain;
use crate::chain::Chain;
use crate::config::WalletConfig;
use crate::core;
use crate::core::core::{OutputFeatures, OutputIdentifier, Transaction};
use crate::core::{consensus, global, pow};
@@ -23,13 +22,10 @@ use crate::keychain;
use crate::libwallet;
use crate::libwallet::api_impl::{foreign, owner};
use crate::libwallet::{
BlockFees, CbData, InitTxArgs, NodeClient, WalletBackend, WalletInfo, WalletInst,
BlockFees, CbData, InitTxArgs, NodeClient, WalletInfo, WalletInst, WalletLCProvider,
};
use crate::util;
use crate::util::secp::pedersen;
use crate::util::Mutex;
use crate::LMDBBackend;
use crate::WalletSeed;
use chrono::Duration;
use std::sync::Arc;
use std::thread;
@@ -105,14 +101,15 @@ pub fn add_block_with_reward(chain: &Chain, txs: Vec<&Transaction>, reward: CbDa
/// adds a reward output to a wallet, includes that reward in a block, mines
/// the block and adds it to the chain, with option transactions included.
/// Helpful for building up precise wallet balances for testing.
pub fn award_block_to_wallet<C, K>(
pub fn award_block_to_wallet<'a, L, C, K>(
chain: &Chain,
txs: Vec<&Transaction>,
wallet: Arc<Mutex<dyn WalletInst<C, K>>>,
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K> + 'a>>>,
) -> Result<(), libwallet::Error>
where
C: NodeClient,
K: keychain::Keychain,
L: WalletLCProvider<'a, C, K>,
C: NodeClient + 'a,
K: keychain::Keychain + 'a,
{
// build block fees
let prev = chain.head_header().unwrap();
@@ -124,10 +121,9 @@ where
};
// build coinbase (via api) and add block
let coinbase_tx = {
let mut w = wallet.lock();
w.open_with_credentials()?;
let res = foreign::build_coinbase(&mut *w, &block_fees, false)?;
w.close()?;
let mut w_lock = wallet.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
let res = foreign::build_coinbase(&mut **w, &block_fees, false)?;
res
};
add_block_with_reward(chain, txs, coinbase_tx.clone());
@@ -135,15 +131,16 @@ where
}
/// Award a blocks to a wallet directly
pub fn award_blocks_to_wallet<C, K>(
pub fn award_blocks_to_wallet<'a, L, C, K>(
chain: &Chain,
wallet: Arc<Mutex<dyn WalletInst<C, K>>>,
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K> + 'a>>>,
number: usize,
pause_between: bool,
) -> Result<(), libwallet::Error>
where
C: NodeClient,
K: keychain::Keychain,
L: WalletLCProvider<'a, C, K>,
C: NodeClient + 'a,
K: keychain::Keychain + 'a,
{
for _ in 0..number {
award_block_to_wallet(chain, vec![], wallet.clone())?;
@@ -154,50 +151,22 @@ where
Ok(())
}
/// dispatch a db wallet
pub fn create_wallet<C, K>(
dir: &str,
n_client: C,
rec_phrase: Option<&str>,
) -> Arc<Mutex<dyn WalletInst<C, K>>>
where
C: NodeClient + 'static,
K: keychain::Keychain + 'static,
{
let z_string = match rec_phrase {
Some(s) => Some(util::ZeroingString::from(s)),
None => None,
};
let mut wallet_config = WalletConfig::default();
wallet_config.data_file_dir = String::from(dir);
let _ = WalletSeed::init_file(&wallet_config, 32, z_string, "");
let mut wallet = LMDBBackend::new(wallet_config.clone(), "", n_client)
.unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config));
wallet.open_with_credentials().unwrap_or_else(|e| {
panic!(
"Error initializing wallet: {:?} Config: {:?}",
e, wallet_config
)
});
Arc::new(Mutex::new(wallet))
}
/// send an amount to a destination
pub fn send_to_dest<T: ?Sized, C, K>(
wallet: Arc<Mutex<dyn WalletInst<C, K>>>,
pub fn send_to_dest<'a, L, C, K>(
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
client: LocalWalletClient,
dest: &str,
amount: u64,
test_mode: bool,
) -> Result<(), libwallet::Error>
where
T: WalletBackend<C, K>,
C: NodeClient,
K: keychain::Keychain,
L: WalletLCProvider<'a, C, K>,
C: NodeClient + 'a,
K: keychain::Keychain + 'a,
{
let slate = {
let mut w = wallet.lock();
w.open_with_credentials()?;
let mut w_lock = wallet.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
let args = InitTxArgs {
src_acct_name: None,
amount,
@@ -207,15 +176,15 @@ where
selection_strategy_is_use_all: true,
..Default::default()
};
let slate_i = owner::init_send_tx(&mut *w, args, test_mode)?;
let slate_i = owner::init_send_tx(&mut **w, args, test_mode)?;
let slate = client.send_tx_slate_direct(dest, &slate_i)?;
owner::tx_lock_outputs(&mut *w, &slate, 0)?;
let slate = owner::finalize_tx(&mut *w, &slate)?;
w.close()?;
owner::tx_lock_outputs(&mut **w, &slate, 0)?;
let slate = owner::finalize_tx(&mut **w, &slate)?;
slate
};
let client = {
let mut w = wallet.lock();
let mut w_lock = wallet.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
w.w2n_client().clone()
};
owner::post_tx(&client, &slate.tx, false)?; // mines a block
@@ -223,18 +192,17 @@ where
}
/// get wallet info totals
pub fn wallet_info<T: ?Sized, C, K>(
wallet: Arc<Mutex<dyn WalletInst<C, K>>>,
pub fn wallet_info<'a, L, C, K>(
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
) -> Result<WalletInfo, libwallet::Error>
where
T: WalletBackend<C, K>,
C: NodeClient,
K: keychain::Keychain,
L: WalletLCProvider<'a, C, K>,
C: NodeClient + 'a,
K: keychain::Keychain + 'a,
{
let mut w = wallet.lock();
w.open_with_credentials()?;
let (wallet_refreshed, wallet_info) = owner::retrieve_summary_info(&mut *w, true, 1)?;
let mut w_lock = wallet.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
let (wallet_refreshed, wallet_info) = owner::retrieve_summary_info(&mut **w, true, 1)?;
assert!(wallet_refreshed);
w.close()?;
Ok(wallet_info)
}
+24 -71
View File
@@ -19,23 +19,23 @@
use crate::api;
use crate::chain::types::NoopAdapter;
use crate::chain::Chain;
use crate::config::WalletConfig;
use crate::core::core::verifier_cache::LruVerifierCache;
use crate::core::core::Transaction;
use crate::core::global::{set_mining_mode, ChainTypes};
use crate::core::{pow, ser};
use crate::keychain::Keychain;
use crate::libwallet;
use crate::libwallet::api_impl::foreign;
use crate::libwallet::{NodeClient, NodeVersionInfo, Slate, TxWrapper, WalletInst};
use crate::libwallet::{
NodeClient, NodeVersionInfo, Slate, TxWrapper, WalletInst, WalletLCProvider,
};
use crate::util;
use crate::util::secp::pedersen;
use crate::util::secp::pedersen::Commitment;
use crate::util::{Mutex, RwLock};
use crate::{libwallet, WalletCommAdapter};
use failure::ResultExt;
use serde_json;
use std::collections::HashMap;
use std::marker::PhantomData;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::Arc;
@@ -57,10 +57,11 @@ pub struct WalletProxyMessage {
/// communicates with a chain instance or other wallet
/// listener APIs via message queues
pub struct WalletProxy<C, K>
pub struct WalletProxy<'a, L, C, K>
where
C: NodeClient,
K: Keychain,
L: WalletLCProvider<'a, C, K>,
C: NodeClient + 'a,
K: Keychain + 'a,
{
/// directory to create the chain in
pub chain_dir: String,
@@ -71,7 +72,7 @@ where
String,
(
Sender<WalletProxyMessage>,
Arc<Mutex<dyn WalletInst<LocalWalletClient, K>>>,
Arc<Mutex<Box<dyn WalletInst<'a, L, C, K> + 'a>>>,
),
>,
/// simulate json send to another client
@@ -81,16 +82,13 @@ where
pub rx: Receiver<WalletProxyMessage>,
/// queue control
pub running: Arc<AtomicBool>,
/// Phantom
phantom_c: PhantomData<C>,
/// Phantom
phantom_k: PhantomData<K>,
}
impl<C, K> WalletProxy<C, K>
impl<'a, L, C, K> WalletProxy<'a, L, C, K>
where
C: NodeClient,
K: Keychain,
L: WalletLCProvider<'a, C, K>,
C: NodeClient + 'a,
K: Keychain + 'a,
{
/// Create a new client that will communicate with the given grin node
pub fn new(chain_dir: &str) -> Self {
@@ -115,8 +113,6 @@ where
rx: rx,
wallets: HashMap::new(),
running: Arc::new(AtomicBool::new(false)),
phantom_c: PhantomData,
phantom_k: PhantomData,
};
retval
}
@@ -126,7 +122,7 @@ where
&mut self,
addr: &str,
tx: Sender<WalletProxyMessage>,
wallet: Arc<Mutex<dyn WalletInst<LocalWalletClient, K>>>,
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K> + 'a>>>,
) {
self.wallets.insert(addr.to_owned(), (tx, wallet));
}
@@ -212,11 +208,10 @@ where
)?;
;
{
let mut w = wallet.1.lock();
w.open_with_credentials()?;
let mut w_lock = wallet.1.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
// receive tx
slate = foreign::receive_tx(&mut *w, &slate, None, None, false)?;
w.close()?;
slate = foreign::receive_tx(&mut **w, &slate, None, None, false)?;
}
Ok(WalletProxyMessage {
@@ -344,55 +339,6 @@ impl LocalWalletClient {
}
}
impl WalletCommAdapter for LocalWalletClient {
fn supports_sync(&self) -> bool {
true
}
/// Send the slate to a listening wallet instance
fn send_tx_sync(&self, dest: &str, slate: &Slate) -> Result<Slate, libwallet::Error> {
let m = WalletProxyMessage {
sender_id: self.id.clone(),
dest: dest.to_owned(),
method: "send_tx_slate".to_owned(),
body: serde_json::to_string(slate).unwrap(),
};
{
let p = self.proxy_tx.lock();
p.send(m).context(libwallet::ErrorKind::ClientCallback(
"Send TX Slate".to_owned(),
))?;
}
let r = self.rx.lock();
let m = r.recv().unwrap();
trace!("Received send_tx_slate response: {:?}", m.clone());
Ok(
serde_json::from_str(&m.body).context(libwallet::ErrorKind::ClientCallback(
"Parsing send_tx_slate response".to_owned(),
))?,
)
}
fn send_tx_async(&self, _dest: &str, _slate: &Slate) -> Result<(), libwallet::Error> {
unimplemented!();
}
fn receive_tx_async(&self, _params: &str) -> Result<Slate, libwallet::Error> {
unimplemented!();
}
fn listen(
&self,
_params: HashMap<String, String>,
_config: WalletConfig,
_passphrase: &str,
_account: &str,
_node_api_secret: Option<String>,
) -> Result<(), libwallet::Error> {
unimplemented!();
}
}
impl NodeClient for LocalWalletClient {
fn node_url(&self) -> &str {
"node"
@@ -535,3 +481,10 @@ impl NodeClient for LocalWalletClient {
Ok((o.highest_index, o.last_retrieved_index, api_outputs))
}
}
unsafe impl<'a, L, C, K> Send for WalletProxy<'a, L, C, K>
where
L: WalletLCProvider<'a, C, K>,
C: NodeClient + 'a,
K: Keychain + 'a,
{
}