mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-10-17 15:21:39 +02:00
Store XORed wallet seed in-mem (#200)
* experimental xor token work * rustfmt * test implementation of build_coinbase_t function * rustfmt * add separate foreign_rpc_s interface for secure functions * rustfmt * rustfmt * fix http scheme to allow https as well * add tokenized owner API, modify all functions to use token * rustfmt * fix for api doctests, tests passing up to api crate * rustfmt * controller crate compilation * rustfmt * controller tests passing and modified some to use masked keychains * rustfmt * fix wallet tests * rustfmt * build from github * rustfmt
This commit is contained in:
+84
-50
@@ -22,6 +22,7 @@ use crate::impls::{create_sender, KeybaseAllChannels, SlateGetter as _, SlateRec
|
||||
use crate::impls::{PathToSlate, SlatePutter};
|
||||
use crate::keychain;
|
||||
use crate::libwallet::{InitTxArgs, IssueInvoiceTxArgs, NodeClient, WalletInst, WalletLCProvider};
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::{Mutex, ZeroingString};
|
||||
use crate::{controller, display};
|
||||
use serde_json as json;
|
||||
@@ -120,6 +121,7 @@ pub struct ListenArgs {
|
||||
|
||||
pub fn listen<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
config: &WalletConfig,
|
||||
args: &ListenArgs,
|
||||
g_args: &GlobalArgs,
|
||||
@@ -132,6 +134,7 @@ where
|
||||
let res = match args.method.as_str() {
|
||||
"http" => controller::foreign_listener(
|
||||
wallet.clone(),
|
||||
keychain_mask,
|
||||
&config.api_listen_addr(),
|
||||
g_args.tls_conf.clone(),
|
||||
),
|
||||
@@ -158,6 +161,7 @@ where
|
||||
|
||||
pub fn owner_api<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
config: &WalletConfig,
|
||||
g_args: &GlobalArgs,
|
||||
) -> Result<(), Error>
|
||||
@@ -168,6 +172,7 @@ where
|
||||
{
|
||||
let res = controller::owner_listener(
|
||||
wallet,
|
||||
keychain_mask,
|
||||
config.owner_api_listen_addr().as_str(),
|
||||
g_args.node_api_secret.clone(),
|
||||
g_args.tls_conf.clone(),
|
||||
@@ -186,6 +191,7 @@ pub struct AccountArgs {
|
||||
|
||||
pub fn account<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: AccountArgs,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
@@ -194,8 +200,8 @@ where
|
||||
K: keychain::Keychain + 'a,
|
||||
{
|
||||
if args.create.is_none() {
|
||||
let res = controller::owner_single_use(wallet, |api| {
|
||||
let acct_mappings = api.accounts()?;
|
||||
let res = controller::owner_single_use(wallet, keychain_mask, |api, m| {
|
||||
let acct_mappings = api.accounts(m)?;
|
||||
// give logging thread a moment to catch up
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
display::accounts(acct_mappings);
|
||||
@@ -207,8 +213,8 @@ where
|
||||
}
|
||||
} else {
|
||||
let label = args.create.unwrap();
|
||||
let res = controller::owner_single_use(wallet, |api| {
|
||||
api.create_account_path(&label)?;
|
||||
let res = controller::owner_single_use(wallet, keychain_mask, |api, m| {
|
||||
api.create_account_path(m, &label)?;
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
info!("Account: '{}' Created!", label);
|
||||
Ok(())
|
||||
@@ -239,6 +245,7 @@ pub struct SendArgs {
|
||||
|
||||
pub fn send<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: SendArgs,
|
||||
dark_scheme: bool,
|
||||
) -> Result<(), Error>
|
||||
@@ -247,7 +254,7 @@ where
|
||||
C: NodeClient + 'a,
|
||||
K: keychain::Keychain + 'a,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
if args.estimate_selection_strategies {
|
||||
let strategies = vec!["smallest", "all"]
|
||||
.into_iter()
|
||||
@@ -262,7 +269,7 @@ where
|
||||
estimate_only: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let slate = api.init_send_tx(init_args).unwrap();
|
||||
let slate = api.init_send_tx(m, init_args).unwrap();
|
||||
(strategy, slate.amount, slate.fee)
|
||||
})
|
||||
.collect();
|
||||
@@ -280,7 +287,7 @@ where
|
||||
send_args: None,
|
||||
..Default::default()
|
||||
};
|
||||
let result = api.init_send_tx(init_args);
|
||||
let result = api.init_send_tx(m, init_args);
|
||||
let mut slate = match result {
|
||||
Ok(s) => {
|
||||
info!(
|
||||
@@ -300,12 +307,16 @@ where
|
||||
match args.method.as_str() {
|
||||
"file" => {
|
||||
PathToSlate((&args.dest).into()).put_tx(&slate)?;
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
return Ok(());
|
||||
}
|
||||
"self" => {
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
controller::foreign_single_use(wallet, |api| {
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
let km = match keychain_mask.as_ref() {
|
||||
None => None,
|
||||
Some(&m) => Some(m.to_owned()),
|
||||
};
|
||||
controller::foreign_single_use(wallet, km, |api| {
|
||||
slate = api.receive_tx(&slate, Some(&args.dest), None)?;
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -313,16 +324,16 @@ where
|
||||
method => {
|
||||
let sender = create_sender(method, &args.dest)?;
|
||||
slate = sender.send_tx(&slate)?;
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
}
|
||||
}
|
||||
|
||||
api.verify_slate_messages(&slate).map_err(|e| {
|
||||
api.verify_slate_messages(m, &slate).map_err(|e| {
|
||||
error!("Error validating participant messages: {}", e);
|
||||
e
|
||||
})?;
|
||||
slate = api.finalize_tx(&slate)?;
|
||||
let result = api.post_tx(&slate.tx, args.fluff);
|
||||
slate = api.finalize_tx(m, &slate)?;
|
||||
let result = api.post_tx(m, &slate.tx, args.fluff);
|
||||
match result {
|
||||
Ok(_) => {
|
||||
info!("Tx sent ok",);
|
||||
@@ -347,6 +358,7 @@ pub struct ReceiveArgs {
|
||||
|
||||
pub fn receive<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
g_args: &GlobalArgs,
|
||||
args: ReceiveArgs,
|
||||
) -> Result<(), Error>
|
||||
@@ -356,7 +368,11 @@ where
|
||||
K: keychain::Keychain + 'a,
|
||||
{
|
||||
let mut slate = PathToSlate((&args.input).into()).get_tx()?;
|
||||
controller::foreign_single_use(wallet, |api| {
|
||||
let km = match keychain_mask.as_ref() {
|
||||
None => None,
|
||||
Some(&m) => Some(m.to_owned()),
|
||||
};
|
||||
controller::foreign_single_use(wallet, km, |api| {
|
||||
if let Err(e) = api.verify_slate_messages(&slate) {
|
||||
error!("Error validating participant messages: {}", e);
|
||||
return Err(e);
|
||||
@@ -380,6 +396,7 @@ pub struct FinalizeArgs {
|
||||
|
||||
pub fn finalize<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: FinalizeArgs,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
@@ -408,7 +425,11 @@ where
|
||||
};
|
||||
|
||||
if is_invoice {
|
||||
controller::foreign_single_use(wallet.clone(), |api| {
|
||||
let km = match keychain_mask.as_ref() {
|
||||
None => None,
|
||||
Some(&m) => Some(m.to_owned()),
|
||||
};
|
||||
controller::foreign_single_use(wallet.clone(), km, |api| {
|
||||
if let Err(e) = api.verify_slate_messages(&slate) {
|
||||
error!("Error validating participant messages: {}", e);
|
||||
return Err(e);
|
||||
@@ -417,18 +438,18 @@ where
|
||||
Ok(())
|
||||
})?;
|
||||
} else {
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
if let Err(e) = api.verify_slate_messages(&slate) {
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
if let Err(e) = api.verify_slate_messages(m, &slate) {
|
||||
error!("Error validating participant messages: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
slate = api.finalize_tx(&mut slate)?;
|
||||
slate = api.finalize_tx(m, &mut slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
let result = api.post_tx(&slate.tx, args.fluff);
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let result = api.post_tx(m, &slate.tx, args.fluff);
|
||||
match result {
|
||||
Ok(_) => {
|
||||
info!("Transaction sent successfully, check the wallet again for confirmation.");
|
||||
@@ -454,6 +475,7 @@ pub struct IssueInvoiceArgs {
|
||||
|
||||
pub fn issue_invoice_tx<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: IssueInvoiceArgs,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
@@ -461,8 +483,8 @@ where
|
||||
C: NodeClient + 'a,
|
||||
K: keychain::Keychain + 'a,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
let slate = api.issue_invoice_tx(args.issue_args)?;
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let slate = api.issue_invoice_tx(m, args.issue_args)?;
|
||||
let mut tx_file = File::create(args.dest.clone())?;
|
||||
tx_file.write_all(json::to_string(&slate).unwrap().as_bytes())?;
|
||||
tx_file.sync_all()?;
|
||||
@@ -486,6 +508,7 @@ pub struct ProcessInvoiceArgs {
|
||||
/// Process invoice
|
||||
pub fn process_invoice<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: ProcessInvoiceArgs,
|
||||
dark_scheme: bool,
|
||||
) -> Result<(), Error>
|
||||
@@ -495,7 +518,7 @@ where
|
||||
K: keychain::Keychain + 'a,
|
||||
{
|
||||
let slate = PathToSlate((&args.input).into()).get_tx()?;
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
if args.estimate_selection_strategies {
|
||||
let strategies = vec!["smallest", "all"]
|
||||
.into_iter()
|
||||
@@ -510,7 +533,7 @@ where
|
||||
estimate_only: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let slate = api.init_send_tx(init_args).unwrap();
|
||||
let slate = api.init_send_tx(m, init_args).unwrap();
|
||||
(strategy, slate.amount, slate.fee)
|
||||
})
|
||||
.collect();
|
||||
@@ -527,11 +550,11 @@ where
|
||||
send_args: None,
|
||||
..Default::default()
|
||||
};
|
||||
if let Err(e) = api.verify_slate_messages(&slate) {
|
||||
if let Err(e) = api.verify_slate_messages(m, &slate) {
|
||||
error!("Error validating participant messages: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
let result = api.process_invoice_tx(&slate, init_args);
|
||||
let result = api.process_invoice_tx(m, &slate, init_args);
|
||||
let mut slate = match result {
|
||||
Ok(s) => {
|
||||
info!(
|
||||
@@ -552,11 +575,15 @@ where
|
||||
"file" => {
|
||||
let slate_putter = PathToSlate((&args.dest).into());
|
||||
slate_putter.put_tx(&slate)?;
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
}
|
||||
"self" => {
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
controller::foreign_single_use(wallet, |api| {
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
let km = match keychain_mask.as_ref() {
|
||||
None => None,
|
||||
Some(&m) => Some(m.to_owned()),
|
||||
};
|
||||
controller::foreign_single_use(wallet, km, |api| {
|
||||
slate = api.finalize_invoice_tx(&slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -564,7 +591,7 @@ where
|
||||
method => {
|
||||
let sender = create_sender(method, &args.dest)?;
|
||||
slate = sender.send_tx(&slate)?;
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -579,6 +606,7 @@ pub struct InfoArgs {
|
||||
|
||||
pub fn info<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
g_args: &GlobalArgs,
|
||||
args: InfoArgs,
|
||||
dark_scheme: bool,
|
||||
@@ -588,9 +616,9 @@ where
|
||||
C: NodeClient + 'a,
|
||||
K: keychain::Keychain + 'a,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let (validated, wallet_info) =
|
||||
api.retrieve_summary_info(true, args.minimum_confirmations)?;
|
||||
api.retrieve_summary_info(m, true, args.minimum_confirmations)?;
|
||||
display::info(&g_args.account, &wallet_info, validated, dark_scheme);
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -599,6 +627,7 @@ where
|
||||
|
||||
pub fn outputs<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
g_args: &GlobalArgs,
|
||||
dark_scheme: bool,
|
||||
) -> Result<(), Error>
|
||||
@@ -607,9 +636,9 @@ where
|
||||
C: NodeClient + 'a,
|
||||
K: keychain::Keychain + 'a,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
let res = api.node_height()?;
|
||||
let (validated, outputs) = api.retrieve_outputs(g_args.show_spent, true, None)?;
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let res = api.node_height(m)?;
|
||||
let (validated, outputs) = api.retrieve_outputs(m, g_args.show_spent, true, None)?;
|
||||
display::outputs(&g_args.account, res.height, validated, outputs, dark_scheme)?;
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -624,6 +653,7 @@ pub struct TxsArgs {
|
||||
|
||||
pub fn txs<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
g_args: &GlobalArgs,
|
||||
args: TxsArgs,
|
||||
dark_scheme: bool,
|
||||
@@ -633,9 +663,9 @@ where
|
||||
C: NodeClient + 'a,
|
||||
K: keychain::Keychain + 'a,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
let res = api.node_height()?;
|
||||
let (validated, txs) = api.retrieve_txs(true, args.id, args.tx_slate_id)?;
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let res = api.node_height(m)?;
|
||||
let (validated, txs) = api.retrieve_txs(m, true, args.id, args.tx_slate_id)?;
|
||||
let include_status = !args.id.is_some() && !args.tx_slate_id.is_some();
|
||||
display::txs(
|
||||
&g_args.account,
|
||||
@@ -662,7 +692,7 @@ where
|
||||
};
|
||||
|
||||
if id.is_some() {
|
||||
let (_, outputs) = api.retrieve_outputs(true, false, id)?;
|
||||
let (_, outputs) = api.retrieve_outputs(m, true, false, id)?;
|
||||
display::outputs(&g_args.account, res.height, validated, outputs, dark_scheme)?;
|
||||
// should only be one here, but just in case
|
||||
for tx in txs {
|
||||
@@ -684,6 +714,7 @@ pub struct RepostArgs {
|
||||
|
||||
pub fn repost<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: RepostArgs,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
@@ -691,9 +722,9 @@ where
|
||||
C: NodeClient + 'a,
|
||||
K: keychain::Keychain + 'a,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
let (_, txs) = api.retrieve_txs(true, Some(args.id), None)?;
|
||||
let stored_tx = api.get_stored_tx(&txs[0])?;
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let (_, txs) = api.retrieve_txs(m, true, Some(args.id), None)?;
|
||||
let stored_tx = api.get_stored_tx(m, &txs[0])?;
|
||||
if stored_tx.is_none() {
|
||||
error!(
|
||||
"Transaction with id {} does not have transaction data. Not reposting.",
|
||||
@@ -710,7 +741,7 @@ where
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
api.post_tx(&stored_tx.unwrap(), args.fluff)?;
|
||||
api.post_tx(m, &stored_tx.unwrap(), args.fluff)?;
|
||||
info!("Reposted transaction at {}", args.id);
|
||||
return Ok(());
|
||||
}
|
||||
@@ -735,6 +766,7 @@ pub struct CancelArgs {
|
||||
|
||||
pub fn cancel<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: CancelArgs,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
@@ -742,8 +774,8 @@ where
|
||||
C: NodeClient + 'a,
|
||||
K: keychain::Keychain + 'a,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
let result = api.cancel_tx(args.tx_id, args.tx_slate_id);
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let result = api.cancel_tx(m, args.tx_id, args.tx_slate_id);
|
||||
match result {
|
||||
Ok(_) => {
|
||||
info!("Transaction {} Cancelled", args.tx_id_string);
|
||||
@@ -760,14 +792,15 @@ where
|
||||
|
||||
pub fn restore<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
L: WalletLCProvider<'a, C, K>,
|
||||
C: NodeClient + 'a,
|
||||
K: keychain::Keychain + 'a,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
let result = api.restore();
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let result = api.restore(m);
|
||||
match result {
|
||||
Ok(_) => {
|
||||
warn!("Wallet restore complete",);
|
||||
@@ -790,6 +823,7 @@ pub struct CheckArgs {
|
||||
|
||||
pub fn check_repair<'a, L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: CheckArgs,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
@@ -797,10 +831,10 @@ where
|
||||
C: NodeClient + 'a,
|
||||
K: keychain::Keychain + 'a,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
warn!("Starting wallet check...",);
|
||||
warn!("Updating all wallet outputs, please wait ...",);
|
||||
let result = api.check_repair(args.delete_unconfirmed);
|
||||
let result = api.check_repair(m, args.delete_unconfirmed);
|
||||
match result {
|
||||
Ok(_) => {
|
||||
warn!("Wallet check complete",);
|
||||
|
||||
@@ -20,6 +20,7 @@ use crate::libwallet::{
|
||||
Error, ErrorKind, NodeClient, NodeVersionInfo, Slate, WalletInst, WalletLCProvider,
|
||||
CURRENT_SLATE_VERSION, GRIN_BLOCK_HEADER_VERSION,
|
||||
};
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::{to_base64, Mutex};
|
||||
use failure::ResultExt;
|
||||
use futures::future::{err, ok};
|
||||
@@ -73,23 +74,25 @@ fn check_middleware(
|
||||
/// Instantiate wallet Owner API for a single-use (command line) call
|
||||
/// Return a function containing a loaded API context to call
|
||||
pub fn owner_single_use<'a, L, F, C, K>(
|
||||
lc_provider: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
f: F,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
L: WalletLCProvider<'a, C, K>,
|
||||
F: FnOnce(&mut Owner<'a, L, C, K>) -> Result<(), Error>,
|
||||
F: FnOnce(&mut Owner<'a, L, C, K>, Option<&SecretKey>) -> Result<(), Error>,
|
||||
C: NodeClient + 'a,
|
||||
K: Keychain + 'a,
|
||||
{
|
||||
f(&mut Owner::new(lc_provider))?;
|
||||
f(&mut Owner::new(wallet), keychain_mask)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Instantiate wallet Foreign API for a single-use (command line) call
|
||||
/// Return a function containing a loaded API context to call
|
||||
pub fn foreign_single_use<'a, L, F, C, K>(
|
||||
lc_provider: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
f: F,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
@@ -98,14 +101,21 @@ where
|
||||
C: NodeClient + 'a,
|
||||
K: Keychain + 'a,
|
||||
{
|
||||
f(&mut Foreign::new(lc_provider, Some(check_middleware)))?;
|
||||
f(&mut Foreign::new(
|
||||
wallet,
|
||||
keychain_mask,
|
||||
Some(check_middleware),
|
||||
))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Listener version, providing same API but listening for requests on a
|
||||
/// port and wrapping the calls
|
||||
/// Note keychain mask is only provided here in case the foreign listener is also being used
|
||||
/// in the same wallet instance
|
||||
pub fn owner_listener<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K> + 'static>>>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
addr: &str,
|
||||
api_secret: Option<String>,
|
||||
tls_config: Option<TLSConfig>,
|
||||
@@ -136,7 +146,7 @@ where
|
||||
// If so configured, add the foreign API to the same port
|
||||
if owner_api_include_foreign.unwrap_or(false) {
|
||||
warn!("Starting HTTP Foreign API on Owner server at {}.", addr);
|
||||
let foreign_api_handler_v2 = ForeignAPIHandlerV2::new(wallet);
|
||||
let foreign_api_handler_v2 = ForeignAPIHandlerV2::new(wallet, keychain_mask);
|
||||
router
|
||||
.add_route("/v2/foreign", Arc::new(foreign_api_handler_v2))
|
||||
.map_err(|_| ErrorKind::GenericError("Router failed to add route".to_string()))?;
|
||||
@@ -160,6 +170,7 @@ where
|
||||
/// port and wrapping the calls
|
||||
pub fn foreign_listener<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K> + 'static>>>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
addr: &str,
|
||||
tls_config: Option<TLSConfig>,
|
||||
) -> Result<(), Error>
|
||||
@@ -168,7 +179,7 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
let api_handler_v2 = ForeignAPIHandlerV2::new(wallet);
|
||||
let api_handler_v2 = ForeignAPIHandlerV2::new(wallet, keychain_mask);
|
||||
|
||||
let mut router = Router::new();
|
||||
|
||||
@@ -275,6 +286,8 @@ where
|
||||
{
|
||||
/// Wallet instance
|
||||
pub wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K> + 'static>>>,
|
||||
/// Keychain mask
|
||||
pub keychain_mask: Option<SecretKey>,
|
||||
}
|
||||
|
||||
impl<L, C, K> ForeignAPIHandlerV2<L, C, K>
|
||||
@@ -286,8 +299,12 @@ where
|
||||
/// Create a new foreign API handler for GET methods
|
||||
pub fn new(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K> + 'static>>>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
) -> ForeignAPIHandlerV2<L, C, K> {
|
||||
ForeignAPIHandlerV2 { wallet }
|
||||
ForeignAPIHandlerV2 {
|
||||
wallet,
|
||||
keychain_mask,
|
||||
}
|
||||
}
|
||||
|
||||
fn call_api(
|
||||
@@ -309,7 +326,11 @@ where
|
||||
}
|
||||
|
||||
fn handle_post_request(&self, req: Request<Body>) -> WalletResponseFuture {
|
||||
let api = Foreign::new(self.wallet.clone(), Some(check_middleware));
|
||||
let api = Foreign::new(
|
||||
self.wallet.clone(),
|
||||
self.keychain_mask.clone(),
|
||||
Some(check_middleware),
|
||||
);
|
||||
Box::new(
|
||||
self.call_api(req, api)
|
||||
.and_then(|resp| ok(json_response_pretty(&resp))),
|
||||
|
||||
@@ -43,20 +43,29 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
create_wallet_and_add!(
|
||||
client1,
|
||||
wallet1,
|
||||
mask1_i,
|
||||
test_dir,
|
||||
"wallet1",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
mask2_i,
|
||||
test_dir,
|
||||
"wallet2",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = wallet_proxy.run() {
|
||||
@@ -69,30 +78,30 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let cm = global::coinbase_maturity(); // assume all testing precedes soft fork height
|
||||
|
||||
// test default accounts exist
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let accounts = api.accounts()?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let accounts = api.accounts(m)?;
|
||||
assert_eq!(accounts[0].label, "default");
|
||||
assert_eq!(accounts[0].path, ExtKeychain::derive_key_id(2, 0, 0, 0, 0));
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let new_path = api.create_account_path("account1").unwrap();
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let new_path = api.create_account_path(m, "account1").unwrap();
|
||||
assert_eq!(new_path, ExtKeychain::derive_key_id(2, 1, 0, 0, 0));
|
||||
let new_path = api.create_account_path("account2").unwrap();
|
||||
let new_path = api.create_account_path(m, "account2").unwrap();
|
||||
assert_eq!(new_path, ExtKeychain::derive_key_id(2, 2, 0, 0, 0));
|
||||
let new_path = api.create_account_path("account3").unwrap();
|
||||
let new_path = api.create_account_path(m, "account3").unwrap();
|
||||
assert_eq!(new_path, ExtKeychain::derive_key_id(2, 3, 0, 0, 0));
|
||||
// trying to add same label again should fail
|
||||
let res = api.create_account_path("account1");
|
||||
let res = api.create_account_path(m, "account1");
|
||||
assert!(res.is_err());
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// add account to wallet 2
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let new_path = api.create_account_path("listener_account").unwrap();
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let new_path = api.create_account_path(m, "listener_account").unwrap();
|
||||
assert_eq!(new_path, ExtKeychain::derive_key_id(2, 1, 0, 0, 0));
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -109,24 +118,24 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
w.set_parent_key_id_by_name("account1")?;
|
||||
assert_eq!(w.parent_key_id(), ExtKeychain::derive_key_id(2, 1, 0, 0, 0));
|
||||
}
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 7, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 7, false);
|
||||
|
||||
{
|
||||
wallet_inst!(wallet1, w);
|
||||
w.set_parent_key_id_by_name("account2")?;
|
||||
assert_eq!(w.parent_key_id(), ExtKeychain::derive_key_id(2, 2, 0, 0, 0));
|
||||
}
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 5, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 5, false);
|
||||
|
||||
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 12);
|
||||
assert_eq!(wallet1_info.total, 5 * reward);
|
||||
assert_eq!(wallet1_info.amount_currently_spendable, (5 - cm) * reward);
|
||||
// check tx log as well
|
||||
let (_, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert_eq!(txs.len(), 5);
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -137,17 +146,17 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let w = lc.wallet_inst()?;
|
||||
w.set_parent_key_id_by_name("account1")?;
|
||||
}
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
// check last confirmed height on this account is different from above (should be 0)
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(false, 1)?;
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, false, 1)?;
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 0);
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 12);
|
||||
assert_eq!(wallet1_info.total, 7 * reward);
|
||||
assert_eq!(wallet1_info.amount_currently_spendable, 7 * reward);
|
||||
// check tx log as well
|
||||
let (_, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert_eq!(txs.len(), 7);
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -157,16 +166,16 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
wallet_inst!(wallet1, w);
|
||||
w.set_parent_key_id_by_name("default")?;
|
||||
}
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(false, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, false, 1)?;
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 0);
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 12);
|
||||
assert_eq!(wallet1_info.total, 0,);
|
||||
assert_eq!(wallet1_info.amount_currently_spendable, 0,);
|
||||
// check tx log as well
|
||||
let (_, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert_eq!(txs.len(), 0);
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -177,7 +186,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
w.set_parent_key_id_by_name("account1")?;
|
||||
}
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: reward,
|
||||
@@ -187,19 +196,19 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let mut slate = api.init_send_tx(args)?;
|
||||
let mut slate = api.init_send_tx(m, args)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
slate = api.finalize_tx(&slate)?;
|
||||
api.post_tx(&slate.tx, false)?;
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
slate = api.finalize_tx(m, &slate)?;
|
||||
api.post_tx(m, &slate.tx, false)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 13);
|
||||
let (_, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert_eq!(txs.len(), 9);
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -209,23 +218,23 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
wallet_inst!(wallet1, w);
|
||||
w.set_parent_key_id_by_name("account2")?;
|
||||
}
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(false, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, false, 1)?;
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 12);
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 13);
|
||||
let (_, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
println!("{:?}", txs);
|
||||
assert_eq!(txs.len(), 5);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// wallet 2 should only have this tx on the listener account
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.last_confirmed_height, 13);
|
||||
let (_, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert_eq!(txs.len(), 1);
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -234,16 +243,16 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
wallet_inst!(wallet2, w);
|
||||
w.set_parent_key_id_by_name("default")?;
|
||||
}
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let (_, wallet2_info) = api.retrieve_summary_info(false, 1)?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let (_, wallet2_info) = api.retrieve_summary_info(m, false, 1)?;
|
||||
assert_eq!(wallet2_info.last_confirmed_height, 0);
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(true, 1)?;
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.last_confirmed_height, 13);
|
||||
assert_eq!(wallet2_info.total, 0,);
|
||||
assert_eq!(wallet2_info.amount_currently_spendable, 0,);
|
||||
// check tx log as well
|
||||
let (_, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert_eq!(txs.len(), 0);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
+327
-142
@@ -35,14 +35,14 @@ mod common;
|
||||
use common::{create_wallet_proxy, setup};
|
||||
|
||||
macro_rules! send_to_dest {
|
||||
($a:expr, $b:expr, $c:expr, $d:expr) => {
|
||||
test_framework::send_to_dest($a, $b, $c, $d, false)
|
||||
($a:expr, $m: expr, $b:expr, $c:expr, $d:expr) => {
|
||||
test_framework::send_to_dest($a, $m, $b, $c, $d, false)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! wallet_info {
|
||||
($a:expr) => {
|
||||
test_framework::wallet_info($a)
|
||||
($a:expr, $m:expr) => {
|
||||
test_framework::wallet_info($a, $m)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -59,19 +59,25 @@ fn check_repair_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
create_wallet_and_add!(
|
||||
client1,
|
||||
wallet1,
|
||||
mask1_i,
|
||||
test_dir,
|
||||
"wallet1",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
mask2_i,
|
||||
test_dir,
|
||||
"wallet2",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -85,34 +91,35 @@ fn check_repair_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let cm = global::coinbase_maturity() as u64; // assume all testing precedes soft fork height
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
api.create_account_path("account_1")?;
|
||||
api.create_account_path("account_2")?;
|
||||
api.create_account_path("account_3")?;
|
||||
api.set_active_account("account_1")?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.create_account_path(m, "account_1")?;
|
||||
api.create_account_path(m, "account_2")?;
|
||||
api.create_account_path(m, "account_3")?;
|
||||
api.set_active_account(m, "account_1")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// add account to wallet 2
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
api.create_account_path("account_1")?;
|
||||
api.set_active_account("account_1")?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
api.create_account_path(m, "account_1")?;
|
||||
api.set_active_account(m, "account_1")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// Do some mining
|
||||
let bh = 20u64;
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize, false);
|
||||
let _ =
|
||||
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
|
||||
|
||||
// Sanity check contents
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, bh * reward);
|
||||
assert_eq!(wallet1_info.amount_currently_spendable, (bh - cm) * reward);
|
||||
// check tx log as well
|
||||
let (_, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
let (c, _) = libwallet::TxLogEntry::sum_confirmed(&txs);
|
||||
assert_eq!(wallet1_info.total, c);
|
||||
assert_eq!(txs.len(), bh as usize);
|
||||
@@ -121,8 +128,8 @@ fn check_repair_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
|
||||
// Accidentally delete some outputs
|
||||
let mut w1_outputs_commits = vec![];
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
w1_outputs_commits = api.retrieve_outputs(false, true, None)?.1;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
w1_outputs_commits = api.retrieve_outputs(m, false, true, None)?.1;
|
||||
Ok(())
|
||||
})?;
|
||||
let w1_outputs: Vec<libwallet::OutputData> =
|
||||
@@ -130,7 +137,7 @@ fn check_repair_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
{
|
||||
wallet_inst!(wallet1, w);
|
||||
{
|
||||
let mut batch = w.batch()?;
|
||||
let mut batch = w.batch(mask1)?;
|
||||
batch.delete(&w1_outputs[4].key_id, &None)?;
|
||||
batch.delete(&w1_outputs[10].key_id, &None)?;
|
||||
let mut accidental_spent = w1_outputs[13].clone();
|
||||
@@ -141,30 +148,30 @@ fn check_repair_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
}
|
||||
|
||||
// check we have a problem now
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
let (_, txs) = api.retrieve_txs(true, None, None)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
let (c, _) = libwallet::TxLogEntry::sum_confirmed(&txs);
|
||||
assert!(wallet1_info.total != c);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// this should restore our missing outputs
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
api.check_repair(true)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.check_repair(m, true)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// check our outputs match again
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.total, bh * reward);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// perform a transaction, but don't let it finish
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
// send to send
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -175,30 +182,30 @@ fn check_repair_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate = api.init_send_tx(args)?;
|
||||
let slate = api.init_send_tx(m, args)?;
|
||||
// output tx file
|
||||
let send_file = format!("{}/part_tx_1.tx", test_dir);
|
||||
PathToSlate(send_file.into()).put_tx(&slate)?;
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// check we're all locked
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_info.amount_currently_spendable == 0);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// unlock/restore
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
api.check_repair(true)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.check_repair(m, true)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// check spendable amount again
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert_eq!(wallet1_info.amount_currently_spendable, (bh - cm) * reward);
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -221,94 +228,134 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
|
||||
// Create a new wallet test client, and set its queues to communicate with the
|
||||
// proxy
|
||||
create_wallet_and_add!(m_client, miner, test_dir, "miner", None, &mut wallet_proxy);
|
||||
create_wallet_and_add!(
|
||||
m_client,
|
||||
miner,
|
||||
miner_mask_i,
|
||||
test_dir,
|
||||
"miner",
|
||||
None,
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let miner_mask = (&miner_mask_i).as_ref();
|
||||
|
||||
// non-mining recipient wallets
|
||||
create_wallet_and_add!(
|
||||
client1,
|
||||
wallet1,
|
||||
mask1_i,
|
||||
test_dir,
|
||||
"wallet1",
|
||||
seed_phrase,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
mask2_i,
|
||||
test_dir,
|
||||
"wallet2",
|
||||
seed_phrase,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
// we'll restore into here
|
||||
create_wallet_and_add!(
|
||||
client3,
|
||||
wallet3,
|
||||
mask3_i,
|
||||
test_dir,
|
||||
"wallet3",
|
||||
seed_phrase,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask3 = (&mask3_i).as_ref();
|
||||
// also restore into here
|
||||
create_wallet_and_add!(
|
||||
client4,
|
||||
wallet4,
|
||||
mask4_i,
|
||||
test_dir,
|
||||
"wallet4",
|
||||
seed_phrase,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask4 = (&mask4_i).as_ref();
|
||||
// Simulate a recover from seed without restore into here
|
||||
create_wallet_and_add!(
|
||||
client5,
|
||||
wallet5,
|
||||
mask5_i,
|
||||
test_dir,
|
||||
"wallet5",
|
||||
seed_phrase,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
//simulate a recover from seed without restore into here
|
||||
let mask5 = (&mask5_i).as_ref();
|
||||
create_wallet_and_add!(
|
||||
client6,
|
||||
wallet6,
|
||||
mask6_i,
|
||||
test_dir,
|
||||
"wallet6",
|
||||
seed_phrase,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask6 = (&mask6_i).as_ref();
|
||||
|
||||
create_wallet_and_add!(
|
||||
client7,
|
||||
wallet7,
|
||||
mask7_i,
|
||||
test_dir,
|
||||
"wallet7",
|
||||
seed_phrase,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask7 = (&mask7_i).as_ref();
|
||||
create_wallet_and_add!(
|
||||
client8,
|
||||
wallet8,
|
||||
mask8_i,
|
||||
test_dir,
|
||||
"wallet8",
|
||||
seed_phrase,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask8 = (&mask8_i).as_ref();
|
||||
create_wallet_and_add!(
|
||||
client9,
|
||||
wallet9,
|
||||
mask9_i,
|
||||
test_dir,
|
||||
"wallet9",
|
||||
seed_phrase,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask9 = (&mask9_i).as_ref();
|
||||
create_wallet_and_add!(
|
||||
client10,
|
||||
wallet10,
|
||||
mask10_i,
|
||||
test_dir,
|
||||
"wallet10",
|
||||
seed_phrase,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask10 = (&mask10_i).as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -324,38 +371,80 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
// Do some mining
|
||||
let mut bh = 20u64;
|
||||
let base_amount = consensus::GRIN_BASE;
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), bh as usize, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(
|
||||
&chain,
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
bh as usize,
|
||||
false,
|
||||
);
|
||||
|
||||
// send some funds to wallets 1
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet1", base_amount * 1)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet1", base_amount * 2)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet1", base_amount * 3)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet1",
|
||||
base_amount * 1
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet1",
|
||||
base_amount * 2
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet1",
|
||||
base_amount * 3
|
||||
)?;
|
||||
bh += 3;
|
||||
|
||||
// 0) Check repair when all is okay should leave wallet contents alone
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
api.check_repair(true)?;
|
||||
let info = wallet_info!(wallet1.clone())?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.check_repair(m, true)?;
|
||||
let info = wallet_info!(wallet1.clone(), m)?;
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 6);
|
||||
assert_eq!(info.total, base_amount * 6);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// send some funds to wallet 2
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet2", base_amount * 4)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet2", base_amount * 5)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet2", base_amount * 6)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet2",
|
||||
base_amount * 4
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet2",
|
||||
base_amount * 5
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet2",
|
||||
base_amount * 6
|
||||
)?;
|
||||
bh += 3;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), miner_mask, cm, false);
|
||||
bh += cm as u64;
|
||||
|
||||
// confirm balances
|
||||
let info = wallet_info!(wallet1.clone())?;
|
||||
let info = wallet_info!(wallet1.clone(), mask1)?;
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 6);
|
||||
assert_eq!(info.total, base_amount * 6);
|
||||
|
||||
let info = wallet_info!(wallet2.clone())?;
|
||||
let info = wallet_info!(wallet2.clone(), mask2)?;
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 15);
|
||||
assert_eq!(info.total, base_amount * 15);
|
||||
|
||||
@@ -363,14 +452,14 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
// seed + BIP32 path.
|
||||
|
||||
// 1) a full restore should recover all of them:
|
||||
wallet::controller::owner_single_use(wallet3.clone(), |api| {
|
||||
api.restore()?;
|
||||
wallet::controller::owner_single_use(wallet3.clone(), mask3, |api, m| {
|
||||
api.restore(m)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet3.clone(), |api| {
|
||||
let info = wallet_info!(wallet3.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
wallet::controller::owner_single_use(wallet3.clone(), mask3, |api, m| {
|
||||
let info = wallet_info!(wallet3.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 6);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 21);
|
||||
assert_eq!(info.total, base_amount * 21);
|
||||
@@ -378,14 +467,14 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
})?;
|
||||
|
||||
// 2) check_repair should recover them into a single wallet
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
api.check_repair(true)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.check_repair(m, true)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let info = wallet_info!(wallet1.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let info = wallet_info!(wallet1.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 6);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 21);
|
||||
Ok(())
|
||||
@@ -393,30 +482,48 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
|
||||
// 3) If I recover from seed and start using the wallet without restoring,
|
||||
// check_repair should restore the older outputs
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet4", base_amount * 7)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet4", base_amount * 8)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet4", base_amount * 9)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet4",
|
||||
base_amount * 7
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet4",
|
||||
base_amount * 8
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet4",
|
||||
base_amount * 9
|
||||
)?;
|
||||
bh += 3;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), miner_mask, cm, false);
|
||||
bh += cm as u64;
|
||||
|
||||
wallet::controller::owner_single_use(wallet4.clone(), |api| {
|
||||
let info = wallet_info!(wallet4.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
wallet::controller::owner_single_use(wallet4.clone(), mask4, |api, m| {
|
||||
let info = wallet_info!(wallet4.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 3);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 24);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet5.clone(), |api| {
|
||||
api.restore()?;
|
||||
wallet::controller::owner_single_use(wallet5.clone(), mask5, |api, m| {
|
||||
api.restore(m)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet5.clone(), |api| {
|
||||
let info = wallet_info!(wallet5.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
wallet::controller::owner_single_use(wallet5.clone(), mask5, |api, m| {
|
||||
let info = wallet_info!(wallet5.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 9);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * (45));
|
||||
Ok(())
|
||||
@@ -424,30 +531,54 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
|
||||
// 4) If I recover from seed and start using the wallet without restoring,
|
||||
// check_repair should restore the older outputs
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet6", base_amount * 10)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet6", base_amount * 11)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet6", base_amount * 12)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet6",
|
||||
base_amount * 10
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet6",
|
||||
base_amount * 11
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet6",
|
||||
base_amount * 12
|
||||
)?;
|
||||
bh += 3;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm as usize, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(
|
||||
&chain,
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
cm as usize,
|
||||
false,
|
||||
);
|
||||
bh += cm as u64;
|
||||
|
||||
wallet::controller::owner_single_use(wallet6.clone(), |api| {
|
||||
let info = wallet_info!(wallet6.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
wallet::controller::owner_single_use(wallet6.clone(), mask6, |api, m| {
|
||||
let info = wallet_info!(wallet6.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 3);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 33);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet6.clone(), |api| {
|
||||
api.check_repair(true)?;
|
||||
wallet::controller::owner_single_use(wallet6.clone(), mask6, |api, m| {
|
||||
api.check_repair(m, true)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet6.clone(), |api| {
|
||||
let info = wallet_info!(wallet6.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
wallet::controller::owner_single_use(wallet6.clone(), mask6, |api, m| {
|
||||
let info = wallet_info!(wallet6.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 12);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * (78));
|
||||
Ok(())
|
||||
@@ -456,49 +587,85 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
// 5) Start using same seed with a different account, amounts should
|
||||
// be distinct and restore should return funds from other account
|
||||
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet7", base_amount * 13)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet7", base_amount * 14)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet7", base_amount * 15)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet7",
|
||||
base_amount * 13
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet7",
|
||||
base_amount * 14
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet7",
|
||||
base_amount * 15
|
||||
)?;
|
||||
bh += 3;
|
||||
|
||||
// mix it up a bit
|
||||
wallet::controller::owner_single_use(wallet7.clone(), |api| {
|
||||
api.create_account_path("account_1")?;
|
||||
api.set_active_account("account_1")?;
|
||||
wallet::controller::owner_single_use(wallet7.clone(), mask7, |api, m| {
|
||||
api.create_account_path(m, "account_1")?;
|
||||
api.set_active_account(m, "account_1")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet7", base_amount * 1)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet7", base_amount * 2)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet7", base_amount * 3)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet7",
|
||||
base_amount * 1
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet7",
|
||||
base_amount * 2
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet7",
|
||||
base_amount * 3
|
||||
)?;
|
||||
bh += 3;
|
||||
|
||||
// check balances
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), miner_mask, cm, false);
|
||||
bh += cm as u64;
|
||||
|
||||
wallet::controller::owner_single_use(wallet7.clone(), |api| {
|
||||
let info = wallet_info!(wallet7.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
wallet::controller::owner_single_use(wallet7.clone(), mask7, |api, m| {
|
||||
let info = wallet_info!(wallet7.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 3);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 6);
|
||||
api.set_active_account("default")?;
|
||||
let info = wallet_info!(wallet7.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
api.set_active_account(m, "default")?;
|
||||
let info = wallet_info!(wallet7.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 3);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 42);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet8.clone(), |api| {
|
||||
api.restore()?;
|
||||
let info = wallet_info!(wallet8.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
wallet::controller::owner_single_use(wallet8.clone(), mask8, |api, m| {
|
||||
api.restore(m)?;
|
||||
let info = wallet_info!(wallet8.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 15);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 120);
|
||||
api.set_active_account("account_1")?;
|
||||
let info = wallet_info!(wallet8.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
api.set_active_account(m, "account_1")?;
|
||||
let info = wallet_info!(wallet8.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 3);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 6);
|
||||
Ok(())
|
||||
@@ -508,51 +675,69 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
// ids on account 2 as well, check_repair should get all outputs created
|
||||
// to now into 2 accounts
|
||||
|
||||
wallet::controller::owner_single_use(wallet9.clone(), |api| {
|
||||
api.create_account_path("account_1")?;
|
||||
api.set_active_account("account_1")?;
|
||||
wallet::controller::owner_single_use(wallet9.clone(), mask9, |api, m| {
|
||||
api.create_account_path(m, "account_1")?;
|
||||
api.set_active_account(m, "account_1")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet9", base_amount * 4)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet9", base_amount * 5)?;
|
||||
send_to_dest!(miner.clone(), m_client.clone(), "wallet9", base_amount * 6)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet9",
|
||||
base_amount * 4
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet9",
|
||||
base_amount * 5
|
||||
)?;
|
||||
send_to_dest!(
|
||||
miner.clone(),
|
||||
miner_mask,
|
||||
m_client.clone(),
|
||||
"wallet9",
|
||||
base_amount * 6
|
||||
)?;
|
||||
bh += 3;
|
||||
let _bh = bh;
|
||||
|
||||
wallet::controller::owner_single_use(wallet9.clone(), |api| {
|
||||
let info = wallet_info!(wallet9.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
wallet::controller::owner_single_use(wallet9.clone(), mask9, |api, m| {
|
||||
let info = wallet_info!(wallet9.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 3);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 15);
|
||||
api.check_repair(true)?;
|
||||
let info = wallet_info!(wallet9.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
api.check_repair(m, true)?;
|
||||
let info = wallet_info!(wallet9.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 6);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 21);
|
||||
|
||||
api.set_active_account("default")?;
|
||||
let info = wallet_info!(wallet9.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
api.set_active_account(m, "default")?;
|
||||
let info = wallet_info!(wallet9.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 15);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 120);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), cm, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), miner_mask, cm, false);
|
||||
|
||||
// 7) Ensure check_repair creates missing accounts
|
||||
wallet::controller::owner_single_use(wallet10.clone(), |api| {
|
||||
api.check_repair(true)?;
|
||||
api.set_active_account("account_1")?;
|
||||
let info = wallet_info!(wallet10.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
wallet::controller::owner_single_use(wallet10.clone(), mask10, |api, m| {
|
||||
api.check_repair(m, true)?;
|
||||
api.set_active_account(m, "account_1")?;
|
||||
let info = wallet_info!(wallet10.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 6);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 21);
|
||||
|
||||
api.set_active_account("default")?;
|
||||
let info = wallet_info!(wallet10.clone())?;
|
||||
let outputs = api.retrieve_outputs(true, false, None)?.1;
|
||||
api.set_active_account(m, "default")?;
|
||||
let info = wallet_info!(wallet10.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 15);
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 120);
|
||||
Ok(())
|
||||
|
||||
@@ -28,6 +28,7 @@ use impls::test_framework::{LocalWalletClient, WalletProxy};
|
||||
use impls::{DefaultLCProvider, DefaultWalletImpl};
|
||||
use std::fs;
|
||||
use std::sync::Arc;
|
||||
use util::secp::key::SecretKey;
|
||||
use util::{Mutex, ZeroingString};
|
||||
|
||||
#[macro_export]
|
||||
@@ -41,20 +42,36 @@ macro_rules! wallet_inst {
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! create_wallet_and_add {
|
||||
($client:ident, $wallet: ident, $test_dir: expr, $name: expr, $seed_phrase: expr, $proxy: expr) => {
|
||||
($client:ident, $wallet: ident, $mask: ident, $test_dir: expr, $name: expr, $seed_phrase: expr, $proxy: expr, $create_mask: expr) => {
|
||||
let $client = LocalWalletClient::new($name, $proxy.tx.clone());
|
||||
let $wallet =
|
||||
common::create_local_wallet($test_dir, $name, $seed_phrase.clone(), $client.clone());
|
||||
$proxy.add_wallet($name, $client.get_send_instance(), $wallet.clone());
|
||||
let ($wallet, $mask) = common::create_local_wallet(
|
||||
$test_dir,
|
||||
$name,
|
||||
$seed_phrase.clone(),
|
||||
$client.clone(),
|
||||
$create_mask,
|
||||
);
|
||||
$proxy.add_wallet(
|
||||
$name,
|
||||
$client.get_send_instance(),
|
||||
$wallet.clone(),
|
||||
$mask.clone(),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! open_wallet_and_add {
|
||||
($client:ident, $wallet: ident, $test_dir: expr, $name: expr, $proxy: expr) => {
|
||||
($client:ident, $wallet: ident, $mask: ident, $test_dir: expr, $name: expr, $proxy: expr, $create_mask: expr) => {
|
||||
let $client = LocalWalletClient::new($name, $proxy.tx.clone());
|
||||
let $wallet = common::open_local_wallet($test_dir, $name, $client.clone());
|
||||
$proxy.add_wallet($name, $client.get_send_instance(), $wallet.clone());
|
||||
let ($wallet, $mask) =
|
||||
common::open_local_wallet($test_dir, $name, $client.clone(), $create_mask);
|
||||
$proxy.add_wallet(
|
||||
$name,
|
||||
$client.get_send_instance(),
|
||||
$wallet.clone(),
|
||||
$mask.clone(),
|
||||
);
|
||||
};
|
||||
}
|
||||
pub fn clean_output_dir(test_dir: &str) {
|
||||
@@ -79,18 +96,22 @@ pub fn create_local_wallet(
|
||||
name: &str,
|
||||
mnemonic: Option<ZeroingString>,
|
||||
client: LocalWalletClient,
|
||||
) -> Arc<
|
||||
Mutex<
|
||||
Box<
|
||||
WalletInst<
|
||||
'static,
|
||||
DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>,
|
||||
LocalWalletClient,
|
||||
ExtKeychain,
|
||||
create_mask: bool,
|
||||
) -> (
|
||||
Arc<
|
||||
Mutex<
|
||||
Box<
|
||||
WalletInst<
|
||||
'static,
|
||||
DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>,
|
||||
LocalWalletClient,
|
||||
ExtKeychain,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
Option<SecretKey>,
|
||||
) {
|
||||
let mut wallet = Box::new(DefaultWalletImpl::<LocalWalletClient>::new(client).unwrap())
|
||||
as Box<
|
||||
WalletInst<
|
||||
@@ -103,26 +124,32 @@ pub fn create_local_wallet(
|
||||
lc.set_wallet_directory(&format!("{}/{}", test_dir, name));
|
||||
lc.create_wallet(None, mnemonic, 32, ZeroingString::from(""))
|
||||
.unwrap();
|
||||
lc.open_wallet(None, ZeroingString::from("")).unwrap();
|
||||
Arc::new(Mutex::new(wallet))
|
||||
let mask = lc
|
||||
.open_wallet(None, ZeroingString::from(""), create_mask, false)
|
||||
.unwrap();
|
||||
(Arc::new(Mutex::new(wallet)), mask)
|
||||
}
|
||||
|
||||
pub fn open_local_wallet(
|
||||
test_dir: &str,
|
||||
name: &str,
|
||||
client: LocalWalletClient,
|
||||
) -> Arc<
|
||||
Mutex<
|
||||
Box<
|
||||
WalletInst<
|
||||
'static,
|
||||
DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>,
|
||||
LocalWalletClient,
|
||||
ExtKeychain,
|
||||
create_mask: bool,
|
||||
) -> (
|
||||
Arc<
|
||||
Mutex<
|
||||
Box<
|
||||
WalletInst<
|
||||
'static,
|
||||
DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>,
|
||||
LocalWalletClient,
|
||||
ExtKeychain,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
Option<SecretKey>,
|
||||
) {
|
||||
let mut wallet = Box::new(DefaultWalletImpl::<LocalWalletClient>::new(client).unwrap())
|
||||
as Box<
|
||||
WalletInst<
|
||||
@@ -133,6 +160,8 @@ pub fn open_local_wallet(
|
||||
>;
|
||||
let lc = wallet.lc_provider().unwrap();
|
||||
lc.set_wallet_directory(&format!("{}/{}", test_dir, name));
|
||||
lc.open_wallet(None, ZeroingString::from("")).unwrap();
|
||||
Arc::new(Mutex::new(wallet))
|
||||
let mask = lc
|
||||
.open_wallet(None, ZeroingString::from(""), create_mask, false)
|
||||
.unwrap();
|
||||
(Arc::new(Mutex::new(wallet)), mask)
|
||||
}
|
||||
|
||||
+37
-30
@@ -46,19 +46,25 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
create_wallet_and_add!(
|
||||
client1,
|
||||
wallet1,
|
||||
mask1_i,
|
||||
test_dir,
|
||||
"wallet1",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
mask2_i,
|
||||
test_dir,
|
||||
"wallet2",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -71,16 +77,16 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
let reward = core::consensus::REWARD;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
api.create_account_path("mining")?;
|
||||
api.create_account_path("listener")?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.create_account_path(m, "mining")?;
|
||||
api.create_account_path(m, "listener")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
api.create_account_path("account1")?;
|
||||
api.create_account_path("account2")?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
api.create_account_path(m, "account1")?;
|
||||
api.create_account_path(m, "account2")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -90,7 +96,8 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
w.set_parent_key_id_by_name("mining")?;
|
||||
}
|
||||
let mut bh = 10u64;
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize, false);
|
||||
let _ =
|
||||
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
|
||||
|
||||
let send_file = format!("{}/part_tx_1.tx", test_dir);
|
||||
let receive_file = format!("{}/part_tx_2.tx", test_dir);
|
||||
@@ -99,8 +106,8 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
let message = "sender test message, sender test message";
|
||||
|
||||
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, bh * reward);
|
||||
@@ -115,10 +122,10 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
message: Some(message.to_owned()),
|
||||
..Default::default()
|
||||
};
|
||||
let mut slate = api.init_send_tx(args)?;
|
||||
let mut slate = api.init_send_tx(m, args)?;
|
||||
// output tx file
|
||||
PathToSlate((&send_file).into()).put_tx(&mut slate)?;
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -133,37 +140,37 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
naughty_slate.participant_data[0].message = Some("I changed the message".to_owned());
|
||||
|
||||
// verify messages on slate match
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
api.verify_slate_messages(&slate)?;
|
||||
assert!(api.verify_slate_messages(&naughty_slate).is_err());
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.verify_slate_messages(m, &slate)?;
|
||||
assert!(api.verify_slate_messages(m, &naughty_slate).is_err());
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let sender2_message = "And this is sender 2's message".to_owned();
|
||||
|
||||
// wallet 2 receives file, completes, sends file back
|
||||
wallet::controller::foreign_single_use(wallet2.clone(), |api| {
|
||||
wallet::controller::foreign_single_use(wallet2.clone(), mask2_i.clone(), |api| {
|
||||
slate = api.receive_tx(&slate, None, Some(sender2_message.clone()))?;
|
||||
PathToSlate((&receive_file).into()).put_tx(&slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// wallet 1 finalises and posts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let mut slate = PathToSlate(receive_file.into()).get_tx()?;
|
||||
api.verify_slate_messages(&slate)?;
|
||||
slate = api.finalize_tx(&slate)?;
|
||||
api.post_tx(&slate.tx, false)?;
|
||||
api.verify_slate_messages(m, &slate)?;
|
||||
slate = api.finalize_tx(m, &slate)?;
|
||||
api.post_tx(m, &slate.tx, false)?;
|
||||
bh += 1;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
bh += 3;
|
||||
|
||||
// Check total in mining account
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, bh * reward - reward * 2);
|
||||
@@ -171,8 +178,8 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
})?;
|
||||
|
||||
// Check total in 'wallet 2' account
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet2_info.total, 2 * reward);
|
||||
@@ -180,8 +187,8 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
})?;
|
||||
|
||||
// Check messages, all participants should have both
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (_, tx) = api.retrieve_txs(true, None, Some(slate.id))?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (_, tx) = api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
assert_eq!(
|
||||
tx[0].clone().messages.unwrap().messages[0].message,
|
||||
Some(message.to_owned())
|
||||
@@ -196,8 +203,8 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let (_, tx) = api.retrieve_txs(true, None, Some(slate.id))?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let (_, tx) = api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
assert_eq!(
|
||||
tx[0].clone().messages.unwrap().messages[0].message,
|
||||
Some(message.to_owned())
|
||||
|
||||
+41
-29
@@ -41,19 +41,25 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
create_wallet_and_add!(
|
||||
client1,
|
||||
wallet1,
|
||||
mask1_i,
|
||||
test_dir,
|
||||
"wallet1",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
true
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
mask2_i,
|
||||
test_dir,
|
||||
"wallet2",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
true
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -66,9 +72,9 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let reward = core::consensus::REWARD;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
api.create_account_path("mining")?;
|
||||
api.create_account_path("listener")?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.create_account_path(m, "mining")?;
|
||||
api.create_account_path(m, "listener")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -78,11 +84,17 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
w.set_parent_key_id_by_name("mining")?;
|
||||
}
|
||||
let mut bh = 10u64;
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(
|
||||
&chain,
|
||||
wallet1.clone(),
|
||||
mask1,
|
||||
bh as usize,
|
||||
false,
|
||||
);
|
||||
|
||||
// Sanity check wallet 1 contents
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, bh * reward);
|
||||
@@ -91,17 +103,17 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
|
||||
let mut slate = Slate::blank(2);
|
||||
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
// Wallet 2 inititates an invoice transaction, requesting payment
|
||||
let args = IssueInvoiceTxArgs {
|
||||
amount: reward * 2,
|
||||
..Default::default()
|
||||
};
|
||||
slate = api.issue_invoice_tx(args)?;
|
||||
slate = api.issue_invoice_tx(m, args)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
// Wallet 1 receives the invoice transaction
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -112,32 +124,32 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
slate = api.process_invoice_tx(&slate, args)?;
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
slate = api.process_invoice_tx(m, &slate, args)?;
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// wallet 2 finalizes and posts
|
||||
wallet::controller::foreign_single_use(wallet2.clone(), |api| {
|
||||
wallet::controller::foreign_single_use(wallet2.clone(), mask2_i.clone(), |api| {
|
||||
// Wallet 2 receives the invoice transaction
|
||||
slate = api.finalize_invoice_tx(&slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// wallet 1 posts so wallet 2 doesn't get the mined amount
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
api.post_tx(&slate.tx, false)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.post_tx(m, &slate.tx, false)?;
|
||||
Ok(())
|
||||
})?;
|
||||
bh += 1;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
bh += 3;
|
||||
|
||||
// Check transaction log for wallet 2
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let (_, wallet2_info) = api.retrieve_summary_info(true, 1)?;
|
||||
let (refreshed, txs) = api.retrieve_txs(true, None, None)?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let (_, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
assert!(txs.len() == 1);
|
||||
println!(
|
||||
@@ -151,9 +163,9 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
|
||||
// Check transaction log for wallet 1, ensure only 1 entry
|
||||
// exists
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
let (refreshed, txs) = api.retrieve_txs(true, None, None)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
assert_eq!(txs.len() as u64, bh + 1);
|
||||
println!(
|
||||
@@ -164,13 +176,13 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// Test self-sending
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
// Wallet 1 inititates an invoice transaction, requesting payment
|
||||
let args = IssueInvoiceTxArgs {
|
||||
amount: reward * 2,
|
||||
..Default::default()
|
||||
};
|
||||
slate = api.issue_invoice_tx(args)?;
|
||||
slate = api.issue_invoice_tx(m, args)?;
|
||||
// Wallet 1 receives the invoice transaction
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -181,19 +193,19 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
slate = api.process_invoice_tx(&slate, args)?;
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
slate = api.process_invoice_tx(m, &slate, args)?;
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// wallet 1 finalizes and posts
|
||||
wallet::controller::foreign_single_use(wallet1.clone(), |api| {
|
||||
wallet::controller::foreign_single_use(wallet1.clone(), mask1_i.clone(), |api| {
|
||||
// Wallet 2 receives the invoice transaction
|
||||
slate = api.finalize_invoice_tx(&slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
//bh += 3;
|
||||
|
||||
// let logging finish
|
||||
|
||||
+47
-40
@@ -43,19 +43,25 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
create_wallet_and_add!(
|
||||
client1,
|
||||
wallet1,
|
||||
mask1_i,
|
||||
test_dir,
|
||||
"wallet1",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
mask2_i,
|
||||
test_dir,
|
||||
"wallet2",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -68,16 +74,16 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
let reward = core::consensus::REWARD;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
api.create_account_path("mining")?;
|
||||
api.create_account_path("listener")?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.create_account_path(m, "mining")?;
|
||||
api.create_account_path(m, "listener")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
api.create_account_path("account1")?;
|
||||
api.create_account_path("account2")?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
api.create_account_path(m, "account1")?;
|
||||
api.create_account_path(m, "account2")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -87,7 +93,8 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
w.set_parent_key_id_by_name("mining")?;
|
||||
}
|
||||
let mut bh = 10u64;
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize, false);
|
||||
let _ =
|
||||
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
|
||||
|
||||
let send_file = format!("{}/part_tx_1.tx", test_dir);
|
||||
let receive_file = format!("{}/part_tx_2.tx", test_dir);
|
||||
@@ -95,8 +102,8 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
let mut slate = Slate::blank(2);
|
||||
|
||||
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, bh * reward);
|
||||
@@ -110,13 +117,13 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate = api.init_send_tx(args)?;
|
||||
let slate = api.init_send_tx(m, args)?;
|
||||
PathToSlate((&send_file).into()).put_tx(&slate)?;
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
bh += 3;
|
||||
|
||||
// wallet 1 receives file to different account, completes
|
||||
@@ -125,7 +132,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
w.set_parent_key_id_by_name("listener")?;
|
||||
}
|
||||
|
||||
wallet::controller::foreign_single_use(wallet1.clone(), |api| {
|
||||
wallet::controller::foreign_single_use(wallet1.clone(), mask1_i.clone(), |api| {
|
||||
slate = PathToSlate((&send_file).into()).get_tx()?;
|
||||
slate = api.receive_tx(&slate, None, None)?;
|
||||
PathToSlate((&receive_file).into()).put_tx(&slate)?;
|
||||
@@ -139,27 +146,27 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
}
|
||||
|
||||
// wallet 1 finalize
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
slate = PathToSlate((&receive_file).into()).get_tx()?;
|
||||
slate = api.finalize_tx(&slate)?;
|
||||
slate = api.finalize_tx(m, &slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// Now repost from cached
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (_, txs) = api.retrieve_txs(true, None, Some(slate.id))?;
|
||||
let stored_tx = api.get_stored_tx(&txs[0])?;
|
||||
api.post_tx(&stored_tx.unwrap(), false)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
let stored_tx = api.get_stored_tx(m, &txs[0])?;
|
||||
api.post_tx(m, &stored_tx.unwrap(), false)?;
|
||||
bh += 1;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
bh += 3;
|
||||
|
||||
// update/test contents of both accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, bh * reward - reward * 2);
|
||||
@@ -171,8 +178,8 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
w.set_parent_key_id_by_name("listener")?;
|
||||
}
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet2_info.total, 2 * reward);
|
||||
@@ -192,7 +199,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
let mut slate = Slate::blank(2);
|
||||
let amount = 60_000_000_000;
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -203,39 +210,39 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.init_send_tx(args)?;
|
||||
let slate_i = sender_api.init_send_tx(m, args)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, 0)?;
|
||||
slate = sender_api.finalize_tx(&mut slate)?;
|
||||
sender_api.tx_lock_outputs(m, &slate, 0)?;
|
||||
slate = sender_api.finalize_tx(m, &mut slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
bh += 3;
|
||||
|
||||
// Now repost from cached
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (_, txs) = api.retrieve_txs(true, None, Some(slate.id))?;
|
||||
let stored_tx = api.get_stored_tx(&txs[0])?;
|
||||
api.post_tx(&stored_tx.unwrap(), false)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
let stored_tx = api.get_stored_tx(m, &txs[0])?;
|
||||
api.post_tx(m, &stored_tx.unwrap(), false)?;
|
||||
bh += 1;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
bh += 3;
|
||||
//
|
||||
// update/test contents of both accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, bh * reward - reward * 4);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet2_info.total, 2 * amount);
|
||||
|
||||
+72
-52
@@ -41,10 +41,12 @@ fn restore_wallet(base_dir: &'static str, wallet_dir: &str) -> Result<(), libwal
|
||||
create_wallet_and_add!(
|
||||
client,
|
||||
wallet,
|
||||
mask,
|
||||
base_dir,
|
||||
&dest_wallet_name,
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
// close created wallet
|
||||
let mut w_lock = wallet.lock();
|
||||
@@ -59,10 +61,13 @@ fn restore_wallet(base_dir: &'static str, wallet_dir: &str) -> Result<(), libwal
|
||||
open_wallet_and_add!(
|
||||
client,
|
||||
wallet,
|
||||
mask_i,
|
||||
&base_dir,
|
||||
&dest_wallet_name,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask = (&mask_i).as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
let wp_running = wallet_proxy.running.clone();
|
||||
@@ -73,9 +78,9 @@ fn restore_wallet(base_dir: &'static str, wallet_dir: &str) -> Result<(), libwal
|
||||
});
|
||||
|
||||
// perform the restore and update wallet info
|
||||
wallet::controller::owner_single_use(wallet.clone(), |api| {
|
||||
let _ = api.restore()?;
|
||||
let _ = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet.clone(), mask, |api, m| {
|
||||
let _ = api.restore(m)?;
|
||||
let _ = api.retrieve_summary_info(m, true, 1)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -96,17 +101,23 @@ fn compare_wallet_restore(
|
||||
open_wallet_and_add!(
|
||||
client,
|
||||
wallet_source,
|
||||
source_mask_i,
|
||||
&base_dir,
|
||||
&wallet_dir,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let source_mask = (&source_mask_i).as_ref();
|
||||
open_wallet_and_add!(
|
||||
client,
|
||||
wallet_dest,
|
||||
dest_mask_i,
|
||||
&base_dir,
|
||||
&restore_name,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let dest_mask = (&dest_mask_i).as_ref();
|
||||
|
||||
{
|
||||
wallet_inst!(wallet_source, w);
|
||||
@@ -136,17 +147,17 @@ fn compare_wallet_restore(
|
||||
let mut dest_accts: Option<Vec<AcctPathMapping>> = None;
|
||||
|
||||
// Overall wallet info should be the same
|
||||
wallet::controller::owner_single_use(wallet_source.clone(), |api| {
|
||||
src_info = Some(api.retrieve_summary_info(true, 1)?.1);
|
||||
src_txs = Some(api.retrieve_txs(true, None, None)?.1);
|
||||
src_accts = Some(api.accounts()?);
|
||||
wallet::controller::owner_single_use(wallet_source.clone(), source_mask, |api, m| {
|
||||
src_info = Some(api.retrieve_summary_info(m, true, 1)?.1);
|
||||
src_txs = Some(api.retrieve_txs(m, true, None, None)?.1);
|
||||
src_accts = Some(api.accounts(m)?);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet_dest.clone(), |api| {
|
||||
dest_info = Some(api.retrieve_summary_info(true, 1)?.1);
|
||||
dest_txs = Some(api.retrieve_txs(true, None, None)?.1);
|
||||
dest_accts = Some(api.accounts()?);
|
||||
wallet::controller::owner_single_use(wallet_dest.clone(), dest_mask, |api, m| {
|
||||
dest_info = Some(api.retrieve_summary_info(m, true, 1)?.1);
|
||||
dest_txs = Some(api.retrieve_txs(m, true, None, None)?.1);
|
||||
dest_accts = Some(api.accounts(m)?);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -194,24 +205,30 @@ fn setup_restore(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
create_wallet_and_add!(
|
||||
client1,
|
||||
wallet1,
|
||||
mask1_i,
|
||||
test_dir,
|
||||
"wallet1",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
mask2_i,
|
||||
test_dir,
|
||||
"wallet2",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
|
||||
// wallet 2 will use another account
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
api.create_account_path("account1")?;
|
||||
api.create_account_path("account2")?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
api.create_account_path(m, "account1")?;
|
||||
api.create_account_path(m, "account2")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -225,11 +242,14 @@ fn setup_restore(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
create_wallet_and_add!(
|
||||
client3,
|
||||
wallet3,
|
||||
mask3_i,
|
||||
test_dir,
|
||||
"wallet3",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask3 = (&mask3_i).as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
let wp_running = wallet_proxy.running.clone();
|
||||
@@ -240,13 +260,13 @@ fn setup_restore(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
});
|
||||
|
||||
// mine a few blocks
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 10, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 10, false);
|
||||
|
||||
// assert wallet contents
|
||||
// and a single use api for a send command
|
||||
let amount = 60_000_000_000;
|
||||
let mut slate = Slate::blank(1);
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -257,19 +277,19 @@ fn setup_restore(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.init_send_tx(args)?;
|
||||
let slate_i = sender_api.init_send_tx(m, args)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, 0)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
sender_api.post_tx(&slate.tx, false)?;
|
||||
sender_api.tx_lock_outputs(m, &slate, 0)?;
|
||||
slate = sender_api.finalize_tx(m, &slate)?;
|
||||
sender_api.post_tx(m, &slate.tx, false)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// mine a few more blocks
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
|
||||
// Send some to wallet 3
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -280,19 +300,19 @@ fn setup_restore(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.init_send_tx(args)?;
|
||||
let slate_i = sender_api.init_send_tx(m, args)?;
|
||||
slate = client1.send_tx_slate_direct("wallet3", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, 0)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
sender_api.post_tx(&slate.tx, false)?;
|
||||
sender_api.tx_lock_outputs(m, &slate, 0)?;
|
||||
slate = sender_api.finalize_tx(m, &slate)?;
|
||||
sender_api.post_tx(m, &slate.tx, false)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// mine a few more blocks
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet3.clone(), 10, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet3.clone(), mask3, 10, false);
|
||||
|
||||
// Wallet3 to wallet 2
|
||||
wallet::controller::owner_single_use(wallet3.clone(), |sender_api| {
|
||||
wallet::controller::owner_single_use(wallet3.clone(), mask3, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -303,11 +323,11 @@ fn setup_restore(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.init_send_tx(args)?;
|
||||
let slate_i = sender_api.init_send_tx(m, args)?;
|
||||
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, 0)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
sender_api.post_tx(&slate.tx, false)?;
|
||||
sender_api.tx_lock_outputs(m, &slate, 0)?;
|
||||
slate = sender_api.finalize_tx(m, &slate)?;
|
||||
sender_api.post_tx(m, &slate.tx, false)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -318,10 +338,10 @@ fn setup_restore(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
}
|
||||
|
||||
// mine a few more blocks
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 2, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 2, false);
|
||||
|
||||
// Wallet3 to wallet 2 again (to another account)
|
||||
wallet::controller::owner_single_use(wallet3.clone(), |sender_api| {
|
||||
wallet::controller::owner_single_use(wallet3.clone(), mask3, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -332,28 +352,28 @@ fn setup_restore(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.init_send_tx(args)?;
|
||||
let slate_i = sender_api.init_send_tx(m, args)?;
|
||||
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, 0)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
sender_api.post_tx(&slate.tx, false)?;
|
||||
sender_api.tx_lock_outputs(m, &slate, 0)?;
|
||||
slate = sender_api.finalize_tx(m, &slate)?;
|
||||
sender_api.post_tx(m, &slate.tx, false)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// mine a few more blocks
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 5, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 5, false);
|
||||
|
||||
// update everyone
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let _ = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let _ = api.retrieve_summary_info(m, true, 1)?;
|
||||
Ok(())
|
||||
})?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let _ = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let _ = api.retrieve_summary_info(m, true, 1)?;
|
||||
Ok(())
|
||||
})?;
|
||||
wallet::controller::owner_single_use(wallet3.clone(), |api| {
|
||||
let _ = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet3.clone(), mask3, |api, m| {
|
||||
let _ = api.retrieve_summary_info(m, true, 1)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
|
||||
@@ -41,11 +41,14 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
create_wallet_and_add!(
|
||||
client1,
|
||||
wallet1,
|
||||
mask1_i,
|
||||
test_dir,
|
||||
"wallet1",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
true
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -58,9 +61,9 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let reward = core::consensus::REWARD;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
api.create_account_path("mining")?;
|
||||
api.create_account_path("listener")?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.create_account_path(m, "mining")?;
|
||||
api.create_account_path(m, "listener")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -70,11 +73,12 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
w.set_parent_key_id_by_name("mining")?;
|
||||
}
|
||||
let mut bh = 10u64;
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize, false);
|
||||
let _ =
|
||||
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
|
||||
|
||||
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, bh * reward);
|
||||
@@ -88,25 +92,25 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let mut slate = api.init_send_tx(args)?;
|
||||
api.tx_lock_outputs(&slate, 0)?;
|
||||
let mut slate = api.init_send_tx(m, args)?;
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
// Send directly to self
|
||||
wallet::controller::foreign_single_use(wallet1.clone(), |api| {
|
||||
wallet::controller::foreign_single_use(wallet1.clone(), mask1_i.clone(), |api| {
|
||||
slate = api.receive_tx(&slate, Some("listener"), None)?;
|
||||
Ok(())
|
||||
})?;
|
||||
slate = api.finalize_tx(&slate)?;
|
||||
api.post_tx(&slate.tx, false)?; // mines a block
|
||||
slate = api.finalize_tx(m, &slate)?;
|
||||
api.post_tx(m, &slate.tx, false)?; // mines a block
|
||||
bh += 1;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
bh += 3;
|
||||
|
||||
// Check total in mining account
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, bh * reward - reward * 2);
|
||||
@@ -118,8 +122,8 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
wallet_inst!(wallet1, w);
|
||||
w.set_parent_key_id_by_name("listener")?;
|
||||
}
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, 2 * reward);
|
||||
|
||||
@@ -42,19 +42,27 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
create_wallet_and_add!(
|
||||
client1,
|
||||
wallet1,
|
||||
mask1_i,
|
||||
test_dir,
|
||||
"wallet1",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
true
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
println!("Mask1: {:?}", mask1);
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
mask2_i,
|
||||
test_dir,
|
||||
"wallet2",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
println!("Mask2: {:?}", mask2);
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -67,11 +75,11 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
let reward = core::consensus::REWARD;
|
||||
let cm = global::coinbase_maturity();
|
||||
// mine a few blocks
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 10, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 10, false);
|
||||
|
||||
// Check wallet 1 contents are as expected
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
debug!(
|
||||
"Wallet 1 Info Pre-Transaction, after {} blocks: {:?}",
|
||||
wallet1_info.last_confirmed_height, wallet1_info
|
||||
@@ -89,7 +97,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
// and a single use api for a send command
|
||||
let amount = 60_000_000_000;
|
||||
let mut slate = Slate::blank(1);
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -100,15 +108,15 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.init_send_tx(args)?;
|
||||
let slate_i = sender_api.init_send_tx(m, args)?;
|
||||
|
||||
// Check we are creating a tx with the expected lock_height of 0.
|
||||
// We will check this produces a Plain kernel later.
|
||||
assert_eq!(0, slate.lock_height);
|
||||
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, 0)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
sender_api.tx_lock_outputs(m, &slate, 0)?;
|
||||
slate = sender_api.finalize_tx(m, &slate)?;
|
||||
|
||||
// Check we have a single kernel and that it is a Plain kernel (no lock_height).
|
||||
assert_eq!(slate.tx.kernels().len(), 1);
|
||||
@@ -125,9 +133,9 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
})?;
|
||||
|
||||
// Check transaction log for wallet 1
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
let (refreshed, txs) = api.retrieve_txs(true, None, None)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
let fee = core::libtx::tx_fee(
|
||||
wallet1_info.last_confirmed_height as usize - cm as usize,
|
||||
@@ -148,8 +156,8 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
})?;
|
||||
|
||||
// Check transaction log for wallet 2
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let (refreshed, txs) = api.retrieve_txs(true, None, None)?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
// we should have a transaction entry for this slate
|
||||
let tx = txs.iter().find(|t| t.tx_slate_id == Some(slate.id));
|
||||
@@ -164,14 +172,14 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
})?;
|
||||
|
||||
// post transaction
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
api.post_tx(&slate.tx, false)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.post_tx(m, &slate.tx, false)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// Check wallet 1 contents are as expected
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
debug!(
|
||||
"Wallet 1 Info Post Transaction, after {} blocks: {:?}",
|
||||
wallet1_info.last_confirmed_height, wallet1_info
|
||||
@@ -195,7 +203,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
assert_eq!(wallet1_info.amount_immature, cm * reward + fee);
|
||||
|
||||
// check tx log entry is confirmed
|
||||
let (refreshed, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
let tx = txs.iter().find(|t| t.tx_slate_id == Some(slate.id));
|
||||
assert!(tx.is_some());
|
||||
@@ -207,11 +215,11 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
})?;
|
||||
|
||||
// mine a few more blocks
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
|
||||
// refresh wallets and retrieve info/tests for each wallet after maturity
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
debug!("Wallet 1 Info: {:?}", wallet1_info);
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(
|
||||
@@ -225,13 +233,13 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.amount_currently_spendable, amount);
|
||||
|
||||
// check tx log entry is confirmed
|
||||
let (refreshed, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
let tx = txs.iter().find(|t| t.tx_slate_id == Some(slate.id));
|
||||
assert!(tx.is_some());
|
||||
@@ -242,7 +250,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
})?;
|
||||
|
||||
// Estimate fee and locked amount for a transaction
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
let init_args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: amount * 2,
|
||||
@@ -253,7 +261,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
estimate_only: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let est = sender_api.init_send_tx(init_args)?;
|
||||
let est = sender_api.init_send_tx(m, init_args)?;
|
||||
assert_eq!(est.amount, 600_000_000_000);
|
||||
assert_eq!(est.fee, 4_000_000);
|
||||
|
||||
@@ -267,7 +275,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
estimate_only: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let est = sender_api.init_send_tx(init_args)?;
|
||||
let est = sender_api.init_send_tx(m, init_args)?;
|
||||
assert_eq!(est.amount, 180_000_000_000);
|
||||
assert_eq!(est.fee, 6_000_000);
|
||||
|
||||
@@ -276,7 +284,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
|
||||
// Send another transaction, but don't post to chain immediately and use
|
||||
// the stored transaction instead
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -287,25 +295,25 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.init_send_tx(args)?;
|
||||
let slate_i = sender_api.init_send_tx(m, args)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, 0)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
sender_api.tx_lock_outputs(m, &slate, 0)?;
|
||||
slate = sender_api.finalize_tx(m, &slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
let (refreshed, _wallet1_info) = sender_api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
let (refreshed, _wallet1_info) = sender_api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(refreshed);
|
||||
let (_, txs) = sender_api.retrieve_txs(true, None, None)?;
|
||||
let (_, txs) = sender_api.retrieve_txs(m, true, None, None)?;
|
||||
// find the transaction
|
||||
let tx = txs
|
||||
.iter()
|
||||
.find(|t| t.tx_slate_id == Some(slate.id))
|
||||
.unwrap();
|
||||
let stored_tx = sender_api.get_stored_tx(&tx)?;
|
||||
sender_api.post_tx(&stored_tx.unwrap(), false)?;
|
||||
let (_, wallet1_info) = sender_api.retrieve_summary_info(true, 1)?;
|
||||
let stored_tx = sender_api.get_stored_tx(m, &tx)?;
|
||||
sender_api.post_tx(m, &stored_tx.unwrap(), false)?;
|
||||
let (_, wallet1_info) = sender_api.retrieve_summary_info(m, true, 1)?;
|
||||
// should be mined now
|
||||
assert_eq!(
|
||||
wallet1_info.total,
|
||||
@@ -315,16 +323,16 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
})?;
|
||||
|
||||
// mine a few more blocks
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 3, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
|
||||
// check wallet2 has stored transaction
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.amount_currently_spendable, amount * 3);
|
||||
|
||||
// check tx log entry is confirmed
|
||||
let (refreshed, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
let tx = txs.iter().find(|t| t.tx_slate_id == Some(slate.id));
|
||||
assert!(tx.is_some());
|
||||
@@ -350,19 +358,25 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
create_wallet_and_add!(
|
||||
client1,
|
||||
wallet1,
|
||||
mask1_i,
|
||||
test_dir,
|
||||
"wallet1",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
create_wallet_and_add!(
|
||||
client2,
|
||||
wallet2,
|
||||
mask2_i,
|
||||
test_dir,
|
||||
"wallet2",
|
||||
None,
|
||||
&mut wallet_proxy
|
||||
&mut wallet_proxy,
|
||||
false
|
||||
);
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
|
||||
// Set the wallet proxy listener running
|
||||
thread::spawn(move || {
|
||||
@@ -375,11 +389,11 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let reward = core::consensus::REWARD;
|
||||
let cm = global::coinbase_maturity(); // assume all testing precedes soft fork height
|
||||
// mine a few blocks
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 5, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 5, false);
|
||||
|
||||
let amount = 30_000_000_000;
|
||||
let mut slate = Slate::blank(1);
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -391,29 +405,29 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let slate_i = sender_api.init_send_tx(args)?;
|
||||
let slate_i = sender_api.init_send_tx(m, args)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, 0)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
sender_api.tx_lock_outputs(m, &slate, 0)?;
|
||||
slate = sender_api.finalize_tx(m, &slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// Check transaction log for wallet 1
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let (refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
let (refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
println!(
|
||||
"last confirmed height: {}",
|
||||
wallet1_info.last_confirmed_height
|
||||
);
|
||||
assert!(refreshed);
|
||||
let (_, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
// we should have a transaction entry for this slate
|
||||
let tx = txs.iter().find(|t| t.tx_slate_id == Some(slate.id));
|
||||
assert!(tx.is_some());
|
||||
let mut locked_count = 0;
|
||||
let mut unconfirmed_count = 0;
|
||||
// get the tx entry, check outputs are as expected
|
||||
let (_, output_mappings) = api.retrieve_outputs(true, false, Some(tx.unwrap().id))?;
|
||||
let (_, output_mappings) = api.retrieve_outputs(m, true, false, Some(tx.unwrap().id))?;
|
||||
for m in output_mappings.clone() {
|
||||
if m.output.status == OutputStatus::Locked {
|
||||
locked_count = locked_count + 1;
|
||||
@@ -430,14 +444,14 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// Check transaction log for wallet 2
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let (refreshed, txs) = api.retrieve_txs(true, None, None)?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
let mut unconfirmed_count = 0;
|
||||
let tx = txs.iter().find(|t| t.tx_slate_id == Some(slate.id));
|
||||
assert!(tx.is_some());
|
||||
// get the tx entry, check outputs are as expected
|
||||
let (_, outputs) = api.retrieve_outputs(true, false, Some(tx.unwrap().id))?;
|
||||
let (_, outputs) = api.retrieve_outputs(m, true, false, Some(tx.unwrap().id))?;
|
||||
for m in outputs.clone() {
|
||||
if m.output.status == OutputStatus::Unconfirmed {
|
||||
unconfirmed_count = unconfirmed_count + 1;
|
||||
@@ -445,7 +459,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
}
|
||||
assert_eq!(outputs.len(), 1);
|
||||
assert_eq!(unconfirmed_count, 1);
|
||||
let (refreshed, wallet2_info) = api.retrieve_summary_info(true, 1)?;
|
||||
let (refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(refreshed);
|
||||
assert_eq!(wallet2_info.amount_currently_spendable, 0,);
|
||||
assert_eq!(wallet2_info.amount_awaiting_finalization, amount);
|
||||
@@ -454,20 +468,20 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
|
||||
// wallet 1 is bold and doesn't ever post the transaction
|
||||
// mine a few more blocks
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), 5, false);
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 5, false);
|
||||
|
||||
// Wallet 1 decides to roll back instead
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
// can't roll back coinbase
|
||||
let res = api.cancel_tx(Some(1), None);
|
||||
let res = api.cancel_tx(m, Some(1), None);
|
||||
assert!(res.is_err());
|
||||
let (_, txs) = api.retrieve_txs(true, None, None)?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
let tx = txs
|
||||
.iter()
|
||||
.find(|t| t.tx_slate_id == Some(slate.id))
|
||||
.unwrap();
|
||||
api.cancel_tx(Some(tx.id), None)?;
|
||||
let (refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||
api.cancel_tx(m, Some(tx.id), None)?;
|
||||
let (refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(refreshed);
|
||||
println!(
|
||||
"last confirmed height: {}",
|
||||
@@ -480,27 +494,27 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
(wallet1_info.last_confirmed_height - cm) * reward
|
||||
);
|
||||
// can't roll back again
|
||||
let res = api.cancel_tx(Some(tx.id), None);
|
||||
let res = api.cancel_tx(m, Some(tx.id), None);
|
||||
assert!(res.is_err());
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// Wallet 2 rolls back
|
||||
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||
let (_, txs) = api.retrieve_txs(true, None, None)?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
let tx = txs
|
||||
.iter()
|
||||
.find(|t| t.tx_slate_id == Some(slate.id))
|
||||
.unwrap();
|
||||
api.cancel_tx(Some(tx.id), None)?;
|
||||
let (refreshed, wallet2_info) = api.retrieve_summary_info(true, 1)?;
|
||||
api.cancel_tx(m, Some(tx.id), None)?;
|
||||
let (refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(refreshed);
|
||||
// check all eligible inputs should be now be spendable
|
||||
assert_eq!(wallet2_info.amount_currently_spendable, 0,);
|
||||
assert_eq!(wallet2_info.total, 0,);
|
||||
// can't roll back again
|
||||
let res = api.cancel_tx(Some(tx.id), None);
|
||||
let res = api.cancel_tx(m, Some(tx.id), None);
|
||||
assert!(res.is_err());
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user