mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 03:21:08 +03:00
Optional Slate Message (#2047)
* add optional signed message to slate * rustfmt
This commit is contained in:
parent
b9cfcc777b
commit
16aa64bfab
18 changed files with 185 additions and 43 deletions
|
@ -268,6 +268,15 @@ Other flags here are:
|
|||
[host]$ grin wallet send -f -d "http://192.168.0.10:13415" 60.00
|
||||
```
|
||||
|
||||
* `-g` 'Message' - You can specify an optional message to include alongside your transaction data. This message is purely for informational
|
||||
purposes between all transacting participants, and is not included in transaction data sent to the chain. Each participant message includes
|
||||
a signature that can be verified with the participant's public key. A message can also be specified by the recipient during a `grin wallet receive`
|
||||
command.
|
||||
|
||||
```sh
|
||||
[host]$ grin wallet send -f -d "http://192.168.0.10:13415" -g "This is from Dave" 60.00
|
||||
```
|
||||
|
||||
### outputs
|
||||
|
||||
Simply displays all the the outputs in your wallet: e.g:
|
||||
|
@ -322,7 +331,6 @@ Transaction Log - Account 'default' - Block Height: 49
|
|||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
6 Received Tx 03715cf6-f29b-4a3a-bda5-b02cba6bf0d9 2018-07-20 19:46:46.120244904 UTC false None 0 1 60.000000000 0.000000000 None 60.000000000
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
>>>>>>> master
|
||||
|
||||
To see the inputs/outputs associated with a particular transaction, use the `-i` switch providing the Id of the given transaction, e.g:
|
||||
|
||||
|
|
|
@ -352,6 +352,7 @@ impl LocalServerContainer {
|
|||
max_outputs,
|
||||
change_outputs,
|
||||
selection_strategy == "all",
|
||||
None,
|
||||
)?;
|
||||
slate = client_w.send_tx_sync(dest, &slate)?;
|
||||
api.finalize_tx(&mut slate)?;
|
||||
|
|
|
@ -969,6 +969,7 @@ fn replicate_tx_fluff_failure() {
|
|||
500, // max outputs
|
||||
1000, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
)?;
|
||||
slate = client1_w.send_tx_sync(dest, &slate)?;
|
||||
api.finalize_tx(&mut slate)?;
|
||||
|
|
|
@ -355,6 +355,10 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) -> i
|
|||
e
|
||||
))
|
||||
})?;
|
||||
let message = match send_args.is_present("message") {
|
||||
true => Some(send_args.value_of("message").unwrap().to_owned()),
|
||||
false => None,
|
||||
};
|
||||
let minimum_confirmations: u64 = send_args
|
||||
.value_of("minimum_confirmations")
|
||||
.ok_or_else(|| {
|
||||
|
@ -417,6 +421,7 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) -> i
|
|||
max_outputs,
|
||||
change_outputs,
|
||||
selection_strategy == "all",
|
||||
message,
|
||||
);
|
||||
let (mut slate, lock_fn) = match result {
|
||||
Ok(s) => {
|
||||
|
@ -453,11 +458,15 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) -> i
|
|||
slate = adapter.send_tx_sync(dest, &slate)?;
|
||||
if method == "self" {
|
||||
controller::foreign_single_use(wallet, |api| {
|
||||
api.receive_tx(&mut slate, Some(dest))?;
|
||||
api.receive_tx(&mut slate, Some(dest), None)?;
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
||||
if let Err(e) = api.verify_slate_messages(&slate) {
|
||||
error!("Error validating participant messages: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
api.finalize_tx(&mut slate)?;
|
||||
} else {
|
||||
adapter.send_tx_async(dest, &slate)?;
|
||||
|
@ -481,6 +490,10 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) -> i
|
|||
}
|
||||
("receive", Some(send_args)) => {
|
||||
let mut receive_result: Result<(), grin_wallet::libwallet::Error> = Ok(());
|
||||
let message = match send_args.is_present("message") {
|
||||
true => Some(send_args.value_of("message").unwrap().to_owned()),
|
||||
false => None,
|
||||
};
|
||||
let tx_file = send_args.value_of("input").ok_or_else(|| {
|
||||
ErrorKind::GenericError("Transaction file required".to_string())
|
||||
})?;
|
||||
|
@ -492,7 +505,7 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) -> i
|
|||
let adapter = FileWalletCommAdapter::new();
|
||||
let mut slate = adapter.receive_tx_async(tx_file)?;
|
||||
controller::foreign_single_use(wallet, |api| {
|
||||
api.receive_tx(&mut slate, Some(account))?;
|
||||
api.receive_tx(&mut slate, Some(account), message)?;
|
||||
Ok(())
|
||||
})?;
|
||||
let send_tx = format!("{}.response", tx_file);
|
||||
|
@ -515,6 +528,10 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) -> i
|
|||
}
|
||||
let adapter = FileWalletCommAdapter::new();
|
||||
let mut slate = adapter.receive_tx_async(tx_file)?;
|
||||
if let Err(e) = api.verify_slate_messages(&slate) {
|
||||
error!("Error validating participant messages: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
let _ = api.finalize_tx(&mut slate).expect("Finalize failed");
|
||||
|
||||
let result = api.post_tx(&slate.tx, fluff);
|
||||
|
|
|
@ -246,15 +246,25 @@ fn real_main() -> i32 {
|
|||
.arg(Arg::with_name("fluff")
|
||||
.help("Fluff the transaction (ignore Dandelion relay protocol)")
|
||||
.short("f")
|
||||
.long("fluff")))
|
||||
.long("fluff"))
|
||||
.arg(Arg::with_name("message")
|
||||
.help("Optional participant message to include")
|
||||
.short("g")
|
||||
.long("message")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("stored_tx")
|
||||
.help("If present, use the previously stored Unconfirmed transaction with given id.")
|
||||
.short("t")
|
||||
.long("stored_tx")
|
||||
.takes_value(true))
|
||||
.takes_value(true)))
|
||||
|
||||
.subcommand(SubCommand::with_name("receive")
|
||||
.about("Processes a transaction file to accept a transfer from a sender.")
|
||||
.arg(Arg::with_name("message")
|
||||
.help("Optional participant message to include")
|
||||
.short("g")
|
||||
.long("message")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("input")
|
||||
.help("Partial transaction to process, expects the sender's transaction file.")
|
||||
.short("i")
|
||||
|
|
|
@ -171,7 +171,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn retrieve_outputs(
|
||||
pub fn retrieve_outputs(
|
||||
&self,
|
||||
req: &Request<Body>,
|
||||
api: APIOwner<T, C, K>,
|
||||
|
@ -195,7 +195,7 @@ where
|
|||
api.retrieve_outputs(show_spent, update_from_node, id)
|
||||
}
|
||||
|
||||
fn retrieve_txs(
|
||||
pub fn retrieve_txs(
|
||||
&self,
|
||||
req: &Request<Body>,
|
||||
api: APIOwner<T, C, K>,
|
||||
|
@ -222,7 +222,7 @@ where
|
|||
api.retrieve_txs(update_from_node, tx_id, tx_slate_id)
|
||||
}
|
||||
|
||||
fn retrieve_stored_tx(
|
||||
pub fn retrieve_stored_tx(
|
||||
&self,
|
||||
req: &Request<Body>,
|
||||
api: APIOwner<T, C, K>,
|
||||
|
@ -251,7 +251,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn retrieve_summary_info(
|
||||
pub fn retrieve_summary_info(
|
||||
&self,
|
||||
req: &Request<Body>,
|
||||
mut api: APIOwner<T, C, K>,
|
||||
|
@ -269,7 +269,7 @@ where
|
|||
api.retrieve_summary_info(update_from_node, minimum_confirmations)
|
||||
}
|
||||
|
||||
fn node_height(
|
||||
pub fn node_height(
|
||||
&self,
|
||||
_req: &Request<Body>,
|
||||
mut api: APIOwner<T, C, K>,
|
||||
|
@ -297,7 +297,7 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn issue_send_tx(
|
||||
pub fn issue_send_tx(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
mut api: APIOwner<T, C, K>,
|
||||
|
@ -310,6 +310,7 @@ where
|
|||
args.max_outputs,
|
||||
args.num_change_outputs,
|
||||
args.selection_strategy_is_use_all,
|
||||
args.message,
|
||||
);
|
||||
let (mut slate, lock_fn) = match result {
|
||||
Ok(s) => {
|
||||
|
@ -353,7 +354,7 @@ where
|
|||
}))
|
||||
}
|
||||
|
||||
fn finalize_tx(
|
||||
pub fn finalize_tx(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
mut api: APIOwner<T, C, K>,
|
||||
|
@ -369,7 +370,7 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
fn cancel_tx(
|
||||
pub fn cancel_tx(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
mut api: APIOwner<T, C, K>,
|
||||
|
@ -414,7 +415,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn post_tx(
|
||||
pub fn post_tx(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
api: APIOwner<T, C, K>,
|
||||
|
@ -548,7 +549,8 @@ where
|
|||
mut api: APIForeign<T, C, K>,
|
||||
) -> Box<Future<Item = Slate, Error = Error> + Send> {
|
||||
Box::new(parse_body(req).and_then(
|
||||
move |mut slate| match api.receive_tx(&mut slate, None) {
|
||||
//TODO: No way to insert a message from the params
|
||||
move |mut slate| match api.receive_tx(&mut slate, None, None) {
|
||||
Ok(_) => ok(slate.clone()),
|
||||
Err(e) => {
|
||||
error!("receive_tx: failed with error: {}", e);
|
||||
|
|
|
@ -420,6 +420,28 @@ pub fn verify_completed_sig(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds signatures
|
||||
pub fn add_signatures(
|
||||
secp: &Secp256k1,
|
||||
part_sigs: Vec<&Signature>,
|
||||
nonce_sum: &PublicKey,
|
||||
) -> Result<Signature, Error> {
|
||||
// Add public nonces kR*G + kS*G
|
||||
let sig = aggsig::add_signatures_single(&secp, part_sigs, &nonce_sum)?;
|
||||
Ok(sig)
|
||||
}
|
||||
|
||||
/// Just a simple sig, creates its own nonce, etc
|
||||
pub fn sign_single(
|
||||
secp: &Secp256k1,
|
||||
msg: &Message,
|
||||
skey: &SecretKey,
|
||||
pubkey_sum: Option<&PublicKey>,
|
||||
) -> Result<Signature, Error> {
|
||||
let sig = aggsig::sign_single(secp, &msg, skey, None, None, None, pubkey_sum, None)?;
|
||||
Ok(sig)
|
||||
}
|
||||
|
||||
/// Verifies an aggsig signature
|
||||
pub fn verify_single(
|
||||
secp: &Secp256k1,
|
||||
|
@ -435,17 +457,6 @@ pub fn verify_single(
|
|||
)
|
||||
}
|
||||
|
||||
/// Adds signatures
|
||||
pub fn add_signatures(
|
||||
secp: &Secp256k1,
|
||||
part_sigs: Vec<&Signature>,
|
||||
nonce_sum: &PublicKey,
|
||||
) -> Result<Signature, Error> {
|
||||
// Add public nonces kR*G + kS*G
|
||||
let sig = aggsig::add_signatures_single(&secp, part_sigs, &nonce_sum)?;
|
||||
Ok(sig)
|
||||
}
|
||||
|
||||
/// Just a simple sig, creates its own nonce, etc
|
||||
pub fn sign_with_blinding(
|
||||
secp: &Secp256k1,
|
||||
|
|
|
@ -32,6 +32,8 @@ use util::secp::key::{PublicKey, SecretKey};
|
|||
use util::secp::Signature;
|
||||
use util::RwLock;
|
||||
|
||||
use blake2::blake2b::blake2b;
|
||||
|
||||
/// Public data for each participant in the slate
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
|
@ -44,6 +46,10 @@ pub struct ParticipantData {
|
|||
pub public_nonce: PublicKey,
|
||||
/// Public partial signature
|
||||
pub part_sig: Option<Signature>,
|
||||
/// A message for other participants
|
||||
pub message: Option<String>,
|
||||
/// Signature, created with private key corresponding to 'public_blind_excess'
|
||||
pub message_sig: Option<Signature>,
|
||||
}
|
||||
|
||||
impl ParticipantData {
|
||||
|
@ -133,6 +139,7 @@ impl Slate {
|
|||
sec_key: &mut SecretKey,
|
||||
sec_nonce: &SecretKey,
|
||||
participant_id: usize,
|
||||
message: Option<String>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
K: Keychain,
|
||||
|
@ -141,7 +148,14 @@ impl Slate {
|
|||
if self.tx.offset == BlindingFactor::zero() {
|
||||
self.generate_offset(keychain, sec_key)?;
|
||||
}
|
||||
self.add_participant_info(keychain, &sec_key, &sec_nonce, participant_id, None)?;
|
||||
self.add_participant_info(
|
||||
keychain,
|
||||
&sec_key,
|
||||
&sec_nonce,
|
||||
participant_id,
|
||||
None,
|
||||
message,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -234,6 +248,7 @@ impl Slate {
|
|||
sec_nonce: &SecretKey,
|
||||
id: usize,
|
||||
part_sig: Option<Signature>,
|
||||
message: Option<String>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
K: Keychain,
|
||||
|
@ -241,11 +256,24 @@ impl Slate {
|
|||
// Add our public key and nonce to the slate
|
||||
let pub_key = PublicKey::from_secret_key(keychain.secp(), &sec_key)?;
|
||||
let pub_nonce = PublicKey::from_secret_key(keychain.secp(), &sec_nonce)?;
|
||||
// Sign the provided message
|
||||
let message_sig = {
|
||||
if let Some(m) = message.clone() {
|
||||
let hashed = blake2b(secp::constants::MESSAGE_SIZE, &[], &m.as_bytes()[..]);
|
||||
let m = secp::Message::from_slice(&hashed.as_bytes())?;
|
||||
let res = aggsig::sign_single(&keychain.secp(), &m, &sec_key, None)?;
|
||||
Some(res)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
self.participant_data.push(ParticipantData {
|
||||
id: id as u64,
|
||||
public_blind_excess: pub_key,
|
||||
public_nonce: pub_nonce,
|
||||
part_sig: part_sig,
|
||||
message: message,
|
||||
message_sig: message_sig,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
|
@ -321,6 +349,30 @@ impl Slate {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Verifies any messages in the slate's participant data match their signatures
|
||||
pub fn verify_messages(&self, secp: &secp::Secp256k1) -> Result<(), Error> {
|
||||
for p in self.participant_data.iter() {
|
||||
if let Some(m) = p.message.clone() {
|
||||
let hashed = blake2b(secp::constants::MESSAGE_SIZE, &[], &m.as_bytes()[..]);
|
||||
let m = secp::Message::from_slice(&hashed.as_bytes())?;
|
||||
if !aggsig::verify_single(
|
||||
secp,
|
||||
&p.message_sig.as_ref().unwrap(),
|
||||
&m,
|
||||
None,
|
||||
&p.public_blind_excess,
|
||||
None,
|
||||
false,
|
||||
) {
|
||||
return Err(ErrorKind::Signature(
|
||||
"Optional participant messages do not match signatures".to_owned(),
|
||||
))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This should be callable by either the sender or receiver
|
||||
/// once phase 3 is done
|
||||
///
|
||||
|
|
|
@ -462,6 +462,7 @@ where
|
|||
max_outputs: usize,
|
||||
num_change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
message: Option<String>,
|
||||
) -> Result<(Slate, impl FnOnce(&mut W, &str) -> Result<(), Error>), Error> {
|
||||
let mut w = self.wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
|
@ -485,6 +486,7 @@ where
|
|||
selection_strategy_is_use_all,
|
||||
&parent_key_id,
|
||||
false,
|
||||
message,
|
||||
)?;
|
||||
|
||||
// Save the aggsig context in our DB for when we
|
||||
|
@ -577,6 +579,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Verifies all messages in the slate match their public keys
|
||||
pub fn verify_slate_messages(&mut self, slate: &Slate) -> Result<(), Error> {
|
||||
let mut w = self.wallet.lock();
|
||||
slate.verify_messages(w.keychain().secp())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Attempt to restore contents of wallet
|
||||
pub fn restore(&mut self) -> Result<(), Error> {
|
||||
let mut w = self.wallet.lock();
|
||||
|
@ -660,6 +669,7 @@ where
|
|||
&mut self,
|
||||
slate: &mut Slate,
|
||||
dest_acct_name: Option<&str>,
|
||||
message: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let mut w = self.wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
|
@ -673,7 +683,7 @@ where
|
|||
}
|
||||
None => w.parent_key_id(),
|
||||
};
|
||||
let res = tx::receive_tx(&mut *w, slate, &parent_key_id, false);
|
||||
let res = tx::receive_tx(&mut *w, slate, &parent_key_id, false, message);
|
||||
w.close()?;
|
||||
|
||||
if let Err(e) = res {
|
||||
|
|
|
@ -31,6 +31,7 @@ pub fn receive_tx<T: ?Sized, C, K>(
|
|||
slate: &mut Slate,
|
||||
parent_key_id: &Identifier,
|
||||
is_self: bool,
|
||||
message: Option<String>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
|
@ -51,6 +52,7 @@ where
|
|||
&mut context.sec_key,
|
||||
&context.sec_nonce,
|
||||
1,
|
||||
message,
|
||||
)?;
|
||||
|
||||
// perform partial sig
|
||||
|
@ -73,6 +75,7 @@ pub fn create_send_tx<T: ?Sized, C, K>(
|
|||
selection_strategy_is_use_all: bool,
|
||||
parent_key_id: &Identifier,
|
||||
is_self: bool,
|
||||
message: Option<String>,
|
||||
) -> Result<
|
||||
(
|
||||
Slate,
|
||||
|
@ -122,6 +125,7 @@ where
|
|||
&mut context.sec_key,
|
||||
&context.sec_nonce,
|
||||
0,
|
||||
message,
|
||||
)?;
|
||||
|
||||
Ok((slate, context, sender_lock_fn))
|
||||
|
|
|
@ -700,4 +700,6 @@ pub struct SendTXArgs {
|
|||
pub num_change_outputs: usize,
|
||||
/// whether to use all outputs (combine)
|
||||
pub selection_strategy_is_use_all: bool,
|
||||
/// Optional message, that will be signed
|
||||
pub message: Option<String>,
|
||||
}
|
||||
|
|
|
@ -190,6 +190,7 @@ fn accounts_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
|
||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
||||
|
|
|
@ -211,7 +211,7 @@ where
|
|||
let w = dest_wallet.unwrap().1.clone();
|
||||
let mut slate = serde_json::from_str(&m.body).unwrap();
|
||||
controller::foreign_single_use(w.clone(), |listener_api| {
|
||||
listener_api.receive_tx(&mut slate, None)?;
|
||||
listener_api.receive_tx(&mut slate, None, None)?;
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(WalletProxyMessage {
|
||||
|
|
|
@ -97,6 +97,9 @@ fn file_exchange_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
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";
|
||||
|
||||
// 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)?;
|
||||
|
@ -106,13 +109,12 @@ fn file_exchange_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
// 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
|
||||
//"mining",
|
||||
//"listener",
|
||||
reward * 2, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
Some(message.to_owned()), // optional message
|
||||
)?;
|
||||
// output tx file
|
||||
let file_adapter = FileWalletCommAdapter::new();
|
||||
|
@ -127,11 +129,23 @@ fn file_exchange_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
w.set_parent_key_id_by_name("account1")?;
|
||||
}
|
||||
|
||||
let adapter = FileWalletCommAdapter::new();
|
||||
let mut slate = adapter.receive_tx_async(&send_file)?;
|
||||
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(wallet1.clone(), |api| {
|
||||
api.verify_slate_messages(&slate)?;
|
||||
assert!(api.verify_slate_messages(&naughty_slate).is_err());
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let sender2_message = "And this is sender 2's message".to_owned();
|
||||
|
||||
// wallet 2 receives file, completes, sends file back
|
||||
wallet::controller::foreign_single_use(wallet2.clone(), |api| {
|
||||
let adapter = FileWalletCommAdapter::new();
|
||||
let mut slate = adapter.receive_tx_async(&send_file)?;
|
||||
api.receive_tx(&mut slate, None)?;
|
||||
api.receive_tx(&mut slate, None, Some(sender2_message))?;
|
||||
adapter.send_tx_async(&receive_file, &mut slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
@ -140,6 +154,7 @@ fn file_exchange_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let adapter = FileWalletCommAdapter::new();
|
||||
let mut slate = adapter.receive_tx_async(&receive_file)?;
|
||||
api.verify_slate_messages(&slate)?;
|
||||
api.finalize_tx(&mut slate)?;
|
||||
api.post_tx(&slate.tx, false)?;
|
||||
bh += 1;
|
||||
|
|
|
@ -112,6 +112,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
)?;
|
||||
// output tx file
|
||||
let file_adapter = FileWalletCommAdapter::new();
|
||||
|
@ -132,7 +133,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
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)?;
|
||||
api.receive_tx(&mut slate, None, None)?;
|
||||
adapter.send_tx_async(&receive_file, &mut slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
@ -207,6 +208,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
||||
|
|
|
@ -236,6 +236,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
||||
|
@ -257,6 +258,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
)?;
|
||||
slate = client1.send_tx_slate_direct("wallet3", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
||||
|
@ -278,6 +280,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
)?;
|
||||
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
||||
|
@ -305,6 +308,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
)?;
|
||||
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
||||
|
|
|
@ -99,12 +99,11 @@ fn self_send_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
//"mining",
|
||||
//"listener",
|
||||
None,
|
||||
)?;
|
||||
// Send directly to self
|
||||
wallet::controller::foreign_single_use(wallet1.clone(), |api| {
|
||||
api.receive_tx(&mut slate, Some("listener"))?;
|
||||
api.receive_tx(&mut slate, Some("listener"), None)?;
|
||||
Ok(())
|
||||
})?;
|
||||
api.finalize_tx(&mut slate)?;
|
||||
|
|
|
@ -110,6 +110,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
||||
|
@ -244,6 +245,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.finalize_tx(&mut slate)?;
|
||||
|
@ -337,6 +339,7 @@ fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.finalize_tx(&mut slate)?;
|
||||
|
|
Loading…
Reference in a new issue