mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-11-10 17:53:53 +01:00
Lock outputs before sending with Tor (#814)
Co-authored-by: wiesche <wiesche89@googlemail.com>
(cherry picked from commit 452a3ec51b)
This commit is contained in:
+43
-30
@@ -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.
|
||||
///
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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));
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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, ¶ms, &last_output.commit, true)?;
|
||||
let mwixnet_req = api1.create_mwixnet_req(mask1, ¶ms, &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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
+510
-598
File diff suppressed because it is too large
Load Diff
+53
-102
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user