Compact slate merge (#404)

* Add support for sending compact slates (#366)

* WIP add support for sending compact slates

* add repopulate_tx function to internal API

* first pass at compacted slate working

* move slate compaction to separate function

* test fixes

* support compact slate inits in invoice workflow

* add compress flags to send and invoice

* attempting to remove is_compact and assume all V4 slates begin as compact

* attempting to calculate offsets when full tx data isn't available

* update calc_commit to use participant blind data

* update doctests for compact slates

* start to remove unneeded fields from serialization

* make num_participants optional

* remove other_version from slate

* use grin master branch

* remove message field

* lock height assumed to be 0 if it doesn't exist

* don't serialise receiver signature when null

* don't serialize payment_info if not needed

* remove participant id from participant info

* add note on id field

* fix finalize and receive doctests

* finalize_tx tests, init_send_tx tests

* doctests for process_invoice_tx, retrieve_tx, tx_lock_outputs

* finished test changes

* update from grin master

* rebuild PR from diff (#380)

* recreate PR from diff (#381)

* serialize tx struct into top level coms object (#382)

* remove height (#383)

* Add State Slate (#384)

* add state field to slate and SlateV4

* set slate state at each transaction stage, add check to tests

* serialize slate status properly

* V4 Slate field tweaks (#386)

* various tweaks to V4 slate

* field renaming

* serialize slate v4 ID as base64 (#387)

* remove amount and fee where not needed (#388)

* Final Changes for compact Slate (#389)

* add tests for all types of file output, remove message args

* default range proof serialization

* shorten output features serialization

* rename payment proof fields in slate v4

* v4 payment proof serialization

* Binary Slates (#385)

* start test implementation

* add experimental binary serialization to slate

* serialize id

* serialize fields that can be skipped as a separate struct

* factor out sigs serialization

* clean up sigs and coms serialization

* completed v4 bin serialization

* add manual de/ser traits for V4 bin slate

* add simple byte array serializer

* complete wiring in of bin slate serialization

* clarify comment

* clarify comment

* update version

* test output dir name fix

* update slate v4 change description

* add binary output to command line

* Remove unneeded signature data during S2 and I2 stages (#390)

* remove unneeded return signature data during S2

* remove unneeded sig data from I2

* Doctest Fixes for compact slate branch (#392)

* begin to fix doctests

* more doctest fixes

* fix receive_tx

* update get_stored_tx to accept an UUID instead of a tx object, and operate on a raw Transaction object (#394)

* Fixes to async transaction posting (#395)

* unstash post_tx changes

* add offset during S3 and I3

* Revert slate id serialization to hex-string uuid (#396)

* update from master (#397)

* v3.x.x - v4.0.0 wallet compatibility fixes (#398)

* changes to support http sending to v3 wallets

* sending via http/tor TO 3.0.0 wallet works

* receiving FROM 3.0.0 wallets works over http/tor

* output converted V3 slate when needed

* paying invoices from 3.0.0 wallets working

* handle all participant info in slate states

* sending and receiving standard file transactions between v3 and 4 wallets confirmed working

* all file-based workflows working

* fixes resulting from tests

* remove reminder warnings

* remove lock_height, add kernel_features + arguments (#399)

* grin-wallet master now building against grin master (#402) (#403)

Co-authored-by: Antioch Peverell <apeverell@protonmail.com>

* Enhanced offset creation (#407)

* initial tests reworking offset creation

* invoice flow fixing + tests

* further test fixes

* change offset name in v4 slate, base64 serialize

* logic optimisation

* changes based on review feedback

Co-authored-by: Antioch Peverell <apeverell@protonmail.com>
This commit is contained in:
Yeastplume
2020-05-19 11:19:03 +01:00
committed by GitHub
co-authored by Antioch Peverell
parent 19da1e4aec
commit 9450d2a3b8
49 changed files with 5124 additions and 3800 deletions
+117 -62
View File
@@ -20,10 +20,11 @@ use crate::config::{TorConfig, WalletConfig, WALLET_CONFIG_FILE_NAME};
use crate::core::{core, global};
use crate::error::{Error, ErrorKind};
use crate::impls::{create_sender, KeybaseAllChannels, SlateGetter as _, SlateReceiver as _};
use crate::impls::{PathToSlate, SlatePutter};
use crate::impls::{HttpSlateSender, PathToSlate, SlatePutter};
use crate::keychain;
use crate::libwallet::{
self, InitTxArgs, IssueInvoiceTxArgs, NodeClient, PaymentProof, WalletLCProvider,
self, InitTxArgs, IssueInvoiceTxArgs, NodeClient, PaymentProof, Slate, SlateVersion,
WalletLCProvider,
};
use crate::util::secp::key::SecretKey;
use crate::util::{Mutex, ZeroingString};
@@ -266,7 +267,6 @@ where
/// Arguments for the send command
pub struct SendArgs {
pub amount: u64,
pub message: Option<String>,
pub minimum_confirmations: u64,
pub selection_strategy: String,
pub estimate_selection_strategies: bool,
@@ -278,6 +278,8 @@ pub struct SendArgs {
pub target_slate_version: Option<u16>,
pub payment_proof_address: Option<OnionV3Address>,
pub ttl_blocks: Option<u64>,
//TODO: Remove HF3
pub output_v4_slate: bool,
}
pub fn send<L, C, K>(
@@ -293,6 +295,60 @@ where
K: keychain::Keychain + 'static,
{
let wallet_inst = owner_api.wallet_inst.clone();
// Check other version, and if it only supports 3 set the target slate
// version to 3 to avoid removing the transaction object
// TODO: This block is temporary, for the period between the release of v4.0.0 and HF3,
// after which this should be removable
let mut args = args;
{
let invalid = || {
ErrorKind::GenericError(format!(
"Invalid wallet comm type and destination. method: {}, dest: {}",
args.method, args.dest
))
};
let trailing = match args.dest.ends_with('/') {
true => "",
false => "/",
};
let url_str = format!("{}{}v2/foreign", args.dest, trailing);
match args.method.as_ref() {
"http" => {
let v_sender = HttpSlateSender::new(&args.dest).map_err(|_| invalid())?;
let other_version = v_sender.check_other_version(&url_str)?;
if other_version == SlateVersion::V3 {
args.target_slate_version = Some(3);
}
}
"tor" => {
let v_sender = HttpSlateSender::with_socks_proxy(
&args.dest,
&tor_config.as_ref().unwrap().socks_proxy_addr,
&tor_config.as_ref().unwrap().send_config_dir,
)
.map_err(|_| invalid())?;
let other_version = v_sender.check_other_version(&url_str)?;
if other_version == SlateVersion::V3 {
args.target_slate_version = Some(3);
}
}
"file" => {
// For files spit out a V3 Slate if we're before HF3,
// Or V4 slate otherwise
let cur_height = {
libwallet::wallet_lock!(wallet_inst, w);
w.w2n_client().get_chain_tip()?.0
};
// TODO: Floonet HF4
if cur_height < 786240 && !args.output_v4_slate {
args.target_slate_version = Some(3);
}
}
_ => {}
}
}
// end block to delete post HF3
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
if args.estimate_selection_strategies {
let strategies = vec!["smallest", "all"]
@@ -321,7 +377,6 @@ where
max_outputs: args.max_outputs as u32,
num_change_outputs: args.change_outputs as u32,
selection_strategy_is_use_all: args.selection_strategy == "all",
message: args.message.clone(),
target_slate_version: args.target_slate_version,
payment_proof_recipient_address: args.payment_proof_address.clone(),
ttl_blocks: args.ttl_blocks,
@@ -347,34 +402,35 @@ where
match args.method.as_str() {
"file" => {
PathToSlate((&args.dest).into()).put_tx(&slate)?;
api.tx_lock_outputs(m, &slate, 0)?;
PathToSlate((&args.dest).into()).put_tx(&slate, false)?;
api.tx_lock_outputs(m, &slate)?;
return Ok(());
}
"binfile" => {
PathToSlate((&args.dest).into()).put_tx(&slate, true)?;
api.tx_lock_outputs(m, &slate)?;
return Ok(());
}
"self" => {
api.tx_lock_outputs(m, &slate, 0)?;
api.tx_lock_outputs(m, &slate)?;
let km = match keychain_mask.as_ref() {
None => None,
Some(&m) => Some(m.to_owned()),
};
controller::foreign_single_use(wallet_inst, km, |api| {
slate = api.receive_tx(&slate, Some(&args.dest), None)?;
slate = api.receive_tx(&slate, Some(&args.dest))?;
Ok(())
})?;
}
method => {
let sender = create_sender(method, &args.dest, tor_config)?;
slate = sender.send_tx(&slate)?;
api.tx_lock_outputs(m, &slate, 0)?;
api.tx_lock_outputs(m, &slate)?;
}
}
api.verify_slate_messages(m, &slate).map_err(|e| {
error!("Error validating participant messages: {}", e);
e
})?;
slate = api.finalize_tx(m, &slate)?;
let result = api.post_tx(m, slate.tx_or_err()?, args.fluff);
let result = api.post_tx(m, &slate, args.fluff);
match result {
Ok(_) => {
info!("Tx sent ok",);
@@ -394,7 +450,6 @@ where
/// Receive command argument
pub struct ReceiveArgs {
pub input: String,
pub message: Option<String>,
}
pub fn receive<L, C, K>(
@@ -408,20 +463,16 @@ where
C: NodeClient + 'static,
K: keychain::Keychain + 'static,
{
let mut slate = PathToSlate((&args.input).into()).get_tx()?;
let (mut slate, was_bin) = PathToSlate((&args.input).into()).get_tx()?;
let km = match keychain_mask.as_ref() {
None => None,
Some(&m) => Some(m.to_owned()),
};
controller::foreign_single_use(owner_api.wallet_inst.clone(), km, |api| {
if let Err(e) = api.verify_slate_messages(&slate) {
error!("Error validating participant messages: {}", e);
return Err(e);
}
slate = api.receive_tx(&slate, Some(&g_args.account), args.message.clone())?;
slate = api.receive_tx(&slate, Some(&g_args.account))?;
Ok(())
})?;
PathToSlate(format!("{}.response", args.input).into()).put_tx(&slate)?;
PathToSlate(format!("{}.response", args.input).into()).put_tx(&slate, was_bin)?;
info!(
"Response file {}.response generated, and can be sent back to the transaction originator.",
args.input
@@ -447,25 +498,18 @@ where
C: NodeClient + 'static,
K: keychain::Keychain + 'static,
{
let mut slate = PathToSlate((&args.input).into()).get_tx()?;
let (mut slate, was_bin) = PathToSlate((&args.input).into()).get_tx()?;
// Rather than duplicating the entire command, we'll just
// try to determine what kind of finalization this is
// based on the slate contents
// for now, we can tell this is an invoice transaction
// if the receipient (participant 1) hasn't completed sigs
let part_data = slate.participant_with_id(1);
let is_invoice = {
match part_data {
None => {
error!("Expected slate participant data missing");
return Err(ErrorKind::ArgumentError(
"Expected Slate participant data missing".into(),
))?;
}
Some(p) => !p.is_complete(),
}
};
let mut is_invoice = false;
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
is_invoice = api.context_is_invoice(m, &slate)?;
Ok(())
})?;
if is_invoice {
let km = match keychain_mask.as_ref() {
@@ -473,19 +517,11 @@ where
Some(&m) => Some(m.to_owned()),
};
controller::foreign_single_use(owner_api.wallet_inst.clone(), km, |api| {
if let Err(e) = api.verify_slate_messages(&slate) {
error!("Error validating participant messages: {}", e);
return Err(e);
}
slate = api.finalize_invoice_tx(&slate)?;
Ok(())
})?;
} else {
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
if let Err(e) = api.verify_slate_messages(m, &slate) {
error!("Error validating participant messages: {}", e);
return Err(e);
}
slate = api.finalize_tx(m, &slate)?;
Ok(())
})?;
@@ -493,7 +529,7 @@ where
if !args.nopost {
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
let result = api.post_tx(m, slate.tx_or_err()?, args.fluff);
let result = api.post_tx(m, &slate, args.fluff);
match result {
Ok(_) => {
info!(
@@ -510,7 +546,7 @@ where
}
if args.dest.is_some() {
PathToSlate((&args.dest.unwrap()).into()).put_tx(&slate)?;
PathToSlate((&args.dest.unwrap()).into()).put_tx(&slate, was_bin)?;
}
Ok(())
@@ -522,6 +558,11 @@ pub struct IssueInvoiceArgs {
pub dest: String,
/// issue invoice tx args
pub issue_args: IssueInvoiceTxArgs,
/// whether to output as bin
pub bin: bool,
// TODO: Remove HF3
/// whether to output a V4 slate
pub output_v4_slate: bool,
}
pub fn issue_invoice_tx<L, C, K>(
@@ -534,9 +575,23 @@ where
C: NodeClient + 'static,
K: keychain::Keychain + 'static,
{
//TODO: Remove block HF3
let args = {
let mut a = args;
let wallet_inst = owner_api.wallet_inst.clone();
let cur_height = {
libwallet::wallet_lock!(wallet_inst, w);
w.w2n_client().get_chain_tip()?.0
};
// TODO: Floonet HF4
if cur_height < 786240 && !a.output_v4_slate && !a.bin {
a.issue_args.target_slate_version = Some(3);
}
a
};
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
let slate = api.issue_invoice_tx(m, args.issue_args)?;
PathToSlate((&args.dest).into()).put_tx(&slate)?;
PathToSlate((&args.dest).into()).put_tx(&slate, args.bin)?;
Ok(())
})?;
Ok(())
@@ -544,7 +599,6 @@ where
/// Arguments for the process_invoice command
pub struct ProcessInvoiceArgs {
pub message: Option<String>,
pub minimum_confirmations: u64,
pub selection_strategy: String,
pub method: String,
@@ -568,7 +622,7 @@ where
C: NodeClient + 'static,
K: keychain::Keychain + 'static,
{
let slate = PathToSlate((&args.input).into()).get_tx()?;
let (slate, _) = PathToSlate((&args.input).into()).get_tx()?;
let wallet_inst = owner_api.wallet_inst.clone();
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
if args.estimate_selection_strategies {
@@ -598,15 +652,10 @@ where
max_outputs: args.max_outputs as u32,
num_change_outputs: 1u32,
selection_strategy_is_use_all: args.selection_strategy == "all",
message: args.message.clone(),
ttl_blocks: args.ttl_blocks,
send_args: None,
..Default::default()
};
if let Err(e) = api.verify_slate_messages(m, &slate) {
error!("Error validating participant messages: {}", e);
return Err(e);
}
let result = api.process_invoice_tx(m, &slate, init_args);
let mut slate = match result {
Ok(s) => {
@@ -627,11 +676,16 @@ where
match args.method.as_str() {
"file" => {
let slate_putter = PathToSlate((&args.dest).into());
slate_putter.put_tx(&slate)?;
api.tx_lock_outputs(m, &slate, 0)?;
slate_putter.put_tx(&slate, false)?;
api.tx_lock_outputs(m, &slate)?;
}
"filebin" => {
let slate_putter = PathToSlate((&args.dest).into());
slate_putter.put_tx(&slate, true)?;
api.tx_lock_outputs(m, &slate)?;
}
"self" => {
api.tx_lock_outputs(m, &slate, 0)?;
api.tx_lock_outputs(m, &slate)?;
let km = match keychain_mask.as_ref() {
None => None,
Some(&m) => Some(m.to_owned()),
@@ -644,7 +698,7 @@ where
method => {
let sender = create_sender(method, &args.dest, tor_config)?;
slate = sender.send_tx(&slate)?;
api.tx_lock_outputs(m, &slate, 0)?;
api.tx_lock_outputs(m, &slate)?;
}
}
}
@@ -769,7 +823,6 @@ where
)?;
// should only be one here, but just in case
for tx in txs {
display::tx_messages(&tx, dark_scheme)?;
display::payment_proof(&tx)?;
}
}
@@ -795,10 +848,10 @@ where
C: NodeClient + 'static,
K: keychain::Keychain + 'static,
{
let slate = PathToSlate((&args.input).into()).get_tx()?;
let slate = PathToSlate((&args.input).into()).get_tx()?.0;
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
api.post_tx(m, slate.tx_or_err()?, args.fluff)?;
api.post_tx(m, &slate, args.fluff)?;
info!("Posted transaction");
return Ok(());
})?;
@@ -824,7 +877,7 @@ where
{
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
let (_, txs) = api.retrieve_txs(m, true, Some(args.id), None)?;
let stored_tx = api.get_stored_tx(m, &txs[0])?;
let stored_tx = api.get_stored_tx(m, txs[0].tx_slate_id.unwrap())?;
if stored_tx.is_none() {
error!(
"Transaction with id {} does not have transaction data. Not reposting.",
@@ -841,7 +894,9 @@ where
);
return Ok(());
}
api.post_tx(m, &stored_tx.unwrap(), args.fluff)?;
let mut slate = Slate::blank(2, false);
slate.tx = Some(stored_tx.unwrap());
api.post_tx(m, &slate, args.fluff)?;
info!("Reposted transaction at {}", args.id);
return Ok(());
}
+2 -77
View File
@@ -1,4 +1,4 @@
// Copyright 2019 The Grin Developers
// Copyright 2020 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.
@@ -17,7 +17,7 @@ use crate::core::global;
use crate::libwallet::{
AcctPathMapping, Error, OutputCommitMapping, OutputStatus, TxLogEntry, WalletInfo,
};
use crate::util::{static_secp_instance, ToHex};
use crate::util::ToHex;
use grin_wallet_util::OnionV3Address;
use prettytable;
use std::io::prelude::Write;
@@ -448,81 +448,6 @@ pub fn accounts(acct_mappings: Vec<AcctPathMapping>) {
println!();
}
/// Display transaction log messages
pub fn tx_messages(tx: &TxLogEntry, dark_background_color_scheme: bool) -> Result<(), Error> {
let title = format!("Transaction Messages - Transaction '{}'", tx.id,);
println!();
if term::stdout().is_none() {
println!("Could not open terminal");
return Ok(());
}
let mut t = term::stdout().unwrap();
t.fg(term::color::MAGENTA).unwrap();
writeln!(t, "{}", title).unwrap();
t.reset().unwrap();
let msgs = match tx.messages.clone() {
None => {
writeln!(t, "None").unwrap();
t.reset().unwrap();
return Ok(());
}
Some(m) => m.clone(),
};
if msgs.messages.is_empty() {
writeln!(t, "None").unwrap();
t.reset().unwrap();
return Ok(());
}
let mut table = table!();
table.set_titles(row![
bMG->"Participant Id",
bMG->"Message",
bMG->"Public Key",
bMG->"Signature",
]);
let secp = static_secp_instance();
let secp_lock = secp.lock();
for m in msgs.messages {
let id = format!("{}", m.id);
let public_key = format!("{}", m.public_key.serialize_vec(&secp_lock, true).to_hex());
let message = match m.message {
Some(m) => format!("{}", m),
None => "None".to_owned(),
};
let message_sig = match m.message_sig {
Some(s) => format!("{}", s.serialize_der(&secp_lock).to_hex()),
None => "None".to_owned(),
};
if dark_background_color_scheme {
table.add_row(row![
bFC->id,
bFC->message,
bFC->public_key,
bFB->message_sig,
]);
} else {
table.add_row(row![
bFD->id,
bFb->message,
bFD->public_key,
bFB->message_sig,
]);
}
}
table.set_format(*prettytable::format::consts::FORMAT_NO_COLSEP);
table.printstd();
println!();
Ok(())
}
/// Display individual Payment Proof
pub fn payment_proof(tx: &TxLogEntry) -> Result<(), Error> {
let title = format!("Payment Proof - Transaction '{}'", tx.id,);
+2 -2
View File
@@ -200,9 +200,9 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
};
let mut slate = api.init_send_tx(m, args)?;
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
api.tx_lock_outputs(m, &slate, 0)?;
api.tx_lock_outputs(m, &slate)?;
slate = api.finalize_tx(m, &slate)?;
api.post_tx(m, slate.tx_or_err()?, false)?;
api.post_tx(m, &slate, false)?;
Ok(())
})?;
+2 -2
View File
@@ -190,8 +190,8 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
let slate = api.init_send_tx(m, args)?;
// output tx file
let send_file = format!("{}/part_tx_1.tx", test_dir);
PathToSlate(send_file.into()).put_tx(&slate)?;
api.tx_lock_outputs(m, &slate, 0)?;
PathToSlate(send_file.into()).put_tx(&slate, false)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
})?;
+144 -54
View File
@@ -19,6 +19,7 @@ extern crate grin_wallet_impls as impls;
use grin_wallet_libwallet as libwallet;
use grin_wallet_util::grin_core as core;
use grin_wallet_util::OnionV3Address;
use impls::test_framework::{self, LocalWalletClient};
use impls::{PathToSlate, SlateGetter as _, SlatePutter as _};
@@ -26,16 +27,14 @@ use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
use grin_wallet_libwallet::InitTxArgs;
use serde_json;
use grin_wallet_libwallet::{InitTxArgs, IssueInvoiceTxArgs, Slate};
#[macro_use]
mod common;
use common::{clean_output_dir, create_wallet_proxy, setup};
/// self send impl
fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
fn file_exchange_test_impl(test_dir: &'static str, use_bin: bool) -> Result<(), libwallet::Error> {
// Create a new proxy to simulate server and wallet responses
let mut wallet_proxy = create_wallet_proxy(test_dir);
let chain = wallet_proxy.chain.clone();
@@ -99,11 +98,18 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
let _ =
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
let send_file = format!("{}/part_tx_1.tx", test_dir);
let receive_file = format!("{}/part_tx_2.tx", test_dir);
// test optional message
let message = "sender test message, sender test message";
let (send_file, receive_file, final_file) = match use_bin {
false => (
format!("{}/standard_S1.tx", test_dir),
format!("{}/standard_S2.tx", test_dir),
format!("{}/standard_S3.tx", test_dir),
),
true => (
format!("{}/standard_S1.txbin", test_dir),
format!("{}/standard_S2.txbin", test_dir),
format!("{}/standard_S3.txbin", test_dir),
),
};
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
@@ -119,13 +125,12 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
max_outputs: 500,
num_change_outputs: 1,
selection_strategy_is_use_all: true,
message: Some(message.to_owned()),
..Default::default()
};
let slate = api.init_send_tx(m, args)?;
// output tx file
PathToSlate((&send_file).into()).put_tx(&slate)?;
api.tx_lock_outputs(m, &slate, 0)?;
PathToSlate((&send_file).into()).put_tx(&slate, use_bin)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
})?;
@@ -135,32 +140,22 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
w.set_parent_key_id_by_name("account1")?;
}
let mut slate = PathToSlate((&send_file).into()).get_tx()?;
let mut naughty_slate = slate.clone();
naughty_slate.participant_data[0].message = Some("I changed the message".to_owned());
// verify messages on slate match
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
api.verify_slate_messages(m, &slate)?;
assert!(api.verify_slate_messages(m, &naughty_slate).is_err());
Ok(())
})?;
let sender2_message = "And this is sender 2's message".to_owned();
let mut slate = PathToSlate((&send_file).into()).get_tx()?.0;
// wallet 2 receives file, completes, sends file back
wallet::controller::foreign_single_use(wallet2.clone(), mask2_i.clone(), |api| {
slate = api.receive_tx(&slate, None, Some(sender2_message.clone()))?;
PathToSlate((&receive_file).into()).put_tx(&slate)?;
slate = api.receive_tx(&slate, None)?;
PathToSlate((&receive_file).into()).put_tx(&slate, use_bin)?;
Ok(())
})?;
// wallet 1 finalises and posts
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
let mut slate = PathToSlate(receive_file.into()).get_tx()?;
api.verify_slate_messages(m, &slate)?;
let mut slate = PathToSlate(receive_file.into()).get_tx()?.0;
slate = api.finalize_tx(m, &slate)?;
api.post_tx(m, slate.tx_or_err()?, false)?;
// Output final file for reference
PathToSlate((&final_file).into()).put_tx(&slate, use_bin)?;
api.post_tx(m, &slate, false)?;
bh += 1;
Ok(())
})?;
@@ -186,33 +181,117 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
Ok(())
})?;
// Check messages, all participants should have both
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
let (_, tx) = api.retrieve_txs(m, true, None, Some(slate.id))?;
assert_eq!(
tx[0].clone().messages.unwrap().messages[0].message,
Some(message.to_owned())
);
assert_eq!(
tx[0].clone().messages.unwrap().messages[1].message,
Some(sender2_message.to_owned())
);
// Now other types of exchange, for reference
// Invoice transaction
let (send_file, receive_file, final_file) = match use_bin {
false => (
format!("{}/invoice_I1.tx", test_dir),
format!("{}/invoice_I2.tx", test_dir),
format!("{}/invoice_I3.tx", test_dir),
),
true => (
format!("{}/invoice_I1.txbin", test_dir),
format!("{}/invoice_I2.txbin", test_dir),
format!("{}/invoice_I3.txbin", test_dir),
),
};
let msg_json = serde_json::to_string_pretty(&tx[0].clone().messages.unwrap()).unwrap();
println!("{}", msg_json);
let mut slate = Slate::blank(2, true);
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |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(())
})?;
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |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(), mask2_i.clone(), |api| {
// Wallet 2 receives the invoice transaction
slate = PathToSlate((&receive_file).into()).get_tx()?.0;
slate = api.finalize_invoice_tx(&slate)?;
PathToSlate((&final_file).into()).put_tx(&slate, use_bin)?;
Ok(())
})?;
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
api.post_tx(m, &slate, false)?;
Ok(())
})?;
// Standard, with payment proof
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
let (send_file, receive_file, final_file) = match use_bin {
false => (
format!("{}/standard_pp_S1.tx", test_dir),
format!("{}/standard_pp_S2.tx", test_dir),
format!("{}/standard_pp_S3.tx", test_dir),
),
true => (
format!("{}/standard_pp_S1.txbin", test_dir),
format!("{}/standard_pp_S2.txbin", test_dir),
format!("{}/standard_pp_S3.txbin", test_dir),
),
};
let mut slate = Slate::blank(2, true);
let mut address = None;
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
let (_, tx) = api.retrieve_txs(m, true, None, Some(slate.id))?;
assert_eq!(
tx[0].clone().messages.unwrap().messages[0].message,
Some(message.to_owned())
);
assert_eq!(
tx[0].clone().messages.unwrap().messages[1].message,
Some(sender2_message)
);
address = Some(api.get_public_proof_address(m, 0)?);
Ok(())
})?;
let address = OnionV3Address::from_bytes(address.as_ref().unwrap().to_bytes());
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |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: Some(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(())
})?;
wallet::controller::foreign_single_use(wallet2.clone(), mask2_i.clone(), |api| {
slate = PathToSlate((&send_file).into()).get_tx()?.0;
slate = api.receive_tx(&slate, None)?;
PathToSlate((&receive_file).into()).put_tx(&slate, use_bin)?;
Ok(())
})?;
// wallet 1 finalises and posts
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |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(())
})?;
@@ -223,10 +302,21 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
}
#[test]
fn wallet_file_exchange() {
let test_dir = "test_output/file_exchange";
fn wallet_file_exchange_json() {
let test_dir = "test_output/file_exchange_json";
setup(test_dir);
if let Err(e) = file_exchange_test_impl(test_dir) {
// Json output
if let Err(e) = file_exchange_test_impl(test_dir, false) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap());
}
clean_output_dir(test_dir);
}
#[test]
fn wallet_file_exchange_bin() {
let test_dir = "test_output/file_exchange_bin";
setup(test_dir);
if let Err(e) = file_exchange_test_impl(test_dir, true) {
panic!("Libwallet Error: {} - {}", e, e.backtrace().unwrap());
}
clean_output_dir(test_dir);
+11 -6
View File
@@ -21,7 +21,7 @@ use grin_wallet_libwallet as libwallet;
use grin_wallet_util::grin_core as core;
use impls::test_framework::{self, LocalWalletClient};
use libwallet::{InitTxArgs, IssueInvoiceTxArgs, Slate};
use libwallet::{InitTxArgs, IssueInvoiceTxArgs, Slate, SlateState};
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
@@ -95,7 +95,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
Ok(())
})?;
let mut slate = Slate::blank(2);
let mut slate = Slate::blank(2, true);
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
// Wallet 2 inititates an invoice transaction, requesting payment
@@ -106,6 +106,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
slate = api.issue_invoice_tx(m, args)?;
Ok(())
})?;
assert_eq!(slate.state, SlateState::Invoice1);
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
// Wallet 1 receives the invoice transaction
@@ -119,9 +120,10 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
..Default::default()
};
slate = api.process_invoice_tx(m, &slate, args)?;
api.tx_lock_outputs(m, &slate, 0)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
})?;
assert_eq!(slate.state, SlateState::Invoice2);
// wallet 2 finalizes and posts
wallet::controller::foreign_single_use(wallet2.clone(), mask2_i.clone(), |api| {
@@ -129,10 +131,11 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
slate = api.finalize_invoice_tx(&slate)?;
Ok(())
})?;
assert_eq!(slate.state, SlateState::Invoice3);
// wallet 1 posts so wallet 2 doesn't get the mined amount
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
api.post_tx(m, slate.tx_or_err()?, false)?;
api.post_tx(m, &slate, false)?;
Ok(())
})?;
bh += 1;
@@ -151,7 +154,6 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
wallet2_info.last_confirmed_height, bh
);
assert!(refreshed);
assert_eq!(wallet2_info.amount_currently_spendable, slate.amount);
Ok(())
})?;
@@ -187,11 +189,14 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
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, 0)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
})?;
println!("Self invoice slate after process: {}", slate);
// wallet 1 finalizes and posts
wallet::controller::foreign_single_use(wallet1.clone(), mask1_i.clone(), |api| {
// Wallet 2 receives the invoice transaction
+50 -8
View File
@@ -76,7 +76,8 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
let fee = core::libtx::tx_fee(1, 1, 1, None);
// send a single block's worth of transactions with minimal strategy
let mut slate = Slate::blank(2);
let mut slate = Slate::blank(2, false);
let mut stored_excess = None;
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
let args = InitTxArgs {
src_acct_name: None,
@@ -89,19 +90,42 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
};
slate = api.init_send_tx(m, args)?;
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
api.tx_lock_outputs(m, &slate, 0)?;
api.tx_lock_outputs(m, &slate)?;
slate = api.finalize_tx(m, &slate)?;
api.post_tx(m, slate.tx_or_err()?, false)?;
println!("Posted Slate: {:?}", slate);
println!("Posted TX: {}", slate);
stored_excess = Some(slate.tx.as_ref().unwrap().body.kernels[0].excess);
api.post_tx(m, &slate, false)?;
Ok(())
})?;
// 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(Some(wallet1.clone()), mask2, None, |api, m| {
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
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(())
})?;
// Refresh and check transaction log for wallet 2
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
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(())
})?;
@@ -128,7 +152,7 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
..Default::default()
};
slate = api.process_invoice_tx(m, &slate, args)?;
api.tx_lock_outputs(m, &slate, 0)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
})?;
@@ -139,16 +163,34 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
Ok(())
})?;
wallet::controller::owner_single_use(Some(wallet2.clone()), mask1, None, |api, m| {
api.post_tx(m, slate.tx_or_err()?, false)?;
println!("Invoice Posted TX: {}", slate);
stored_excess = Some(slate.tx.as_ref().unwrap().body.kernels[0].excess);
api.post_tx(m, &slate, false)?;
Ok(())
})?;
// check wallet 2's version
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
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(())
})?;
// Refresh and check transaction log for wallet 1
wallet::controller::owner_single_use(Some(wallet1.clone()), mask2, None, |api, m| {
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
assert!(refreshed);
for tx in txs {
println!("{:?}", tx);
println!("Wallet 1: {:?}", tx);
println!();
assert_eq!(stored_excess, tx.kernel_excess);
assert!(tx.confirmed);
}
Ok(())
+6 -6
View File
@@ -87,7 +87,7 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
let address = OnionV3Address::from_bytes(address.as_ref().unwrap().to_bytes());
println!("Public address is: {:?}", address);
let amount = 60_000_000_000;
let mut slate = Slate::blank(1);
let mut slate = Slate::blank(1, false);
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
@@ -111,12 +111,12 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
slate_i.payment_proof.as_ref().unwrap().sender_address
);
// Check we are creating a tx with the expected lock_height of 0.
// Check we are creating a tx with kernel features 0
// We will check this produces a Plain kernel later.
assert_eq!(0, slate.lock_height);
assert_eq!(0, slate.kernel_features);
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
sender_api.tx_lock_outputs(m, &slate, 0)?;
sender_api.tx_lock_outputs(m, &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))?;
@@ -135,7 +135,7 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
assert!(pp.is_err());
slate = sender_api.finalize_tx(m, &slate)?;
sender_api.post_tx(m, slate.tx_or_err()?, true)?;
sender_api.post_tx(m, &slate, true)?;
Ok(())
})?;
@@ -145,7 +145,7 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
// Check payment proof here
let mut pp = sender_api.retrieve_payment_proof(m, true, None, Some(slate.id))?;
println!("{:?}", pp);
println!("Payment proof: {:?}", pp);
// verify, should be good
let res = sender_api.verify_payment_proof(m, &pp)?;
+16 -13
View File
@@ -99,7 +99,7 @@ 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);
let mut slate = Slate::blank(2, false);
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
@@ -118,8 +118,8 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
..Default::default()
};
let slate = api.init_send_tx(m, args)?;
PathToSlate((&send_file).into()).put_tx(&slate)?;
api.tx_lock_outputs(m, &slate, 0)?;
PathToSlate((&send_file).into()).put_tx(&slate, false)?;
api.tx_lock_outputs(m, &slate)?;
Ok(())
})?;
@@ -133,9 +133,9 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
}
wallet::controller::foreign_single_use(wallet1.clone(), mask1_i.clone(), |api| {
slate = PathToSlate((&send_file).into()).get_tx()?;
slate = api.receive_tx(&slate, None, None)?;
PathToSlate((&receive_file).into()).put_tx(&slate)?;
slate = PathToSlate((&send_file).into()).get_tx()?.0;
slate = api.receive_tx(&slate, None)?;
PathToSlate((&receive_file).into()).put_tx(&slate, false)?;
Ok(())
})?;
@@ -147,7 +147,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
// wallet 1 finalize
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
slate = PathToSlate((&receive_file).into()).get_tx()?;
slate = PathToSlate((&receive_file).into()).get_tx()?.0;
slate = api.finalize_tx(m, &slate)?;
Ok(())
})?;
@@ -155,8 +155,10 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
// Now repost from cached
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
let stored_tx = api.get_stored_tx(m, &txs[0])?;
api.post_tx(m, &stored_tx.unwrap(), false)?;
println!("TXS[0]: {:?}", txs[0]);
let stored_tx = api.get_stored_tx(m, txs[0].tx_slate_id.unwrap())?;
println!("Stored tx: {:?}", stored_tx);
api.post_tx(m, &slate, false)?;
bh += 1;
Ok(())
})?;
@@ -196,7 +198,7 @@ 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);
let mut slate = Slate::blank(2, false);
let amount = 60_000_000_000;
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
@@ -212,7 +214,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
};
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, 0)?;
sender_api.tx_lock_outputs(m, &slate)?;
slate = sender_api.finalize_tx(m, &slate)?;
Ok(())
})?;
@@ -223,8 +225,9 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
// Now repost from cached
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
let stored_tx = api.get_stored_tx(m, &txs[0])?;
api.post_tx(m, &stored_tx.unwrap(), false)?;
let stored_tx = api.get_stored_tx(m, txs[0].tx_slate_id.unwrap())?;
slate.tx = stored_tx;
api.post_tx(m, &slate, false)?;
bh += 1;
Ok(())
})?;
+2 -2
View File
@@ -169,8 +169,8 @@ fn revert(
let slate = api.init_send_tx(m, args)?;
// output tx file
let send_file = format!("{}/part_tx_1.tx", test_dir);
PathToSlate(send_file.into()).put_tx(&slate)?;
api.tx_lock_outputs(m, &slate, 0)?;
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 = Some(slate.tx);
+3 -3
View File
@@ -94,14 +94,14 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
..Default::default()
};
let mut slate = api.init_send_tx(m, args)?;
api.tx_lock_outputs(m, &slate, 0)?;
api.tx_lock_outputs(m, &slate)?;
// Send directly to self
wallet::controller::foreign_single_use(wallet1.clone(), mask1_i.clone(), |api| {
slate = api.receive_tx(&slate, Some("listener"), None)?;
slate = api.receive_tx(&slate, Some("listener"))?;
Ok(())
})?;
slate = api.finalize_tx(m, &slate)?;
api.post_tx(m, slate.tx_or_err()?, false)?; // mines a block
api.post_tx(m, &slate, false)?; // mines a block
bh += 1;
Ok(())
})?;
+15 -10
View File
@@ -22,7 +22,7 @@ use grin_wallet_util::grin_core as core;
use self::core::core::transaction;
use self::core::global;
use self::libwallet::{InitTxArgs, OutputStatus, Slate};
use self::libwallet::{InitTxArgs, OutputStatus, Slate, SlateState};
use impls::test_framework::{self, LocalWalletClient};
use std::sync::atomic::Ordering;
use std::thread;
@@ -97,7 +97,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
// assert wallet contents
// and a single use api for a send command
let amount = 60_000_000_000;
let mut slate = Slate::blank(1);
let mut slate = Slate::blank(1, false);
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
@@ -111,13 +111,17 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
};
let slate_i = sender_api.init_send_tx(m, args)?;
assert_eq!(slate_i.state, SlateState::Standard1);
// Check we are creating a tx with the expected lock_height of 0.
// We will check this produces a Plain kernel later.
assert_eq!(0, slate.lock_height);
assert_eq!(0, slate.kernel_features);
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
sender_api.tx_lock_outputs(m, &slate, 0)?;
assert_eq!(slate.state, SlateState::Standard2);
sender_api.tx_lock_outputs(m, &slate)?;
slate = sender_api.finalize_tx(m, &slate)?;
assert_eq!(slate.state, SlateState::Standard3);
// Check we have a single kernel and that it is a Plain kernel (no lock_height).
assert_eq!(slate.tx_or_err()?.kernels().len(), 1);
@@ -175,7 +179,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
// post transaction
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
api.post_tx(m, slate.tx_or_err()?, false)?;
api.post_tx(m, &slate, false)?;
Ok(())
})?;
@@ -299,7 +303,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
};
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, 0)?;
sender_api.tx_lock_outputs(m, &slate)?;
slate = sender_api.finalize_tx(m, &slate)?;
Ok(())
})?;
@@ -313,8 +317,9 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
.iter()
.find(|t| t.tx_slate_id == Some(slate.id))
.unwrap();
let stored_tx = sender_api.get_stored_tx(m, &tx)?;
sender_api.post_tx(m, &stored_tx.unwrap(), false)?;
let stored_tx = sender_api.get_stored_tx(m, tx.tx_slate_id.unwrap())?;
slate.tx = stored_tx;
sender_api.post_tx(m, &slate, false)?;
let (_, wallet1_info) = sender_api.retrieve_summary_info(m, true, 1)?;
// should be mined now
assert_eq!(
@@ -395,7 +400,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 5, false);
let amount = 30_000_000_000;
let mut slate = Slate::blank(1);
let mut slate = Slate::blank(1, false);
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
@@ -410,7 +415,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
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, 0)?;
sender_api.tx_lock_outputs(m, &slate)?;
slate = sender_api.finalize_tx(m, &slate)?;
Ok(())
})?;
+4 -4
View File
@@ -77,7 +77,7 @@ 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);
let mut slate = Slate::blank(1, false);
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
@@ -93,7 +93,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
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, 0)?;
sender_api.tx_lock_outputs(m, &slate)?;
let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id))?;
let tx = txs[0].clone();
@@ -127,7 +127,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
})?;
// try again, except try and send off the transaction for completion beyond the expiry
let mut slate = Slate::blank(1);
let mut slate = Slate::blank(1, false);
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
// note this will increment the block count as part of the transaction "Posting"
let args = InitTxArgs {
@@ -141,7 +141,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
..Default::default()
};
let slate_i = sender_api.init_send_tx(m, args)?;
sender_api.tx_lock_outputs(m, &slate_i, 0)?;
sender_api.tx_lock_outputs(m, &slate_i)?;
slate = slate_i;
let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id))?;