mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 11:31:08 +03:00
Fixes to grin wallet repost
, cancel tx (#2029)
* fixes to wallet cancel, repost, ensure stored transaction is updated with final signatures * rustfmt * add tests for reposting * fixes to tests * repost
This commit is contained in:
parent
79d540cf86
commit
b95caecc27
9 changed files with 314 additions and 23 deletions
|
@ -453,11 +453,12 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) -> i
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
api.tx_lock_outputs(&slate, lock_fn)?;
|
||||||
api.finalize_tx(&mut slate)?;
|
api.finalize_tx(&mut slate)?;
|
||||||
} else {
|
} else {
|
||||||
adapter.send_tx_async(dest, &slate)?;
|
adapter.send_tx_async(dest, &slate)?;
|
||||||
}
|
|
||||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
api.tx_lock_outputs(&slate, lock_fn)?;
|
||||||
|
}
|
||||||
if adapter.supports_sync() {
|
if adapter.supports_sync() {
|
||||||
let result = api.post_tx(&slate, fluff);
|
let result = api.post_tx(&slate, fluff);
|
||||||
match result {
|
match result {
|
||||||
|
|
|
@ -222,9 +222,11 @@ where
|
||||||
/// propagation.
|
/// propagation.
|
||||||
pub fn finalize_tx(&mut self, slate: &mut Slate) -> Result<(), Error> {
|
pub fn finalize_tx(&mut self, slate: &mut Slate) -> Result<(), Error> {
|
||||||
let mut w = self.wallet.lock();
|
let mut w = self.wallet.lock();
|
||||||
|
let parent_key_id = w.parent_key_id();
|
||||||
w.open_with_credentials()?;
|
w.open_with_credentials()?;
|
||||||
let context = w.get_private_context(slate.id.as_bytes())?;
|
let context = w.get_private_context(slate.id.as_bytes())?;
|
||||||
tx::complete_tx(&mut *w, slate, &context)?;
|
tx::complete_tx(&mut *w, slate, &context)?;
|
||||||
|
tx::update_tx_hex(&mut *w, &parent_key_id, slate)?;
|
||||||
{
|
{
|
||||||
let mut batch = w.batch()?;
|
let mut batch = w.batch()?;
|
||||||
batch.delete_private_context(slate.id.as_bytes())?;
|
batch.delete_private_context(slate.id.as_bytes())?;
|
||||||
|
@ -367,24 +369,14 @@ where
|
||||||
);
|
);
|
||||||
return Err(ErrorKind::TransactionBuildingNotCompleted(tx_id))?;
|
return Err(ErrorKind::TransactionBuildingNotCompleted(tx_id))?;
|
||||||
}
|
}
|
||||||
|
client.post_tx(
|
||||||
let res = client.post_tx(
|
|
||||||
&TxWrapper {
|
&TxWrapper {
|
||||||
tx_hex: tx_hex.unwrap(),
|
tx_hex: tx_hex.unwrap(),
|
||||||
},
|
},
|
||||||
fluff,
|
fluff,
|
||||||
);
|
)?;
|
||||||
if let Err(e) = res {
|
|
||||||
error!("api: repost_tx: failed with error: {}", e);
|
|
||||||
Err(e)
|
|
||||||
} else {
|
|
||||||
debug!(
|
|
||||||
"api: repost_tx: successfully posted tx at: {}, fluff? {}",
|
|
||||||
tx_id, fluff
|
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempt to restore contents of wallet
|
/// Attempt to restore contents of wallet
|
||||||
pub fn restore(&mut self) -> Result<(), Error> {
|
pub fn restore(&mut self) -> Result<(), Error> {
|
||||||
|
|
|
@ -195,7 +195,19 @@ pub enum ErrorKind {
|
||||||
|
|
||||||
impl Display for Error {
|
impl Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
Display::fmt(&self.inner, f)
|
let cause = match self.cause() {
|
||||||
|
Some(c) => format!("{}", c),
|
||||||
|
None => String::from("Unknown"),
|
||||||
|
};
|
||||||
|
let backtrace = match self.backtrace() {
|
||||||
|
Some(b) => format!("{}", b),
|
||||||
|
None => String::from("Unknown"),
|
||||||
|
};
|
||||||
|
let output = format!(
|
||||||
|
"{} \n Cause: {} \n Backtrace: {}",
|
||||||
|
self.inner, cause, backtrace
|
||||||
|
);
|
||||||
|
Display::fmt(&output, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,12 @@
|
||||||
//! Transaction building functions
|
//! Transaction building functions
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use util::RwLock;
|
use util::{self, RwLock};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use core::core::verifier_cache::LruVerifierCache;
|
use core::core::verifier_cache::LruVerifierCache;
|
||||||
use core::core::Transaction;
|
use core::core::Transaction;
|
||||||
|
use core::ser;
|
||||||
use keychain::{Identifier, Keychain};
|
use keychain::{Identifier, Keychain};
|
||||||
use libtx::slate::Slate;
|
use libtx::slate::Slate;
|
||||||
use libtx::{build, tx_fee};
|
use libtx::{build, tx_fee};
|
||||||
|
@ -206,6 +207,30 @@ where
|
||||||
Ok((tx.confirmed, tx.tx_hex))
|
Ok((tx.confirmed, tx.tx_hex))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the stored hex transaction (this update needs to happen when the TX is finalised)
|
||||||
|
pub fn update_tx_hex<T: ?Sized, C, K>(
|
||||||
|
wallet: &mut T,
|
||||||
|
parent_key_id: &Identifier,
|
||||||
|
slate: &Slate,
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
T: WalletBackend<C, K>,
|
||||||
|
C: NodeClient,
|
||||||
|
K: Keychain,
|
||||||
|
{
|
||||||
|
let tx_hex = util::to_hex(ser::ser_vec(&slate.tx).unwrap());
|
||||||
|
let tx_vec = updater::retrieve_txs(wallet, None, Some(slate.id), parent_key_id)?;
|
||||||
|
if tx_vec.len() != 1 {
|
||||||
|
return Err(ErrorKind::TransactionDoesntExist(slate.id.to_string()))?;
|
||||||
|
}
|
||||||
|
let mut tx = tx_vec[0].clone();
|
||||||
|
tx.tx_hex = Some(tx_hex);
|
||||||
|
let batch = wallet.batch()?;
|
||||||
|
batch.save_tx_log_entry(tx, &parent_key_id)?;
|
||||||
|
batch.commit()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Issue a burn tx
|
/// Issue a burn tx
|
||||||
pub fn issue_burn_tx<T: ?Sized, C, K>(
|
pub fn issue_burn_tx<T: ?Sized, C, K>(
|
||||||
wallet: &mut T,
|
wallet: &mut T,
|
||||||
|
|
|
@ -91,7 +91,9 @@ where
|
||||||
{
|
{
|
||||||
// just read the wallet here, no need for a write lock
|
// just read the wallet here, no need for a write lock
|
||||||
let mut txs = if let Some(id) = tx_id {
|
let mut txs = if let Some(id) = tx_id {
|
||||||
let tx = wallet.tx_log_iter().find(|t| t.id == id);
|
let tx = wallet
|
||||||
|
.tx_log_iter()
|
||||||
|
.find(|t| t.id == id && t.parent_key_id == *parent_key_id);
|
||||||
if let Some(t) = tx {
|
if let Some(t) = tx {
|
||||||
vec![t]
|
vec![t]
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -192,8 +192,8 @@ fn accounts_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
true, // select all outputs
|
true, // select all outputs
|
||||||
)?;
|
)?;
|
||||||
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
|
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
|
||||||
api.finalize_tx(&mut slate)?;
|
|
||||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
api.tx_lock_outputs(&slate, lock_fn)?;
|
||||||
|
api.finalize_tx(&mut slate)?;
|
||||||
api.post_tx(&slate, false)?;
|
api.post_tx(&slate, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
259
wallet/tests/repost.rs
Normal file
259
wallet/tests/repost.rs
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
// Copyright 2018 The Grin Developers
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
//! Test a wallet repost command
|
||||||
|
extern crate grin_chain as chain;
|
||||||
|
extern crate grin_core as core;
|
||||||
|
extern crate grin_keychain as keychain;
|
||||||
|
extern crate grin_store as store;
|
||||||
|
extern crate grin_util as util;
|
||||||
|
extern crate grin_wallet as wallet;
|
||||||
|
extern crate rand;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
extern crate chrono;
|
||||||
|
extern crate serde;
|
||||||
|
extern crate uuid;
|
||||||
|
|
||||||
|
mod common;
|
||||||
|
use common::testclient::{LocalWalletClient, WalletProxy};
|
||||||
|
|
||||||
|
use std::fs;
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use core::global;
|
||||||
|
use core::global::ChainTypes;
|
||||||
|
use keychain::ExtKeychain;
|
||||||
|
use wallet::libtx::slate::Slate;
|
||||||
|
use wallet::{libwallet, FileWalletCommAdapter};
|
||||||
|
|
||||||
|
fn clean_output_dir(test_dir: &str) {
|
||||||
|
let _ = fs::remove_dir_all(test_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(test_dir: &str) {
|
||||||
|
util::init_test_logger();
|
||||||
|
clean_output_dir(test_dir);
|
||||||
|
global::set_mining_mode(ChainTypes::AutomatedTesting);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// self send impl
|
||||||
|
fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
|
setup(test_dir);
|
||||||
|
// Create a new proxy to simulate server and wallet responses
|
||||||
|
let mut wallet_proxy: WalletProxy<LocalWalletClient, ExtKeychain> = WalletProxy::new(test_dir);
|
||||||
|
let chain = wallet_proxy.chain.clone();
|
||||||
|
|
||||||
|
let client1 = LocalWalletClient::new("wallet1", wallet_proxy.tx.clone());
|
||||||
|
let wallet1 = common::create_wallet(&format!("{}/wallet1", test_dir), client1.clone());
|
||||||
|
wallet_proxy.add_wallet("wallet1", client1.get_send_instance(), wallet1.clone());
|
||||||
|
|
||||||
|
let client2 = LocalWalletClient::new("wallet2", wallet_proxy.tx.clone());
|
||||||
|
let wallet2 = common::create_wallet(&format!("{}/wallet2", test_dir), client2.clone());
|
||||||
|
wallet_proxy.add_wallet("wallet2", client2.get_send_instance(), wallet2.clone());
|
||||||
|
|
||||||
|
// Set the wallet proxy listener running
|
||||||
|
thread::spawn(move || {
|
||||||
|
if let Err(e) = wallet_proxy.run() {
|
||||||
|
error!("Wallet Proxy error: {}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// few values to keep things shorter
|
||||||
|
let reward = core::consensus::REWARD;
|
||||||
|
|
||||||
|
// add some accounts
|
||||||
|
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||||
|
api.new_account_path("mining")?;
|
||||||
|
api.new_account_path("listener")?;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// add some accounts
|
||||||
|
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||||
|
api.new_account_path("account1")?;
|
||||||
|
api.new_account_path("account2")?;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Get some mining done
|
||||||
|
{
|
||||||
|
let mut w = wallet1.lock();
|
||||||
|
w.set_parent_key_id_by_name("mining")?;
|
||||||
|
}
|
||||||
|
let mut bh = 10u64;
|
||||||
|
let _ = common::award_blocks_to_wallet(&chain, wallet1.clone(), bh as usize);
|
||||||
|
|
||||||
|
let send_file = format!("{}/part_tx_1.tx", test_dir);
|
||||||
|
let receive_file = format!("{}/part_tx_2.tx", test_dir);
|
||||||
|
|
||||||
|
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
|
||||||
|
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||||
|
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||||
|
assert!(wallet1_refreshed);
|
||||||
|
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||||
|
assert_eq!(wallet1_info.total, bh * reward);
|
||||||
|
// send to send
|
||||||
|
let (mut slate, lock_fn) = api.initiate_tx(
|
||||||
|
Some("mining"),
|
||||||
|
reward * 2, // amount
|
||||||
|
2, // minimum confirmations
|
||||||
|
500, // max outputs
|
||||||
|
1, // num change outputs
|
||||||
|
true, // select all outputs
|
||||||
|
)?;
|
||||||
|
// output tx file
|
||||||
|
let file_adapter = FileWalletCommAdapter::new();
|
||||||
|
file_adapter.send_tx_async(&send_file, &mut slate)?;
|
||||||
|
api.tx_lock_outputs(&slate, lock_fn)?;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let _ = common::award_blocks_to_wallet(&chain, wallet1.clone(), 3);
|
||||||
|
bh += 3;
|
||||||
|
|
||||||
|
// wallet 1 receives file to different account, completes
|
||||||
|
{
|
||||||
|
let mut w = wallet1.lock();
|
||||||
|
w.set_parent_key_id_by_name("listener")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
wallet::controller::foreign_single_use(wallet1.clone(), |api| {
|
||||||
|
let adapter = FileWalletCommAdapter::new();
|
||||||
|
let mut slate = adapter.receive_tx_async(&send_file)?;
|
||||||
|
api.receive_tx(&mut slate, None)?;
|
||||||
|
adapter.send_tx_async(&receive_file, &mut slate)?;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// wallet 1 receives file to different account, completes
|
||||||
|
{
|
||||||
|
let mut w = wallet1.lock();
|
||||||
|
w.set_parent_key_id_by_name("mining")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut slate = Slate::blank(2);
|
||||||
|
// wallet 1 finalize
|
||||||
|
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||||
|
let adapter = FileWalletCommAdapter::new();
|
||||||
|
slate = adapter.receive_tx_async(&receive_file)?;
|
||||||
|
api.finalize_tx(&mut slate)?;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Now repost from cached
|
||||||
|
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||||
|
let (_, txs) = api.retrieve_txs(true, None, Some(slate.id))?;
|
||||||
|
api.post_stored_tx(txs[0].id, false)?;
|
||||||
|
bh += 1;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let _ = common::award_blocks_to_wallet(&chain, wallet1.clone(), 3);
|
||||||
|
bh += 3;
|
||||||
|
|
||||||
|
// update/test contents of both accounts
|
||||||
|
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||||
|
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||||
|
assert!(wallet1_refreshed);
|
||||||
|
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||||
|
assert_eq!(wallet1_info.total, bh * reward - reward * 2);
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut w = wallet1.lock();
|
||||||
|
w.set_parent_key_id_by_name("listener")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||||
|
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(true, 1)?;
|
||||||
|
assert!(wallet2_refreshed);
|
||||||
|
assert_eq!(wallet2_info.last_confirmed_height, bh);
|
||||||
|
assert_eq!(wallet2_info.total, 2 * reward);
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// as above, but syncronously
|
||||||
|
{
|
||||||
|
let mut w = wallet1.lock();
|
||||||
|
w.set_parent_key_id_by_name("mining")?;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut w = wallet2.lock();
|
||||||
|
w.set_parent_key_id_by_name("account1")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut slate = Slate::blank(2);
|
||||||
|
let amount = 60_000_000_000;
|
||||||
|
|
||||||
|
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||||
|
// note this will increment the block count as part of the transaction "Posting"
|
||||||
|
let (slate_i, lock_fn) = sender_api.initiate_tx(
|
||||||
|
None,
|
||||||
|
amount * 2, // amount
|
||||||
|
2, // minimum confirmations
|
||||||
|
500, // max outputs
|
||||||
|
1, // num change outputs
|
||||||
|
true, // select all outputs
|
||||||
|
)?;
|
||||||
|
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||||
|
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
||||||
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let _ = common::award_blocks_to_wallet(&chain, wallet1.clone(), 3);
|
||||||
|
bh += 3;
|
||||||
|
|
||||||
|
// Now repost from cached
|
||||||
|
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||||
|
let (_, txs) = api.retrieve_txs(true, None, Some(slate.id))?;
|
||||||
|
api.post_stored_tx(txs[0].id, false)?;
|
||||||
|
bh += 1;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let _ = common::award_blocks_to_wallet(&chain, wallet1.clone(), 3);
|
||||||
|
bh += 3;
|
||||||
|
//
|
||||||
|
// update/test contents of both accounts
|
||||||
|
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||||
|
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(true, 1)?;
|
||||||
|
assert!(wallet1_refreshed);
|
||||||
|
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||||
|
assert_eq!(wallet1_info.total, bh * reward - reward * 4);
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
wallet::controller::owner_single_use(wallet2.clone(), |api| {
|
||||||
|
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(true, 1)?;
|
||||||
|
assert!(wallet2_refreshed);
|
||||||
|
assert_eq!(wallet2_info.last_confirmed_height, bh);
|
||||||
|
assert_eq!(wallet2_info.total, 2 * amount);
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// let logging finish
|
||||||
|
thread::sleep(Duration::from_millis(200));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn wallet_file_repost() {
|
||||||
|
let test_dir = "test_output/file_repost";
|
||||||
|
if let Err(e) = file_repost_test_impl(test_dir) {
|
||||||
|
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap());
|
||||||
|
}
|
||||||
|
}
|
|
@ -238,8 +238,8 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
true, // select all outputs
|
true, // select all outputs
|
||||||
)?;
|
)?;
|
||||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
||||||
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
sender_api.post_tx(&slate, false)?;
|
sender_api.post_tx(&slate, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
@ -259,8 +259,8 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
true, // select all outputs
|
true, // select all outputs
|
||||||
)?;
|
)?;
|
||||||
slate = client1.send_tx_slate_direct("wallet3", &slate_i)?;
|
slate = client1.send_tx_slate_direct("wallet3", &slate_i)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
||||||
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
sender_api.post_tx(&slate, false)?;
|
sender_api.post_tx(&slate, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
@ -280,8 +280,8 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
true, // select all outputs
|
true, // select all outputs
|
||||||
)?;
|
)?;
|
||||||
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
||||||
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
sender_api.post_tx(&slate, false)?;
|
sender_api.post_tx(&slate, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
@ -307,8 +307,8 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
true, // select all outputs
|
true, // select all outputs
|
||||||
)?;
|
)?;
|
||||||
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
||||||
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
sender_api.post_tx(&slate, false)?;
|
sender_api.post_tx(&slate, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
|
@ -112,8 +112,8 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
true, // select all outputs
|
true, // select all outputs
|
||||||
)?;
|
)?;
|
||||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
||||||
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue