Lock outputs before sending with Tor (#814)

Co-authored-by: wiesche <wiesche89@googlemail.com>
(cherry picked from commit 452a3ec51b)
This commit is contained in:
ardocrat
2026-10-11 00:45:56 +03:00
parent cec94917de
commit 2302135709
27 changed files with 2275 additions and 3452 deletions
+43 -30
View File
@@ -40,6 +40,7 @@ use grin_wallet_util::OnionV3Address;
use chrono::prelude::*;
use ed25519_dalek::SigningKey as DalekSecretKey;
use libwallet::wallet_lock;
use std::convert::TryFrom;
use std::fs::File;
use std::io::Write;
@@ -709,9 +710,9 @@ where
/// is confirmed. This method also returns a function that will perform that locking, and it is
/// up to the caller to decide the best time to call the lock function
/// (via the [`tx_lock_outputs`](struct.Owner.html#method.tx_lock_outputs) method).
/// If the exchange method is intended to be synchronous (such as via a direct http call,)
/// If the exchange method is intended to be synchronous (such as via a direct http call)
/// then the lock call can wait until the response is confirmed. If it is asynchronous, (such
/// as via file transfer,) the lock call should happen immediately (before the file is sent
/// as via file transfer) the lock call should happen immediately (before the file is sent
/// to the recipient).
///
/// If the `send_args` [`InitTxSendArgs`](../grin_wallet_libwallet/types/struct.InitTxSendArgs.html),
@@ -719,7 +720,7 @@ where
/// function will attempt to send the slate back to the sender using the slatepack sync
/// send (TOR). If providing this argument, check the `state` field of the slate to see if the
/// sync_send was successful (it should be S2 if the sync sent successfully). It will also post
/// the transction if the `post_tx` field is set.
/// the transaction if the `post_tx` field is set.
///
/// # Arguments
/// * `keychain_mask` - Wallet secret mask to XOR against the stored wallet seed before using, if
@@ -730,11 +731,15 @@ where
/// # Returns
/// * a result containing:
/// * The transaction [Slate](../grin_wallet_libwallet/slate/struct.Slate.html),
/// which can be forwarded to the recieving party by any means. Once the caller is relatively
/// certain that the transaction has been sent to the recipient, the associated wallet
/// transaction outputs should be locked via a call to
/// [`tx_lock_outputs`](struct.Owner.html#method.tx_lock_outputs). This must be called before calling
/// [`finalize_tx`](struct.Owner.html#method.finalize_tx).
/// which can be forwarded to the receiving party by any means. With normal locking, an
/// attempted Tor send already locks the outputs, even if sending fails. Do not call
/// [`tx_lock_outputs`](struct.Owner.html#method.tx_lock_outputs) again when forwarding manually.
/// If sending was not requested or was skipped, lock the outputs before forwarding the slate.
/// With late locking, outputs are locked during finalization instead.
/// If `skip_tor` is omitted, `skip_send_attempt` in the Tor config decides whether to send.
/// With normal locking, a returned S1 slate alone does not tell you whether outputs are locked.
/// Set `skip_tor` explicitly or check [`retrieve_txs`](struct.Owner.html#method.retrieve_txs)
/// for the slate ID before locking manually.
/// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered.
///
/// # Remarks
@@ -768,7 +773,7 @@ where
/// if let Ok(slate) = result {
/// // Send slate somehow
/// // ...
/// // Lock our outputs if we're happy the slate was (or is being) sent
/// // Lock outputs for manual sending without late locking
/// api_owner.tx_lock_outputs(None, &slate);
/// }
/// ```
@@ -785,32 +790,36 @@ where
}
_ => None,
};
let (slate, tor_config) = {
let mut w_lock = self.wallet_inst.lock();
let tor_config = send_args
.as_ref()
.map(|_| crate::tor_config::load(&self.config_path()))
.transpose()?;
let w = w_lock.lc_provider()?.wallet_inst()?;
let slate = owner::init_send_tx(w, keychain_mask, args, self.doctest_mode)?;
(slate, tor_config)
};
let tor_config = send_args
.as_ref()
.map(|_| crate::tor_config::load(&self.config_path()))
.transpose()?;
// Helper functionality. If send arguments exist, attempt to send sync and
// finalize
match send_args {
Some(sa) => {
let tc = tor_config.ok_or_else(|| {
Error::TorConfig("Tor config was not loaded with send arguments".into())
})?;
let can_send = tc.send_tor(sa.skip_tor);
if self.doctest_mode || !can_send || dest.is_none() {
return Ok(slate);
}
let slate = {
wallet_lock!(self.wallet_inst, w);
let late_lock = args.late_lock.unwrap_or(false);
let slate = owner::init_send_tx(w, keychain_mask, args, self.doctest_mode)?;
let tc = tor_config.as_ref().ok_or_else(|| {
Error::TorConfig("Tor config was not loaded with send arguments".into())
})?;
let can_send = tc.send_tor(sa.skip_tor);
if self.doctest_mode || !can_send || dest.is_none() {
return Ok(slate);
}
if !late_lock {
owner::tx_lock_outputs(w, keychain_mask, &slate)?;
}
slate
};
let res =
try_slatepack_sync_workflow(&slate, &dest.unwrap(), Some(tc), None, false);
try_slatepack_sync_workflow(&slate, &dest.unwrap(), tor_config, None, false);
match res {
Ok(s) => {
self.tx_lock_outputs(keychain_mask, &s)?;
let ret_slate = self.finalize_tx(keychain_mask, &s)?;
if sa.post_tx {
let result = self.post_tx(keychain_mask, &ret_slate, sa.fluff);
@@ -834,7 +843,11 @@ where
}
}
}
None => Ok(slate),
None => {
wallet_lock!(self.wallet_inst, w);
let slate = owner::init_send_tx(w, keychain_mask, args, self.doctest_mode)?;
Ok(slate)
}
}
}
@@ -2353,7 +2366,7 @@ where
///
/// * `keychain_mask` - Wallet secret mask to XOR against the stored wallet seed before using, if
/// * `slatepack` - A string representing an armored slatepack
/// * `secret_indices` - Indices along this wallet's deriviation path with which to attempt
/// * `secret_indices` - Indices along this wallet's derivation path with which to attempt
/// decryption. This function will attempt to use secret keys at each index along this path
/// to attempt to decrypt the payload, returning an error if none of the keys match.
///
+26 -8
View File
@@ -439,7 +439,6 @@ where
target_slate_version: args.target_slate_version,
payment_proof_recipient_address,
ttl_blocks: args.ttl_blocks,
send_args: None,
late_lock: Some(args.late_lock),
..Default::default()
};
@@ -494,14 +493,14 @@ where
tor_config.bridge.bridge_line = Some(b);
}
let output_sp = || -> Result<(), Error> {
let output_sp = |owner_api: &mut Owner<L, C, K>, lock_outputs: bool| -> Result<(), Error> {
Ok(output_slatepack(
owner_api,
keychain_mask,
&slate,
dest.clone(),
args.outfile,
true,
lock_outputs,
false,
args.slatepack_qr,
)?)
@@ -509,7 +508,11 @@ where
let can_send = tor_config.send_tor(args.skip_tor);
if test_mode || !can_send || dest.is_none() {
return output_sp();
return output_sp(owner_api, !args.late_lock);
}
if !args.late_lock {
owner_api.tx_lock_outputs(keychain_mask, &slate)?;
}
let dest = dest.as_ref().unwrap();
@@ -517,7 +520,6 @@ where
match res {
Ok(s) => {
owner_api.tx_lock_outputs(keychain_mask, &s)?;
let ret_slate = owner_api.finalize_tx(keychain_mask, &s)?;
let result = owner_api.post_tx(keychain_mask, &ret_slate, args.fluff);
match result {
@@ -532,7 +534,13 @@ where
}
Err(e) => {
error!("Error sending slate sync: {}", e);
output_sp()?;
output_sp(owner_api, false)?;
if !args.late_lock {
println!(
"Outputs are locked. To unlock them, cancel with `cancel -t {}`.",
slate.id
);
}
}
}
Ok(())
@@ -581,7 +589,18 @@ where
println!();
if !finalizing {
println!("Slatepack data follows. Please provide this output to the other party");
let cancel_hint = if lock {
format!(
" or cancel it manually with `cancel -t {}` command",
slate.id
)
} else {
"".to_string()
};
println!(
"Slatepack data follows. Please provide this output to the other party{}.",
cancel_hint
);
} else {
println!("Slatepack data follows.");
}
@@ -1074,7 +1093,6 @@ where
selection_strategy_is_use_all: args.selection_strategy == "all",
refresh_outputs_from_node: !info_updated,
ttl_blocks: args.ttl_blocks,
send_args: None,
..Default::default()
};
let result = owner_api.process_invoice_tx(keychain_mask, &slate, init_args);
-17
View File
@@ -136,23 +136,6 @@ fn init_tor_listener(
Ok(process)
}
/// 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<L, F, C, K>(
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
keychain_mask: Option<&SecretKey>,
config_path: PathBuf,
f: F,
) -> Result<(), Error>
where
L: WalletLCProvider<'static, C, K> + 'static,
F: FnOnce(&mut Owner<L, C, K>, Option<&SecretKey>) -> Result<(), Error>,
C: NodeClient + 'static,
K: Keychain + 'static,
{
f(&mut Owner::new(wallet, None, config_path), keychain_mask)
}
/// 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>(
+112 -182
View File
@@ -19,7 +19,6 @@ extern crate grin_wallet_impls as impls;
use grin_core as core;
use grin_keychain as keychain;
use std::path::PathBuf;
use self::core::global;
use self::keychain::{ExtKeychain, Keychain};
@@ -49,7 +48,8 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
@@ -62,7 +62,8 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
@@ -79,48 +80,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(),
mask1,
PathBuf::from(test_dir),
|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(())
},
)?;
{
let accounts = api1.accounts(mask1)?;
assert_eq!(accounts[0].label, "default");
assert_eq!(accounts[0].path, ExtKeychain::derive_key_id(2, 0, 0, 0, 0));
}
// add some accounts
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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(m, "account2").unwrap();
assert_eq!(new_path, ExtKeychain::derive_key_id(2, 2, 0, 0, 0));
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(m, "account1");
assert!(res.is_err());
Ok(())
},
)?;
{
let new_path = api1.create_account_path(mask1, "account1").unwrap();
assert_eq!(new_path, ExtKeychain::derive_key_id(2, 1, 0, 0, 0));
let new_path = api1.create_account_path(mask1, "account2").unwrap();
assert_eq!(new_path, ExtKeychain::derive_key_id(2, 2, 0, 0, 0));
let new_path = api1.create_account_path(mask1, "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 = api1.create_account_path(mask1, "account1");
assert!(res.is_err());
}
// add account to wallet 2
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|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(())
},
)?;
{
let new_path = api2.create_account_path(mask2, "listener_account").unwrap();
assert_eq!(new_path, ExtKeychain::derive_key_id(2, 1, 0, 0, 0));
}
// Default wallet 2 to listen on that account
{
@@ -144,120 +127,85 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
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(),
mask1,
PathBuf::from(test_dir),
|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(m, true, None, None, None)?;
assert_eq!(txs.len(), 5);
Ok(())
},
)?;
{
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, 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) = api1.retrieve_txs(mask1, true, None, None, None)?;
assert_eq!(txs.len(), 5);
}
// now check second account
{
// let mut w_lock = wallet1.lock();
// let lc = w_lock.lc_provider()?;
// let w = lc.wallet_inst()?;
wallet_inst!(wallet1, w);
w.set_parent_key_id_by_name("account1")?;
}
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let labels: Vec<_> = api.accounts(m)?.into_iter().map(|a| a.label).collect();
assert_eq!(labels, ["account1", "default", "account2", "account3"]);
// check last confirmed height on this account is different from above (should be 0)
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(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(m, true, None, None, None)?;
assert_eq!(txs.len(), 7);
Ok(())
},
)?;
{
let labels: Vec<_> = api1.accounts(mask1)?.into_iter().map(|a| a.label).collect();
assert_eq!(labels, ["account1", "default", "account2", "account3"]);
// check last confirmed height on this account is different from above (should be 0)
let (_, wallet1_info) = api1.retrieve_summary_info(mask1, false, 1)?;
assert_eq!(wallet1_info.last_confirmed_height, 0);
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, 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) = api1.retrieve_txs(mask1, true, None, None, None)?;
assert_eq!(txs.len(), 7);
}
// should be nothing in default account
{
wallet_inst!(wallet1, w);
w.set_parent_key_id_by_name("default")?;
}
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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(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(m, true, None, None, None)?;
assert_eq!(txs.len(), 0);
Ok(())
},
)?;
{
let (_, wallet1_info) = api1.retrieve_summary_info(mask1, false, 1)?;
assert_eq!(wallet1_info.last_confirmed_height, 0);
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, 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) = api1.retrieve_txs(mask1, true, None, None, None)?;
assert_eq!(txs.len(), 0);
}
// Send a tx to another wallet
{
wallet_inst!(wallet1, w);
w.set_parent_key_id_by_name("account1")?;
}
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let args = InitTxArgs {
src_acct_name: None,
amount: reward,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let mut slate = api.init_send_tx(m, args)?;
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
api.tx_lock_outputs(m, &slate)?;
slate = api.finalize_tx(m, &slate)?;
api.post_tx(m, &slate, false)?;
Ok(())
},
)?;
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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(m, true, None, None, None)?;
assert_eq!(txs.len(), 9);
Ok(())
},
)?;
{
let args = InitTxArgs {
src_acct_name: None,
amount: reward,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let mut slate = api1.init_send_tx(mask1, args)?;
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
api1.tx_lock_outputs(mask1, &slate)?;
slate = api1.finalize_tx(mask1, &slate)?;
api1.post_tx(mask1, &slate, false)?;
}
{
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, 13);
let (_, txs) = api1.retrieve_txs(mask1, true, None, None, None)?;
assert_eq!(txs.len(), 9);
}
// Use the requested account's stored height
{
wallet_inst!(wallet1, w);
@@ -272,59 +220,41 @@ 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(),
mask1,
PathBuf::from(test_dir),
|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(m, true, 1)?;
assert_eq!(wallet1_info.last_confirmed_height, 13);
let (_, txs) = api.retrieve_txs(m, true, None, None, None)?;
println!("{:?}", txs);
assert_eq!(txs.len(), 5);
Ok(())
},
)?;
{
let (_, wallet1_info) = api1.retrieve_summary_info(mask1, false, 1)?;
assert_eq!(wallet1_info.last_confirmed_height, 12);
let (_, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert_eq!(wallet1_info.last_confirmed_height, 13);
let (_, txs) = api1.retrieve_txs(mask1, true, None, None, None)?;
println!("{:?}", txs);
assert_eq!(txs.len(), 5);
}
// wallet 2 should only have this tx on the listener account
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|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(m, true, None, None, None)?;
assert_eq!(txs.len(), 1);
Ok(())
},
)?;
{
let (wallet2_refreshed, wallet2_info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(wallet2_refreshed);
assert_eq!(wallet2_info.last_confirmed_height, 13);
let (_, txs) = api2.retrieve_txs(mask2, true, None, None, None)?;
assert_eq!(txs.len(), 1);
}
// Default account on wallet 2 should be untouched
{
wallet_inst!(wallet2, w);
w.set_parent_key_id_by_name("default")?;
}
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|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(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(m, true, None, None, None)?;
assert_eq!(txs.len(), 0);
Ok(())
},
)?;
{
let (_, wallet2_info) = api2.retrieve_summary_info(mask2, false, 1)?;
assert_eq!(wallet2_info.last_confirmed_height, 0);
let (wallet2_refreshed, wallet2_info) = api2.retrieve_summary_info(mask2, 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) = api2.retrieve_txs(mask2, true, None, None, None)?;
assert_eq!(txs.len(), 0);
}
// let logging finish
stopper.store(false, Ordering::Relaxed);
+29 -62
View File
@@ -21,9 +21,8 @@ extern crate grin_wallet_impls as impls;
extern crate grin_wallet_libwallet as libwallet;
use grin_core as core;
use std::path::PathBuf;
use self::libwallet::{InitTxArgs, Slate};
use self::libwallet::InitTxArgs;
use impls::test_framework::{self, LocalWalletClient};
use rand::Rng;
use std::sync::atomic::Ordering;
@@ -48,7 +47,8 @@ fn build_chain(test_dir: &'static str, block_height: usize) -> Result<(), libwal
"wallet1",
None,
&mut wallet_proxy,
true
true,
api1
);
let mask1 = (&mask1_i).as_ref();
debug!("Mask1: {:?}", mask1);
@@ -60,7 +60,8 @@ fn build_chain(test_dir: &'static str, block_height: usize) -> Result<(), libwal
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
debug!("Mask2: {:?}", mask2);
@@ -74,25 +75,8 @@ fn build_chain(test_dir: &'static str, block_height: usize) -> Result<(), libwal
// Stop the scanning updater threads because it extends the time needed to build the chain
// exponentially
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, _m| {
api.stop_updater()?;
Ok(())
},
)?;
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, _m| {
api.stop_updater()?;
Ok(())
},
)?;
api1.stop_updater()?;
api2.stop_updater()?;
// few values to keep things shorter
let reward = core::consensus::REWARD;
@@ -105,22 +89,14 @@ fn build_chain(test_dir: &'static str, block_height: usize) -> Result<(), libwal
let mut wallet_1_has_funds = false;
// Check wallet 1 contents
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
debug!(
"Wallet 1 spendable - {}",
wallet1_info.amount_currently_spendable
);
if wallet1_info.amount_currently_spendable > reward {
wallet_1_has_funds = true;
}
Ok(())
},
)?;
let (_, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
debug!(
"Wallet 1 spendable - {}",
wallet1_info.amount_currently_spendable
);
if wallet1_info.amount_currently_spendable > reward {
wallet_1_has_funds = true;
}
// let's say 1 in every 3 blocks has a transaction (i.e. random 0 here and wallet1 has funds)
let transact = rng.gen_range(0, 2) == 0;
@@ -134,30 +110,21 @@ fn build_chain(test_dir: &'static str, block_height: usize) -> Result<(), libwal
let num_txs = rng.gen_range(0, 3);
for _ in 0..num_txs {
let amount: u64 = rng.gen_range(1, 10_000_000_001);
let mut slate = Slate::blank(1, false);
debug!("Creating TX for {}", amount);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|sender_api, m| {
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount,
minimum_confirmations: 1,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
let slate_i = sender_api.init_send_tx(m, args)?;
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
sender_api.tx_lock_outputs(m, &slate)?;
slate = sender_api.finalize_tx(m, &slate)?;
Ok(())
},
)?;
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount,
minimum_confirmations: 1,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
let slate_i = api1.init_send_tx(mask1, args)?;
let slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
api1.tx_lock_outputs(mask1, &slate)?;
api1.finalize_tx(mask1, &slate)?;
}
}
// let logging finish
+13 -22
View File
@@ -25,7 +25,6 @@ use grin_util::{secp, ZeroingString};
use grin_wallet_libwallet as libwallet;
use impls::test_framework::LocalWalletClient;
use rand::{thread_rng, Rng};
use std::path::PathBuf;
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
@@ -37,7 +36,7 @@ use common::{clean_output_dir, create_wallet_proxy, setup};
fn build_output_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
// Generate seed so we can verify the blinding factor is derived correctly
let seed: [u8; 32] = thread_rng().gen();
let keychain = ExtKeychain::from_seed(&seed, false).unwrap();
let keychain = ExtKeychain::from_seed(&seed, false)?;
let mnemonic = mnemonic::from_entropy(&seed).unwrap();
// Create a new proxy to simulate server and wallet responses
@@ -52,7 +51,8 @@ fn build_output_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error
"wallet1",
Some(ZeroingString::from(mnemonic)),
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
@@ -67,28 +67,19 @@ fn build_output_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
let features = OutputFeatures::Plain;
let amount = 60_000_000_000;
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|sender_api, m| {
let built_output = sender_api.build_output(m, features, amount)?;
let built_output = api1.build_output(mask1, features, amount)?;
let key_id = built_output.key_id;
assert_eq!(key_id.to_path(), ExtKeychainPath::new(3, 0, 0, 0, 0));
let key_id = built_output.key_id;
assert_eq!(key_id.to_path(), ExtKeychainPath::new(3, 0, 0, 0, 0));
let blind = built_output.blind;
let key = keychain.derive_key(amount, &key_id, SwitchCommitmentType::Regular)?;
assert_eq!(blind, BlindingFactor::from_secret_key(key.clone()));
let blind = built_output.blind;
let key = keychain.derive_key(amount, &key_id, SwitchCommitmentType::Regular)?;
assert_eq!(blind, BlindingFactor::from_secret_key(key.clone()));
let output = built_output.output;
assert_eq!(output.features(), features);
assert_eq!(output.commitment(), secp.commit(amount, key)?);
output.verify_proof()?;
Ok(())
},
)?;
let output = built_output.output;
assert_eq!(output.features(), features);
assert_eq!(output.commitment(), secp.commit(amount, key)?);
output.verify_proof()?;
// let logging finish
stopper.store(false, Ordering::Relaxed);
+203 -445
View File
@@ -27,7 +27,6 @@ use impls::test_framework::{self, LocalWalletClient};
use impls::{PathToSlate, SlatePutter as _};
use libwallet::{InitTxArgs, NodeClient};
use std::cmp;
use std::path::PathBuf;
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
@@ -66,7 +65,8 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
create_wallet_and_add!(
@@ -77,7 +77,8 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
@@ -89,34 +90,22 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
});
// few values to keep things shorter
let reward = core::consensus::REWARD;
let cm = global::coinbase_maturity() as u64; // assume all testing precedes soft fork height
let reward = consensus::REWARD;
let cm = global::coinbase_maturity(); // assume all testing precedes soft fork height
// add some accounts
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "named_account_1")?;
api.create_account_path(m, "account_2")?;
api.create_account_path(m, "account_3")?;
api.set_active_account(m, "named_account_1")?;
Ok(())
},
)?;
{
api1.create_account_path(mask1, "named_account_1")?;
api1.create_account_path(mask1, "account_2")?;
api1.create_account_path(mask1, "account_3")?;
api1.set_active_account(mask1, "named_account_1")?;
}
// add account to wallet 2
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "account_1")?;
api.set_active_account(m, "account_1")?;
Ok(())
},
)?;
{
api2.create_account_path(mask2, "account_1")?;
api2.set_active_account(mask2, "account_1")?;
}
// Do some mining
let bh = 20u64;
@@ -124,36 +113,21 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
// Sanity check contents
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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(m, true, None, None, None)?;
let (c, _) = libwallet::TxLogEntry::sum_confirmed(&txs);
assert_eq!(wallet1_info.total, c);
assert_eq!(txs.len(), bh as usize);
Ok(())
},
)?;
{
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, 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) = api1.retrieve_txs(mask1, true, None, None, None)?;
let (c, _) = libwallet::TxLogEntry::sum_confirmed(&txs);
assert_eq!(wallet1_info.total, c);
assert_eq!(txs.len(), bh as usize);
}
// Accidentally delete some outputs
let mut w1_outputs_commits = vec![];
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
w1_outputs_commits = api.retrieve_outputs(m, false, true, None)?.1;
Ok(())
},
)?;
let w1_outputs_commits = api1.retrieve_outputs(mask1, false, true, None)?.1;
let w1_outputs: Vec<libwallet::OutputData> =
w1_outputs_commits.into_iter().map(|m| m.output).collect();
{
@@ -170,108 +144,54 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
}
// check we have a problem now
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
let (_, txs) = api.retrieve_txs(m, true, None, None, None)?;
let (c, _) = libwallet::TxLogEntry::sum_confirmed(&txs);
assert_ne!(wallet1_info.total, c);
Ok(())
},
)?;
let (_, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
let (_, txs) = api1.retrieve_txs(mask1, true, None, None, None)?;
let (c, _) = libwallet::TxLogEntry::sum_confirmed(&txs);
assert_ne!(wallet1_info.total, c);
// this should restore our missing outputs
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.scan(m, None, true)?;
Ok(())
},
)?;
api1.scan(mask1, None, true)?;
// check our outputs match again
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.total, bh * reward);
// And check account names haven't been splatted
let accounts = api.accounts(m)?;
assert_eq!(accounts.len(), 4);
assert!(api.set_active_account(m, "account_1").is_err());
assert!(api.set_active_account(m, "named_account_1").is_ok());
Ok(())
},
)?;
{
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.total, bh * reward);
// And check account names haven't been splatted
let accounts = api1.accounts(mask1)?;
assert_eq!(accounts.len(), 4);
assert!(api1.set_active_account(mask1, "account_1").is_err());
assert!(api1.set_active_account(mask1, "named_account_1").is_ok());
}
// perform a transaction, but don't let it finish
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
// send to send
let args = InitTxArgs {
src_acct_name: None,
amount: reward * 2,
minimum_confirmations: cm,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
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, false)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
},
)?;
{
// send to send
let args = InitTxArgs {
src_acct_name: None,
amount: reward * 2,
minimum_confirmations: cm,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let slate = api1.init_send_tx(mask1, args)?;
// output tx file
let send_file = format!("{}/part_tx_1.tx", test_dir);
PathToSlate(send_file.into()).put_tx(&slate, false)?;
api1.tx_lock_outputs(mask1, &slate)?;
}
// check we're all locked
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.amount_currently_spendable, 0);
Ok(())
},
)?;
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.amount_currently_spendable, 0);
// unlock/restore
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.scan(m, None, true)?;
Ok(())
},
)?;
api1.scan(mask1, None, true)?;
// check spendable amount again
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
assert_eq!(wallet1_info.amount_currently_spendable, (bh - cm) * reward);
Ok(())
},
)?;
let (_, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert_eq!(wallet1_info.amount_currently_spendable, (bh - cm) * reward);
// let logging finish
stopper.store(false, Ordering::Relaxed);
@@ -300,7 +220,8 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
"miner",
None,
&mut wallet_proxy,
false
false,
_m_api
);
let miner_mask = (&miner_mask_i).as_ref();
@@ -313,7 +234,8 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
"wallet1",
seed_phrase,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
create_wallet_and_add!(
@@ -324,7 +246,8 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
"wallet2",
seed_phrase,
&mut wallet_proxy,
false
false,
_api2
);
let mask2 = (&mask2_i).as_ref();
// we'll restore into here
@@ -336,7 +259,8 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
"wallet3",
seed_phrase,
&mut wallet_proxy,
false
false,
api3
);
let mask3 = (&mask3_i).as_ref();
// also restore into here
@@ -348,7 +272,8 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
"wallet4",
seed_phrase,
&mut wallet_proxy,
false
false,
api4
);
let mask4 = (&mask4_i).as_ref();
// Simulate a recover from seed without restore into here
@@ -360,7 +285,8 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
"wallet5",
seed_phrase,
&mut wallet_proxy,
false
false,
api5
);
//simulate a recover from seed without restore into here
let mask5 = (&mask5_i).as_ref();
@@ -372,7 +298,8 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
"wallet6",
seed_phrase,
&mut wallet_proxy,
false
false,
api6
);
let mask6 = (&mask6_i).as_ref();
@@ -384,7 +311,8 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
"wallet7",
seed_phrase,
&mut wallet_proxy,
false
false,
api7
);
let mask7 = (&mask7_i).as_ref();
create_wallet_and_add!(
@@ -395,7 +323,8 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
"wallet8",
seed_phrase,
&mut wallet_proxy,
false
false,
api8
);
let mask8 = (&mask8_i).as_ref();
create_wallet_and_add!(
@@ -406,7 +335,8 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
"wallet9",
seed_phrase,
&mut wallet_proxy,
false
false,
api9
);
let mask9 = (&mask9_i).as_ref();
create_wallet_and_add!(
@@ -417,7 +347,8 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
"wallet10",
seed_phrase,
&mut wallet_proxy,
false
false,
api10
);
let mask10 = (&mask10_i).as_ref();
@@ -468,18 +399,10 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
bh += 3;
// 0) Check repair when all is okay should leave wallet contents alone
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.scan(m, None, 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(())
},
)?;
api1.scan(mask1, None, true)?;
let info = wallet_info!(wallet1.clone(), mask1)?;
assert_eq!(info.amount_currently_spendable, base_amount * 6);
assert_eq!(info.total, base_amount * 6);
// send some funds to wallet 2
send_to_dest!(
@@ -523,53 +446,21 @@ 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(),
mask3,
PathBuf::from(test_dir),
|api, m| {
api.scan(m, None, false)?;
Ok(())
},
)?;
api3.scan(mask3, None, false)?;
wallet::controller::owner_single_use(
wallet3.clone(),
mask3,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
let info = wallet_info!(wallet3.clone(), mask3)?;
let outputs = api3.retrieve_outputs(mask3, 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);
// 2) scan should recover them into a single wallet
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.scan(m, None, true)?;
Ok(())
},
)?;
api1.scan(mask1, None, true)?;
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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(())
},
)?;
let info = wallet_info!(wallet1.clone(), mask1)?;
let outputs = api1.retrieve_outputs(mask1, true, false, None)?.1;
assert_eq!(outputs.len(), 6);
assert_eq!(info.amount_currently_spendable, base_amount * 21);
// 3) If I recover from seed and start using the wallet without restoring,
// scan should restore the older outputs
@@ -601,41 +492,17 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
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(),
mask4,
PathBuf::from(test_dir),
|api, m| {
let info = wallet_info!(wallet4.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(())
},
)?;
let info = wallet_info!(wallet4.clone(), mask4)?;
let outputs = api4.retrieve_outputs(mask4, true, false, None)?.1;
assert_eq!(outputs.len(), 9);
assert_eq!(info.amount_currently_spendable, base_amount * 45);
wallet::controller::owner_single_use(
wallet5.clone(),
mask5,
PathBuf::from(test_dir),
|api, m| {
api.scan(m, None, false)?;
Ok(())
},
)?;
api5.scan(mask5, None, false)?;
wallet::controller::owner_single_use(
wallet5.clone(),
mask5,
PathBuf::from(test_dir),
|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(())
},
)?;
let info = wallet_info!(wallet5.clone(), mask5)?;
let outputs = api5.retrieve_outputs(mask5, true, false, None)?.1;
assert_eq!(outputs.len(), 9);
assert_eq!(info.amount_currently_spendable, base_amount * (45));
// 4) If I recover from seed and start using the wallet without restoring,
// scan should restore the older outputs
@@ -662,50 +529,20 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
)?;
bh += 3;
let _ = test_framework::award_blocks_to_wallet(
&chain,
miner.clone(),
miner_mask,
cm as usize,
false,
);
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), miner_mask, cm, false);
bh += cm as u64;
wallet::controller::owner_single_use(
wallet6.clone(),
mask6,
PathBuf::from(test_dir),
|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(())
},
)?;
let info = wallet_info!(wallet6.clone(), mask6)?;
let outputs = api6.retrieve_outputs(mask6, true, false, None)?.1;
assert_eq!(outputs.len(), 12);
assert_eq!(info.amount_currently_spendable, base_amount * 78);
wallet::controller::owner_single_use(
wallet6.clone(),
mask6,
PathBuf::from(test_dir),
|api, m| {
api.scan(m, None, true)?;
Ok(())
},
)?;
api6.scan(mask6, None, true)?;
wallet::controller::owner_single_use(
wallet6.clone(),
mask6,
PathBuf::from(test_dir),
|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(())
},
)?;
let info = wallet_info!(wallet6.clone(), mask6)?;
let outputs = api6.retrieve_outputs(mask6, true, false, None)?.1;
assert_eq!(outputs.len(), 12);
assert_eq!(info.amount_currently_spendable, base_amount * (78));
// 5) Start using same seed with a different account, amounts should
// be distinct and restore should return funds from other account
@@ -734,16 +571,8 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
bh += 3;
// mix it up a bit
wallet::controller::owner_single_use(
wallet7.clone(),
mask7,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "account_1")?;
api.set_active_account(m, "account_1")?;
Ok(())
},
)?;
api7.create_account_path(mask7, "account_1")?;
api7.set_active_account(mask7, "account_1")?;
send_to_dest!(
miner.clone(),
@@ -772,57 +601,33 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
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(),
mask7,
PathBuf::from(test_dir),
|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(m, "default")?;
let info = wallet_info!(wallet7.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 info = wallet_info!(wallet7.clone(), mask7)?;
let outputs = api7.retrieve_outputs(mask7, true, false, None)?.1;
assert_eq!(outputs.len(), 3);
assert_eq!(info.amount_currently_spendable, base_amount * 6);
api7.set_active_account(mask7, "default")?;
let info = wallet_info!(wallet7.clone(), mask7)?;
let outputs = api7.retrieve_outputs(mask7, true, false, None)?.1;
assert_eq!(outputs.len(), 15);
assert_eq!(info.amount_currently_spendable, base_amount * 120);
wallet::controller::owner_single_use(
wallet8.clone(),
mask8,
PathBuf::from(test_dir),
|api, m| {
api.scan(m, None, false)?;
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(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(())
},
)?;
api8.scan(mask8, None, false)?;
let info = wallet_info!(wallet8.clone(), mask8)?;
let outputs = api8.retrieve_outputs(mask8, true, false, None)?.1;
assert_eq!(outputs.len(), 15);
assert_eq!(info.amount_currently_spendable, base_amount * 120);
api8.set_active_account(mask8, "account_1")?;
let info = wallet_info!(wallet8.clone(), mask8)?;
let outputs = api8.retrieve_outputs(mask8, true, false, None)?.1;
assert_eq!(outputs.len(), 3);
assert_eq!(info.amount_currently_spendable, base_amount * 6);
// 6) Start using same seed with a different account, now overwriting
// ids on account 2 as well, scan should get all outputs created
// to now into 2 accounts
wallet::controller::owner_single_use(
wallet9.clone(),
mask9,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "account_1")?;
api.set_active_account(m, "account_1")?;
Ok(())
},
)?;
api9.create_account_path(mask9, "account_1")?;
api9.set_active_account(mask9, "account_1")?;
send_to_dest!(
miner.clone(),
@@ -848,53 +653,37 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
bh += 3;
let _bh = bh;
wallet::controller::owner_single_use(
wallet9.clone(),
mask9,
PathBuf::from(test_dir),
|api, m| {
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.scan(m, None, 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);
let info = wallet_info!(wallet9.clone(), mask9)?;
let outputs = api9.retrieve_outputs(mask9, true, false, None)?.1;
assert_eq!(outputs.len(), 6);
assert_eq!(info.amount_currently_spendable, base_amount * 21);
api9.scan(mask9, None, true)?;
let info = wallet_info!(wallet9.clone(), mask9)?;
let outputs = api9.retrieve_outputs(mask9, true, false, None)?.1;
assert_eq!(outputs.len(), 6);
assert_eq!(info.amount_currently_spendable, base_amount * 21);
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(())
},
)?;
api9.set_active_account(mask9, "default")?;
let info = wallet_info!(wallet9.clone(), mask9)?;
let outputs = api9.retrieve_outputs(mask9, true, false, None)?.1;
assert_eq!(outputs.len(), 15);
assert_eq!(info.amount_currently_spendable, base_amount * 120);
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), miner_mask, cm, false);
// 7) Ensure scan creates missing accounts
wallet::controller::owner_single_use(
wallet10.clone(),
mask10,
PathBuf::from(test_dir),
|api, m| {
api.scan(m, None, 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);
api10.scan(mask10, None, true)?;
api10.set_active_account(mask10, "account_1")?;
let info = wallet_info!(wallet10.clone(), mask10)?;
let outputs = api10.retrieve_outputs(mask10, true, false, None)?.1;
assert_eq!(outputs.len(), 6);
assert_eq!(info.amount_currently_spendable, base_amount * 21);
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(())
},
)?;
api10.set_active_account(mask10, "default")?;
let info = wallet_info!(wallet10.clone(), mask10)?;
let outputs = api10.retrieve_outputs(mask10, true, false, None)?.1;
assert_eq!(outputs.len(), 15);
assert_eq!(info.amount_currently_spendable, base_amount * 120);
// let logging finish
stopper.store(false, Ordering::Relaxed);
@@ -918,7 +707,8 @@ fn output_scanning_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
"wallet1",
None,
&mut wallet_proxy,
false
false,
_api1
);
let mask1 = (&mask1_i).as_ref();
thread::spawn(move || {
@@ -952,7 +742,7 @@ fn output_scanning_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
);
assert_eq!(outputs.2.len(), 14);
// mid range
// mid-range
let ranges = client1.height_range_to_pmmr_indices(5, Some(14))?;
assert_eq!(ranges, (8, 25));
let outputs = client1.get_outputs_by_pmmr_index(ranges.0, Some(ranges.1), 1000)?;
@@ -1002,7 +792,8 @@ fn multi_batch_scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
@@ -1017,19 +808,10 @@ fn multi_batch_scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
let _ =
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
let mut output_commits = vec![];
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, info) = api.retrieve_summary_info(m, true, 1)?;
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, bh * reward);
output_commits = api.retrieve_outputs(m, false, true, None)?.1;
Ok(())
},
)?;
let (_, info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, bh * reward);
let output_commits = api1.retrieve_outputs(mask1, false, true, None)?.1;
{
wallet_inst!(wallet1, w);
@@ -1076,18 +858,10 @@ fn multi_batch_scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
}
assert!(batches > 1);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, restored_outputs) = api.retrieve_outputs(m, false, true, None)?;
let (_, info) = api.retrieve_summary_info(m, false, 1)?;
assert_eq!(info.total, bh * reward);
assert_eq!(restored_outputs.len(), bh as usize);
Ok(())
},
)?;
let (_, restored_outputs) = api1.retrieve_outputs(mask1, false, true, None)?;
let (_, info) = api1.retrieve_summary_info(mask1, false, 1)?;
assert_eq!(info.total, bh * reward);
assert_eq!(restored_outputs.len(), bh as usize);
stopper.store(false, Ordering::Relaxed);
thread::sleep(Duration::from_millis(200));
@@ -1109,7 +883,8 @@ fn restore_corrupted_outputs_across_batches_impl(
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
@@ -1124,18 +899,9 @@ fn restore_corrupted_outputs_across_batches_impl(
let _ =
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
let mut output_commits = vec![];
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, info) = api.retrieve_summary_info(m, true, 1)?;
assert_eq!(info.total, bh * reward);
output_commits = api.retrieve_outputs(m, false, true, None)?.1;
Ok(())
},
)?;
let (_, info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert_eq!(info.total, bh * reward);
let output_commits = api1.retrieve_outputs(mask1, false, true, None)?.1;
{
wallet_inst!(wallet1, w);
@@ -1173,30 +939,22 @@ fn restore_corrupted_outputs_across_batches_impl(
assert_eq!(last_scanned.hash, "");
}
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, outputs_after_first_batch) = api.retrieve_outputs(m, false, false, None)?;
assert_eq!(outputs_after_first_batch.len(), (bh - 1) as usize);
let (_, outputs_after_first_batch) = api1.retrieve_outputs(mask1, false, false, None)?;
assert_eq!(outputs_after_first_batch.len(), (bh - 1) as usize);
let (_, info) = api.retrieve_summary_info(m, true, 1)?;
let (_, restored_outputs) = api.retrieve_outputs(m, false, true, None)?;
let unique_keys = restored_outputs
.iter()
.map(|o| o.output.key_id.clone())
.collect::<std::collections::HashSet<_>>();
let (_, info) = api1.retrieve_summary_info(mask1, true, 1)?;
let (_, restored_outputs) = api1.retrieve_outputs(mask1, false, true, None)?;
let unique_keys = restored_outputs
.iter()
.map(|o| o.output.key_id.clone())
.collect::<std::collections::HashSet<_>>();
assert_eq!(info.total, bh * reward);
assert_eq!(restored_outputs.len(), bh as usize);
assert_eq!(unique_keys.len(), bh as usize);
assert!(restored_outputs
.iter()
.all(|o| o.output.status == libwallet::OutputStatus::Unspent));
Ok(())
},
)?;
assert_eq!(info.total, bh * reward);
assert_eq!(restored_outputs.len(), bh as usize);
assert_eq!(unique_keys.len(), bh as usize);
assert!(restored_outputs
.iter()
.all(|o| o.output.status == libwallet::OutputStatus::Unspent));
stopper.store(false, Ordering::Relaxed);
thread::sleep(Duration::from_millis(200));
+31 -4
View File
@@ -19,11 +19,15 @@ extern crate grin_wallet_libwallet as libwallet;
use grin_core as core;
use grin_keychain as keychain;
use grin_util as util;
use std::env;
use std::path::PathBuf;
use self::core::global;
use self::core::global::ChainTypes;
use self::keychain::ExtKeychain;
use self::libwallet::WalletInst;
use grin_wallet_api::Owner;
use grin_wallet_config::{initial_setup_wallet, GRIN_WALLET_DIR};
use impls::test_framework::{LocalWalletClient, WalletProxy};
use impls::{DefaultLCProvider, DefaultWalletImpl};
use std::sync::Arc;
@@ -41,9 +45,9 @@ macro_rules! wallet_inst {
#[macro_export]
macro_rules! create_wallet_and_add {
($client:ident, $wallet: ident, $mask: ident, $test_dir: expr, $name: expr, $seed_phrase: expr, $proxy: expr, $create_mask: expr) => {
($client:ident, $wallet: ident, $mask: ident, $test_dir: expr, $name: expr, $seed_phrase: expr, $proxy: expr, $create_mask: expr, $owner_api: ident) => {
let $client = LocalWalletClient::new($name, $proxy.tx.clone());
let ($wallet, $mask) = common::create_local_wallet(
let ($wallet, $mask, $owner_api) = common::create_local_wallet(
$test_dir,
$name,
$seed_phrase.clone(),
@@ -125,7 +129,18 @@ pub fn create_local_wallet(
>,
>,
Option<SecretKey>,
Owner<DefaultLCProvider<LocalWalletClient, ExtKeychain>, LocalWalletClient, ExtKeychain>,
) {
let mut current_dir;
current_dir = env::current_dir().unwrap_or_else(|e| {
panic!("Error creating config file: {}", e);
});
current_dir.push(test_dir);
current_dir.push(name);
let config =
initial_setup_wallet(&ChainTypes::AutomatedTesting, Some(current_dir), true).unwrap();
let mut wallet_config = config.clone().members.wallet;
let mut wallet = Box::new(DefaultWalletImpl::<LocalWalletClient>::new(client).unwrap())
as Box<
dyn WalletInst<
@@ -135,13 +150,25 @@ pub fn create_local_wallet(
>,
>;
let lc = wallet.lc_provider().unwrap();
let _ = lc.set_top_level_directory(&format!("{}/{}", test_dir, name));
// legacy hack to avoid the need for changes in existing grin-wallet.toml files
// remove `wallet_data` from end of path as
// new lifecycle provider assumes grin_wallet.toml is in root of data directory
let mut top_level_wallet_dir = PathBuf::from(wallet_config.clone().data_file_dir);
if top_level_wallet_dir.ends_with(GRIN_WALLET_DIR) {
top_level_wallet_dir.pop();
wallet_config.data_file_dir = top_level_wallet_dir.to_str().unwrap().into();
}
let _ = lc.set_top_level_directory(&wallet_config.data_file_dir);
lc.create_wallet(None, mnemonic, 32, ZeroingString::from(""), false)
.unwrap();
let mask = lc
.open_wallet(None, ZeroingString::from(""), create_mask, false)
.unwrap();
(Arc::new(Mutex::new(wallet)), mask)
let wallet = Arc::new(Mutex::new(wallet));
let owner_api = Owner::new(wallet.clone(), None, config.config_file_path.clone());
(wallet, mask, owner_api)
}
#[allow(dead_code)]
+13 -5
View File
@@ -21,9 +21,9 @@ use config::config::{get_global_config, reload_global_config};
use config::GlobalWalletConfig;
use impls::test_framework::LocalWalletClient;
use libwallet::{InitTxArgs, InitTxSendArgs};
use std::fs;
use std::path::{Path, PathBuf};
use std::sync::atomic::Ordering;
use std::{env, fs};
mod common;
use common::{clean_output_dir, create_wallet_proxy, setup};
@@ -63,7 +63,8 @@ fn tor_disable() {
"wallet",
None,
&mut wallet_proxy,
false
false,
_api
);
let path = PathBuf::from(test_dir).join("grin-wallet.toml");
let mut config =
@@ -94,6 +95,7 @@ fn tor_disable() {
);
assert_eq!(cached, stored);
drop(_api);
drop(owner);
drop(wallet);
drop(wallet_proxy);
@@ -113,7 +115,8 @@ fn send_preflight() {
"wallet",
None,
&mut wallet_proxy,
false
false,
_api
);
let owner = api::Owner::new(
wallet.clone(),
@@ -144,6 +147,7 @@ fn send_preflight() {
assert!(after_txs.is_empty());
assert_eq!(snapshot(&wallet_data), before_data);
drop(_api);
drop(owner);
drop(wallet);
drop(wallet_proxy);
@@ -163,9 +167,13 @@ fn directory_change() {
"wallet",
None,
&mut wallet_proxy,
false
false,
_api
);
let old_dir = PathBuf::from(test_dir).join("wallet");
let old_dir = env::current_dir().unwrap_or_else(|e| {
panic!("Error creating config file: {}", e);
});
let old_dir = old_dir.join(test_dir).join("wallet");
let old_config = old_dir.join("grin-wallet.toml");
let new_dir = PathBuf::from(test_dir).join("other");
let owner = api::Owner::new(wallet.clone(), None, old_config.clone());
+84 -181
View File
@@ -27,7 +27,7 @@ use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
use grin_wallet_libwallet::{InitTxArgs, IssueInvoiceTxArgs, Slate};
use grin_wallet_libwallet::{InitTxArgs, IssueInvoiceTxArgs};
#[macro_use]
mod common;
@@ -50,7 +50,8 @@ fn file_exchange_test_impl(test_dir: &'static str, use_bin: bool) -> Result<(),
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
create_wallet_and_add!(
@@ -61,7 +62,8 @@ fn file_exchange_test_impl(test_dir: &'static str, use_bin: bool) -> Result<(),
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
@@ -76,28 +78,12 @@ fn file_exchange_test_impl(test_dir: &'static str, use_bin: bool) -> Result<(),
let reward = core::consensus::REWARD;
// add some accounts
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "mining")?;
api.create_account_path(m, "listener")?;
Ok(())
},
)?;
api1.create_account_path(mask1, "mining")?;
api1.create_account_path(mask1, "listener")?;
// add some accounts
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "account1")?;
api.create_account_path(m, "account2")?;
Ok(())
},
)?;
api2.create_account_path(mask2, "account1")?;
api2.create_account_path(mask2, "account2")?;
// Get some mining done
{
@@ -122,32 +108,24 @@ fn file_exchange_test_impl(test_dir: &'static str, use_bin: bool) -> Result<(),
};
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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);
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let slate = api.init_send_tx(m, args)?;
// output tx file
PathToSlate((&send_file).into()).put_tx(&slate, use_bin)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
},
)?;
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, bh * reward);
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let slate = api1.init_send_tx(mask1, args)?;
// output tx file
PathToSlate((&send_file).into()).put_tx(&slate, use_bin)?;
api1.tx_lock_outputs(mask1, &slate)?;
// Get some mining done
{
@@ -169,52 +147,28 @@ fn file_exchange_test_impl(test_dir: &'static str, use_bin: bool) -> Result<(),
},
)?;
// wallet 1 finalises and posts
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let mut slate = PathToSlate(receive_file.into()).get_tx()?.0;
slate = api.finalize_tx(m, &slate)?;
// Output final file for reference
PathToSlate((&final_file).into()).put_tx(&slate, use_bin)?;
api.post_tx(m, &slate, false)?;
bh += 1;
Ok(())
},
)?;
// wallet 1 finalizes and posts
let mut slate = PathToSlate(receive_file.into()).get_tx()?.0;
slate = api1.finalize_tx(mask1, &slate)?;
// Output final file for reference
PathToSlate((&final_file).into()).put_tx(&slate, use_bin)?;
api1.post_tx(mask1, &slate, false)?;
bh += 1;
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(),
mask1,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, bh * reward - reward * 2);
// Check total in 'wallet 2' account
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
let (wallet2_refreshed, wallet2_info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(wallet2_refreshed);
assert_eq!(wallet2_info.last_confirmed_height, bh);
assert_eq!(wallet2_info.total, 2 * reward);
// Now other types of exchange, for reference
// Invoice transaction
@@ -231,44 +185,27 @@ fn file_exchange_test_impl(test_dir: &'static str, use_bin: bool) -> Result<(),
),
};
let mut slate = Slate::blank(2, true);
let args = IssueInvoiceTxArgs {
amount: 1000000000,
..Default::default()
};
let mut slate = api2.issue_invoice_tx(mask2, args)?;
PathToSlate((&send_file).into()).put_tx(&slate, use_bin)?;
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
let args = IssueInvoiceTxArgs {
amount: 1000000000,
..Default::default()
};
slate = api.issue_invoice_tx(m, args)?;
PathToSlate((&send_file).into()).put_tx(&slate, use_bin)?;
Ok(())
},
)?;
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
slate = PathToSlate((&send_file).into()).get_tx()?.0;
slate = api1.process_invoice_tx(mask1, &slate, args)?;
api1.tx_lock_outputs(mask1, &slate)?;
PathToSlate((&receive_file).into()).put_tx(&slate, use_bin)?;
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
slate = PathToSlate((&send_file).into()).get_tx()?.0;
slate = api.process_invoice_tx(m, &slate, args)?;
api.tx_lock_outputs(m, &slate)?;
PathToSlate((&receive_file).into()).put_tx(&slate, use_bin)?;
Ok(())
},
)?;
wallet::controller::foreign_single_use(
wallet2.clone(),
PathBuf::from(test_dir),
@@ -281,15 +218,8 @@ fn file_exchange_test_impl(test_dir: &'static str, use_bin: bool) -> Result<(),
Ok(())
},
)?;
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.post_tx(m, &slate, false)?;
Ok(())
},
)?;
api1.post_tx(mask1, &slate, false)?;
// Standard, with payment proof
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
@@ -305,40 +235,22 @@ fn file_exchange_test_impl(test_dir: &'static str, use_bin: bool) -> Result<(),
format!("{}/standard_pp_S3.txbin", test_dir),
),
};
let mut slate = Slate::blank(2, true);
let mut address = None;
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
address = Some(api.get_slatepack_address(m, 0)?);
Ok(())
},
)?;
let address = Some(api2.get_slatepack_address(mask2, 0)?);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
payment_proof_recipient_address: address.clone(),
..Default::default()
};
let slate = api.init_send_tx(m, args)?;
PathToSlate((&send_file).into()).put_tx(&slate, use_bin)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
},
)?;
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
payment_proof_recipient_address: address.clone(),
..Default::default()
};
let mut slate = api1.init_send_tx(mask1, args)?;
PathToSlate((&send_file).into()).put_tx(&slate, use_bin)?;
api1.tx_lock_outputs(mask1, &slate)?;
wallet::controller::foreign_single_use(
wallet2.clone(),
@@ -352,21 +264,12 @@ fn file_exchange_test_impl(test_dir: &'static str, use_bin: bool) -> Result<(),
},
)?;
// wallet 1 finalises and posts
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
slate = PathToSlate(receive_file.into()).get_tx()?.0;
slate = api.finalize_tx(m, &slate)?;
// Output final file for reference
PathToSlate((&final_file).into()).put_tx(&slate, use_bin)?;
api.post_tx(m, &slate, false)?;
bh += 1;
Ok(())
},
)?;
// wallet 1 finalizes and posts
slate = PathToSlate(receive_file.into()).get_tx()?.0;
slate = api1.finalize_tx(mask1, &slate)?;
// Output final file for reference
PathToSlate((&final_file).into()).put_tx(&slate, use_bin)?;
api1.post_tx(mask1, &slate, false)?;
// let logging finish
stopper.store(false, Ordering::Relaxed);
+135 -262
View File
@@ -22,7 +22,7 @@ use grin_wallet_libwallet as libwallet;
use std::path::PathBuf;
use impls::test_framework::{self, LocalWalletClient};
use libwallet::{InitTxArgs, IssueInvoiceTxArgs, Slate, SlateState};
use libwallet::{InitTxArgs, IssueInvoiceTxArgs, SlateState};
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
@@ -46,7 +46,8 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet1",
None,
&mut wallet_proxy,
true
true,
api1
);
let mask1 = (&mask1_i).as_ref();
create_wallet_and_add!(
@@ -57,7 +58,8 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet2",
None,
&mut wallet_proxy,
true
true,
api2
);
let mask2 = (&mask2_i).as_ref();
@@ -72,16 +74,8 @@ 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(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "mining")?;
api.create_account_path(m, "listener")?;
Ok(())
},
)?;
api1.create_account_path(mask1, "mining")?;
api1.create_account_path(mask1, "listener")?;
// Get some mining done
{
@@ -93,46 +87,28 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
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(),
mask1,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, _bh);
assert_eq!(wallet1_info.total, _bh * reward);
let mut slate = Slate::blank(2, true);
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
let error = api
.issue_invoice_tx(
m,
IssueInvoiceTxArgs {
amount: 0,
..Default::default()
},
)
.unwrap_err();
assert_eq!(error, libwallet::Error::InvalidAmount);
// Wallet 2 inititates an invoice transaction, requesting payment
let args = IssueInvoiceTxArgs {
amount: reward * 2,
let error = api2
.issue_invoice_tx(
mask2,
IssueInvoiceTxArgs {
amount: 0,
..Default::default()
};
slate = api.issue_invoice_tx(m, args)?;
Ok(())
},
)?;
},
)
.unwrap_err();
assert_eq!(error, libwallet::Error::InvalidAmount);
// Wallet 2 initiates an invoice transaction, requesting payment
let args = IssueInvoiceTxArgs {
amount: reward * 2,
..Default::default()
};
let mut slate = api2.issue_invoice_tx(mask2, args)?;
assert_eq!(slate.state, SlateState::Invoice1);
let receive_result = wallet::controller::foreign_single_use(
@@ -142,16 +118,8 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|api| api.receive_tx(&slate, None, None).map(|_| ()),
);
assert_eq!(receive_result, Err(libwallet::Error::SlateState));
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, txs) = api.retrieve_txs(m, false, None, Some(slate.id), None)?;
assert!(txs.is_empty());
Ok(())
},
)?;
let (_, txs) = api1.retrieve_txs(mask1, false, None, Some(slate.id), None)?;
assert!(txs.is_empty());
// receive must reject every slate state except S1
for state in [
@@ -173,51 +141,34 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
assert_eq!(res, Err(libwallet::Error::SlateState), "state {}", state);
}
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
// Wallet 1 receives the invoice transaction
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let mut zero_amount_slate = slate.clone();
zero_amount_slate.amount = 0;
assert_eq!(
api.process_invoice_tx(m, &zero_amount_slate, args.clone())
.unwrap_err(),
libwallet::Error::InvalidAmount
);
slate = api.process_invoice_tx(m, &slate, args)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
},
)?;
// Wallet 1 receives the invoice transaction
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let mut zero_amount_slate = slate.clone();
zero_amount_slate.amount = 0;
assert_eq!(
api1.process_invoice_tx(mask1, &zero_amount_slate, args.clone())
.unwrap_err(),
libwallet::Error::InvalidAmount
);
slate = api1.process_invoice_tx(mask1, &slate, args)?;
api1.tx_lock_outputs(mask1, &slate)?;
assert_eq!(slate.state, SlateState::Invoice2);
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
assert_eq!(
api.tx_lock_outputs(m, &slate),
Err(libwallet::Error::SlateState)
);
let (_, txs) = api.retrieve_txs(m, false, None, None, None)?;
assert_eq!(txs.len(), 1);
assert_eq!(txs[0].tx_type, libwallet::TxLogEntryType::TxReceived);
Ok(())
},
)?;
assert_eq!(
api2.tx_lock_outputs(mask2, &slate),
Err(libwallet::Error::SlateState)
);
let (_, txs) = api2.retrieve_txs(mask2, false, None, None, None)?;
assert_eq!(txs.len(), 1);
assert_eq!(txs[0].tx_type, libwallet::TxLogEntryType::TxReceived);
// wallet 2 finalizes and posts
wallet::controller::foreign_single_use(
@@ -233,86 +184,54 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
assert_eq!(slate.state, SlateState::Invoice3);
// wallet 1 posts so wallet 2 doesn't get the mined amount
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.post_tx(m, &slate, false)?;
Ok(())
},
)?;
api1.post_tx(mask1, &slate, false)?;
_bh += 1;
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(),
mask2,
PathBuf::from(test_dir),
|api, m| {
let (_, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert!(refreshed);
assert!(txs.len() == 1);
println!(
"last confirmed height: {}, bh: {}",
wallet2_info.last_confirmed_height, _bh
);
assert!(refreshed);
Ok(())
},
)?;
let (_, wallet2_info) = api2.retrieve_summary_info(mask2, true, 1)?;
let (refreshed, txs) = api2.retrieve_txs(mask2, true, None, None, None)?;
assert!(refreshed);
assert_eq!(txs.len(), 1);
println!(
"last confirmed height: {}, bh: {}",
wallet2_info.last_confirmed_height, _bh
);
assert!(refreshed);
// Check transaction log for wallet 1, ensure only 1 entry
// exists
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert!(refreshed);
assert_eq!(txs.len() as u64, _bh + 1);
println!(
"Wallet 1: last confirmed height: {}, bh: {}",
wallet1_info.last_confirmed_height, _bh
);
Ok(())
},
)?;
let (_, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
let (refreshed, txs) = api1.retrieve_txs(mask1, true, None, None, None)?;
assert!(refreshed);
assert_eq!(txs.len() as u64, _bh + 1);
println!(
"Wallet 1: last confirmed height: {}, bh: {}",
wallet1_info.last_confirmed_height, _bh
);
// Test self-sending
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
// Wallet 1 inititates an invoice transaction, requesting payment
let args = IssueInvoiceTxArgs {
amount: reward * 2,
..Default::default()
};
slate = api.issue_invoice_tx(m, args)?;
// Wallet 1 receives the invoice transaction
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
println!("Self invoice slate init: {}", slate);
slate = api.process_invoice_tx(m, &slate, args)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
},
)?;
// Wallet 1 initiates an invoice transaction, requesting payment
let args = IssueInvoiceTxArgs {
amount: reward * 2,
..Default::default()
};
slate = api1.issue_invoice_tx(mask1, args)?;
// Wallet 1 receives the invoice transaction
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
println!("Self invoice slate init: {}", slate);
slate = api1.process_invoice_tx(mask1, &slate, args)?;
api1.tx_lock_outputs(mask1, &slate)?;
println!("Self invoice slate after process: {}", slate);
@@ -329,112 +248,66 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
)?;
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
//bh += 3;
// As above, but use owner API to finalize
let mut slate = Slate::blank(2, true);
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
// Wallet 2 inititates an invoice transaction, requesting payment
let args = IssueInvoiceTxArgs {
amount: reward * 2,
..Default::default()
};
slate = api.issue_invoice_tx(m, args)?;
Ok(())
},
)?;
// Wallet 2 initiates an invoice transaction, requesting payment
let args = IssueInvoiceTxArgs {
amount: reward * 2,
..Default::default()
};
slate = api2.issue_invoice_tx(mask2, args)?;
assert_eq!(slate.state, SlateState::Invoice1);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
// Wallet 1 receives the invoice transaction
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
slate = api.process_invoice_tx(m, &slate, args)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
},
)?;
// Wallet 1 receives the invoice transaction
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
slate = api1.process_invoice_tx(mask1, &slate, args)?;
api1.tx_lock_outputs(mask1, &slate)?;
assert_eq!(slate.state, SlateState::Invoice2);
// wallet 2 finalizes via owner API
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
// Wallet 2 receives the invoice transaction
slate = api.finalize_tx(m, &slate)?;
Ok(())
},
)?;
// Wallet 2 receives and finalizes via owner API
slate = api2.finalize_tx(mask2, &slate)?;
assert_eq!(slate.state, SlateState::Invoice3);
// test that payee can only cancel once
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
_bh += 3;
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
// Wallet 2 inititates an invoice transaction, requesting payment
let args = IssueInvoiceTxArgs {
amount: reward * 2,
..Default::default()
};
slate = api.issue_invoice_tx(m, args)?;
Ok(())
},
)?;
// Wallet 2 initiates an invoice transaction, requesting payment
let args = IssueInvoiceTxArgs {
amount: reward * 2,
..Default::default()
};
slate = api2.issue_invoice_tx(mask2, args)?;
assert_eq!(slate.state, SlateState::Invoice1);
let orig_slate = slate.clone();
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
// Wallet 1 receives the invoice transaction
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
slate = api.process_invoice_tx(m, &slate, args.clone())?;
api.tx_lock_outputs(m, &slate)?;
// Wallet 1 receives the invoice transaction
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
slate = api1.process_invoice_tx(mask1, &slate, args.clone())?;
api1.tx_lock_outputs(mask1, &slate)?;
// Wallet 1 cancels the invoice transaction
api.cancel_tx(m, None, Some(slate.id))?;
// Wallet 1 cancels the invoice transaction
api1.cancel_tx(mask1, None, Some(slate.id))?;
// Wallet 1 attempts to repay again
let res = api.process_invoice_tx(m, &orig_slate, args);
assert!(res.is_err());
Ok(())
},
)?;
// Wallet 1 attempts to repay again
let res = api1.process_invoice_tx(mask1, &orig_slate, args);
assert!(res.is_err());
assert_eq!(slate.state, SlateState::Invoice2);
// let logging finish
+67 -78
View File
@@ -18,9 +18,8 @@ extern crate grin_wallet_controller as wallet;
extern crate grin_wallet_impls as impls;
extern crate grin_wallet_libwallet as libwallet;
use self::libwallet::{InitTxArgs, Slate};
use self::libwallet::InitTxArgs;
use impls::test_framework::{self, LocalWalletClient};
use std::path::PathBuf;
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
@@ -28,6 +27,7 @@ use std::time::Duration;
#[macro_use]
mod common;
use common::{clean_output_dir, create_wallet_proxy, setup};
use libwallet::InitTxSendArgs;
/// self send impl
fn late_lock_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
@@ -46,7 +46,8 @@ fn late_lock_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
create_wallet_and_add!(
@@ -57,7 +58,8 @@ fn late_lock_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
@@ -69,26 +71,8 @@ fn late_lock_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
});
// add some accounts
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "mining")?;
Ok(())
},
)?;
// add some accounts
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "account1")?;
Ok(())
},
)?;
api1.create_account_path(mask1, "mining")?;
api2.create_account_path(mask2, "account1")?;
// Get some mining done
{
@@ -102,70 +86,75 @@ fn late_lock_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 10, false)?;
let mut slate = Slate::blank(2, false);
let amount = 100_000_000_000;
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|sender_api, m| {
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
late_lock: Some(true),
..Default::default()
};
let slate_i = sender_api.init_send_tx(m, args)?;
println!("S1 SLATE: {}", slate_i);
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
println!("S2 SLATE: {}", slate);
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
late_lock: Some(true),
..Default::default()
};
let slate_i = api1.init_send_tx(mask1, args)?;
println!("S1 SLATE: {}", slate_i);
let mut slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
println!("S2 SLATE: {}", slate);
// Note we don't call `tx_lock_outputs` on the sender side here,
// as the outputs will only be locked during finalization
// Note we don't call `tx_lock_outputs` on the sender side here,
// as the outputs will only be locked during finalization
slate = sender_api.finalize_tx(m, &slate)?;
println!("S3 SLATE: {}", slate);
slate = api1.finalize_tx(mask1, &slate)?;
println!("S3 SLATE: {}", slate);
// Now post tx to our node for inclusion in the next block.
sender_api.post_tx(m, &slate, true)?;
Ok(())
},
)?;
// Now post tx to our node for inclusion in the next block.
api1.post_tx(mask1, &slate, true)?;
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false)?;
// update/test contents of both accounts
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (wallet1_refreshed, wallet_info) = api.retrieve_summary_info(m, true, 1)?;
assert!(wallet1_refreshed);
// Reward from mining 11 blocks, minus the amount sent.
// Note: We mined the block containing the tx, so fees are effectively refunded.
assert_eq!(560_000_000_000, wallet_info.amount_currently_spendable);
Ok(())
},
)?;
let (wallet1_refreshed, wallet_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
// Reward from mining 11 blocks, minus the amount sent.
// Note: We mined the block containing the tx, so fees are effectively refunded.
assert_eq!(560_000_000_000, wallet_info.amount_currently_spendable);
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
let (wallet2_refreshed, wallet_info) = api.retrieve_summary_info(m, true, 1)?;
assert!(wallet2_refreshed);
assert_eq!(amount, wallet_info.amount_currently_spendable);
Ok(())
},
)?;
// Make sure outputs are not locked on failed send with arguments.
// Fail sending without starting Tor
api1.set_tor_config(Some(grin_wallet_config::TorConfig {
use_integrated: Some(false),
socks_proxy_addr: "invalid".into(),
..Default::default()
}))?;
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
late_lock: Some(true),
send_args: Some(InitTxSendArgs {
dest: "tgrin1xtxavwfgs48ckf3gk8wwgcndmn0nt4tvkl8a7ltyejjcy2mc6nfs9gm2lp".into(),
post_tx: false,
fluff: false,
skip_tor: Some(false),
}),
..Default::default()
};
let slate = api1.init_send_tx(mask1, args)?;
let (_, txs) = api1.retrieve_txs(mask1, false, None, Some(slate.id), None)?;
assert!(txs.is_empty());
// Make sure spendable balance not changed.
let (wallet1_refreshed, wallet_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(560_000_000_000, wallet_info.amount_currently_spendable);
let (wallet2_refreshed, wallet_info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(wallet2_refreshed);
assert_eq!(amount, wallet_info.amount_currently_spendable);
// let logging finish
stopper.store(false, Ordering::Relaxed);
+61 -107
View File
@@ -50,7 +50,8 @@ fn mwixnet_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet1",
None,
&mut wallet_proxy,
true
true,
api1
);
let mask1 = (&mask1_i).as_ref();
@@ -65,16 +66,8 @@ fn mwixnet_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
let reward = core::consensus::REWARD;
// add some accounts
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "mining")?;
api.create_account_path(m, "listener")?;
Ok(())
},
)?;
api1.create_account_path(mask1, "mining")?;
api1.create_account_path(mask1, "listener")?;
// Get some mining done
{
@@ -86,123 +79,84 @@ fn mwixnet_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
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(
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, bh * reward);
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let mut slate = api1.init_send_tx(mask1, args)?;
api1.tx_lock_outputs(mask1, &slate)?;
// Send directly to self
wallet::controller::foreign_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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);
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let mut slate = api.init_send_tx(m, args)?;
api.tx_lock_outputs(m, &slate)?;
// Send directly to self
wallet::controller::foreign_single_use(
wallet1.clone(),
PathBuf::from(test_dir),
mask1_i.clone(),
|api| {
slate = api.receive_tx(&slate, Some("listener"), None)?;
Ok(())
},
)?;
slate = api.finalize_tx(m, &slate)?;
api.post_tx(m, &slate, false)?; // mines a block
bh += 1;
mask1_i.clone(),
|api| {
slate = api.receive_tx(&slate, Some("listener"), None)?;
Ok(())
},
)?;
slate = api1.finalize_tx(mask1, &slate)?;
api1.post_tx(mask1, &slate, false)?; // mines a block
bh += 1;
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(),
mask1,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, bh * reward - reward * 2);
// Check total in 'listener' account
{
wallet_inst!(wallet1, w);
w.set_parent_key_id_by_name("listener")?;
}
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, 2 * reward);
// Recipient wallet creates a mwixnet request from the last output
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let secp_locked = util::static_secp_instance();
let secp = secp_locked.lock();
let server_pubkey_str_1 =
"97444ae673bb92c713c1a2f7b8882ffbfc1c67401a280a775dce1a8651584332";
let server_pubkey_str_2 =
"0c9414341f2140ed34a5a12a6479bf5a6404820d001ab81d9d3e8cc38f049b4e";
let server_pubkey_str_3 =
"b58ece97d60e71bb7e53218400b0d67bfe6a3cb7d3b4a67a44f8fb7c525cbca5";
let server_key_1 =
SecretKey::from_slice(&secp, &grin_util::from_hex(&server_pubkey_str_1).unwrap())
.unwrap();
let server_key_2 =
SecretKey::from_slice(&secp, &grin_util::from_hex(&server_pubkey_str_2).unwrap())
.unwrap();
let server_key_3 =
SecretKey::from_slice(&secp, &grin_util::from_hex(&server_pubkey_str_3).unwrap())
.unwrap();
let params = MixnetReqCreationParams {
server_keys: vec![server_key_1, server_key_2, server_key_3],
fee_per_hop: 50_000_000,
};
let outputs = api.retrieve_outputs(mask1, false, false, None)?;
// get last output
let last_output = outputs.1[outputs.1.len() - 1].clone();
let secp_locked = util::static_secp_instance();
let secp = secp_locked.lock();
let server_pubkey_str_1 = "97444ae673bb92c713c1a2f7b8882ffbfc1c67401a280a775dce1a8651584332";
let server_pubkey_str_2 = "0c9414341f2140ed34a5a12a6479bf5a6404820d001ab81d9d3e8cc38f049b4e";
let server_pubkey_str_3 = "b58ece97d60e71bb7e53218400b0d67bfe6a3cb7d3b4a67a44f8fb7c525cbca5";
let server_key_1 =
SecretKey::from_slice(&secp, &grin_util::from_hex(&server_pubkey_str_1).unwrap())?;
let server_key_2 =
SecretKey::from_slice(&secp, &grin_util::from_hex(&server_pubkey_str_2).unwrap())?;
let server_key_3 =
SecretKey::from_slice(&secp, &grin_util::from_hex(&server_pubkey_str_3).unwrap())?;
let params = MixnetReqCreationParams {
server_keys: vec![server_key_1, server_key_2, server_key_3],
fee_per_hop: 50_000_000,
};
let outputs = api1.retrieve_outputs(mask1, false, false, None)?;
// get last output
let last_output = outputs.1[outputs.1.len() - 1].clone();
let mwixnet_req = api.create_mwixnet_req(m, &params, &last_output.commit, true)?;
let mwixnet_req = api1.create_mwixnet_req(mask1, &params, &last_output.commit, true)?;
println!("MWIXNET REQ: {:?}", mwixnet_req);
println!("MWIXNET REQ: {:?}", mwixnet_req);
// check output we created comsig for is indeed locked
let outputs = api.retrieve_outputs(mask1, false, false, None)?;
// get last output
let last_output = outputs.1[outputs.1.len() - 1].clone();
assert!(last_output.output.status == libwallet::OutputStatus::Locked);
Ok(())
},
)?;
// check output we created comsig for is indeed locked
let outputs = api1.retrieve_outputs(mask1, false, false, None)?;
// get last output
let last_output = outputs.1[outputs.1.len() - 1].clone();
assert_eq!(last_output.output.status, libwallet::OutputStatus::Locked);
// let logging finish
stopper.store(false, Ordering::Relaxed);
+75 -139
View File
@@ -22,7 +22,7 @@ use std::path::PathBuf;
use grin_wallet_libwallet as libwallet;
use impls::test_framework::{self, LocalWalletClient};
use libwallet::{InitTxArgs, IssueInvoiceTxArgs, Slate};
use libwallet::{InitTxArgs, IssueInvoiceTxArgs};
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
@@ -44,7 +44,8 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
@@ -57,7 +58,8 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
@@ -77,109 +79,67 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
let fee = core::libtx::tx_fee(1, 1, 1);
// send a single block's worth of transactions with minimal strategy
let mut slate = Slate::blank(2, false);
let mut stored_excess = None;
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let args = InitTxArgs {
src_acct_name: None,
amount: reward - fee,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
slate = api.init_send_tx(m, args)?;
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
api.tx_lock_outputs(m, &slate)?;
slate = api.finalize_tx(m, &slate)?;
println!("Posted Slate: {:?}", slate);
stored_excess = Some(slate.tx.as_ref().unwrap().body.kernels[0].excess);
api.post_tx(m, &slate, false)?;
Ok(())
},
)?;
let args = InitTxArgs {
src_acct_name: None,
amount: reward - fee,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
let mut slate = api1.init_send_tx(mask1, args)?;
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
api1.tx_lock_outputs(mask1, &slate)?;
slate = api1.finalize_tx(mask1, &slate)?;
println!("Posted Slate: {:?}", slate);
let mut stored_excess = Some(slate.tx.as_ref().unwrap().body.kernels[0].excess);
api1.post_tx(mask1, &slate, false)?;
// ensure stored excess is correct in both wallets
// Wallet 1 calculated the excess with the full slate // Wallet 2 only had the excess provided by
// wallet 1
// Refresh and check transaction log for wallet 1
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id), None)?;
assert!(refreshed);
let tx = txs[0].clone();
println!("SIMPLE SEND - SENDING WALLET");
println!("{:?}", tx);
println!();
assert!(tx.confirmed);
assert_eq!(stored_excess, tx.kernel_excess);
Ok(())
},
)?;
let (refreshed, txs) = api1.retrieve_txs(mask1, true, None, Some(slate.id), None)?;
assert!(refreshed);
let tx = txs[0].clone();
println!("SIMPLE SEND - SENDING WALLET");
println!("{:?}", tx);
println!();
assert!(tx.confirmed);
assert_eq!(stored_excess, tx.kernel_excess);
// Refresh and check transaction log for wallet 2
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id), None)?;
assert!(refreshed);
let tx = txs[0].clone();
println!("SIMPLE SEND - RECEIVING WALLET");
println!("{:?}", tx);
println!();
assert!(tx.confirmed);
assert_eq!(stored_excess, tx.kernel_excess);
Ok(())
},
)?;
let (refreshed, txs) = api2.retrieve_txs(mask2, true, None, Some(slate.id), None)?;
assert!(refreshed);
let tx = txs[0].clone();
println!("SIMPLE SEND - RECEIVING WALLET");
println!("{:?}", tx);
println!();
assert!(tx.confirmed);
assert_eq!(stored_excess, tx.kernel_excess);
// ensure invoice TX works as well with no change
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
// Wallet 2 inititates an invoice transaction, requesting payment
let args = IssueInvoiceTxArgs {
amount: reward - fee,
..Default::default()
};
slate = api.issue_invoice_tx(m, args)?;
Ok(())
},
)?;
// Wallet 2 initiates an invoice transaction, requesting payment
let args = IssueInvoiceTxArgs {
amount: reward - fee,
..Default::default()
};
slate = api2.issue_invoice_tx(mask2, args)?;
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
// Wallet 1 receives the invoice transaction
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
slate = api.process_invoice_tx(m, &slate, args)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
},
)?;
// Wallet 1 receives the invoice transaction
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
slate = api1.process_invoice_tx(mask1, &slate, args)?;
api1.tx_lock_outputs(mask1, &slate)?;
// wallet 2 finalizes and posts
wallet::controller::foreign_single_use(
@@ -192,54 +152,30 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
Ok(())
},
)?;
wallet::controller::owner_single_use(
wallet2.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
println!("Invoice Posted TX: {}", slate);
stored_excess = Some(slate.tx.as_ref().unwrap().body.kernels[0].excess);
api.post_tx(m, &slate, false)?;
Ok(())
},
)?;
println!("Invoice Posted TX: {}", slate);
stored_excess = Some(slate.tx.as_ref().unwrap().body.kernels[0].excess);
api2.post_tx(mask2, &slate, false)?;
// check wallet 2's version
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id), None)?;
assert!(refreshed);
for tx in txs {
stored_excess = tx.kernel_excess;
println!("Wallet 2: {:?}", tx);
println!();
assert!(tx.confirmed);
assert_eq!(stored_excess, tx.kernel_excess);
}
Ok(())
},
)?;
let (refreshed, txs) = api2.retrieve_txs(mask2, true, None, Some(slate.id), None)?;
assert!(refreshed);
for tx in txs {
stored_excess = tx.kernel_excess;
println!("Wallet 2: {:?}", tx);
println!();
assert!(tx.confirmed);
assert_eq!(stored_excess, tx.kernel_excess);
}
// Refresh and check transaction log for wallet 1
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id), None)?;
assert!(refreshed);
for tx in txs {
println!("Wallet 1: {:?}", tx);
println!();
assert_eq!(stored_excess, tx.kernel_excess);
assert!(tx.confirmed);
}
Ok(())
},
)?;
let (refreshed, txs) = api1.retrieve_txs(mask1, true, None, Some(slate.id), None)?;
assert!(refreshed);
for tx in txs {
println!("Wallet 1: {:?}", tx);
println!();
assert_eq!(stored_excess, tx.kernel_excess);
assert!(tx.confirmed);
}
// let logging finish
stopper.store(false, Ordering::Relaxed);
+56 -80
View File
@@ -21,7 +21,6 @@ extern crate grin_wallet_util;
use grin_wallet_libwallet as libwallet;
use impls::test_framework::{self, LocalWalletClient};
use libwallet::{InitTxArgs, Slate};
use std::path::PathBuf;
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
@@ -45,7 +44,8 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
@@ -58,7 +58,8 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
@@ -77,99 +78,74 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
let _ =
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
let mut address = None;
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
address = Some(api.get_slatepack_address(m, 0)?);
Ok(())
},
)?;
let address = Some(api2.get_slatepack_address(mask2, 0)?);
println!("Public address is: {:?}", address);
let amount = 60_000_000_000;
let mut slate = Slate::blank(1, false);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|sender_api, m| {
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount: amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
payment_proof_recipient_address: address.clone(),
..Default::default()
};
let slate_i = sender_api.init_send_tx(m, args)?;
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
payment_proof_recipient_address: address.clone(),
..Default::default()
};
let slate_i = api1.init_send_tx(mask1, args)?;
assert_eq!(
slate_i.payment_proof.as_ref().unwrap().receiver_address,
address.as_ref().unwrap().pub_key,
);
println!(
"Sender addr: {:?}",
slate_i.payment_proof.as_ref().unwrap().sender_address
);
assert_eq!(
slate_i.payment_proof.as_ref().unwrap().receiver_address,
address.as_ref().unwrap().pub_key,
);
println!(
"Sender addr: {:?}",
slate_i.payment_proof.as_ref().unwrap().sender_address
);
// Check we are creating a tx with kernel features 0
// We will check this produces a Plain kernel later.
assert_eq!(0, slate.kernel_features);
// Check we are creating a tx with kernel features 0
// We will check this produces a Plain kernel later.
assert_eq!(0, slate.kernel_features);
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
sender_api.tx_lock_outputs(m, &slate)?;
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
api1.tx_lock_outputs(mask1, &slate)?;
// Ensure what's stored in TX log for payment proof is correct
let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id), None)?;
assert!(txs[0].payment_proof.is_some());
let pp = txs[0].clone().payment_proof.unwrap();
assert_eq!(
pp.receiver_address,
slate_i.payment_proof.as_ref().unwrap().receiver_address
);
assert!(pp.receiver_signature.is_some());
assert_eq!(pp.sender_address_path, 0);
assert_eq!(pp.sender_signature, None);
// Ensure what's stored in TX log for payment proof is correct
let (_, txs) = api1.retrieve_txs(mask1, true, None, Some(slate.id), None)?;
assert!(txs[0].payment_proof.is_some());
let pp = txs[0].clone().payment_proof.unwrap();
assert_eq!(
pp.receiver_address,
slate_i.payment_proof.as_ref().unwrap().receiver_address
);
assert!(pp.receiver_signature.is_some());
assert_eq!(pp.sender_address_path, 0);
assert_eq!(pp.sender_signature, None);
// check we should get an error at this point since proof is not complete
let pp = sender_api.retrieve_payment_proof(m, true, None, Some(slate.id));
assert!(pp.is_err());
// check we should get an error at this point since proof is not complete
let pp = api1.retrieve_payment_proof(mask1, true, None, Some(slate.id));
assert!(pp.is_err());
slate = sender_api.finalize_tx(m, &slate)?;
sender_api.post_tx(m, &slate, true)?;
Ok(())
},
)?;
slate = api1.finalize_tx(mask1, &slate)?;
api1.post_tx(mask1, &slate, true)?;
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 2, false);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|sender_api, m| {
// Check payment proof here
let mut pp = sender_api.retrieve_payment_proof(m, true, None, Some(slate.id))?;
// Check payment proof here
let mut pp = api1.retrieve_payment_proof(mask1, true, None, Some(slate.id))?;
println!("Payment proof: {:?}", pp);
println!("Payment proof: {:?}", pp);
// verify, should be good
let res = sender_api.verify_payment_proof(m, &pp)?;
assert_eq!(res, (true, false));
// verify, should be good
let res = api1.verify_payment_proof(mask1, &pp)?;
assert_eq!(res, (true, false));
// Modify values, should not be good
pp.amount = 20;
let res = sender_api.verify_payment_proof(m, &pp);
assert!(res.is_err());
Ok(())
},
)?;
// Modify values, should not be good
pp.amount = 20;
let res = api1.verify_payment_proof(mask1, &pp);
assert!(res.is_err());
// let logging finish
stopper.store(false, Ordering::Relaxed);
+71 -161
View File
@@ -21,7 +21,7 @@ extern crate grin_wallet_libwallet as libwallet;
use grin_core as core;
use std::path::PathBuf;
use self::libwallet::{InitTxArgs, Slate};
use self::libwallet::InitTxArgs;
use impls::test_framework::{self, LocalWalletClient};
use impls::{PathToSlate, SlateGetter as _, SlatePutter as _};
use std::sync::atomic::Ordering;
@@ -49,7 +49,8 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
create_wallet_and_add!(
@@ -60,7 +61,8 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
@@ -75,28 +77,11 @@ 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(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "mining")?;
api.create_account_path(m, "listener")?;
Ok(())
},
)?;
api1.create_account_path(mask1, "mining")?;
api1.create_account_path(mask1, "listener")?;
// add some accounts
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "account1")?;
api.create_account_path(m, "account2")?;
Ok(())
},
)?;
api2.create_account_path(mask2, "account1")?;
api2.create_account_path(mask2, "account2")?;
// Get some mining done
{
@@ -110,34 +95,24 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
let send_file = format!("{}/part_tx_1.tx", test_dir);
let receive_file = format!("{}/part_tx_2.tx", test_dir);
let mut slate = Slate::blank(2, false);
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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);
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let slate = api.init_send_tx(m, args)?;
PathToSlate((&send_file).into()).put_tx(&slate, false)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
},
)?;
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, bh * reward);
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let mut slate = api1.init_send_tx(mask1, args)?;
PathToSlate((&send_file).into()).put_tx(&slate, false)?;
api1.tx_lock_outputs(mask1, &slate)?;
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
bh += 3;
@@ -167,69 +142,37 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
}
// wallet 1 finalize
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
slate = PathToSlate((&receive_file).into()).get_tx()?.0;
slate = api.finalize_tx(m, &slate)?;
Ok(())
},
)?;
slate = PathToSlate((&receive_file).into()).get_tx()?.0;
slate = api1.finalize_tx(mask1, &slate)?;
// Now repost from cached
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id), None)?;
println!("TXS[0]: {:?}", txs[0]);
let stored_tx = api.get_stored_tx(m, None, Some(&txs[0].tx_slate_id.unwrap()))?;
println!("Stored tx: {:?}", stored_tx);
api.post_tx(m, &slate, false)?;
bh += 1;
Ok(())
},
)?;
let (_, txs) = api1.retrieve_txs(mask1, true, None, Some(slate.id), None)?;
println!("TXS[0]: {:?}", txs[0]);
let stored_tx = api1.get_stored_tx(mask1, None, Some(&txs[0].tx_slate_id.unwrap()))?;
println!("Stored tx: {:?}", stored_tx);
api1.post_tx(mask1, &slate, false)?;
bh += 1;
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(),
mask1,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, bh * reward - reward * 2);
{
wallet_inst!(wallet1, w);
w.set_parent_key_id_by_name("listener")?;
}
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, 2 * reward);
// as above, but syncronously
// as above, but synchronously
{
wallet_inst!(wallet1, w);
w.set_parent_key_id_by_name("mining")?;
@@ -239,78 +182,45 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
w.set_parent_key_id_by_name("account1")?;
}
let mut slate = Slate::blank(2, false);
let amount = 60_000_000_000;
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|sender_api, m| {
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let slate_i = sender_api.init_send_tx(m, args)?;
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
sender_api.tx_lock_outputs(m, &slate)?;
slate = sender_api.finalize_tx(m, &slate)?;
Ok(())
},
)?;
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let slate_i = api1.init_send_tx(mask1, args)?;
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
api1.tx_lock_outputs(mask1, &slate)?;
slate = api1.finalize_tx(mask1, &slate)?;
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(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id), None)?;
let stored_tx_slate = api.get_stored_tx(m, Some(txs[0].id), None)?.unwrap();
api.post_tx(m, &stored_tx_slate, false)?;
bh += 1;
Ok(())
},
)?;
let (_, txs) = api1.retrieve_txs(mask1, true, None, Some(slate.id), None)?;
let stored_tx_slate = api1.get_stored_tx(mask1, Some(txs[0].id), None)?.unwrap();
api1.post_tx(mask1, &stored_tx_slate, false)?;
bh += 1;
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(),
mask1,
PathBuf::from(test_dir),
|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(),
mask2,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
// update/test contents of both accounts
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, bh * reward - reward * 4);
let (wallet2_refreshed, wallet2_info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(wallet2_refreshed);
assert_eq!(wallet2_info.last_confirmed_height, bh);
assert_eq!(wallet2_info.total, 2 * amount);
// let logging finish
stopper.store(false, Ordering::Relaxed);
+128 -161
View File
@@ -24,14 +24,13 @@ use grin_core::global;
use grin_keychain::ExtKeychain;
use grin_util::secp::key::SecretKey;
use grin_util::Mutex;
use grin_wallet_controller::controller::owner_single_use as owner;
use grin_wallet_api::Owner;
use grin_wallet_impls::test_framework::*;
use grin_wallet_impls::{DefaultLCProvider, PathToSlate, SlatePutter};
use grin_wallet_libwallet as libwallet;
use grin_wallet_libwallet::api_impl::types::InitTxArgs;
use grin_wallet_libwallet::WalletInst;
use log::error;
use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
@@ -63,6 +62,8 @@ fn revert(
Option<SecretKey>,
Wallet,
Option<SecretKey>,
Owner<DefaultLCProvider<LocalWalletClient, ExtKeychain>, LocalWalletClient, ExtKeychain>,
Owner<DefaultLCProvider<LocalWalletClient, ExtKeychain>, LocalWalletClient, ExtKeychain>,
),
libwallet::Error,
> {
@@ -82,7 +83,8 @@ fn revert(
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = mask1_i.as_ref();
@@ -94,28 +96,23 @@ fn revert(
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = mask2_i.as_ref();
// Set the wallet proxy listener running
std::thread::spawn(move || {
thread::spawn(move || {
if let Err(e) = wallet_proxy.run() {
error!("Wallet Proxy error: {}", e);
}
});
owner(wallet1.clone(), mask1, PathBuf::from(test_dir), |api, m| {
api.create_account_path(m, "a")?;
api.set_active_account(m, "a")?;
Ok(())
})?;
api1.create_account_path(mask1, "a")?;
api1.set_active_account(mask1, "a")?;
owner(wallet2.clone(), mask2, PathBuf::from(test_dir), |api, m| {
api.create_account_path(m, "b")?;
api.set_active_account(m, "b")?;
Ok(())
})?;
api2.create_account_path(mask2, "b")?;
api2.set_active_account(mask2, "b")?;
let reward = core::consensus::REWARD;
let cm = global::coinbase_maturity() as u64;
@@ -126,76 +123,60 @@ fn revert(
award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false)?;
// Sanity check contents
owner(wallet1.clone(), mask1, PathBuf::from(test_dir), |api, m| {
let (refreshed, info) = api.retrieve_summary_info(m, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, bh * reward);
assert_eq!(info.amount_currently_spendable, (bh - cm) * reward);
assert_eq!(info.amount_reverted, 0);
// check tx log as well
let (_, txs) = api.retrieve_txs(m, true, None, None, None)?;
let (c, _) = libwallet::TxLogEntry::sum_confirmed(&txs);
assert_eq!(info.total, c);
assert_eq!(txs.len(), bh as usize);
Ok(())
})?;
let (refreshed, info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, bh * reward);
assert_eq!(info.amount_currently_spendable, (bh - cm) * reward);
assert_eq!(info.amount_reverted, 0);
// check tx log as well
let (_, txs) = api1.retrieve_txs(mask1, true, None, None, None)?;
let (c, _) = libwallet::TxLogEntry::sum_confirmed(&txs);
assert_eq!(info.total, c);
assert_eq!(txs.len(), bh as usize);
owner(wallet2.clone(), mask2, PathBuf::from(test_dir), |api, m| {
let (refreshed, info) = api.retrieve_summary_info(m, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, 0);
assert_eq!(info.amount_currently_spendable, 0);
assert_eq!(info.amount_reverted, 0);
// check tx log as well
let (_, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert_eq!(txs.len(), 0);
Ok(())
})?;
let (refreshed, info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, 0);
assert_eq!(info.amount_currently_spendable, 0);
assert_eq!(info.amount_reverted, 0);
// check tx log as well
let (_, txs) = api2.retrieve_txs(mask2, true, None, None, None)?;
assert_eq!(txs.len(), 0);
// Send some funds
let mut tx = None;
owner(wallet1.clone(), mask1, PathBuf::from(test_dir), |api, m| {
// send to send
let args = InitTxArgs {
src_acct_name: None,
amount: sent,
minimum_confirmations: cm,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
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, false)?;
api.tx_lock_outputs(m, &slate)?;
let slate = client1.send_tx_slate_direct("wallet2", &slate)?;
let slate = api.finalize_tx(m, &slate)?;
tx = slate.tx;
Ok(())
})?;
let tx = tx.expect("tx from slate");
// send to send
let args = InitTxArgs {
src_acct_name: None,
amount: sent,
minimum_confirmations: cm,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
let slate = api1.init_send_tx(mask1, args)?;
// output tx file
let send_file = format!("{}/part_tx_1.tx", test_dir);
PathToSlate(send_file.into()).put_tx(&slate, false)?;
api1.tx_lock_outputs(mask1, &slate)?;
let slate = client1.send_tx_slate_direct("wallet2", &slate)?;
let slate = api1.finalize_tx(mask1, &slate)?;
let tx = slate.tx.expect("tx from slate");
// Check funds have been received
owner(wallet2.clone(), mask2, PathBuf::from(test_dir), |api, m| {
let (refreshed, info) = api.retrieve_summary_info(m, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, 0);
assert_eq!(info.amount_currently_spendable, 0);
assert_eq!(info.amount_reverted, 0);
// check tx log as well
let (_, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert_eq!(txs.len(), 1);
let tx = &txs[0];
assert_eq!(tx.tx_type, libwallet::TxLogEntryType::TxReceived);
assert!(!tx.confirmed);
Ok(())
})?;
let (refreshed, info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, 0);
assert_eq!(info.amount_currently_spendable, 0);
assert_eq!(info.amount_reverted, 0);
// check tx log as well
let (_, txs) = api2.retrieve_txs(mask2, true, None, None, None)?;
assert_eq!(txs.len(), 1);
assert_eq!(txs[0].tx_type, libwallet::TxLogEntryType::TxReceived);
assert!(!&txs[0].confirmed);
// Update parallel chain
assert_eq!(chain2.head_header().unwrap().height, 0);
@@ -223,23 +204,19 @@ fn revert(
let bh = bh + 1;
// Check funds have been confirmed
owner(wallet2.clone(), mask2, PathBuf::from(test_dir), |api, m| {
let (refreshed, info) = api.retrieve_summary_info(m, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, sent);
assert_eq!(info.amount_currently_spendable, sent);
assert_eq!(info.amount_reverted, 0);
// check tx log as well
let (_, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert_eq!(txs.len(), 1);
let tx = &txs[0];
assert_eq!(tx.tx_type, libwallet::TxLogEntryType::TxReceived);
assert!(tx.confirmed);
assert!(tx.kernel_excess.is_some());
assert!(tx.reverted_after.is_none());
Ok(())
})?;
let (refreshed, info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, sent);
assert_eq!(info.amount_currently_spendable, sent);
assert_eq!(info.amount_reverted, 0);
// check tx log as well
let (_, txs) = api2.retrieve_txs(mask2, true, None, None, None)?;
assert_eq!(txs.len(), 1);
assert_eq!(txs[0].tx_type, libwallet::TxLogEntryType::TxReceived);
assert!(&txs[0].confirmed);
assert!(&txs[0].kernel_excess.is_some());
assert!(&txs[0].reverted_after.is_none());
// Attach more blocks to the parallel chain, making it the longest one
award_block_to_wallet(&chain2, &[], wallet1.clone(), mask1)?;
@@ -258,32 +235,29 @@ fn revert(
let bh = bh + 1;
// Check funds have been reverted
owner(wallet2.clone(), mask2, PathBuf::from(test_dir), |api, m| {
api.scan(m, None, false)?;
let (refreshed, info) = api.retrieve_summary_info(m, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, 0);
assert_eq!(info.amount_currently_spendable, 0);
assert_eq!(info.amount_reverted, sent);
// check tx log as well
let (_, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert_eq!(txs.len(), 1);
let tx = &txs[0];
assert_eq!(tx.tx_type, libwallet::TxLogEntryType::TxReverted);
assert!(!tx.confirmed);
assert!(tx.reverted_after.is_some());
Ok(())
})?;
api2.scan(mask2, None, false)?;
let (refreshed, info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, 0);
assert_eq!(info.amount_currently_spendable, 0);
assert_eq!(info.amount_reverted, sent);
// check tx log as well
let (_, txs) = api2.retrieve_txs(mask2, true, None, None, None)?;
assert_eq!(txs.len(), 1);
assert_eq!(txs[0].tx_type, libwallet::TxLogEntryType::TxReverted);
assert!(!&txs[0].confirmed);
assert!(&txs[0].reverted_after.is_some());
stopper2.store(false, Ordering::Relaxed);
Ok((
chain, stopper, sent, bh, tx, wallet1, mask1_i, wallet2, mask2_i,
chain, stopper, sent, bh, tx, wallet1, mask1_i, wallet2, mask2_i, api1, api2,
))
}
fn revert_reconfirm_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
let (chain, stopper, sent, bh, tx, wallet1, mask1_i, wallet2, mask2_i) = revert(test_dir)?;
let (chain, stopper, sent, bh, tx, wallet1, mask1_i, _wallet2, mask2_i, _api1, api2) =
revert(test_dir)?;
let mask1 = mask1_i.as_ref();
let mask2 = mask2_i.as_ref();
@@ -293,22 +267,19 @@ fn revert_reconfirm_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
let bh = bh + 1;
// Check funds have been confirmed again
owner(wallet2.clone(), mask2, PathBuf::from(test_dir), |api, m| {
let (refreshed, info) = api.retrieve_summary_info(m, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, sent);
assert_eq!(info.amount_currently_spendable, sent);
assert_eq!(info.amount_reverted, 0);
// check tx log as well
let (_, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert_eq!(txs.len(), 1);
let tx = &txs[0];
assert_eq!(tx.tx_type, libwallet::TxLogEntryType::TxReceived);
assert!(tx.confirmed);
assert!(tx.reverted_after.is_none());
Ok(())
})?;
let (refreshed, info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, sent);
assert_eq!(info.amount_currently_spendable, sent);
assert_eq!(info.amount_reverted, 0);
// check tx log as well
let (_, txs) = api2.retrieve_txs(mask2, true, None, None, None)?;
assert_eq!(txs.len(), 1);
let tx = &txs[0];
assert_eq!(tx.tx_type, libwallet::TxLogEntryType::TxReceived);
assert!(tx.confirmed);
assert!(tx.reverted_after.is_none());
// let logging finish
stopper.store(false, Ordering::Relaxed);
@@ -317,41 +288,37 @@ fn revert_reconfirm_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
}
fn revert_cancel_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
let (_, stopper, sent, bh, _, _, _, wallet2, mask2_i) = revert(test_dir)?;
let (_, stopper, sent, bh, _, _, _, _wallet2, mask2_i, _api1, api2) = revert(test_dir)?;
let mask2 = mask2_i.as_ref();
// Cancelling tx
owner(wallet2.clone(), mask2, PathBuf::from(test_dir), |api, m| {
// Sanity check
let (refreshed, info) = api.retrieve_summary_info(m, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, 0);
assert_eq!(info.amount_currently_spendable, 0);
assert_eq!(info.amount_reverted, sent);
// Sanity check
let (refreshed, info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, 0);
assert_eq!(info.amount_currently_spendable, 0);
assert_eq!(info.amount_reverted, sent);
let (_, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert_eq!(txs.len(), 1);
let tx = &txs[0];
let (_, txs) = api2.retrieve_txs(mask2, true, None, None, None)?;
assert_eq!(txs.len(), 1);
let tx = &txs[0];
// Cancel
api.cancel_tx(m, Some(tx.id), None)?;
// Cancel
api2.cancel_tx(mask2, Some(tx.id), None)?;
// Check updated summary info
let (refreshed, info) = api.retrieve_summary_info(m, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, 0);
assert_eq!(info.amount_currently_spendable, 0);
assert_eq!(info.amount_reverted, 0);
// Check updated summary info
let (refreshed, info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(refreshed);
assert_eq!(info.last_confirmed_height, bh);
assert_eq!(info.total, 0);
assert_eq!(info.amount_currently_spendable, 0);
assert_eq!(info.amount_reverted, 0);
// Check updated tx log
let (_, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert_eq!(txs.len(), 1);
let tx = &txs[0];
assert_eq!(tx.tx_type, libwallet::TxLogEntryType::TxReceivedCancelled);
Ok(())
})?;
// Check updated tx log
let (_, txs) = api2.retrieve_txs(mask2, true, None, None, None)?;
assert_eq!(txs.len(), 1);
let tx = &txs[0];
assert_eq!(tx.tx_type, libwallet::TxLogEntryType::TxReceivedCancelled);
// let logging finish
stopper.store(false, Ordering::Relaxed);
+36 -67
View File
@@ -48,7 +48,8 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet1",
None,
&mut wallet_proxy,
true
true,
api1
);
let mask1 = (&mask1_i).as_ref();
@@ -63,16 +64,8 @@ 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(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "mining")?;
api.create_account_path(m, "listener")?;
Ok(())
},
)?;
api1.create_account_path(mask1, "mining")?;
api1.create_account_path(mask1, "listener")?;
// Get some mining done
{
@@ -84,78 +77,54 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
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(
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, bh * reward);
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let mut slate = api1.init_send_tx(mask1, args)?;
api1.tx_lock_outputs(mask1, &slate)?;
// Send directly to self
wallet::controller::foreign_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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);
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let mut slate = api.init_send_tx(m, args)?;
api.tx_lock_outputs(m, &slate)?;
// Send directly to self
wallet::controller::foreign_single_use(
wallet1.clone(),
PathBuf::from(test_dir),
mask1_i.clone(),
|api| {
slate = api.receive_tx(&slate, Some("listener"), None)?;
Ok(())
},
)?;
slate = api.finalize_tx(m, &slate)?;
api.post_tx(m, &slate, false)?; // mines a block
bh += 1;
mask1_i.clone(),
|api| {
slate = api.receive_tx(&slate, Some("listener"), None)?;
Ok(())
},
)?;
slate = api1.finalize_tx(mask1, &slate)?;
api1.post_tx(mask1, &slate, false)?; // mines a block
bh += 1;
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(),
mask1,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, bh * reward - reward * 2);
// Check total in 'listener' account
{
wallet_inst!(wallet1, w);
w.set_parent_key_id_by_name("listener")?;
}
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, 2 * reward);
// let logging finish
stopper.store(false, Ordering::Relaxed);
+190 -322
View File
@@ -100,7 +100,8 @@ fn slatepack_exchange_test_impl(
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
create_wallet_and_add!(
@@ -111,7 +112,8 @@ fn slatepack_exchange_test_impl(
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
@@ -126,28 +128,11 @@ fn slatepack_exchange_test_impl(
let reward = core::consensus::REWARD;
// add some accounts
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "mining")?;
api.create_account_path(m, "listener")?;
Ok(())
},
)?;
api1.create_account_path(mask1, "mining")?;
api1.create_account_path(mask1, "listener")?;
// add some accounts
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "account1")?;
api.create_account_path(m, "account2")?;
Ok(())
},
)?;
api2.create_account_path(mask2, "account1")?;
api2.create_account_path(mask2, "account2")?;
// Get some mining done
{
@@ -160,19 +145,9 @@ fn slatepack_exchange_test_impl(
let (recipients_1, dec_key_1, sender_1) = match use_encryption {
true => {
let mut rec_address = SlatepackAddress::random();
let mut sec_key = edDalekSecretKey::from_bytes(&[0u8; 32]);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
sec_key = api.get_slatepack_secret_key(m, 0)?;
let pub_key = edDalekPublicKey::from(&sec_key);
rec_address = SlatepackAddress::new(&pub_key);
Ok(())
},
)?;
let sec_key = api1.get_slatepack_secret_key(mask1, 0)?;
let pub_key = edDalekPublicKey::from(&sec_key);
let rec_address = SlatepackAddress::new(&pub_key);
(
vec![rec_address.clone()],
Some(sec_key),
@@ -184,19 +159,9 @@ fn slatepack_exchange_test_impl(
let (recipients_2, dec_key_2, sender_2) = match use_encryption {
true => {
let mut rec_address = SlatepackAddress::random();
let mut sec_key = edDalekSecretKey::from_bytes(&[0u8; 32]);
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
sec_key = api.get_slatepack_secret_key(m, 0)?;
let pub_key = edDalekPublicKey::from(&sec_key);
rec_address = SlatepackAddress::new(&pub_key);
Ok(())
},
)?;
let sec_key = api2.get_slatepack_secret_key(mask2, 0)?;
let pub_key = edDalekPublicKey::from(&sec_key);
let rec_address = SlatepackAddress::new(&pub_key);
(
vec![rec_address.clone()],
Some(sec_key),
@@ -219,39 +184,31 @@ fn slatepack_exchange_test_impl(
),
};
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|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);
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let slate = api.init_send_tx(m, args)?;
// output tx file
output_slatepack(
&slate,
&send_file,
use_armored,
use_bin,
sender_1.clone(),
recipients_2.clone(),
)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
},
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, bh * reward);
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let slate = api1.init_send_tx(mask1, args)?;
// output tx file
output_slatepack(
&slate,
&send_file,
use_armored,
use_bin,
sender_1.clone(),
recipients_2.clone(),
)?;
api1.tx_lock_outputs(mask1, &slate)?;
// Get some mining done
{
@@ -286,52 +243,27 @@ fn slatepack_exchange_test_impl(
)?;
// wallet 1 finalizes and posts
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, mut slate) =
slate_from_packed(&receive_file, use_armored, (&dec_key_1).as_ref())?;
slate = api.finalize_tx(m, &slate)?;
// Output final file for reference
output_slatepack(&slate, &final_file, use_armored, use_bin, None, vec![])?;
api.post_tx(m, &slate, false)?;
bh += 1;
Ok(())
},
)?;
let (_, mut slate) = slate_from_packed(&receive_file, use_armored, (&dec_key_1).as_ref())?;
slate = api1.finalize_tx(mask1, &slate)?;
// Output final file for reference
output_slatepack(&slate, &final_file, use_armored, use_bin, None, vec![])?;
api1.post_tx(mask1, &slate, false)?;
bh += 1;
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(),
mask1,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
let (wallet1_refreshed, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
assert!(wallet1_refreshed);
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.total, bh * reward - reward * 2);
// Check total in 'wallet 2' account
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|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);
Ok(())
},
)?;
let (wallet2_refreshed, wallet2_info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(wallet2_refreshed);
assert_eq!(wallet2_info.last_confirmed_height, bh);
assert_eq!(wallet2_info.total, 2 * reward);
// Now other types of exchange, for reference
// Invoice transaction
@@ -348,61 +280,43 @@ fn slatepack_exchange_test_impl(
),
};
let mut slate = Slate::blank(2, true);
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
let args = IssueInvoiceTxArgs {
amount: 1000000000,
..Default::default()
};
slate = api.issue_invoice_tx(m, args)?;
output_slatepack(
&slate,
&send_file,
use_armored,
use_bin,
sender_2.clone(),
recipients_1.clone(),
)?;
Ok(())
},
let args = IssueInvoiceTxArgs {
amount: 1000000000,
..Default::default()
};
let mut slate = api2.issue_invoice_tx(mask2, args)?;
output_slatepack(
&slate,
&send_file,
use_armored,
use_bin,
sender_2.clone(),
recipients_1.clone(),
)?;
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let res = slate_from_packed(&send_file, use_armored, (&dec_key_1).as_ref())?;
slatepack = res.0;
slate = res.1;
slate = api.process_invoice_tx(m, &slate, args)?;
api.tx_lock_outputs(m, &slate)?;
output_slatepack(
&slate,
&receive_file,
use_armored,
use_bin,
sender_1.clone(),
match slatepack.sender.clone() {
Some(s) => vec![s.clone()],
None => vec![],
},
)?;
Ok(())
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let res = slate_from_packed(&send_file, use_armored, (&dec_key_1).as_ref())?;
slatepack = res.0;
slate = res.1;
slate = api1.process_invoice_tx(mask1, &slate, args)?;
api1.tx_lock_outputs(mask1, &slate)?;
output_slatepack(
&slate,
&receive_file,
use_armored,
use_bin,
sender_1.clone(),
match slatepack.sender.clone() {
Some(s) => vec![s.clone()],
None => vec![],
},
)?;
wallet::controller::foreign_single_use(
@@ -418,15 +332,7 @@ fn slatepack_exchange_test_impl(
Ok(())
},
)?;
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.post_tx(m, &slate, false)?;
Ok(())
},
)?;
api1.post_tx(mask1, &slate, false)?;
// Standard, with payment proof
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
@@ -443,47 +349,29 @@ fn slatepack_exchange_test_impl(
),
};
let mut slate = Slate::blank(2, true);
let mut address = None;
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
address = Some(api.get_slatepack_address(m, 0)?);
Ok(())
},
)?;
let address = Some(api2.get_slatepack_address(mask2, 0)?);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
payment_proof_recipient_address: address.clone(),
..Default::default()
};
let slate = api.init_send_tx(m, args)?;
output_slatepack(
&slate,
&send_file,
use_armored,
use_bin,
sender_1,
recipients_2.clone(),
)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
},
// send to send
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
payment_proof_recipient_address: address.clone(),
..Default::default()
};
let mut slate = api1.init_send_tx(mask1, args)?;
output_slatepack(
&slate,
&send_file,
use_armored,
use_bin,
sender_1,
recipients_2.clone(),
)?;
api1.tx_lock_outputs(mask1, &slate)?;
wallet::controller::foreign_single_use(
wallet2.clone(),
@@ -509,22 +397,13 @@ fn slatepack_exchange_test_impl(
},
)?;
// wallet 1 finalises and posts
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let res = slate_from_packed(&receive_file, use_armored, (&dec_key_1).as_ref())?;
slate = res.1;
slate = api.finalize_tx(m, &slate)?;
// Output final file for reference
output_slatepack(&slate, &final_file, use_armored, use_bin, None, vec![])?;
api.post_tx(m, &slate, false)?;
bh += 1;
Ok(())
},
)?;
// wallet 1 finalizes and posts
let res = slate_from_packed(&receive_file, use_armored, (&dec_key_1).as_ref())?;
slate = res.1;
slate = api1.finalize_tx(mask1, &slate)?;
// Output final file for reference
output_slatepack(&slate, &final_file, use_armored, use_bin, None, vec![])?;
api1.post_tx(mask1, &slate, false)?;
// let logging finish
stopper.store(false, Ordering::Relaxed);
@@ -550,7 +429,8 @@ fn slatepack_api_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
@@ -569,32 +449,24 @@ fn slatepack_api_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
let _ =
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let slate = api.init_send_tx(m, args)?;
// create an encrypted slatepack (just encrypted for self)
let enc_addr = api.get_slatepack_address(m, 0)?;
let slatepack = api.create_slatepack_message(m, &slate, Some(0), vec![enc_addr])?;
println!("{}", slatepack);
let slatepack_raw = api.decode_slatepack_message(m, slatepack.clone(), vec![0])?;
println!("{}", slatepack_raw);
let decoded_slate = api.slate_from_slatepack_message(m, slatepack, vec![0])?;
println!("{}", decoded_slate);
Ok(())
},
)?;
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward * 2,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let slate = api1.init_send_tx(mask1, args)?;
// create an encrypted slatepack (just encrypted for self)
let enc_addr = api1.get_slatepack_address(mask1, 0)?;
let slatepack = api1.create_slatepack_message(mask1, &slate, Some(0), vec![enc_addr])?;
println!("{}", slatepack);
let slatepack_raw = api1.decode_slatepack_message(mask1, slatepack.clone(), vec![0])?;
println!("{}", slatepack_raw);
let decoded_slate = api1.slate_from_slatepack_message(mask1, slatepack, vec![0])?;
println!("{}", decoded_slate);
// let logging finish
stopper.store(false, Ordering::Relaxed);
@@ -609,8 +481,7 @@ fn slatepack_address_validation(test_dir: &'static str) -> Result<(), libwallet:
let stopper = wallet_proxy.running.clone();
let config_path = PathBuf::from(test_dir).join("grin-wallet.toml");
GlobalWalletConfig::for_chain(&core::global::ChainTypes::AutomatedTesting, &config_path)
.write_to_file(config_path.to_str().unwrap(), false, None, None)
.unwrap();
.write_to_file(config_path.to_str().unwrap(), false, None, None)?;
create_wallet_and_add!(
client1,
@@ -620,7 +491,8 @@ fn slatepack_address_validation(test_dir: &'static str) -> Result<(), libwallet:
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
@@ -632,7 +504,8 @@ fn slatepack_address_validation(test_dir: &'static str) -> Result<(), libwallet:
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
@@ -644,62 +517,57 @@ fn slatepack_address_validation(test_dir: &'static str) -> Result<(), libwallet:
let reward = core::consensus::REWARD;
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 6, false);
let mut slate = Slate::blank(2, true);
wallet::controller::owner_single_use(wallet2.clone(), mask2, config_path.clone(), |api, m| {
slate = api.issue_invoice_tx(
m,
IssueInvoiceTxArgs {
amount: reward,
..Default::default()
},
)?;
Ok(())
})?;
wallet::controller::owner_single_use(wallet1.clone(), mask1, config_path, |api, m| {
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
let slate = api2.issue_invoice_tx(
mask2,
IssueInvoiceTxArgs {
amount: reward,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
},
)?;
let mut wrong_net_args = args.clone();
wrong_net_args.send_args = Some(InitTxSendArgs {
dest: "grin1dvge9z4uqgqlpspmljrd7smh3grrw9xu2r9lkz3u67s3emj3ud2sd5gk9p".to_string(),
post_tx: false,
fluff: false,
skip_tor: Some(true),
});
assert!(api.init_send_tx(m, wrong_net_args.clone()).is_err());
assert!(api.process_invoice_tx(m, &slate, wrong_net_args).is_err());
let args = InitTxArgs {
src_acct_name: Some("mining".to_owned()),
amount: reward,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
..Default::default()
};
let mut invalid_args = args.clone();
invalid_args.send_args = Some(InitTxSendArgs {
dest: "tgrinaddr10qlk22rxjap2ny8qltc2tl996kenxr3hhwuu6hrzs6tdq08yaqgqnlumr7"
.to_string(),
post_tx: false,
fluff: false,
skip_tor: Some(true),
});
assert!(api.init_send_tx(m, invalid_args.clone()).is_err());
assert!(api.process_invoice_tx(m, &slate, invalid_args).is_err());
let mut wrong_net_args = args.clone();
wrong_net_args.send_args = Some(InitTxSendArgs {
dest: "grin1dvge9z4uqgqlpspmljrd7smh3grrw9xu2r9lkz3u67s3emj3ud2sd5gk9p".to_string(),
post_tx: false,
fluff: false,
skip_tor: Some(true),
});
assert!(api1.init_send_tx(mask1, wrong_net_args.clone()).is_err());
assert!(api1
.process_invoice_tx(mask1, &slate, wrong_net_args)
.is_err());
let mut valid_args = args;
valid_args.send_args = Some(InitTxSendArgs {
dest: "tgrin1xtxavwfgs48ckf3gk8wwgcndmn0nt4tvkl8a7ltyejjcy2mc6nfs9gm2lp".to_string(),
post_tx: false,
fluff: false,
skip_tor: Some(true),
});
api.process_invoice_tx(m, &slate, valid_args.clone())?;
api.init_send_tx(m, valid_args)?;
Ok(())
})?;
let mut invalid_args = args.clone();
invalid_args.send_args = Some(InitTxSendArgs {
dest: "tgrinaddr10qlk22rxjap2ny8qltc2tl996kenxr3hhwuu6hrzs6tdq08yaqgqnlumr7".to_string(),
post_tx: false,
fluff: false,
skip_tor: Some(true),
});
assert!(api1.init_send_tx(mask1, invalid_args.clone()).is_err());
assert!(api1
.process_invoice_tx(mask1, &slate, invalid_args)
.is_err());
let mut valid_args = args;
valid_args.send_args = Some(InitTxSendArgs {
dest: "tgrin1xtxavwfgs48ckf3gk8wwgcndmn0nt4tvkl8a7ltyejjcy2mc6nfs9gm2lp".to_string(),
post_tx: false,
fluff: false,
skip_tor: Some(true),
});
api1.process_invoice_tx(mask1, &slate, valid_args.clone())?;
api1.init_send_tx(mask1, valid_args)?;
stopper.store(false, Ordering::Relaxed);
proxy_thread.join().expect("wallet proxy thread panicked");
@@ -710,7 +578,7 @@ fn slatepack_address_validation(test_dir: &'static str) -> Result<(), libwallet:
fn slatepack_exchange_json() {
let test_dir = "test_output/slatepack_exchange_json";
setup(test_dir);
// Json output
// JSON output
if let Err(e) = slatepack_exchange_test_impl(test_dir, false, false, false) {
panic!("Libwallet Error: {}", e);
}
@@ -743,7 +611,7 @@ fn slatepack_exchange_armored() {
fn slatepack_exchange_json_enc() {
let test_dir = "test_output/slatepack_exchange_json_enc";
setup(test_dir);
// Json output
// JSON output
if let Err(e) = slatepack_exchange_test_impl(test_dir, false, false, true) {
panic!("Libwallet Error: {}", e);
}
@@ -776,7 +644,7 @@ fn slatepack_exchange_armored_enc() {
fn slatepack_api() {
let test_dir = "test_output/slatepack_api";
setup(test_dir);
// Json output
// JSON output
if let Err(e) = slatepack_api_impl(test_dir) {
panic!("Libwallet Error: {}", e);
}
File diff suppressed because it is too large Load Diff
+53 -102
View File
@@ -20,8 +20,7 @@ extern crate grin_wallet_util;
use grin_wallet_libwallet as libwallet;
use impls::test_framework::{self, LocalWalletClient};
use libwallet::{InitTxArgs, Slate, TxLogEntryType};
use std::path::PathBuf;
use libwallet::{InitTxArgs, TxLogEntryType};
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
@@ -45,7 +44,8 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
@@ -58,7 +58,8 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
@@ -78,126 +79,76 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
let amount = 60_000_000_000;
let mut slate = Slate::blank(1, false);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|sender_api, m| {
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount: amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
ttl_blocks: Some(2),
..Default::default()
};
let slate_i = sender_api.init_send_tx(m, args)?;
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
ttl_blocks: Some(2),
..Default::default()
};
let slate_i = api1.init_send_tx(mask1, args)?;
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
sender_api.tx_lock_outputs(m, &slate)?;
let mut slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
api1.tx_lock_outputs(mask1, &slate)?;
let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id), None)?;
let tx = txs[0].clone();
let (_, txs) = api1.retrieve_txs(mask1, true, None, Some(slate.id), None)?;
let tx = txs[0].clone();
assert_eq!(tx.ttl_cutoff_height, Some(12));
Ok(())
},
)?;
assert_eq!(tx.ttl_cutoff_height, Some(12));
// Now mine past the block, and check again. Transaction should be gone.
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 2, false);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|sender_api, m| {
let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id), None)?;
let tx = txs[0].clone();
let (_, txs) = api1.retrieve_txs(mask1, true, None, Some(slate.id), None)?;
let tx = txs[0].clone();
assert_eq!(tx.ttl_cutoff_height, Some(12));
assert_eq!(tx.tx_type, TxLogEntryType::TxSentCancelled);
Ok(())
},
)?;
assert_eq!(tx.ttl_cutoff_height, Some(12));
assert_eq!(tx.tx_type, TxLogEntryType::TxSentCancelled);
// Should also be gone in wallet 2, and output gone
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|sender_api, m| {
let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id), None)?;
let tx = txs[0].clone();
let outputs = sender_api.retrieve_outputs(m, false, true, None)?.1;
assert_eq!(outputs.len(), 0);
let (_, txs) = api2.retrieve_txs(mask2, true, None, Some(slate.id), None)?;
let tx = txs[0].clone();
let outputs = api2.retrieve_outputs(mask2, false, true, None)?.1;
assert_eq!(outputs.len(), 0);
assert_eq!(tx.ttl_cutoff_height, Some(12));
assert_eq!(tx.tx_type, TxLogEntryType::TxReceivedCancelled);
Ok(())
},
)?;
assert_eq!(tx.ttl_cutoff_height, Some(12));
assert_eq!(tx.tx_type, TxLogEntryType::TxReceivedCancelled);
// try again, except try and send off the transaction for completion beyond the expiry
let mut slate = Slate::blank(1, false);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|sender_api, m| {
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
ttl_blocks: Some(2),
..Default::default()
};
let slate_i = sender_api.init_send_tx(m, args)?;
sender_api.tx_lock_outputs(m, &slate_i)?;
slate = slate_i;
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount,
minimum_confirmations: 2,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
ttl_blocks: Some(2),
..Default::default()
};
let slate_i = api1.init_send_tx(mask1, args)?;
api1.tx_lock_outputs(mask1, &slate_i)?;
slate = slate_i;
let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id), None)?;
let tx = txs[0].clone();
let (_, txs) = api1.retrieve_txs(mask1, true, None, Some(slate.id), None)?;
let tx = txs[0].clone();
assert_eq!(tx.ttl_cutoff_height, Some(14));
Ok(())
},
)?;
assert_eq!(tx.ttl_cutoff_height, Some(14));
// Mine past the ttl block and try to send
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 2, false);
// Wallet 2 will need to have updated past the TTL
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|sender_api, m| {
let (_, _) = sender_api.retrieve_txs(m, true, None, Some(slate.id), None)?;
Ok(())
},
)?;
let (_, _) = api2.retrieve_txs(mask2, true, None, Some(slate.id), None)?;
// And when wallet 1 sends, should be rejected
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|_sender_api, _m| {
let res = client1.send_tx_slate_direct("wallet2", &slate);
println!("Send after TTL result is: {:?}", res);
assert!(res.is_err());
Ok(())
},
)?;
let res = client1.send_tx_slate_direct("wallet2", &slate);
println!("Send after TTL result is: {:?}", res);
assert!(res.is_err());
// let logging finish
stopper.store(false, Ordering::Relaxed);
+183 -251
View File
@@ -23,210 +23,183 @@ use grin_core as core;
use grin_keychain as keychain;
use grin_util as util;
use libwallet::{RetrieveTxQueryArgs, RetrieveTxQuerySortField};
use std::path::PathBuf;
use self::libwallet::{InitTxArgs, Slate};
use self::libwallet::InitTxArgs;
use impls::test_framework::{self, LocalWalletClient};
use std::sync::{atomic::Ordering, Arc};
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
use util::secp::key::SecretKey;
use util::Mutex;
use self::keychain::ExtKeychain;
use self::libwallet::WalletInst;
use impls::DefaultLCProvider;
mod common;
use common::{clean_output_dir, create_wallet_proxy, setup};
use grin_wallet_api::Owner;
fn test_wallet_tx_filtering(
wallet: Arc<
Mutex<
Box<
dyn WalletInst<
'static,
DefaultLCProvider<LocalWalletClient, ExtKeychain>,
LocalWalletClient,
ExtKeychain,
>,
>,
>,
>,
mask: Option<&SecretKey>,
test_dir: &'static str,
api: Owner<DefaultLCProvider<LocalWalletClient, ExtKeychain>, LocalWalletClient, ExtKeychain>,
) -> Result<(), libwallet::Error> {
wallet::controller::owner_single_use(
wallet.clone(),
mask,
PathBuf::from(test_dir),
|api, _m| {
let query = |args| {
api.retrieve_txs(mask, true, None, None, Some(args))
.map(|(_, txs)| txs)
};
let txs = query(RetrieveTxQueryArgs::default())?;
assert!(!txs.is_empty());
let before_first_tx =
txs.iter().map(|tx| tx.creation_ts).min().unwrap() - Duration::from_secs(1);
let mut tx_query_args = RetrieveTxQueryArgs::default();
let query = |args| {
api.retrieve_txs(mask, true, None, None, Some(args))
.map(|(_, txs)| txs)
};
let txs = query(RetrieveTxQueryArgs::default())?;
assert!(!txs.is_empty());
let before_first_tx =
txs.iter().map(|tx| tx.creation_ts).min().unwrap() - Duration::from_secs(1);
let mut tx_query_args = RetrieveTxQueryArgs::default();
// Max creation time before all test transactions
tx_query_args.max_creation_timestamp = Some(before_first_tx);
assert!(query(tx_query_args.clone())?.is_empty());
// Max creation time before all test transactions
tx_query_args.max_creation_timestamp = Some(before_first_tx);
assert!(query(tx_query_args.clone())?.is_empty());
// Min confirmation time should not affect creation time
tx_query_args.max_creation_timestamp = None;
tx_query_args.min_confirmed_timestamp = Some(before_first_tx);
assert_eq!(query(tx_query_args)?.len(), txs.len());
// Min confirmation time should not affect creation time
tx_query_args.max_creation_timestamp = None;
tx_query_args.min_confirmed_timestamp = Some(before_first_tx);
assert_eq!(query(tx_query_args)?.len(), txs.len());
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.min_id = Some(5);
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.min_id = Some(5);
// Min ID
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results[0].id, 5);
assert_eq!(tx_results[tx_results.len() - 1].id, 33);
// Min ID
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results[0].id, 5);
assert_eq!(tx_results[tx_results.len() - 1].id, 33);
// Max ID
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.min_id = Some(5);
tx_query_args.max_id = Some(20);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results[0].id, 5);
assert_eq!(tx_results[tx_results.len() - 1].id, 20);
// Max ID
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.min_id = Some(5);
tx_query_args.max_id = Some(20);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results[0].id, 5);
assert_eq!(tx_results[tx_results.len() - 1].id, 20);
// Exclude 1 cancelled
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.exclude_cancelled = Some(true);
tx_query_args.min_id = Some(5);
tx_query_args.max_id = Some(50);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 28);
// Exclude 1 canceled
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.exclude_cancelled = Some(true);
tx_query_args.min_id = Some(5);
tx_query_args.max_id = Some(50);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 28);
// Exclude 1 cancelled, show confirmed only
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.exclude_cancelled = Some(true);
tx_query_args.include_confirmed_only = Some(true);
tx_query_args.min_id = Some(5);
tx_query_args.max_id = Some(50);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 14);
// Exclude 1 canceled, show confirmed only
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.exclude_cancelled = Some(true);
tx_query_args.include_confirmed_only = Some(true);
tx_query_args.min_id = Some(5);
tx_query_args.max_id = Some(50);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 14);
// show outstanding only (including cancelled)
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.exclude_cancelled = Some(false);
tx_query_args.include_outstanding_only = Some(true);
tx_query_args.min_id = Some(5);
tx_query_args.max_id = Some(50);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 15);
// show outstanding only (including canceled)
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.exclude_cancelled = Some(false);
tx_query_args.include_outstanding_only = Some(true);
tx_query_args.min_id = Some(5);
tx_query_args.max_id = Some(50);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 15);
// outstanding only and confirmed only should give empty set
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.exclude_cancelled = Some(false);
tx_query_args.include_outstanding_only = Some(true);
tx_query_args.include_confirmed_only = Some(true);
tx_query_args.min_id = Some(5);
tx_query_args.max_id = Some(50);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 0);
// outstanding only and confirmed only should give empty set
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.exclude_cancelled = Some(false);
tx_query_args.include_outstanding_only = Some(true);
tx_query_args.include_confirmed_only = Some(true);
tx_query_args.min_id = Some(5);
tx_query_args.max_id = Some(50);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 0);
// include sent only
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.include_sent_only = Some(true);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 15);
// include sent only
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.include_sent_only = Some(true);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 15);
// include received only (none in this set)
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.include_received_only = Some(true);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 0);
// include received only (none in this set)
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.include_received_only = Some(true);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 0);
// include reverted only (none in this set)
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.include_reverted_only = Some(true);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 0);
// include reverted only (none in this set)
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.include_reverted_only = Some(true);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 0);
// include coinbase only
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.include_coinbase_only = Some(true);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 19);
// include coinbase only
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.include_coinbase_only = Some(true);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 19);
// Amounts
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.min_amount = Some(60_000_000_000 - 59_963_300_000);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 27);
// Amounts
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.min_amount = Some(60_000_000_000 - 59_963_300_000);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 27);
// amount, should see as above with coinbases excluded
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.min_amount = Some(60_000_000_000 - 59_963_300_000);
tx_query_args.max_amount = Some(60_000_000_000 - 1);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 8);
// amount, should see as above with coinbases excluded
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.min_amount = Some(60_000_000_000 - 59_963_300_000);
tx_query_args.max_amount = Some(60_000_000_000 - 1);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 8);
// Amount - should only see coinbase (incoming)
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.min_amount = Some(60_000_000_000);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 19);
// Amount - should only see coinbase (incoming)
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.min_amount = Some(60_000_000_000);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results.len(), 19);
// sort order
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.sort_order = Some(libwallet::RetrieveTxQuerySortOrder::Desc);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
// sort order
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.sort_order = Some(libwallet::RetrieveTxQuerySortOrder::Desc);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results[0].id, 33);
assert_eq!(tx_results[tx_results.len() - 1].id, 0);
assert_eq!(tx_results[0].id, 33);
assert_eq!(tx_results[tx_results.len() - 1].id, 0);
// change sort field to amount desc, should have coinbases first
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.sort_order = Some(libwallet::RetrieveTxQuerySortOrder::Desc);
tx_query_args.sort_field = Some(RetrieveTxQuerySortField::TotalAmount);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results[0].amount_credited, 60_000_000_000);
/*for entry in tx_results.iter() {
println!("{:?}", entry);
}*/
Ok(())
},
)?;
// change sort field to amount desc, should have coinbases first
let mut tx_query_args = RetrieveTxQueryArgs::default();
tx_query_args.sort_order = Some(libwallet::RetrieveTxQuerySortOrder::Desc);
tx_query_args.sort_field = Some(RetrieveTxQuerySortField::TotalAmount);
let tx_results = api
.retrieve_txs(mask, true, None, None, Some(tx_query_args))?
.1;
assert_eq!(tx_results[0].amount_credited, 60_000_000_000);
Ok(())
}
@@ -248,7 +221,8 @@ fn build_chain_for_tx_filtering(
"wallet1",
None,
&mut wallet_proxy,
true
true,
api1
);
let mask1 = (&mask1_i).as_ref();
debug!("Mask1: {:?}", mask1);
@@ -260,7 +234,8 @@ fn build_chain_for_tx_filtering(
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
debug!("Mask2: {:?}", mask2);
@@ -274,25 +249,8 @@ fn build_chain_for_tx_filtering(
// Stop the scanning updater threads because it extends the time needed to build the chain
// exponentially
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, _m| {
api.stop_updater()?;
Ok(())
},
)?;
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, _m| {
api.stop_updater()?;
Ok(())
},
)?;
api1.stop_updater()?;
api2.stop_updater()?;
// few values to keep things shorter
let reward = core::consensus::REWARD;
@@ -304,22 +262,14 @@ fn build_chain_for_tx_filtering(
let mut wallet_1_has_funds = false;
// Check wallet 1 contents
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
debug!(
"Wallet 1 spendable - {}",
wallet1_info.amount_currently_spendable
);
if wallet1_info.amount_currently_spendable > reward {
wallet_1_has_funds = true;
}
Ok(())
},
)?;
let (_, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
debug!(
"Wallet 1 spendable - {}",
wallet1_info.amount_currently_spendable
);
if wallet1_info.amount_currently_spendable > reward {
wallet_1_has_funds = true;
}
if !wallet_1_has_funds {
let _ =
@@ -331,62 +281,44 @@ fn build_chain_for_tx_filtering(
let num_txs = 1;
for _ in 0..num_txs {
let amount: u64 = i as u64 * 1_000_000;
let mut slate = Slate::blank(1, false);
debug!("Creating TX for {}", amount);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|sender_api, m| {
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount: amount,
minimum_confirmations: 1,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
let slate_i = sender_api.init_send_tx(m, args)?;
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
sender_api.tx_lock_outputs(m, &slate)?;
slate = sender_api.finalize_tx(m, &slate)?;
Ok(())
},
)?;
}
}
// Cancel a tx for filtering testing
let amount: u64 = 1_000_000;
let mut slate = Slate::blank(1, false);
debug!("Creating TX for {}", amount);
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|sender_api, m| {
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount: amount,
amount,
minimum_confirmations: 1,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
let slate_i = sender_api.init_send_tx(m, args)?;
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
sender_api.tx_lock_outputs(m, &slate)?;
sender_api.cancel_tx(m, Some(33), None)?;
Ok(())
},
)?;
let slate_i = api1.init_send_tx(mask1, args)?;
let slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
api1.tx_lock_outputs(mask1, &slate)?;
api1.finalize_tx(mask1, &slate)?;
}
}
// Cancel a tx for filtering testing
let amount: u64 = 1_000_000;
debug!("Creating TX for {}", amount);
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
src_acct_name: None,
amount,
minimum_confirmations: 1,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
let slate_i = api1.init_send_tx(mask1, args)?;
let slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
api1.tx_lock_outputs(mask1, &slate)?;
api1.cancel_tx(mask1, Some(33), None)?;
// Perform actual testing
test_wallet_tx_filtering(wallet1, mask1, test_dir)?;
test_wallet_tx_filtering(mask1, api1)?;
// let logging finish
stopper.store(false, Ordering::Relaxed);
+8 -23
View File
@@ -46,7 +46,8 @@ fn updater_thread_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
"wallet1",
None,
&mut wallet_proxy,
false
false,
api1
);
let mask1 = (&mask1_i).as_ref();
create_wallet_and_add!(
@@ -57,7 +58,8 @@ fn updater_thread_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
"wallet2",
None,
&mut wallet_proxy,
false
false,
api2
);
let mask2 = (&mask2_i).as_ref();
@@ -69,28 +71,11 @@ fn updater_thread_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
});
// add some accounts
wallet::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "mining")?;
api.create_account_path(m, "listener")?;
Ok(())
},
)?;
api1.create_account_path(mask1, "mining")?;
api1.create_account_path(mask1, "listener")?;
// add some accounts
wallet::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
api.create_account_path(m, "account1")?;
api.create_account_path(m, "account2")?;
Ok(())
},
)?;
api2.create_account_path(mask2, "account1")?;
api2.create_account_path(mask2, "account2")?;
// Get some mining done
{
+1 -1
View File
@@ -124,7 +124,7 @@ impl TorSlateSender {
let res: String = self.post(url, req).map_err(|e| {
let mut report = format!("Performing version check (is recipient listening?): {}", e);
let err_string = format!("{}", e);
if err_string.contains("404") {
if !self.config.use_integrated.unwrap_or(false) && err_string.contains("404") {
// Report that the other version of the wallet is out of date
report = "Other wallet is incompatible and requires an upgrade. \
Please urge the other wallet owner to upgrade and try the transaction again."
+1 -1
View File
@@ -366,7 +366,7 @@ impl From<ser::Error> for OnionError {
}
#[cfg(test)]
pub mod tests {
mod tests {
use super::*;
use crate::mwixnet::onion::crypto::secp::random_secret;
use crate::mwixnet::onion::{new_hop, Hop};
+129 -119
View File
@@ -21,9 +21,9 @@ extern crate log;
extern crate grin_wallet;
use grin_wallet_impls::test_framework::{self, LocalWalletClient, WalletProxy};
use std::path::PathBuf;
use clap::App;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
@@ -32,9 +32,23 @@ use grin_wallet_impls::DefaultLCProvider;
mod common;
use common::{clean_output_dir, execute_command, initial_setup_wallet, instantiate_wallet, setup};
use grin_wallet_api::Owner;
use grin_wallet_libwallet::{OutputStatus, TxLogEntryType};
/// command line tests
fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::Error> {
let (logs_tx, logs_rx) = mpsc::sync_channel(100);
let panic_hook = std::panic::take_hook();
grin_util::init_logger(
Some(grin_util::logger::LoggingConfig {
log_to_file: false,
stdout_log_level: log::Level::Error,
tui_running: Some(true),
..Default::default()
}),
Some(logs_tx),
);
std::panic::set_hook(panic_hook);
setup(test_dir);
// Create a new proxy to simulate server and wallet responses
let mut wallet_proxy: WalletProxy<
@@ -158,15 +172,9 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
let (wallet1, mask1_i) =
instantiate_wallet(wallet_config1, client1.clone(), "password1", "default")?;
let mask1 = (&mask1_i).as_ref();
grin_wallet_controller::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.set_active_account(m, "mining")?;
Ok(())
},
)?;
let api1 = Owner::new(wallet1.clone(), None, config1.config_file_path.clone());
api1.set_active_account(mask1, "mining")?;
let mut bh = 10u64;
let _ =
@@ -236,23 +244,16 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
"default",
)?;
let mask1 = (&mask1_i).as_ref();
let api1 = Owner::new(wallet1.clone(), None, config1.config_file_path.clone());
// Check our transaction log, should have 10 entries
grin_wallet_controller::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.set_active_account(m, "mining")?;
let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert!(refreshed);
assert_eq!(txs.len(), bh as usize);
for t in txs {
assert!(t.kernel_excess.is_some());
}
Ok(())
},
)?;
api1.set_active_account(mask1, "mining")?;
let (refreshed, txs) = api1.retrieve_txs(mask1, true, None, None, None)?;
assert!(refreshed);
assert_eq!(txs.len(), bh as usize);
for t in txs {
assert!(t.kernel_excess.is_some());
}
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 10, false);
bh += 10;
@@ -273,33 +274,17 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
"default",
)?;
let mask2 = (&mask2_i).as_ref();
let api2 = Owner::new(wallet2.clone(), None, config2.config_file_path.clone());
grin_wallet_controller::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
api.set_active_account(m, "account_1")?;
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.amount_currently_spendable, 10_000_000_000);
Ok(())
},
)?;
api2.set_active_account(mask2, "account_1")?;
let (_, wallet1_info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert_eq!(wallet1_info.last_confirmed_height, bh);
assert_eq!(wallet1_info.amount_currently_spendable, 10_000_000_000);
// Send to wallet 2 with --amount_includes_fee
let mut old_balance = 0;
grin_wallet_controller::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.set_active_account(m, "mining")?;
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
old_balance = wallet1_info.amount_currently_spendable;
Ok(())
},
)?;
api1.set_active_account(mask1, "mining")?;
let (_, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
let old_balance = wallet1_info.amount_currently_spendable;
let arg_vec = vec![
"grin-wallet",
"-p",
@@ -349,22 +334,14 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
// Check the new balance of wallet 1 reduced by EXACTLY the tx amount (instead of amount + fee)
// This confirms that the TX amount was correctly computed to allow for the fee
grin_wallet_controller::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.set_active_account(m, "mining")?;
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
// make sure the new balance is exactly equal to the old balance - the tx amount + the amount mined since then
let amt_mined = 10 * 60_000_000_000;
assert_eq!(
wallet1_info.amount_currently_spendable + 10_000_000_000,
old_balance + amt_mined
);
Ok(())
},
)?;
api1.set_active_account(mask1, "mining")?;
let (_, wallet1_info) = api1.retrieve_summary_info(mask1, true, 1)?;
// make sure the new balance is exactly equal to the old balance - the tx amount + the amount mined since then
let amt_mined = 10 * 60_000_000_000;
assert_eq!(
wallet1_info.amount_currently_spendable + 10_000_000_000,
old_balance + amt_mined
);
// Send encrypted from wallet 1 to wallet 2
// output wallet 2's address for test creation purposes,
@@ -435,19 +412,12 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
"default",
)?;
let mask1 = (&mask1_i).as_ref();
let api1 = Owner::new(wallet1.clone(), None, config1.config_file_path.clone());
grin_wallet_controller::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.set_active_account(m, "mining")?;
let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert!(refreshed);
assert_eq!(txs.len(), bh as usize);
Ok(())
},
)?;
api1.set_active_account(mask1, "mining")?;
let (refreshed, txs) = api1.retrieve_txs(mask1, true, None, None, None)?;
assert!(refreshed);
assert_eq!(txs.len(), bh as usize);
// Send to self
let arg_vec = vec![
@@ -508,19 +478,12 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
"default",
)?;
let mask1 = (&mask1_i).as_ref();
let api1 = Owner::new(wallet1.clone(), None, config1.config_file_path.clone());
grin_wallet_controller::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.set_active_account(m, "mining")?;
let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?;
assert!(refreshed);
assert_eq!(txs.len(), bh as usize + 1);
Ok(())
},
)?;
api1.set_active_account(mask1, "mining")?;
let (refreshed, txs) = api1.retrieve_txs(mask1, true, None, None, None)?;
assert!(refreshed);
assert_eq!(txs.len(), bh as usize + 1);
// Another file exchange, don't send, but unlock with repair command
let arg_vec = vec![
@@ -649,24 +612,15 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
execute_command(&app, test_dir, "wallet2", &client2, arg_vec)?;
// get tx output via -tx parameter
let mut tx_id = "".to_string();
grin_wallet_controller::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
api.set_active_account(m, "default")?;
let (_, txs) = api.retrieve_txs(m, true, None, None, None)?;
let some_tx_id = txs[0].tx_slate_id.clone();
assert!(some_tx_id.is_some());
tx_id = some_tx_id.unwrap().to_string().clone();
Ok(())
},
)?;
api2.set_active_account(mask2, "default")?;
let (_, txs) = api2.retrieve_txs(mask2, true, None, None, None)?;
let some_tx_id = txs[0].tx_slate_id.clone();
assert!(some_tx_id.is_some());
let tx_id = some_tx_id.unwrap().to_string().clone();
let arg_vec = vec!["grin-wallet", "-p", "password2", "txs", "-t", &tx_id[..]];
execute_command(&app, test_dir, "wallet2", &client2, arg_vec)?;
// bit of mining
// a bit of mining
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 10, false);
// Test wallet sweep
@@ -717,21 +671,77 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
// Check wallet 1 is now empty, except for immature coinbase outputs from recent mining),
// and recently matured coinbase outputs, which were not mature at time of spending.
// This confirms that the TX amount was correctly computed to allow for the fee
grin_wallet_controller::controller::owner_single_use(
wallet1.clone(),
mask1,
PathBuf::from(test_dir),
|api, m| {
api.set_active_account(m, "mining")?;
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 10)?;
// Entire 'spendable' wallet balance should have been swept, except the coinbase outputs
// which matured in the last batch of mining. Check that the new spendable balance is
// exactly equal to those matured coins.
let amt_mined = 10 * 60_000_000_000;
assert_eq!(wallet1_info.amount_currently_spendable, amt_mined);
Ok(())
},
)?;
api1.set_active_account(mask1, "mining")?;
let (_, wallet1_info) = api1.retrieve_summary_info(mask1, true, 10)?;
// Entire 'spendable' wallet balance should have been swept, except the coinbase outputs
// which matured in the last batch of mining. Check that the new spendable balance is
// exactly equal to those matured coins.
let amt_mined = 10 * 60_000_000_000;
assert_eq!(wallet1_info.amount_currently_spendable, amt_mined);
// Failed send, with --late-lock, make sure outputs not locked (amount not changed).
api2.set_active_account(mask2, "account_1")?;
let (_, txs_before) = api2.retrieve_txs(mask2, false, None, None, None)?;
let (_, wallet1_info) = api2.retrieve_summary_info(mask2, true, 1)?;
let old_balance = wallet1_info.amount_currently_spendable;
let mut arg_vec = vec![
"grin-wallet",
"-p",
"password2",
"-a",
"account_1",
"send",
"-d",
"tgrin1xtxavwfgs48ckf3gk8wwgcndmn0nt4tvkl8a7ltyejjcy2mc6nfs9gm2lp",
"1",
"--late-lock",
];
let args = app.clone().get_matches_from(arg_vec.clone());
let mut config = initial_setup_wallet(test_dir, "wallet2");
config.members.tor = Some(grin_wallet_config::TorConfig {
use_integrated: Some(false),
socks_proxy_addr: "invalid".into(),
..Default::default()
});
let send = |args: &clap::ArgMatches| -> Result<(), grin_wallet_controller::Error> {
logs_rx.try_iter().for_each(drop);
grin_wallet::cmd::wallet_args::wallet_command(
args,
config.clone(),
client2.clone(),
false,
|_| {},
)?;
assert!(logs_rx.try_iter().any(|entry| {
entry.log.contains("Error sending slate sync:") && entry.log.contains("AddrParseError")
}));
Ok(())
};
send(&args)?;
api2.set_active_account(mask2, "account_1")?;
let (_, txs_after) = api2.retrieve_txs(mask2, false, None, None, None)?;
assert_eq!(txs_before.len(), txs_after.len());
let (_, wallet1_info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert_eq!(old_balance, wallet1_info.amount_currently_spendable);
// The same failure without late locking leaves one transaction and locked outputs
arg_vec.pop();
let args = app.clone().get_matches_from(arg_vec);
send(&args)?;
let (_, txs_after) = api2.retrieve_txs(mask2, false, None, None, None)?;
assert_eq!(txs_after.len(), txs_before.len() + 1);
let tx = txs_after
.iter()
.find(|tx| !txs_before.iter().any(|before| before.id == tx.id))
.unwrap();
assert_eq!(tx.tx_type, TxLogEntryType::TxSent);
assert!(tx.tx_slate_id.is_some());
let (_, outputs) = api2.retrieve_outputs(mask2, false, false, Some(tx.id))?;
assert!(outputs
.iter()
.any(|output| output.output.status == OutputStatus::Locked));
let (_, wallet_info) = api2.retrieve_summary_info(mask2, true, 1)?;
assert!(wallet_info.amount_currently_spendable < old_balance);
// let logging finish
thread::sleep(Duration::from_millis(200));
+17 -24
View File
@@ -19,7 +19,7 @@ extern crate log;
extern crate grin_wallet;
use grin_wallet_api::{ECDHPubkey, JsonId};
use grin_wallet_api::{ECDHPubkey, JsonId, Owner};
use grin_wallet_impls::test_framework::{self, LocalWalletClient, WalletProxy};
use clap::App;
@@ -64,7 +64,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
>,
>,
> = Arc::new(Mutex::new(WalletProxy::new(test_dir)));
let (chain, wallet2, mask2_i) = {
let (chain, wallet2, mask2_i, config2) = {
let mut wallet_proxy = wallet_proxy_a.lock();
let chain = wallet_proxy.chain.clone();
@@ -118,7 +118,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
)
.unwrap();
});
(chain, wallet2, mask2_i)
(chain, wallet2, mask2_i, config2)
};
// give a bit for wallet to init and populate proxy with wallet via callback in thread above
thread::sleep(Duration::from_millis(500));
@@ -402,27 +402,20 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
let mut slate: Slate = res.unwrap().into();
// give this slate over to wallet 2 manually
grin_wallet_controller::controller::owner_single_use(
wallet2.clone(),
mask2,
PathBuf::from(test_dir),
|api, m| {
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 1,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
let res = api.process_invoice_tx(m, &slate, args);
assert!(res.is_ok());
slate = res.unwrap();
api.tx_lock_outputs(m, &slate)?;
Ok(())
},
)?;
let api2 = Owner::new(wallet2.clone(), None, config2.config_file_path.clone());
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: 1,
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
let res = api2.process_invoice_tx(mask2, &slate, args);
assert!(res.is_ok());
slate = res?;
api2.tx_lock_outputs(mask2, &slate)?;
//16) Finalize the invoice tx (to foreign api)
// (Tests that foreign API on same port also has its stored mask updated)